Skip to content

Commit 737d209

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 737d209

File tree

2 files changed

+121
-0
lines changed

2 files changed

+121
-0
lines changed

llvm/lib/CodeGen/LiveRangeShrink.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ bool LiveRangeShrink::runOnMachineFunction(MachineFunction &MF) {
125125
if (MBB.empty())
126126
continue;
127127
bool SawStore = false;
128+
bool IsEHPad = MBB.isEHPad();
129+
bool SawEHLabel = false;
128130
BuildInstOrderMap(MBB.begin(), IOM);
129131
UseMap.clear();
130132

@@ -135,6 +137,13 @@ bool LiveRangeShrink::runOnMachineFunction(MachineFunction &MF) {
135137
continue;
136138
if (MI.mayStore())
137139
SawStore = true;
140+
if (IsEHPad && !SawEHLabel && MI.isEHLabel() && Next != MBB.end()) {
141+
// If MI is the first EHLabel of an EHPad, it should become a
142+
// barrier for code motion. IOM is rebuild from the next instruction
143+
// to prevent later instructions from being moved before this MI.
144+
SawEHLabel = true;
145+
BuildInstOrderMap(Next, IOM);
146+
}
138147

139148
unsigned CurrentOrder = IOM[&MI];
140149
unsigned Barrier = 0;
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)