Skip to content

Commit 53445f5

Browse files
committed
[GlobalISel] Add a new G_INVOKE_REGION_START instruction to fix an EH bug.
We currently have a bug where the legalizer, when dealing with phi operands, may create instructions in the phi's incoming blocks at points which are effectively dead due to a possible exception throw. Say we have: throwbb: EH_LABEL x0 = %callarg1 BL @may_throw_call EH_LABEL B returnbb bb: %v = phi i1 %true, throwbb, %false.... When legalizing we may need to widen the i1 %true value, and to do that we need to create new extension instructions in the incoming block. Our insertion point currently is the MBB::getFirstTerminator() which puts the IP before the unconditional branch terminator in throwbb. These extensions may never be executed if the call throws, and therefore we need to emit them before the call (but not too early, since our new instruction may need values defined within throwbb as well). throwbb: EH_LABEL x0 = %callarg1 BL @may_throw_call EH_LABEL %true = G_CONSTANT i32 1 ; <<<-- ruh'roh, this never executes if may_throw_call() throws! B returnbb bb: %v = phi i32 %true, throwbb, %false.... To fix this, I've added two new instructions. The main idea is that G_INVOKE_REGION_START is a terminator, which tries to model the fact that in the IR, the original invoke inst is actually a terminator as well. By using that as the new insertion point, we make sure to place new instructions on always executing paths. Unfortunately we still need to make the legalizer use a new insertion point API that I've added, since the existing `getFirstTerminator()` method does a reverse walk up the block, and any non-terminator instructions cause it to bail out. To avoid impacting compile time for all `getFirstTerminator()` uses, I've added a new method that does a forward walk instead. Differential Revision: https://reviews.llvm.org/D137905
1 parent 14ea545 commit 53445f5

15 files changed

+192
-5
lines changed

llvm/docs/GlobalISel/GenericOpcode.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -838,6 +838,14 @@ codegen with GlobalISel.
838838
839839
The above example generates a pointer to the source jump table index.
840840

841+
G_INVOKE_REGION_START
842+
^^^^^^^^^^^^^^^^^^^^^
843+
844+
A marker instruction that acts as a pseudo-terminator for regions of code that may
845+
throw exceptions. Being a terminator, it prevents code from being inserted after
846+
it during passes like legalization. This is needed because calls to exception
847+
throw routines do not return, so no code that must be on an executable path must
848+
be placed after throwing.
841849

842850
G_INTRINSIC, G_INTRINSIC_W_SIDE_EFFECTS
843851
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

llvm/include/llvm/CodeGen/MachineBasicBlock.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -833,6 +833,11 @@ class MachineBasicBlock
833833
/// instr_iterator instead.
834834
instr_iterator getFirstInstrTerminator();
835835

836+
/// Finds the first terminator in a block by scanning forward. This can handle
837+
/// cases in GlobalISel where there may be non-terminator instructions between
838+
/// terminators, for which getFirstTerminator() will not work correctly.
839+
iterator getFirstTerminatorForward();
840+
836841
/// Returns an iterator to the first non-debug instruction in the basic block,
837842
/// or end(). Skip any pseudo probe operation if \c SkipPseudoOp is true.
838843
/// Pseudo probes are like debug instructions which do not turn into real

llvm/include/llvm/Support/TargetOpcodes.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,9 @@ HANDLE_TARGET_OPCODE(G_BRCOND)
404404
/// Generic indirect branch instruction.
405405
HANDLE_TARGET_OPCODE(G_BRINDIRECT)
406406

407+
/// Begin an invoke region marker.
408+
HANDLE_TARGET_OPCODE(G_INVOKE_REGION_START)
409+
407410
/// Generic intrinsic use (without side effects).
408411
HANDLE_TARGET_OPCODE(G_INTRINSIC)
409412

llvm/include/llvm/Target/GenericOpcodes.td

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1270,6 +1270,15 @@ def G_BRJT : GenericInstruction {
12701270
let isIndirectBranch = true;
12711271
}
12721272

