Skip to content

Commit

Permalink
[CVP] Process binary operations even when def is local
Browse files Browse the repository at this point in the history
Summary:
This patch adds processing of binary operations when the def of operands are in
the same block (i.e. local processing).

Earlier we bailed out in such cases (the bail out was introduced in rL252032)
because LVI at that time was more precise about context at the end of basic
blocks, which implied local def and use analysis didn't benefit CVP.

Since then we've added support for LVI in presence of assumes and guards. The
test cases added show how local def processing in CVP helps adding more
information to the ashr, sdiv, srem and add operators.

Note: processCmp which suffers from the same problem will
be handled in a later patch.

Reviewers: philip, apilipenko, SjoerdMeijer, hfinkel

Subscribers: llvm-commits

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

llvm-svn: 315634
  • Loading branch information
annamthomas committed Oct 12, 2017
1 parent 3a9c114 commit 61aec18
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 16 deletions.
20 changes: 4 additions & 16 deletions llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
Expand Up @@ -335,18 +335,6 @@ static bool processCallSite(CallSite CS, LazyValueInfo *LVI) {
return true;
}

// Helper function to rewrite srem and sdiv. As a policy choice, we choose not
// to waste compile time on anything where the operands are local defs. While
// LVI can sometimes reason about such cases, it's not its primary purpose.
static bool hasLocalDefs(BinaryOperator *SDI) {
for (Value *O : SDI->operands()) {
auto *I = dyn_cast<Instruction>(O);
if (I && I->getParent() == SDI->getParent())
return true;
}
return false;
}

