Skip to content

Commit a17be2c

Browse files
committed
next iteration
1 parent 3ecbcc1 commit a17be2c

File tree

3 files changed

+103
-32
lines changed

3 files changed

+103
-32
lines changed

include/circt/Dialect/LLHD/IR/LLHDStructureOps.td

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,7 @@ def CombinationalOp : LLHDOp<"combinational", [
143143
def WaitOp : LLHDOp<"wait", [
144144
AttrSizedOperandSegments,
145145
HasParent<"ProcessOp">,
146-
Terminator,
147-
DeclareOpInterfaceMethods<BranchOpInterface, ["getSuccessorForOperands"]>
146+
Terminator
148147
]> {
149148
let summary = "Suspend execution of a process";
150149
let description = [{

lib/Dialect/LLHD/IR/LLHDOps.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -546,15 +546,6 @@ static LogicalResult verifyYieldResults(Operation *op,
546546
return success();
547547
}
548548

549-
SuccessorOperands WaitOp::getSuccessorOperands(unsigned index) {
550-
assert(index == 0 && "invalid successor index");
551-
return SuccessorOperands(getDestOperandsMutable());
552-
}
553-
554-
Block *WaitOp::getSuccessorForOperands(ArrayRef<Attribute>) {
555-
return getDest();
556-
}
557-
558549
LogicalResult WaitOp::verify() {
559550
return verifyYieldResults(*this, getYieldOperands());
560551
}

lib/Dialect/LLHD/Transforms/LowerProcesses.cpp

Lines changed: 102 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -288,31 +288,112 @@ struct LowerProcessesPass
288288
void runOnOperation() override;
289289
};
290290

291-
// Perform cleanup on the process operation prior to lowering.
292-
// This can remove redundant operands passed to the successor of llhd.wait.
293-
//
294-
// ^bb0
295-
// cf.br ^bb1(%clock : i1)
296-
// ^bb1(%1: i1): // pred: ^bb0, ^bb2
297-
// llhd.wait yield (...), (%clock : i1), ^bb2(%1 : i1)
298-
// ^bb2(%2: i1): // pred: ^bb1
299-
// cf.cond_br %true, ^bb3, ^bb1(%2 : i1)
300-
// ^bb3:
301-
//
302-
// The above IR can be rewritten as:
303-
//
304-
// ^bb0
305-
// cf.br ^bb1
306-
// ^bb1: // pred: ^bb0, ^bb2
307-
// llhd.wait yield (...), (%clock : i1), ^bb2
308-
// ^bb2: // pred: ^bb1
309-
// cf.cond_br %true, ^bb3, ^bb1
310-
// ^bb3:
311-
//
291+
static LogicalResult dropRedundantArguments(RewriterBase &rewriter,
292+
Block &block) {
293+
SmallVector<size_t> argsToErase;
294+
295+
// Go through the arguments of the block.
296+
for (auto [argIdx, blockOperand] : llvm::enumerate(block.getArguments())) {
297+
bool sameArg = true;
298+
Value commonValue;
299+
300+
// Go through the block predecessor and flag if they pass to the block
301+
// different values for the same argument.
302+
for (Block::pred_iterator predIt = block.pred_begin(),
303+
predE = block.pred_end();
304+
predIt != predE; ++predIt) {
305+
Operation *terminator = (*predIt)->getTerminator();
306+
auto branchOperand =
307+
llvm::TypeSwitch<Operation *, std::optional<Value>>(terminator)
308+
.Case([&, argIdx = argIdx](BranchOpInterface branchOp) {
309+
auto succIndex = predIt.getSuccessorIndex();
310+
SuccessorOperands succOperands =
311+
branchOp.getSuccessorOperands(succIndex);
312+
auto branchOperands = succOperands.getForwardedOperands();
313+
return branchOperands[argIdx];
314+
})
315+
.Case([&, argIdx = argIdx](WaitOp waitOp) {
316+
auto destOperands = waitOp.getDestOperands();
317+
return destOperands[argIdx];
318+
})
319+
.Default([](Operation *) { return std::nullopt; });
320+
321+
if (!branchOperand.has_value()) {
322+
sameArg = false;
323+
break;
324+
}
325+
326+
if (!commonValue) {
327+
commonValue = *branchOperand;
328+
continue;
329+
}
330+
331+
if (*branchOperand != commonValue) {
332+
sameArg = false;
333+
break;
334+
}
335+
}
336+
337+
// If they are passing the same value, drop the argument.
338+
if (commonValue && sameArg) {
339+
argsToErase.push_back(argIdx);
340+
341+
// Remove the argument from the block.
342+
rewriter.replaceAllUsesWith(blockOperand, commonValue);
343+
}
344+
}
345+
346+
// Remove the arguments.
347+
for (size_t argIdx : llvm::reverse(argsToErase)) {
348+
block.eraseArgument(argIdx);
349+
350+
// Remove the argument from the branch ops.
351+
for (auto predIt = block.pred_begin(), predE = block.pred_end();
352+
predIt != predE; ++predIt) {
353+
llvm::TypeSwitch<Operation *, void>((*predIt)->getTerminator())
354+
.Case([&](BranchOpInterface branchOp) {
355+
auto branch = cast<BranchOpInterface>((*predIt)->getTerminator());
356+
unsigned succIndex = predIt.getSuccessorIndex();
357+
SuccessorOperands succOperands =
358+
branch.getSuccessorOperands(succIndex);
359+
succOperands.erase(argIdx);
360+
})
361+
.Case([&](WaitOp waitOp) {
362+
auto destOperands = waitOp.getDestOperandsMutable();
363+
destOperands.erase(argIdx);
364+
})
365+
.Default([](Operation *) {
366+
llvm_unreachable("Unexpected predecessor terminator");
367+
});
368+
}
369+
}
370+
371+
return success(!argsToErase.empty());
372+
}
373+
312374
static void simplifyProcess(ProcessOp &processOp) {
313375
OpBuilder builder(processOp);
314376
IRRewriter rewriter(builder);
315377
(void)simplifyRegions(rewriter, processOp->getRegions());
378+
379+
// simplifyRegions does not prune the destination operands of the
380+
// `llhd.wait` operation because it does not implement BranchOpInterface, due
381+
// to its side-effect semantics. Implementing BranchOpInterface could allow
382+
// other optimizations to forward branch operands from the llhd.wait
383+
// operation to the destination block where execution resumes. However, this
384+
// would be invalid, as the SSA value might change across the wait operation.
385+
// Therefore, we manually prune the destination block arguments ourselves.
386+
for (auto &block : processOp.getBody()) {
387+
auto waitOp = dyn_cast<WaitOp>(block.getTerminator());
388+
if (!waitOp)
389+
continue;
390+
391+
auto dstOperands = waitOp.getDestOperands();
392+
if (dstOperands.empty())
393+
continue;
394+
395+
(void)dropRedundantArguments(rewriter, *waitOp.getDest());
396+
}
316397
}
317398

318399
} // namespace

0 commit comments

Comments
 (0)