STATISTIC(NumReturns, "Number of return values propagated");
STATISTIC(NumDeadCases, "Number of switch cases removed");
STATISTIC(NumSDivs, "Number of sdiv converted to udiv");
+STATISTIC(NumSRems, "Number of srem converted to urem");
namespace {
class CorrelatedValuePropagation : public FunctionPass {
return true;
}
-/// See if LazyValueInfo's ability to exploit edge conditions or range
-/// information is sufficient to prove the both operands of this SDiv are
-/// positive. If this is the case, replace the SDiv with a UDiv. Even for local
-/// conditions, this can sometimes prove conditions instcombine can't by
-/// exploiting range information.
-static bool processSDiv(BinaryOperator *SDI, LazyValueInfo *LVI) {
- if (SDI->getType()->isVectorTy())
- return false;
-
+// 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()) {
- // 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.
auto *I = dyn_cast<Instruction>(O);
if (I && I->getParent() == SDI->getParent())
- return false;
+ return true;
}
+ return false;
+}
+static bool hasPositiveOperands(BinaryOperator *SDI, LazyValueInfo *LVI) {
Constant *Zero = ConstantInt::get(SDI->getType(), 0);
for (Value *O : SDI->operands()) {
- LazyValueInfo::Tristate Result =
- LVI->getPredicateAt(ICmpInst::ICMP_SGE, O, Zero, SDI);
+ auto Result = LVI->getPredicateAt(ICmpInst::ICMP_SGE, O, Zero, SDI);
if (Result != LazyValueInfo::True)
return false;
}
+ return true;
+}
+
+static bool processSRem(BinaryOperator *SDI, LazyValueInfo *LVI) {
+ if (SDI->getType()->isVectorTy() || hasLocalDefs(SDI) ||
+ !hasPositiveOperands(SDI, LVI))
+ return false;
+
+ ++NumSRems;
+ auto *BO = BinaryOperator::CreateURem(SDI->getOperand(0), SDI->getOperand(1),
+ SDI->getName(), SDI);
+ SDI->replaceAllUsesWith(BO);
+ SDI->eraseFromParent();
+ return true;
+}
+
+/// See if LazyValueInfo's ability to exploit edge conditions or range
+/// information is sufficient to prove the both operands of this SDiv are
+/// positive. If this is the case, replace the SDiv with a UDiv. Even for local
+/// 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) ||
+ !hasPositiveOperands(SDI, LVI))
+ return false;
++NumSDivs;
auto *BO = BinaryOperator::CreateUDiv(SDI->getOperand(0), SDI->getOperand(1),
case Instruction::Invoke:
BBChanged |= processCallSite(CallSite(II), LVI);
break;
+ case Instruction::SRem:
+ BBChanged |= processSRem(cast<BinaryOperator>(II), LVI);
+ break;
case Instruction::SDiv:
BBChanged |= processSDiv(cast<BinaryOperator>(II), LVI);
break;