@@ -309,3 +309,143 @@ if.then.y:
309309exit:
310310 ret i1 %cmp.y
311311}
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