Skip to content

Commit

Permalink
[LLHD][TCM] Ignore processes with CFG loops within a TR (#8196)
Browse files Browse the repository at this point in the history
  • Loading branch information
maerhart authored Feb 6, 2025
1 parent db08ceb commit e8ede37
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 0 deletions.
39 changes: 39 additions & 0 deletions lib/Dialect/LLHD/Transforms/TemporalCodeMotionPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,46 @@ void TemporalCodeMotionPass::runOnOperation() {
(void)runOnProcess(proc); // Ignore processes that could not be lowered
}

static LogicalResult checkForCFGLoop(llhd::ProcessOp procOp) {
SmallVector<Block *> toCheck(
llvm::map_range(procOp.getOps<llhd::WaitOp>(), [](llhd::WaitOp waitOp) {
return waitOp.getSuccessor();
}));
toCheck.push_back(&procOp.getBody().front());

SmallVector<Block *> worklist;
DenseSet<Block *> visited;
for (auto *block : toCheck) {
worklist.clear();
visited.clear();
worklist.push_back(block);

while (!worklist.empty()) {
Block *curr = worklist.pop_back_val();
if (isa<llhd::WaitOp>(curr->getTerminator()))
continue;

visited.insert(curr);

for (auto *succ : curr->getSuccessors()) {
if (visited.contains(succ))
return failure();

worklist.push_back(succ);
}
}
}

return success();
}

LogicalResult TemporalCodeMotionPass::runOnProcess(llhd::ProcessOp procOp) {
// Make sure there are no CFG loops that don't contain a block with a wait
// terminator in the cycle because that's currently not supported by the
// temporal region analysis and this pass.
if (failed(checkForCFGLoop(procOp)))
return failure();

llhd::TemporalRegionAnalysis trAnalysis =
llhd::TemporalRegionAnalysis(procOp);
unsigned numTRs = trAnalysis.getNumTemporalRegions();
Expand Down
5 changes: 5 additions & 0 deletions lib/Dialect/LLHD/Transforms/TemporalRegions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ void llhd::TemporalRegionAnalysis::recalculate(Operation *operation) {
// If at least one predecessor has a wait terminator or at least one
// predecessor has an unknown temporal region or not all predecessors have
// the same TR, create a new TR
// FIXME: `!allPredecessorTRsKnown` is a problem when there are CFG loops
// in the process. If there is no wait op along any of the CFG edges of
// such a loop we don't want to assign a new temporal region. However, we
// also cannot just assume here that we can just assign the same TR, so
// this might require a bigger change to the algorithm.
} else if (!allPredecessorTRsKnown(block, workDone) ||
anyPredecessorHasWait(block) ||
!(std::adjacent_find(block->pred_begin(), block->pred_end(),
Expand Down
15 changes: 15 additions & 0 deletions test/Dialect/LLHD/Transforms/temporal-code-motion.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -205,3 +205,18 @@ hw.module @more_than_one_TR_wait_terminator(in %cond: i1) {
cf.br ^bb1
}
}

// CHECK-LABEL: @unsupportedLoop
hw.module @unsupportedLoop() {
// CHECK-NEXT: llhd.process {
// CHECK-NEXT: cf.br ^bb
// CHECK-NEXT: ^bb
// CHECK-NEXT: llhd.wait ^bb
// CHECK-NEXT: }
llhd.process {
cf.br ^bb1
^bb1:
llhd.wait ^bb1
}
hw.output
}

0 comments on commit e8ede37

Please sign in to comment.