diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
index de1cc299f062..5b49ab14286b 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -535,8 +535,10 @@ public:
/// Parse NSW/NUW flags from add/sub/mul IR binary operation \p Op into
/// SCEV no-wrap flags, and deduce flag[s] that aren't known yet.
- /// Does not mutate the original instruction.
- std::pair
+ /// Does not mutate the original instruction. Returns None if it could not
+ /// deduce more precise flags than the instruction already has, otherwise
+ /// returns proven flags.
+ Optional
getStrengthenedNoWrapFlagsFromBinOp(const OverflowingBinaryOperator *OBO);
/// Notify this ScalarEvolution that \p User directly uses SCEVs in \p Ops.
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index e8aa99c253e0..f73fd49b5058 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -2319,9 +2319,13 @@ bool ScalarEvolution::willNotOverflow(Instruction::BinaryOps BinOp, bool Signed,
return A == B;
}
-std::pair
+Optional
ScalarEvolution::getStrengthenedNoWrapFlagsFromBinOp(
const OverflowingBinaryOperator *OBO) {
+ // It cannot be done any better.
+ if (OBO->hasNoUnsignedWrap() && OBO->hasNoSignedWrap())
+ return None;
+
SCEV::NoWrapFlags Flags = SCEV::NoWrapFlags::FlagAnyWrap;
if (OBO->hasNoUnsignedWrap())
@@ -2331,13 +2335,10 @@ ScalarEvolution::getStrengthenedNoWrapFlagsFromBinOp(
bool Deduced = false;
- if (OBO->hasNoUnsignedWrap() && OBO->hasNoSignedWrap())
- return {Flags, Deduced};
-
if (OBO->getOpcode() != Instruction::Add &&
OBO->getOpcode() != Instruction::Sub &&
OBO->getOpcode() != Instruction::Mul)
- return {Flags, Deduced};
+ return None;
const SCEV *LHS = getSCEV(OBO->getOperand(0));
const SCEV *RHS = getSCEV(OBO->getOperand(1));
@@ -2356,7 +2357,9 @@ ScalarEvolution::getStrengthenedNoWrapFlagsFromBinOp(
Deduced = true;
}
- return {Flags, Deduced};
+ if (Deduced)
+ return Flags;
+ return None;
}
// We're trying to construct a SCEV of type `Type' with `Ops' as operands and
diff --git a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
index 64546ae88af6..153fa364db9c 100644
--- a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
@@ -749,17 +749,15 @@ bool SimplifyIndvar::eliminateIdentitySCEV(Instruction *UseInst,
/// unsigned-overflow. Returns true if anything changed, false otherwise.
bool SimplifyIndvar::strengthenOverflowingOperation(BinaryOperator *BO,
Value *IVOperand) {
- SCEV::NoWrapFlags Flags;
- bool Deduced;
- std::tie(Flags, Deduced) = SE->getStrengthenedNoWrapFlagsFromBinOp(
+ auto Flags = SE->getStrengthenedNoWrapFlagsFromBinOp(
cast(BO));
- if (!Deduced)
- return Deduced;
+ if (!Flags)
+ return false;
- BO->setHasNoUnsignedWrap(ScalarEvolution::maskFlags(Flags, SCEV::FlagNUW) ==
+ BO->setHasNoUnsignedWrap(ScalarEvolution::maskFlags(*Flags, SCEV::FlagNUW) ==
SCEV::FlagNUW);
- BO->setHasNoSignedWrap(ScalarEvolution::maskFlags(Flags, SCEV::FlagNSW) ==
+ BO->setHasNoSignedWrap(ScalarEvolution::maskFlags(*Flags, SCEV::FlagNSW) ==
SCEV::FlagNSW);
// The getStrengthenedNoWrapFlagsFromBinOp() check inferred additional nowrap
@@ -767,7 +765,7 @@ bool SimplifyIndvar::strengthenOverflowingOperation(BinaryOperator *BO,
// 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;
+ return true;
}
/// Annotate the Shr in (X << IVOperand) >> C as exact using the