diff options
| author | Nikita Popov <nikita.ppv@gmail.com> | 2019-05-31 20:48:26 +0000 |
|---|---|---|
| committer | Nikita Popov <nikita.ppv@gmail.com> | 2019-05-31 20:48:26 +0000 |
| commit | 7bafae55c01dda8478aeff74a8d657a4148630af (patch) | |
| tree | 7c0b11691f9dbb847ce733ffd832d212973cca32 /llvm/lib | |
| parent | d43509305674e89e6ac482b5a76c2ac20c2de1c4 (diff) | |
| download | bcm5719-llvm-7bafae55c01dda8478aeff74a8d657a4148630af.tar.gz bcm5719-llvm-7bafae55c01dda8478aeff74a8d657a4148630af.zip | |
Reapply [CVP] Simplify non-overflowing saturating add/sub
If we can determine that a saturating add/sub will not overflow based
on range analysis, convert it into a simple binary operation. This is
a sibling transform to the existing with.overflow handling.
Reapplying this with an additional check that the saturating intrinsic
has integer type, as LVI currently does not support vector types.
Differential Revision: https://reviews.llvm.org/D62703
llvm-svn: 362263
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp | 25 |
1 files changed, 24 insertions, 1 deletions
diff --git a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp index 9ec2afb99d6..5bfdf17c9a0 100644 --- a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp +++ b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp @@ -63,6 +63,8 @@ STATISTIC(NumUDivs, "Number of udivs whose width was decreased"); STATISTIC(NumAShrs, "Number of ashr converted to lshr"); STATISTIC(NumSRems, "Number of srem converted to urem"); STATISTIC(NumOverflows, "Number of overflow checks removed"); +STATISTIC(NumSaturating, + "Number of saturating arithmetics converted to normal arithmetics"); static cl::opt<bool> DontAddNoWrapFlags("cvp-dont-add-nowrap-flags", cl::init(true)); @@ -413,7 +415,7 @@ static void processOverflowIntrinsic(WithOverflowInst *WO) { IRBuilder<> B(WO); Value *NewOp = B.CreateBinOp( WO->getBinaryOp(), WO->getLHS(), WO->getRHS(), WO->getName()); - // Constant-holing could have happened. + // Constant-folding could have happened. if (auto *Inst = dyn_cast<Instruction>(NewOp)) { if (WO->isSigned()) Inst->setHasNoSignedWrap(); @@ -428,6 +430,20 @@ static void processOverflowIntrinsic(WithOverflowInst *WO) { ++NumOverflows; } +static void processSaturatingInst(SaturatingInst *SI) { + BinaryOperator *BinOp = BinaryOperator::Create( + SI->getBinaryOp(), SI->getLHS(), SI->getRHS(), SI->getName(), SI); + BinOp->setDebugLoc(SI->getDebugLoc()); + if (SI->isSigned()) + BinOp->setHasNoSignedWrap(); + else + BinOp->setHasNoUnsignedWrap(); + + SI->replaceAllUsesWith(BinOp); + SI->eraseFromParent(); + ++NumSaturating; +} + /// Infer nonnull attributes for the arguments at the specified callsite. static bool processCallSite(CallSite CS, LazyValueInfo *LVI) { SmallVector<unsigned, 4> ArgNos; @@ -440,6 +456,13 @@ static bool processCallSite(CallSite CS, LazyValueInfo *LVI) { } } + if (auto *SI = dyn_cast<SaturatingInst>(CS.getInstruction())) { + if (SI->getType()->isIntegerTy() && willNotOverflow(SI, LVI)) { + processSaturatingInst(SI); + return true; + } + } + // Deopt bundle operands are intended to capture state with minimal // perturbance of the code otherwise. If we can find a constant value for // any such operand and remove a use of the original value, that's |

