-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[MLIR][LLVM] Support for indirectbr #135092
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[MLIR][LLVM] Support for indirectbr #135092
Conversation
Now that LLVM dialect has blockaddress support, introduce import/translation for indirectbr intruction.
@llvm/pr-subscribers-mlir-llvm @llvm/pr-subscribers-mlir Author: Bruno Cardoso Lopes (bcardosolopes) ChangesNow that LLVM dialect has blockaddress support, introduce import/translation for indirectbr instruction. Full diff: https://github.com/llvm/llvm-project/pull/135092.diff 10 Files Affected:
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index 6602318b07b85..154594833906d 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -1705,6 +1705,65 @@ def LLVM_BlockTagOp : LLVM_Op<"blocktag"> {
let hasVerifier = 0;
}
+//===----------------------------------------------------------------------===//
+// IndirectBrOp
+//===----------------------------------------------------------------------===//
+
+def LLVM_IndirectBrOp : LLVM_TerminatorOp<"indirectbr",
+ [SameVariadicOperandSize, DeclareOpInterfaceMethods<BranchOpInterface>,
+ Pure]> {
+ let description = [{
+ Transfer control flow to address in `$addr`. A list of possible target
+ blocks in `$successors` can be provided and maybe used as a hint in LLVM:
+
+ ```mlir
+ ...
+ llvm.func @g(...
+ %dest = llvm.blockaddress <function = @g, tag = <id = 0>> : !llvm.ptr
+ llvm.indirectbr %dest : !llvm.ptr, [
+ ^head
+ ]
+ ^head:
+ llvm.blocktag <id = 0>
+ llvm.return %arg0 : i32
+ ...
+ ```
+
+ It also supports a list of operands that can be passed to a target block:
+
+ ```mlir
+ llvm.indirectbr %dest : !llvm.ptr, [
+ ^head(%arg0 : i32),
+ ^tail(%arg1 : i32)
+ ]
+ ^head(%r0 : i32):
+ llvm.return %r0 : i32
+ ^tail(%r1 : i32):
+ llvm.return %r1 : i32
+
+ ```
+ }];
+ let arguments = (ins LLVM_AnyPointer:$addr,
+ VariadicOfVariadic<AnyType, "indbr_operand_segments">:$succOperands,
+ DenseI32ArrayAttr:$indbr_operand_segments
+ );
+ let successors = (successor VariadicSuccessor<AnySuccessor>:$successors);
+ let assemblyFormat = [{
+ $addr `:` type($addr) `,`
+ custom<IndirectBrOpSucessors>(ref(type($addr)),
+ $successors,
+ $succOperands,
+ type($succOperands))
+ attr-dict
+ }];
+
+ let builders = [
+ OpBuilder<(ins "Value":$addr,
+ CArg<"BlockRange", "{}">:$successors,
+ CArg<"ArrayRef<ValueRange>", "{}">:$succOperands)>
+ ];
+}
+
def LLVM_ComdatSelectorOp : LLVM_Op<"comdat_selector", [Symbol]> {
let arguments = (ins
SymbolNameAttr:$sym_name,
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index 33a1686541996..d28f97893206c 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -3879,6 +3879,64 @@ LogicalResult BlockAddressOp::verify() {
/// attribute.
OpFoldResult BlockAddressOp::fold(FoldAdaptor) { return getBlockAddr(); }
+//===----------------------------------------------------------------------===//
+// LLVM::IndirectBrOp
+//===----------------------------------------------------------------------===//
+
+SuccessorOperands IndirectBrOp::getSuccessorOperands(unsigned index) {
+ assert(index < getNumSuccessors() && "invalid successor index");
+ return SuccessorOperands(getSuccOperandsMutable()[index]);
+}
+
+static ParseResult parseIndirectBrOpSucessors(
+ OpAsmParser &parser, Type &flagType,
+ SmallVectorImpl<Block *> &succOperandBlocks,
+ SmallVectorImpl<SmallVector<OpAsmParser::UnresolvedOperand>> &succOperands,
+ SmallVectorImpl<SmallVector<Type>> &succOperandsTypes) {
+ if (failed(parser.parseCommaSeparatedList(
+ OpAsmParser::Delimiter::Square,
+ [&]() {
+ Block *destination = nullptr;
+ SmallVector<OpAsmParser::UnresolvedOperand> operands;
+ SmallVector<Type> operandTypes;
+
+ if (parser.parseSuccessor(destination).failed())
+ return failure();
+
+ if (succeeded(parser.parseOptionalLParen())) {
+ if (failed(parser.parseOperandList(
+ operands, OpAsmParser::Delimiter::None)) ||
+ failed(parser.parseColonTypeList(operandTypes)) ||
+ failed(parser.parseRParen()))
+ return failure();
+ }
+ succOperandBlocks.push_back(destination);
+ succOperands.emplace_back(operands);
+ succOperandsTypes.emplace_back(operandTypes);
+ return success();
+ },
+ "successor blocks")))
+ return failure();
+ return success();
+}
+
+static void
+printIndirectBrOpSucessors(OpAsmPrinter &p, IndirectBrOp op, Type flagType,
+ SuccessorRange succs, OperandRangeRange succOperands,
+ const TypeRangeRange &succOperandsTypes) {
+ p << "[";
+ llvm::interleave(
+ llvm::zip(succs, succOperands),
+ [&](auto i) {
+ p.printNewline();
+ p.printSuccessorAndUseList(std::get<0>(i), std::get<1>(i));
+ },
+ [&] { p << ','; });
+ if (!succOperands.empty())
+ p.printNewline();
+ p << "]";
+}
+
//===----------------------------------------------------------------------===//
// AssumeOp (intrinsic)
//===----------------------------------------------------------------------===//
diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
index 738f036bb376a..5c7f032404010 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
@@ -503,6 +503,15 @@ convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
moduleTranslation.mapBranch(&opInst, switchInst);
return success();
}
+ if (auto indBrOp = dyn_cast<LLVM::IndirectBrOp>(opInst)) {
+ llvm::IndirectBrInst *indBr = builder.CreateIndirectBr(
+ moduleTranslation.lookupValue(indBrOp.getAddr()),
+ indBrOp->getNumSuccessors());
+ for (auto *succ : indBrOp.getSuccessors())
+ indBr->addDestination(moduleTranslation.lookupBlock(succ));
+ moduleTranslation.mapBranch(&opInst, indBr);
+ return success();
+ }
// Emit addressof. We need to look up the global value referenced by the
// operation and store it in the MLIR-to-LLVM value mapping. This does not
diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index 187f1bdf7af6e..a1faef695aecb 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -1988,6 +1988,31 @@ LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
return success();
}
+ if (inst->getOpcode() == llvm::Instruction::IndirectBr) {
+ auto *indBrInst = cast<llvm::IndirectBrInst>(inst);
+
+ FailureOr<Value> basePtr = convertValue(indBrInst->getAddress());
+ if (failed(basePtr))
+ return failure();
+
+ SmallVector<Block *> succBlocks;
+ SmallVector<ValueRange> succBlockArgs;
+ for (auto i : llvm::seq<unsigned>(0, indBrInst->getNumSuccessors())) {
+ llvm::BasicBlock *succ = indBrInst->getSuccessor(i);
+ SmallVector<Value> blockArgs;
+ if (failed(convertBranchArgs(indBrInst, succ, blockArgs)))
+ return failure();
+ succBlocks.push_back(lookupBlock(succ));
+ succBlockArgs.push_back(blockArgs);
+ }
+ Location loc = translateLoc(inst->getDebugLoc());
+ auto indBrOp = builder.create<LLVM::IndirectBrOp>(
+ loc, TypeRange{}, *basePtr, succBlockArgs, succBlocks);
+
+ mapNoResultOp(inst, indBrOp);
+ return success();
+ }
+
// Convert all instructions that have an mlirBuilder.
if (succeeded(convertInstructionImpl(builder, inst, *this, iface)))
return success();
@@ -1998,8 +2023,8 @@ LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
LogicalResult ModuleImport::processInstruction(llvm::Instruction *inst) {
// FIXME: Support uses of SubtargetData.
// FIXME: Add support for call / operand attributes.
- // FIXME: Add support for the indirectbr, cleanupret, catchret, catchswitch,
- // callbr, vaarg, catchpad, cleanuppad instructions.
+ // FIXME: Add support for the cleanupret, catchret, catchswitch, callbr,
+ // vaarg, catchpad, cleanuppad instructions.
// Convert LLVM intrinsics calls to MLIR intrinsics.
if (auto *intrinsic = dyn_cast<llvm::IntrinsicInst>(inst))
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index ee7dc3a5231f4..54d9e4410714b 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -805,6 +805,12 @@ static Value getPHISourceValue(Block *current, Block *pred,
return switchOp.getCaseOperands(i.index())[index];
}
+ if (auto indBrOp = dyn_cast<LLVM::IndirectBrOp>(terminator)) {
+ // For indirect branches we take operands for each successor.
+ for (const auto &i : llvm::enumerate(indBrOp->getSuccessors()))
+ return indBrOp.getSuccessorOperands(i.index())[index];
+ }
+
if (auto invokeOp = dyn_cast<LLVM::InvokeOp>(terminator)) {
return invokeOp.getNormalDest() == current
? invokeOp.getNormalDestOperands()[index]
diff --git a/mlir/test/Dialect/LLVMIR/indirectbr.mlir b/mlir/test/Dialect/LLVMIR/indirectbr.mlir
new file mode 100644
index 0000000000000..c3c04eacb1a73
--- /dev/null
+++ b/mlir/test/Dialect/LLVMIR/indirectbr.mlir
@@ -0,0 +1,81 @@
+// RUN: mlir-opt -split-input-file --verify-roundtrip %s | FileCheck %s
+
+llvm.func @ib0(%dest : !llvm.ptr, %arg0 : i32, %arg1 : i32) -> i32 {
+ llvm.indirectbr %dest : !llvm.ptr, [
+ ^head(%arg0 : i32),
+ ^tail(%arg1 : i32)
+ ]
+^head(%r0 : i32):
+ llvm.return %r0 : i32
+^tail(%r1 : i32):
+ llvm.return %r1 : i32
+}
+
+// CHECK: llvm.func @ib0(%[[Addr:.*]]: !llvm.ptr, %[[A0:.*]]: i32, %[[A1:.*]]: i32) -> i32 {
+// CHECK: llvm.indirectbr %[[Addr]] : !llvm.ptr, [
+// CHECK: ^bb1(%[[A0:.*]] : i32)
+// CHECK: ^bb2(%[[A1:.*]] : i32)
+// CHECK: ]
+// CHECK: ^bb1(%[[Op0:.*]]: i32):
+// CHECK: llvm.return %[[Op0]] : i32
+// CHECK: ^bb2(%[[Op1:.*]]: i32):
+// CHECK: llvm.return %[[Op1]] : i32
+// CHECK: }
+
+// -----
+
+llvm.func @ib1(%dest : !llvm.ptr) {
+ llvm.indirectbr %dest : !llvm.ptr, []
+}
+
+// CHECK: llvm.func @ib1(%[[Addr:.*]]: !llvm.ptr) {
+// CHECK: llvm.indirectbr %[[Addr]] : !llvm.ptr, []
+// CHECK: }
+
+// -----
+
+// CHECK: llvm.func @test_indirectbr_phi(
+// CHECK-SAME: %arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr, %arg3: i32) -> i32 {
+llvm.func @callee(!llvm.ptr, i32, i32) -> i32
+llvm.func @test_indirectbr_phi(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr, %arg3: i32) -> i32 {
+ %0 = llvm.mlir.undef : i1
+ %1 = llvm.mlir.addressof @test_indirectbr_phi : !llvm.ptr
+ %2 = llvm.blockaddress <function = @test_indirectbr_phi, tag = <id = 1>> : !llvm.ptr
+ // CHECK: %[[ONE:.*]] = llvm.mlir.constant(1 : i32) : i32
+ %3 = llvm.mlir.constant(1 : i32) : i32
+ // CHECK: %[[TWO:.*]] = llvm.mlir.constant(2 : i32) : i32
+ %4 = llvm.mlir.constant(2 : i32) : i32
+ %5 = llvm.select %0, %2, %arg0 : i1, !llvm.ptr
+ // CHECK: llvm.indirectbr {{.*}} : !llvm.ptr, [
+ // CHECK: ^[[HEAD_BB:.*]],
+ // CHECK: ^[[TAIL_BB:.*]](%[[ONE]] : i32)
+ // CHECK: ]
+ llvm.indirectbr %5 : !llvm.ptr, [
+ ^bb1,
+ ^bb2(%3 : i32)
+ ]
+^bb1:
+ // CHECK: ^[[HEAD_BB]]:
+ // CHECK: llvm.indirectbr {{.*}} : !llvm.ptr, [
+ // CHECK: ^[[TAIL_BB]](%[[TWO]] : i32),
+ // CHECK: ^[[END_BB:.*]]
+ // CHECK: ]
+ %6 = llvm.select %0, %2, %arg0 : i1, !llvm.ptr
+ llvm.indirectbr %6 : !llvm.ptr, [
+ ^bb2(%4 : i32),
+ ^bb3
+ ]
+^bb2(%7: i32):
+ // CHECK: ^[[TAIL_BB]](%[[BLOCK_ARG:.*]]: i32):
+ // CHECK: {{.*}} = llvm.call @callee({{.*}}, %[[BLOCK_ARG]])
+ // CHECK: llvm.return
+ %8 = llvm.call @callee(%arg1, %arg3, %7) : (!llvm.ptr, i32, i32) -> i32
+ llvm.return %8 : i32
+^bb3:
+ // CHECK: ^[[END_BB]]:
+ // CHECK: llvm.blocktag
+ // CHECK: llvm.return
+ // CHECK: }
+ llvm.blocktag <id = 1>
+ llvm.return %arg3 : i32
+}
diff --git a/mlir/test/Target/LLVMIR/Import/import-failure.ll b/mlir/test/Target/LLVMIR/Import/import-failure.ll
index 4fbf187659a7b..782925a0a938e 100644
--- a/mlir/test/Target/LLVMIR/Import/import-failure.ll
+++ b/mlir/test/Target/LLVMIR/Import/import-failure.ll
@@ -1,17 +1,5 @@
; RUN: not mlir-translate -import-llvm -emit-expensive-warnings -split-input-file %s 2>&1 -o /dev/null | FileCheck %s
-; CHECK: <unknown>
-; CHECK-SAME: error: unhandled instruction: indirectbr ptr %dst, [label %bb1, label %bb2]
-define i32 @unhandled_instruction(ptr %dst) {
- indirectbr ptr %dst, [label %bb1, label %bb2]
-bb1:
- ret i32 0
-bb2:
- ret i32 1
-}
-
-; // -----
-
; Check that debug intrinsics with an unsupported argument are dropped.
declare void @llvm.dbg.value(metadata, metadata, metadata)
diff --git a/mlir/test/Target/LLVMIR/Import/indirectbr.ll b/mlir/test/Target/LLVMIR/Import/indirectbr.ll
new file mode 100644
index 0000000000000..f1da3e3887927
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/Import/indirectbr.ll
@@ -0,0 +1,86 @@
+; RUN: mlir-translate --import-llvm %s -split-input-file | FileCheck %s
+
+; CHECK: llvm.func @basic(%[[arg0:.*]]: !llvm.ptr)
+define i32 @basic(ptr %dst) {
+ ; CHECK: llvm.indirectbr %[[arg0]] : !llvm.ptr, [
+ ; CHECK: ^[[bb1:.*]],
+ ; CHECK: ^[[bb2:.*]]
+ ; CHECK: ]
+ indirectbr ptr %dst, [label %bb1, label %bb2]
+bb1:
+ ; CHECK: ^[[bb1]]:
+ ; CHECK: llvm.return
+ ret i32 0
+bb2:
+ ; CHECK: ^[[bb2]]:
+ ; CHECK: llvm.return
+ ret i32 1
+}
+
+; // -----
+
+; CHECK: llvm.mlir.global external @addr()
+@addr = global ptr null
+
+; CHECK-LABEL: llvm.func @test_indirectbr() {
+define void @test_indirectbr() {
+ ; CHECK: %[[BA:.*]] = llvm.blockaddress <function = @test_indirectbr, tag = <id = 1>> : !llvm.ptr
+ ; CHECK: {{.*}} = llvm.mlir.addressof @addr : !llvm.ptr
+ ; CHECK: llvm.store %[[BA]], {{.*}} : !llvm.ptr, !llvm.ptr
+ store ptr blockaddress(@test_indirectbr, %block), ptr @addr
+ ; CHECK: %[[TARGET_ADDR:.*]] = llvm.load {{.*}} : !llvm.ptr -> !llvm.ptr
+ %val = load ptr, ptr @addr
+ ; CHECK: llvm.indirectbr %[[TARGET_ADDR]] : !llvm.ptr, [
+ ; CHECK: ^[[TARGET_BB:.*]]
+ ; CHECK: ]
+ indirectbr ptr %val, [label %block]
+ ; CHECK: ^[[TARGET_BB]]:
+ ; CHECK: llvm.blocktag <id = 1>
+ ; CHECK: llvm.return
+ ; CHECK: }
+block:
+ ret void
+}
+
+; // -----
+
+; CHECK: llvm.func @callee(!llvm.ptr, i32, i32) -> i32
+declare i32 @callee(ptr %a, i32 %v, i32 %p)
+
+; CHECK: llvm.func @test_indirectbr_phi(
+; CHECK-SAME: %arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr, %arg3: i32) -> i32 {
+define i32 @test_indirectbr_phi(ptr %address, ptr %a, ptr %b, i32 %v) {
+entry:
+ ; CHECK: %[[ONE:.*]] = llvm.mlir.constant(1 : i32) : i32
+ ; CHECK: %[[TWO:.*]] = llvm.mlir.constant(2 : i32) : i32
+ %dest = select i1 undef, ptr blockaddress(@test_indirectbr_phi, %end), ptr %address
+ ; CHECK: llvm.indirectbr {{.*}} : !llvm.ptr, [
+ ; CHECK: ^[[HEAD_BB:.*]],
+ ; CHECK: ^[[TAIL_BB:.*]](%[[ONE]] : i32)
+ ; CHECK: ]
+ indirectbr ptr %dest, [label %head, label %tail]
+
+head:
+ ; CHECK: ^[[HEAD_BB]]:
+ ; CHECK: llvm.indirectbr {{.*}} : !llvm.ptr, [
+ ; CHECK: ^[[TAIL_BB]](%[[TWO]] : i32),
+ ; CHECK: ^[[END_BB:.*]]
+ ; CHECK: ]
+ %dest2 = select i1 undef, ptr blockaddress(@test_indirectbr_phi, %end), ptr %address
+ indirectbr ptr %dest2, [label %tail, label %end]
+
+tail:
+ ; CHECK: ^[[TAIL_BB]](%[[BLOCK_ARG:.*]]: i32):
+ ; CHECK: {{.*}} = llvm.call @callee({{.*}}, %[[BLOCK_ARG]])
+ ; CHECK: llvm.return
+ %p = phi i32 [1, %entry], [2, %head]
+ %r = call i32 @callee(ptr %a, i32 %v, i32 %p)
+ ret i32 %r
+
+end:
+ ; CHECK: ^[[END_BB]]:
+ ; CHECK: llvm.blocktag
+ ; CHECK: llvm.return
+ ; CHECK: }
+ ret i32 %v
+}
diff --git a/mlir/test/Target/LLVMIR/indirectbr.mlir b/mlir/test/Target/LLVMIR/indirectbr.mlir
new file mode 100644
index 0000000000000..538220721e9eb
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/indirectbr.mlir
@@ -0,0 +1,40 @@
+// RUN: mlir-translate -mlir-to-llvmir %s -split-input-file | FileCheck %s
+
+llvm.func @callee(!llvm.ptr, i32, i32) -> i32
+
+// CHECK: define i32 @test_indirectbr_phi(ptr %[[IN_PTR:.*]], ptr %[[ARG1:.*]], i32 %[[ARG2:.*]]) {
+llvm.func @test_indirectbr_phi(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg3: i32) -> i32 {
+ %0 = llvm.mlir.undef : i1
+ %2 = llvm.blockaddress <function = @test_indirectbr_phi, tag = <id = 1>> : !llvm.ptr
+ %3 = llvm.mlir.constant(1 : i32) : i32
+ %4 = llvm.mlir.constant(2 : i32) : i32
+ %5 = llvm.select %0, %2, %arg0 : i1, !llvm.ptr
+ // CHECK: %[[BA0:.*]] = select i1 undef, ptr blockaddress(@test_indirectbr_phi, %[[RET_BB:.*]]), ptr %[[IN_PTR]]
+ // CHECK: indirectbr ptr %[[BA0]], [label %[[BB1:.*]], label %[[BB2:.*]]]
+ llvm.indirectbr %5 : !llvm.ptr, [
+ ^bb1,
+ ^bb2(%3 : i32)
+ ]
+^bb1:
+ // CHECK: [[BB1]]:
+ // CHECK: %[[BA1:.*]] = select i1 undef, ptr blockaddress(@test_indirectbr_phi, %[[RET_BB]]), ptr %[[IN_PTR]]
+ // CHECK: indirectbr ptr %[[BA1]], [label %[[BB2]], label %[[RET_BB]]]
+ %6 = llvm.select %0, %2, %arg0 : i1, !llvm.ptr
+ llvm.indirectbr %6 : !llvm.ptr, [
+ ^bb2(%4 : i32),
+ ^bb3
+ ]
+^bb2(%7: i32):
+ // CHECK: [[BB2]]:
+ // CHECK: %[[PHI:.*]] = phi i32 [ 2, %[[BB1]] ], [ 1, {{.*}} ]
+ // CHECK: %[[CALL:.*]] = call i32 @callee(ptr %[[ARG1]], i32 %[[ARG2]], i32 %[[PHI]])
+ // CHECK: ret i32 %[[CALL]]
+ %8 = llvm.call @callee(%arg1, %arg3, %7) : (!llvm.ptr, i32, i32) -> i32
+ llvm.return %8 : i32
+^bb3:
+ // CHECK: [[RET_BB]]:
+ // CHECK: ret i32 %[[ARG2]]
+ // CHECK: }
+ llvm.blocktag <id = 1>
+ llvm.return %arg3 : i32
+}
diff --git a/mlir/test/mlir-translate/import-diagnostics.ll b/mlir/test/mlir-translate/import-diagnostics.ll
index acf45eb1c7c5d..6767d948e3bbd 100644
--- a/mlir/test/mlir-translate/import-diagnostics.ll
+++ b/mlir/test/mlir-translate/import-diagnostics.ll
@@ -21,14 +21,16 @@ end:
; ERROR: error:
; DEFAULT: error:
; EXPENSIVE: error:
-define i32 @error(ptr %dst) {
- indirectbr ptr %dst, [label %bb1, label %bb2]
-bb1:
- ret i32 0
-bb2:
- ret i32 1
+define dso_local void @tbaa(ptr %0) {
+ store i32 1, ptr %0, align 4, !tbaa !2
+ ret void
}
+!2 = !{!3, !3, i64 0, i64 4}
+!3 = !{!4, i64 4, !"int"}
+!4 = !{!5, i64 1, !"omnipotent char"}
+!5 = !{!"Simple C++ TBAA"}
+
; // -----
declare void @llvm.dbg.value(metadata, metadata, metadata)
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!
Looks good to me! Can you verify if this works together with canoncialize/region simplify or if we may delete dead blocks bcs the indirect branch cannot be analyzed (I tried to describe an example in the comments below).
* origin/main: (287 commits) [Sema] On Windows, silence erroneous warning when building with MSVC [lldb][lldbp-dap] On Windoows, silence warnings when building with MSVC [lldb] Fix erroneous return value [compiler-rt] On Windows, silence warning when building with Clang ToT [clang][unittests] On Windows, silence warning when building with MSVC [lldb] On Windows, silence warning when building with Clang ToT [CIR] Make LLVM & OGCG variables match the same pattern (llvm#135427) [mlir][SMT] upstream `SMT` dialect (llvm#131480) [clang] fix serialization for SubstNonTypeTemplateParmPackExpr (llvm#135428) [flang][openacc] Allow if_present multiple times on host_data and update (llvm#135422) [flang][openacc] Allow finalize clause on exit data more than once (llvm#135415) [flang] IEEE_SCALB and SCALE - kind=2, kind=3 (llvm#135374) [-Wunsafe-buffer-usage] Add findUnsafePointers (llvm#135421) [compiler-rt][sanitizer] add Haiku support (llvm#134772) [cpp23] Remove usage of std::aligned_union<> in llvm (llvm#135146) [mlir][tosa] Add error_if checks for Mul Op (llvm#135075) [VPlan] Merge cases using getResultType in inferScalarType (NFC). [flang][runtime] Fix recently broken big-endian formatted integer input (llvm#135417) [AMDGPU][Verifier] Mark calls to entry functions as invalid in the IR verifier (llvm#134910) [llvm][Hexagon] Promote operand v2i1 to v2i32 (llvm#135409) ...
* origin/main: [mlir][vector] Prevent folding non memref-type gather into maskedload (llvm#135371) [mlir][SMT] remove custom forall/exists builder because of asan memory leak [bazel] Fix a typo (llvm#135460) [bazel] Add support for SMT Dialect (llvm#135454) [clang] ASTImporter: fix SubstNonTypeTemplateParmExpr source location (llvm#135450) [RISCV] Don't fold offsets into auipc if offset is larger than the reference global variable. (llvm#135297) [gn] port d1fd977 [NFC][LLVM] Apply std::move to object being pushed back in findSymbolCommon (llvm#135290) [AMDGPU] Teach iterative schedulers about IGLP (llvm#134953)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After looking that the changes I wonder if we want to keep the additional verifier since:
- We probably need some DFS to detect dead blocks reliably
- The verifier is different from the verifier in LLVM proper (which we should normally avoid, I wrote some comment why we could make an exception here)
- The verifier actually kicks in while the IR is technically still correct (maybe we should rely on the block address op verifier instead that kicks in once the IR is invalid, see may explanation below)
Would this additional verifier be helpful for your use case? Maybe clang IR actually wants / needs to produce such unreachable blocks with tags. That may be perfectly fine as long as we do not call region simplify. So this verifier may actually come into our way at some point. Instead we can maybe rely on the existing blockaddress op verifier that kicks in once bad things happened (i.e. a tag operation got deleted)?
As you wrote the only real long-term solution will probably be to hook into region simplify.
* origin/main: (199 commits) [NFC][AsmPrinter] Refactor AsmPrinter and AArch64AsmPrinter to prepare for jump table partitions on aarch64 (llvm#125993) [HEXAGON] Fix corner cases for hwloops pass (llvm#135439) [flang] Handle volatility in lowering and codegen (llvm#135311) [MLIR][Shape] Support >2 args in `shape.broadcast` folder (llvm#126808) [DirectX] Use scalar arguments for @llvm.dx.dot intrinsics (llvm#134570) Remove the redundant check for "WeakPtr" in isSmartPtrClass to fix the issue 135612. (llvm#135629) [BOLT] Support relative vtable (llvm#135449) [flang] Fix linking to libMLIR (llvm#135483) [AsmPrinter] Link .section_sizes to the correct section (llvm#135583) [ctxprof] Handle instrumenting functions with `musttail` calls (llvm#135121) [SystemZ] Consider VST/VL as SimpleBDXStore/Load (llvm#135623) [libc++][CI] Pin the XCode version. (llvm#135412) [lldb-dap] Fix win32 build. (llvm#135638) [Interp] Mark inline-virtual.cpp as unsupported with ASan (llvm#135402) [libc++] Removes the _LIBCPP_VERBOSE_ABORT_NOT_NOEXCEPT macro. (llvm#135494) [CVP] Add tests for ucmp/scmp with switch (NFC) [mlir][tosa] Align AbsOp example variable names (llvm#135268) [mlir][tosa] Align AddOp examples to spec (llvm#135266) [mlir][tosa] Align RFFT2d and FFT2d operator examples (llvm#135261) [flang][OpenMP][HLFIR] Support vector subscripted array sections for DEPEND (llvm#133892) ...
Agreed. This works fine for our current use cases and in the future we can go for the long term solution. |
Addressed last round of reviews + fixed CI failure. |
"Code formatting" failures are unrelated (the tool is crashing for some other reason), verified by running git-clang-format locally. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I think dropping the verifier makes more sense. Sorry saw this only once I reviewed the actual solution...
LGTM modulo some optional code style suggestion.
This reverts commit 5216633.
Now that LLVM dialect has `blockaddress` support, introduce import/translation for `indirectbr` instruction.
Now that LLVM dialect has blockaddress support, introduce import/translation for indirectbr instruction.