diff --git a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp --- a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp +++ b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp @@ -64,7 +64,7 @@ STATISTIC(NumSRems, "Number of srem converted to urem"); STATISTIC(NumOverflows, "Number of overflow checks removed"); -static cl::opt DontProcessAdds("cvp-dont-process-adds", cl::init(true)); +static cl::opt DontAddNoWrapFlags("cvp-dont-add-nowrap-flags", cl::init(true)); namespace { @@ -607,53 +607,53 @@ 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 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 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 @@ BBChanged |= processAShr(cast(II), LVI); break; case Instruction::Add: - BBChanged |= processAdd(cast(II), LVI); + case Instruction::Sub: + BBChanged |= processBinOp(cast(II), LVI); break; } } diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/add.ll b/llvm/test/Transforms/CorrelatedValuePropagation/add.ll --- a/llvm/test/Transforms/CorrelatedValuePropagation/add.ll +++ b/llvm/test/Transforms/CorrelatedValuePropagation/add.ll @@ -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) { diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/add.ll b/llvm/test/Transforms/CorrelatedValuePropagation/sub.ll copy from llvm/test/Transforms/CorrelatedValuePropagation/add.ll copy to llvm/test/Transforms/CorrelatedValuePropagation/sub.ll --- a/llvm/test/Transforms/CorrelatedValuePropagation/add.ll +++ b/llvm/test/Transforms/CorrelatedValuePropagation/sub.ll @@ -1,14 +1,14 @@ -; 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) { entry: - %cmp = icmp slt i32 %a, 100 + %cmp = icmp sgt i32 %a, 100 br i1 %cmp, label %bb, label %exit bb: -; CHECK: %add = add nsw i32 %a, 1 - %add = add i32 %a, 1 +; CHECK: %sub = sub nuw nsw i32 %a, 1 + %sub = sub i32 %a, 1 br label %exit exit: @@ -18,12 +18,12 @@ ; CHECK-LABEL: @test1( define void @test1(i32 %a) { entry: - %cmp = icmp ult i32 %a, 100 + %cmp = icmp ugt i32 %a, 100 br i1 %cmp, label %bb, label %exit bb: -; CHECK: %add = add nuw nsw i32 %a, 1 - %add = add i32 %a, 1 +; CHECK: %sub = sub nuw i32 %a, 1 + %sub = sub i32 %a, 1 br label %exit exit: @@ -33,12 +33,12 @@ ; CHECK-LABEL: @test2( define void @test2(i32 %a) { entry: - %cmp = icmp ult i32 %a, -1 + %cmp = icmp ugt i32 %a, -1 br i1 %cmp, label %bb, label %exit bb: -; CHECK: %add = add nuw i32 %a, 1 - %add = add i32 %a, 1 +; CHECK: %sub = sub i32 %a, 1 + %sub = sub i32 %a, 1 br label %exit exit: @@ -48,12 +48,12 @@ ; CHECK-LABEL: @test3( define void @test3(i32 %a) { entry: - %cmp = icmp ule i32 %a, -1 + %cmp = icmp sgt i32 %a, -1 br i1 %cmp, label %bb, label %exit bb: -; CHECK: %add = add i32 %a, 1 - %add = add i32 %a, 1 +; CHECK: %sub = sub nsw i32 %a, 1 + %sub = sub i32 %a, 1 br label %exit exit: @@ -63,12 +63,12 @@ ; CHECK-LABEL: @test4( define void @test4(i32 %a) { entry: - %cmp = icmp slt i32 %a, 2147483647 + %cmp = icmp ugt i32 %a, 2147483647 br i1 %cmp, label %bb, label %exit bb: -; CHECK: %add = add nsw i32 %a, 1 - %add = add i32 %a, 1 +; CHECK: %sub = sub nuw i32 %a, 1 + %sub = sub i32 %a, 1 br label %exit exit: @@ -82,8 +82,8 @@ br i1 %cmp, label %bb, label %exit bb: -; CHECK: %add = add i32 %a, 1 - %add = add i32 %a, 1 +; CHECK: %sub = sub i32 %a, 1 + %sub = sub i32 %a, 1 br label %exit exit: @@ -96,29 +96,29 @@ @b = global i32 0, align 4 define void @test6(i32 %a) { bb: - %add = add i32 %a, ptrtoint (i32* @b to i32) + %sub = sub i32 %a, ptrtoint (i32* @b to i32) ret void } -; Check that we can gather information for conditions is the form of +; Check that we can gather information for conditions in the form of ; and ( i s< 100, Unknown ) ; CHECK-LABEL: @test7( define void @test7(i32 %a, i1 %flag) { entry: - %cmp.1 = icmp slt i32 %a, 100 + %cmp.1 = icmp ugt i32 %a, 100 %cmp = and i1 %cmp.1, %flag br i1 %cmp, label %bb, label %exit bb: -; CHECK: %add = add nsw i32 %a, 1 - %add = add i32 %a, 1 +; CHECK: %sub = sub nuw i32 %a, 1 + %sub = sub i32 %a, 1 br label %exit exit: ret void } -; Check that we can gather information for conditions is the form of +; Check that we can gather information for conditions in the form of ; and ( i s< 100, i s> 0 ) ; CHECK-LABEL: @test8( define void @test8(i32 %a) { @@ -129,15 +129,15 @@ br i1 %cmp, label %bb, label %exit bb: -; CHECK: %add = add nuw nsw i32 %a, 1 - %add = add i32 %a, 1 +; CHECK: %sub = sub nuw nsw i32 %a, 1 + %sub = sub i32 %a, 1 br label %exit exit: ret void } -; Check that for conditions is the form of cond1 && cond2 we don't mistakenly +; Check that for conditions in the form of cond1 && cond2 we don't mistakenly ; assume that !cond1 && !cond2 holds down to false path. ; CHECK-LABEL: @test8_neg( define void @test8_neg(i32 %a) { @@ -148,15 +148,15 @@ br i1 %cmp, label %exit, label %bb bb: -; CHECK: %add = add i32 %a, 1 - %add = add i32 %a, 1 +; CHECK: %sub = sub i32 %a, 1 + %sub = sub i32 %a, 1 br label %exit exit: ret void } -; Check that we can gather information for conditions is the form of +; Check that we can gather information for conditions in the form of ; and ( i s< 100, and (i s> 0, Unknown ) ; CHECK-LABEL: @test9( define void @test9(i32 %a, i1 %flag) { @@ -168,26 +168,26 @@ br i1 %cmp, label %bb, label %exit bb: -; CHECK: %add = add nuw nsw i32 %a, 1 - %add = add i32 %a, 1 +; CHECK: %sub = sub nuw nsw i32 %a, 1 + %sub = sub i32 %a, 1 br label %exit exit: ret void } -; Check that we can gather information for conditions is the form of -; and ( i s< Unknown, ... ) +; Check that we can gather information for conditions in the form of +; and ( i s> Unknown, ... ) ; CHECK-LABEL: @test10( define void @test10(i32 %a, i32 %b, i1 %flag) { entry: - %cmp.1 = icmp slt i32 %a, %b + %cmp.1 = icmp sgt i32 %a, %b %cmp = and i1 %cmp.1, %flag br i1 %cmp, label %bb, label %exit bb: -; CHECK: %add = add nsw i32 %a, 1 - %add = add i32 %a, 1 +; CHECK: %sub = sub nsw i32 %a, 1 + %sub = sub i32 %a, 1 br label %exit exit: @@ -198,33 +198,33 @@ ; CHECK-LABEL: @test11( define i32 @test11(i32* %p, i32 %i) { %limit = load i32, i32* %p, !range !{i32 0, i32 2147483647} - %within.1 = icmp ugt i32 %limit, %i - %i.plus.7 = add i32 %i, 7 - %within.2 = icmp ugt i32 %limit, %i.plus.7 + %within.1 = icmp slt i32 %limit, %i + %i.minus.7 = add i32 %i, -7 + %within.2 = icmp slt i32 %limit, %i.minus.7 %within = and i1 %within.1, %within.2 br i1 %within, label %then, label %else then: -; CHECK: %i.plus.6 = add nuw nsw i32 %i, 6 - %i.plus.6 = add i32 %i, 6 - ret i32 %i.plus.6 +; CHECK: %i.minus.6 = sub nuw nsw i32 %i, 6 + %i.minus.6 = sub i32 %i, 6 + ret i32 %i.minus.6 else: ret i32 0 } ; Check that we can gather information for conditions is the form of -; or ( i s>= 100, Unknown ) +; or ( i s<= -100, Unknown ) ; CHECK-LABEL: @test12( define void @test12(i32 %a, i1 %flag) { entry: - %cmp.1 = icmp sge i32 %a, 100 + %cmp.1 = icmp sle i32 %a, -100 %cmp = or i1 %cmp.1, %flag br i1 %cmp, label %exit, label %bb bb: -; CHECK: %add = add nsw i32 %a, 1 - %add = add i32 %a, 1 +; CHECK: %sub = sub nsw i32 %a, 1 + %sub = sub i32 %a, 1 br label %exit exit: @@ -242,8 +242,8 @@ br i1 %cmp, label %exit, label %bb bb: -; CHECK: %add = add nuw nsw i32 %a, 1 - %add = add i32 %a, 1 +; CHECK: %sub = sub nuw nsw i32 %a, 1 + %sub = sub i32 %a, 1 br label %exit exit: @@ -261,8 +261,8 @@ br i1 %cmp, label %bb, label %exit bb: -; CHECK: %add = add i32 %a, 1 - %add = add i32 %a, 1 +; CHECK: %sub = sub i32 %a, 1 + %sub = sub i32 %a, 1 br label %exit exit: @@ -281,8 +281,8 @@ br i1 %cmp, label %exit, label %bb bb: -; CHECK: %add = add nuw nsw i32 %a, 1 - %add = add i32 %a, 1 +; CHECK: %sub = sub nuw nsw i32 %a, 1 + %sub = sub i32 %a, 1 br label %exit exit: @@ -290,17 +290,17 @@ } ; Check that we can gather information for conditions is the form of -; or ( i s>= Unknown, ... ) +; or ( i s<= Unknown, ... ) ; CHECK-LABEL: @test15( define void @test15(i32 %a, i32 %b, i1 %flag) { entry: - %cmp.1 = icmp sge i32 %a, %b + %cmp.1 = icmp sle i32 %a, %b %cmp = or i1 %cmp.1, %flag br i1 %cmp, label %exit, label %bb bb: -; CHECK: %add = add nsw i32 %a, 1 - %add = add i32 %a, 1 +; CHECK: %sub = sub nsw i32 %a, 1 + %sub = sub i32 %a, 1 br label %exit exit: @@ -308,7 +308,7 @@ } ; single basic block loop -; because the loop exit condition is SLT, we can supplement the iv add +; because the loop exit condition is SLT, we can supplement the iv sub ; (iv.next def) with an nsw. ; CHECK-LABEL: @test16( define i32 @test16(i32* %n, i32* %a) { @@ -316,13 +316,13 @@ br label %loop loop: -; CHECK: %iv.next = add nsw i32 %iv, 1 +; CHECK: %iv.next = sub nsw i32 %iv, -1 %iv = phi i32 [ 0, %preheader ], [ %iv.next, %loop ] %acc = phi i32 [ 0, %preheader ], [ %acc.curr, %loop ] %x = load atomic i32, i32* %a unordered, align 8 fence acquire - %acc.curr = add i32 %acc, %x - %iv.next = add i32 %iv, 1 + %acc.curr = sub i32 %acc, %x + %iv.next = sub i32 %iv, -1 %nval = load atomic i32, i32* %n unordered, align 8 %cmp = icmp slt i32 %iv.next, %nval br i1 %cmp, label %loop, label %exit @@ -330,3 +330,63 @@ exit: ret i32 %acc.curr } + +; CHECK-LABEL: @test17( +define void @test17(i32 %a) { +entry: + %cmp = icmp sgt i32 %a, 100 + br i1 %cmp, label %bb, label %exit + +bb: +; CHECK: %sub = sub nsw i32 1, %a + %sub = sub i32 1, %a + br label %exit + +exit: + ret void +} + +; CHECK-LABEL: @test18( +define void @test18(i32 %a) { +entry: + %cmp = icmp sgt i32 %a, 10000 + br i1 %cmp, label %bb, label %exit + +bb: +; CHECK: %sub = sub nuw i32 -2, %a + %sub = sub i32 -2, %a + br label %exit + +exit: + ret void +} + +; CHECK-LABEL: @test19( +define void @test19(i32 %a) { +entry: + %cmp = icmp ult i32 %a, 100 + br i1 %cmp, label %bb, label %exit + +bb: +; CHECK: %sub = sub nuw nsw i32 -1, %a + %sub = sub i32 -1, %a + br label %exit + +exit: + ret void +} + +; CHECK-LABEL: @test20( +define void @test20(i32 %a) { +entry: + %cmp = icmp ugt i32 %a, 2147483647 + br i1 %cmp, label %bb, label %exit + +bb: +; CHECK: %sub = sub i32 0, %a + %sub = sub i32 0, %a + br label %exit + +exit: + ret void +} \ No newline at end of file