diff options
author | Roman Lebedev <lebedev.ri@gmail.com> | 2021-06-01 11:33:52 +0300 |
---|---|---|
committer | Roman Lebedev <lebedev.ri@gmail.com> | 2021-06-05 12:17:51 +0300 |
commit | e350494fb044c5badec9cd8bfd7ab05026babf81 (patch) | |
tree | 545d1ddbbb236233385c8525e1c50bc8640ae8e8 /llvm/lib/Transforms/Utils/SimplifyIndVar.cpp | |
parent | 92ce29ee45b26513a9f4e42c6f287f43cb3de238 (diff) | |
download | llvm-e350494fb044c5badec9cd8bfd7ab05026babf81.zip llvm-e350494fb044c5badec9cd8bfd7ab05026babf81.tar.gz llvm-e350494fb044c5badec9cd8bfd7ab05026babf81.tar.bz2 |
[NFC] Promote willNotOverflow() / getStrengthenedNoWrapFlagsFromBinOp() from IndVars into SCEV proper
We might want to use it when creating SCEV proper in createSCEV(),
now that we don't `forgetValue()` in `SimplifyIndvar::strengthenOverflowingOperation()`,
which might have caused us to loose some optimization potential.
Diffstat (limited to 'llvm/lib/Transforms/Utils/SimplifyIndVar.cpp')
-rw-r--r-- | llvm/lib/Transforms/Utils/SimplifyIndVar.cpp | 90 |
1 files changed, 21 insertions, 69 deletions
diff --git a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp index 246bc0a..ff60667 100644 --- a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp @@ -422,46 +422,10 @@ void SimplifyIndvar::simplifyIVRemainder(BinaryOperator *Rem, Value *IVOperand, replaceSRemWithURem(Rem); } -static bool willNotOverflow(ScalarEvolution *SE, Instruction::BinaryOps BinOp, - bool Signed, const SCEV *LHS, const SCEV *RHS) { - const SCEV *(ScalarEvolution::*Operation)(const SCEV *, const SCEV *, - SCEV::NoWrapFlags, unsigned); - switch (BinOp) { - default: - llvm_unreachable("Unsupported binary op"); - case Instruction::Add: - Operation = &ScalarEvolution::getAddExpr; - break; - case Instruction::Sub: - Operation = &ScalarEvolution::getMinusSCEV; - break; - case Instruction::Mul: - Operation = &ScalarEvolution::getMulExpr; - break; - } - - const SCEV *(ScalarEvolution::*Extension)(const SCEV *, Type *, unsigned) = - Signed ? &ScalarEvolution::getSignExtendExpr - : &ScalarEvolution::getZeroExtendExpr; - - // Check ext(LHS op RHS) == ext(LHS) op ext(RHS) - auto *NarrowTy = cast<IntegerType>(LHS->getType()); - auto *WideTy = - IntegerType::get(NarrowTy->getContext(), NarrowTy->getBitWidth() * 2); - - const SCEV *A = - (SE->*Extension)((SE->*Operation)(LHS, RHS, SCEV::FlagAnyWrap, 0), - WideTy, 0); - const SCEV *B = - (SE->*Operation)((SE->*Extension)(LHS, WideTy, 0), - (SE->*Extension)(RHS, WideTy, 0), SCEV::FlagAnyWrap, 0); - return A == B; -} - bool SimplifyIndvar::eliminateOverflowIntrinsic(WithOverflowInst *WO) { const SCEV *LHS = SE->getSCEV(WO->getLHS()); const SCEV *RHS = SE->getSCEV(WO->getRHS()); - if (!willNotOverflow(SE, WO->getBinaryOp(), WO->isSigned(), LHS, RHS)) + if (!SE->willNotOverflow(WO->getBinaryOp(), WO->isSigned(), LHS, RHS)) return false; // Proved no overflow, nuke the overflow check and, if possible, the overflow @@ -502,7 +466,7 @@ bool SimplifyIndvar::eliminateOverflowIntrinsic(WithOverflowInst *WO) { 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)) + if (!SE->willNotOverflow(SI->getBinaryOp(), SI->isSigned(), LHS, RHS)) return false; BinaryOperator *BO = BinaryOperator::Create( @@ -756,37 +720,25 @@ bool SimplifyIndvar::eliminateIdentitySCEV(Instruction *UseInst, /// unsigned-overflow. Returns true if anything changed, false otherwise. bool SimplifyIndvar::strengthenOverflowingOperation(BinaryOperator *BO, Value *IVOperand) { - // Fastpath: we don't have any work to do if `BO` is `nuw` and `nsw`. - if (BO->hasNoUnsignedWrap() && BO->hasNoSignedWrap()) - return false; - - if (BO->getOpcode() != Instruction::Add && - BO->getOpcode() != Instruction::Sub && - BO->getOpcode() != Instruction::Mul) - return false; - - const SCEV *LHS = SE->getSCEV(BO->getOperand(0)); - const SCEV *RHS = SE->getSCEV(BO->getOperand(1)); - bool Changed = false; - - if (!BO->hasNoUnsignedWrap() && - willNotOverflow(SE, BO->getOpcode(), /* Signed */ false, LHS, RHS)) { - BO->setHasNoUnsignedWrap(); - Changed = true; - } - - if (!BO->hasNoSignedWrap() && - willNotOverflow(SE, BO->getOpcode(), /* Signed */ true, LHS, RHS)) { - BO->setHasNoSignedWrap(); - Changed = true; - } - - // The willNotOverflow() check might infer additional nowrap flags on addrecs - // while performing zero/sign extensions. We could call forgetValue() here - // to make sure those flags also propagate to any other SCEV expressions - // based on the addrec. However, this can have pathological compile-time - // impact, see https://bugs.llvm.org/show_bug.cgi?id=50384. - return Changed; + SCEV::NoWrapFlags Flags; + bool Deduced; + std::tie(Flags, Deduced) = SE->getStrengthenedNoWrapFlagsFromBinOp( + cast<OverflowingBinaryOperator>(BO)); + + if (!Deduced) + return Deduced; + + BO->setHasNoUnsignedWrap(ScalarEvolution::maskFlags(Flags, SCEV::FlagNUW) == + SCEV::FlagNUW); + BO->setHasNoSignedWrap(ScalarEvolution::maskFlags(Flags, SCEV::FlagNSW) == + SCEV::FlagNSW); + + // The getStrengthenedNoWrapFlagsFromBinOp() check inferred additional nowrap + // flags on addrecs while performing zero/sign extensions. We could call + // forgetValue() here to make sure those flags also propagate to any other + // SCEV expressions based on the addrec. However, this can have pathological + // compile-time impact, see https://bugs.llvm.org/show_bug.cgi?id=50384. + return Deduced; } /// Annotate the Shr in (X << IVOperand) >> C as exact using the |