diff options
author | Antonio Frighetto <me@antoniofrighetto.com> | 2024-05-16 08:50:50 +0200 |
---|---|---|
committer | Antonio Frighetto <me@antoniofrighetto.com> | 2024-05-24 19:25:09 +0200 |
commit | e897b0bbe908ea17188f0b1ed96e6b6c8f8954d8 (patch) | |
tree | 2401e65eb8a2dff176f7a08005360df38e055054 /llvm/lib/IR/ConstantRange.cpp | |
parent | f49247129f3e873841bc6c3fec4bdc7c9d6f1dd7 (diff) | |
download | llvm-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.cpp | 22 |
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(); |