1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=instcombine,verify -S < %s | FileCheck %s --check-prefixes=ALL,INSTCOMBINE
3
4; Make sure GVN won't undo the transformation:
5; RUN: opt -passes=instcombine,gvn -S < %s | FileCheck %s --check-prefixes=ALL,INSTCOMBINEGVN
6
7declare i8* @get_ptr.i8()
8declare i32* @get_ptr.i32()
9declare void @foo.i8(i8*)
10declare void @foo.i32(i32*)
11
12define i32 @test_gep_and_bitcast(i1 %cond, i1 %cond2) {
13; ALL-LABEL: @test_gep_and_bitcast(
14; ALL-NEXT:  entry:
15; ALL-NEXT:    [[OBJ:%.*]] = call i8* @get_ptr.i8()
16; ALL-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
17; ALL:       bb1:
18; ALL-NEXT:    br label [[EXIT:%.*]]
19; ALL:       bb2:
20; ALL-NEXT:    br label [[EXIT]]
21; ALL:       exit:
22; ALL-NEXT:    [[PTR_TYPED_IN:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16
23; ALL-NEXT:    [[PTR_TYPED:%.*]] = bitcast i8* [[PTR_TYPED_IN]] to i32*
24; ALL-NEXT:    [[RES_PHI:%.*]] = load i32, i32* [[PTR_TYPED]], align 4
25; ALL-NEXT:    store i32 1, i32* [[PTR_TYPED]], align 4
26; ALL-NEXT:    [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
27; ALL-NEXT:    ret i32 [[RES]]
28;
29entry:
30  %obj = call i8* @get_ptr.i8()
31  br i1 %cond, label %bb1, label %bb2
32
33bb1:
34  %ptr1 = getelementptr inbounds i8, i8* %obj, i64 16
35  %ptr1.typed = bitcast i8* %ptr1 to i32*
36  %res1 = load i32, i32* %ptr1.typed
37  br label %exit
38
39bb2:
40  %ptr2 = getelementptr inbounds i8, i8* %obj, i64 16
41  %ptr2.typed = bitcast i8* %ptr2 to i32*
42  %res2 = load i32, i32* %ptr2.typed
43  br label %exit
44
45exit:
46  %ptr.typed = phi i32* [ %ptr1.typed, %bb1 ], [ %ptr2.typed, %bb2 ]
47  %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ]
48  store i32 1, i32* %ptr.typed
49  %res.load = load i32, i32* %ptr.typed
50  %res = select i1 %cond2, i32 %res.phi, i32 %res.load
51  ret i32 %res
52}
53
54define i32 @test_gep_and_bitcast_arg(i8* %obj, i1 %cond, i1 %cond2) {
55; ALL-LABEL: @test_gep_and_bitcast_arg(
56; ALL-NEXT:  entry:
57; ALL-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
58; ALL:       bb1:
59; ALL-NEXT:    br label [[EXIT:%.*]]
60; ALL:       bb2:
61; ALL-NEXT:    br label [[EXIT]]
62; ALL:       exit:
63; ALL-NEXT:    [[PTR_TYPED_IN:%.*]] = getelementptr inbounds i8, i8* [[OBJ:%.*]], i64 16
64; ALL-NEXT:    [[PTR_TYPED:%.*]] = bitcast i8* [[PTR_TYPED_IN]] to i32*
65; ALL-NEXT:    [[RES_PHI:%.*]] = load i32, i32* [[PTR_TYPED]], align 4
66; ALL-NEXT:    store i32 1, i32* [[PTR_TYPED]], align 4
67; ALL-NEXT:    [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
68; ALL-NEXT:    ret i32 [[RES]]
69;
70entry:
71  br i1 %cond, label %bb1, label %bb2
72
73bb1:
74  %ptr1 = getelementptr inbounds i8, i8* %obj, i64 16
75  %ptr1.typed = bitcast i8* %ptr1 to i32*
76  %res1 = load i32, i32* %ptr1.typed
77  br label %exit
78
79bb2:
80  %ptr2 = getelementptr inbounds i8, i8* %obj, i64 16
81  %ptr2.typed = bitcast i8* %ptr2 to i32*
82  %res2 = load i32, i32* %ptr2.typed
83  br label %exit
84
85exit:
86  %ptr.typed = phi i32* [ %ptr1.typed, %bb1 ], [ %ptr2.typed, %bb2 ]
87  %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ]
88  store i32 1, i32* %ptr.typed
89  %res.load = load i32, i32* %ptr.typed
90  %res = select i1 %cond2, i32 %res.phi, i32 %res.load
91  ret i32 %res
92}
93
94define i32 @test_gep_and_bitcast_phi(i1 %cond, i1 %cond2, i1 %cond3) {
95; ALL-LABEL: @test_gep_and_bitcast_phi(
96; ALL-NEXT:  entry:
97; ALL-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
98; ALL:       bb1:
99; ALL-NEXT:    [[OBJ1:%.*]] = call i8* @get_ptr.i8()
100; ALL-NEXT:    br label [[MERGE:%.*]]
101; ALL:       bb2:
102; ALL-NEXT:    [[OBJ2_TYPED:%.*]] = call i32* @get_ptr.i32()
103; ALL-NEXT:    [[OBJ2:%.*]] = bitcast i32* [[OBJ2_TYPED]] to i8*
104; ALL-NEXT:    br label [[MERGE]]
105; ALL:       merge:
106; ALL-NEXT:    [[OBJ:%.*]] = phi i8* [ [[OBJ1]], [[BB1]] ], [ [[OBJ2]], [[BB2]] ]
107; ALL-NEXT:    [[ANOTHER_PHI:%.*]] = phi i8* [ [[OBJ1]], [[BB1]] ], [ null, [[BB2]] ]
108; ALL-NEXT:    call void @foo.i8(i8* [[ANOTHER_PHI]])
109; ALL-NEXT:    br i1 [[COND2:%.*]], label [[BB3:%.*]], label [[BB4:%.*]]
110; ALL:       bb3:
111; ALL-NEXT:    br label [[EXIT:%.*]]
112; ALL:       bb4:
113; ALL-NEXT:    br label [[EXIT]]
114; ALL:       exit:
115; ALL-NEXT:    [[PTR_TYPED_IN:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16
116; ALL-NEXT:    [[PTR_TYPED:%.*]] = bitcast i8* [[PTR_TYPED_IN]] to i32*
117; ALL-NEXT:    [[RES_PHI:%.*]] = load i32, i32* [[PTR_TYPED]], align 4
118; ALL-NEXT:    store i32 1, i32* [[PTR_TYPED]], align 4
119; ALL-NEXT:    [[RES:%.*]] = select i1 [[COND3:%.*]], i32 [[RES_PHI]], i32 1
120; ALL-NEXT:    ret i32 [[RES]]
121;
122entry:
123  br i1 %cond, label %bb1, label %bb2
124
125bb1:
126  %obj1 = call i8* @get_ptr.i8()
127  br label %merge
128
129bb2:
130  %obj2.typed = call i32* @get_ptr.i32()
131  %obj2 = bitcast i32* %obj2.typed to i8*
132  br label %merge
133
134merge:
135  %obj = phi i8* [ %obj1, %bb1 ], [ %obj2, %bb2 ]
136  %another_phi = phi i8* [ %obj1, %bb1 ], [ null, %bb2 ]
137  call void @foo.i8(i8* %another_phi)
138  br i1 %cond2, label %bb3, label %bb4
139
140bb3:
141  %ptr1 = getelementptr inbounds i8, i8* %obj, i64 16
142  %ptr1.typed = bitcast i8* %ptr1 to i32*
143  %res1 = load i32, i32* %ptr1.typed
144  br label %exit
145
146bb4:
147  %ptr2 = getelementptr inbounds i8, i8* %obj, i64 16
148  %ptr2.typed = bitcast i8* %ptr2 to i32*
149  %res2 = load i32, i32* %ptr2.typed
150  br label %exit
151
152exit:
153  %ptr.typed = phi i32* [ %ptr1.typed, %bb3 ], [ %ptr2.typed, %bb4 ]
154  %res.phi = phi i32 [ %res1, %bb3 ], [ %res2, %bb4 ]
155  store i32 1, i32* %ptr.typed
156  %res.load = load i32, i32* %ptr.typed
157  %res = select i1 %cond3, i32 %res.phi, i32 %res.load
158  ret i32 %res
159}
160
161define i32 @test_gep_i32ptr(i1 %cond, i1 %cond2) {
162; ALL-LABEL: @test_gep_i32ptr(
163; ALL-NEXT:  entry:
164; ALL-NEXT:    [[OBJ:%.*]] = call i32* @get_ptr.i32()
165; ALL-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
166; ALL:       bb1:
167; ALL-NEXT:    br label [[EXIT:%.*]]
168; ALL:       bb2:
169; ALL-NEXT:    br label [[EXIT]]
170; ALL:       exit:
171; ALL-NEXT:    [[PTR_TYPED:%.*]] = getelementptr inbounds i32, i32* [[OBJ]], i64 16
172; ALL-NEXT:    [[RES_PHI:%.*]] = load i32, i32* [[PTR_TYPED]], align 4
173; ALL-NEXT:    store i32 1, i32* [[PTR_TYPED]], align 4
174; ALL-NEXT:    [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
175; ALL-NEXT:    ret i32 [[RES]]
176;
177entry:
178  %obj = call i32* @get_ptr.i32()
179  br i1 %cond, label %bb1, label %bb2
180
181bb1:
182  %ptr1.typed = getelementptr inbounds i32, i32* %obj, i64 16
183  %res1 = load i32, i32* %ptr1.typed
184  br label %exit
185
186bb2:
187  %ptr2.typed = getelementptr inbounds i32, i32* %obj, i64 16
188  %res2 = load i32, i32* %ptr2.typed
189  br label %exit
190
191exit:
192  %ptr.typed = phi i32* [ %ptr1.typed, %bb1 ], [ %ptr2.typed, %bb2 ]
193  %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ]
194  store i32 1, i32* %ptr.typed
195  %res.load = load i32, i32* %ptr.typed
196  %res = select i1 %cond2, i32 %res.phi, i32 %res.load
197  ret i32 %res
198}
199
200define i32 @test_gep_and_bitcast_gep_base_ptr(i1 %cond, i1 %cond2) {
201; ALL-LABEL: @test_gep_and_bitcast_gep_base_ptr(
202; ALL-NEXT:  entry:
203; ALL-NEXT:    [[OBJ0:%.*]] = call i8* @get_ptr.i8()
204; ALL-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
205; ALL:       bb1:
206; ALL-NEXT:    br label [[EXIT:%.*]]
207; ALL:       bb2:
208; ALL-NEXT:    br label [[EXIT]]
209; ALL:       exit:
210; ALL-NEXT:    [[PTR_TYPED_IN:%.*]] = getelementptr inbounds i8, i8* [[OBJ0]], i64 32
211; ALL-NEXT:    [[PTR_TYPED:%.*]] = bitcast i8* [[PTR_TYPED_IN]] to i32*
212; ALL-NEXT:    [[RES_PHI:%.*]] = load i32, i32* [[PTR_TYPED]], align 4
213; ALL-NEXT:    store i32 1, i32* [[PTR_TYPED]], align 4
214; ALL-NEXT:    [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
215; ALL-NEXT:    ret i32 [[RES]]
216;
217entry:
218  %obj0 = call i8* @get_ptr.i8()
219  %obj = getelementptr inbounds i8, i8* %obj0, i64 16
220  br i1 %cond, label %bb1, label %bb2
221
222bb1:
223  %ptr1 = getelementptr inbounds i8, i8* %obj, i64 16
224  %ptr1.typed = bitcast i8* %ptr1 to i32*
225  %res1 = load i32, i32* %ptr1.typed
226  br label %exit
227
228bb2:
229  %ptr2 = getelementptr inbounds i8, i8* %obj, i64 16
230  %ptr2.typed = bitcast i8* %ptr2 to i32*
231  %res2 = load i32, i32* %ptr2.typed
232  br label %exit
233
234exit:
235  %ptr.typed = phi i32* [ %ptr1.typed, %bb1 ], [ %ptr2.typed, %bb2 ]
236  %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ]
237  store i32 1, i32* %ptr.typed
238  %res.load = load i32, i32* %ptr.typed
239  %res = select i1 %cond2, i32 %res.phi, i32 %res.load
240  ret i32 %res
241}
242
243define i32 @test_gep_and_bitcast_same_bb(i1 %cond, i1 %cond2) {
244; ALL-LABEL: @test_gep_and_bitcast_same_bb(
245; ALL-NEXT:  entry:
246; ALL-NEXT:    [[OBJ:%.*]] = call i8* @get_ptr.i8()
247; ALL-NEXT:    br i1 [[COND:%.*]], label [[EXIT:%.*]], label [[BB2:%.*]]
248; ALL:       bb2:
249; ALL-NEXT:    br label [[EXIT]]
250; ALL:       exit:
251; ALL-NEXT:    [[PTR_TYPED_IN:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16
252; ALL-NEXT:    [[PTR_TYPED:%.*]] = bitcast i8* [[PTR_TYPED_IN]] to i32*
253; ALL-NEXT:    [[RES_PHI:%.*]] = load i32, i32* [[PTR_TYPED]], align 4
254; ALL-NEXT:    store i32 1, i32* [[PTR_TYPED]], align 4
255; ALL-NEXT:    [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
256; ALL-NEXT:    ret i32 [[RES]]
257;
258entry:
259  %obj = call i8* @get_ptr.i8()
260  %ptr1 = getelementptr inbounds i8, i8* %obj, i64 16
261  %ptr1.typed = bitcast i8* %ptr1 to i32*
262  %res1 = load i32, i32* %ptr1.typed
263  br i1 %cond, label %exit, label %bb2
264
265bb2:
266  %ptr2 = getelementptr inbounds i8, i8* %obj, i64 16
267  %ptr2.typed = bitcast i8* %ptr2 to i32*
268  %res2 = load i32, i32* %ptr2.typed
269  br label %exit
270
271exit:
272  %ptr.typed = phi i32* [ %ptr1.typed, %entry ], [ %ptr2.typed, %bb2 ]
273  %res.phi = phi i32 [ %res1, %entry ], [ %res2, %bb2 ]
274  store i32 1, i32* %ptr.typed
275  %res.load = load i32, i32* %ptr.typed
276  %res = select i1 %cond2, i32 %res.phi, i32 %res.load
277  ret i32 %res
278}
279
280define i32 @test_gep_and_bitcast_same_bb_and_extra_use(i1 %cond, i1 %cond2) {
281; INSTCOMBINE-LABEL: @test_gep_and_bitcast_same_bb_and_extra_use(
282; INSTCOMBINE-NEXT:  entry:
283; INSTCOMBINE-NEXT:    [[OBJ:%.*]] = call i8* @get_ptr.i8()
284; INSTCOMBINE-NEXT:    [[PTR1:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16
285; INSTCOMBINE-NEXT:    [[PTR1_TYPED:%.*]] = bitcast i8* [[PTR1]] to i32*
286; INSTCOMBINE-NEXT:    call void @foo.i32(i32* nonnull [[PTR1_TYPED]])
287; INSTCOMBINE-NEXT:    br i1 [[COND:%.*]], label [[EXIT:%.*]], label [[BB2:%.*]]
288; INSTCOMBINE:       bb2:
289; INSTCOMBINE-NEXT:    [[PTR2:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16
290; INSTCOMBINE-NEXT:    [[PTR2_TYPED:%.*]] = bitcast i8* [[PTR2]] to i32*
291; INSTCOMBINE-NEXT:    br label [[EXIT]]
292; INSTCOMBINE:       exit:
293; INSTCOMBINE-NEXT:    [[PTR_TYPED:%.*]] = phi i32* [ [[PTR1_TYPED]], [[ENTRY:%.*]] ], [ [[PTR2_TYPED]], [[BB2]] ]
294; INSTCOMBINE-NEXT:    [[RES_PHI:%.*]] = load i32, i32* [[PTR_TYPED]], align 4
295; INSTCOMBINE-NEXT:    store i32 1, i32* [[PTR_TYPED]], align 4
296; INSTCOMBINE-NEXT:    [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
297; INSTCOMBINE-NEXT:    ret i32 [[RES]]
298;
299; INSTCOMBINEGVN-LABEL: @test_gep_and_bitcast_same_bb_and_extra_use(
300; INSTCOMBINEGVN-NEXT:  entry:
301; INSTCOMBINEGVN-NEXT:    [[OBJ:%.*]] = call i8* @get_ptr.i8()
302; INSTCOMBINEGVN-NEXT:    [[PTR1:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16
303; INSTCOMBINEGVN-NEXT:    [[PTR1_TYPED:%.*]] = bitcast i8* [[PTR1]] to i32*
304; INSTCOMBINEGVN-NEXT:    call void @foo.i32(i32* nonnull [[PTR1_TYPED]])
305; INSTCOMBINEGVN-NEXT:    br i1 [[COND:%.*]], label [[EXIT:%.*]], label [[BB2:%.*]]
306; INSTCOMBINEGVN:       bb2:
307; INSTCOMBINEGVN-NEXT:    br label [[EXIT]]
308; INSTCOMBINEGVN:       exit:
309; INSTCOMBINEGVN-NEXT:    [[RES_PHI:%.*]] = load i32, i32* [[PTR1_TYPED]], align 4
310; INSTCOMBINEGVN-NEXT:    store i32 1, i32* [[PTR1_TYPED]], align 4
311; INSTCOMBINEGVN-NEXT:    [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
312; INSTCOMBINEGVN-NEXT:    ret i32 [[RES]]
313;
314entry:
315  %obj = call i8* @get_ptr.i8()
316  %ptr1 = getelementptr inbounds i8, i8* %obj, i64 16
317  %ptr1.typed = bitcast i8* %ptr1 to i32*
318  call void @foo.i32(i32* %ptr1.typed)
319  %res1 = load i32, i32* %ptr1.typed
320  br i1 %cond, label %exit, label %bb2
321
322bb2:
323  %ptr2 = getelementptr inbounds i8, i8* %obj, i64 16
324  %ptr2.typed = bitcast i8* %ptr2 to i32*
325  %res2 = load i32, i32* %ptr2.typed
326  br label %exit
327
328exit:
329  %ptr.typed = phi i32* [ %ptr1.typed, %entry ], [ %ptr2.typed, %bb2 ]
330  %res.phi = phi i32 [ %res1, %entry ], [ %res2, %bb2 ]
331  store i32 1, i32* %ptr.typed
332  %res.load = load i32, i32* %ptr.typed
333  %res = select i1 %cond2, i32 %res.phi, i32 %res.load
334  ret i32 %res
335}
336
337define i8 @test_gep(i1 %cond, i1 %cond2) {
338; ALL-LABEL: @test_gep(
339; ALL-NEXT:  entry:
340; ALL-NEXT:    [[OBJ:%.*]] = call i8* @get_ptr.i8()
341; ALL-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
342; ALL:       bb1:
343; ALL-NEXT:    br label [[EXIT:%.*]]
344; ALL:       bb2:
345; ALL-NEXT:    br label [[EXIT]]
346; ALL:       exit:
347; ALL-NEXT:    [[PTR_TYPED:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16
348; ALL-NEXT:    [[RES_PHI:%.*]] = load i8, i8* [[PTR_TYPED]], align 1
349; ALL-NEXT:    store i8 1, i8* [[PTR_TYPED]], align 1
350; ALL-NEXT:    [[RES:%.*]] = select i1 [[COND2:%.*]], i8 [[RES_PHI]], i8 1
351; ALL-NEXT:    ret i8 [[RES]]
352;
353entry:
354  %obj = call i8* @get_ptr.i8()
355  br i1 %cond, label %bb1, label %bb2
356
357bb1:
358  %ptr1 = getelementptr inbounds i8, i8* %obj, i64 16
359  %res1 = load i8, i8* %ptr1
360  br label %exit
361
362bb2:
363  %ptr2 = getelementptr inbounds i8, i8* %obj, i64 16
364  %res2 = load i8, i8* %ptr2
365  br label %exit
366
367exit:
368  %ptr.typed = phi i8* [ %ptr1, %bb1 ], [ %ptr2, %bb2 ]
369  %res.phi = phi i8 [ %res1, %bb1 ], [ %res2, %bb2 ]
370  store i8 1, i8* %ptr.typed
371  %res.load = load i8, i8* %ptr.typed
372  %res = select i1 %cond2, i8 %res.phi, i8 %res.load
373  ret i8 %res
374}
375
376define i32 @test_extra_uses(i1 %cond, i1 %cond2) {
377; ALL-LABEL: @test_extra_uses(
378; ALL-NEXT:  entry:
379; ALL-NEXT:    [[OBJ:%.*]] = call i8* @get_ptr.i8()
380; ALL-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
381; ALL:       bb1:
382; ALL-NEXT:    [[PTR1:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16
383; ALL-NEXT:    [[PTR1_TYPED:%.*]] = bitcast i8* [[PTR1]] to i32*
384; ALL-NEXT:    [[RES1:%.*]] = load i32, i32* [[PTR1_TYPED]], align 4
385; ALL-NEXT:    call void @foo.i32(i32* nonnull [[PTR1_TYPED]])
386; ALL-NEXT:    br label [[EXIT:%.*]]
387; ALL:       bb2:
388; ALL-NEXT:    [[PTR2:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16
389; ALL-NEXT:    [[PTR2_TYPED:%.*]] = bitcast i8* [[PTR2]] to i32*
390; ALL-NEXT:    [[RES2:%.*]] = load i32, i32* [[PTR2_TYPED]], align 4
391; ALL-NEXT:    call void @foo.i32(i32* nonnull [[PTR2_TYPED]])
392; ALL-NEXT:    br label [[EXIT]]
393; ALL:       exit:
394; ALL-NEXT:    [[PTR_TYPED:%.*]] = phi i32* [ [[PTR1_TYPED]], [[BB1]] ], [ [[PTR2_TYPED]], [[BB2]] ]
395; ALL-NEXT:    [[RES_PHI:%.*]] = phi i32 [ [[RES1]], [[BB1]] ], [ [[RES2]], [[BB2]] ]
396; ALL-NEXT:    store i32 1, i32* [[PTR_TYPED]], align 4
397; ALL-NEXT:    [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
398; ALL-NEXT:    ret i32 [[RES]]
399;
400entry:
401  %obj = call i8* @get_ptr.i8()
402  br i1 %cond, label %bb1, label %bb2
403
404bb1:
405  %ptr1 = getelementptr inbounds i8, i8* %obj, i64 16
406  %ptr1.typed = bitcast i8* %ptr1 to i32*
407  %res1 = load i32, i32* %ptr1.typed
408  call void @foo.i32(i32* %ptr1.typed)
409  br label %exit
410
411bb2:
412  %ptr2 = getelementptr inbounds i8, i8* %obj, i64 16
413  %ptr2.typed = bitcast i8* %ptr2 to i32*
414  %res2 = load i32, i32* %ptr2.typed
415  call void @foo.i32(i32* %ptr2.typed)
416  br label %exit
417
418exit:
419  %ptr.typed = phi i32* [ %ptr1.typed, %bb1 ], [ %ptr2.typed, %bb2 ]
420  %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ]
421  store i32 1, i32* %ptr.typed
422  %res.load = load i32, i32* %ptr.typed
423  %res = select i1 %cond2, i32 %res.phi, i32 %res.load
424  ret i32 %res
425}
426
427define i32 @test_extra_uses_non_inbounds(i1 %cond, i1 %cond2) {
428; ALL-LABEL: @test_extra_uses_non_inbounds(
429; ALL-NEXT:  entry:
430; ALL-NEXT:    [[OBJ:%.*]] = call i8* @get_ptr.i8()
431; ALL-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
432; ALL:       bb1:
433; ALL-NEXT:    [[PTR1:%.*]] = getelementptr i8, i8* [[OBJ]], i64 16
434; ALL-NEXT:    [[PTR1_TYPED:%.*]] = bitcast i8* [[PTR1]] to i32*
435; ALL-NEXT:    [[RES1:%.*]] = load i32, i32* [[PTR1_TYPED]], align 4
436; ALL-NEXT:    call void @foo.i32(i32* nonnull [[PTR1_TYPED]])
437; ALL-NEXT:    br label [[EXIT:%.*]]
438; ALL:       bb2:
439; ALL-NEXT:    [[PTR2:%.*]] = getelementptr i8, i8* [[OBJ]], i64 16
440; ALL-NEXT:    [[PTR2_TYPED:%.*]] = bitcast i8* [[PTR2]] to i32*
441; ALL-NEXT:    [[RES2:%.*]] = load i32, i32* [[PTR2_TYPED]], align 4
442; ALL-NEXT:    call void @foo.i32(i32* nonnull [[PTR2_TYPED]])
443; ALL-NEXT:    br label [[EXIT]]
444; ALL:       exit:
445; ALL-NEXT:    [[PTR_TYPED:%.*]] = phi i32* [ [[PTR1_TYPED]], [[BB1]] ], [ [[PTR2_TYPED]], [[BB2]] ]
446; ALL-NEXT:    [[RES_PHI:%.*]] = phi i32 [ [[RES1]], [[BB1]] ], [ [[RES2]], [[BB2]] ]
447; ALL-NEXT:    store i32 1, i32* [[PTR_TYPED]], align 4
448; ALL-NEXT:    [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
449; ALL-NEXT:    ret i32 [[RES]]
450;
451entry:
452  %obj = call i8* @get_ptr.i8()
453  br i1 %cond, label %bb1, label %bb2
454
455bb1:
456  %ptr1 = getelementptr i8, i8* %obj, i64 16
457  %ptr1.typed = bitcast i8* %ptr1 to i32*
458  %res1 = load i32, i32* %ptr1.typed
459  call void @foo.i32(i32* %ptr1.typed)
460  br label %exit
461
462bb2:
463  %ptr2 = getelementptr i8, i8* %obj, i64 16
464  %ptr2.typed = bitcast i8* %ptr2 to i32*
465  %res2 = load i32, i32* %ptr2.typed
466  call void @foo.i32(i32* %ptr2.typed)
467  br label %exit
468
469exit:
470  %ptr.typed = phi i32* [ %ptr1.typed, %bb1 ], [ %ptr2.typed, %bb2 ]
471  %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ]
472  store i32 1, i32* %ptr.typed
473  %res.load = load i32, i32* %ptr.typed
474  %res = select i1 %cond2, i32 %res.phi, i32 %res.load
475  ret i32 %res
476}
477
478define i32 @test_extra_uses_multiple_geps(i1 %cond, i1 %cond2) {
479; ALL-LABEL: @test_extra_uses_multiple_geps(
480; ALL-NEXT:  entry:
481; ALL-NEXT:    [[OBJ:%.*]] = call i8* @get_ptr.i8()
482; ALL-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
483; ALL:       bb1:
484; ALL-NEXT:    [[PTR1:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16
485; ALL-NEXT:    [[PTR1_TYPED:%.*]] = bitcast i8* [[PTR1]] to i32*
486; ALL-NEXT:    [[RES1:%.*]] = load i32, i32* [[PTR1_TYPED]], align 4
487; ALL-NEXT:    call void @foo.i32(i32* nonnull [[PTR1_TYPED]])
488; ALL-NEXT:    br label [[EXIT:%.*]]
489; ALL:       bb2:
490; ALL-NEXT:    [[PTR2_1:%.*]] = getelementptr i8, i8* [[OBJ]], i64 16
491; ALL-NEXT:    [[PTR2_TYPED:%.*]] = bitcast i8* [[PTR2_1]] to i32*
492; ALL-NEXT:    [[RES2:%.*]] = load i32, i32* [[PTR2_TYPED]], align 4
493; ALL-NEXT:    call void @foo.i32(i32* nonnull [[PTR2_TYPED]])
494; ALL-NEXT:    br label [[EXIT]]
495; ALL:       exit:
496; ALL-NEXT:    [[PTR_TYPED:%.*]] = phi i32* [ [[PTR1_TYPED]], [[BB1]] ], [ [[PTR2_TYPED]], [[BB2]] ]
497; ALL-NEXT:    [[RES_PHI:%.*]] = phi i32 [ [[RES1]], [[BB1]] ], [ [[RES2]], [[BB2]] ]
498; ALL-NEXT:    store i32 1, i32* [[PTR_TYPED]], align 4
499; ALL-NEXT:    [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
500; ALL-NEXT:    ret i32 [[RES]]
501;
502entry:
503  %obj = call i8* @get_ptr.i8()
504  br i1 %cond, label %bb1, label %bb2
505
506bb1:
507  %ptr1 = getelementptr inbounds i8, i8* %obj, i64 16
508  %ptr1.typed = bitcast i8* %ptr1 to i32*
509  %res1 = load i32, i32* %ptr1.typed
510  call void @foo.i32(i32* %ptr1.typed)
511  br label %exit
512
513bb2:
514  %ptr2.0 = getelementptr i8, i8* %obj, i64 8
515  %ptr2.1 = getelementptr inbounds i8, i8* %ptr2.0, i64 8
516  %ptr2.typed = bitcast i8* %ptr2.1 to i32*
517  %res2 = load i32, i32* %ptr2.typed
518  call void @foo.i32(i32* %ptr2.typed)
519  br label %exit
520
521exit:
522  %ptr.typed = phi i32* [ %ptr1.typed, %bb1 ], [ %ptr2.typed, %bb2 ]
523  %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ]
524  store i32 1, i32* %ptr.typed
525  %res.load = load i32, i32* %ptr.typed
526  %res = select i1 %cond2, i32 %res.phi, i32 %res.load
527  ret i32 %res
528}
529
530define i8 @test_gep_extra_uses(i1 %cond, i1 %cond2) {
531; ALL-LABEL: @test_gep_extra_uses(
532; ALL-NEXT:  entry:
533; ALL-NEXT:    [[OBJ:%.*]] = call i8* @get_ptr.i8()
534; ALL-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
535; ALL:       bb1:
536; ALL-NEXT:    [[PTR1:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16
537; ALL-NEXT:    [[RES1:%.*]] = load i8, i8* [[PTR1]], align 1
538; ALL-NEXT:    call void @foo.i8(i8* nonnull [[PTR1]])
539; ALL-NEXT:    br label [[EXIT:%.*]]
540; ALL:       bb2:
541; ALL-NEXT:    [[PTR2:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16
542; ALL-NEXT:    [[RES2:%.*]] = load i8, i8* [[PTR2]], align 1
543; ALL-NEXT:    call void @foo.i8(i8* nonnull [[PTR2]])
544; ALL-NEXT:    br label [[EXIT]]
545; ALL:       exit:
546; ALL-NEXT:    [[PTR_TYPED:%.*]] = phi i8* [ [[PTR1]], [[BB1]] ], [ [[PTR2]], [[BB2]] ]
547; ALL-NEXT:    [[RES_PHI:%.*]] = phi i8 [ [[RES1]], [[BB1]] ], [ [[RES2]], [[BB2]] ]
548; ALL-NEXT:    store i8 1, i8* [[PTR_TYPED]], align 1
549; ALL-NEXT:    [[RES:%.*]] = select i1 [[COND2:%.*]], i8 [[RES_PHI]], i8 1
550; ALL-NEXT:    ret i8 [[RES]]
551;
552entry:
553  %obj = call i8* @get_ptr.i8()
554  br i1 %cond, label %bb1, label %bb2
555
556bb1:
557  %ptr1 = getelementptr inbounds i8, i8* %obj, i64 16
558  %res1 = load i8, i8* %ptr1
559  call void @foo.i8(i8* %ptr1)
560  br label %exit
561
562bb2:
563  %ptr2 = getelementptr inbounds i8, i8* %obj, i64 16
564  %res2 = load i8, i8* %ptr2
565  call void @foo.i8(i8* %ptr2)
566  br label %exit
567
568exit:
569  %ptr.typed = phi i8* [ %ptr1, %bb1 ], [ %ptr2, %bb2 ]
570  %res.phi = phi i8 [ %res1, %bb1 ], [ %res2, %bb2 ]
571  store i8 1, i8* %ptr.typed
572  %res.load = load i8, i8* %ptr.typed
573  %res = select i1 %cond2, i8 %res.phi, i8 %res.load
574  ret i8 %res
575}
576
577; `swifterror` addresses are restricted to load and stores and call arguments.
578declare void @takeAddress(i8** swifterror)
579
580define i8* @test_dont_optimize_swifterror(i1 %cond, i1 %cond2, i8* %ptr) {
581; INSTCOMBINE-LABEL: @test_dont_optimize_swifterror(
582; INSTCOMBINE-NEXT:  entry:
583; INSTCOMBINE-NEXT:    [[OBJ:%.*]] = alloca swifterror i8*, align 8
584; INSTCOMBINE-NEXT:    [[OBJ2:%.*]] = alloca swifterror i8*, align 8
585; INSTCOMBINE-NEXT:    call void @takeAddress(i8** nonnull swifterror [[OBJ]])
586; INSTCOMBINE-NEXT:    call void @takeAddress(i8** nonnull swifterror [[OBJ2]])
587; INSTCOMBINE-NEXT:    store i8* [[PTR:%.*]], i8** [[OBJ]], align 8
588; INSTCOMBINE-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
589; INSTCOMBINE:       bb1:
590; INSTCOMBINE-NEXT:    [[RES1:%.*]] = load i8*, i8** [[OBJ]], align 8
591; INSTCOMBINE-NEXT:    br label [[EXIT:%.*]]
592; INSTCOMBINE:       bb2:
593; INSTCOMBINE-NEXT:    [[RES2:%.*]] = load i8*, i8** [[OBJ2]], align 8
594; INSTCOMBINE-NEXT:    br label [[EXIT]]
595; INSTCOMBINE:       exit:
596; INSTCOMBINE-NEXT:    [[RES_PHI:%.*]] = phi i8* [ [[RES1]], [[BB1]] ], [ [[RES2]], [[BB2]] ]
597; INSTCOMBINE-NEXT:    store i8* null, i8** [[OBJ]], align 8
598; INSTCOMBINE-NEXT:    [[RES:%.*]] = select i1 [[COND2:%.*]], i8* [[RES_PHI]], i8* null
599; INSTCOMBINE-NEXT:    ret i8* [[RES]]
600;
601; INSTCOMBINEGVN-LABEL: @test_dont_optimize_swifterror(
602; INSTCOMBINEGVN-NEXT:  entry:
603; INSTCOMBINEGVN-NEXT:    [[OBJ:%.*]] = alloca swifterror i8*, align 8
604; INSTCOMBINEGVN-NEXT:    [[OBJ2:%.*]] = alloca swifterror i8*, align 8
605; INSTCOMBINEGVN-NEXT:    call void @takeAddress(i8** nonnull swifterror [[OBJ]])
606; INSTCOMBINEGVN-NEXT:    call void @takeAddress(i8** nonnull swifterror [[OBJ2]])
607; INSTCOMBINEGVN-NEXT:    store i8* [[PTR:%.*]], i8** [[OBJ]], align 8
608; INSTCOMBINEGVN-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
609; INSTCOMBINEGVN:       bb1:
610; INSTCOMBINEGVN-NEXT:    br label [[EXIT:%.*]]
611; INSTCOMBINEGVN:       bb2:
612; INSTCOMBINEGVN-NEXT:    [[RES2:%.*]] = load i8*, i8** [[OBJ2]], align 8
613; INSTCOMBINEGVN-NEXT:    br label [[EXIT]]
614; INSTCOMBINEGVN:       exit:
615; INSTCOMBINEGVN-NEXT:    [[RES_PHI:%.*]] = phi i8* [ [[PTR]], [[BB1]] ], [ [[RES2]], [[BB2]] ]
616; INSTCOMBINEGVN-NEXT:    store i8* null, i8** [[OBJ]], align 8
617; INSTCOMBINEGVN-NEXT:    [[RES:%.*]] = select i1 [[COND2:%.*]], i8* [[RES_PHI]], i8* null
618; INSTCOMBINEGVN-NEXT:    ret i8* [[RES]]
619;
620entry:
621  %obj = alloca swifterror i8*, align 8
622  %obj2 = alloca swifterror i8*, align 8
623  call void @takeAddress(i8** swifterror %obj)
624  call void @takeAddress(i8** swifterror %obj2)
625  store i8* %ptr, i8** %obj, align 8
626  br i1 %cond, label %bb1, label %bb2
627
628bb1:                                              ; preds = %entry
629  %res1 = load i8*, i8** %obj, align 8
630  br label %exit
631
632bb2:                                              ; preds = %entry
633  %res2 = load i8*, i8** %obj2, align 8
634  br label %exit
635
636exit:                                             ; preds = %bb2, %bb1
637  %res.phi = phi i8* [ %res1, %bb1 ], [ %res2, %bb2 ]
638  store i8* null, i8** %obj, align 8
639  %res = select i1 %cond2, i8* %res.phi, i8* null
640  ret i8* %res
641}
642