[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / InstCombine / phi-equal-incoming-pointers.ll
blob4e37dfc1357f2c1ebb18f51ebe9695accffebdb3
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
4 ; Make sure GVN won't undo the transformation:
5 ; RUN: opt -passes=instcombine,gvn -S < %s | FileCheck %s --check-prefixes=ALL,INSTCOMBINEGVN
7 declare i8* @get_ptr.i8()
8 declare i32* @get_ptr.i32()
9 declare void @foo.i8(i8*)
10 declare void @foo.i32(i32*)
12 define 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]]
29 entry:
30   %obj = call i8* @get_ptr.i8()
31   br i1 %cond, label %bb1, label %bb2
33 bb1:
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
39 bb2:
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
45 exit:
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
54 define 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]]
70 entry:
71   br i1 %cond, label %bb1, label %bb2
73 bb1:
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
79 bb2:
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
85 exit:
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
94 define 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]]
122 entry:
123   br i1 %cond, label %bb1, label %bb2
125 bb1:
126   %obj1 = call i8* @get_ptr.i8()
127   br label %merge
129 bb2:
130   %obj2.typed = call i32* @get_ptr.i32()
131   %obj2 = bitcast i32* %obj2.typed to i8*
132   br label %merge
134 merge:
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
140 bb3:
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
146 bb4:
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
152 exit:
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
161 define 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]]
177 entry:
178   %obj = call i32* @get_ptr.i32()
179   br i1 %cond, label %bb1, label %bb2
181 bb1:
182   %ptr1.typed = getelementptr inbounds i32, i32* %obj, i64 16
183   %res1 = load i32, i32* %ptr1.typed
184   br label %exit
186 bb2:
187   %ptr2.typed = getelementptr inbounds i32, i32* %obj, i64 16
188   %res2 = load i32, i32* %ptr2.typed
189   br label %exit
191 exit:
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
200 define 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]]
217 entry:
218   %obj0 = call i8* @get_ptr.i8()
219   %obj = getelementptr inbounds i8, i8* %obj0, i64 16
220   br i1 %cond, label %bb1, label %bb2
222 bb1:
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
228 bb2:
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
234 exit:
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
243 define 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]]
258 entry:
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
265 bb2:
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
271 exit:
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
280 define 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]]
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]]
314 entry:
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
322 bb2:
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
328 exit:
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
337 define 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]]
353 entry:
354   %obj = call i8* @get_ptr.i8()
355   br i1 %cond, label %bb1, label %bb2
357 bb1:
358   %ptr1 = getelementptr inbounds i8, i8* %obj, i64 16
359   %res1 = load i8, i8* %ptr1
360   br label %exit
362 bb2:
363   %ptr2 = getelementptr inbounds i8, i8* %obj, i64 16
364   %res2 = load i8, i8* %ptr2
365   br label %exit
367 exit:
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
376 define 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]]
400 entry:
401   %obj = call i8* @get_ptr.i8()
402   br i1 %cond, label %bb1, label %bb2
404 bb1:
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
411 bb2:
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
418 exit:
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
427 define 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]]
451 entry:
452   %obj = call i8* @get_ptr.i8()
453   br i1 %cond, label %bb1, label %bb2
455 bb1:
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
462 bb2:
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
469 exit:
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
478 define 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]]
502 entry:
503   %obj = call i8* @get_ptr.i8()
504   br i1 %cond, label %bb1, label %bb2
506 bb1:
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
513 bb2:
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
521 exit:
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
530 define 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]]
552 entry:
553   %obj = call i8* @get_ptr.i8()
554   br i1 %cond, label %bb1, label %bb2
556 bb1:
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
562 bb2:
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
568 exit:
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