diff options
Diffstat (limited to 'llvm/lib/Transforms/Utils/SimplifyIndVar.cpp')
-rw-r--r-- | llvm/lib/Transforms/Utils/SimplifyIndVar.cpp | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp index f1048d9..cbb114f 100644 --- a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp @@ -81,6 +81,7 @@ namespace { bool replaceIVUserWithLoopInvariant(Instruction *UseInst); bool eliminateOverflowIntrinsic(WithOverflowInst *WO); + bool eliminateSaturatingIntrinsic(SaturatingInst *SI); bool eliminateTrunc(TruncInst *TI); bool eliminateIVUser(Instruction *UseInst, Instruction *IVOperand); bool makeIVComparisonInvariant(ICmpInst *ICmp, Value *IVOperand); @@ -477,6 +478,25 @@ bool SimplifyIndvar::eliminateOverflowIntrinsic(WithOverflowInst *WO) { return true; } +bool SimplifyIndvar::eliminateSaturatingIntrinsic(SaturatingInst *SI) { + const SCEV *LHS = SE->getSCEV(SI->getLHS()); + const SCEV *RHS = SE->getSCEV(SI->getRHS()); + if (!willNotOverflow(SE, SI->getBinaryOp(), SI->isSigned(), LHS, RHS)) + return false; + + BinaryOperator *BO = BinaryOperator::Create( + SI->getBinaryOp(), SI->getLHS(), SI->getRHS(), SI->getName(), SI); + if (SI->isSigned()) + BO->setHasNoSignedWrap(); + else + BO->setHasNoUnsignedWrap(); + + SI->replaceAllUsesWith(BO); + DeadInsts.emplace_back(SI); + Changed = true; + return true; +} + bool SimplifyIndvar::eliminateTrunc(TruncInst *TI) { // It is always legal to replace // icmp <pred> i32 trunc(iv), n @@ -614,6 +634,10 @@ bool SimplifyIndvar::eliminateIVUser(Instruction *UseInst, if (eliminateOverflowIntrinsic(WO)) return true; + if (auto *SI = dyn_cast<SaturatingInst>(UseInst)) + if (eliminateSaturatingIntrinsic(SI)) + return true; + if (auto *TI = dyn_cast<TruncInst>(UseInst)) if (eliminateTrunc(TI)) return true; |