153 Commits

Author SHA1 Message Date
Nikita Popov
9707b98e57 [ConstantRange] Perform increment on APInt (NFC)
This handles the edge case where BitWidth is 1 and doing the
increment gets a value that's not valid in that width, while we
just want wrap-around.

Split out of https://github.com/llvm/llvm-project/pull/80309.
2024-09-05 16:11:00 +02:00
Yingwei Zheng
07b29fc808
[ConstantRange] Improve shlWithNoWrap (#101800)
Closes https://github.com/dtcxzyw/llvm-tools/issues/22.
2024-08-07 02:00:33 +08:00
Yingwei Zheng
1a5d8926c5
[ConstantRange] Add support for shlWithNoWrap (#100594)
This patch adds initial support for `ConstantRange:: shlWithNoWrap` to
fold https://github.com/dtcxzyw/llvm-tools/issues/22. However, this
patch cannot fix the original issue. Improvements will be submitted in subsequent patches.
2024-08-02 00:03:44 +08:00
Yingwei Zheng
ca00cec997
[ConstantRange] Infer nonnegative for mul nuw nsw (#100554)
Alive2: https://alive2.llvm.org/ce/z/byzmsV
2024-07-25 21:29:18 +08:00
Nikita Popov
3ab2247d10 [ConstantRange] Optimize icmp() implementation (NFC)
These are pretty hot code paths, so provide direct implementations
for them, instead of going through makeSatisfyingICmpRegion().
2024-07-03 18:10:22 +02:00
Ramkumar Ramachandra
edbbc832a5
ConstantRange: add query for isAllPositive (#97420)
ConstantRange has queries for isAllNegative and isAllNonNegative, but
misses a query for isAllPositive. Add this function.
2024-07-03 10:50:22 +01:00
Antonio Frighetto
c22d3917b9 [LVI][ConstantRange] Generalize mask not equal conditions handling
Extend `V & Mask != 0` for non-zero constants if satisfiable, when
retrieving constraint value information from a non-equality comparison.

Proof: https://alive2.llvm.org/ce/z/dc5BeT.

Motivating example: https://github.com/gcc-mirror/gcc/blob/master/gcc/testsuite/gcc.dg/tree-ssa/vrp76.c.
2024-06-17 21:13:52 +02:00
c8ef
b25b1db819
[KnownBits] Remove hasConflict() assertions (#94568)
Allow KnownBits to represent "always poison" values via conflict.

close: #94436
2024-06-07 17:01:22 +02:00
Antonio Frighetto
e897b0bbe9 [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.
2024-05-24 19:25:09 +02:00
Craig Topper
12836467b7
[ConstantRange] Fix off by 1 bugs in UIToFP and SIToFP handling. (#86041)
We were passing the min and max values of the range to the ConstantRange
constructor, but the constructor expects the upper bound to 1 more than
the max value so we need to add 1.

We also need to use getNonEmpty so that passing 0, 0 to the constructor
creates a full range rather than an empty range. And passing smin,
smax+1 doesn't cause an assertion.

I believe this fixes at least some of the reason #79158 was reverted.
2024-03-21 09:25:13 -07:00
Yingwei Zheng
d9e92765c5
[ConstantRange] Improve ConstantRange::binaryXor (#80146)
`ConstantRange::binaryXor` gives poor results as it currently depends on
`KnownBits::operator^`.
Since `sub A, B` is canonicalized into `xor A, B` if `B` is the subset
of `A`, this patch reverts the transform in `ConstantRange::binaryXor`,
which will give better results.

Alive2: https://alive2.llvm.org/ce/z/bmTMV9
Fixes #79696.
2024-02-08 22:34:52 +08:00
Yingwei Zheng
6f1d3b97c7
[ConstantRange] Handle Intrinsic::cttz (#67917)
This patch adds support for `Intrinsic::cttz` in ConstantRange. It
calculates the range in O(1) with the LCP-based method.

Migrated from https://reviews.llvm.org/D153505.
2023-11-06 19:17:39 +08:00
Yingwei Zheng
b6deea1b53
[ConstantRange] Handle Intrinsic::ctpop (#68310)
This patch adds support for `Intrinsic::ctpop` in ConstantRange. It
calculates the range in O(1) with the LCP-based method.

Migrated from https://reviews.llvm.org/D153505.
2023-11-06 15:59:50 +08:00
Nikita Popov
ab6667f844 [ConstantRange] Optimize smul nowrap with constant (NFC)
Don't call makeExactMulNSWRegion() twice with the same value.
2023-09-15 13:50:08 +02:00
Nikita Popov
4dd392fcd7 [ConstantRange] Make shl() for negative LHS more precise
This differs from the positive case in that shifting by a larger
amount makes the result smaller, not larger.
2023-08-29 14:48:33 +02:00
Nikita Popov
7cf567d461 [ConstantRange] Calculate precise range for multiply by -1
These are pretty common in SCEV, so make sure we get a precise
result by mapping to the sub() operation.
2023-06-23 12:17:48 +02:00
Kazu Hirata
a28b252d85 Use APInt::getSignificantBits instead of APInt::getMinSignedBits (NFC)
Note that getMinSignedBits has been soft-deprecated in favor of
getSignificantBits.
2023-02-19 23:56:52 -08:00
Kazu Hirata
f8f3db2756 Use APInt::count{l,r}_{zero,one} (NFC) 2023-02-19 22:04:47 -08:00
Antonio Frighetto
65898e5260 [ConstantRange] Handle Intrinsic::ctlz
Introduce ConstantRange support for ctlz intrinsic, including
exhaustive testing. Among other things, LVI may now be able to
propagate information about cltz constant ranges lattice values.

Differential Revision: https://reviews.llvm.org/D142234
2023-02-17 09:57:35 +01:00
Nikita Popov
fd07583ca4 [ConstantRange] Fix single bit abs range (PR59887)
For a full range input, we would produce an empty range instead
of a full range. The change to the SMin.isNonNegative() branch is
an optimality fix, because we should account for the potentially
discarded SMin value in the IntMinIsPoison case.

Change TestUnaryOpExhaustive to test both 4 and 1 bits, to both
cover this specific case in unit tests, and make sure all other
unary operations deal with 1-bit inputs correctly.

Fixes https://github.com/llvm/llvm-project/issues/59887.
2023-01-09 16:34:09 +01:00
Krzysztof Parzyszek
29041bc050 [APInt] Convert GetMostSignificantDifferentBit to std::optional 2022-12-10 14:03:29 -06:00
Nikita Popov
b04fc99c34 [ConstantRange] Fix nsw nowrap region for 1 bit integers (PR59301)
The special case for V=1 was incorrect for one bit types, where
1 is also -1. Remove it, and use getNonEmpty() to handle the full
range case instead.

Adjust the exhaustive nowrap tests to test both 5 bit and 1 bit
types.

Fixes https://github.com/llvm/llvm-project/issues/59301.
2022-12-06 16:37:43 +01:00
Fangrui Song
89fae41ef1 [IR] llvm::Optional => std::optional
Many llvm/IR/* files have been migrated by other contributors.
This migrates most remaining files.
2022-12-05 04:13:11 +00:00
Kazu Hirata
e842c06c2d [IR] Use std::nullopt instead of None (NFC)
This patch mechanically replaces None with std::nullopt where the
compiler would warn if None were deprecated.  The intent is to reduce
the amount of manual work required in migrating from Optional to
std::optional.

This is part of an effort to migrate from llvm::Optional to
std::optional:

https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
2022-12-02 20:05:20 -08:00
Nikita Popov
ba1e04b966 [ConstantRange] Fix sdiv() with one bit values (PR56333)
Signed one bit values can only be -1 or 0, not positive. The code
was interpreting the 1 as -1 and intersecting with a full range
rather than an empty one.

Fixes https://github.com/llvm/llvm-project/issues/56333.
2022-07-01 15:44:59 +02:00
Alexander Shaposhnikov
9398caf399 Recommit "[ConstantRange] Improve the implementation of binaryOr"
This recommits https://reviews.llvm.org/rG6990e7477d24ff585ae86549f5280f0be65422a6
as the problematic test has been updated updated in
https://reviews.llvm.org/rG3bd112c720dc614a59e3f34ebf9b45075037bfa0.
2022-05-20 18:39:58 +00:00
Douglas Yung
54e3bf5f37 Revert "[ConstantRange] Improve the implementation of binaryOr"
This reverts commit 6990e7477d24ff585ae86549f5280f0be65422a6.

This change was causing the test compiler-rt/test/fuzzer/merge_two_step.test to fail on
our internal bot as well as other build bots such as https://lab.llvm.org/buildbot/#/builders/179/builds/3712.
2022-05-20 10:24:20 -07:00
Alexander Shaposhnikov
6990e7477d [ConstantRange] Improve the implementation of binaryOr
This diff adjusts binaryOr to take advantage of the analysis
based on KnownBits.

Differential revision: https://reviews.llvm.org/D125933

Test plan:
1/ ninja check-llvm
2/ ninja check-llvm-unit
2022-05-19 21:39:19 +00:00
Jay Foad
6bec3e9303 [APInt] Remove all uses of zextOrSelf, sextOrSelf and truncOrSelf
Most clients only used these methods because they wanted to be able to
extend or truncate to the same bit width (which is a no-op). Now that
the standard zext, sext and trunc allow this, there is no reason to use
the OrSelf versions.

The OrSelf versions additionally have the strange behaviour of allowing
extending to a *smaller* width, or truncating to a *larger* width, which
are also treated as no-ops. A small amount of client code relied on this
(ConstantRange::castOp and MicrosoftCXXNameMangler::mangleNumber) and
needed rewriting.

Differential Revision: https://reviews.llvm.org/D125557
2022-05-19 11:23:13 +01:00
Alexander Shaposhnikov
0f4d9f9b71 [ConstantRange] Improve the implementation of binaryAnd
This diff adjusts binaryAnd to take advantage of the analysis
based on KnownBits.

Differential revision: https://reviews.llvm.org/D125603

Test plan:
1/ ninja check-llvm
2/ ninja check-llvm-unit
2022-05-17 22:06:03 +00:00
Nikita Popov
2db4dc7ec0 [ConstantRange] Implement binaryXor() using known bits
This allows us to compute known high bits. It's not optimal, but
better than nothing.
2022-05-17 10:05:12 +02:00
Nikita Popov
8ab819ad90 [ConstantRange] Add toKnownBits() method
Add toKnownBits() method to mirror fromKnownBits(). We know the
top bits that are constant between min and max.

The return value for an empty range is chosen to be conservative.
2022-05-16 16:12:25 +02:00
Nikita Popov
2060895c9c [ConstantRange] Add exact union/intersect (NFC)
For some optimizations on comparisons it's necessary that the
union/intersect is exact and not a superset. Add methods that
return Optional<ConstantRange> only if the result is exact.

For the sake of simplicity this is implemented by comparing
the subset and superset approximations for now, but it should be
possible to do this more directly, as unionWith() and intersectWith()
already distinguish the cases where the result is imprecise for the
preferred range type functionality.
2021-11-07 21:46:06 +01:00
Nikita Popov
cf71a5ea8f [ConstantRange] Support zero size in isSizeLargerThan()
From an API perspective, it does not make a lot of sense that 0
is not a valid argument to this function. Add the exact check needed
to support it.
2021-11-07 21:22:45 +01:00
Nikita Popov
9f0194be45 [ConstantRange] Add getEquivalentICmp() variant with offset (NFCI)
Add a variant of getEquivalentICmp() that produces an optional
offset. This allows us to create an equivalent icmp for all ranges.

Use this in the with.overflow folding code, which was doing this
adjustment separately -- this clarifies that the fold will indeed
always apply.
2021-11-06 21:59:45 +01:00
Roman Lebedev
03a4f1f3b8
[ConstantRange] Sign-flipping of signedness-invariant comparisons
For certain combination of LHS and RHS constant ranges,
the signedness of the relational comparison predicate is irrelevant.

This implements complete and precise model for all predicates,
as confirmed by the brute-force tests. I'm not sure if there are
some more cases that we can handle here.

In a follow-up, CVP will make use of this.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D90924
2021-10-31 22:53:17 +03:00
Nikita Popov
ea7be26045 [ConstantRange] Optimize smul_sat() (NFC)
Base the implementation on the APInt smul_sat() implementation,
which is much more efficient than performing calculations in
double the bitwidth.
2021-10-27 21:01:09 +02:00
Nikita Popov
274b2439f8 [ConstantRange] Add fast signed multiply
The multiply() implementation is very slow -- it performs six
multiplications in double the bitwidth, which means that it will
typically work on allocated APInts and bypass fast-path
implementations. Add an additional implementation that doesn't
try to produce anything better than a full range if overflow is
possible. At least for the BasicAA use-case, we really don't care
about more precise modeling of overflow behavior. The current
use of multiply() is fine while the implementation is limited to
a single index, but extending it to the multiple-index case makes
the compile-time impact untenable.
2021-10-17 16:41:49 +02:00
Nikita Popov
587493b441 [ConstantRange] Compute precise shl range for single elements
For the common case where the shift amount is constant (a single
element range) we can easily compute a precise range (up to
unsigned envelope), so do that.
2021-10-15 23:44:41 +02:00
Jay Foad
a9bceb2b05 [APInt] Stop using soft-deprecated constructors and methods in llvm. NFC.
Stop using APInt constructors and methods that were soft-deprecated in
D109483. This fixes all the uses I found in llvm, except for the APInt
unit tests which should still test the deprecated methods.

Differential Revision: https://reviews.llvm.org/D110807
2021-10-04 08:57:44 +01:00
Chris Lattner
735f46715d [APInt] Normalize naming on keep constructors / predicate methods.
This renames the primary methods for creating a zero value to `getZero`
instead of `getNullValue` and renames predicates like `isAllOnesValue`
to simply `isAllOnes`.  This achieves two things:

1) This starts standardizing predicates across the LLVM codebase,
   following (in this case) ConstantInt.  The word "Value" doesn't
   convey anything of merit, and is missing in some of the other things.

2) Calling an integer "null" doesn't make any sense.  The original sin
   here is mine and I've regretted it for years.  This moves us to calling
   it "zero" instead, which is correct!

APInt is widely used and I don't think anyone is keen to take massive source
breakage on anything so core, at least not all in one go.  As such, this
doesn't actually delete any entrypoints, it "soft deprecates" them with a
comment.

Included in this patch are changes to a bunch of the codebase, but there are
more.  We should normalize SelectionDAG and other APIs as well, which would
make the API change more mechanical.

Differential Revision: https://reviews.llvm.org/D109483
2021-09-09 09:50:24 -07:00
Florian Hahn
611a02cce5
[ConstantRanges] Use APInt for constant case for urem/srem.
Currently UREM & SREM on constant ranges produces overly pessimistic
results for single element constant ranges.

Delegate to APInt's implementation if both operands are single element
constant ranges. We already do something similar for other binary
operators, like binary AND.

Fixes PR49731.

Reviewed By: lebedev.ri

Differential Revision: https://reviews.llvm.org/D105115
2021-06-30 11:18:20 +01:00
Roman Lebedev
e8c7f43e2c
[NFC][ConstantRange] Add 'icmp' helper method
"Does the predicate hold between two ranges?"

Not very surprisingly, some places were already doing this check,
without explicitly naming the algorithm, cleanup them all.
2021-04-10 19:38:55 +03:00
Roman Lebedev
7b12c8c59d
Revert "[NFC][ConstantRange] Add 'icmp' helper method"
This reverts commit 17cf2c94230bc107e7294ef84fad3b47f4cd1b73.
2021-04-10 19:37:53 +03:00
Roman Lebedev
17cf2c9423
[NFC][ConstantRange] Add 'icmp' helper method
"Does the predicate hold between two ranges?"

Not very surprisingly, some places were already doing this check,
without explicitly naming the algorithm, cleanup them all.
2021-04-10 19:09:52 +03:00
Nikita Popov
a852234f70 [ConstantRange] Handle wrapping ranges in min/max (PR48643)
When one of the inputs is a wrapping range, intersect with the
union of the two inputs. The union of the two inputs corresponds
to the result we would get if we treated the min/max as a simple
select.

This fixes PR48643.
2021-02-20 22:52:09 +01:00
Nikita Popov
b6088f7465 [ConstantRange] Handle wrapping range in binaryNot()
We don't need any special handling for wrapping ranges (or empty
ranges for that matter). The sub() call will already compute a
correct and precise range.

We only need to adjust the test expectation: We're now computing
an optimal result, rather than an unsigned envelope.
2021-02-20 21:45:59 +01:00
Roman Lebedev
7465da2077
[ConstantRange] Introduce getMinSignedBits() method
Similar to the ConstantRange::getActiveBits(), and to similarly-named
methods in APInt, returns the bitwidth needed to represent
the given signed constant range
2020-09-22 21:37:30 +03:00
Roman Lebedev
2ed9c4c70b
[ConstantRange] Introduce getActiveBits() method
Much like APInt::getActiveBits(), computes how many bits are needed
to be able to represent every value in this constant range,
treating the values as unsigned.
2020-09-22 21:37:29 +03:00
Roman Lebedev
b38d897e80
[ConstantRange] binaryXor(): special-case binary complement case - the result is precise
Use the fact that `~X` is equivalent to `-1 - X`, which gives us
fully-precise answer, and we only need to special-handle the wrapped case.

This fires ~16k times for vanilla llvm test-suite + RawSpeed.
2020-09-22 21:37:29 +03:00