aboutsummaryrefslogtreecommitdiff
path: root/llvm/test/CodeGen/X86/statepoint-vector.ll
blob: f53ac2f8f6279eb97e66f09199cb8cb20803e31e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -verify-machineinstrs -stack-symbol-ordering=0 -mcpu=nehalem -debug-only=stackmaps < %s | FileCheck %s
; REQUIRES: asserts

target triple = "x86_64-pc-linux-gnu"

; Can we lower a single vector?
define <2 x ptr addrspace(1)> @test(<2 x ptr addrspace(1)> %obj) gc "statepoint-example" {
; CHECK-LABEL: test:
; CHECK:       # %bb.0: # %entry
; CHECK-NEXT:    subq $24, %rsp
; CHECK-NEXT:    .cfi_def_cfa_offset 32
; CHECK-NEXT:    movaps %xmm0, (%rsp)
; CHECK-NEXT:    callq do_safepoint@PLT
; CHECK-NEXT:  .Ltmp0:
; CHECK-NEXT:    movaps (%rsp), %xmm0
; CHECK-NEXT:    addq $24, %rsp
; CHECK-NEXT:    .cfi_def_cfa_offset 8
; CHECK-NEXT:    retq
entry:
  %safepoint_token = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) @do_safepoint, i32 0, i32 0, i32 0, i32 0) ["gc-live" (<2 x ptr addrspace(1)> %obj)]
  %obj.relocated = call coldcc <2 x ptr addrspace(1)> @llvm.experimental.gc.relocate.v2p1(token %safepoint_token, i32 0, i32 0) ; (%obj, %obj)
  ret <2 x ptr addrspace(1)> %obj.relocated
}

; Can we lower the base, derived pairs if both are vectors?
define <2 x ptr addrspace(1)> @test2(<2 x ptr addrspace(1)> %obj, i64 %offset) gc "statepoint-example" {
; CHECK-LABEL: test2:
; CHECK:       # %bb.0: # %entry
; CHECK-NEXT:    subq $40, %rsp
; CHECK-NEXT:    .cfi_def_cfa_offset 48
; CHECK-NEXT:    movq %rdi, %xmm1
; CHECK-NEXT:    pshufd {{.*#+}} xmm1 = xmm1[0,1,0,1]
; CHECK-NEXT:    paddq %xmm0, %xmm1
; CHECK-NEXT:    movdqa %xmm0, (%rsp)
; CHECK-NEXT:    movdqa %xmm1, {{[0-9]+}}(%rsp)
; CHECK-NEXT:    callq do_safepoint@PLT
; CHECK-NEXT:  .Ltmp1:
; CHECK-NEXT:    movaps {{[0-9]+}}(%rsp), %xmm0
; CHECK-NEXT:    addq $40, %rsp
; CHECK-NEXT:    .cfi_def_cfa_offset 8
; CHECK-NEXT:    retq
entry:
  %derived = getelementptr i8, <2 x ptr addrspace(1)> %obj, i64 %offset
  %safepoint_token = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) @do_safepoint, i32 0, i32 0, i32 0, i32 0) ["gc-live" (<2 x ptr addrspace(1)> %obj, <2 x ptr addrspace(1)> %derived)]
  %derived.relocated = call coldcc <2 x ptr addrspace(1)> @llvm.experimental.gc.relocate.v2p1(token %safepoint_token, i32 0, i32 1) ; (%obj, %derived)
  ret <2 x ptr addrspace(1)> %derived.relocated
}

