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(
15 ; ALL-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i8()
16 ; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
18 ; ALL-NEXT: br label [[EXIT:%.*]]
20 ; ALL-NEXT: br label [[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]]
29 %obj = call ptr @get_ptr.i8()
30 br i1 %cond, label %bb1, label %bb2
33 %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16
34 %res1 = load i32, ptr %ptr1
38 %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16
39 %res2 = load i32, ptr %ptr2
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
51 define i32 @test_gep_and_bitcast_arg(ptr %obj, i1 %cond, i1 %cond2) {
52 ; ALL-LABEL: @test_gep_and_bitcast_arg(
54 ; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
56 ; ALL-NEXT: br label [[EXIT:%.*]]
58 ; ALL-NEXT: br label [[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]]
67 br i1 %cond, label %bb1, label %bb2
70 %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16
71 %res1 = load i32, ptr %ptr1
75 %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16
76 %res2 = load i32, ptr %ptr2
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
88 define i32 @test_gep_and_bitcast_phi(i1 %cond, i1 %cond2, i1 %cond3) {
89 ; ALL-LABEL: @test_gep_and_bitcast_phi(
91 ; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
93 ; ALL-NEXT: [[OBJ1:%.*]] = call ptr @get_ptr.i8()
94 ; ALL-NEXT: br label [[MERGE:%.*]]
96 ; ALL-NEXT: [[OBJ2_TYPED:%.*]] = call ptr @get_ptr.i32()
97 ; ALL-NEXT: br label [[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:%.*]]
104 ; ALL-NEXT: br label [[EXIT:%.*]]
106 ; ALL-NEXT: br label [[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]]
115 br i1 %cond, label %bb1, label %bb2
118 %obj1 = call ptr @get_ptr.i8()
122 %obj2.typed = call ptr @get_ptr.i32()
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
132 %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16
133 %res1 = load i32, ptr %ptr1
137 %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16
138 %res2 = load i32, ptr %ptr2
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
150 define i32 @test_gep_i32ptr(i1 %cond, i1 %cond2) {
151 ; ALL-LABEL: @test_gep_i32ptr(
153 ; ALL-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i32()
154 ; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
156 ; ALL-NEXT: br label [[EXIT:%.*]]
158 ; ALL-NEXT: br label [[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]]
167 %obj = call ptr @get_ptr.i32()
168 br i1 %cond, label %bb1, label %bb2
171 %ptr1.typed = getelementptr inbounds i32, ptr %obj, i64 16
172 %res1 = load i32, ptr %ptr1.typed
176 %ptr2.typed = getelementptr inbounds i32, ptr %obj, i64 16
177 %res2 = load i32, ptr %ptr2.typed
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
189 define i32 @test_gep_and_bitcast_gep_base_ptr(i1 %cond, i1 %cond2) {
190 ; ALL-LABEL: @test_gep_and_bitcast_gep_base_ptr(
192 ; ALL-NEXT: [[OBJ0:%.*]] = call ptr @get_ptr.i8()
193 ; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
195 ; ALL-NEXT: br label [[EXIT:%.*]]
197 ; ALL-NEXT: br label [[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]]
206 %obj0 = call ptr @get_ptr.i8()
207 %obj = getelementptr inbounds i8, ptr %obj0, i64 16
208 br i1 %cond, label %bb1, label %bb2
211 %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16
212 %res1 = load i32, ptr %ptr1
216 %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16
217 %res2 = load i32, ptr %ptr2
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
229 define i32 @test_gep_and_bitcast_same_bb(i1 %cond, i1 %cond2) {
230 ; ALL-LABEL: @test_gep_and_bitcast_same_bb(
232 ; ALL-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i8()
233 ; ALL-NEXT: br i1 [[COND:%.*]], label [[EXIT:%.*]], label [[BB2:%.*]]
235 ; ALL-NEXT: br label [[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]]
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
250 %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16
251 %res2 = load i32, ptr %ptr2
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
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:%.*]]
271 ; INSTCOMBINE-NEXT: [[PTR2:%.*]] = getelementptr inbounds i8, ptr [[OBJ]], i64 16
272 ; INSTCOMBINE-NEXT: br label [[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]]
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
302 %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16
303 %res2 = load i32, ptr %ptr2
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
315 define i8 @test_gep(i1 %cond, i1 %cond2) {
316 ; ALL-LABEL: @test_gep(
318 ; ALL-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i8()
319 ; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
321 ; ALL-NEXT: br label [[EXIT:%.*]]
323 ; ALL-NEXT: br label [[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]]
332 %obj = call ptr @get_ptr.i8()
333 br i1 %cond, label %bb1, label %bb2
336 %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16
337 %res1 = load i8, ptr %ptr1
341 %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16
342 %res2 = load i8, ptr %ptr2
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
354 define i32 @test_extra_uses(i1 %cond, i1 %cond2) {
355 ; ALL-LABEL: @test_extra_uses(
357 ; ALL-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i8()
358 ; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
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:%.*]]
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]]
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]]
377 %obj = call ptr @get_ptr.i8()
378 br i1 %cond, label %bb1, label %bb2
381 %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16
382 %res1 = load i32, ptr %ptr1
383 call void @foo.i32(ptr %ptr1)
387 %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16
388 %res2 = load i32, ptr %ptr2
389 call void @foo.i32(ptr %ptr2)
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
401 define i32 @test_extra_uses_non_inbounds(i1 %cond, i1 %cond2) {
402 ; ALL-LABEL: @test_extra_uses_non_inbounds(
404 ; ALL-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i8()
405 ; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
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:%.*]]
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]]
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]]
424 %obj = call ptr @get_ptr.i8()
425 br i1 %cond, label %bb1, label %bb2
428 %ptr1 = getelementptr i8, ptr %obj, i64 16
429 %res1 = load i32, ptr %ptr1
430 call void @foo.i32(ptr %ptr1)
434 %ptr2 = getelementptr i8, ptr %obj, i64 16
435 %res2 = load i32, ptr %ptr2
436 call void @foo.i32(ptr %ptr2)
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
448 define i32 @test_extra_uses_multiple_geps(i1 %cond, i1 %cond2) {
449 ; ALL-LABEL: @test_extra_uses_multiple_geps(
451 ; ALL-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i8()
452 ; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
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:%.*]]
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]]
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]]
471 %obj = call ptr @get_ptr.i8()
472 br i1 %cond, label %bb1, label %bb2
475 %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16
476 %res1 = load i32, ptr %ptr1
477 call void @foo.i32(ptr %ptr1)
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)
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
496 define i8 @test_gep_extra_uses(i1 %cond, i1 %cond2) {
497 ; ALL-LABEL: @test_gep_extra_uses(
499 ; ALL-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i8()
500 ; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
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:%.*]]
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]]
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]]
519 %obj = call ptr @get_ptr.i8()
520 br i1 %cond, label %bb1, label %bb2
523 %ptr1 = getelementptr inbounds i8, ptr %obj, i64 16
524 %res1 = load i8, ptr %ptr1
525 call void @foo.i8(ptr %ptr1)
529 %ptr2 = getelementptr inbounds i8, ptr %obj, i64 16
530 %res2 = load i8, ptr %ptr2
531 call void @foo.i8(ptr %ptr2)
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
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:%.*]]
556 ; INSTCOMBINE-NEXT: [[RES1:%.*]] = load ptr, ptr [[OBJ]], align 8
557 ; INSTCOMBINE-NEXT: br label [[EXIT:%.*]]
559 ; INSTCOMBINE-NEXT: [[RES2:%.*]] = load ptr, ptr [[OBJ2]], align 8
560 ; INSTCOMBINE-NEXT: br label [[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]]
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
598 bb2: ; preds = %entry
599 %res2 = load ptr, ptr %obj2, align 8
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