static bool hasPositiveOperands(BinaryOperator *SDI, LazyValueInfo *LVI) {
Constant *Zero = ConstantInt::get(SDI->getType(), 0);
for (Value *O : SDI->operands()) {
Expand All @@ -358,7 +346,7 @@ static bool hasPositiveOperands(BinaryOperator *SDI, LazyValueInfo *LVI) {
}

static bool processSRem(BinaryOperator *SDI, LazyValueInfo *LVI) {
if (SDI->getType()->isVectorTy() || hasLocalDefs(SDI) ||
if (SDI->getType()->isVectorTy() ||
!hasPositiveOperands(SDI, LVI))
return false;

Expand All @@ -376,7 +364,7 @@ static bool processSRem(BinaryOperator *SDI, LazyValueInfo *LVI) {
/// conditions, this can sometimes prove conditions instcombine can't by
/// exploiting range information.
static bool processSDiv(BinaryOperator *SDI, LazyValueInfo *LVI) {
if (SDI->getType()->isVectorTy() || hasLocalDefs(SDI) ||
if (SDI->getType()->isVectorTy() ||
!hasPositiveOperands(SDI, LVI))
return false;

Expand All @@ -391,7 +379,7 @@ static bool processSDiv(BinaryOperator *SDI, LazyValueInfo *LVI) {
}

static bool processAShr(BinaryOperator *SDI, LazyValueInfo *LVI) {
if (SDI->getType()->isVectorTy() || hasLocalDefs(SDI))
if (SDI->getType()->isVectorTy())
return false;

Constant *Zero = ConstantInt::get(SDI->getType(), 0);
Expand All @@ -415,7 +403,7 @@ static bool processAdd(BinaryOperator *AddOp, LazyValueInfo *LVI) {
if (DontProcessAdds)
return false;

if (AddOp->getType()->isVectorTy() || hasLocalDefs(AddOp))
if (AddOp->getType()->isVectorTy())
return false;

bool NSW = AddOp->hasNoSignedWrap();
Expand Down
23 changes: 23 additions & 0 deletions llvm/test/Transforms/CorrelatedValuePropagation/add.ll
Expand Up @@ -307,3 +307,26 @@ exit:
ret void
}

; single basic block loop
; because the loop exit condition is SLT, we can supplement the iv add
; (iv.next def) with an nsw.
; CHECK-LABEL: @test16(
define i32 @test16(i32* %n, i32* %a) {
preheader:
br label %loop

loop:
; CHECK: %iv.next = add 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
%nval = load atomic i32, i32* %n unordered, align 8
%cmp = icmp slt i32 %iv.next, %nval
br i1 %cmp, label %loop, label %exit

exit:
ret i32 %acc.curr
}
43 changes: 43 additions & 0 deletions llvm/test/Transforms/CorrelatedValuePropagation/ashr.ll
Expand Up @@ -54,3 +54,46 @@ bb:
exit:
ret void
}

; looping case where loop has exactly one block
; at the point of ashr, we know that the operand is always greater than 0,
; because of the guard before it, so we can transform it to lshr.
declare void @llvm.experimental.guard(i1,...)
; CHECK-LABEL: @test4
define void @test4(i32 %n) {
entry:
%cmp = icmp sgt i32 %n, 0
br i1 %cmp, label %loop, label %exit

loop:
; CHECK: lshr i32 %a, 1
%a = phi i32 [ %n, %entry ], [ %shr, %loop ]
%cond = icmp sgt i32 %a, 2
call void(i1,...) @llvm.experimental.guard(i1 %cond) [ "deopt"() ]
%shr = ashr i32 %a, 1
br i1 %cond, label %loop, label %exit

exit:
ret void
}

; same test as above with assume instead of guard.
declare void @llvm.assume(i1)
; CHECK-LABEL: @test5
define void @test5(i32 %n) {
entry:
%cmp = icmp sgt i32 %n, 0
br i1 %cmp, label %loop, label %exit

loop:
; CHECK: lshr i32 %a, 1
%a = phi i32 [ %n, %entry ], [ %shr, %loop ]
%cond = icmp sgt i32 %a, 4
call void @llvm.assume(i1 %cond)
%shr = ashr i32 %a, 1
%loopcond = icmp sgt i32 %shr, 8
br i1 %loopcond, label %loop, label %exit

exit:
ret void
}
43 changes: 43 additions & 0 deletions llvm/test/Transforms/CorrelatedValuePropagation/sdiv.ll
Expand Up @@ -52,3 +52,46 @@ bb:
exit:
ret void
}

; looping case where loop has exactly one block
; at the point of sdiv, we know that %a is always greater than 0,
; because of the guard before it, so we can transform it to udiv.
declare void @llvm.experimental.guard(i1,...)
; CHECK-LABEL: @test4
define void @test4(i32 %n) {
entry:
%cmp = icmp sgt i32 %n, 0
br i1 %cmp, label %loop, label %exit

loop:
; CHECK: udiv i32 %a, 6
%a = phi i32 [ %n, %entry ], [ %div, %loop ]
%cond = icmp sgt i32 %a, 4
call void(i1,...) @llvm.experimental.guard(i1 %cond) [ "deopt"() ]
%div = sdiv i32 %a, 6
br i1 %cond, label %loop, label %exit

exit:
ret void
}

; same test as above with assume instead of guard.
declare void @llvm.assume(i1)
; CHECK-LABEL: @test5
define void @test5(i32 %n) {
entry:
%cmp = icmp sgt i32 %n, 0
br i1 %cmp, label %loop, label %exit

loop:
; CHECK: udiv i32 %a, 6
%a = phi i32 [ %n, %entry ], [ %div, %loop ]
%cond = icmp sgt i32 %a, 4
call void @llvm.assume(i1 %cond)
%div = sdiv i32 %a, 6
%loopcond = icmp sgt i32 %div, 8
br i1 %loopcond, label %loop, label %exit

exit:
ret void
}
23 changes: 23 additions & 0 deletions llvm/test/Transforms/CorrelatedValuePropagation/srem.ll
Expand Up @@ -19,3 +19,26 @@ if.then:
if.end:
ret void
}

; looping case where loop has exactly one block
; at the point of srem, we know that %a is always greater than 0,
; because of the assume before it, so we can transform it to urem.
declare void @llvm.assume(i1)
; CHECK-LABEL: @test4
define void @test4(i32 %n) {
entry:
%cmp = icmp sgt i32 %n, 0
br i1 %cmp, label %loop, label %exit

loop:
; CHECK: urem i32 %a, 6
%a = phi i32 [ %n, %entry ], [ %rem, %loop ]
%cond = icmp sgt i32 %a, 4
call void @llvm.assume(i1 %cond)
%rem = srem i32 %a, 6
%loopcond = icmp sgt i32 %rem, 8
br i1 %loopcond, label %loop, label %exit

exit:
ret void
}

0 comments on commit 61aec18

Please sign in to comment.