; Originally, this was just a variant of @test2 above, but it ends up
; covering a bunch of interesting missed optimizations.  Specifically:
; - We waste a stack slot for a value that a backend transform pass
;   CSEd to another spilled one.
; - We don't remove the testb even though it serves no purpose
; - We could in principal reuse the argument memory (%rsi) and do away
;   with stack slots entirely.
define <2 x ptr addrspace(1)> @test3(i1 %cnd, ptr %ptr) gc "statepoint-example" {
; CHECK-LABEL: test3:
; CHECK:       # %bb.0: # %entry
; CHECK-NEXT:    testb $1, %dil
; CHECK-NEXT:    movaps (%rsi), %xmm0
; CHECK-NEXT:    subq $40, %rsp
; CHECK-NEXT:    .cfi_def_cfa_offset 48
; CHECK-NEXT:    movaps %xmm0, (%rsp)
; CHECK-NEXT:    movaps %xmm0, {{[0-9]+}}(%rsp)
; CHECK-NEXT:    callq do_safepoint@PLT
; CHECK-NEXT:  .Ltmp2:
; CHECK-NEXT:    movaps (%rsp), %xmm0
; CHECK-NEXT:    addq $40, %rsp
; CHECK-NEXT:    .cfi_def_cfa_offset 8
; CHECK-NEXT:    retq
entry:
  br i1 %cnd, label %taken, label %untaken

taken:                                            ; preds = %entry
  %obja = load <2 x ptr addrspace(1)>, ptr %ptr
  br label %merge

untaken:                                          ; preds = %entry
  %objb = load <2 x ptr addrspace(1)>, ptr %ptr
  br label %merge

merge:                                            ; preds = %untaken, %taken
  %obj.base = phi <2 x ptr addrspace(1)> [ %obja, %taken ], [ %objb, %untaken ]
  %obj = phi <2 x ptr addrspace(1)> [ %obja, %taken ], [ %objb, %untaken ]
  %safepoint_token = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) @do_safepoint, i32 0, i32 0, i32 0, i32 0) ["gc-live" (<2 x ptr addrspace(1)> %obj, <2 x ptr addrspace(1)> %obj.base)]
  %obj.relocated = call coldcc <2 x ptr addrspace(1)> @llvm.experimental.gc.relocate.v2p1(token %safepoint_token, i32 1, i32 0) ; (%obj.base, %obj)
  %obj.relocated.casted = bitcast <2 x ptr addrspace(1)> %obj.relocated to <2 x ptr addrspace(1)>
  %obj.base.relocated = call coldcc <2 x ptr addrspace(1)> @llvm.experimental.gc.relocate.v2p1(token %safepoint_token, i32 1, i32 1) ; (%obj.base, %obj.base)
  %obj.base.relocated.casted = bitcast <2 x ptr addrspace(1)> %obj.base.relocated to <2 x ptr addrspace(1)>
  ret <2 x ptr addrspace(1)> %obj.relocated.casted
}

; Can we handle vector constants?  At the moment, we don't appear to actually
; get selection dag nodes for these.
define <2 x ptr addrspace(1)> @test4() gc "statepoint-example" {
; CHECK-LABEL: test4:
; CHECK:       # %bb.0: # %entry
; CHECK-NEXT:    subq $24, %rsp
; CHECK-NEXT:    .cfi_def_cfa_offset 32
; CHECK-NEXT:    xorps %xmm0, %xmm0
; CHECK-NEXT:    movaps %xmm0, (%rsp)
; CHECK-NEXT:    callq do_safepoint@PLT
; CHECK-NEXT:  .Ltmp3:
; CHECK-NEXT:    movaps (%rsp), %xmm0
; CHECK-NEXT:    addq $24, %rsp
; CHECK-NEXT:    .cfi_def_cfa_offset 8
; CHECK-NEXT:    retq
entry:
  %safepoint_token = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) @do_safepoint, i32 0, i32 0, i32 0, i32 0) ["gc-live" (<2 x ptr addrspace(1)> zeroinitializer)]
  %obj.relocated = call coldcc <2 x ptr addrspace(1)> @llvm.experimental.gc.relocate.v2p1(token %safepoint_token, i32 0, i32 0)
  ret <2 x ptr addrspace(1)> %obj.relocated
}

