Skip to content

Commit ef45313

Browse files
authored
[SCFToCalyx] Add combinational group inlining [11/12] (#1862)
This commit introduces combinational group inlining. The conversion strategy of SCFToCalyx is to create a distinct CombGroupOp for each combinational operator in the source program. This implies that the created CombGroupOp is analogous to the SSA value which the original operation represented. In Calyx, a source operand for a `calyx.assign` must be fully defined within the group that performs the assignment. This means that the source operand is either the output of a sequential component, or a fully defined combinational assignment chain. This commit achieves the latter by recursively inlining use-def chains op combinational logic, by backtracking through the CombGroupOps which generated the combinational assignments of the original program.
1 parent 815029c commit ef45313

File tree

3 files changed

+299
-44
lines changed

3 files changed

+299
-44
lines changed

lib/Conversion/SCFToCalyx/SCFToCalyx.cpp

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1234,6 +1234,85 @@ class BuildControl : public FuncOpPartialLoweringPattern {
12341234
}
12351235
};
12361236

1237+
/// This pass recursively inlines use-def chains of combinational logic (from
1238+
/// non-stateful groups) into groups referenced in the control schedule.
1239+
class InlineCombGroups
1240+
: public PartialLoweringPattern<calyx::GroupInterface,
1241+
OpInterfaceRewritePattern> {
1242+
public:
1243+
InlineCombGroups(MLIRContext *context, LogicalResult &resRef,
1244+
ProgramLoweringState &pls)
1245+
: PartialLoweringPattern(context, resRef), pls(pls) {}
1246+
1247+
LogicalResult partiallyLower(calyx::GroupInterface originGroup,
1248+
PatternRewriter &rewriter) const override {
1249+
auto &state = pls.compLoweringState(
1250+
originGroup->getParentOfType<calyx::ComponentOp>());
1251+
1252+
/// Filter groups which are not part of the control schedule.
1253+
if (SymbolTable::symbolKnownUseEmpty(originGroup.symName(),
1254+
state.getComponentOp().getControlOp()))
1255+
return success();
1256+
1257+
/// Maintain a set of the groups which we've inlined so far. The group
1258+
/// itself is implicitly inlined.
1259+
llvm::SmallSetVector<Operation *, 8> inlinedGroups;
1260+
inlinedGroups.insert(originGroup);
1261+
1262+
/// Starting from the matched originGroup, we traverse use-def chains of
1263+
/// combinational logic, and inline assignments from the defining
1264+
/// combinational groups.
1265+
recurseInlineCombGroups(
1266+
rewriter, state, inlinedGroups, originGroup, originGroup,
1267+
/*disable inlining of the originGroup itself*/ false);
1268+
return success();
1269+
}
1270+
1271+
private:
1272+
void
1273+
recurseInlineCombGroups(PatternRewriter &rewriter,
1274+
ComponentLoweringState &state,
1275+
llvm::SmallSetVector<Operation *, 8> &inlinedGroups,
1276+
calyx::GroupInterface originGroup,
1277+
calyx::GroupInterface recGroup, bool doInline) const {
1278+
inlinedGroups.insert(recGroup);
1279+
for (auto assignOp : recGroup.getBody()->getOps<calyx::AssignOp>()) {
1280+
if (doInline) {
1281+
/// Inline the assignment into the originGroup.
1282+
auto clonedAssignOp = rewriter.clone(*assignOp.getOperation());
1283+
clonedAssignOp->moveBefore(originGroup.getBody(),
1284+
originGroup.getBody()->end());
1285+
}
1286+
auto src = assignOp.src();
1287+
auto srcDefOp = src.getDefiningOp();
1288+
1289+
/// Things which stop recursive inlining (or in other words, what
1290+
/// breaks combinational paths).
1291+
/// - Component inputs
1292+
/// - Register and memory reads
1293+
/// - Constant ops (constant ops are not evaluated by any group)
1294+
/// - 'While' return values (these are registers, however, 'while'
1295+
/// return values have at the current point of conversion not yet
1296+
/// been rewritten to their register outputs, see comment in
1297+
/// LateSSAReplacement)
1298+
if (src.isa<BlockArgument>() ||
1299+
isa<calyx::RegisterOp, calyx::MemoryOp, hw::ConstantOp, ConstantOp,
1300+
scf::WhileOp>(srcDefOp))
1301+
continue;
1302+
1303+
auto srcCombGroup = state.getEvaluatingGroup<calyx::CombGroupOp>(src);
1304+
assert(srcCombGroup && "expected combinational group");
1305+
if (inlinedGroups.count(srcCombGroup))
1306+
continue;
1307+
1308+
recurseInlineCombGroups(rewriter, state, inlinedGroups, originGroup,
1309+
srcCombGroup, true);
1310+
}
1311+
}
1312+
1313+
ProgramLoweringState &pls;
1314+
};
1315+
12371316
/// LateSSAReplacement contains various functions for replacing SSA values that
12381317
/// were not replaced during op construction.
12391318
class LateSSAReplacement : public FuncOpPartialLoweringPattern {
@@ -1665,6 +1744,10 @@ void SCFToCalyxPass::runOnOperation() {
16651744
/// basic block in the source function.
16661745
addOncePattern<BuildControl>(loweringPatterns, funcMap, *loweringState);
16671746

1747+
/// This pass recursively inlines use-def chains of combinational logic (from
1748+
/// non-stateful groups) into groups referenced in the control schedule.
1749+
addOncePattern<InlineCombGroups>(loweringPatterns, *loweringState);
1750+
16681751
/// This pattern performs various SSA replacements that must be done
16691752
/// after control generation.
16701753
addOncePattern<LateSSAReplacement>(loweringPatterns, funcMap, *loweringState);

0 commit comments

Comments
 (0)