Revert "[InstCombine] Support gep nuw in icmp folds" (#118698)
[llvm-project.git] / llvm / test / Transforms / InstCombine / phi-equal-incoming-pointers.ll
blob998169ec2fe26f6bb1752770cb08f391c02004d3
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 ptr @get_ptr.i8()
8 declare ptr @get_ptr.i32()
9 declare void @foo.i8(ptr)
10 declare void @foo.i32(ptr)
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 ptr @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:%.*]] = getelementptr inbounds i8, ptr [[OBJ]], i64 16
23 ; ALL-NEXT:    [[RES_PHI:%.*]] = load i32, ptr [[PTR_TYPED]], align 4
24 ; ALL-NEXT:    store i32 1, ptr [[PTR_TYPED]], align 4
25 ; ALL-NEXT:    [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
26 ; ALL-NEXT:    ret i32 [[RES]]
28 entry:
29   %obj = call ptr @get_ptr.i8()
30   br i1 %cond, label %bb1, label %bb2
32 bb1:
33   %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16
34   %res1 = load i32, ptr %ptr1
35   br label %exit
37 bb2:
38   %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16
39   %res2 = load i32, ptr %ptr2
40   br label %exit
42 exit:
43   %ptr.typed = phi ptr [ %ptr1, %bb1 ], [ %ptr2, %bb2 ]
44   %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ]
45   store i32 1, ptr %ptr.typed
46   %res.load = load i32, ptr %ptr.typed
47   %res = select i1 %cond2, i32 %res.phi, i32 %res.load
48   ret i32 %res
51 define i32 @test_gep_and_bitcast_arg(ptr %obj, i1 %cond, i1 %cond2) {
52 ; ALL-LABEL: @test_gep_and_bitcast_arg(
53 ; ALL-NEXT:  entry:
54 ; ALL-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
55 ; ALL:       bb1:
56 ; ALL-NEXT:    br label [[EXIT:%.*]]
57 ; ALL:       bb2:
58 ; ALL-NEXT:    br label [[EXIT]]
59 ; ALL:       exit:
60 ; ALL-NEXT:    [[PTR_TYPED:%.*]] = getelementptr inbounds i8, ptr [[OBJ:%.*]], i64 16
61 ; ALL-NEXT:    [[RES_PHI:%.*]] = load i32, ptr [[PTR_TYPED]], align 4
62 ; ALL-NEXT:    store i32 1, ptr [[PTR_TYPED]], align 4
63 ; ALL-NEXT:    [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
64 ; ALL-NEXT:    ret i32 [[RES]]
66 entry:
67   br i1 %cond, label %bb1, label %bb2
69 bb1:
70   %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16
71   %res1 = load i32, ptr %ptr1
72   br label %exit
74 bb2:
75   %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16
76   %res2 = load i32, ptr %ptr2
77   br label %exit
79 exit:
80   %ptr.typed = phi ptr [ %ptr1, %bb1 ], [ %ptr2, %bb2 ]
81   %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ]
82   store i32 1, ptr %ptr.typed
83   %res.load = load i32, ptr %ptr.typed
84   %res = select i1 %cond2, i32 %res.phi, i32 %res.load
85   ret i32 %res
88 define i32 @test_gep_and_bitcast_phi(i1 %cond, i1 %cond2, i1 %cond3) {
89 ; ALL-LABEL: @test_gep_and_bitcast_phi(
90 ; ALL-NEXT:  entry:
91 ; ALL-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
92 ; ALL:       bb1:
93 ; ALL-NEXT:    [[OBJ1:%.*]] = call ptr @get_ptr.i8()
94 ; ALL-NEXT:    br label [[MERGE:%.*]]
95 ; ALL:       bb2:
96 ; ALL-NEXT:    [[OBJ2_TYPED:%.*]] = call ptr @get_ptr.i32()
97 ; ALL-NEXT:    br label [[MERGE]]
98 ; ALL:       merge:
99 ; ALL-NEXT:    [[OBJ:%.*]] = phi ptr [ [[OBJ1]], [[BB1]] ], [ [[OBJ2_TYPED]], [[BB2]] ]
100 ; ALL-NEXT:    [[ANOTHER_PHI:%.*]] = phi ptr [ [[OBJ1]], [[BB1]] ], [ null, [[BB2]] ]
101 ; ALL-NEXT:    call void @foo.i8(ptr [[ANOTHER_PHI]])
102 ; ALL-NEXT:    br i1 [[COND2:%.*]], label [[BB3:%.*]], label [[BB4:%.*]]
103 ; ALL:       bb3:
104 ; ALL-NEXT:    br label [[EXIT:%.*]]
105 ; ALL:       bb4:
106 ; ALL-NEXT:    br label [[EXIT]]
107 ; ALL:       exit:
108 ; ALL-NEXT:    [[PTR_TYPED:%.*]] = getelementptr inbounds i8, ptr [[OBJ]], i64 16
109 ; ALL-NEXT:    [[RES_PHI:%.*]] = load i32, ptr [[PTR_TYPED]], align 4
110 ; ALL-NEXT:    store i32 1, ptr [[PTR_TYPED]], align 4
111 ; ALL-NEXT:    [[RES:%.*]] = select i1 [[COND3:%.*]], i32 [[RES_PHI]], i32 1
112 ; ALL-NEXT:    ret i32 [[RES]]
114 entry:
115   br i1 %cond, label %bb1, label %bb2
117 bb1:
118   %obj1 = call ptr @get_ptr.i8()
119   br label %merge
121 bb2:
122   %obj2.typed = call ptr @get_ptr.i32()
123   br label %merge
125 merge:
126   %obj = phi ptr [ %obj1, %bb1 ], [ %obj2.typed, %bb2 ]
127   %another_phi = phi ptr [ %obj1, %bb1 ], [ null, %bb2 ]
128   call void @foo.i8(ptr %another_phi)
129   br i1 %cond2, label %bb3, label %bb4
131 bb3:
132   %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16
133   %res1 = load i32, ptr %ptr1
134   br label %exit
136 bb4:
137   %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16
138   %res2 = load i32, ptr %ptr2
139   br label %exit
141 exit:
142   %ptr.typed = phi ptr [ %ptr1, %bb3 ], [ %ptr2, %bb4 ]
143   %res.phi = phi i32 [ %res1, %bb3 ], [ %res2, %bb4 ]
144   store i32 1, ptr %ptr.typed
145   %res.load = load i32, ptr %ptr.typed
146   %res = select i1 %cond3, i32 %res.phi, i32 %res.load
147   ret i32 %res
150 define i32 @test_gep_i32ptr(i1 %cond, i1 %cond2) {
151 ; ALL-LABEL: @test_gep_i32ptr(
152 ; ALL-NEXT:  entry:
153 ; ALL-NEXT:    [[OBJ:%.*]] = call ptr @get_ptr.i32()
154 ; ALL-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
155 ; ALL:       bb1:
156 ; ALL-NEXT:    br label [[EXIT:%.*]]
157 ; ALL:       bb2:
158 ; ALL-NEXT:    br label [[EXIT]]
159 ; ALL:       exit:
160 ; ALL-NEXT:    [[PTR_TYPED:%.*]] = getelementptr inbounds i8, ptr [[OBJ]], i64 64
161 ; ALL-NEXT:    [[RES_PHI:%.*]] = load i32, ptr [[PTR_TYPED]], align 4
162 ; ALL-NEXT:    store i32 1, ptr [[PTR_TYPED]], align 4
163 ; ALL-NEXT:    [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
164 ; ALL-NEXT:    ret i32 [[RES]]
166 entry:
167   %obj = call ptr @get_ptr.i32()
168   br i1 %cond, label %bb1, label %bb2
170 bb1:
171   %ptr1.typed = getelementptr inbounds i32, ptr %obj, i64 16
172   %res1 = load i32, ptr %ptr1.typed
173   br label %exit
175 bb2:
176   %ptr2.typed = getelementptr inbounds i32, ptr %obj, i64 16
177   %res2 = load i32, ptr %ptr2.typed
178   br label %exit
180 exit:
181   %ptr.typed = phi ptr [ %ptr1.typed, %bb1 ], [ %ptr2.typed, %bb2 ]
182   %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ]
183   store i32 1, ptr %ptr.typed
184   %res.load = load i32, ptr %ptr.typed
185   %res = select i1 %cond2, i32 %res.phi, i32 %res.load
186   ret i32 %res
189 define i32 @test_gep_and_bitcast_gep_base_ptr(i1 %cond, i1 %cond2) {
190 ; ALL-LABEL: @test_gep_and_bitcast_gep_base_ptr(
191 ; ALL-NEXT:  entry:
192 ; ALL-NEXT:    [[OBJ0:%.*]] = call ptr @get_ptr.i8()
193 ; ALL-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
194 ; ALL:       bb1:
195 ; ALL-NEXT:    br label [[EXIT:%.*]]
196 ; ALL:       bb2:
197 ; ALL-NEXT:    br label [[EXIT]]
198 ; ALL:       exit:
199 ; ALL-NEXT:    [[PTR_TYPED:%.*]] = getelementptr inbounds i8, ptr [[OBJ0]], i64 32
200 ; ALL-NEXT:    [[RES_PHI:%.*]] = load i32, ptr [[PTR_TYPED]], align 4
201 ; ALL-NEXT:    store i32 1, ptr [[PTR_TYPED]], align 4
202 ; ALL-NEXT:    [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
203 ; ALL-NEXT:    ret i32 [[RES]]
205 entry:
206   %obj0 = call ptr @get_ptr.i8()
207   %obj = getelementptr inbounds i8, ptr %obj0, i64 16
208   br i1 %cond, label %bb1, label %bb2
210 bb1:
211   %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16
212   %res1 = load i32, ptr %ptr1
213   br label %exit
215 bb2:
216   %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16
217   %res2 = load i32, ptr %ptr2
218   br label %exit
220 exit:
221   %ptr.typed = phi ptr [ %ptr1, %bb1 ], [ %ptr2, %bb2 ]
222   %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ]
223   store i32 1, ptr %ptr.typed
224   %res.load = load i32, ptr %ptr.typed
225   %res = select i1 %cond2, i32 %res.phi, i32 %res.load
226   ret i32 %res
229 define i32 @test_gep_and_bitcast_same_bb(i1 %cond, i1 %cond2) {
230 ; ALL-LABEL: @test_gep_and_bitcast_same_bb(
231 ; ALL-NEXT:  entry:
232 ; ALL-NEXT:    [[OBJ:%.*]] = call ptr @get_ptr.i8()
233 ; ALL-NEXT:    br i1 [[COND:%.*]], label [[EXIT:%.*]], label [[BB2:%.*]]
234 ; ALL:       bb2:
235 ; ALL-NEXT:    br label [[EXIT]]
236 ; ALL:       exit:
237 ; ALL-NEXT:    [[PTR_TYPED:%.*]] = getelementptr inbounds i8, ptr [[OBJ]], i64 16
238 ; ALL-NEXT:    [[RES_PHI:%.*]] = load i32, ptr [[PTR_TYPED]], align 4
239 ; ALL-NEXT:    store i32 1, ptr [[PTR_TYPED]], align 4
240 ; ALL-NEXT:    [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
241 ; ALL-NEXT:    ret i32 [[RES]]
243 entry:
244   %obj = call ptr @get_ptr.i8()
245   %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16
246   %res1 = load i32, ptr %ptr1
247   br i1 %cond, label %exit, label %bb2
249 bb2:
250   %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16
251   %res2 = load i32, ptr %ptr2
252   br label %exit
254 exit:
255   %ptr.typed = phi ptr [ %ptr1, %entry ], [ %ptr2, %bb2 ]
256   %res.phi = phi i32 [ %res1, %entry ], [ %res2, %bb2 ]
257   store i32 1, ptr %ptr.typed
258   %res.load = load i32, ptr %ptr.typed
259   %res = select i1 %cond2, i32 %res.phi, i32 %res.load
260   ret i32 %res
263 define i32 @test_gep_and_bitcast_same_bb_and_extra_use(i1 %cond, i1 %cond2) {
264 ; INSTCOMBINE-LABEL: @test_gep_and_bitcast_same_bb_and_extra_use(
265 ; INSTCOMBINE-NEXT:  entry:
266 ; INSTCOMBINE-NEXT:    [[OBJ:%.*]] = call ptr @get_ptr.i8()
267 ; INSTCOMBINE-NEXT:    [[PTR1:%.*]] = getelementptr inbounds i8, ptr [[OBJ]], i64 16
268 ; INSTCOMBINE-NEXT:    call void @foo.i32(ptr nonnull [[PTR1]])
269 ; INSTCOMBINE-NEXT:    br i1 [[COND:%.*]], label [[EXIT:%.*]], label [[BB2:%.*]]
270 ; INSTCOMBINE:       bb2:
271 ; INSTCOMBINE-NEXT:    [[PTR2:%.*]] = getelementptr inbounds i8, ptr [[OBJ]], i64 16
272 ; INSTCOMBINE-NEXT:    br label [[EXIT]]
273 ; INSTCOMBINE:       exit:
274 ; INSTCOMBINE-NEXT:    [[PTR_TYPED:%.*]] = phi ptr [ [[PTR1]], [[ENTRY:%.*]] ], [ [[PTR2]], [[BB2]] ]
275 ; INSTCOMBINE-NEXT:    [[RES_PHI:%.*]] = load i32, ptr [[PTR_TYPED]], align 4
276 ; INSTCOMBINE-NEXT:    store i32 1, ptr [[PTR_TYPED]], align 4
277 ; INSTCOMBINE-NEXT:    [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
278 ; INSTCOMBINE-NEXT:    ret i32 [[RES]]
280 ; INSTCOMBINEGVN-LABEL: @test_gep_and_bitcast_same_bb_and_extra_use(
281 ; INSTCOMBINEGVN-NEXT:  entry:
282 ; INSTCOMBINEGVN-NEXT:    [[OBJ:%.*]] = call ptr @get_ptr.i8()
283 ; INSTCOMBINEGVN-NEXT:    [[PTR1:%.*]] = getelementptr inbounds i8, ptr [[OBJ]], i64 16
284 ; INSTCOMBINEGVN-NEXT:    call void @foo.i32(ptr nonnull [[PTR1]])
285 ; INSTCOMBINEGVN-NEXT:    br i1 [[COND:%.*]], label [[EXIT:%.*]], label [[BB2:%.*]]
286 ; INSTCOMBINEGVN:       bb2:
287 ; INSTCOMBINEGVN-NEXT:    br label [[EXIT]]
288 ; INSTCOMBINEGVN:       exit:
289 ; INSTCOMBINEGVN-NEXT:    [[RES_PHI:%.*]] = load i32, ptr [[PTR1]], align 4
290 ; INSTCOMBINEGVN-NEXT:    store i32 1, ptr [[PTR1]], align 4
291 ; INSTCOMBINEGVN-NEXT:    [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
292 ; INSTCOMBINEGVN-NEXT:    ret i32 [[RES]]
294 entry:
295   %obj = call ptr @get_ptr.i8()
296   %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16
297   call void @foo.i32(ptr %ptr1)
298   %res1 = load i32, ptr %ptr1
299   br i1 %cond, label %exit, label %bb2
301 bb2:
302   %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16
303   %res2 = load i32, ptr %ptr2
304   br label %exit
306 exit:
307   %ptr.typed = phi ptr [ %ptr1, %entry ], [ %ptr2, %bb2 ]
308   %res.phi = phi i32 [ %res1, %entry ], [ %res2, %bb2 ]
309   store i32 1, ptr %ptr.typed
310   %res.load = load i32, ptr %ptr.typed
311   %res = select i1 %cond2, i32 %res.phi, i32 %res.load
312   ret i32 %res
315 define i8 @test_gep(i1 %cond, i1 %cond2) {
316 ; ALL-LABEL: @test_gep(
317 ; ALL-NEXT:  entry:
318 ; ALL-NEXT:    [[OBJ:%.*]] = call ptr @get_ptr.i8()
319 ; ALL-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
320 ; ALL:       bb1:
321 ; ALL-NEXT:    br label [[EXIT:%.*]]
322 ; ALL:       bb2:
323 ; ALL-NEXT:    br label [[EXIT]]
324 ; ALL:       exit:
325 ; ALL-NEXT:    [[PTR_TYPED:%.*]] = getelementptr inbounds i8, ptr [[OBJ]], i64 16
326 ; ALL-NEXT:    [[RES_PHI:%.*]] = load i8, ptr [[PTR_TYPED]], align 1
327 ; ALL-NEXT:    store i8 1, ptr [[PTR_TYPED]], align 1
328 ; ALL-NEXT:    [[RES:%.*]] = select i1 [[COND2:%.*]], i8 [[RES_PHI]], i8 1
329 ; ALL-NEXT:    ret i8 [[RES]]
331 entry:
332   %obj = call ptr @get_ptr.i8()
333   br i1 %cond, label %bb1, label %bb2
335 bb1:
336   %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16
337   %res1 = load i8, ptr %ptr1
338   br label %exit
340 bb2:
341   %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16
342   %res2 = load i8, ptr %ptr2
343   br label %exit
345 exit:
346   %ptr.typed = phi ptr [ %ptr1, %bb1 ], [ %ptr2, %bb2 ]
347   %res.phi = phi i8 [ %res1, %bb1 ], [ %res2, %bb2 ]
348   store i8 1, ptr %ptr.typed
349   %res.load = load i8, ptr %ptr.typed
350   %res = select i1 %cond2, i8 %res.phi, i8 %res.load
351   ret i8 %res
354 define i32 @test_extra_uses(i1 %cond, i1 %cond2) {
355 ; ALL-LABEL: @test_extra_uses(
356 ; ALL-NEXT:  entry:
357 ; ALL-NEXT:    [[OBJ:%.*]] = call ptr @get_ptr.i8()
358 ; ALL-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
359 ; ALL:       bb1:
360 ; ALL-NEXT:    [[PTR1:%.*]] = getelementptr inbounds i8, ptr [[OBJ]], i64 16
361 ; ALL-NEXT:    [[RES1:%.*]] = load i32, ptr [[PTR1]], align 4
362 ; ALL-NEXT:    call void @foo.i32(ptr nonnull [[PTR1]])
363 ; ALL-NEXT:    br label [[EXIT:%.*]]
364 ; ALL:       bb2:
365 ; ALL-NEXT:    [[PTR2:%.*]] = getelementptr inbounds i8, ptr [[OBJ]], i64 16
366 ; ALL-NEXT:    [[RES2:%.*]] = load i32, ptr [[PTR2]], align 4
367 ; ALL-NEXT:    call void @foo.i32(ptr nonnull [[PTR2]])
368 ; ALL-NEXT:    br label [[EXIT]]
369 ; ALL:       exit:
370 ; ALL-NEXT:    [[PTR_TYPED:%.*]] = phi ptr [ [[PTR1]], [[BB1]] ], [ [[PTR2]], [[BB2]] ]
371 ; ALL-NEXT:    [[RES_PHI:%.*]] = phi i32 [ [[RES1]], [[BB1]] ], [ [[RES2]], [[BB2]] ]
372 ; ALL-NEXT:    store i32 1, ptr [[PTR_TYPED]], align 4
373 ; ALL-NEXT:    [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
374 ; ALL-NEXT:    ret i32 [[RES]]
376 entry:
377   %obj = call ptr @get_ptr.i8()
378   br i1 %cond, label %bb1, label %bb2
380 bb1:
381   %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16
382   %res1 = load i32, ptr %ptr1
383   call void @foo.i32(ptr %ptr1)
384   br label %exit
386 bb2:
387   %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16
388   %res2 = load i32, ptr %ptr2
389   call void @foo.i32(ptr %ptr2)
390   br label %exit
392 exit:
393   %ptr.typed = phi ptr [ %ptr1, %bb1 ], [ %ptr2, %bb2 ]
394   %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ]
395   store i32 1, ptr %ptr.typed
396   %res.load = load i32, ptr %ptr.typed
397   %res = select i1 %cond2, i32 %res.phi, i32 %res.load
398   ret i32 %res
401 define i32 @test_extra_uses_non_inbounds(i1 %cond, i1 %cond2) {
402 ; ALL-LABEL: @test_extra_uses_non_inbounds(
403 ; ALL-NEXT:  entry:
404 ; ALL-NEXT:    [[OBJ:%.*]] = call ptr @get_ptr.i8()
405 ; ALL-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
406 ; ALL:       bb1:
407 ; ALL-NEXT:    [[PTR1:%.*]] = getelementptr i8, ptr [[OBJ]], i64 16
408 ; ALL-NEXT:    [[RES1:%.*]] = load i32, ptr [[PTR1]], align 4
409 ; ALL-NEXT:    call void @foo.i32(ptr nonnull [[PTR1]])
410 ; ALL-NEXT:    br label [[EXIT:%.*]]
411 ; ALL:       bb2:
412 ; ALL-NEXT:    [[PTR2:%.*]] = getelementptr i8, ptr [[OBJ]], i64 16
413 ; ALL-NEXT:    [[RES2:%.*]] = load i32, ptr [[PTR2]], align 4
414 ; ALL-NEXT:    call void @foo.i32(ptr nonnull [[PTR2]])
415 ; ALL-NEXT:    br label [[EXIT]]
416 ; ALL:       exit:
417 ; ALL-NEXT:    [[PTR_TYPED:%.*]] = phi ptr [ [[PTR1]], [[BB1]] ], [ [[PTR2]], [[BB2]] ]
418 ; ALL-NEXT:    [[RES_PHI:%.*]] = phi i32 [ [[RES1]], [[BB1]] ], [ [[RES2]], [[BB2]] ]
419 ; ALL-NEXT:    store i32 1, ptr [[PTR_TYPED]], align 4
420 ; ALL-NEXT:    [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
421 ; ALL-NEXT:    ret i32 [[RES]]
423 entry:
424   %obj = call ptr @get_ptr.i8()
425   br i1 %cond, label %bb1, label %bb2
427 bb1:
428   %ptr1 = getelementptr i8, ptr %obj, i64 16
429   %res1 = load i32, ptr %ptr1
430   call void @foo.i32(ptr %ptr1)
431   br label %exit
433 bb2:
434   %ptr2 = getelementptr i8, ptr %obj, i64 16
435   %res2 = load i32, ptr %ptr2
436   call void @foo.i32(ptr %ptr2)
437   br label %exit
439 exit:
440   %ptr.typed = phi ptr [ %ptr1, %bb1 ], [ %ptr2, %bb2 ]
441   %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ]
442   store i32 1, ptr %ptr.typed
443   %res.load = load i32, ptr %ptr.typed
444   %res = select i1 %cond2, i32 %res.phi, i32 %res.load
445   ret i32 %res
448 define i32 @test_extra_uses_multiple_geps(i1 %cond, i1 %cond2) {
449 ; ALL-LABEL: @test_extra_uses_multiple_geps(
450 ; ALL-NEXT:  entry:
451 ; ALL-NEXT:    [[OBJ:%.*]] = call ptr @get_ptr.i8()
452 ; ALL-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
453 ; ALL:       bb1:
454 ; ALL-NEXT:    [[PTR1:%.*]] = getelementptr inbounds i8, ptr [[OBJ]], i64 16
455 ; ALL-NEXT:    [[RES1:%.*]] = load i32, ptr [[PTR1]], align 4
456 ; ALL-NEXT:    call void @foo.i32(ptr nonnull [[PTR1]])
457 ; ALL-NEXT:    br label [[EXIT:%.*]]
458 ; ALL:       bb2:
459 ; ALL-NEXT:    [[PTR2_1:%.*]] = getelementptr i8, ptr [[OBJ]], i64 16
460 ; ALL-NEXT:    [[RES2:%.*]] = load i32, ptr [[PTR2_1]], align 4
461 ; ALL-NEXT:    call void @foo.i32(ptr nonnull [[PTR2_1]])
462 ; ALL-NEXT:    br label [[EXIT]]
463 ; ALL:       exit:
464 ; ALL-NEXT:    [[PTR_TYPED:%.*]] = phi ptr [ [[PTR1]], [[BB1]] ], [ [[PTR2_1]], [[BB2]] ]
465 ; ALL-NEXT:    [[RES_PHI:%.*]] = phi i32 [ [[RES1]], [[BB1]] ], [ [[RES2]], [[BB2]] ]
466 ; ALL-NEXT:    store i32 1, ptr [[PTR_TYPED]], align 4
467 ; ALL-NEXT:    [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
468 ; ALL-NEXT:    ret i32 [[RES]]
470 entry:
471   %obj = call ptr @get_ptr.i8()
472   br i1 %cond, label %bb1, label %bb2
474 bb1:
475   %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16
476   %res1 = load i32, ptr %ptr1
477   call void @foo.i32(ptr %ptr1)
478   br label %exit
480 bb2:
481   %ptr2.0 = getelementptr i8, ptr %obj, i64 8
482   %ptr2.1 = getelementptr inbounds i8, ptr %ptr2.0, i64 8
483   %res2 = load i32, ptr %ptr2.1
484   call void @foo.i32(ptr %ptr2.1)
485   br label %exit
487 exit:
488   %ptr.typed = phi ptr [ %ptr1, %bb1 ], [ %ptr2.1, %bb2 ]
489   %res.phi = phi i32 [ %res1, %bb1 ], [ %res2, %bb2 ]
490   store i32 1, ptr %ptr.typed
491   %res.load = load i32, ptr %ptr.typed
492   %res = select i1 %cond2, i32 %res.phi, i32 %res.load
493   ret i32 %res
496 define i8 @test_gep_extra_uses(i1 %cond, i1 %cond2) {
497 ; ALL-LABEL: @test_gep_extra_uses(
498 ; ALL-NEXT:  entry:
499 ; ALL-NEXT:    [[OBJ:%.*]] = call ptr @get_ptr.i8()
500 ; ALL-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
501 ; ALL:       bb1:
502 ; ALL-NEXT:    [[PTR1:%.*]] = getelementptr inbounds i8, ptr [[OBJ]], i64 16
503 ; ALL-NEXT:    [[RES1:%.*]] = load i8, ptr [[PTR1]], align 1
504 ; ALL-NEXT:    call void @foo.i8(ptr nonnull [[PTR1]])
505 ; ALL-NEXT:    br label [[EXIT:%.*]]
506 ; ALL:       bb2:
507 ; ALL-NEXT:    [[PTR2:%.*]] = getelementptr inbounds i8, ptr [[OBJ]], i64 16
508 ; ALL-NEXT:    [[RES2:%.*]] = load i8, ptr [[PTR2]], align 1
509 ; ALL-NEXT:    call void @foo.i8(ptr nonnull [[PTR2]])
510 ; ALL-NEXT:    br label [[EXIT]]
511 ; ALL:       exit:
512 ; ALL-NEXT:    [[PTR_TYPED:%.*]] = phi ptr [ [[PTR1]], [[BB1]] ], [ [[PTR2]], [[BB2]] ]
513 ; ALL-NEXT:    [[RES_PHI:%.*]] = phi i8 [ [[RES1]], [[BB1]] ], [ [[RES2]], [[BB2]] ]
514 ; ALL-NEXT:    store i8 1, ptr [[PTR_TYPED]], align 1
515 ; ALL-NEXT:    [[RES:%.*]] = select i1 [[COND2:%.*]], i8 [[RES_PHI]], i8 1
516 ; ALL-NEXT:    ret i8 [[RES]]
518 entry:
519   %obj = call ptr @get_ptr.i8()
520   br i1 %cond, label %bb1, label %bb2
522 bb1:
523   %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16
524   %res1 = load i8, ptr %ptr1
525   call void @foo.i8(ptr %ptr1)
526   br label %exit
528 bb2:
529   %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16
530   %res2 = load i8, ptr %ptr2
531   call void @foo.i8(ptr %ptr2)
532   br label %exit
534 exit:
535   %ptr.typed = phi ptr [ %ptr1, %bb1 ], [ %ptr2, %bb2 ]
536   %res.phi = phi i8 [ %res1, %bb1 ], [ %res2, %bb2 ]
537   store i8 1, ptr %ptr.typed
538   %res.load = load i8, ptr %ptr.typed
539   %res = select i1 %cond2, i8 %res.phi, i8 %res.load
540   ret i8 %res
543 ; `swifterror` addresses are restricted to load and stores and call arguments.
544 declare void @takeAddress(ptr swifterror)
546 define ptr @test_dont_optimize_swifterror(i1 %cond, i1 %cond2, ptr %ptr) {
547 ; INSTCOMBINE-LABEL: @test_dont_optimize_swifterror(
548 ; INSTCOMBINE-NEXT:  entry:
549 ; INSTCOMBINE-NEXT:    [[OBJ:%.*]] = alloca swifterror ptr, align 8
550 ; INSTCOMBINE-NEXT:    [[OBJ2:%.*]] = alloca swifterror ptr, align 8
551 ; INSTCOMBINE-NEXT:    call void @takeAddress(ptr nonnull swifterror [[OBJ]])
552 ; INSTCOMBINE-NEXT:    call void @takeAddress(ptr nonnull swifterror [[OBJ2]])
553 ; INSTCOMBINE-NEXT:    store ptr [[PTR:%.*]], ptr [[OBJ]], align 8
554 ; INSTCOMBINE-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
555 ; INSTCOMBINE:       bb1:
556 ; INSTCOMBINE-NEXT:    [[RES1:%.*]] = load ptr, ptr [[OBJ]], align 8
557 ; INSTCOMBINE-NEXT:    br label [[EXIT:%.*]]
558 ; INSTCOMBINE:       bb2:
559 ; INSTCOMBINE-NEXT:    [[RES2:%.*]] = load ptr, ptr [[OBJ2]], align 8
560 ; INSTCOMBINE-NEXT:    br label [[EXIT]]
561 ; INSTCOMBINE:       exit:
562 ; INSTCOMBINE-NEXT:    [[RES_PHI:%.*]] = phi ptr [ [[RES1]], [[BB1]] ], [ [[RES2]], [[BB2]] ]
563 ; INSTCOMBINE-NEXT:    store ptr null, ptr [[OBJ]], align 8
564 ; INSTCOMBINE-NEXT:    [[RES:%.*]] = select i1 [[COND2:%.*]], ptr [[RES_PHI]], ptr null
565 ; INSTCOMBINE-NEXT:    ret ptr [[RES]]
567 ; INSTCOMBINEGVN-LABEL: @test_dont_optimize_swifterror(
568 ; INSTCOMBINEGVN-NEXT:  entry:
569 ; INSTCOMBINEGVN-NEXT:    [[OBJ:%.*]] = alloca swifterror ptr, align 8
570 ; INSTCOMBINEGVN-NEXT:    [[OBJ2:%.*]] = alloca swifterror ptr, align 8
571 ; INSTCOMBINEGVN-NEXT:    call void @takeAddress(ptr nonnull swifterror [[OBJ]])
572 ; INSTCOMBINEGVN-NEXT:    call void @takeAddress(ptr nonnull swifterror [[OBJ2]])
573 ; INSTCOMBINEGVN-NEXT:    store ptr [[PTR:%.*]], ptr [[OBJ]], align 8
574 ; INSTCOMBINEGVN-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
575 ; INSTCOMBINEGVN:       bb1:
576 ; INSTCOMBINEGVN-NEXT:    br label [[EXIT:%.*]]
577 ; INSTCOMBINEGVN:       bb2:
578 ; INSTCOMBINEGVN-NEXT:    [[RES2:%.*]] = load ptr, ptr [[OBJ2]], align 8
579 ; INSTCOMBINEGVN-NEXT:    br label [[EXIT]]
580 ; INSTCOMBINEGVN:       exit:
581 ; INSTCOMBINEGVN-NEXT:    [[RES_PHI:%.*]] = phi ptr [ [[PTR]], [[BB1]] ], [ [[RES2]], [[BB2]] ]
582 ; INSTCOMBINEGVN-NEXT:    store ptr null, ptr [[OBJ]], align 8
583 ; INSTCOMBINEGVN-NEXT:    [[RES:%.*]] = select i1 [[COND2:%.*]], ptr [[RES_PHI]], ptr null
584 ; INSTCOMBINEGVN-NEXT:    ret ptr [[RES]]
586 entry:
587   %obj = alloca swifterror ptr, align 8
588   %obj2 = alloca swifterror ptr, align 8
589   call void @takeAddress(ptr swifterror %obj)
590   call void @takeAddress(ptr swifterror %obj2)
591   store ptr %ptr, ptr %obj, align 8
592   br i1 %cond, label %bb1, label %bb2
594 bb1:                                              ; preds = %entry
595   %res1 = load ptr, ptr %obj, align 8
596   br label %exit
598 bb2:                                              ; preds = %entry
599   %res2 = load ptr, ptr %obj2, align 8
600   br label %exit
602 exit:                                             ; preds = %bb2, %bb1
603   %res.phi = phi ptr [ %res1, %bb1 ], [ %res2, %bb2 ]
604   store ptr null, ptr %obj, align 8
605   %res = select i1 %cond2, ptr %res.phi, ptr null
606   ret ptr %res