; Check that we can lower a constant typed as i128 correctly.  We don't have
; a representation of larger than 64 bit constant in the StackMap format. At
; the moment, this simply means spilling them, but there's a potential
; optimization for values representable as sext(Con64).
define void @test5() gc "statepoint-example" {
; CHECK-LABEL: test5:
; CHECK:       # %bb.0: # %entry
; CHECK-NEXT:    subq $40, %rsp
; CHECK-NEXT:    .cfi_def_cfa_offset 48
; CHECK-NEXT:    xorps %xmm0, %xmm0
; CHECK-NEXT:    movaps %xmm0, {{[0-9]+}}(%rsp)
; CHECK-NEXT:    movq $-1, {{[0-9]+}}(%rsp)
; CHECK-NEXT:    movq $-1, (%rsp)
; CHECK-NEXT:    callq do_safepoint@PLT
; CHECK-NEXT:  .Ltmp4:
; CHECK-NEXT:    addq $40, %rsp
; CHECK-NEXT:    .cfi_def_cfa_offset 8
; CHECK-NEXT:    retq
entry:
  %safepoint_token = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) @do_safepoint, i32 0, i32 0, i32 0, i32 0) ["deopt" (i128 0, i128 -1)]
  ret void
}

; CHECK: __LLVM_StackMaps:

; CHECK: .Ltmp0-test
; Check for the two spill slots
; Stack Maps: 		Loc 3: Indirect 7+0	[encoding: .byte 3, .byte 0, .short 16, .short 7, .short 0, .int 0]
; Stack Maps: 		Loc 4: Indirect 7+0	[encoding: .byte 3, .byte 0, .short 16, .short 7, .short 0, .int 0]
; CHECK: .byte	3
; CHECK: .byte	0
; CHECK: .short 16
; CHECK: .short	7
; CHECK: .short	0
; CHECK: .long	0
; CHECK: .byte	3
; CHECK: .byte	0
; CHECK: .short 16
; CHECK: .short	7
; CHECK: .short	0
; CHECK: .long	0

; CHECK: .Ltmp1-test2
; Check for the two spill slots
; Stack Maps: 		Loc 3: Indirect 7+16	[encoding: .byte 3, .byte 0, .short 16, .short 7, .short 0, .int 16]
; Stack Maps: 		Loc 4: Indirect 7+0	[encoding: .byte 3, .byte 0, .short 16, .short 7, .short 0, .int 0]
; CHECK: .byte	3
; CHECK: .byte	0
; CHECK: .short 16
; CHECK: .short	7
; CHECK: .short	0
; CHECK: .long	0
; CHECK: .byte	3
; CHECK: .byte	0
; CHECK: .short 16
; CHECK: .short	7
; CHECK: .short	0
; CHECK: .long	16

; CHECK: .Ltmp2-test3
; Check for the four spill slots
; Stack Maps: 		Loc 3: Indirect 7+16	[encoding: .byte 3, .byte 0, .short 16, .short 7, .short 0, .int 16]
; Stack Maps: 		Loc 4: Indirect 7+16	[encoding: .byte 3, .byte 0, .short 16, .short 7, .short 0, .int 16]
; Stack Maps: 		Loc 5: Indirect 7+16	[encoding: .byte 3, .byte 0, .short 16, .short 7, .short 0, .int 16]
; Stack Maps: 		Loc 6: Indirect 7+0	[encoding: .byte 3, .byte 0, .short 16, .short 7, .short 0, .int 0]
; CHECK: .byte	3
; CHECK: .byte	0
; CHECK: .short 16
; CHECK: .short	7
; CHECK: .short	0
; CHECK: .long	16
; CHECK: .byte	3
; CHECK: .byte	 0
; CHECK: .short 16
; CHECK: .short	7
; CHECK: .short	0
; CHECK: .long	16
; CHECK: .byte	3
; CHECK: .byte	 0
; CHECK: .short 16
; CHECK: .short	7
; CHECK: .short	0
; CHECK: .long	16
; CHECK: .byte	3
; CHECK: .byte	 0
; CHECK: .short 16
; CHECK: .short	7
; CHECK: .short	0
; CHECK: .long	0

declare void @do_safepoint()

declare token @llvm.experimental.gc.statepoint.p0(i64, i32, ptr, i32, i32, ...)
declare ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token, i32, i32)
declare <2 x ptr addrspace(1)> @llvm.experimental.gc.relocate.v2p1(token, i32, i32)