]> granicus.if.org Git - llvm/commitdiff
[CorrelatedValuePropagation] Mark subs that we know not to wrap with nuw/nsw.
authorLuqman Aden <me@luqman.ca>
Sat, 20 Apr 2019 13:14:18 +0000 (13:14 +0000)
committerLuqman Aden <me@luqman.ca>
Sat, 20 Apr 2019 13:14:18 +0000 (13:14 +0000)
Summary:
Teach CorrelatedValuePropagation to also handle sub instructions in addition to add. Relatively simple since makeGuaranteedNoWrapRegion already understood sub instructions. Only subtle change is which range is passed as "Other" to that function, since sub isn't commutative.

Note that CorrelatedValuePropagation::processAddSub is still hidden behind a default-off flag as IndVarSimplify hasn't yet been fixed to strip the added nsw/nuw flags and causes a miscompile. (PR31181)

Reviewers: sanjoy, apilipenko, nikic

Reviewed By: nikic

Subscribers: hiraditya, jfb, jdoerfert, llvm-commits

Tags: #llvm

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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@358816 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
test/Transforms/CorrelatedValuePropagation/add.ll
test/Transforms/CorrelatedValuePropagation/sub.ll

index a56a37a618bc63d86c1d03cfd923c46dfdfa1425..2c31e4aa6cd16120ce4cbda8bdf410367dc8aa3b 100644 (file)
@@ -64,7 +64,7 @@ STATISTIC(NumAShrs,     "Number of ashr converted to lshr");
 STATISTIC(NumSRems,     "Number of srem converted to urem");
 STATISTIC(NumOverflows, "Number of overflow checks removed");
 
