[ValueTracking] Use computeConstantRange() for unsigned add/sub overflow
Improve computeOverflowForUnsignedAdd/Sub in ValueTracking by
intersecting the computeConstantRange() result into the ConstantRange
created from computeKnownBits(). This allows us to detect some
additional never/always overflows conditions that can't be determined
from known bits.
This revision also adds basic handling for constants to
computeConstantRange(). Non-splat vectors will be handled in a followup.
The signed case will also be handled in a followup, as it needs some
more groundwork.
Differential Revision: https://reviews.llvm.org/D59386
llvm-svn: 356489
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index b566a70..99d6010 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -4077,18 +4077,27 @@
llvm_unreachable("Unknown OverflowResult");
}
+/// Combine constant ranges from computeConstantRange() and computeKnownBits().
+static ConstantRange computeConstantRangeIncludingKnownBits(
+ const Value *V, bool ForSigned, const DataLayout &DL, unsigned Depth,
+ AssumptionCache *AC, const Instruction *CxtI, const DominatorTree *DT,
+ OptimizationRemarkEmitter *ORE = nullptr, bool UseInstrInfo = true) {
+ KnownBits Known = computeKnownBits(
+ V, DL, Depth, AC, CxtI, DT, ORE, UseInstrInfo);
+ ConstantRange CR = computeConstantRange(V, UseInstrInfo);
+ return ConstantRange::fromKnownBits(Known, ForSigned).intersectWith(CR);
+}
+
OverflowResult llvm::computeOverflowForUnsignedAdd(
const Value *LHS, const Value *RHS, const DataLayout &DL,
AssumptionCache *AC, const Instruction *CxtI, const DominatorTree *DT,
bool UseInstrInfo) {
- KnownBits LHSKnown = computeKnownBits(LHS, DL, /*Depth=*/0, AC, CxtI, DT,
- nullptr, UseInstrInfo);
- KnownBits RHSKnown = computeKnownBits(RHS, DL, /*Depth=*/0, AC, CxtI, DT,
- nullptr, UseInstrInfo);
- ConstantRange LHSRange =
- ConstantRange::fromKnownBits(LHSKnown, /*signed*/ false);
- ConstantRange RHSRange =
- ConstantRange::fromKnownBits(RHSKnown, /*signed*/ false);
+ ConstantRange LHSRange = computeConstantRangeIncludingKnownBits(
+ LHS, /*ForSigned=*/false, DL, /*Depth=*/0, AC, CxtI, DT,
+ nullptr, UseInstrInfo);
+ ConstantRange RHSRange = computeConstantRangeIncludingKnownBits(
+ RHS, /*ForSigned=*/false, DL, /*Depth=*/0, AC, CxtI, DT,
+ nullptr, UseInstrInfo);
return mapOverflowResult(LHSRange.unsignedAddMayOverflow(RHSRange));
}
@@ -4161,12 +4170,10 @@
AssumptionCache *AC,
const Instruction *CxtI,
const DominatorTree *DT) {
- KnownBits LHSKnown = computeKnownBits(LHS, DL, /*Depth=*/0, AC, CxtI, DT);
- KnownBits RHSKnown = computeKnownBits(RHS, DL, /*Depth=*/0, AC, CxtI, DT);
- ConstantRange LHSRange =
- ConstantRange::fromKnownBits(LHSKnown, /*signed*/ false);
- ConstantRange RHSRange =
- ConstantRange::fromKnownBits(RHSKnown, /*signed*/ false);
+ ConstantRange LHSRange = computeConstantRangeIncludingKnownBits(
+ LHS, /*ForSigned=*/false, DL, /*Depth=*/0, AC, CxtI, DT);
+ ConstantRange RHSRange = computeConstantRangeIncludingKnownBits(
+ RHS, /*ForSigned=*/false, DL, /*Depth=*/0, AC, CxtI, DT);
return mapOverflowResult(LHSRange.unsignedSubMayOverflow(RHSRange));
}
@@ -5690,6 +5697,10 @@
ConstantRange llvm::computeConstantRange(const Value *V, bool UseInstrInfo) {
assert(V->getType()->isIntOrIntVectorTy() && "Expected integer instruction");
+ const APInt *C;
+ if (match(V, m_APInt(C)))
+ return ConstantRange(*C);
+
InstrInfoQuery IIQ(UseInstrInfo);
unsigned BitWidth = V->getType()->getScalarSizeInBits();
APInt Lower = APInt(BitWidth, 0);