15 #include "mlir/Dialect/Func/IR/FuncOps.h"
16 #include "mlir/IR/MLIRContext.h"
17 #include "mlir/Pass/Pass.h"
18 #include "mlir/Support/LogicalResult.h"
19 #include "mlir/Transforms/DialectConversion.h"
20 #include "llvm/ADT/STLExtras.h"
21 #include "llvm/Support/raw_ostream.h"
24 #define GEN_PASS_DEF_MAXIMIZESSA
25 #include "circt/Transforms/Passes.h.inc"
29 using namespace circt;
33 if (
auto blockArg = dyn_cast<BlockArgument>(value); blockArg)
34 return blockArg.getParentBlock();
37 auto *defOp = value.getDefiningOp();
39 return defOp->getBlock();
46 auto branchOp = dyn_cast<BranchOpInterface>(predBlock->getTerminator());
48 return predBlock->getTerminator()->emitError(
49 "Expected terminator operation of block to be a "
50 "branch-like operation");
54 for (
auto [idx, succBlock] : llvm::enumerate(branchOp->getSuccessors()))
55 if (succBlock == block)
56 branchOp.getSuccessorOperands(idx).append(value);
65 for (
auto &block : region.getBlocks())
66 for (
auto &op : block.getOperations())
67 for (
auto operand : op.getOperands())
92 DenseSet<Block *> blocksUsing;
93 for (
auto &use : value.getUses()) {
94 auto *block = use.getOwner()->getBlock();
95 if (block != defBlock)
96 blocksUsing.insert(block);
103 SmallVector<Block *> blocksToVisit(blocksUsing.begin(), blocksUsing.end());
110 DenseMap<Block *, BlockArgument> blockToArg;
111 while (!blocksToVisit.empty()) {
113 auto *block = blocksToVisit.pop_back_val();
117 block->addArgument(value.getType(), rewriter.getUnknownLoc());
121 SmallPtrSet<Block *, 8> uniquePredecessors;
122 for (
auto *predBlock : block->getPredecessors()) {
127 if (
auto [_, newPredecessor] = uniquePredecessors.insert(predBlock);
138 if (predBlock != defBlock)
139 if (
auto [_, blockNewlyUsing] = blocksUsing.insert(predBlock);
141 blocksToVisit.push_back(predBlock);
146 SmallVector<Operation *> users;
147 for (
auto &use : value.getUses()) {
148 auto *owner = use.getOwner();
149 if (owner->getBlock() != defBlock)
150 users.push_back(owner);
152 for (
auto *user : users)
153 user->replaceUsesOfWith(value, blockToArg[user->getBlock()]);
160 PatternRewriter &rewriter) {
162 for (
auto res : op->getResults())
172 PatternRewriter &rewriter) {
174 for (
auto arg : block->getArguments())
180 for (
auto &op : block->getOperations())
190 PatternRewriter &rewriter) {
192 for (
auto &block : region.getBlocks())
202 struct MaxSSAConversion :
public ConversionPattern {
204 MaxSSAConversion(MLIRContext *context)
205 : ConversionPattern(MatchAnyOpTypeTag(), 1, context) {}
207 matchAndRewrite(Operation *op, ArrayRef<Value> operands,
208 ConversionPatternRewriter &rewriter)
const override {
209 LogicalResult conversionStatus = success();
210 rewriter.modifyOpInPlace(op, [&] {
211 for (
auto ®ion : op->getRegions()) {
212 SSAMaximizationStrategy strategy;
213 if (failed(maximizeSSA(region, strategy, rewriter)))
214 conversionStatus = failure();
217 return conversionStatus;
221 struct MaximizeSSAPass :
public circt::impl::MaximizeSSABase<MaximizeSSAPass> {
223 void runOnOperation()
override {
224 auto *ctx = &getContext();
227 patterns.add<MaxSSAConversion>(ctx);
228 ConversionTarget target(*ctx);
231 target.markUnknownOpDynamicallyLegal([](Operation *op) {
237 if (failed(applyPartialConversion(getOperation(), target,
247 return std::make_unique<MaximizeSSAPass>();
assert(baseType &&"element must be base type")
static LogicalResult addArgToTerminator(Block *block, Block *predBlock, Value value)
static Block * getDefiningBlock(Value value)
Strategy class to control the behavior of SSA maximization.
virtual bool maximizeResult(OpResult res)
Determines whether an operation's result should be SSA maximized.
virtual bool maximizeArgument(BlockArgument arg)
Determines whether a block argument should be SSA maximized.
virtual bool maximizeBlock(Block *block)
Determines whether a block should have the values it defines (i.e., block arguments and operation res...
virtual bool maximizeOp(Operation *op)
Determines whether an operation should have its results SSA maximized.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
std::unique_ptr< mlir::Pass > createMaximizeSSAPass()
LogicalResult maximizeSSA(Value value, PatternRewriter &rewriter)
Converts a single value within a function into maximal SSA form.
bool isRegionSSAMaximized(Region ®ion)