1273+
// A marker to signal the following code is an invoke region, that may throw
1274+
// an exception and therefore not return.
1275+
def G_INVOKE_REGION_START : GenericInstruction {
1276+
let OutOperandList = (outs);
1277+
let InOperandList = (ins);
1278+
let isTerminator = true; // This must be a terminator.
1279+
let hasSideEffects = false;
1280+
}
1281+
12731282
def G_READ_REGISTER : GenericInstruction {
12741283
let OutOperandList = (outs type0:$dst);
12751284
let InOperandList = (ins unknown:$register);

llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2599,6 +2599,7 @@ bool IRTranslator::translateInvoke(const User &U,
25992599
// the region covered by the try.
26002600
MCSymbol *BeginSymbol = nullptr;
26012601
if (NeedEHLabel) {
2602+
MIRBuilder.buildInstr(TargetOpcode::G_INVOKE_REGION_START);
26022603
BeginSymbol = Context.createTempSymbol();
26032604
MIRBuilder.buildInstr(TargetOpcode::EH_LABEL).addSym(BeginSymbol);
26042605
}

llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,11 @@ bool InstructionSelect::runOnMachineFunction(MachineFunction &MF) {
184184
continue;
185185
}
186186

187+
if (MI.getOpcode() == TargetOpcode::G_INVOKE_REGION_START) {
188+
MI.eraseFromParent();
189+
continue;
190+
}
191+
187192
if (!ISel->select(MI)) {
188193
// FIXME: It would be nice to dump all inserted instructions. It's
189194
// not obvious how, esp. considering select() can insert after MI.

llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,7 +1174,7 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
11741174
Observer.changingInstr(MI);
11751175
for (unsigned i = 1; i < MI.getNumOperands(); i += 2) {
11761176
MachineBasicBlock &OpMBB = *MI.getOperand(i + 1).getMBB();
1177-
MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
1177+
MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminatorForward());
11781178
extractParts(MI.getOperand(i).getReg(), NarrowTy, NumParts,
11791179
SrcRegs[i / 2]);
11801180
}
@@ -2459,7 +2459,7 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
24592459
Observer.changingInstr(MI);
24602460
for (unsigned I = 1; I < MI.getNumOperands(); I += 2) {
24612461
MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB();
2462-
MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
2462+
MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminatorForward());
24632463
widenScalarSrc(MI, WideTy, I, TargetOpcode::G_ANYEXT);
24642464
}
24652465

@@ -3785,7 +3785,7 @@ LegalizerHelper::fewerElementsVectorPhi(GenericMachineInstr &MI,
37853785
for (unsigned UseIdx = NumDefs, UseNo = 0; UseIdx < MI.getNumOperands();
37863786
UseIdx += 2, ++UseNo) {
37873787
MachineBasicBlock &OpMBB = *MI.getOperand(UseIdx + 1).getMBB();
3788-
MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
3788+
MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminatorForward());
37893789
extractVectorParts(MI.getReg(UseIdx), NumElts, InputOpsPieces[UseNo]);
37903790
}
37913791

llvm/lib/CodeGen/MachineBasicBlock.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "llvm/CodeGen/MachineBasicBlock.h"
14+
#include "llvm/ADT/STLExtras.h"
1415
#include "llvm/CodeGen/LiveIntervals.h"
1516
#include "llvm/CodeGen/LivePhysRegs.h"
1617
#include "llvm/CodeGen/LiveVariables.h"
@@ -254,6 +255,10 @@ MachineBasicBlock::instr_iterator MachineBasicBlock::getFirstInstrTerminator() {
254255
return I;
255256
}
256257

258+
MachineBasicBlock::iterator MachineBasicBlock::getFirstTerminatorForward() {
259+
return find_if(instrs(), [](auto &II) { return II.isTerminator(); });
260+
}
261+
257262
MachineBasicBlock::iterator
258263
MachineBasicBlock::getFirstNonDebugInstr(bool SkipPseudoOp) {
259264
// Skip over begin-of-block dbg_value instructions.

llvm/lib/CodeGen/MachineVerifier.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -830,8 +830,12 @@ void MachineVerifier::visitMachineBundleBefore(const MachineInstr *MI) {
830830
if (!FirstTerminator)
831831
FirstTerminator = MI;
832832
} else if (FirstTerminator) {
833-
report("Non-terminator instruction after the first terminator", MI);
834-
errs() << "First terminator was:\t" << *FirstTerminator;
833+
// For GlobalISel, G_INVOKE_REGION_START is a terminator that we allow to
834+
// precede non-terminators.
835+
if (FirstTerminator->getOpcode() != TargetOpcode::G_INVOKE_REGION_START) {
836+
report("Non-terminator instruction after the first terminator", MI);
837+
errs() << "First terminator was:\t" << *FirstTerminator;
838+
}
835839
}
836840
}
837841

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
2+
; RUN: llc -O0 -mtriple=aarch64-apple-ios -global-isel -stop-after=legalizer %s -o - | FileCheck %s
3+
4+
@global_var = external global i32
5+
declare i32 @__gxx_personality_v0(...)
6+
declare void @may_throw()
7+
8+
; This test checks that the widened G_CONSTANT operand to the phi in "continue" bb
9+
; is placed before the potentially throwing call in the entry block.
10+
define i1 @test_lpad_phi_widen_into_pred() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
11+
; CHECK-LABEL: name: test_lpad_phi_widen_into_pred
12+
; CHECK: bb.1 (%ir-block.0):
13+
; CHECK-NEXT: successors: %bb.3(0x40000000), %bb.2(0x40000000)
14+
; CHECK-NEXT: {{ $}}
15+
; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 42
16+
; CHECK-NEXT: [[GV:%[0-9]+]]:_(p0) = G_GLOBAL_VALUE @global_var
17+
; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 11
18+
; CHECK-NEXT: G_STORE [[C]](s32), [[GV]](p0) :: (store (s32) into @global_var)
19+
; CHECK-NEXT: [[C2:%[0-9]+]]:_(s16) = G_CONSTANT i16 1
20+
; CHECK-NEXT: G_INVOKE_REGION_START
21+
; CHECK-NEXT: EH_LABEL <mcsymbol >
22+
; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
23+
; CHECK-NEXT: BL @may_throw, csr_darwin_aarch64_aapcs, implicit-def $lr, implicit $sp
24+
; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
25+
; CHECK-NEXT: EH_LABEL <mcsymbol >
26+
; CHECK-NEXT: G_BR %bb.3
27+
; CHECK-NEXT: {{ $}}
28+
; CHECK-NEXT: bb.2.lpad (landing-pad):
29+
; CHECK-NEXT: successors: %bb.3(0x80000000)
30+
; CHECK-NEXT: liveins: $x0, $x1
31+
; CHECK-NEXT: {{ $}}
32+
; CHECK-NEXT: [[PHI:%[0-9]+]]:_(s32) = G_PHI [[C1]](s32), %bb.1
33+
; CHECK-NEXT: EH_LABEL <mcsymbol >
34+
; CHECK-NEXT: G_STORE [[PHI]](s32), [[GV]](p0) :: (store (s32) into @global_var)
35+
; CHECK-NEXT: [[C3:%[0-9]+]]:_(s16) = G_CONSTANT i16 0
36+
; CHECK-NEXT: G_BR %bb.3
37+
; CHECK-NEXT: {{ $}}
38+
; CHECK-NEXT: bb.3.continue:
39+
; CHECK-NEXT: [[PHI1:%[0-9]+]]:_(s16) = G_PHI [[C2]](s16), %bb.1, [[C3]](s16), %bb.2
40+
; CHECK-NEXT: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
41+
; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[PHI1]](s16)
42+
; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ANYEXT]], [[C4]]
43+
; CHECK-NEXT: $w0 = COPY [[AND]](s32)
44+
; CHECK-NEXT: RET_ReallyLR implicit $w0
45+
store i32 42, i32* @global_var
46+
invoke void @may_throw()
47+
to label %continue unwind label %lpad
48+
49+
lpad: ; preds = %entry
50+
%p = phi i32 [ 11, %0 ]
51+
%1 = landingpad { i8*, i32 }
52+
catch i8* null
53+
store i32 %p, i32* @global_var
54+
br label %continue
55+
56+
continue: ; preds = %entry, %lpad
57+
%r.0 = phi i1 [ 1, %0 ], [ 0, %lpad ]
58+
ret i1 %r.0
59+
}
60+
61+
; Same test but with extensions.
62+
define i1 @test_lpad_phi_widen_into_pred_ext(i1 *%ptr) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
63+
; CHECK-LABEL: name: test_lpad_phi_widen_into_pred_ext
64+
; CHECK: bb.1 (%ir-block.0):
65+
; CHECK-NEXT: successors: %bb.3(0x40000000), %bb.2(0x40000000)
66+
; CHECK-NEXT: liveins: $x0
67+
; CHECK-NEXT: {{ $}}
68+
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0
69+
; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 42
70+
; CHECK-NEXT: [[GV:%[0-9]+]]:_(p0) = G_GLOBAL_VALUE @global_var
71+
; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 11
72+
; CHECK-NEXT: G_STORE [[C]](s32), [[GV]](p0) :: (store (s32) into @global_var)
73+
; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(s8) = G_LOAD [[COPY]](p0) :: (load (s8) from %ir.ptr)
74+
; CHECK-NEXT: [[ASSERT_ZEXT:%[0-9]+]]:_(s8) = G_ASSERT_ZEXT [[LOAD]], 1
75+
; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[ASSERT_ZEXT]](s8)
76+
; CHECK-NEXT: G_INVOKE_REGION_START
77+
; CHECK-NEXT: EH_LABEL <mcsymbol >
78+
; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
79+
; CHECK-NEXT: BL @may_throw, csr_darwin_aarch64_aapcs, implicit-def $lr, implicit $sp
80+
; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
81+
; CHECK-NEXT: EH_LABEL <mcsymbol >
82+
; CHECK-NEXT: G_BR %bb.3
83+
; CHECK-NEXT: {{ $}}
84+
; CHECK-NEXT: bb.2.lpad (landing-pad):
85+
; CHECK-NEXT: successors: %bb.3(0x80000000)
86+
; CHECK-NEXT: liveins: $x0, $x1
87+
; CHECK-NEXT: {{ $}}
88+
; CHECK-NEXT: [[PHI:%[0-9]+]]:_(s32) = G_PHI [[C1]](s32), %bb.1
89+
; CHECK-NEXT: EH_LABEL <mcsymbol >
90+
; CHECK-NEXT: G_STORE [[PHI]](s32), [[GV]](p0) :: (store (s32) into @global_var)
91+
; CHECK-NEXT: [[C2:%[0-9]+]]:_(s16) = G_CONSTANT i16 0
92+
; CHECK-NEXT: G_BR %bb.3
93+
; CHECK-NEXT: {{ $}}
94+
; CHECK-NEXT: bb.3.continue:
95+
; CHECK-NEXT: [[PHI1:%[0-9]+]]:_(s16) = G_PHI [[ANYEXT]](s16), %bb.1, [[C2]](s16), %bb.2
96+
; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
97+
; CHECK-NEXT: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[PHI1]](s16)
98+
; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ANYEXT1]], [[C3]]
99+
; CHECK-NEXT: $w0 = COPY [[AND]](s32)
100+
; CHECK-NEXT: RET_ReallyLR implicit $w0
101+
store i32 42, i32* @global_var
102+
%v = load i1, i1* %ptr
103+
invoke void @may_throw()
104+
to label %continue unwind label %lpad
105+
106+
lpad: ; preds = %entry
107+
%p = phi i32 [ 11, %0 ]
108+
%1 = landingpad { i8*, i32 }
109+
catch i8* null
110+
store i32 %p, i32* @global_var
111+
br label %continue
112+
113+
continue: ; preds = %entry, %lpad
114+
%r.0 = phi i1 [ %v, %0 ], [ 0, %lpad ]
115+
ret i1 %r.0
116+
}

llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-exceptions.ll

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ define { ptr, i32 } @bar() personality ptr @__gxx_personality_v0 {
1515
; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 42
1616
; CHECK-NEXT: [[DEF:%[0-9]+]]:_(p0) = G_IMPLICIT_DEF
1717
; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
18+
; CHECK-NEXT: G_INVOKE_REGION_START
1819
; CHECK-NEXT: EH_LABEL <mcsymbol >
1920
; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
2021
; CHECK-NEXT: $w0 = COPY [[C]](s32)
@@ -61,6 +62,7 @@ define void @test_invoke_indirect(ptr %callee) personality ptr @__gxx_personalit
6162
; CHECK-NEXT: liveins: $x0
6263
; CHECK-NEXT: {{ $}}
6364
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64(p0) = COPY $x0
65+
; CHECK-NEXT: G_INVOKE_REGION_START
6466
; CHECK-NEXT: EH_LABEL <mcsymbol >
6567
; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
6668
; CHECK-NEXT: BLR [[COPY]](p0), csr_darwin_aarch64_aapcs, implicit-def $lr, implicit $sp
@@ -99,6 +101,7 @@ define void @test_invoke_varargs() personality ptr @__gxx_personality_v0 {
99101
; CHECK-NEXT: [[C:%[0-9]+]]:_(p0) = G_CONSTANT i64 0
100102
; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 42
101103
; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_FCONSTANT float 1.000000e+00
104+
; CHECK-NEXT: G_INVOKE_REGION_START
102105
; CHECK-NEXT: EH_LABEL <mcsymbol >
103106
; CHECK-NEXT: ADJCALLSTACKDOWN 16, 0, implicit-def $sp, implicit $sp
104107
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $sp
@@ -151,6 +154,7 @@ define i32 @test_lpad_phi() personality ptr @__gxx_personality_v0 {
151154
; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 13
152155
; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 55
153156
; CHECK-NEXT: G_STORE [[C]](s32), [[GV]](p0) :: (store (s32) into @global_var)
157+
; CHECK-NEXT: G_INVOKE_REGION_START
154158
; CHECK-NEXT: EH_LABEL <mcsymbol >
155159
; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
156160
; CHECK-NEXT: BL @may_throw, csr_darwin_aarch64_aapcs, implicit-def $lr, implicit $sp

llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-unwind-inline-asm.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ define dso_local void @test() personality ptr @__gxx_personality_v0 {
1919
; CHECK-NEXT: successors: %bb.2(0x40000000), %bb.3(0x40000000)
2020
; CHECK-NEXT: {{ $}}
2121
; CHECK-NEXT: [[GV:%[0-9]+]]:_(p0) = G_GLOBAL_VALUE @.str.2
22+
; CHECK-NEXT: G_INVOKE_REGION_START
2223
; CHECK-NEXT: EH_LABEL <mcsymbol >
2324
; CHECK-NEXT: INLINEASM &"bl trap", 1 /* sideeffect attdialect */
2425
; CHECK-NEXT: EH_LABEL <mcsymbol >

llvm/test/CodeGen/AArch64/GlobalISel/legalize-exceptions.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ define void @bar() personality ptr @__gxx_personality_v0 {
1616
; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 42
1717
; CHECK-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0.exn.slot
1818
; CHECK-NEXT: [[FRAME_INDEX1:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.1.ehselector.slot
19+
; CHECK-NEXT: G_INVOKE_REGION_START
1920
; CHECK-NEXT: EH_LABEL <mcsymbol >
2021
; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
2122
; CHECK-NEXT: $w0 = COPY [[C]](s32)

llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,9 @@
248248
# DEBUG-NEXT: G_BRINDIRECT (opcode {{[0-9]+}}): 1 type index, 0 imm indices
249249
# DEBUG-NEXT: .. the first uncovered type index: 1, OK
250250
# DEBUG-NEXT: .. the first uncovered imm index: 0, OK
251+
# DEBUG-NEXT: G_INVOKE_REGION_START (opcode {{[0-9]+}}): 0 type indices, 0 imm indices
252+
# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
253+
# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
251254
# DEBUG-NEXT: G_INTRINSIC (opcode {{[0-9]+}}): 0 type indices, 0 imm indices
252255
# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
253256
# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#RUN: llc -march=aarch64 -o - -global-isel -run-pass=none -verify-machineinstrs %s 2>&1 | FileCheck %s
2+
# REQUIRES: aarch64-registered-target
3+
4+
---
5+
name: test_invoke_start
6+
legalized: true
7+
regBankSelected: false
8+
selected: false
9+
tracksRegLiveness: true
10+
liveins:
11+
body: |
12+
bb.0:
13+
14+
%0:_(s32) = G_CONSTANT i32 0
15+
16+
; Check we don't error when preceding a non-terminator
17+
; CHECK: G_INVOKE_REGION_START
18+
G_INVOKE_REGION_START
19+
20+
%1:_(s32) = G_ADD %0, %0
21+
22+
...

0 commit comments

Comments
 (0)