11 #include "mlir/Pass/Pass.h"
19 #include "mlir/Transforms/DialectConversion.h"
23 #define GEN_PASS_DEF_KANAGAWAREBLOCK
24 #include "circt/Dialect/Kanagawa/KanagawaPasses.h.inc"
28 using namespace circt;
29 using namespace kanagawa;
34 :
public circt::kanagawa::impl::KanagawaReblockBase<ReblockPass> {
35 void runOnOperation()
override;
39 LogicalResult reblock(ArrayRef<Operation *> ops, Operation *blockTerminator);
42 SmallVector<Operation *> opsToErase;
47 static bool isSBlockTerminator(Operation *op) {
48 return op->hasTrait<OpTrait::IsTerminator>() ||
49 isa<kanagawa::InlineStaticBlockEndOp, InlineStaticBlockBeginOp>(op);
54 void ReblockPass::runOnOperation() {
55 MethodOp parent = getOperation();
57 llvm::SmallVector<Operation *> opsToBlock;
58 for (Block &block : parent.getRegion()) {
59 for (Operation &op : llvm::make_early_inc_range(block)) {
60 if (isSBlockTerminator(&op)) {
61 if (opsToBlock.empty())
63 if (failed(reblock(opsToBlock, &op)))
64 return signalPassFailure();
66 if (isa<InlineStaticBlockBeginOp>(op))
67 opsToBlock.push_back(&op);
69 opsToBlock.push_back(&op);
73 llvm::for_each(opsToErase, [](Operation *op) { op->erase(); });
76 LogicalResult ReblockPass::reblock(ArrayRef<Operation *> ops,
77 Operation *blockTerminator) {
81 kanagawa::InlineStaticBlockBeginOp blockBeginOp;
82 if (isa<InlineStaticBlockEndOp>(blockTerminator)) {
83 blockBeginOp = dyn_cast<InlineStaticBlockBeginOp>(ops.front());
85 "Expected block begin op when a block end block was provided");
86 ops = ops.drop_front();
89 Operation *beginOp = ops.front();
90 auto startIt = ops.front()->getIterator();
91 Operation *endOp = ops.back();
92 auto terminatorIt = blockTerminator->getIterator();
93 Block *sblockParentBlock = beginOp->getBlock();
95 auto usedOutsideBlock = [&](OpOperand &use) {
96 Operation *owner = use.getOwner();
97 Block *useBlock = owner->getBlock();
98 if (useBlock != sblockParentBlock)
100 bool isBefore = owner->isBeforeInBlock(beginOp);
101 bool isAfter = isBefore ? false : endOp->isBeforeInBlock(owner);
102 return isBefore || isAfter;
105 llvm::MapVector<Value, llvm::SmallVector<OpOperand *>> returnValueUses;
106 for (
auto &op : llvm::make_range(startIt, terminatorIt)) {
107 for (Value result : op.getResults()) {
108 for (OpOperand &use : result.getUses())
109 if (usedOutsideBlock(use))
110 returnValueUses[result].push_back(&use);
115 llvm::SmallVector<Type> blockRetTypes;
116 llvm::SmallVector<Value> blockRetValues;
117 for (
auto &[v, _] : returnValueUses) {
118 blockRetTypes.push_back(v.getType());
119 blockRetValues.push_back(v);
122 auto b = OpBuilder(beginOp);
124 b.create<StaticBlockOp>(beginOp->getLoc(), blockRetTypes, ValueRange{});
129 kanagawaBlock->setAttrs(blockBeginOp->getAttrs());
132 BlockReturnOp blockReturn =
133 cast<BlockReturnOp>(kanagawaBlock.getBodyBlock()->getTerminator());
136 llvm::make_early_inc_range(llvm::make_range(startIt, terminatorIt)))
137 op.moveBefore(blockReturn);
140 blockReturn->setOperands(blockRetValues);
144 for (
auto [blockRet, innerDefAndUses] :
145 llvm::zip(kanagawaBlock.getResults(), returnValueUses)) {
146 auto &uses = std::get<1>(innerDefAndUses);
147 for (OpOperand *use : uses)
153 opsToErase.push_back(blockBeginOp);
154 opsToErase.push_back(blockTerminator);
161 return std::make_unique<ReblockPass>();
assert(baseType &&"element must be base type")
std::unique_ptr< mlir::Pass > createReblockPass()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.