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"
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())
194 if (failed(
maximizeSSA(&block, strategy, rewriter)))
204 MaxSSAConversion(MLIRContext *
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)))
217 return conversionStatus;
221struct MaximizeSSAPass :
public circt::impl::MaximizeSSABase<MaximizeSSAPass> {
223 void runOnOperation()
override {
224 auto *ctx = &getContext();
226 RewritePatternSet patterns{ctx};
227 patterns.add<MaxSSAConversion>(ctx);
228 ConversionTarget target(*ctx);
231 target.markUnknownOpDynamicallyLegal([](Operation *op) {
237 if (failed(applyPartialConversion(getOperation(), target,
238 std::move(patterns))))
247 return std::make_unique<MaximizeSSAPass>();
assert(baseType &&"element must be base type")
static std::unique_ptr< Context > context
static LogicalResult addArgToTerminator(Block *block, Block *predBlock, Value value)
static Block * getDefiningBlock(Value value)
false return failure()
Parse an optional keyword or string and set instance into 'result'.
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)