-static cl::opt<bool> DontProcessAdds("cvp-dont-process-adds", cl::init(true));
+static cl::opt<bool> DontAddNoWrapFlags("cvp-dont-add-nowrap-flags", cl::init(true));
 
 namespace {
 
@@ -607,53 +607,53 @@ static bool processAShr(BinaryOperator *SDI, LazyValueInfo *LVI) {
   return true;
 }
 
-static bool processAdd(BinaryOperator *AddOp, LazyValueInfo *LVI) {
+static bool processBinOp(BinaryOperator *BinOp, LazyValueInfo *LVI) {
   using OBO = OverflowingBinaryOperator;
 
-  if (DontProcessAdds)
+  if (DontAddNoWrapFlags)
     return false;
 
-  if (AddOp->getType()->isVectorTy())
+  if (BinOp->getType()->isVectorTy())
     return false;
 
-  bool NSW = AddOp->hasNoSignedWrap();
-  bool NUW = AddOp->hasNoUnsignedWrap();
+  bool NSW = BinOp->hasNoSignedWrap();
+  bool NUW = BinOp->hasNoUnsignedWrap();
   if (NSW && NUW)
     return false;
 
-  BasicBlock *BB = AddOp->getParent();
+  BasicBlock *BB = BinOp->getParent();
 
-  Value *LHS = AddOp->getOperand(0);
-  Value *RHS = AddOp->getOperand(1);
+  Value *LHS = BinOp->getOperand(0);
+  Value *RHS = BinOp->getOperand(1);
 
-  ConstantRange LRange = LVI->getConstantRange(LHS, BB, AddOp);
+  ConstantRange RRange = LVI->getConstantRange(RHS, BB, BinOp);
 
-  // Initialize RRange only if we need it. If we know that guaranteed no wrap
-  // range for the given LHS range is empty don't spend time calculating the
-  // range for the RHS.
-  Optional<ConstantRange> RRange;
-  auto LazyRRange = [&] () {
-      if (!RRange)
-        RRange = LVI->getConstantRange(RHS, BB, AddOp);
-      return RRange.getValue();
+  // Initialize LRange only if we need it. If we know that guaranteed no wrap
+  // range for the given RHS range is empty don't spend time calculating the
+  // range for the LHS.
+  Optional<ConstantRange> LRange;
+  auto LazyLRange = [&] () {
+      if (!LRange)
+        LRange = LVI->getConstantRange(LHS, BB, BinOp);
+      return LRange.getValue();
   };
 
   bool Changed = false;
   if (!NUW) {
     ConstantRange NUWRange = ConstantRange::makeGuaranteedNoWrapRegion(
-        BinaryOperator::Add, LRange, OBO::NoUnsignedWrap);
+        BinOp->getOpcode(), RRange, OBO::NoUnsignedWrap);
     if (!NUWRange.isEmptySet()) {
-      bool NewNUW = NUWRange.contains(LazyRRange());
-      AddOp->setHasNoUnsignedWrap(NewNUW);
+      bool NewNUW = NUWRange.contains(LazyLRange());
+      BinOp->setHasNoUnsignedWrap(NewNUW);
       Changed |= NewNUW;
     }
   }
   if (!NSW) {
     ConstantRange NSWRange = ConstantRange::makeGuaranteedNoWrapRegion(
-        BinaryOperator::Add, LRange, OBO::NoSignedWrap);
+        BinOp->getOpcode(), RRange, OBO::NoSignedWrap);
     if (!NSWRange.isEmptySet()) {
-      bool NewNSW = NSWRange.contains(LazyRRange());
-      AddOp->setHasNoSignedWrap(NewNSW);
+      bool NewNSW = NSWRange.contains(LazyLRange());
+      BinOp->setHasNoSignedWrap(NewNSW);
       Changed |= NewNSW;
     }
   }
@@ -729,7 +729,8 @@ static bool runImpl(Function &F, LazyValueInfo *LVI, DominatorTree *DT,
         BBChanged |= processAShr(cast<BinaryOperator>(II), LVI);
         break;
       case Instruction::Add:
-        BBChanged |= processAdd(cast<BinaryOperator>(II), LVI);
+      case Instruction::Sub:
+        BBChanged |= processBinOp(cast<BinaryOperator>(II), LVI);
         break;
       }
     }
index 4001f511f94d360b4505a87b4e10d789e47f3d72..026af75220df9c83488308c6510b6754f84a1ab6 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: opt < %s -correlated-propagation -cvp-dont-process-adds=false -S | FileCheck %s
+; RUN: opt < %s -correlated-propagation -cvp-dont-add-nowrap-flags=false -S | FileCheck %s
 
 ; CHECK-LABEL: @test0(
 define void @test0(i32 %a) {
index 83f6ff15d1a095d0d4b883799ac9a17cf959e226..6e954e8ff67fa0c0fbe83bd2a68326cbf54f7018 100644 (file)
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt < %s -correlated-propagation -cvp-dont-process-adds=false -S | FileCheck %s
+; RUN: opt < %s -correlated-propagation -cvp-dont-add-nowrap-flags=false -S | FileCheck %s
 
 define void @test0(i32 %a) {
 ; CHECK-LABEL: @test0(
@@ -7,7 +7,7 @@ define void @test0(i32 %a) {
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 100
 ; CHECK-NEXT:    br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
 ; CHECK:       bb:
-; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[A]], 1
+; CHECK-NEXT:    [[SUB:%.*]] = sub nuw nsw i32 [[A]], 1
 ; CHECK-NEXT:    br label [[EXIT]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
@@ -30,7 +30,7 @@ define void @test1(i32 %a) {
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[A:%.*]], 100
 ; CHECK-NEXT:    br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
 ; CHECK:       bb:
-; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[A]], 1
+; CHECK-NEXT:    [[SUB:%.*]] = sub nuw i32 [[A]], 1
 ; CHECK-NEXT:    br label [[EXIT]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
@@ -76,7 +76,7 @@ define void @test3(i32 %a) {
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], -1
 ; CHECK-NEXT:    br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
 ; CHECK:       bb:
-; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[A]], 1
+; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i32 [[A]], 1
 ; CHECK-NEXT:    br label [[EXIT]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
@@ -99,7 +99,7 @@ define void @test4(i32 %a) {
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[A:%.*]], 2147483647
 ; CHECK-NEXT:    br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
 ; CHECK:       bb:
-; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[A]], 1
+; CHECK-NEXT:    [[SUB:%.*]] = sub nuw i32 [[A]], 1
 ; CHECK-NEXT:    br label [[EXIT]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
@@ -163,7 +163,7 @@ define void @test7(i32 %a, i1 %flag) {
 ; CHECK-NEXT:    [[CMP:%.*]] = and i1 [[CMP_1]], [[FLAG:%.*]]
 ; CHECK-NEXT:    br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
 ; CHECK:       bb:
-; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[A]], 1
+; CHECK-NEXT:    [[SUB:%.*]] = sub nuw i32 [[A]], 1
 ; CHECK-NEXT:    br label [[EXIT]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
@@ -191,7 +191,7 @@ define void @test8(i32 %a) {
 ; CHECK-NEXT:    [[CMP:%.*]] = and i1 [[CMP_1]], [[CMP_2]]
 ; CHECK-NEXT:    br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
 ; CHECK:       bb:
-; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[A]], 1
+; CHECK-NEXT:    [[SUB:%.*]] = sub nuw nsw i32 [[A]], 1
 ; CHECK-NEXT:    br label [[EXIT]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
@@ -250,7 +250,7 @@ define void @test9(i32 %a, i1 %flag) {
 ; CHECK-NEXT:    [[CMP:%.*]] = and i1 [[CMP_1]], [[CMP_3]]
 ; CHECK-NEXT:    br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
 ; CHECK:       bb:
-; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[A]], 1
+; CHECK-NEXT:    [[SUB:%.*]] = sub nuw nsw i32 [[A]], 1
 ; CHECK-NEXT:    br label [[EXIT]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
@@ -279,7 +279,7 @@ define void @test10(i32 %a, i32 %b, i1 %flag) {
 ; CHECK-NEXT:    [[CMP:%.*]] = and i1 [[CMP_1]], [[FLAG:%.*]]
 ; CHECK-NEXT:    br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
 ; CHECK:       bb:
-; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[A]], 1
+; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i32 [[A]], 1
 ; CHECK-NEXT:    br label [[EXIT]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
@@ -307,7 +307,7 @@ define i32 @test11(i32* %p, i32 %i) {
 ; CHECK-NEXT:    [[WITHIN:%.*]] = and i1 [[WITHIN_1]], [[WITHIN_2]]
 ; CHECK-NEXT:    br i1 [[WITHIN]], label [[THEN:%.*]], label [[ELSE:%.*]]
 ; CHECK:       then:
-; CHECK-NEXT:    [[I_MINUS_6:%.*]] = sub i32 [[I]], 6
+; CHECK-NEXT:    [[I_MINUS_6:%.*]] = sub nuw nsw i32 [[I]], 6
 ; CHECK-NEXT:    ret i32 [[I_MINUS_6]]
 ; CHECK:       else:
 ; CHECK-NEXT:    ret i32 0
@@ -336,7 +336,7 @@ define void @test12(i32 %a, i1 %flag) {
 ; CHECK-NEXT:    [[CMP:%.*]] = or i1 [[CMP_1]], [[FLAG:%.*]]
 ; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[BB:%.*]]
 ; CHECK:       bb:
-; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[A]], 1
+; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i32 [[A]], 1
 ; CHECK-NEXT:    br label [[EXIT]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
@@ -364,7 +364,7 @@ define void @test13(i32 %a) {
 ; CHECK-NEXT:    [[CMP:%.*]] = or i1 [[CMP_1]], [[CMP_2]]
 ; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[BB:%.*]]
 ; CHECK:       bb:
-; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[A]], 1
+; CHECK-NEXT:    [[SUB:%.*]] = sub nuw nsw i32 [[A]], 1
 ; CHECK-NEXT:    br label [[EXIT]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
@@ -423,7 +423,7 @@ define void @test14(i32 %a, i1 %flag) {
 ; CHECK-NEXT:    [[CMP:%.*]] = or i1 [[CMP_1]], [[CMP_3]]
 ; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[BB:%.*]]
 ; CHECK:       bb:
-; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[A]], 1
+; CHECK-NEXT:    [[SUB:%.*]] = sub nuw nsw i32 [[A]], 1
 ; CHECK-NEXT:    br label [[EXIT]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
@@ -452,7 +452,7 @@ define void @test15(i32 %a, i32 %b, i1 %flag) {
 ; CHECK-NEXT:    [[CMP:%.*]] = or i1 [[CMP_1]], [[FLAG:%.*]]
 ; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[BB:%.*]]
 ; CHECK:       bb:
-; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[A]], 1
+; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i32 [[A]], 1
 ; CHECK-NEXT:    br label [[EXIT]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
@@ -483,7 +483,7 @@ define i32 @test16(i32* %n, i32* %a) {
 ; CHECK-NEXT:    [[X:%.*]] = load atomic i32, i32* [[A:%.*]] unordered, align 8
 ; CHECK-NEXT:    fence acquire
 ; CHECK-NEXT:    [[ACC_CURR]] = sub i32 [[ACC]], [[X]]
-; CHECK-NEXT:    [[IV_NEXT]] = sub i32 [[IV]], -1
+; CHECK-NEXT:    [[IV_NEXT]] = sub nsw i32 [[IV]], -1
 ; CHECK-NEXT:    [[NVAL:%.*]] = load atomic i32, i32* [[N:%.*]] unordered, align 8
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[IV_NEXT]], [[NVAL]]
 ; CHECK-NEXT:    br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]]
@@ -514,7 +514,7 @@ define void @test17(i32 %a) {
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 100
 ; CHECK-NEXT:    br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
 ; CHECK:       bb:
-; CHECK-NEXT:    [[SUB:%.*]] = sub i32 1, [[A]]
+; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i32 1, [[A]]
 ; CHECK-NEXT:    br label [[EXIT]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
@@ -537,7 +537,7 @@ define void @test18(i32 %a) {
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 10000
 ; CHECK-NEXT:    br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
 ; CHECK:       bb:
-; CHECK-NEXT:    [[SUB:%.*]] = sub i32 -2, [[A]]
+; CHECK-NEXT:    [[SUB:%.*]] = sub nuw i32 -2, [[A]]
 ; CHECK-NEXT:    br label [[EXIT]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
@@ -560,7 +560,7 @@ define void @test19(i32 %a) {
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 100
 ; CHECK-NEXT:    br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
 ; CHECK:       bb:
-; CHECK-NEXT:    [[SUB:%.*]] = sub i32 -1, [[A]]
+; CHECK-NEXT:    [[SUB:%.*]] = sub nuw nsw i32 -1, [[A]]
 ; CHECK-NEXT:    br label [[EXIT]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void