Skip to content

Commit 9d26409

Browse files
committed
[MLIR][LLVM] Fix inlining of a single block ending with unreachable
1 parent 2914ba1 commit 9d26409

File tree

5 files changed

+55
-8
lines changed

5 files changed

+55
-8
lines changed

mlir/include/mlir/Transforms/InliningUtils.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,15 @@ class DialectInlinerInterface
176176
/// is invoked before inlined terminator operations have been processed.
177177
virtual void processInlinedCallBlocks(
178178
Operation *call, iterator_range<Region::iterator> inlinedBlocks) const {}
179+
180+
/// Process a set of blocks that have been inlined. This callback is invoked
181+
/// *before* inlined terminator operations have been processed. Returns true
182+
/// if the inliner can assume a fast path of not creating a new block, if
183+
/// there is only one block.
184+
virtual bool
185+
processInlinedBlocks(iterator_range<Region::iterator> inlinedBlocks) const {
186+
return true;
187+
}
179188
};
180189

181190
/// This interface provides the hooks into the inlining interface.
@@ -186,11 +195,6 @@ class InlinerInterface
186195
public:
187196
using Base::Base;
188197

189-
/// Process a set of blocks that have been inlined. This callback is invoked
190-
/// *before* inlined terminator operations have been processed.
191-
virtual void
192-
processInlinedBlocks(iterator_range<Region::iterator> inlinedBlocks) {}
193-
194198
/// These hooks mirror the hooks for the DialectInlinerInterface, with default
195199
/// implementations that call the hook on the handler for the dialect 'op' is
196200
/// registered to.
@@ -211,6 +215,9 @@ class InlinerInterface
211215
// Transformation Hooks
212216
//===--------------------------------------------------------------------===//
213217

218+
virtual bool
219+
processInlinedBlocks(iterator_range<Region::iterator> inlinedBlocks);
220+
214221
virtual void handleTerminator(Operation *op, Block *newDest) const;
215222
virtual void handleTerminator(Operation *op, ValueRange valuesToRepl) const;
216223

mlir/lib/Dialect/LLVMIR/Transforms/InlinerInterfaceImpl.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,14 @@ struct LLVMInlinerInterface : public DialectInlinerInterface {
743743
op->erase();
744744
}
745745

746+
bool processInlinedBlocks(
747+
iterator_range<Region::iterator> inlinedBlocks) const final {
748+
if (!inlinedBlocks.empty() &&
749+
isa<LLVM::UnreachableOp>(inlinedBlocks.begin()->getTerminator()))
750+
return false;
751+
return true;
752+
}
753+
746754
/// Handle the given inlined return by replacing the uses of the call with the
747755
/// operands of the return. This overload is called when the inlined region
748756
/// only contains one block.

mlir/lib/Transforms/Utils/Inliner.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ struct InlinerInterfaceImpl : public InlinerInterface {
382382

383383
/// Process a set of blocks that have been inlined. This callback is invoked
384384
/// *before* inlined terminator operations have been processed.
385-
void
385+
bool
386386
processInlinedBlocks(iterator_range<Region::iterator> inlinedBlocks) final {
387387
// Find the closest callgraph node from the first block.
388388
CallGraphNode *node;
@@ -394,6 +394,7 @@ struct InlinerInterfaceImpl : public InlinerInterface {
394394

395395
collectCallOps(inlinedBlocks, node, cg, symbolTable, calls,
396396
/*traverseNestedCGNodes=*/true);
397+
return InlinerInterface::processInlinedBlocks(inlinedBlocks);
397398
}
398399

399400
/// Mark the given callgraph node for deletion.

mlir/lib/Transforms/Utils/InliningUtils.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,21 @@ void InlinerInterface::handleTerminator(Operation *op,
118118
handler->handleTerminator(op, valuesToRepl);
119119
}
120120

121+
/// Process a set of blocks that have been inlined. This callback is invoked
122+
/// *before* inlined terminator operations have been processed. Returns true
123+
/// if the inliner can assume a fast path of not creating a new block, if
124+
/// there is only one block.
125+
bool InlinerInterface::processInlinedBlocks(
126+
iterator_range<Region::iterator> inlinedBlocks) {
127+
if (inlinedBlocks.empty()) {
128+
return true;
129+
} else {
130+
auto *handler = getInterfaceFor(inlinedBlocks.begin()->getParentOp());
131+
assert(handler && "expected valid dialect handler");
132+
return handler->processInlinedBlocks(inlinedBlocks);
133+
}
134+
}
135+
121136
Value InlinerInterface::handleArgument(OpBuilder &builder, Operation *call,
122137
Operation *callable, Value argument,
123138
DictionaryAttr argumentAttrs) const {
@@ -292,10 +307,10 @@ inlineRegionImpl(InlinerInterface &interface, Region *src, Block *inlineBlock,
292307
// Process the newly inlined blocks.
293308
if (call)
294309
interface.processInlinedCallBlocks(call, newBlocks);
295-
interface.processInlinedBlocks(newBlocks);
310+
bool singleBlockFastPath = interface.processInlinedBlocks(newBlocks);
296311

297312
// Handle the case where only a single block was inlined.
298-
if (std::next(newBlocks.begin()) == newBlocks.end()) {
313+
if (singleBlockFastPath && std::next(newBlocks.begin()) == newBlocks.end()) {
299314
// Run the result attribute handler on the terminator operands.
300315
Operation *firstBlockTerminator = firstNewBlock->getTerminator();
301316
builder.setInsertionPoint(firstBlockTerminator);

mlir/test/Dialect/LLVMIR/inlining.mlir

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,3 +676,19 @@ llvm.func @caller(%x : i32) -> i32 {
676676
%z = llvm.call @private_func(%x) : (i32) -> (i32)
677677
llvm.return %z : i32
678678
}
679+
680+
// -----
681+
682+
llvm.func @unreachable_func(%a : i32) -> i32 {
683+
"llvm.intr.trap"() : () -> ()
684+
llvm.unreachable
685+
}
686+
687+
// CHECK-LABEL: func @caller
688+
llvm.func @caller(%x : i32) -> i32 {
689+
// CHECK-NOT: llvm.call @unreachable_func
690+
// CHECK: llvm.intr.trap
691+
// CHECK: llvm.unreachable
692+
%z = llvm.call @unreachable_func(%x) : (i32) -> (i32)
693+
llvm.return %z : i32
694+
}

0 commit comments

Comments
 (0)