[SCCP] Don't mark ranges from branch conditions as potentially undef
authorNikita Popov <npopov@redhat.com>
Mon, 30 May 2022 13:05:04 +0000 (15:05 +0200)
committerNikita Popov <npopov@redhat.com>
Tue, 7 Jun 2022 08:20:24 +0000 (10:20 +0200)
Now that transforms introducing branch on poison have been removed,
we can stop marking ranges that have been derived from branch
conditions as containing undef. The existing comment explains why
this is legal. I've checked that alive2 is happy with SCCP tests
after this change.

Differential Revision: https://reviews.llvm.org/D126647

llvm/lib/Transforms/Utils/SCCPSolver.cpp
llvm/test/Transforms/SCCP/conditions-ranges.ll
llvm/test/Transforms/SCCP/ip-ranges-sext.ll
llvm/test/Transforms/SCCP/replace-dereferenceable-ptr-with-undereferenceable.ll

index a9fe37f..1ffa518 100644 (file)
@@ -1295,17 +1295,6 @@ void SCCPInstVisitor::handleCallResult(CallBase &CB) {
         return;
       }
 
-      // TODO: Actually filp MayIncludeUndef for the created range to false,
-      // once most places in the optimizer respect the branches on
-      // undef/poison are UB rule. The reason why the new range cannot be
-      // undef is as follows below:
-      // The new range is based on a branch condition. That guarantees that
-      // neither of the compare operands can be undef in the branch targets,
-      // unless we have conditions that are always true/false (e.g. icmp ule
-      // i32, %a, i32_max). For the latter overdefined/empty range will be
-      // inferred, but the branch will get folded accordingly anyways.
-      bool MayIncludeUndef = !isa<PredicateAssume>(PI);
-
       ValueLatticeElement CondVal = getValueState(OtherOp);
       ValueLatticeElement &IV = ValueState[&CB];
       if (CondVal.isConstantRange() || CopyOfVal.isConstantRange()) {
@@ -1330,9 +1319,15 @@ void SCCPInstVisitor::handleCallResult(CallBase &CB) {
         if (!CopyOfCR.contains(NewCR) && CopyOfCR.getSingleMissingElement())
           NewCR = CopyOfCR;
 
+        // The new range is based on a branch condition. That guarantees that
+        // neither of the compare operands can be undef in the branch targets,
+        // unless we have conditions that are always true/false (e.g. icmp ule
+        // i32, %a, i32_max). For the latter overdefined/empty range will be
+        // inferred, but the branch will get folded accordingly anyways.
         addAdditionalUser(OtherOp, &CB);
-        mergeInValue(IV, &CB,
-                     ValueLatticeElement::getRange(NewCR, MayIncludeUndef));
+        mergeInValue(
+            IV, &CB,
+            ValueLatticeElement::getRange(NewCR, /*MayIncludeUndef*/ false));
         return;
       } else if (Pred == CmpInst::ICMP_EQ && CondVal.isConstant()) {
         // For non-integer values or integer constant expressions, only
@@ -1340,8 +1335,7 @@ void SCCPInstVisitor::handleCallResult(CallBase &CB) {
         addAdditionalUser(OtherOp, &CB);
         mergeInValue(IV, &CB, CondVal);
         return;
-      } else if (Pred == CmpInst::ICMP_NE && CondVal.isConstant() &&
-                 !MayIncludeUndef) {
+      } else if (Pred == CmpInst::ICMP_NE && CondVal.isConstant()) {
         // Propagate inequalities.
         addAdditionalUser(OtherOp, &CB);
         mergeInValue(IV, &CB,
index 519724c..9c63b7c 100644 (file)
@@ -85,7 +85,6 @@ false: ;%b in [0, 276)
   ret void
 }
 
-; TODO: Use information %a != 0 in false branch.
 define void @f2_ptr(i8* %a, i8* %b) {
 ; CHECK-LABEL: @f2_ptr(
 ; CHECK-NEXT:  entry:
@@ -98,10 +97,8 @@ define void @f2_ptr(i8* %a, i8* %b) {
 ; CHECK-NEXT:    call void @use(i1 [[C_1]])
 ; CHECK-NEXT:    ret void
 ; CHECK:       false:
-; CHECK-NEXT:    [[F_2:%.*]] = icmp eq i8* [[A]], null
-; CHECK-NEXT:    call void @use(i1 [[F_2]])
-; CHECK-NEXT:    [[T_2:%.*]] = icmp ne i8* [[A]], null
-; CHECK-NEXT:    call void @use(i1 [[T_2]])
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    [[C_2:%.*]] = icmp eq i8* [[A]], [[B]]
 ; CHECK-NEXT:    call void @use(i1 [[C_2]])
 ; CHECK-NEXT:    ret void
index e76490b..6fa74b3 100644 (file)
@@ -6,7 +6,7 @@ define i64 @test1(i32 %x) {
 ; CHECK-NEXT:    [[C:%.*]] = icmp sgt i32 [[X:%.*]], 0
 ; CHECK-NEXT:    br i1 [[C]], label [[TRUE:%.*]], label [[FALSE:%.*]]
 ; CHECK:       true:
-; CHECK-NEXT:    [[EXT_1:%.*]] = sext i32 [[X]] to i64
+; CHECK-NEXT:    [[EXT_1:%.*]] = zext i32 [[X]] to i64
 ; CHECK-NEXT:    ret i64 [[EXT_1]]
 ; CHECK:       false:
 ; CHECK-NEXT:    [[EXT_2:%.*]] = sext i32 [[X]] to i64
@@ -29,7 +29,7 @@ define i64 @test2(i32 %x) {
 ; CHECK-NEXT:    [[C:%.*]] = icmp sge i32 [[X:%.*]], 0
 ; CHECK-NEXT:    br i1 [[C]], label [[TRUE:%.*]], label [[FALSE:%.*]]
 ; CHECK:       true:
-; CHECK-NEXT:    [[EXT_1:%.*]] = sext i32 [[X]] to i64
+; CHECK-NEXT:    [[EXT_1:%.*]] = zext i32 [[X]] to i64
 ; CHECK-NEXT:    ret i64 [[EXT_1]]
 ; CHECK:       false:
 ; CHECK-NEXT:    [[EXT_2:%.*]] = sext i32 [[X]] to i64
@@ -105,8 +105,8 @@ exit:
 define i64 @test5(i32 %x) {
 ; CHECK-LABEL: @test5(
 ; CHECK-NEXT:    [[P:%.*]] = and i32 [[X:%.*]], 15
-; CHECK-NEXT:    [[TMP1:%.*]] = zext i32 [[P]] to i64
-; CHECK-NEXT:    ret i64 [[TMP1]]
+; CHECK-NEXT:    [[EXT:%.*]] = zext i32 [[P]] to i64
+; CHECK-NEXT:    ret i64 [[EXT]]
 ;
   %p = and i32 %x, 15
   %ext = sext i32 %p to i64
@@ -126,8 +126,8 @@ define i64 @test6(i32 %x) {
 define i64 @test7(i16 %x) {
 ; CHECK-LABEL: @test7(
 ; CHECK-NEXT:    [[P:%.*]] = and i16 [[X:%.*]], 15
-; CHECK-NEXT:    [[TMP1:%.*]] = zext i16 [[P]] to i32
-; CHECK-NEXT:    [[EXT_2:%.*]] = sext i32 [[TMP1]] to i64
+; CHECK-NEXT:    [[EXT_1:%.*]] = zext i16 [[P]] to i32
+; CHECK-NEXT:    [[EXT_2:%.*]] = sext i32 [[EXT_1]] to i64
 ; CHECK-NEXT:    ret i64 [[EXT_2]]
 ;
   %p = and i16 %x, 15
index 0a894c0..b887e78 100644 (file)
@@ -68,8 +68,7 @@ define i1 @eq_undereferenceable_cmp_simp(i32* %p) {
 ; CHECK-NEXT:    store i32 2, i32* getelementptr inbounds ([1 x i32], [1 x i32]* @x, i64 1, i64 0), align 4
 ; CHECK-NEXT:    ret i1 true
 ; CHECK:       if.end:
-; CHECK-NEXT:    [[CMP_2:%.*]] = icmp eq i32* [[P]], getelementptr inbounds ([1 x i32], [1 x i32]* @x, i64 1, i64 0)
-; CHECK-NEXT:    ret i1 [[CMP_2]]
+; CHECK-NEXT:    ret i1 false
 ;
 entry:
   %cmp.0 = icmp eq i32* %p, getelementptr inbounds (i32, i32* getelementptr inbounds ([1 x i32], [1 x i32]* @x, i64 0, i64 0), i64 1)