1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -rewrite-statepoints-for-gc -S 2>&1 | FileCheck %s
3; RUN: opt < %s -passes=rewrite-statepoints-for-gc -S 2>&1 | FileCheck %s
4
5; A collection of tests for exercising the base inference logic in the
6; findBasePointers.  That is, the logic which proves a potentially derived
7; pointer is actually a base pointer itself.
8
9define i8 addrspace(1)* @test(i8 addrspace(1)* %a) gc "statepoint-example" {
10; CHECK-LABEL: @test(
11; CHECK-NEXT:    [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i8 addrspace(1)* [[A:%.*]]) ]
12; CHECK-NEXT:    [[A_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0)
13; CHECK-NEXT:    ret i8 addrspace(1)* [[A_RELOCATED]]
14;
15  call void @foo()
16  ret i8 addrspace(1)* %a
17}
18
19define i8 addrspace(1)* @test_select(i1 %c, i8 addrspace(1)* %a1, i8 addrspace(1)* %a2) gc "statepoint-example" {
20; CHECK-LABEL: @test_select(
21; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[C:%.*]], i8 addrspace(1)* [[A1:%.*]], i8 addrspace(1)* [[A2:%.*]]
22; CHECK-NEXT:    [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i8 addrspace(1)* [[SEL]]) ]
23; CHECK-NEXT:    [[SEL_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0)
24; CHECK-NEXT:    ret i8 addrspace(1)* [[SEL_RELOCATED]]
25;
26  %sel = select i1 %c, i8 addrspace(1)* %a1, i8 addrspace(1)* %a2
27  call void @foo()
28  ret i8 addrspace(1)* %sel
29}
30
31define i8 addrspace(1)* @test_phi1(i1 %c, i8 addrspace(1)* %a1, i8 addrspace(1)* %a2) gc "statepoint-example" {
32; CHECK-LABEL: @test_phi1(
33; CHECK-NEXT:  entry:
34; CHECK-NEXT:    br i1 [[C:%.*]], label [[TAKEN:%.*]], label [[UNTAKEN:%.*]]
35; CHECK:       taken:
36; CHECK-NEXT:    br label [[MERGE:%.*]]
37; CHECK:       untaken:
38; CHECK-NEXT:    br label [[MERGE]]
39; CHECK:       merge:
40; CHECK-NEXT:    [[PHI:%.*]] = phi i8 addrspace(1)* [ [[A1:%.*]], [[TAKEN]] ], [ [[A2:%.*]], [[UNTAKEN]] ]
41; CHECK-NEXT:    [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i8 addrspace(1)* [[PHI]]) ]
42; CHECK-NEXT:    [[PHI_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0)
43; CHECK-NEXT:    ret i8 addrspace(1)* [[PHI_RELOCATED]]
44;
45entry:
46  br i1 %c, label %taken, label %untaken
47taken:
48  br label %merge
49untaken:
50  br label %merge
51merge:
52  %phi = phi i8 addrspace(1)* [%a1, %taken], [%a2, %untaken]
53  call void @foo()
54  ret i8 addrspace(1)* %phi
55}
56
57define i8 addrspace(1)* @test_phi_lcssa(i1 %c, i8 addrspace(1)* %a1, i8 addrspace(1)* %a2) gc "statepoint-example" {
58; CHECK-LABEL: @test_phi_lcssa(
59; CHECK-NEXT:  entry:
60; CHECK-NEXT:    br label [[MERGE:%.*]]
61; CHECK:       merge:
62; CHECK-NEXT:    [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i8 addrspace(1)* [[A1:%.*]]) ]
63; CHECK-NEXT:    [[A1_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0)
64; CHECK-NEXT:    ret i8 addrspace(1)* [[A1_RELOCATED]]
65;
66entry:
67  br label %merge
68merge:
69  %phi = phi i8 addrspace(1)* [%a1, %entry]
70  call void @foo()
71  ret i8 addrspace(1)* %phi
72}
73
74
75define i8 addrspace(1)* @test_loop1(i1 %c, i8 addrspace(1)* %a1, i8 addrspace(1)* %a2) gc "statepoint-example" {
76; CHECK-LABEL: @test_loop1(
77; CHECK-NEXT:  entry:
78; CHECK-NEXT:    br label [[LOOP:%.*]]
79; CHECK:       loop:
80; CHECK-NEXT:    [[PHI:%.*]] = phi i8 addrspace(1)* [ [[A1:%.*]], [[ENTRY:%.*]] ], [ [[A2:%.*]], [[LOOP]] ]
81; CHECK-NEXT:    br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]]
82; CHECK:       exit:
83; CHECK-NEXT:    [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i8 addrspace(1)* [[PHI]]) ]
84; CHECK-NEXT:    [[PHI_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0)
85; CHECK-NEXT:    ret i8 addrspace(1)* [[PHI_RELOCATED]]
86;
87entry:
88  br label %loop
89loop:
90  %phi = phi i8 addrspace(1)* [%a1, %entry], [%a2, %loop]
91  br i1 %c, label %exit, label %loop
92exit:
93  %phi2 = phi i8 addrspace(1)* [%phi, %loop]
94  call void @foo()
95  ret i8 addrspace(1)* %phi2
96}
97
98define i8 addrspace(1)* @test_loop2(i1 %c, i8 addrspace(1)* %a1) gc "statepoint-example" {
99; CHECK-LABEL: @test_loop2(
100; CHECK-NEXT:  entry:
101; CHECK-NEXT:    br label [[LOOP:%.*]]
102; CHECK:       loop:
103; CHECK-NEXT:    [[PHI:%.*]] = phi i8 addrspace(1)* [ [[A1:%.*]], [[ENTRY:%.*]] ], [ [[O2:%.*]], [[LOOP]] ]
104; CHECK-NEXT:    [[ADDR:%.*]] = bitcast i8 addrspace(1)* [[PHI]] to i8 addrspace(1)* addrspace(1)*
105; CHECK-NEXT:    [[O2]] = load i8 addrspace(1)*, i8 addrspace(1)* addrspace(1)* [[ADDR]], align 8
106; CHECK-NEXT:    br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]]
107; CHECK:       exit:
108; CHECK-NEXT:    [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i8 addrspace(1)* [[PHI]]) ]
109; CHECK-NEXT:    [[PHI_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0)
110; CHECK-NEXT:    ret i8 addrspace(1)* [[PHI_RELOCATED]]
111;
112entry:
113  br label %loop
114loop:
115  %phi = phi i8 addrspace(1)* [%a1, %entry], [%o2, %loop]
116  %addr = bitcast i8 addrspace(1)* %phi to i8 addrspace(1)* addrspace(1)*
117  %o2 = load i8 addrspace(1)*, i8 addrspace(1)* addrspace(1)* %addr
118  br i1 %c, label %exit, label %loop
119exit:
120  %phi2 = phi i8 addrspace(1)* [%phi, %loop]
121  call void @foo()
122  ret i8 addrspace(1)* %phi2
123}
124
125; %phi1 and phi2 are not base pointers, but they do have a single
126; base pointer which is %a1
127define i8 addrspace(1)* @test_loop3(i1 %c, i8 addrspace(1)* %a1) gc "statepoint-example" {
128; CHECK-LABEL: @test_loop3(
129; CHECK-NEXT:  entry:
130; CHECK-NEXT:    br label [[LOOP:%.*]]
131; CHECK:       loop:
132; CHECK-NEXT:    [[PHI:%.*]] = phi i8 addrspace(1)* [ [[A1:%.*]], [[ENTRY:%.*]] ], [ [[GEP:%.*]], [[LOOP]] ]
133; CHECK-NEXT:    [[GEP]] = getelementptr i8, i8 addrspace(1)* [[PHI]], i64 16
134; CHECK-NEXT:    br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]]
135; CHECK:       exit:
136; CHECK-NEXT:    [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i8 addrspace(1)* [[PHI]], i8 addrspace(1)* [[A1]]) ]
137; CHECK-NEXT:    [[PHI_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 0)
138; CHECK-NEXT:    [[A1_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 1)
139; CHECK-NEXT:    ret i8 addrspace(1)* [[PHI_RELOCATED]]
140;
141entry:
142  br label %loop
143loop:
144  %phi = phi i8 addrspace(1)* [%a1, %entry], [%gep, %loop]
145  %gep = getelementptr i8, i8 addrspace(1)* %phi, i64 16
146  br i1 %c, label %exit, label %loop
147exit:
148  %phi2 = phi i8 addrspace(1)* [%phi, %loop]
149  call void @foo()
150  ret i8 addrspace(1)* %phi2
151}
152
153define <2 x i8 addrspace(1)*> @test_vec_passthrough(<2 x i8 addrspace(1)*> %a) gc "statepoint-example" {
154; CHECK-LABEL: @test_vec_passthrough(
155; CHECK-NEXT:    [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(<2 x i8 addrspace(1)*> [[A:%.*]]) ]
156; CHECK-NEXT:    [[A_RELOCATED:%.*]] = call coldcc <2 x i8 addrspace(1)*> @llvm.experimental.gc.relocate.v2p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0)
157; CHECK-NEXT:    ret <2 x i8 addrspace(1)*> [[A_RELOCATED]]
158;
159  call void @foo()
160  ret <2 x i8 addrspace(1)*> %a
161}
162
163
164define <2 x i8 addrspace(1)*> @test_insert(i8 addrspace(1)* %a) gc "statepoint-example" {
165; CHECK-LABEL: @test_insert(
166; CHECK-NEXT:    [[VEC:%.*]] = insertelement <2 x i8 addrspace(1)*> zeroinitializer, i8 addrspace(1)* [[A:%.*]], i64 0
167; CHECK-NEXT:    [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(<2 x i8 addrspace(1)*> [[VEC]]) ]
168; CHECK-NEXT:    [[VEC_RELOCATED:%.*]] = call coldcc <2 x i8 addrspace(1)*> @llvm.experimental.gc.relocate.v2p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0)
169; CHECK-NEXT:    ret <2 x i8 addrspace(1)*> [[VEC_RELOCATED]]
170;
171  %vec = insertelement <2 x i8 addrspace(1)*> zeroinitializer, i8 addrspace(1)* %a, i64 0
172  call void @foo()
173  ret <2 x i8 addrspace(1)*> %vec
174}
175
176define i8 addrspace(1)* @test_extract(<2 x i8 addrspace(1)*> %a) gc "statepoint-example" {
177; CHECK-LABEL: @test_extract(
178; CHECK-NEXT:    [[EE:%.*]] = extractelement <2 x i8 addrspace(1)*> [[A:%.*]], i64 0
179; CHECK-NEXT:    [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i8 addrspace(1)* [[EE]]) ]
180; CHECK-NEXT:    [[EE_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0)
181; CHECK-NEXT:    ret i8 addrspace(1)* [[EE_RELOCATED]]
182;
183  %ee = extractelement <2 x i8 addrspace(1)*> %a, i64 0
184  call void @foo()
185  ret i8 addrspace(1)* %ee
186}
187
188define <2 x i8 addrspace(1)*> @test_shuffle(<2 x i8 addrspace(1)*> %a1) gc "statepoint-example" {
189; CHECK-LABEL: @test_shuffle(
190; CHECK-NEXT:    [[RES:%.*]] = shufflevector <2 x i8 addrspace(1)*> [[A1:%.*]], <2 x i8 addrspace(1)*> [[A1]], <2 x i32> zeroinitializer
191; CHECK-NEXT:    [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(<2 x i8 addrspace(1)*> [[RES]]) ]
192; CHECK-NEXT:    [[RES_RELOCATED:%.*]] = call coldcc <2 x i8 addrspace(1)*> @llvm.experimental.gc.relocate.v2p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0)
193; CHECK-NEXT:    ret <2 x i8 addrspace(1)*> [[RES_RELOCATED]]
194;
195  %res = shufflevector <2 x i8 addrspace(1)*> %a1, <2 x i8 addrspace(1)*> %a1, <2 x i32> zeroinitializer
196  call void @foo()
197  ret <2 x i8 addrspace(1)*> %res
198}
199
200define <2 x i8 addrspace(1)*> @test_shuffle2(<2 x i8 addrspace(1)*> %a1, <2 x i8 addrspace(1)*> %a2) gc "statepoint-example" {
201; CHECK-LABEL: @test_shuffle2(
202; CHECK-NEXT:    [[RES:%.*]] = shufflevector <2 x i8 addrspace(1)*> [[A1:%.*]], <2 x i8 addrspace(1)*> [[A2:%.*]], <2 x i32> zeroinitializer
203; CHECK-NEXT:    [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(<2 x i8 addrspace(1)*> [[RES]]) ]
204; CHECK-NEXT:    [[RES_RELOCATED:%.*]] = call coldcc <2 x i8 addrspace(1)*> @llvm.experimental.gc.relocate.v2p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0)
205; CHECK-NEXT:    ret <2 x i8 addrspace(1)*> [[RES_RELOCATED]]
206;
207  %res = shufflevector <2 x i8 addrspace(1)*> %a1, <2 x i8 addrspace(1)*> %a2, <2 x i32> zeroinitializer
208  call void @foo()
209  ret <2 x i8 addrspace(1)*> %res
210}
211
212define <4 x i8 addrspace(1)*> @test_shuffle_concat(<2 x i8 addrspace(1)*> %a1, <2 x i8 addrspace(1)*> %a2) gc "statepoint-example" {
213; CHECK-LABEL: @test_shuffle_concat(
214; CHECK-NEXT:    [[RES:%.*]] = shufflevector <2 x i8 addrspace(1)*> [[A1:%.*]], <2 x i8 addrspace(1)*> [[A2:%.*]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
215; CHECK-NEXT:    [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(<4 x i8 addrspace(1)*> [[RES]]) ]
216; CHECK-NEXT:    [[RES_RELOCATED:%.*]] = call coldcc <4 x i8 addrspace(1)*> @llvm.experimental.gc.relocate.v4p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0)
217; CHECK-NEXT:    ret <4 x i8 addrspace(1)*> [[RES_RELOCATED]]
218;
219  %res = shufflevector <2 x i8 addrspace(1)*> %a1, <2 x i8 addrspace(1)*> %a2, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
220  call void @foo()
221  ret <4 x i8 addrspace(1)*> %res
222}
223
224; TODO: Special case worth handling - we interpret the shuffle as if we need
225; to select the base pointers from either input when the mask is known.
226define <2 x i8 addrspace(1)*> @test_shuffle_broadcast(i8 addrspace(1)* %a) gc "statepoint-example" {
227; CHECK-LABEL: @test_shuffle_broadcast(
228; CHECK-NEXT:  entry:
229; CHECK-NEXT:    [[IE:%.*]] = insertelement <2 x i8 addrspace(1)*> zeroinitializer, i8 addrspace(1)* [[A:%.*]], i64 0
230; CHECK-NEXT:    [[BROADCAST:%.*]] = shufflevector <2 x i8 addrspace(1)*> [[IE]], <2 x i8 addrspace(1)*> undef, <2 x i32> zeroinitializer
231; CHECK-NEXT:    [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(<2 x i8 addrspace(1)*> [[BROADCAST]]) ]
232; CHECK-NEXT:    [[BROADCAST_RELOCATED:%.*]] = call coldcc <2 x i8 addrspace(1)*> @llvm.experimental.gc.relocate.v2p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0)
233; CHECK-NEXT:    ret <2 x i8 addrspace(1)*> [[BROADCAST_RELOCATED]]
234;
235entry:
236  %ie = insertelement <2 x i8 addrspace(1)*> zeroinitializer, i8 addrspace(1)* %a, i64 0
237  %broadcast = shufflevector <2 x i8 addrspace(1)*> %ie, <2 x i8 addrspace(1)*> undef, <2 x i32> zeroinitializer
238  call void @foo()
239  ret <2 x i8 addrspace(1)*> %broadcast
240}
241
242; Show a case where only a portion of the sub-graph propagates base pointers.
243define i8 @test_subgraph(i1 %c, i8 addrspace(1)* %a1, i8 addrspace(1)* %a2) gc "statepoint-example" {
244; CHECK-LABEL: @test_subgraph(
245; CHECK-NEXT:  entry:
246; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[C:%.*]], i8 addrspace(1)* [[A1:%.*]], i8 addrspace(1)* [[A2:%.*]]
247; CHECK-NEXT:    br i1 [[C]], label [[TAKEN:%.*]], label [[MERGE:%.*]]
248; CHECK:       taken:
249; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i8, i8 addrspace(1)* [[SEL]], i64 8
250; CHECK-NEXT:    br label [[MERGE]]
251; CHECK:       merge:
252; CHECK-NEXT:    [[PHI:%.*]] = phi i8 addrspace(1)* [ [[GEP]], [[TAKEN]] ], [ [[SEL]], [[ENTRY:%.*]] ]
253; CHECK-NEXT:    [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i8 addrspace(1)* [[PHI]], i8 addrspace(1)* [[SEL]]) ]
254; CHECK-NEXT:    [[PHI_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 0)
255; CHECK-NEXT:    [[SEL_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 1)
256; CHECK-NEXT:    [[RES:%.*]] = load i8, i8 addrspace(1)* [[PHI_RELOCATED]], align 1
257; CHECK-NEXT:    ret i8 [[RES]]
258;
259entry:
260  %sel = select i1 %c, i8 addrspace(1)* %a1, i8 addrspace(1)* %a2
261  br i1 %c, label %taken, label %merge
262taken:
263  %gep = getelementptr i8, i8 addrspace(1)* %sel, i64 8
264  br label %merge
265merge:
266  %phi = phi i8 addrspace(1)* [%gep, %taken], [%sel, %entry]
267  call void @foo()
268  %res = load i8, i8 addrspace(1)* %phi
269  ret i8 %res
270}
271
272; An example of a non-trivial subgraph computing base pointers.
273define i8 @test_subgraph2(i1 %c, i8 addrspace(1)* %a1, i8 addrspace(1)* %a2) gc "statepoint-example" {
274; CHECK-LABEL: @test_subgraph2(
275; CHECK-NEXT:  entry:
276; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[C:%.*]], i8 addrspace(1)* [[A1:%.*]], i8 addrspace(1)* [[A2:%.*]]
277; CHECK-NEXT:    [[IE:%.*]] = insertelement <2 x i8 addrspace(1)*> zeroinitializer, i8 addrspace(1)* [[SEL]], i64 0
278; CHECK-NEXT:    [[BROADCAST:%.*]] = shufflevector <2 x i8 addrspace(1)*> [[IE]], <2 x i8 addrspace(1)*> [[IE]], <2 x i32> zeroinitializer
279; CHECK-NEXT:    [[EE:%.*]] = extractelement <2 x i8 addrspace(1)*> [[BROADCAST]], i32 1
280; CHECK-NEXT:    [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i8 addrspace(1)* [[EE]]) ]
281; CHECK-NEXT:    [[EE_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0)
282; CHECK-NEXT:    [[RES:%.*]] = load i8, i8 addrspace(1)* [[EE_RELOCATED]], align 1
283; CHECK-NEXT:    ret i8 [[RES]]
284;
285entry:
286  %sel = select i1 %c, i8 addrspace(1)* %a1, i8 addrspace(1)* %a2
287  %ie = insertelement <2 x i8 addrspace(1)*> zeroinitializer, i8 addrspace(1)* %sel, i64 0
288  %broadcast = shufflevector <2 x i8 addrspace(1)*> %ie, <2 x i8 addrspace(1)*> %ie, <2 x i32> zeroinitializer
289  %ee = extractelement <2 x i8 addrspace(1)*> %broadcast, i32 1
290  call void @foo()
291  %res = load i8, i8 addrspace(1)* %ee
292  ret i8 %res
293}
294
295
296declare void @foo()
297