@@ -309,3 +309,143 @@ if.then.y:
309
309
exit:
310
310
ret i1 %cmp.y
311
311
}
312
+
313
+ declare void @foo ()
314
+ declare void @bar () #1
315
+
316
+ ; Test that two if-regions are not merged when there's potential aliasing
317
+ ; between a store in the first if-region and a load in the second if-region's header
318
+ define i32 @test_alias (i32 %a , i32 %b , ptr %p1 , ptr %p2 ) {
319
+ ; CHECK-LABEL: define i32 @test_alias
320
+ ; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], ptr [[P1:%.*]], ptr [[P2:%.*]]) {
321
+ ; CHECK-NEXT: entry:
322
+ ; CHECK-NEXT: store i32 42, ptr [[P1]], align 4
323
+ ; CHECK-NEXT: [[COND1:%.*]] = icmp eq i32 [[A]], 0
324
+ ; CHECK-NEXT: br i1 [[COND1]], label [[IF_THEN1:%.*]], label [[IF_END1:%.*]]
325
+ ; CHECK: if.then1:
326
+ ; CHECK-NEXT: store i32 100, ptr [[P2]], align 4
327
+ ; CHECK-NEXT: br label [[IF_END1]]
328
+ ; CHECK: if.end1:
329
+ ; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[P1]], align 4
330
+ ; CHECK-NEXT: [[COND2:%.*]] = icmp eq i32 [[B]], 0
331
+ ; CHECK-NEXT: br i1 [[COND2]], label [[IF_THEN2:%.*]], label [[IF_END2:%.*]]
332
+ ; CHECK: if.then2:
333
+ ; CHECK-NEXT: store i32 100, ptr [[P2]], align 4
334
+ ; CHECK-NEXT: br label [[IF_END2]]
335
+ ; CHECK: if.end2:
336
+ ; CHECK-NEXT: ret i32 0
337
+ ;
338
+ entry:
339
+ store i32 42 , ptr %p1
340
+ %cond1 = icmp eq i32 %a , 0
341
+ br i1 %cond1 , label %if.then1 , label %if.end1
342
+
343
+ if.then1:
344
+ store i32 100 , ptr %p2 ; May alias with the load below
345
+ br label %if.end1
346
+
347
+ if.end1:
348
+ %val = load i32 , ptr %p1 ; This load prevents merging due to potential alias
349
+ %cond2 = icmp eq i32 %b , 0
350
+ br i1 %cond2 , label %if.then2 , label %if.end2
351
+
352
+ if.then2:
353
+ store i32 100 , ptr %p2
354
+ br label %if.end2
355
+
356
+ if.end2:
357
+ ret i32 0
358
+ }
359
+
360
+ ; Test that two if-regions are not merged when there's potential aliasing
361
+ ; between a store in the first if-region and a function call in the second if-region's header
362
+ define i32 @test_alias_2 (i32 %a , i32 %b ) {
363
+ ; CHECK-LABEL: define i32 @test_alias_2
364
+ ; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {
365
+ ; CHECK-NEXT: entry:
366
+ ; CHECK-NEXT: [[P:%.*]] = alloca i32, align 4
367
+ ; CHECK-NEXT: store i32 42, ptr [[P]], align 4
368
+ ; CHECK-NEXT: [[COND1:%.*]] = icmp eq i32 [[A]], 0
369
+ ; CHECK-NEXT: br i1 [[COND1]], label [[IF_THEN1:%.*]], label [[IF_END1:%.*]]
370
+ ; CHECK: if.then1:
371
+ ; CHECK-NEXT: store i32 100, ptr @g, align 4
372
+ ; CHECK-NEXT: br label [[IF_END1]]
373
+ ; CHECK: if.end1:
374
+ ; CHECK-NEXT: call void @foo()
375
+ ; CHECK-NEXT: [[COND2:%.*]] = icmp eq i32 [[B]], 0
376
+ ; CHECK-NEXT: br i1 [[COND2]], label [[IF_THEN2:%.*]], label [[IF_END2:%.*]]
377
+ ; CHECK: if.then2:
378
+ ; CHECK-NEXT: store i32 100, ptr @g, align 4
379
+ ; CHECK-NEXT: br label [[IF_END2]]
380
+ ; CHECK: if.end2:
381
+ ; CHECK-NEXT: ret i32 0
382
+ ;
383
+ entry:
384
+ %p = alloca i32
385
+ store i32 42 , ptr %p
386
+ %cond1 = icmp eq i32 %a , 0
387
+ br i1 %cond1 , label %if.then1 , label %if.end1
388
+
389
+ if.then1:
390
+ store i32 100 , ptr @g
391
+ br label %if.end1
392
+
393
+ if.end1:
394
+ call void @foo ()
395
+ %cond2 = icmp eq i32 %b , 0
396
+ br i1 %cond2 , label %if.then2 , label %if.end2
397
+
398
+ if.then2:
399
+ store i32 100 , ptr @g
400
+ br label %if.end2
401
+
402
+ if.end2:
403
+ ret i32 0
404
+ }
405
+
406
+ ; Test that two if-regions are merged when there's no potential aliasing
407
+ ; between a store in the first if-region and a load in the second if-region's header
408
+ define i32 @test_no_alias (i32 %a , i32 %b ) {
409
+ ; CHECK-LABEL: define i32 @test_no_alias
410
+ ; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {
411
+ ; CHECK-NEXT: entry:
412
+ ; CHECK-NEXT: [[P:%.*]] = alloca i32, align 4
413
+ ; CHECK-NEXT: store i32 42, ptr [[P]], align 4
414
+ ; CHECK-NEXT: [[COND1:%.*]] = icmp eq i32 [[A]], 0
415
+ ; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr @g, align 4
416
+ ; CHECK-NEXT: [[COND2:%.*]] = icmp eq i32 [[B]], 0
417
+ ; CHECK-NEXT: [[TMP0:%.*]] = or i1 [[COND1]], [[COND2]]
418
+ ; CHECK-NEXT: br i1 [[TMP0]], label [[IF_THEN2:%.*]], label [[IF_END2:%.*]]
419
+ ; CHECK: if.then2:
420
+ ; CHECK-NEXT: store i32 100, ptr [[P]], align 4
421
+ ; CHECK-NEXT: call void @bar()
422
+ ; CHECK-NEXT: br label [[IF_END2]]
423
+ ; CHECK: if.end2:
424
+ ; CHECK-NEXT: ret i32 0
425
+ ;
426
+ entry:
427
+ %p = alloca i32
428
+ store i32 42 , ptr %p
429
+ %cond1 = icmp eq i32 %a , 0
430
+ br i1 %cond1 , label %if.then1 , label %if.end1
431
+
432
+ if.then1:
433
+ store i32 100 , ptr %p ; No alias with the load below
434
+ call void @bar () ; No alias with the load below since it's a pure function
435
+ br label %if.end1
436
+
437
+ if.end1:
438
+ %val = load i32 , ptr @g
439
+ %cond2 = icmp eq i32 %b , 0
440
+ br i1 %cond2 , label %if.then2 , label %if.end2
441
+
442
+ if.then2:
443
+ store i32 100 , ptr %p
444
+ call void @bar ()
445
+ br label %if.end2
446
+
447
+ if.end2:
448
+ ret i32 0
449
+ }
450
+
451
+ attributes #1 = { readnone willreturn nounwind }
0 commit comments