Skip to content

Commit b76832b

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 b76832b

File tree

2 files changed

+129
-2
lines changed

2 files changed

+129
-2
lines changed

llvm/lib/CodeGen/LiveRangeShrink.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,16 +74,26 @@ using InstOrderMap = DenseMap<MachineInstr *, unsigned>;
7474
/// M[A] > M[B] guarantees that A is dominated by B.
7575
/// If \p New is not in \p M, return \p Old. Otherwise if \p Old is null, return
7676
/// \p New.
77+
/// If \p New is part of an EHPad and is not dominated by \p EHBarrier, return
78+
/// \p Old, because the start of the landingpad is required to be the first
79+
/// non-PHI instruction.
7780
static MachineInstr *FindDominatedInstruction(MachineInstr &New,
7881
MachineInstr *Old,
82+
MachineInstr *EHBarrier,
7983
const InstOrderMap &M) {
8084
auto NewIter = M.find(&New);
8185
if (NewIter == M.end())
8286
return Old;
87+
unsigned OrderNew = NewIter->second;
88+
if (EHBarrier) {
89+
unsigned OrderBarrier = M.find(EHBarrier)->second;
90+
if (OrderBarrier > OrderNew) {
91+
return Old;
92+
}
93+
}
8394
if (Old == nullptr)
8495
return &New;
8596
unsigned OrderOld = M.find(Old)->second;
86-
unsigned OrderNew = NewIter->second;
8797
if (OrderOld != OrderNew)
8898
return OrderOld < OrderNew ? &New : Old;
8999
// OrderOld == OrderNew, we need to iterate down from Old to see if it
@@ -125,14 +135,19 @@ bool LiveRangeShrink::runOnMachineFunction(MachineFunction &MF) {
125135
if (MBB.empty())
126136
continue;
127137
bool SawStore = false;
138+
bool IsEHPad = MBB.isEHPad();
139+
MachineInstr *EHBarrier = nullptr;
128140
BuildInstOrderMap(MBB.begin(), IOM);
129141
UseMap.clear();
130142

131143
for (MachineBasicBlock::iterator Next = MBB.begin(); Next != MBB.end();) {
132144
MachineInstr &MI = *Next;
133145
++Next;
146+
134147
if (MI.isPHI() || MI.isDebugOrPseudoInstr())
135148
continue;
149+
if (IsEHPad && !EHBarrier && MI.isEHLabel())
150+
EHBarrier = &MI;
136151
if (MI.mayStore())
137152
SawStore = true;
138153

@@ -201,7 +216,7 @@ bool LiveRangeShrink::runOnMachineFunction(MachineFunction &MF) {
201216
MachineInstr &DefInstr = *MRI.def_instr_begin(Reg);
202217
if (!TII.isCopyInstr(DefInstr))
203218
NumEligibleUse++;
204-
Insert = FindDominatedInstruction(DefInstr, Insert, IOM);
219+
Insert = FindDominatedInstruction(DefInstr, Insert, EHBarrier, IOM);
205220
} else {
206221
Insert = nullptr;
207222
break;
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)