Skip to content

Commit 9379a2c

Browse files
committed
[CodeGen] Use first EHLabel as a stop gate for live range shrinking
This fixes issue #114194 The issue happens during the LiveRangeShrink pass, which runs early, before phi elimination. LandingPads, which are lowered to EHLabels, need to be the first non phi instruction in an EHPad. In case of a phi node being in front of the EHLabel and a use being after the EHLabel, we hoist the use in front of the label. This results in a portion of the landingpad missing due to being hoisted in front of the label.
1 parent f358422 commit 9379a2c

File tree

2 files changed

+127
-6
lines changed

2 files changed

+127
-6
lines changed

llvm/lib/CodeGen/LiveRangeShrink.cpp

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -124,15 +124,24 @@ bool LiveRangeShrink::runOnMachineFunction(MachineFunction &MF) {
124124
for (MachineBasicBlock &MBB : MF) {
125125
if (MBB.empty())
126126
continue;
127-
bool SawStore = false;
128-
BuildInstOrderMap(MBB.begin(), IOM);
127+
128+
MachineBasicBlock::iterator Next = MBB.begin();
129+
if (MBB.isEHPad()) {
130+
// Do not track PHIs in IOM when handling EHPads.
131+
// Otherwise their uses may be hoisted outside a landingpad range.
132+
Next = MBB.SkipPHIsLabelsAndDebug(Next);
133+
if (Next == MBB.end())
134+
continue;
135+
}
136+
137+
BuildInstOrderMap(Next, IOM);
138+
Next = MBB.SkipPHIsLabelsAndDebug(Next);
129139
UseMap.clear();
140+
bool SawStore = false;
130141

131-
for (MachineBasicBlock::iterator Next = MBB.begin(); Next != MBB.end();) {
142+
while (Next != MBB.end()) {
132143
MachineInstr &MI = *Next;
133-
++Next;
134-
if (MI.isPHI() || MI.isDebugOrPseudoInstr())
135-
continue;
144+
Next = MBB.SkipPHIsLabelsAndDebug(++Next);
136145
if (MI.mayStore())
137146
SawStore = true;
138147

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
2+
; RUN: llc -mtriple x86_64-unknown-linux-gnu %s -o - | FileCheck %s
3+
4+
declare i32 @__gxx_personality_v0(...)
5+
declare void @maythrow()
6+
declare void @cleanup(i32)
7+
8+
@external_bool = external global i1
9+
@externalA = external global i32
10+
@externalB = external global i32
11+
@externalC = external global i32
12+
@externalD = external global i32
13+
14+
define void @test() personality ptr @__gxx_personality_v0 {
15+
; CHECK-LABEL: test:
16+
; CHECK: # %bb.0:
17+
; CHECK-NEXT: pushq %rbp
18+
; CHECK-NEXT: .cfi_def_cfa_offset 16
19+
; CHECK-NEXT: pushq %r15
20+
; CHECK-NEXT: .cfi_def_cfa_offset 24
21+
; CHECK-NEXT: pushq %r14
22+
; CHECK-NEXT: .cfi_def_cfa_offset 32
23+
; CHECK-NEXT: pushq %r13
24+
; CHECK-NEXT: .cfi_def_cfa_offset 40
25+
; CHECK-NEXT: pushq %r12
26+
; CHECK-NEXT: .cfi_def_cfa_offset 48
27+
; CHECK-NEXT: pushq %rbx
28+
; CHECK-NEXT: .cfi_def_cfa_offset 56
29+
; CHECK-NEXT: pushq %rax
30+
; CHECK-NEXT: .cfi_def_cfa_offset 64
31+
; CHECK-NEXT: .cfi_offset %rbx, -56
32+
; CHECK-NEXT: .cfi_offset %r12, -48
33+
; CHECK-NEXT: .cfi_offset %r13, -40
34+
; CHECK-NEXT: .cfi_offset %r14, -32
35+
; CHECK-NEXT: .cfi_offset %r15, -24
36+
; CHECK-NEXT: .cfi_offset %rbp, -16
37+
; CHECK-NEXT: movq external_bool@GOTPCREL(%rip), %rax
38+
; CHECK-NEXT: cmpb $1, (%rax)
39+
; CHECK-NEXT: jne .LBB0_3
40+
; CHECK-NEXT: # %bb.1: # %branchA
41+
; CHECK-NEXT: movq externalA@GOTPCREL(%rip), %rax
42+
; CHECK-NEXT: movl (%rax), %eax
43+
; CHECK-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
44+
; CHECK-NEXT: movq externalC@GOTPCREL(%rip), %rax
45+
; CHECK-NEXT: movl (%rax), %eax
46+
; CHECK-NEXT: movl %eax, (%rsp) # 4-byte Spill
47+
; CHECK-NEXT: #APP
48+
; CHECK-NEXT: #NO_APP
49+
; CHECK-NEXT: .Ltmp2:
50+
; CHECK-NEXT: callq maythrow@PLT
51+
; CHECK-NEXT: .Ltmp3:
52+
; CHECK-NEXT: jmp .LBB0_4
53+
; CHECK-NEXT: .LBB0_3: # %branchB
54+
; CHECK-NEXT: movq externalB@GOTPCREL(%rip), %rax
55+
; CHECK-NEXT: movl (%rax), %eax
56+
; CHECK-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
57+
; CHECK-NEXT: movq externalD@GOTPCREL(%rip), %rax
58+
; CHECK-NEXT: movl (%rax), %eax
59+
; CHECK-NEXT: movl %eax, (%rsp) # 4-byte Spill
60+
; CHECK-NEXT: #APP
61+
; CHECK-NEXT: #NO_APP
62+
; CHECK-NEXT: .Ltmp0:
63+
; CHECK-NEXT: callq maythrow@PLT
64+
; CHECK-NEXT: .Ltmp1:
65+
; CHECK-NEXT: .LBB0_4: # %end
66+
; CHECK-NEXT: addq $8, %rsp
67+
; CHECK-NEXT: .cfi_def_cfa_offset 56
68+
; CHECK-NEXT: popq %rbx
69+
; CHECK-NEXT: .cfi_def_cfa_offset 48
70+
; CHECK-NEXT: popq %r12
71+
; CHECK-NEXT: .cfi_def_cfa_offset 40
72+
; CHECK-NEXT: popq %r13
73+
; CHECK-NEXT: .cfi_def_cfa_offset 32
74+
; CHECK-NEXT: popq %r14
75+
; CHECK-NEXT: .cfi_def_cfa_offset 24
76+
; CHECK-NEXT: popq %r15
77+
; CHECK-NEXT: .cfi_def_cfa_offset 16
78+
; CHECK-NEXT: popq %rbp
79+
; CHECK-NEXT: .cfi_def_cfa_offset 8
80+
; CHECK-NEXT: retq
81+
; CHECK-NEXT: .LBB0_2: # %lpad
82+
; CHECK-NEXT: .cfi_def_cfa_offset 64
83+
; CHECK-NEXT: .Ltmp4:
84+
; CHECK-NEXT: movq %rax, %rbx
85+
; CHECK-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %edi # 4-byte Reload
86+
; CHECK-NEXT: addl (%rsp), %edi # 4-byte Folded Reload
87+
; CHECK-NEXT: callq cleanup@PLT
88+
; CHECK-NEXT: movq %rbx, %rdi
89+
; CHECK-NEXT: callq _Unwind_Resume@PLT
90+
%1 = load i1, ptr @external_bool
91+
br i1 %1, label %branchA, label %branchB
92+
branchA:
93+
%valueA = load i32, ptr @externalA
94+
%valueC = load i32, ptr @externalC
95+
call void asm sideeffect "", "~{rbp},~{rsi},~{rdi},~{rcx},~{rbx},~{r12},~{r13},~{r14},~{r15},~{flags}"()
96+
invoke void @maythrow() to label %end unwind label %lpad
97+
branchB:
98+
%valueB = load i32, ptr @externalB
99+
%valueD = load i32, ptr @externalD
100+
call void asm sideeffect "", "~{rbp},~{rsi},~{rdi},~{rcx},~{rbx},~{r12},~{r13},~{r14},~{r15},~{flags}"()
101+
invoke void @maythrow() to label %end unwind label %lpad
102+
lpad:
103+
%phiValue = phi i32 [%valueA, %branchA], [%valueB, %branchB]
104+
%phiValue2 = phi i32 [%valueC, %branchA], [%valueD, %branchB]
105+
%lp = landingpad { ptr, i32 }
106+
cleanup
107+
%3 = add i32 %phiValue2, %phiValue
108+
call void @cleanup(i32 %3)
109+
resume { ptr, i32 } %lp
110+
end:
111+
ret void
112+
}

0 commit comments

Comments
 (0)