• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: opt < %s -rewrite-statepoints-for-gc -S | FileCheck  %s
2; RUN: opt < %s -passes=rewrite-statepoints-for-gc -S | FileCheck  %s
3
4
5define i64 addrspace(1)* @test(<2 x i64 addrspace(1)*> %vec, i32 %idx) gc "statepoint-example" {
6; CHECK-LABEL: @test
7; CHECK: extractelement
8; CHECK: extractelement
9; CHECK: statepoint
10; CHECK: gc.relocate
11; CHECK-DAG: ; (%base_ee, %obj)
12; CHECK: gc.relocate
13; CHECK-DAG: ; (%base_ee, %base_ee)
14; Note that the second extractelement is actually redundant here.  A correct output would
15; be to reuse the existing obj as a base since it is actually a base pointer.
16entry:
17  %obj = extractelement <2 x i64 addrspace(1)*> %vec, i32 %idx
18  call void @do_safepoint() [ "deopt"() ]
19  ret i64 addrspace(1)* %obj
20}
21
22define i64 addrspace(1)* @test2(<2 x i64 addrspace(1)*>* %ptr, i1 %cnd, i32 %idx1, i32 %idx2) gc "statepoint-example" {
23; CHECK-LABEL: test2
24entry:
25  br i1 %cnd, label %taken, label %untaken
26
27taken:                                            ; preds = %entry
28  %obja = load <2 x i64 addrspace(1)*>, <2 x i64 addrspace(1)*>* %ptr
29  br label %merge
30
31untaken:                                          ; preds = %entry
32  %objb = load <2 x i64 addrspace(1)*>, <2 x i64 addrspace(1)*>* %ptr
33  br label %merge
34
35merge:                                            ; preds = %untaken, %taken
36  %vec = phi <2 x i64 addrspace(1)*> [ %obja, %taken ], [ %objb, %untaken ]
37  br i1 %cnd, label %taken2, label %untaken2
38
39taken2:                                           ; preds = %merge
40  %obj0 = extractelement <2 x i64 addrspace(1)*> %vec, i32 %idx1
41  br label %merge2
42
43untaken2:                                         ; preds = %merge
44  %obj1 = extractelement <2 x i64 addrspace(1)*> %vec, i32 %idx2
45  br label %merge2
46
47merge2:                                           ; preds = %untaken2, %taken2
48; CHECK-LABEL: merge2:
49; CHECK: %obj.base = phi i64 addrspace(1)*
50; CHECK: %obj = phi i64 addrspace(1)*
51; CHECK: statepoint
52; CHECK: gc.relocate
53; CHECK-DAG: ; (%obj.base, %obj)
54; CHECK: gc.relocate
55; CHECK-DAG: ; (%obj.base, %obj.base)
56  %obj = phi i64 addrspace(1)* [ %obj0, %taken2 ], [ %obj1, %untaken2 ]
57  call void @do_safepoint() [ "deopt"() ]
58  ret i64 addrspace(1)* %obj
59}
60
61define i64 addrspace(1)* @test3(i64 addrspace(1)* %ptr) gc "statepoint-example" {
62; CHECK-LABEL: test3
63; CHECK: insertelement
64; CHECK: extractelement
65; CHECK: statepoint
66; CHECK: gc.relocate
67; CHECK-DAG: (%obj.base, %obj)
68entry:
69  %vec = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %ptr, i32 0
70  %obj = extractelement <2 x i64 addrspace(1)*> %vec, i32 0
71  call void @do_safepoint() [ "deopt"() ]
72  ret i64 addrspace(1)* %obj
73}
74
75define i64 addrspace(1)* @test4(i64 addrspace(1)* %ptr) gc "statepoint-example" {
76; CHECK-LABEL: test4
77; CHECK: statepoint
78; CHECK: gc.relocate
79; CHECK-DAG: ; (%obj.base, %obj)
80; When we can optimize an extractelement from a known
81; index and avoid introducing new base pointer instructions
82entry:
83  %derived = getelementptr i64, i64 addrspace(1)* %ptr, i64 16
84  %veca = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %derived, i32 0
85  %vec = insertelement <2 x i64 addrspace(1)*> %veca, i64 addrspace(1)* %ptr, i32 1
86  %obj = extractelement <2 x i64 addrspace(1)*> %vec, i32 0
87  call void @do_safepoint() [ "deopt"() ]
88  ret i64 addrspace(1)* %obj
89}
90
91declare void @use(i64 addrspace(1)*) "gc-leaf-function"
92declare void @use_vec(<4 x i64 addrspace(1)*>) "gc-leaf-function"
93
94define void @test5(i1 %cnd, i64 addrspace(1)* %obj) gc "statepoint-example" {
95; CHECK-LABEL: @test5
96; CHECK: gc.relocate
97; CHECK-DAG: (%bdv.base, %bdv)
98; When we fundementally have to duplicate
99entry:
100  %gep = getelementptr i64, i64 addrspace(1)* %obj, i64 1
101  %vec = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %gep, i32 0
102  %bdv = extractelement <2 x i64 addrspace(1)*> %vec, i32 0
103  call void @do_safepoint() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
104  call void @use(i64 addrspace(1)* %bdv)
105  ret void
106}
107
108define void @test6(i1 %cnd, i64 addrspace(1)* %obj, i64 %idx) gc "statepoint-example" {
109; CHECK-LABEL: @test6
110; CHECK: %gep = getelementptr i64, i64 addrspace(1)* %obj, i64 1
111; CHECK: %vec.base = insertelement <2 x i64 addrspace(1)*> zeroinitializer, i64 addrspace(1)* %obj, i32 0, !is_base_value !0
112; CHECK: %vec = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %gep, i32 0
113; CHECK: %bdv.base = extractelement <2 x i64 addrspace(1)*> %vec.base, i64 %idx, !is_base_value !0
114; CHECK:  %bdv = extractelement <2 x i64 addrspace(1)*> %vec, i64 %idx
115; CHECK: gc.statepoint
116; CHECK: gc.relocate
117; CHECK-DAG: (%bdv.base, %bdv)
118; A more complicated example involving vector and scalar bases.
119; This is derived from a failing test case when we didn't have correct
120; insertelement handling.
121entry:
122  %gep = getelementptr i64, i64 addrspace(1)* %obj, i64 1
123  %vec = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %gep, i32 0
124  %bdv = extractelement <2 x i64 addrspace(1)*> %vec, i64 %idx
125  call void @do_safepoint() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
126  call void @use(i64 addrspace(1)* %bdv)
127  ret void
128}
129
130define i64 addrspace(1)* @test7(i1 %cnd, i64 addrspace(1)* %obj, i64 addrspace(1)* %obj2) gc "statepoint-example" {
131; CHECK-LABEL: @test7
132entry:
133  %vec = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %obj2, i32 0
134  br label %merge1
135
136merge1:                                           ; preds = %merge1, %entry
137; CHECK-LABEL: merge1:
138; CHECK: vec2.base
139; CHECK: vec2
140; CHECK: gep
141; CHECK: vec3.base
142; CHECK: vec3
143  %vec2 = phi <2 x i64 addrspace(1)*> [ %vec, %entry ], [ %vec3, %merge1 ]
144  %gep = getelementptr i64, i64 addrspace(1)* %obj2, i64 1
145  %vec3 = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %gep, i32 0
146  br i1 %cnd, label %merge1, label %next1
147
148next1:                                            ; preds = %merge1
149; CHECK-LABEL: next1:
150; CHECK: bdv.base =
151; CHECK: bdv =
152  %bdv = extractelement <2 x i64 addrspace(1)*> %vec2, i32 0
153  br label %merge
154
155merge:                                            ; preds = %merge, %next1
156; CHECK-LABEL: merge:
157; CHECK: %objb.base
158; CHECK: %objb
159; CHECK: gc.statepoint
160; CHECK: gc.relocate
161; CHECK-DAG: (%objb.base, %objb)
162  %objb = phi i64 addrspace(1)* [ %obj, %next1 ], [ %bdv, %merge ]
163  br i1 %cnd, label %merge, label %next
164
165next:                                             ; preds = %merge
166  call void @do_safepoint() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
167  ret i64 addrspace(1)* %objb
168}
169
170; identify base for shufflevector
171define void @test8(i64 addrspace(1)* %obj, i64 %idx) gc "statepoint-example" {
172; CHECK-LABEL: @test8
173; CHECK: %gep = getelementptr i64, i64 addrspace(1)* %obj, i64 1
174; CHECK: %gep2 = getelementptr i64, i64 addrspace(1)* %obj, i64 2
175; CHECK: %vec1.base = insertelement <4 x i64 addrspace(1)*> zeroinitializer, i64 addrspace(1)* %obj, i32 0, !is_base_value !0
176; CHECK: %vec1 = insertelement <4 x i64 addrspace(1)*> undef, i64 addrspace(1)* %gep, i32 0
177; CHECK: %vec2.base = insertelement <4 x i64 addrspace(1)*> zeroinitializer, i64 addrspace(1)* %obj, i32 2, !is_base_value !0
178; CHECK: %vec2 = insertelement <4 x i64 addrspace(1)*> undef, i64 addrspace(1)* %gep2, i32 2
179; CHECK: %vec.base = shufflevector <4 x i64 addrspace(1)*> %vec1.base, <4 x i64 addrspace(1)*> %vec2.base, <2 x i32> <i32 0, i32 2>, !is_base_value !0
180; CHECK: %vec = shufflevector <4 x i64 addrspace(1)*> %vec1, <4 x i64 addrspace(1)*> %vec2, <2 x i32> <i32 0, i32 2>
181; CHECK: %bdv.base = extractelement <2 x i64 addrspace(1)*> %vec.base, i64 %idx, !is_base_value !0
182; CHECK: %bdv = extractelement <2 x i64 addrspace(1)*> %vec, i64 %idx
183; CHECK: gc.statepoint
184; CHECK: gc.relocate
185; CHECK-DAG: (%bdv.base, %bdv)
186entry:
187  %gep = getelementptr i64, i64 addrspace(1)* %obj, i64 1
188  %gep2 = getelementptr i64, i64 addrspace(1)* %obj, i64 2
189  %vec1 = insertelement <4 x i64 addrspace(1)*> undef, i64 addrspace(1)* %gep, i32 0
190  %vec2 = insertelement <4 x i64 addrspace(1)*> undef, i64 addrspace(1)* %gep2, i32 2
191  %vec = shufflevector <4 x i64 addrspace(1)*> %vec1, <4 x i64 addrspace(1)*> %vec2, <2 x i32> <i32 0, i32 2>
192  %bdv = extractelement <2 x i64 addrspace(1)*> %vec, i64 %idx
193  call void @do_safepoint() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
194  call void @use(i64 addrspace(1)* %bdv)
195  ret void
196}
197
198; Since the same 'base' vector is used in the shuffle operands, we do not need
199; create a shufflevector base.
200define void @test9(<4 x i64 addrspace(1)*> %vec1, i64 %idx) gc "statepoint-example" {
201; CHECK-LABEL: @test9
202; CHECK: %vec = shufflevector <4 x i64 addrspace(1)*> %vec1, <4 x i64 addrspace(1)*> %vec1, <2 x i32> <i32 0, i32 2>
203; CHECK: %base_ee = extractelement <4 x i64 addrspace(1)*> %vec1, i64 %idx, !is_base_value !0
204; CHECK: %bdv = extractelement <2 x i64 addrspace(1)*> %vec, i64 %idx
205; CHECK: gc.statepoint
206; CHECK: gc.relocate
207; CHECK-DAG: (%base_ee, %bdv)
208entry:
209 ; shrinking vec1 into vec
210  %vec = shufflevector <4 x i64 addrspace(1)*> %vec1, <4 x i64 addrspace(1)*> %vec1, <2 x i32> <i32 0, i32 2>
211  %bdv = extractelement <2 x i64 addrspace(1)*> %vec, i64 %idx
212  call void @do_safepoint() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
213  call void @use(i64 addrspace(1)* %bdv)
214  ret void
215}
216
217; vector operand of shufflevector is a phi
218define i64 addrspace(1)* @test10(i1 %cnd, i64 addrspace(1)* %obj, i64 addrspace(1)* %obj2) gc "statepoint-example" {
219; CHECK-LABEL: @test10
220entry:
221  %vec1 = insertelement <4 x i64 addrspace(1)*> undef, i64 addrspace(1)* %obj, i32 0
222  br i1 %cnd, label %here, label %merge
223
224here:
225  %vec2 = insertelement <4 x i64 addrspace(1)*> undef, i64 addrspace(1)* %obj2, i32 2
226  br label %merge
227
228merge:                                           ; preds = %merge, %entry, %here
229; CHECK-LABEL: merge:
230; CHECK: %vec.base = phi <4 x i64 addrspace(1)*> [ %vec1.base, %entry ], [ %vec2.base, %here ], [ %vec3.base, %merge ], !is_base_value !0
231; CHECK: vec
232; CHECK: vec3.base = shufflevector <4 x i64 addrspace(1)*> %vec.base, <4 x i64 addrspace(1)*> %vec.base
233; CHECK: vec3
234; CHECK: bdv.base
235; CHECK: bdv
236  %vec = phi <4 x i64 addrspace(1)*> [ %vec1, %entry ], [ %vec2, %here], [ %vec3, %merge]
237  %vec3 = shufflevector <4 x i64 addrspace(1)*> %vec, <4 x i64 addrspace(1)*> %vec, <4 x i32> <i32 2, i32 0, i32 1, i32 3>
238  %bdv = extractelement <4 x i64 addrspace(1)*> %vec3, i32 0
239  br i1 %cnd, label %merge, label %next
240
241next:
242; CHECK-LABEL: next:
243; CHECK: gc.statepoint
244; CHECK: gc.relocate
245; CHECK-DAG: (%bdv.base, %bdv)
246  call void @do_safepoint() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
247  ret i64 addrspace(1)* %bdv
248}
249declare void @do_safepoint()
250
251define void @test11(<4 x i64 addrspace(1)*> %vec1) gc "statepoint-example" {
252; CHECK-LABEL: @test11(
253; CHECK: @llvm.experimental.gc.statepoint.p0f_isVoidf{{.*}}<4 x i64 addrspace(1)*> %vec1)
254; CHECK: %vec1.relocated = call coldcc <4 x i8 addrspace(1)*> @llvm.experimental.gc.relocate.v4p1i8
255; CHECK: %vec1.relocated.casted = bitcast <4 x i8 addrspace(1)*> %vec1.relocated to <4 x i64 addrspace(1)*>
256; CHECK: %vec2.remat = getelementptr i64, <4 x i64 addrspace(1)*> %vec1.relocated.casted, i32 1024
257; CHECK: call void @use_vec(<4 x i64 addrspace(1)*> %vec2.remat)
258entry:
259  %vec2 = getelementptr i64, <4 x i64 addrspace(1)*> %vec1, i32 1024
260  call void @do_safepoint() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
261  call void @use_vec(<4 x i64 addrspace(1) *> %vec2)
262  ret void
263}
264
265declare <4 x i64 addrspace(1)*> @def_vec() "gc-leaf-function"
266
267define void @test12(<4 x i64 addrspace(1)*> %vec1) gc "statepoint-example" {
268; CHECK-LABEL: @test12(
269; CHECK: @llvm.experimental.gc.statepoint.p0f_isVoidf{{.*}}<4 x i64 addrspace(1)*> %vec)
270; CHECK-NEXT: %vec.relocated = call coldcc <4 x i8 addrspace(1)*> @llvm.experimental.gc.relocate.v4p1i8(
271; CHECK-NEXT: %vec.relocated.casted = bitcast <4 x i8 addrspace(1)*> %vec.relocated to <4 x i64 addrspace(1)*>
272; CHECK-NEXT: call void @use_vec(<4 x i64 addrspace(1)*> %vec.relocated.casted)
273; CHECK-NEXT: ret void
274entry:
275  %vec = call <4 x i64 addrspace(1)*> @def_vec()
276  call void @do_safepoint() [ "deopt"() ]
277  call void @use_vec(<4 x i64 addrspace(1)*> %vec)
278  ret void
279}
280