aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/IR/ConstantRange.cpp
diff options
context:
space:
mode:
authorAntonio Frighetto <me@antoniofrighetto.com>2024-05-16 08:50:50 +0200
committerAntonio Frighetto <me@antoniofrighetto.com>2024-05-24 19:25:09 +0200
commite897b0bbe908ea17188f0b1ed96e6b6c8f8954d8 (patch)
tree2401e65eb8a2dff176f7a08005360df38e055054 /llvm/lib/IR/ConstantRange.cpp
parentf49247129f3e873841bc6c3fec4bdc7c9d6f1dd7 (diff)
downloadllvm-e897b0bbe908ea17188f0b1ed96e6b6c8f8954d8.zip
llvm-e897b0bbe908ea17188f0b1ed96e6b6c8f8954d8.tar.gz
llvm-e897b0bbe908ea17188f0b1ed96e6b6c8f8954d8.tar.bz2
[ConstantRange][LVI] Add support for `multiplyWithNoWrap`
Introduce support for computing multiplication ranges when nowrap flags are known. This is achieved by intersecting the multiplication range with the saturating one. Note that we may still conservatively return overdefined when handling non-wrapped/non-sign-wrapped ranges.
Diffstat (limited to 'llvm/lib/IR/ConstantRange.cpp')
-rw-r--r--llvm/lib/IR/ConstantRange.cpp22
1 files changed, 22 insertions, 0 deletions
diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp
index 59e7a9f..c3bde48 100644
--- a/llvm/lib/IR/ConstantRange.cpp
+++ b/llvm/lib/IR/ConstantRange.cpp
@@ -930,6 +930,8 @@ ConstantRange ConstantRange::overflowingBinaryOp(Instruction::BinaryOps BinOp,
return addWithNoWrap(Other, NoWrapKind);
case Instruction::Sub:
return subWithNoWrap(Other, NoWrapKind);
+ case Instruction::Mul:
+ return multiplyWithNoWrap(Other, NoWrapKind);
default:
// Don't know about this Overflowing Binary Operation.
// Conservatively fallback to plain binop handling.
@@ -1167,6 +1169,26 @@ ConstantRange::multiply(const ConstantRange &Other) const {
return UR.isSizeStrictlySmallerThan(SR) ? UR : SR;
}
+ConstantRange
+ConstantRange::multiplyWithNoWrap(const ConstantRange &Other,
+ unsigned NoWrapKind,
+ PreferredRangeType RangeType) const {
+ if (isEmptySet() || Other.isEmptySet())
+ return getEmpty();
+ if (isFullSet() && Other.isFullSet())
+ return getFull();
+
+ ConstantRange Result = multiply(Other);
+
+ if (NoWrapKind & OverflowingBinaryOperator::NoSignedWrap)
+ Result = Result.intersectWith(smul_sat(Other), RangeType);
+
+ if (NoWrapKind & OverflowingBinaryOperator::NoUnsignedWrap)
+ Result = Result.intersectWith(umul_sat(Other), RangeType);
+
+ return Result;
+}
+
ConstantRange ConstantRange::smul_fast(const ConstantRange &Other) const {
if (isEmptySet() || Other.isEmptySet())
return getEmpty();