aboutsummaryrefslogtreecommitdiff
path: root/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Transforms/Scalar/CorrelatedValuePropagation.cpp')
-rw-r--r--lib/Transforms/Scalar/CorrelatedValuePropagation.cpp55
1 files changed, 55 insertions, 0 deletions
diff --git a/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
index ef784fc7882..040e0f59c61 100644
--- a/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
+++ b/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
@@ -31,6 +31,8 @@
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/Type.h"
@@ -58,6 +60,7 @@ 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");
+STATISTIC(NumOverflows, "Number of overflow checks removed");
static cl::opt<bool> DontProcessAdds("cvp-dont-process-adds", cl::init(true));
@@ -323,11 +326,63 @@ static bool processSwitch(SwitchInst *SI, LazyValueInfo *LVI) {
return Changed;
}
+// See if we can prove that the given overflow intrinsic will not overflow.
+static bool willNotOverflow(IntrinsicInst *II, LazyValueInfo *LVI) {
+ using OBO = OverflowingBinaryOperator;
+ auto NoWrapOnAddition = [&] (Value *LHS, Value *RHS, unsigned NoWrapKind) {
+ ConstantRange RRange = LVI->getConstantRange(RHS, II->getParent(), II);
+ ConstantRange NWRegion = ConstantRange::makeGuaranteedNoWrapRegion(
+ BinaryOperator::Add, RRange, NoWrapKind);
+ // As an optimization, do not compute LRange if we do not need it.
+ if (NWRegion.isEmptySet())
+ return false;
+ ConstantRange LRange = LVI->getConstantRange(LHS, II->getParent(), II);
+ return NWRegion.contains(LRange);
+ };
+ switch (II->getIntrinsicID()) {
+ default:
+ break;
+ case Intrinsic::uadd_with_overflow:
+ return NoWrapOnAddition(II->getOperand(0), II->getOperand(1),
+ OBO::NoUnsignedWrap);
+ case Intrinsic::sadd_with_overflow:
+ return NoWrapOnAddition(II->getOperand(0), II->getOperand(1),
+ OBO::NoSignedWrap);
+ }
+ return false;
+}
+
+static void processOverflowIntrinsic(IntrinsicInst *II) {
+ Value *NewOp = nullptr;
+ switch (II->getIntrinsicID()) {
+ default:
+ llvm_unreachable("Illegal instruction.");
+ case Intrinsic::uadd_with_overflow:
+ case Intrinsic::sadd_with_overflow:
+ NewOp = BinaryOperator::CreateAdd(II->getOperand(0), II->getOperand(1),
+ II->getName(), II);
+ break;
+ }
+ ++NumOverflows;
+ IRBuilder<> B(II);
+ Value *NewI = B.CreateInsertValue(UndefValue::get(II->getType()), NewOp, 0);
+ NewI = B.CreateInsertValue(NewI, ConstantInt::getFalse(II->getContext()), 1);
+ II->replaceAllUsesWith(NewI);
+ II->eraseFromParent();
+}
+
/// Infer nonnull attributes for the arguments at the specified callsite.
static bool processCallSite(CallSite CS, LazyValueInfo *LVI) {
SmallVector<unsigned, 4> ArgNos;
unsigned ArgNo = 0;
+ if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(CS.getInstruction())) {
+ if (willNotOverflow(II, LVI)) {
+ processOverflowIntrinsic(II);
+ return true;
+ }
+ }
+
for (Value *V : CS.args()) {
PointerType *Type = dyn_cast<PointerType>(V->getType());
// Try to mark pointer typed parameters as non-null. We skip the