Skip to content

Commit f744390

Browse files
committed
[Statepoint] Handle undef operands in statepoint.
Currently when spilling statepoint register operands in FixupStatepoints we do not pay attention that it might be `undef`. We just generate a spill, which may lead to verifier error because we have a use without def. To handle it, let FixupStateponts ignore `undef` register operands completely and change them to some constant value when generating stack map. Use same value as used by ISel for this purpose (0xFEFEFEFE). Reviewed By: reames Differential Revision: https://reviews.llvm.org/D94703
1 parent 689aaba commit f744390

File tree

3 files changed

+243
-1
lines changed

3 files changed

+243
-1
lines changed

llvm/lib/CodeGen/FixupStatepointCallerSaved.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,9 @@ class StatepointState {
380380
EndIdx = MI.getNumOperands();
381381
Idx < EndIdx; ++Idx) {
382382
MachineOperand &MO = MI.getOperand(Idx);
383-
if (!MO.isReg() || MO.isImplicit())
383+
// Leave `undef` operands as is, StackMaps will rewrite them
384+
// into a constant.
385+
if (!MO.isReg() || MO.isImplicit() || MO.isUndef())
384386
continue;
385387
Register Reg = MO.getReg();
386388
assert(Reg.isPhysical() && "Only physical regs are expected");

llvm/lib/CodeGen/StackMaps.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,12 @@ StackMaps::parseOperand(MachineInstr::const_mop_iterator MOI,
234234
if (MOI->isImplicit())
235235
return ++MOI;
236236

237+
if (MOI->isUndef()) {
238+
// Record `undef` register as constant. Use same value as ISel uses.
239+
Locs.emplace_back(Location::Constant, sizeof(int64_t), 0, 0xFEFEFEFE);
240+
return ++MOI;
241+
}
242+
237243
assert(Register::isPhysicalRegister(MOI->getReg()) &&
238244
"Virtreg operands should have been rewritten before now.");
239245
const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(MOI->getReg());
Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
2+
# RUN: llc -x mir -run-pass fixup-statepoint-caller-saved -verify-machineinstrs < %s | FileCheck %s
3+
# RUN: llc -x mir -start-before fixup-statepoint-caller-saved -verify-machineinstrs < %s | FileCheck %s -check-prefix=STACKMAP
4+
5+
--- |
6+
; ModuleID = 'undef.ll'
7+
source_filename = "test_undef.ll"
8+
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
9+
target triple = "x86_64-unknown-linux-gnu"
10+
11+
define void @test_undef(i8 addrspace(1)* %arg1, i8 addrspace(1)* %arg2, i8 addrspace(1)* %arg3, i8 addrspace(1)* %arg4) #0 gc "statepoint-example" {
12+
bb:
13+
%tmp1 = lshr i32 0, undef
14+
%tmp2 = load atomic i32, i32 addrspace(1)* undef unordered, align 8
15+
%tmp3 = load atomic i32, i32 addrspace(1)* undef unordered, align 8
16+
br label %bb7
17+
18+
bb7: ; preds = %bb
19+
%tmp4 = icmp slt i32 %tmp3, undef
20+
%tmp5 = select i1 %tmp4, i32 6, i32 undef
21+
%tmp6 = add i32 %tmp5, %tmp2
22+
%tmp7 = call i8 addrspace(1)* @wombat()
23+
%tmp20 = call token (i64, i32, void (i8 addrspace(1)*, i32, i32, i8 addrspace(1)*, i32)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidp1i8i32i32p1i8i32f(i64 2, i32 5, void (i8 addrspace(1)*, i32, i32, i8 addrspace(1)*, i32)* nonnull @hoge, i32 5, i32 0, i8 addrspace(1)* %arg3, i32 %tmp2, i32 %tmp6, i8 addrspace(1)* %tmp7, i32 0, i32 0, i32 0) [ "deopt"(i8 addrspace(1)* %arg2, i8 addrspace(1)* %arg1, i8 addrspace(1)* %arg3, i8 addrspace(1)* %arg4, i32 %tmp2, i32 %tmp1, i32 %tmp5), "gc-live"() ]
24+
ret void
25+
}
26+
27+
declare void @hoge(i8 addrspace(1)*, i32, i32, i8 addrspace(1)*, i32) #0
28+
29+
declare i8 addrspace(1)* @wombat() #0
30+
31+
; Function Attrs: nounwind readonly
32+
declare i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token, i32 immarg, i32 immarg) #1
33+
34+
declare token @llvm.experimental.gc.statepoint.p0f_isVoidp1i8i32i32p1i8i32f(i64 immarg, i32 immarg, void (i8 addrspace(1)*, i32, i32, i8 addrspace(1)*, i32)*, i32 immarg, i32 immarg, ...) #0
35+
36+
attributes #0 = { "target-cpu"="broadwell" }
37+
attributes #1 = { nounwind readonly "target-cpu"="broadwell" }
38+
39+
...
40+
---
41+
name: test_undef
42+
alignment: 16
43+
exposesReturnsTwice: false
44+
legalized: false
45+
regBankSelected: false
46+
selected: false
47+
failedISel: false
48+
tracksRegLiveness: true
49+
hasWinCFI: false
50+
registers: []
51+
liveins:
52+
- { reg: '$rdi', virtual-reg: '' }
53+
- { reg: '$rsi', virtual-reg: '' }
54+
- { reg: '$rdx', virtual-reg: '' }
55+
- { reg: '$rcx', virtual-reg: '' }
56+
frameInfo:
57+
isFrameAddressTaken: false
58+
isReturnAddressTaken: false
59+
hasStackMap: false
60+
hasPatchPoint: false
61+
stackSize: 0
62+
offsetAdjustment: 0
63+
maxAlignment: 8
64+
adjustsStack: false
65+
hasCalls: true
66+
stackProtector: ''
67+
maxCallFrameSize: 4294967295
68+
cvBytesOfCalleeSavedRegisters: 0
69+
hasOpaqueSPAdjustment: false
70+
hasVAStart: false
71+
hasMustTailInVarArgFunc: false
72+
localFrameSize: 0
73+
savePoint: ''
74+
restorePoint: ''
75+
fixedStack: []
76+
stack:
77+
- { id: 0, name: '', type: default, offset: 0, size: 8, alignment: 8,
78+
stack-id: default, callee-saved-register: '', callee-saved-restored: true,
79+
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
80+
- { id: 1, name: '', type: default, offset: 0, size: 8, alignment: 8,
81+
stack-id: default, callee-saved-register: '', callee-saved-restored: true,
82+
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
83+
- { id: 2, name: '', type: default, offset: 0, size: 8, alignment: 8,
84+
stack-id: default, callee-saved-register: '', callee-saved-restored: true,
85+
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
86+
- { id: 3, name: '', type: default, offset: 0, size: 8, alignment: 8,
87+
stack-id: default, callee-saved-register: '', callee-saved-restored: true,
88+
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
89+
callSites: []
90+
debugValueSubstitutions: []
91+
constants: []
92+
machineFunctionInfo: {}
93+
body: |
94+
; CHECK-LABEL: name: test_undef
95+
; CHECK: bb.0.bb:
96+
; CHECK: successors: %bb.1(0x80000000)
97+
; CHECK: liveins: $rcx, $rdi, $rdx, $rsi
98+
; CHECK: renamable $r15 = COPY $rcx
99+
; CHECK: renamable $r14 = COPY $rdx
100+
; CHECK: renamable $r13 = COPY $rsi
101+
; CHECK: renamable $r12 = COPY $rdi
102+
; CHECK: renamable $ebx = MOV32rm undef renamable $rax, 1, $noreg, 0, $noreg, implicit-def $rbx :: (load unordered 4 from `i32 addrspace(1)* undef`, align 8, addrspace 1)
103+
; CHECK: bb.1.bb7:
104+
; CHECK: liveins: $rbx, $r12, $r13, $r14, $r15
105+
; CHECK: renamable $ebp = LEA64_32r renamable $rbx, 1, $noreg, 6, $noreg
106+
; CHECK: ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
107+
; CHECK: CALL64pcrel32 target-flags(x86-plt) @wombat, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp, implicit-def $rax
108+
; CHECK: ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
109+
; CHECK: MOV64mr %stack.0, 1, $noreg, 0, $noreg, killed renamable $r13 :: (store 8 into %stack.0)
110+
; CHECK: MOV64mr %stack.1, 1, $noreg, 0, $noreg, killed renamable $r12 :: (store 8 into %stack.1)
111+
; CHECK: MOV64mr %stack.2, 1, $noreg, 0, $noreg, renamable $r14 :: (store 8 into %stack.2)
112+
; CHECK: MOV64mr %stack.3, 1, $noreg, 0, $noreg, killed renamable $r15 :: (store 8 into %stack.3)
113+
; CHECK: ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
114+
; CHECK: $rdi = COPY killed renamable $r14
115+
; CHECK: $esi = COPY renamable $ebx
116+
; CHECK: $edx = COPY killed renamable $ebp
117+
; CHECK: $rcx = COPY killed renamable $rax
118+
; CHECK: $r8d = MOV32r0 implicit-def dead $eflags
119+
; CHECK: STATEPOINT 2, 5, 5, undef renamable $rax, $rdi, $esi, $edx, $rcx, killed $r8d, 2, 0, 2, 0, 2, 7, 1, 8, %stack.0, 0, 1, 8, %stack.1, 0, 1, 8, %stack.2, 0, 1, 8, %stack.3, 0, renamable $ebx, undef renamable $eax, 2, 6, 2, 0, 2, 0, 2, 0, csr_64, implicit-def $rsp, implicit-def $ssp, implicit killed $rbx :: (volatile load store 8 on %stack.0), (volatile load store 8 on %stack.1), (volatile load store 8 on %stack.2), (volatile load store 8 on %stack.3)
120+
; CHECK: ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
121+
; CHECK: RET 0
122+
; STACKMAP-LABEL: __LLVM_StackMaps:
123+
; STACKMAP: .byte 3
124+
; STACKMAP: .byte 0
125+
; STACKMAP: .short 0
126+
; STACKMAP: .long 1
127+
; STACKMAP: .long 1
128+
; STACKMAP: .long 1
129+
; STACKMAP: .quad test_undef
130+
; STACKMAP: .quad 88
131+
; STACKMAP: .quad 1
132+
; STACKMAP: .quad 4278124286
133+
; STACKMAP: .quad 2
134+
; STACKMAP: .long .Ltmp0-test_undef
135+
; STACKMAP: .short 0
136+
; STACKMAP: .short 10
137+
; STACKMAP: .byte 4
138+
; STACKMAP: .byte 0
139+
; STACKMAP: .short 8
140+
; STACKMAP: .short 0
141+
; STACKMAP: .short 0
142+
; STACKMAP: .long 0
143+
; STACKMAP: .byte 4
144+
; STACKMAP: .byte 0
145+
; STACKMAP: .short 8
146+
; STACKMAP: .short 0
147+
; STACKMAP: .short 0
148+
; STACKMAP: .long 0
149+
; STACKMAP: .byte 4
150+
; STACKMAP: .byte 0
151+
; STACKMAP: .short 8
152+
; STACKMAP: .short 0
153+
; STACKMAP: .short 0
154+
; STACKMAP: .long 7
155+
; STACKMAP: .byte 3
156+
; STACKMAP: .byte 0
157+
; STACKMAP: .short 8
158+
; STACKMAP: .short 7
159+
; STACKMAP: .short 0
160+
; STACKMAP: .long 32
161+
; STACKMAP: .byte 3
162+
; STACKMAP: .byte 0
163+
; STACKMAP: .short 8
164+
; STACKMAP: .short 7
165+
; STACKMAP: .short 0
166+
; STACKMAP: .long 24
167+
; STACKMAP: .byte 3
168+
; STACKMAP: .byte 0
169+
; STACKMAP: .short 8
170+
; STACKMAP: .short 7
171+
; STACKMAP: .short 0
172+
; STACKMAP: .long 16
173+
; STACKMAP: .byte 3
174+
; STACKMAP: .byte 0
175+
; STACKMAP: .short 8
176+
; STACKMAP: .short 7
177+
; STACKMAP: .short 0
178+
; STACKMAP: .long 8
179+
; STACKMAP: .byte 1
180+
; STACKMAP: .byte 0
181+
; STACKMAP: .short 4
182+
; STACKMAP: .short 3
183+
; STACKMAP: .short 0
184+
; STACKMAP: .long 0
185+
; This is entry we're looking for, reference to constant pool entry 0xFEFEFEFE
186+
; STACKMAP: .byte 5
187+
; STACKMAP: .byte 0
188+
; STACKMAP: .short 8
189+
; STACKMAP: .short 0
190+
; STACKMAP: .short 0
191+
; STACKMAP: .long 0
192+
; STACKMAP: .byte 4
193+
; STACKMAP: .byte 0
194+
; STACKMAP: .short 8
195+
; STACKMAP: .short 0
196+
; STACKMAP: .short 0
197+
; STACKMAP: .long 6
198+
; STACKMAP: .p2align 3
199+
; STACKMAP: .short 0
200+
; STACKMAP: .short 0
201+
; STACKMAP: .p2align 3
202+
bb.0.bb:
203+
successors: %bb.1(0x80000000)
204+
liveins: $rcx, $rdi, $rdx, $rsi
205+
206+
renamable $r15 = COPY $rcx
207+
renamable $r14 = COPY $rdx
208+
renamable $r13 = COPY $rsi
209+
renamable $r12 = COPY $rdi
210+
renamable $ebx = MOV32rm undef renamable $rax, 1, $noreg, 0, $noreg, implicit-def $rbx :: (load unordered 4 from `i32 addrspace(1)* undef`, align 8, addrspace 1)
211+
212+
bb.1.bb7:
213+
liveins: $rbx, $r12, $r13, $r14, $r15
214+
215+
renamable $ebp = LEA64_32r renamable $rbx, 1, $noreg, 6, $noreg
216+
ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
217+
CALL64pcrel32 target-flags(x86-plt) @wombat, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp, implicit-def $rax
218+
ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
219+
MOV64mr %stack.0, 1, $noreg, 0, $noreg, killed renamable $r13 :: (store 8 into %stack.0)
220+
MOV64mr %stack.1, 1, $noreg, 0, $noreg, killed renamable $r12 :: (store 8 into %stack.1)
221+
MOV64mr %stack.2, 1, $noreg, 0, $noreg, renamable $r14 :: (store 8 into %stack.2)
222+
MOV64mr %stack.3, 1, $noreg, 0, $noreg, killed renamable $r15 :: (store 8 into %stack.3)
223+
ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
224+
$rdi = COPY killed renamable $r14
225+
$esi = COPY renamable $ebx
226+
$edx = COPY killed renamable $ebp
227+
$rcx = COPY killed renamable $rax
228+
$r8d = MOV32r0 implicit-def dead $eflags
229+
STATEPOINT 2, 5, 5, undef renamable $rax, $rdi, $esi, $edx, $rcx, killed $r8d, 2, 0, 2, 0, 2, 7, 1, 8, %stack.0, 0, 1, 8, %stack.1, 0, 1, 8, %stack.2, 0, 1, 8, %stack.3, 0, renamable $ebx, undef renamable $eax, 2, 6, 2, 0, 2, 0, 2, 0, csr_64, implicit-def $rsp, implicit-def $ssp, implicit killed $rbx :: (volatile load store 8 on %stack.0), (volatile load store 8 on %stack.1), (volatile load store 8 on %stack.2), (volatile load store 8 on %stack.3)
230+
ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
231+
RET 0
232+
233+
...
234+

0 commit comments

Comments
 (0)