Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Handshake] Add booleans to mem dependence attr #231

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
12 changes: 8 additions & 4 deletions include/dynamatic/Dialect/Handshake/HandshakeAttributes.td
Original file line number Diff line number Diff line change
Expand Up @@ -208,25 +208,29 @@ def MemDependenceAttr : Handshake_Attr<"MemDependence", "dep"> {
The dependency is furthermore characterized by the loop depth at which the
dependency is (`loopDepth`) and a list of dependence components
(`components`) whose size indicates the number of commom loops surrounding
both operations.
both operations. Also, there is a boolean (`isActive`) that demonstrates
whether the dependency needs to be considered. An example of when there is
no need to consider a dependency is when it is guaranteed by data dependency.
}];

let parameters = (ins
"::mlir::StringAttr":$dstAccess,
"unsigned":$loopDepth,
ArrayRefParameter<"::dynamatic::handshake::DependenceComponentAttr">:$components
ArrayRefParameter<"::dynamatic::handshake::DependenceComponentAttr">:$components,
"::mlir::BoolAttr":$isActive
shundroid marked this conversation as resolved.
Show resolved Hide resolved
);

let builders = [
AttrBuilder<(ins "::mlir::StringRef":$dstAccess,
"unsigned":$loopDepth,
"::mlir::ArrayRef<::mlir::affine::DependenceComponent>":$components), [{
"::mlir::ArrayRef<::mlir::affine::DependenceComponent>":$components,
"::mlir::BoolAttr":$isActive), [{
SmallVector<::dynamatic::handshake::DependenceComponentAttr> compAttrs;
for (auto &comp : components)
compAttrs.push_back(::dynamatic::handshake::DependenceComponentAttr::get(
context, comp.lb, comp.ub));
return $_get(context, ::mlir::StringAttr::get(context, dstAccess),
loopDepth, compAttrs);
loopDepth, compAttrs, isActive);
}]>
];

Expand Down
28 changes: 0 additions & 28 deletions include/dynamatic/Transforms/HandshakeAnalyzeLSQUsage.h

This file was deleted.

28 changes: 28 additions & 0 deletions include/dynamatic/Transforms/HandshakeInactivateEnforcedDeps.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//===- HandshakeInactivateEnforcedDeps.h -----------*- C++ -*-===//
rpirayadi marked this conversation as resolved.
Show resolved Hide resolved
//
// Dynamatic is under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file declares the --handshake-inactiveate-enfroced-deps pass.
//
//===----------------------------------------------------------------------===//

#ifndef DYNAMATIC_TRANSFORMS_HANDSHAKEINACTIVATEENFORCEDDEPS_H
#define DYNAMATIC_TRANSFORMS_HANDSHAKEINACTIVATEENFORCEDDEPS_H

#include "dynamatic/Support/DynamaticPass.h"

namespace dynamatic {

#define GEN_PASS_DECL_HANDSHAKEINACTIVATEENFORCEDDEPS
#define GEN_PASS_DEF_HANDSHAKEINACTIVATEENFORCEDDEPS
#include "dynamatic/Transforms/Passes.h.inc"

std::unique_ptr<dynamatic::DynamaticPass> createHandshakeInactivateEnforcedDeps();

} // namespace dynamatic

