Index: llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp =================================================================== --- llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp +++ llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp @@ -38,6 +38,7 @@ 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 DontProcessAdds("cvp-dont-process-adds", cl::init(false)); @@ -384,6 +385,25 @@ 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 @@ case Instruction::SDiv: BBChanged |= processSDiv(cast(II), LVI); break; + case Instruction::AShr: + BBChanged |= processAShr(cast(II), LVI); + break; case Instruction::Add: BBChanged |= processAdd(cast(II), LVI); break; Index: llvm/trunk/test/Transforms/CorrelatedValuePropagation/ashr.ll =================================================================== --- llvm/trunk/test/Transforms/CorrelatedValuePropagation/ashr.ll +++ llvm/trunk/test/Transforms/CorrelatedValuePropagation/ashr.ll @@ -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 +}