Skip to content

Commit 675c1b7

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

File tree

14 files changed

+51
-17
lines changed

14 files changed

+51
-17
lines changed

flang/lib/Optimizer/Dialect/FIRDialect.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ struct FIRInlinerInterface : public mlir::DialectInlinerInterface {
4444
/// We handle the return (a Fortran FUNCTION) by replacing the values
4545
/// previously returned by the call operation with the operands of the
4646
/// return.
47-
void handleTerminator(mlir::Operation *op,
47+
void handleTerminator(mlir::Operation *op, mlir::OpBuilder &builder,
4848
mlir::ValueRange valuesToRepl) const final {
4949
auto returnOp = llvm::cast<mlir::func::ReturnOp>(op);
5050
assert(returnOp.getNumOperands() == valuesToRepl.size());

mlir/examples/toy/Ch4/mlir/Dialect.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,8 @@ struct ToyInlinerInterface : public DialectInlinerInterface {
7373

7474
/// Handle the given inlined terminator(toy.return) by replacing it with a new
7575
/// operation as necessary.
76-
void handleTerminator(Operation *op, ValueRange valuesToRepl) const final {
76+
void handleTerminator(Operation *op, OpBuilder &builder,
77+
ValueRange valuesToRepl) const final {
7778
// Only "toy.return" needs to be handled here.
7879
auto returnOp = cast<ReturnOp>(op);
7980

mlir/examples/toy/Ch5/mlir/Dialect.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,8 @@ struct ToyInlinerInterface : public DialectInlinerInterface {
7373

7474
/// Handle the given inlined terminator(toy.return) by replacing it with a new
7575
/// operation as necessary.
76-
void handleTerminator(Operation *op, ValueRange valuesToRepl) const final {
76+
void handleTerminator(Operation *op, OpBuilder &builder,
77+
ValueRange valuesToRepl) const final {
7778
// Only "toy.return" needs to be handled here.
7879
auto returnOp = cast<ReturnOp>(op);
7980

mlir/examples/toy/Ch6/mlir/Dialect.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,8 @@ struct ToyInlinerInterface : public DialectInlinerInterface {
7373

7474
/// Handle the given inlined terminator(toy.return) by replacing it with a new
7575
/// operation as necessary.
76-
void handleTerminator(Operation *op, ValueRange valuesToRepl) const final {
76+
void handleTerminator(Operation *op, OpBuilder &builder,
77+
ValueRange valuesToRepl) const final {
7778
// Only "toy.return" needs to be handled here.
7879
auto returnOp = cast<ReturnOp>(op);
7980

mlir/examples/toy/Ch7/mlir/Dialect.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ struct ToyInlinerInterface : public DialectInlinerInterface {
7979

8080
/// Handle the given inlined terminator(toy.return) by replacing it with a new
8181
/// operation as necessary.
82-
void handleTerminator(Operation *op, ValueRange valuesToRepl) const final {
82+
void handleTerminator(Operation *op, OpBuilder &builder,
83+
ValueRange valuesToRepl) const final {
8384
// Only "toy.return" needs to be handled here.
8485
auto returnOp = cast<ReturnOp>(op);
8586

mlir/include/mlir/Transforms/InliningUtils.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ class DialectInlinerInterface
116116
/// calls, these are directly replaced with the operands of the `return`
117117
/// operation). The given 'op' will be removed by the caller, after this
118118
/// function has been called.
119-
virtual void handleTerminator(Operation *op,
119+
virtual void handleTerminator(Operation *op, OpBuilder &builder,
120120
ValueRange valuesToReplace) const {
121121
llvm_unreachable(
122122
"must implement handleTerminator in the case of one inlined block");
@@ -212,7 +212,8 @@ class InlinerInterface
212212
//===--------------------------------------------------------------------===//
213213

214214
virtual void handleTerminator(Operation *op, Block *newDest) const;
215-
virtual void handleTerminator(Operation *op, ValueRange valuesToRepl) const;
215+
virtual void handleTerminator(Operation *op, OpBuilder &builder,
216+
ValueRange valuesToRepl) const;
216217

217218
virtual Value handleArgument(OpBuilder &builder, Operation *call,
218219
Operation *callable, Value argument,

mlir/lib/Dialect/Func/Extensions/InlinerExtension.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ struct FuncInlinerInterface : public DialectInlinerInterface {
6767

6868
/// Handle the given inlined terminator by replacing it with a new operation
6969
/// as necessary.
70-
void handleTerminator(Operation *op, ValueRange valuesToRepl) const final {
70+
void handleTerminator(Operation *op, OpBuilder &builder,
71+
ValueRange valuesToRepl) const final {
7172
// Only return needs to be handled here.
7273
auto returnOp = cast<ReturnOp>(op);
7374

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -746,8 +746,17 @@ struct LLVMInlinerInterface : public DialectInlinerInterface {
746746
/// Handle the given inlined return by replacing the uses of the call with the
747747
/// operands of the return. This overload is called when the inlined region
748748
/// only contains one block.
749-
void handleTerminator(Operation *op, ValueRange valuesToRepl) const final {
750-
// Return will be the only terminator present.
749+
void handleTerminator(Operation *op, OpBuilder &builder,
750+
ValueRange valuesToRepl) const final {
751+
if (isa<LLVM::UnreachableOp>(op)) {
752+
for (auto dst : valuesToRepl) {
753+
auto repl = builder.create<LLVM::PoisonOp>(op->getLoc(), dst.getType());
754+
dst.replaceAllUsesWith(repl);
755+
}
756+
return;
757+
}
758+
759+
// Otherwise return will be the only terminator present.
751760
auto returnOp = cast<LLVM::ReturnOp>(op);
752761

753762
// Replace the values directly with the return operands.

mlir/lib/Dialect/Linalg/IR/LinalgDialect.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ struct LinalgInlinerInterface : public DialectInlinerInterface {
5757
}
5858
// Handle the given inlined terminator by replacing it with a new operation
5959
// as necessary. Required when the region has only one block.
60-
void handleTerminator(Operation *op, ValueRange valuesToRepl) const final {}
60+
void handleTerminator(Operation *op, OpBuilder &builder,
61+
ValueRange valuesToRepl) const final {}
6162
};
6263

6364
} // namespace

mlir/lib/Dialect/SCF/IR/SCF.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ struct SCFInlinerInterface : public DialectInlinerInterface {
5151
}
5252
// Handle the given inlined terminator by replacing it with a new operation
5353
// as necessary. Required when the region has only one block.
54-
void handleTerminator(Operation *op, ValueRange valuesToRepl) const final {
54+
void handleTerminator(Operation *op, OpBuilder &builder,
55+
ValueRange valuesToRepl) const final {
5556
auto retValOp = dyn_cast<scf::YieldOp>(op);
5657
if (!retValOp)
5758
return;

mlir/lib/Dialect/SPIRV/IR/SPIRVDialect.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,8 @@ struct SPIRVInlinerInterface : public DialectInlinerInterface {
103103

104104
/// Handle the given inlined terminator by replacing it with a new operation
105105
/// as necessary.
106-
void handleTerminator(Operation *op, ValueRange valuesToRepl) const final {
106+
void handleTerminator(Operation *op, OpBuilder &builder,
107+
ValueRange valuesToRepl) const final {
107108
// Only spirv.ReturnValue needs to be handled here.
108109
auto retValOp = dyn_cast<spirv::ReturnValueOp>(op);
109110
if (!retValOp)

mlir/lib/Transforms/Utils/InliningUtils.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,11 +111,11 @@ void InlinerInterface::handleTerminator(Operation *op, Block *newDest) const {
111111

112112
/// Handle the given inlined terminator by replacing it with a new operation
113113
/// as necessary.
114-
void InlinerInterface::handleTerminator(Operation *op,
114+
void InlinerInterface::handleTerminator(Operation *op, OpBuilder &builder,
115115
ValueRange valuesToRepl) const {
116116
auto *handler = getInterfaceFor(op);
117117
assert(handler && "expected valid dialect handler");
118-
handler->handleTerminator(op, valuesToRepl);
118+
handler->handleTerminator(op, builder, valuesToRepl);
119119
}
120120

121121
Value InlinerInterface::handleArgument(OpBuilder &builder, Operation *call,
@@ -304,7 +304,7 @@ inlineRegionImpl(InlinerInterface &interface, Region *src, Block *inlineBlock,
304304
firstBlockTerminator->getOperands());
305305

306306
// Have the interface handle the terminator of this block.
307-
interface.handleTerminator(firstBlockTerminator, resultsToReplace);
307+
interface.handleTerminator(firstBlockTerminator, builder, resultsToReplace);
308308
firstBlockTerminator->erase();
309309

310310
// Merge the post insert block into the cloned entry block.

mlir/test/Dialect/LLVMIR/inlining.mlir

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,3 +676,18 @@ 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+
%z = llvm.call @unreachable_func(%x) : (i32) -> (i32)
692+
llvm.return %z : i32
693+
}

mlir/test/lib/Dialect/Test/TestDialectInterfaces.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,8 @@ struct TestInlinerInterface : public DialectInlinerInterface {
316316

317317
/// Handle the given inlined terminator by replacing it with a new operation
318318
/// as necessary.
319-
void handleTerminator(Operation *op, ValueRange valuesToRepl) const final {
319+
void handleTerminator(Operation *op, OpBuilder &builder,
320+
ValueRange valuesToRepl) const final {
320321
// Only handle "test.return" here.
321322
auto returnOp = dyn_cast<TestReturnOp>(op);
322323
if (!returnOp)

0 commit comments

Comments
 (0)