#endif // DYNAMATIC_TRANSFORMS_HANDSHAKEINACTIVATEENFORCEDDEPS_H
2 changes: 1 addition & 1 deletion include/dynamatic/Transforms/Passes.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#include "dynamatic/Transforms/ForceMemoryInterface.h"
#include "dynamatic/Transforms/FuncMaximizeSSA.h"
#include "dynamatic/Transforms/FuncSetArgNames.h"
#include "dynamatic/Transforms/HandshakeAnalyzeLSQUsage.h"
#include "dynamatic/Transforms/HandshakeInactivateEnforcedDeps.h"
#include "dynamatic/Transforms/HandshakeCanonicalize.h"
#include "dynamatic/Transforms/HandshakeHoistExtInstances.h"
#include "dynamatic/Transforms/HandshakeInferBasicBlocks.h"
Expand Down
15 changes: 7 additions & 8 deletions include/dynamatic/Transforms/Passes.td
Original file line number Diff line number Diff line change
Expand Up @@ -109,22 +109,21 @@ def FuncSetArgNames : DynamaticPass<"func-set-arg-names"> {
// Handshake passes
//===----------------------------------------------------------------------===//

def HandshakeAnalyzeLSQUsage : DynamaticPass<"handshake-analyze-lsq-usage"> {
let summary = "Analyzes memory accesses to LSQs to find unnecessary ones";
def HandshakeInactivateEnforcedDeps : DynamaticPass<"handshake-inactivate-enforced-deps"> {
let summary = "Uses `shrink it or shred it` logic to mark the dependencies that are insured as `inactive`";
rpirayadi marked this conversation as resolved.
Show resolved Hide resolved
let description = [{
Performs flow analysis to identify WAR dependencies between memory accesses
that are ensured by the circuit's semantics and which therefore do not need
to be enforced by an LSQ. This allows to reduce the number of memory ports
that go to LSQs, thereby improving the circuit's performance and area thanks
to LSQ size reduction (or elimination, in some instances). The pass does not
modify the IR's structure, it only sets `handshake::MemInterfaceAttr`
attributes on memory ports to encode the analysis' results.
to be enforced by an LSQ. It also finds the WAW dependencies between an
operation and itself. The pass then modifies the IR's structure by seting
rpirayadi marked this conversation as resolved.
Show resolved Hide resolved
these dependencies as inactive and determining `handshake::MemInterfaceAttr`
attributes on memory ports at the end.

The pass requires that all eligible operations within Handshake functions
are tagged with the basic block they belong to, and that all memory access
operations are uniquely named.
}];
let constructor = "dynamatic::createHandshakeAnalyzeLSQUsage()";
let constructor = "dynamatic::createHandshakeInactivateEnforcedDeps()";
}

def HandshakeCanonicalize : DynamaticPass<"handshake-canonicalize"> {
Expand Down
20 changes: 18 additions & 2 deletions lib/Dialect/Handshake/HandshakeAttributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,12 @@ static ParseResult parseDependenceComponent(AsmParser &odsParser,
void MemDependenceAttr::print(AsmPrinter &odsPrinter) const {
// Print destination memory access and loop depth
odsPrinter << "<\"" << getDstAccess().str() << "\" (" << getLoopDepth()
<< ")";
<< ") ";
std::string isActiveStr = "inactive";
if (getIsActive().getValue())
isActiveStr = "active";
Copy link
Collaborator

@pcineverdies pcineverdies Jan 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just a thought: is it advisable to have such a long text rather than a single character? (i.e. either A or I or whatever). For instance, in the buffering context, the properties of the buffers are expressed with a single letter, and this does not lack of readability as long as you are aware of their meaning.
The main consequence would be to have a lighter IR rather than a large one (considering that load and store operations are already pretty ugly...).

However, Lucas is probably more aware of the different implications here.


odsPrinter << "\"" << isActiveStr << "\"";

// Print dependence components, if present
auto components = getComponents();
Expand Down Expand Up @@ -122,6 +127,17 @@ Attribute MemDependenceAttr::parse(AsmParser &odsParser, Type odsType) {
odsParser.parseRParen())
return nullptr;

// Parse isActive
std::string boolStr;
if (odsParser.parseString(&boolStr))
return nullptr;
bool isActive;
if (boolStr == "active")
isActive = true;
else if (boolStr == "inactive")
isActive = false;
rpirayadi marked this conversation as resolved.
Show resolved Hide resolved
mlir::BoolAttr isActiveAttr = mlir::BoolAttr::get(ctx, isActive);

// Parse dependence components if present
SmallVector<DependenceComponentAttr> components;
if (!odsParser.parseOptionalLSquare()) {
Expand All @@ -147,7 +163,7 @@ Attribute MemDependenceAttr::parse(AsmParser &odsParser, Type odsType) {

if (odsParser.parseGreater())
return nullptr;
return MemDependenceAttr::get(ctx, dstAccess, loopDepth, components);
return MemDependenceAttr::get(ctx, dstAccess, loopDepth, components, isActiveAttr);
}

//===----------------------------------------------------------------------===//
Expand Down
2 changes: 1 addition & 1 deletion lib/Dialect/Handshake/MemoryInterfaces.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ bool MemoryOpLowering::renameDependencies(Operation *topLevelOp) {
if (opWasReplaced) {
StringAttr newName = StringAttr::get(ctx, replacedName->second);
newMemDeps.push_back(MemDependenceAttr::get(
ctx, newName, oldDep.getLoopDepth(), oldDep.getComponents()));
ctx, newName, oldDep.getLoopDepth(), oldDep.getComponents(), oldDep.getIsActive()));
} else {
newMemDeps.push_back(oldDep);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Transforms/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ add_dynamatic_library(DynamaticTransforms
ForceMemoryInterface.cpp
FuncMaximizeSSA.cpp
FuncSetArgNames.cpp
HandshakeAnalyzeLSQUsage.cpp
HandshakeInactivateEnforcedDeps.cpp
HandshakeCanonicalize.cpp
HandshakeHoistExtInstances.cpp
HandshakeMaterialize.cpp
Expand Down
Loading