Skip to content

Commit

Permalink
[CorrelatedValuePropagation] Mark subs that we know not to wrap with …
Browse files Browse the repository at this point in the history
…nuw/nsw.

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

llvm-svn: 358816
  • Loading branch information
luqmana committed Apr 20, 2019
1 parent d3b2682 commit 2993661
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 44 deletions.
51 changes: 26 additions & 25 deletions llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
Expand Up @@ -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 {

Expand Down Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -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;
}
}
Expand Down
2 changes: 1 addition & 1 deletion 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) {
Expand Down
36 changes: 18 additions & 18 deletions llvm/test/Transforms/CorrelatedValuePropagation/sub.ll
@@ -1,13 +1,13 @@
; 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(
; CHECK-NEXT: entry:
; 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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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:%.*]]
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down

0 comments on commit 2993661

Please sign in to comment.