-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[InstCombine] Intersect nowrap flags between geps while folding into phi #115901
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[InstCombine] Intersect nowrap flags between geps while folding into phi #115901
Conversation
|
@llvm/pr-subscribers-llvm-transforms @llvm/pr-subscribers-debuginfo Author: Antonio Frighetto (antoniofrighetto) ChangesA miscompilation issue has been addressed with refined checking. Fixes: #115149. Full diff: https://github.com/llvm/llvm-project/pull/115901.diff 8 Files Affected:
diff --git a/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp b/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp
index cb5c4473051262..44154193038ac2 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp
@@ -554,6 +554,11 @@ Instruction *InstCombinerImpl::foldPHIArgGEPIntoPHI(PHINode &PN) {
GEP->getSourceElementType() != FirstInst->getSourceElementType() ||
GEP->getNumOperands() != FirstInst->getNumOperands())
return nullptr;
+ // The resulting pointer from the phi-node may compute poison, if a
+ // getelementptr phi-operand carries inbounds semantics. Assume that the
+ // resulting phi-node is non-poison in order to perform the simplification.
+ if (!isGuaranteedNotToBeUndefOrPoison(V))
+ return nullptr;
NW &= GEP->getNoWrapFlags();
diff --git a/llvm/test/DebugInfo/Generic/instcombine-phi.ll b/llvm/test/DebugInfo/Generic/instcombine-phi.ll
index 08f7bc07118084..ee4e6c96ec5236 100644
--- a/llvm/test/DebugInfo/Generic/instcombine-phi.ll
+++ b/llvm/test/DebugInfo/Generic/instcombine-phi.ll
@@ -105,8 +105,7 @@ if.end: ; preds = %if.else, %if.then
; CHECK: define ptr @gep
; CHECK-LABEL: if.end:
-; CHECK: %[[PHI:.*]] = phi i64 [ %call, %if.then ], [ %call1, %if.else ]
-; CHECK: getelementptr inbounds i32, ptr %b, i64 %[[PHI]], !dbg [[gepMergedLoc:![0-9]+]]
+; CHECK: %[[PHI:.*]] = phi ptr [ %arrayidx, %if.then ], [ %arrayidx2, %if.else ]
; CHECK: ret ptr
define ptr @gep(i32 %a, ptr %b) !dbg !23 {
@@ -300,7 +299,6 @@ declare ptr @bar3()
; CHECK: [[binopMergedLoc]] = !DILocation(line: 0
; CHECK: [[cmpMergedLoc]] = !DILocation(line: 0
-; CHECK: [[gepMergedLoc]] = !DILocation(line: 0
; CHECK: [[loadMergedLoc]] = !DILocation(line: 0
; CHECK: [[castMergedLoc]] = !DILocation(line: 0
; CHECK: [[binopConstMergedLoc]] = !DILocation(line: 0
diff --git a/llvm/test/Transforms/InstCombine/gepphigep.ll b/llvm/test/Transforms/InstCombine/gepphigep.ll
index 93266c67543963..7175111c4cdca1 100644
--- a/llvm/test/Transforms/InstCombine/gepphigep.ll
+++ b/llvm/test/Transforms/InstCombine/gepphigep.ll
@@ -86,12 +86,12 @@ define i32 @test3(ptr %dm, i1 %tmp4, i64 %tmp9, i64 %tmp19, i64 %tmp20, i64 %tmp
; CHECK: bb3:
; CHECK-NEXT: [[TMP0:%.*]] = phi i64 [ [[TMP19]], [[BB1]] ], [ [[TMP20]], [[BB2]] ]
; CHECK-NEXT: [[TMP22:%.*]] = invoke i32 @foo1(i32 11)
-; CHECK-NEXT: to label [[BB4:%.*]] unwind label [[BB5:%.*]]
+; CHECK-NEXT: to label [[BB4:%.*]] unwind label [[BB5:%.*]]
; CHECK: bb4:
; CHECK-NEXT: ret i32 0
; CHECK: bb5:
; CHECK-NEXT: [[TMP27:%.*]] = landingpad { ptr, i32 }
-; CHECK-NEXT: catch ptr @_ZTIi
+; CHECK-NEXT: catch ptr @_ZTIi
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT3]], ptr [[DM]], i64 [[TMP0]], i32 1
; CHECK-NEXT: [[TMP35:%.*]] = getelementptr inbounds [[STRUCT4:%.*]], ptr [[TMP1]], i64 [[TMP21:%.*]], i32 1, i32 1
; CHECK-NEXT: [[TMP25:%.*]] = load i32, ptr [[TMP35]], align 4
@@ -140,18 +140,19 @@ define ptr @test4(i32 %value, ptr %buffer) {
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[VALUE:%.*]], 127
; CHECK-NEXT: br i1 [[CMP]], label [[LOOP_HEADER:%.*]], label [[EXIT:%.*]]
; CHECK: loop.header:
+; CHECK-NEXT: [[BUFFER:%.*]] = getelementptr inbounds i8, ptr [[BUFFER1:%.*]], i64 1
; CHECK-NEXT: br label [[LOOP_BODY:%.*]]
; CHECK: loop.body:
-; CHECK-NEXT: [[BUFFER_PN:%.*]] = phi ptr [ [[BUFFER:%.*]], [[LOOP_HEADER]] ], [ [[LOOPPTR:%.*]], [[LOOP_BODY]] ]
+; CHECK-NEXT: [[BUFFER_PN:%.*]] = phi ptr [ [[BUFFER]], [[LOOP_HEADER]] ], [ [[LOOPPTR:%.*]], [[LOOP_BODY]] ]
; CHECK-NEXT: [[NEWVAL:%.*]] = phi i32 [ [[VALUE]], [[LOOP_HEADER]] ], [ [[SHR:%.*]], [[LOOP_BODY]] ]
-; CHECK-NEXT: [[LOOPPTR]] = getelementptr inbounds i8, ptr [[BUFFER_PN]], i64 1
; CHECK-NEXT: [[SHR]] = lshr i32 [[NEWVAL]], 7
+; CHECK-NEXT: [[LOOPPTR]] = getelementptr inbounds i8, ptr [[BUFFER_PN]], i64 1
; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i32 [[NEWVAL]], 16383
; CHECK-NEXT: br i1 [[CMP2]], label [[LOOP_BODY]], label [[LOOP_EXIT:%.*]]
; CHECK: loop.exit:
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
-; CHECK-NEXT: [[TMP0:%.*]] = phi ptr [ [[LOOPPTR]], [[LOOP_EXIT]] ], [ [[BUFFER]], [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[TMP0:%.*]] = phi ptr [ [[BUFFER_PN]], [[LOOP_EXIT]] ], [ [[BUFFER1]], [[ENTRY:%.*]] ]
; CHECK-NEXT: [[INCPTR3:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 2
; CHECK-NEXT: ret ptr [[INCPTR3]]
;
diff --git a/llvm/test/Transforms/InstCombine/new-inst-dbgloc-overwrite.ll b/llvm/test/Transforms/InstCombine/new-inst-dbgloc-overwrite.ll
index 2b933a2f9e0756..2084eb623a66f7 100644
--- a/llvm/test/Transforms/InstCombine/new-inst-dbgloc-overwrite.ll
+++ b/llvm/test/Transforms/InstCombine/new-inst-dbgloc-overwrite.ll
@@ -14,13 +14,14 @@ define void @test(ptr %xfA, ptr %xfB, i1 %cmp5) {
; CHECK-NEXT: entry:
; CHECK-NEXT: br i1 [[CMP5:%.*]], label [[IF_ELSE:%.*]], label [[IF_THEN6:%.*]]
; CHECK: if.then6:
+; CHECK-NEXT: [[XFB:%.*]] = getelementptr i8, ptr [[XFB1:%.*]], i64 4
; CHECK-NEXT: br label [[IF_END11:%.*]]
; CHECK: if.else:
+; CHECK-NEXT: [[XFA:%.*]] = getelementptr i8, ptr [[XFA1:%.*]], i64 4
; CHECK-NEXT: br label [[IF_END11]]
; CHECK: if.end11:
-; CHECK-NEXT: [[XFA_PN:%.*]] = phi ptr [ [[XFA:%.*]], [[IF_ELSE]] ], [ [[XFB:%.*]], [[IF_THEN6]] ]
-; CHECK-NEXT: [[XF1_SROA_8_0_IN:%.*]] = getelementptr i8, ptr [[XFA_PN]], i64 4
-; CHECK-NEXT: [[XF1_SROA_8_0:%.*]] = load float, ptr [[XF1_SROA_8_0_IN]], align 4, !dbg [[DBG3:![0-9]+]], !annotation [[META7:![0-9]+]]
+; CHECK-NEXT: [[XFA_PN:%.*]] = phi ptr [ [[XFA]], [[IF_ELSE]] ], [ [[XFB]], [[IF_THEN6]] ]
+; CHECK-NEXT: [[XF1_SROA_8_0:%.*]] = load float, ptr [[XFA_PN]], align 4, !dbg [[DBG3:![0-9]+]], !annotation [[META7:![0-9]+]]
; CHECK-NEXT: [[CMP_I:%.*]] = fcmp ugt float [[XF1_SROA_8_0]], 0.000000e+00
; CHECK-NEXT: br i1 [[CMP_I]], label [[IF_END_I:%.*]], label [[IF_THEN_I:%.*]]
; CHECK: if.then.i:
diff --git a/llvm/test/Transforms/InstCombine/opaque-ptr.ll b/llvm/test/Transforms/InstCombine/opaque-ptr.ll
index a52a07389baee2..761fb6c89553d7 100644
--- a/llvm/test/Transforms/InstCombine/opaque-ptr.ll
+++ b/llvm/test/Transforms/InstCombine/opaque-ptr.ll
@@ -519,11 +519,13 @@ define ptr @phi_of_gep(i1 %c, ptr %p) {
; CHECK-LABEL: @phi_of_gep(
; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
; CHECK: if:
+; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 4
; CHECK-NEXT: br label [[JOIN:%.*]]
; CHECK: else:
+; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i8, ptr [[P]], i64 4
; CHECK-NEXT: br label [[JOIN]]
; CHECK: join:
-; CHECK-NEXT: [[PHI:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 4
+; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[GEP1]], [[IF]] ], [ [[GEP2]], [[ELSE]] ]
; CHECK-NEXT: ret ptr [[PHI]]
;
br i1 %c, label %if, label %else
@@ -545,11 +547,13 @@ define ptr @phi_of_gep_flags_1(i1 %c, ptr %p) {
; CHECK-LABEL: @phi_of_gep_flags_1(
; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
; CHECK: if:
+; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 4
; CHECK-NEXT: br label [[JOIN:%.*]]
; CHECK: else:
+; CHECK-NEXT: [[GEP2:%.*]] = getelementptr nusw nuw i8, ptr [[P]], i64 4
; CHECK-NEXT: br label [[JOIN]]
; CHECK: join:
-; CHECK-NEXT: [[PHI:%.*]] = getelementptr nusw nuw i8, ptr [[P:%.*]], i64 4
+; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[GEP1]], [[IF]] ], [ [[GEP2]], [[ELSE]] ]
; CHECK-NEXT: ret ptr [[PHI]]
;
br i1 %c, label %if, label %else
@@ -571,11 +575,13 @@ define ptr @phi_of_gep_flags_2(i1 %c, ptr %p) {
; CHECK-LABEL: @phi_of_gep_flags_2(
; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
; CHECK: if:
+; CHECK-NEXT: [[GEP1:%.*]] = getelementptr nusw nuw i8, ptr [[P:%.*]], i64 4
; CHECK-NEXT: br label [[JOIN:%.*]]
; CHECK: else:
+; CHECK-NEXT: [[GEP2:%.*]] = getelementptr nuw i8, ptr [[P]], i64 4
; CHECK-NEXT: br label [[JOIN]]
; CHECK: join:
-; CHECK-NEXT: [[PHI:%.*]] = getelementptr nuw i8, ptr [[P:%.*]], i64 4
+; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[GEP1]], [[IF]] ], [ [[GEP2]], [[ELSE]] ]
; CHECK-NEXT: ret ptr [[PHI]]
;
br i1 %c, label %if, label %else
diff --git a/llvm/test/Transforms/InstCombine/phi-equal-incoming-pointers.ll b/llvm/test/Transforms/InstCombine/phi-equal-incoming-pointers.ll
index 998169ec2fe26f..4d8178b528c636 100644
--- a/llvm/test/Transforms/InstCombine/phi-equal-incoming-pointers.ll
+++ b/llvm/test/Transforms/InstCombine/phi-equal-incoming-pointers.ll
@@ -15,11 +15,13 @@ define i32 @test_gep_and_bitcast(i1 %cond, i1 %cond2) {
; ALL-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i8()
; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
; ALL: bb1:
+; ALL-NEXT: [[PTR1:%.*]] = getelementptr inbounds i8, ptr [[OBJ]], i64 16
; ALL-NEXT: br label [[EXIT:%.*]]
; ALL: bb2:
+; ALL-NEXT: [[PTR2:%.*]] = getelementptr inbounds i8, ptr [[OBJ]], i64 16
; ALL-NEXT: br label [[EXIT]]
; ALL: exit:
-; ALL-NEXT: [[PTR_TYPED:%.*]] = getelementptr inbounds i8, ptr [[OBJ]], i64 16
+; ALL-NEXT: [[PTR_TYPED:%.*]] = phi ptr [ [[PTR1]], [[BB1]] ], [ [[PTR2]], [[BB2]] ]
; ALL-NEXT: [[RES_PHI:%.*]] = load i32, ptr [[PTR_TYPED]], align 4
; ALL-NEXT: store i32 1, ptr [[PTR_TYPED]], align 4
; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
@@ -53,11 +55,13 @@ define i32 @test_gep_and_bitcast_arg(ptr %obj, i1 %cond, i1 %cond2) {
; ALL-NEXT: entry:
; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
; ALL: bb1:
+; ALL-NEXT: [[PTR1:%.*]] = getelementptr inbounds i8, ptr [[OBJ:%.*]], i64 16
; ALL-NEXT: br label [[EXIT:%.*]]
; ALL: bb2:
+; ALL-NEXT: [[PTR2:%.*]] = getelementptr inbounds i8, ptr [[OBJ]], i64 16
; ALL-NEXT: br label [[EXIT]]
; ALL: exit:
-; ALL-NEXT: [[PTR_TYPED:%.*]] = getelementptr inbounds i8, ptr [[OBJ:%.*]], i64 16
+; ALL-NEXT: [[PTR_TYPED:%.*]] = phi ptr [ [[PTR1]], [[BB1]] ], [ [[PTR2]], [[BB2]] ]
; ALL-NEXT: [[RES_PHI:%.*]] = load i32, ptr [[PTR_TYPED]], align 4
; ALL-NEXT: store i32 1, ptr [[PTR_TYPED]], align 4
; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
@@ -101,11 +105,13 @@ define i32 @test_gep_and_bitcast_phi(i1 %cond, i1 %cond2, i1 %cond3) {
; ALL-NEXT: call void @foo.i8(ptr [[ANOTHER_PHI]])
; ALL-NEXT: br i1 [[COND2:%.*]], label [[BB3:%.*]], label [[BB4:%.*]]
; ALL: bb3:
+; ALL-NEXT: [[PTR1:%.*]] = getelementptr inbounds i8, ptr [[OBJ]], i64 16
; ALL-NEXT: br label [[EXIT:%.*]]
; ALL: bb4:
+; ALL-NEXT: [[PTR2:%.*]] = getelementptr inbounds i8, ptr [[OBJ]], i64 16
; ALL-NEXT: br label [[EXIT]]
; ALL: exit:
-; ALL-NEXT: [[PTR_TYPED:%.*]] = getelementptr inbounds i8, ptr [[OBJ]], i64 16
+; ALL-NEXT: [[PTR_TYPED:%.*]] = phi ptr [ [[PTR1]], [[BB3]] ], [ [[PTR2]], [[BB4]] ]
; ALL-NEXT: [[RES_PHI:%.*]] = load i32, ptr [[PTR_TYPED]], align 4
; ALL-NEXT: store i32 1, ptr [[PTR_TYPED]], align 4
; ALL-NEXT: [[RES:%.*]] = select i1 [[COND3:%.*]], i32 [[RES_PHI]], i32 1
@@ -153,11 +159,13 @@ define i32 @test_gep_i32ptr(i1 %cond, i1 %cond2) {
; ALL-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i32()
; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
; ALL: bb1:
+; ALL-NEXT: [[PTR1_TYPED:%.*]] = getelementptr inbounds i8, ptr [[OBJ]], i64 64
; ALL-NEXT: br label [[EXIT:%.*]]
; ALL: bb2:
+; ALL-NEXT: [[PTR2_TYPED:%.*]] = getelementptr inbounds i8, ptr [[OBJ]], i64 64
; ALL-NEXT: br label [[EXIT]]
; ALL: exit:
-; ALL-NEXT: [[PTR_TYPED:%.*]] = getelementptr inbounds i8, ptr [[OBJ]], i64 64
+; ALL-NEXT: [[PTR_TYPED:%.*]] = phi ptr [ [[PTR1_TYPED]], [[BB1]] ], [ [[PTR2_TYPED]], [[BB2]] ]
; ALL-NEXT: [[RES_PHI:%.*]] = load i32, ptr [[PTR_TYPED]], align 4
; ALL-NEXT: store i32 1, ptr [[PTR_TYPED]], align 4
; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
@@ -192,11 +200,13 @@ define i32 @test_gep_and_bitcast_gep_base_ptr(i1 %cond, i1 %cond2) {
; ALL-NEXT: [[OBJ0:%.*]] = call ptr @get_ptr.i8()
; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
; ALL: bb1:
+; ALL-NEXT: [[PTR1:%.*]] = getelementptr inbounds i8, ptr [[OBJ0]], i64 32
; ALL-NEXT: br label [[EXIT:%.*]]
; ALL: bb2:
+; ALL-NEXT: [[PTR2:%.*]] = getelementptr inbounds i8, ptr [[OBJ0]], i64 32
; ALL-NEXT: br label [[EXIT]]
; ALL: exit:
-; ALL-NEXT: [[PTR_TYPED:%.*]] = getelementptr inbounds i8, ptr [[OBJ0]], i64 32
+; ALL-NEXT: [[PTR_TYPED:%.*]] = phi ptr [ [[PTR1]], [[BB1]] ], [ [[PTR2]], [[BB2]] ]
; ALL-NEXT: [[RES_PHI:%.*]] = load i32, ptr [[PTR_TYPED]], align 4
; ALL-NEXT: store i32 1, ptr [[PTR_TYPED]], align 4
; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
@@ -227,18 +237,33 @@ exit:
}
define i32 @test_gep_and_bitcast_same_bb(i1 %cond, i1 %cond2) {
-; ALL-LABEL: @test_gep_and_bitcast_same_bb(
-; ALL-NEXT: entry:
-; ALL-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i8()
-; ALL-NEXT: br i1 [[COND:%.*]], label [[EXIT:%.*]], label [[BB2:%.*]]
-; ALL: bb2:
-; ALL-NEXT: br label [[EXIT]]
-; ALL: exit:
-; ALL-NEXT: [[PTR_TYPED:%.*]] = getelementptr inbounds i8, ptr [[OBJ]], i64 16
-; ALL-NEXT: [[RES_PHI:%.*]] = load i32, ptr [[PTR_TYPED]], align 4
-; ALL-NEXT: store i32 1, ptr [[PTR_TYPED]], align 4
-; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
-; ALL-NEXT: ret i32 [[RES]]
+; INSTCOMBINE-LABEL: @test_gep_and_bitcast_same_bb(
+; INSTCOMBINE-NEXT: entry:
+; INSTCOMBINE-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i8()
+; INSTCOMBINE-NEXT: [[PTR1:%.*]] = getelementptr inbounds i8, ptr [[OBJ]], i64 16
+; INSTCOMBINE-NEXT: br i1 [[COND:%.*]], label [[EXIT:%.*]], label [[BB2:%.*]]
+; INSTCOMBINE: bb2:
+; INSTCOMBINE-NEXT: [[PTR2:%.*]] = getelementptr inbounds i8, ptr [[OBJ]], i64 16
+; INSTCOMBINE-NEXT: br label [[EXIT]]
+; INSTCOMBINE: exit:
+; INSTCOMBINE-NEXT: [[PTR_TYPED:%.*]] = phi ptr [ [[PTR1]], [[ENTRY:%.*]] ], [ [[PTR2]], [[BB2]] ]
+; INSTCOMBINE-NEXT: [[RES_PHI:%.*]] = load i32, ptr [[PTR_TYPED]], align 4
+; INSTCOMBINE-NEXT: store i32 1, ptr [[PTR_TYPED]], align 4
+; INSTCOMBINE-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
+; INSTCOMBINE-NEXT: ret i32 [[RES]]
+;
+; INSTCOMBINEGVN-LABEL: @test_gep_and_bitcast_same_bb(
+; INSTCOMBINEGVN-NEXT: entry:
+; INSTCOMBINEGVN-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i8()
+; INSTCOMBINEGVN-NEXT: [[PTR1:%.*]] = getelementptr inbounds i8, ptr [[OBJ]], i64 16
+; INSTCOMBINEGVN-NEXT: br i1 [[COND:%.*]], label [[EXIT:%.*]], label [[BB2:%.*]]
+; INSTCOMBINEGVN: bb2:
+; INSTCOMBINEGVN-NEXT: br label [[EXIT]]
+; INSTCOMBINEGVN: exit:
+; INSTCOMBINEGVN-NEXT: [[RES_PHI:%.*]] = load i32, ptr [[PTR1]], align 4
+; INSTCOMBINEGVN-NEXT: store i32 1, ptr [[PTR1]], align 4
+; INSTCOMBINEGVN-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
+; INSTCOMBINEGVN-NEXT: ret i32 [[RES]]
;
entry:
%obj = call ptr @get_ptr.i8()
@@ -318,11 +343,13 @@ define i8 @test_gep(i1 %cond, i1 %cond2) {
; ALL-NEXT: [[OBJ:%.*]] = call ptr @get_ptr.i8()
; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
; ALL: bb1:
+; ALL-NEXT: [[PTR1:%.*]] = getelementptr inbounds i8, ptr [[OBJ]], i64 16
; ALL-NEXT: br label [[EXIT:%.*]]
; ALL: bb2:
+; ALL-NEXT: [[PTR2:%.*]] = getelementptr inbounds i8, ptr [[OBJ]], i64 16
; ALL-NEXT: br label [[EXIT]]
; ALL: exit:
-; ALL-NEXT: [[PTR_TYPED:%.*]] = getelementptr inbounds i8, ptr [[OBJ]], i64 16
+; ALL-NEXT: [[PTR_TYPED:%.*]] = phi ptr [ [[PTR1]], [[BB1]] ], [ [[PTR2]], [[BB2]] ]
; ALL-NEXT: [[RES_PHI:%.*]] = load i8, ptr [[PTR_TYPED]], align 1
; ALL-NEXT: store i8 1, ptr [[PTR_TYPED]], align 1
; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i8 [[RES_PHI]], i8 1
diff --git a/llvm/test/Transforms/InstCombine/phi.ll b/llvm/test/Transforms/InstCombine/phi.ll
index 4e90a8f0ba4313..57a8afa76159ec 100644
--- a/llvm/test/Transforms/InstCombine/phi.ll
+++ b/llvm/test/Transforms/InstCombine/phi.ll
@@ -250,11 +250,13 @@ Exit: ; preds = %Loop
define ptr @test8(ptr %A, i1 %b) {
; CHECK-LABEL: @test8(
; CHECK-NEXT: BB0:
+; CHECK-NEXT: [[X:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i64 4
; CHECK-NEXT: br i1 [[B:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
; CHECK: BB1:
+; CHECK-NEXT: [[Y:%.*]] = getelementptr i8, ptr [[A]], i64 4
; CHECK-NEXT: br label [[BB2]]
; CHECK: BB2:
-; CHECK-NEXT: [[C:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 4
+; CHECK-NEXT: [[C:%.*]] = phi ptr [ [[X]], [[BB0:%.*]] ], [ [[Y]], [[BB1]] ]
; CHECK-NEXT: ret ptr [[C]]
;
BB0:
@@ -2794,3 +2796,32 @@ BB4: ; preds = %BB3, %BB2, %BB1, %BB
BB5: ; preds = %BB4
ret void
}
+
+define i64 @wrong_gep_arg_into_phi(ptr noundef %ptr) {
+; CHECK-LABEL: @wrong_gep_arg_into_phi(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[PTR:%.*]] = getelementptr i8, ptr [[PTR1:%.*]], i64 1
+; CHECK-NEXT: br label [[FOR_COND:%.*]]
+; CHECK: for.cond:
+; CHECK-NEXT: [[PTR_PN:%.*]] = phi ptr [ [[PTR]], [[ENTRY:%.*]] ], [ [[DOTPN:%.*]], [[FOR_COND]] ]
+; CHECK-NEXT: [[VAL:%.*]] = load i8, ptr [[PTR_PN]], align 1
+; CHECK-NEXT: [[COND_NOT:%.*]] = icmp eq i8 [[VAL]], 0
+; CHECK-NEXT: [[DOTPN]] = getelementptr inbounds nuw i8, ptr [[PTR_PN]], i64 1
+; CHECK-NEXT: br i1 [[COND_NOT]], label [[EXIT:%.*]], label [[FOR_COND]]
+; CHECK: exit:
+; CHECK-NEXT: ret i64 0
+;
+entry:
+ %add.ptr = getelementptr i8, ptr %ptr, i64 1
+ br label %for.cond
+
+for.cond: ; preds = %for.cond, %entry
+ %.pn = phi ptr [ %add.ptr, %entry ], [ %incdec.ptr, %for.cond ]
+ %val = load i8, ptr %.pn, align 1
+ %cond = icmp ne i8 %val, 0
+ %incdec.ptr = getelementptr inbounds nuw i8, ptr %.pn, i64 1
+ br i1 %cond, label %for.cond, label %exit
+
+exit: ; preds = %for.cond
+ ret i64 0
+}
diff --git a/llvm/test/Transforms/SampleProfile/pseudo-probe-instcombine.ll b/llvm/test/Transforms/SampleProfile/pseudo-probe-instcombine.ll
index d1c15306a72d08..d6883d2d9c6319 100644
--- a/llvm/test/Transforms/SampleProfile/pseudo-probe-instcombine.ll
+++ b/llvm/test/Transforms/SampleProfile/pseudo-probe-instcombine.ll
@@ -28,16 +28,18 @@ define dso_local void @merge(ptr nocapture readonly %params) local_unnamed_addr
; CHECK-NEXT: [[TOBOOL56_NOT:%.*]] = icmp eq i32 [[TMP1]], 0
; CHECK-NEXT: br i1 [[TOBOOL56_NOT]], label [[IF_END109]], label [[IF_END109_THREAD:%.*]]
; CHECK: if.end109.thread:
+; CHECK-NEXT: [[MINPART4:%.*]] = getelementptr inbounds i8, ptr [[PARAMS]], i64 172
; CHECK-NEXT: call void @llvm.pseudoprobe(i64 -6172701105289426098, i64 2, i32 0, i64 -1)
; CHECK-NEXT: br label [[IF_THEN138:%.*]]
; CHECK: if.end109:
+; CHECK-NEXT: [[MINPART:%.*]] = getelementptr inbounds i8, ptr [[PARAMS]], i64 172
; CHECK-NEXT: call void @llvm.pseudoprobe(i64 -6172701105289426098, i64 3, i32 0, i64 -1)
; CHECK-NEXT: [[TOBOOL116_NOT:%.*]] = icmp eq i32 [[TMP1]], 0
; CHECK-NEXT: br i1 [[TOBOOL116_NOT]], label [[IF_THEN117:%.*]], label [[IF_THEN138]]
; CHECK: if.then117:
; CHECK-NEXT: ret void
; CHECK: if.then138:
-; CHECK-NEXT: [[DOTIN:%.*]] = getelementptr inbounds i8, ptr [[PARAMS]], i64 172
+; CHECK-NEXT: [[DOTIN:%.*]] = phi ptr [ [[MINPART4]], [[IF_END109_THREAD]] ], [ [[MINPART]], [[IF_END109]] ]
; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTIN]], align 4
; CHECK-NEXT: [[TOBOOL139_NOT:%.*]] = icmp eq i32 [[TMP2]], 0
; CHECK-NEXT: br i1 [[TOBOOL139_NOT]], label [[IF_ELSE147:%.*]], label [[IF_THEN140:%.*]]
|
nikic
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is the right fix. As far as I can tell this is just a bug in the flag intersection, because we end up ignoring the flags on the first instruction. Would doing this fix the issue?
GEPNoWrapFlags NW = FirstInst->getNoWrapFlags()
53b1105 to
c914c25
Compare
Updated, thank you! Admittedly, I thought about intersecting flags here, but felt like dropping flags (losing inbounds in the gep) at this point might have been unfavourable for later optimizations (so thought of preventing the folding altogether was "sort of" more robust). |
nikic
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
c914c25 to
e5e171a
Compare
A miscompilation issue has been addressed with refined checking. Fixes: llvm#115149.
e5e171a to
929cbe7
Compare
|
Do we want to backport this to 19.x since it mentions introduced in 18.1? |
A miscompilation issue has been addressed with refined checking.
Fixes: #115149.