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

[LLHD][TCM] Ignore processes with CFG loops within a TR #8196

Merged
merged 1 commit into from
Feb 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
}