[CVP] Convert an AShr to a LShr if 1st operand is known to be nonnegative.

An arithmetic shift can be safely changed to a logical shift if the first
operand is known positive. This allows ComputeKnownBits (and similar analysis)
to determine the sign bit of the shifted value in some cases. In turn, this
allows InstCombine to canonicalize a signed comparison (a > 0) into an equality
check (a != 0).

PR30577

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

llvm-svn: 284013
This commit is contained in:
Chad Rosier 2016-10-12 13:41:38 +00:00
parent b271a58e37
commit c215c3fd14
2 changed files with 79 additions and 0 deletions

View File

@ -38,6 +38,7 @@ STATISTIC(NumCmps, "Number of comparisons propagated");
STATISTIC(NumReturns, "Number of return values propagated");
STATISTIC(NumDeadCases, "Number of switch cases removed");
STATISTIC(NumSDivs, "Number of sdiv converted to udiv");
STATISTIC(NumAShrs, "Number of ashr converted to lshr");
STATISTIC(NumSRems, "Number of srem converted to urem");
static cl::opt<bool> DontProcessAdds("cvp-dont-process-adds", cl::init(false));
@ -384,6 +385,25 @@ static bool processSDiv(BinaryOperator *SDI, LazyValueInfo *LVI) {
return true;
}
static bool processAShr(BinaryOperator *SDI, LazyValueInfo *LVI) {
if (SDI->getType()->isVectorTy() || hasLocalDefs(SDI))
return false;
Constant *Zero = ConstantInt::get(SDI->getType(), 0);
if (LVI->getPredicateAt(ICmpInst::ICMP_SGE, SDI->getOperand(0), Zero, SDI) !=
LazyValueInfo::True)
return false;
++NumAShrs;
auto *BO = BinaryOperator::CreateLShr(SDI->getOperand(0), SDI->getOperand(1),
SDI->getName(), SDI);
BO->setIsExact(SDI->isExact());
SDI->replaceAllUsesWith(BO);
SDI->eraseFromParent();
return true;
}
static bool processAdd(BinaryOperator *AddOp, LazyValueInfo *LVI) {
typedef OverflowingBinaryOperator OBO;
@ -495,6 +515,9 @@ static bool runImpl(Function &F, LazyValueInfo *LVI) {
case Instruction::SDiv:
BBChanged |= processSDiv(cast<BinaryOperator>(II), LVI);
break;
case Instruction::AShr:
BBChanged |= processAShr(cast<BinaryOperator>(II), LVI);
break;
case Instruction::Add:
BBChanged |= processAdd(cast<BinaryOperator>(II), LVI);
break;

View File

@ -0,0 +1,56 @@
; RUN: opt < %s -correlated-propagation -S | FileCheck %s
; CHECK-LABEL: @test1
define void @test1(i32 %n) {
entry:
br label %for.cond
for.cond: ; preds = %for.body, %entry
%a = phi i32 [ %n, %entry ], [ %shr, %for.body ]
%cmp = icmp sgt i32 %a, 1
br i1 %cmp, label %for.body, label %for.end
for.body: ; preds = %for.cond
; CHECK: lshr i32 %a, 5
%shr = ashr i32 %a, 5
br label %for.cond
for.end: ; preds = %for.cond
ret void
}
;; Negative test to show transform doesn't happen unless n > 0.
; CHECK-LABEL: @test2
define void @test2(i32 %n) {
entry:
br label %for.cond
for.cond: ; preds = %for.body, %entry
%a = phi i32 [ %n, %entry ], [ %shr, %for.body ]
%cmp = icmp sgt i32 %a, -2
br i1 %cmp, label %for.body, label %for.end
for.body: ; preds = %for.cond
; CHECK: ashr i32 %a, 2
%shr = ashr i32 %a, 2
br label %for.cond
for.end: ; preds = %for.cond
ret void
}
;; Non looping test case.
; CHECK-LABEL: @test3
define void @test3(i32 %n) {
entry:
%cmp = icmp sgt i32 %n, 0
br i1 %cmp, label %bb, label %exit
bb:
; CHECK: lshr exact i32 %n, 4
%shr = ashr exact i32 %n, 4
br label %exit
exit:
ret void
}