Commit Graph

106 Commits

Author SHA1 Message Date
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
Nikita Popov 9ebeac6788 [ConstantRange][CVP] Make use of abs poison flag
Pass the abs poison flag to the underlying ConstantRange
implementation, allowing CVP to simplify based on it.

Importantly, this recognizes that abs with poison flag is actually
non-negative...
2020-07-30 23:06:10 +02:00
Nikita Popov 94f8120cb9 [ConstantRange] Support abs with poison flag
This just adds the ConstantRange support, including exhaustive
testing. It's not wired up to the IR intrinsic flag yet.
2020-07-30 22:49:28 +02:00
Nikita Popov d8a98a9c35 [ConstantRange][CVP] Compute min/max/abs intrinsic ranges
Wire up ConstantRange::intrinsic() to the existing primitives for
min, max and abs.

The poison flag on abs is not yet taken into account.
2020-07-30 22:21:34 +02:00
Nikita Popov 897bdca4b8 [ConstantRange] Add API for intrinsics (NFC)
This adds a common API for compute constant ranges of intrinsics.
The intention here is that
a) we can reuse the same code across different passes that handle
   constant ranges, i.e. this can be reused in SCCP
b) we only have to add knowledge about supported intrinsics to
   ConstantRange, not any consumers.

Differential Revision: https://reviews.llvm.org/D84587
2020-07-29 22:16:27 +02:00
Florian Hahn d307174e1d [ConstantRange] Use APInt::or/APInt::and for single elements.
Currently ConstantRange::binaryAnd/binaryOr results are too pessimistic
for single element constant ranges.

If both operands are single element ranges, we can use APInt's AND and
OR implementations directly.

Note that some other binary operations on constant ranges can cover the
single element cases naturally, but for OR and AND this unfortunately is
not the case.

Reviewers: nikic, spatel, lebedev.ri

Reviewed By: spatel

Differential Revision: https://reviews.llvm.org/D76446
2020-04-01 09:50:24 +01:00
Florian Hahn 7caba33907 [ConstantRange] Add initial support for binaryXor.
The initial implementation just delegates to APInt's implementation of
XOR for single element ranges and conservatively returns the full set
otherwise.

Reviewers: nikic, spatel, lebedev.ri

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D76453
2020-03-24 12:59:50 +00:00
Florian Hahn b35c585a9a [ConstantRange] Respect destination bitwidth for cast results.
We returning a full set, we should use ResultBitWidth. Otherwise we might
it assertions when the resulting constant ranges are used later on.

Reviewers: nikic, spatel, reames

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D71937
2019-12-27 17:38:34 +00:00
Roman Lebedev 9a20c79ddc
[NFC][KnownBits] Add getMinValue() / getMaxValue() methods
As it can be seen from accompanying cleanup, it is not unheard of
to write `~Known.Zero` meaning "what maximal value can this KnownBits
produce". But i think `~Known.Zero` isn't *that* self-explanatory,
as compared to a method with a name.

Note that not all `~Known.Zero` places were cleaned up,
only those where this arguably improves things.
2019-12-03 20:04:51 +03:00
Roman Lebedev 7dddfa2a9c
[NFC] ConstantRange::subWithNoWrap(): fixup comment 2019-11-08 17:52:43 +03:00
Roman Lebedev 5a9fd76d2f
[ConstantRange] Add umul_sat()/smul_sat() methods
Summary:
To be used in `ConstantRange::mulWithNoOverflow()`,
may in future be useful for when saturating shift/mul ops are added.

These are precise as far as i can tell.

I initially though i will need `APInt::[us]mul_sat()` for these,
but it turned out much simpler to do what `ConstantRange::multiply()`
does - perform multiplication in twice the bitwidth, and then truncate.
Though here we want saturating signed truncation.

Reviewers: nikic, reames, spatel

Reviewed By: nikic

Subscribers: hiraditya, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D69994
2019-11-08 17:52:43 +03:00
Roman Lebedev 72a21ad6c9
[CR] ConstantRange::sshl_sat(): check sigdness of the min/max, not ranges
This was pointed out in review,
but forgot to stage this change into the commit itself..
2019-11-08 10:32:56 +03:00
Roman Lebedev e0ea842bae
[ConstantRange] Add `ushl_sat()`/`sshl_sat()` methods.
Summary:
To be used in `ConstantRange::shlWithNoOverflow()`,
may in future be useful for when saturating shift/mul ops are added.

Unlike `ConstantRange::shl()`, these are precise.

Reviewers: nikic, spatel, reames

Reviewed By: nikic

Subscribers: hiraditya, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D69960
2019-11-08 10:31:04 +03:00
Roman Lebedev 69ce2ae990
[ConstantRange][LVI] Use overflow flags from `sub` to constrain the range
Summary:
This notably improves non-negativity deduction:
```
| statistic                              |     old |     new | delta | % change |
| correlated-value-propagation.NumAShrs  |     209 |     227 |    18 |  8.6124% |
| correlated-value-propagation.NumAddNSW |    4972 |    4988 |    16 |  0.3218% |
| correlated-value-propagation.NumAddNUW |    7141 |    7148 |     7 |  0.0980% |
| correlated-value-propagation.NumAddNW  |   12113 |   12136 |    23 |  0.1899% |
| correlated-value-propagation.NumAnd    |     442 |     445 |     3 |  0.6787% |
| correlated-value-propagation.NumNSW    |    7160 |    7176 |    16 |  0.2235% |
| correlated-value-propagation.NumNUW    |   13306 |   13316 |    10 |  0.0752% |
| correlated-value-propagation.NumNW     |   20466 |   20492 |    26 |  0.1270% |
| correlated-value-propagation.NumSDivs  |     207 |     212 |     5 |  2.4155% |
| correlated-value-propagation.NumSExt   |    6279 |    6679 |   400 |  6.3704% |
| correlated-value-propagation.NumSRems  |      28 |      29 |     1 |  3.5714% |
| correlated-value-propagation.NumShlNUW |    2793 |    2796 |     3 |  0.1074% |
| correlated-value-propagation.NumShlNW  |    3964 |    3967 |     3 |  0.0757% |
| correlated-value-propagation.NumUDivs  |     353 |     358 |     5 |  1.4164% |
| instcount.NumAShrInst                  |   13763 |   13741 |   -22 | -0.1598% |
| instcount.NumAddInst                   |  277349 |  277348 |    -1 | -0.0004% |
| instcount.NumLShrInst                  |   27437 |   27463 |    26 |  0.0948% |
| instcount.NumOrInst                    |  102677 |  102678 |     1 |  0.0010% |
| instcount.NumSDivInst                  |    8732 |    8727 |    -5 | -0.0573% |
| instcount.NumSExtInst                  |   80872 |   80468 |  -404 | -0.4996% |
| instcount.NumSRemInst                  |    1679 |    1678 |    -1 | -0.0596% |
| instcount.NumTruncInst                 |   62154 |   62153 |    -1 | -0.0016% |
| instcount.NumUDivInst                  |    2526 |    2527 |     1 |  0.0396% |
| instcount.NumURemInst                  |    1589 |    1590 |     1 |  0.0629% |
| instcount.NumZExtInst                  |   69405 |   69809 |   404 |  0.5821% |
| instcount.TotalInsts                   | 7439575 | 7439574 |    -1 |  0.0000% |
```

Reviewers: nikic, reames, spatel

Reviewed By: nikic

Subscribers: hiraditya, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D69942
2019-11-07 16:18:03 +03:00
Roman Lebedev 7fbe5d4b2a
[ConstantRange] Add `subWithNoWrap()` method
Summary:
Much like D67339, adds ConstantRange handling for
when we know no-wrap behavior of the `sub`.

Unlike addWithNoWrap(), we only get lucky re returning empty set
for signed wrap. For unsigned, we must perform overflow check manually.

A patch that makes use of this in LVI (CVP) to be posted later.

Reviewers: nikic, shchenz, efriedma

Reviewed By: nikic

Subscribers: hiraditya, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D69918
2019-11-07 01:30:53 +03:00
Roman Lebedev 365d729e10
[ConstantRange] Cleanup addWithNoWrap() by just piggybacking on sadd_sat()/uadd_sat()
As discussed in https://reviews.llvm.org/D69918
that happens to work as intended, and returns empty set if
there is always an overflow because we get lucky with intersection.
Since there's now an explicit test for that, let's prefer cleaner code.
2019-11-07 01:30:53 +03:00
Roman Lebedev 1f665046fb
[LVI][CVP] LazyValueInfoImpl::solveBlockValueBinaryOp(): use no-wrap flags from `add` op
Summary:
This was suggested in https://reviews.llvm.org/D69277#1717210
In this form (this is what was suggested, right?), the results aren't staggering
(especially since given LVI cross-block focus)
this does catch some things (as per test-suite), but not too much:

| statistic                                        |       old |       new | delta | % change |
| correlated-value-propagation.NumAddNSW           |      4981 |      4982 |     1 |  0.0201% |
| correlated-value-propagation.NumAddNW            |     12125 |     12126 |     1 |  0.0082% |
| correlated-value-propagation.NumCmps             |      1199 |      1202 |     3 |  0.2502% |
| correlated-value-propagation.NumDeadCases        |       112 |       111 |    -1 | -0.8929% |
| correlated-value-propagation.NumMulNSW           |       275 |       278 |     3 |  1.0909% |
| correlated-value-propagation.NumMulNUW           |      1323 |      1326 |     3 |  0.2268% |
| correlated-value-propagation.NumMulNW            |      1598 |      1604 |     6 |  0.3755% |
| correlated-value-propagation.NumNSW              |      7158 |      7167 |     9 |  0.1257% |
| correlated-value-propagation.NumNUW              |     13304 |     13310 |     6 |  0.0451% |
| correlated-value-propagation.NumNW               |     20462 |     20477 |    15 |  0.0733% |
| correlated-value-propagation.NumOverflows        |         4 |         7 |     3 | 75.0000% |
| correlated-value-propagation.NumPhis             |     15366 |     15381 |    15 |  0.0976% |
| correlated-value-propagation.NumSExt             |      6273 |      6277 |     4 |  0.0638% |
| correlated-value-propagation.NumShlNSW           |      1172 |      1171 |    -1 | -0.0853% |
| correlated-value-propagation.NumShlNUW           |      2793 |      2794 |     1 |  0.0358% |
| correlated-value-propagation.NumSubNSW           |       730 |       736 |     6 |  0.8219% |
| correlated-value-propagation.NumSubNUW           |      2044 |      2046 |     2 |  0.0978% |
| correlated-value-propagation.NumSubNW            |      2774 |      2782 |     8 |  0.2884% |
| instcount.NumAddInst                             |    277586 |    277569 |   -17 | -0.0061% |
| instcount.NumAndInst                             |     66056 |     66054 |    -2 | -0.0030% |
| instcount.NumBrInst                              |    709147 |    709146 |    -1 | -0.0001% |
| instcount.NumCallInst                            |    528579 |    528576 |    -3 | -0.0006% |
| instcount.NumExtractValueInst                    |     18307 |     18301 |    -6 | -0.0328% |
| instcount.NumOrInst                              |    102660 |    102665 |     5 |  0.0049% |
| instcount.NumPHIInst                             |    318008 |    318007 |    -1 | -0.0003% |
| instcount.NumSelectInst                          |     46373 |     46370 |    -3 | -0.0065% |
| instcount.NumSExtInst                            |     79496 |     79488 |    -8 | -0.0101% |
| instcount.NumShlInst                             |     40654 |     40657 |     3 |  0.0074% |
| instcount.NumTruncInst                           |     62251 |     62249 |    -2 | -0.0032% |
| instcount.NumZExtInst                            |     68211 |     68221 |    10 |  0.0147% |
| instcount.TotalBlocks                            |    843910 |    843909 |    -1 | -0.0001% |
| instcount.TotalInsts                             |   7387448 |   7387423 |   -25 | -0.0003% |

Reviewers: nikic, reames

Reviewed By: nikic

Subscribers: hiraditya, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D69321
2019-10-23 18:17:32 +03:00
Roman Lebedev 4b6223263a [ConstantRange] makeGuaranteedNoWrapRegion(): `shl` support
Summary:
If all the shifts amount are already poison-producing,
then we can add more poison-producing flags ontop:
https://rise4fun.com/Alive/Ocwi

Otherwise, we should only consider the possible range of shift amts that don't result in poison.

For unsigned range not not overflow, we must not shift out any set bits,
and the actual limit for `x` can be computed by backtransforming
the maximal value we could ever get out of the `shl` - `-1` through
`lshr`. If the `x` is any larger than that then it will overflow.

Likewise for signed range, but just in signed domain..

This is based on the general idea outlined by @nikic in https://reviews.llvm.org/D68672#1714990

Reviewers: nikic, sanjoy

Reviewed By: nikic

Subscribers: hiraditya, llvm-commits, nikic

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D69217

llvm-svn: 375370
2019-10-20 19:36:55 +00:00
Chen Zheng 9806a1d5f9 [ConstantRange] [NFC] replace addWithNoSignedWrap with addWithNoWrap.
llvm-svn: 374016
2019-10-08 03:00:31 +00:00
Chen Zheng bfec045626 [ConstantRange] add helper function addWithNoWrap().
Differential Revision: https://reviews.llvm.org/D67339

llvm-svn: 373205
2019-09-30 12:57:53 +00:00
Nikita Popov c061b99c5b [ConstantRange] Add sdiv() support
The implementation is conceptually simple: We separate the LHS and
RHS into positive and negative components and then also compute the
positive and negative components of the result, taking into account
that e.g. only pos/pos and neg/neg will give a positive result.

However, there's one significant complication: SignedMin / -1 is UB
for sdiv, and we can't just ignore it, because the APInt result of
SignedMin would break the sign segregation. Instead we drop SignedMin
or -1 from the corresponding ranges, taking into account some edge
cases with wrapped ranges.

Because of the sign segregation, the implementation ends up being
nearly fully precise even for wrapped ranges (the remaining
imprecision is due to ranges that are both signed and unsigned
wrapping and are divided by a trivial divisor like 1). This means
that the testing cannot just check the signed envelope as we
usually do. Instead we collect all possible results in a bitvector
and construct a better sign wrapped range (than the full envelope).

Differential Revision: https://reviews.llvm.org/D61238

llvm-svn: 362430
2019-06-03 18:19:54 +00:00
Nikita Popov 332c100562 [ValueTracking][ConstantRange] Distinguish low/high always overflow
In order to fold an always overflowing signed saturating add/sub,
we need to know in which direction the always overflow occurs.
This patch splits up AlwaysOverflows into AlwaysOverflowsLow and
AlwaysOverflowsHigh to pass through this information (but it is
not used yet).

Differential Revision: https://reviews.llvm.org/D62463

llvm-svn: 361858
2019-05-28 18:08:31 +00:00
Nikita Popov 8b1fa07639 [CVP] Remove unnecessary checks for empty GNWR; NFC
The guaranteed no-wrap region is never empty, it always contains at
least zero, so these optimizations don't ever apply.

To make this more obviously true, replace the conversative return
in makeGNWR with an assertion.

llvm-svn: 361698
2019-05-25 14:11:55 +00:00
Nikita Popov f610110f1a [ConstantRange] Simplify makeGNWR implementation; NFC
Compute results in more direct ways, avoid subset intersect
operations. Extract the core code for computing mul nowrap ranges
into separate static functions, so they can be reused.

llvm-svn: 360189
2019-05-07 20:34:46 +00:00
Nikita Popov d5a403fb80 [ConstantRange] Add srem() support
Add support for srem() to ConstantRange so we can use it in LVI. For
srem the sign of the result matches the sign of the LHS. For the RHS
only the absolute value is important. Apart from that the logic is
like urem.

Just like for urem this is only an approximate implementation. The tests
check a few specific cases and run an exhaustive test for conservative
correctness (but not exactness).

Differential Revision: https://reviews.llvm.org/D61207

llvm-svn: 360055
2019-05-06 16:59:37 +00:00
Nikita Popov 7a94795b2b [ConstantRange] Add makeExactNoWrapRegion()
I got confused on the terminology, and the change in D60598 was not
correct. I was thinking of "exact" in terms of the result being
non-approximate. However, the relevant distinction here is whether
the result is

 * Largest range such that:
   Forall Y in Other: Forall X in Result: X BinOp Y does not wrap.
   (makeGuaranteedNoWrapRegion)
 * Smallest range such that:
   Forall Y in Other: Forall X not in Result: X BinOp Y wraps.
   (A hypothetical makeAllowedNoWrapRegion)
 * Both. (makeExactNoWrapRegion)

I'm adding a separate makeExactNoWrapRegion method accepting a
single APInt (same as makeExactICmpRegion) and using it in the
places where the guarantee is relevant.

Differential Revision: https://reviews.llvm.org/D60960

llvm-svn: 359402
2019-04-28 15:40:56 +00:00
Nikita Popov c0fa4ec01d [ConstantRange] Add abs() support
Add support for abs() to ConstantRange. This will allow to handle
SPF_ABS select flavor in LVI and will also come in handy as a
primitive for the srem implementation.

The implementation is slightly tricky, because a) abs of signed min
is signed min and b) sign-wrapped ranges may have an abs() that is
smaller than a full range, so we need to explicitly handle them.

Differential Revision: https://reviews.llvm.org/D61084

llvm-svn: 359321
2019-04-26 16:50:31 +00:00
Florian Hahn 1038137f14 [ConstantRange] [a, b) udiv a full range is [0, umax(b)).
Reviewers: nikic, spatel, efriedma

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D60536

llvm-svn: 359180
2019-04-25 10:12:43 +00:00
Nikita Popov f945429fed [ConstantRange] Add urem support
Add urem support to ConstantRange, so we can handle in in LVI. This
is an approximate implementation that tries to capture the most useful
conditions: If the LHS is always strictly smaller than the RHS, then
the urem is a no-op and the result is the same as the LHS range.
Otherwise the lower bound is zero and the upper bound is
min(LHSMax, RHSMax - 1).

Differential Revision: https://reviews.llvm.org/D60952

llvm-svn: 359019
2019-04-23 18:00:17 +00:00
Nikita Popov 5aacc7a573 Revert "[ConstantRange] Rename make{Guaranteed -> Exact}NoWrapRegion() NFC"
This reverts commit 7bf4d7c07f2fac862ef34c82ad0fef6513452445.

After thinking about this more, this isn't right, the range is not exact
in the same sense as makeExactICmpRegion(). This needs a separate
function.

llvm-svn: 358876
2019-04-22 09:01:38 +00:00
Nikita Popov 5299e25f50 [ConstantRange] Rename make{Guaranteed -> Exact}NoWrapRegion() NFC
Following D60632 makeGuaranteedNoWrapRegion() always returns an
exact nowrap region. Rename the function accordingly. This is in
line with the naming of makeExactICmpRegion().

llvm-svn: 358875
2019-04-22 08:36:05 +00:00
Nikita Popov 198ab60136 [ConstantRange] Add saturating add/sub methods
Add support for uadd_sat and friends to ConstantRange, so we can
handle uadd.sat and friends in LVI. The implementation is forwarding
to the corresponding APInt methods with appropriate bounds.

One thing worth pointing out here is that the handling of wrapping
ranges is not maximally accurate. A simple example is that adding 0
to a wrapped range will return a full range, rather than the original
wrapped range. The tests also only check that the non-wrapping
envelope is correct and minimal.

Differential Revision: https://reviews.llvm.org/D60946

llvm-svn: 358855
2019-04-21 15:23:05 +00:00
Nikita Popov dbc3fbafe7 [ConstantRange] Add getNonEmpty() constructor
ConstantRanges have an annoying special case: If upper and lower are
the same, it can be either an empty or a full set. When constructing
constant ranges nearly always a full set is intended, but this still
requires an explicit check in many places.

This revision adds a getNonEmpty() constructor that disambiguates this
case: If upper and lower are the same, a full set is created.

Differential Revision: https://reviews.llvm.org/D60947

llvm-svn: 358854
2019-04-21 15:22:54 +00:00
Fangrui Song 43d110bd27 [ConstantRange] Delete unused getSetSize
getSetSize returns an APInt that is 1 bit wider. The APInt is typically 65-bit and requires memory allocation. isSizeStrictlySmallerThan and isSizeLargerThan are preferred. The last use of this helper method was removed by rL302385.

llvm-svn: 358347
2019-04-14 04:45:04 +00:00
Nikita Popov a96480ebc1 [ConstantRange] Disallow NUW | NSW in makeGuaranteedNoWrapRegion()
As motivated in D60598, this drops support for specifying both NUW and
NSW in makeGuaranteedNoWrapRegion(). None of the users of this function
currently make use of this.

When both NUW and NSW are specified, the exact nowrap region has two
disjoint parts and makeGNWR() returns one of them. This result doesn't
seem to be useful for anything, but makes the semantics of the function
fuzzier.

Differential Revision: https://reviews.llvm.org/D60632

llvm-svn: 358340
2019-04-13 19:43:45 +00:00
Nikita Popov 3dc7c7ca31 [ConstantRange] Clarify makeGuaranteedNoWrapRegion() guarantees; NFC
makeGuaranteedNoWrapRegion() is actually makeExactNoWrapRegion() as
long as only one of NUW or NSW is specified. This is not obvious from
the current documentation, and some code seems to think that it is
only exact for single-element ranges. Clarify docs and add tests to
be more confident this really holds.

There are currently no users of makeGuaranteedNoWrapRegion() that
pass both NUW and NSW. I think it would be best to drop support for
this entirely and then rename the function to makeExactNoWrapRegion().

Knowing that the no-wrap region is exact is useful, because we can
backwards-constrain values. What I have in mind in particular is
that LVI should be able to constrain values on edges where the
with.overflow overflow flag is false.

Differential Revision: https://reviews.llvm.org/D60598

llvm-svn: 358305
2019-04-12 19:36:47 +00:00
Nikita Popov e319eafb20 [ConstantRange] Add unsignedMulMayOverflow()
Same as the other ConstantRange overflow checking methods, but for
unsigned mul. In this case there is no cheap overflow criterion, so
using umul_ov for the implementation.

Differential Revision: https://reviews.llvm.org/D60574

llvm-svn: 358228
2019-04-11 21:10:33 +00:00
Fangrui Song dc1f4a6764 [ConstantRange] Delete redundnt {z,s}extOrSelf for multiplication
These calls are redundant because the quotients have the same BitWidth
as MinValue/MaxValue.

llvm-svn: 357886
2019-04-08 07:29:24 +00:00
Nikita Popov f38b46ffca [ConstantRange] Add signed/unsigned unionWith()
This extends D59959 to unionWith(), allowing to specify that a
non-wrapping unsigned/signed range is preferred. This is somewhat
less useful than the intersect case, because union operations are
rarer. An example use would the the phi union computed in SCEV.

The implementation is mostly a straightforward use of getPreferredRange(),
but I also had to adjust some <=/< checks to make sure that no ranges with
lower==upper get constructed before they're passed to getPreferredRange(),
as these have additional constraints.

Differential Revision: https://reviews.llvm.org/D60377

llvm-svn: 357876
2019-04-07 20:20:24 +00:00
Nikita Popov 4246106aba [ConstantRange] Add unsigned and signed intersection types
The intersection of two ConstantRanges may consist of two disjoint
ranges. As we can only return one range as the result, we need to
return one of the two possible ranges that cover both. Currently the
result is picked based on set size. However, this is not always
optimal: If we're in an unsigned context, we'd prefer to get a large
unsigned range over a small signed range -- the latter effectively
becomes a full set in the unsigned domain.

This revision adds a PreferredRangeType, which can be either Smallest,
Unsigned or Signed. Smallest is the current behavior and Unsigned and
Signed are new variants that prefer not to wrap the unsigned/signed
domain. The new type isn't used anywhere yet (but SCEV will be a good
first user, see D60035).

I've also added some comments to illustrate the various cases in
intersectWith(), which should hopefully make it more obvious what is
going on.

Differential Revision: https://reviews.llvm.org/D59959

llvm-svn: 357873
2019-04-07 18:44:36 +00:00
Nikita Popov bad648a23e [ConstantRange] Add isAllNegative() and isAllNonNegative() methods
Add isAllNegative() and isAllNonNegative() methods to ConstantRange,
which determine whether all values in the constant range are
negative/non-negative.

This is useful for replacing KnownBits isNegative() and isNonNegative()
calls when changing code to use constant ranges.

Differential Revision: https://reviews.llvm.org/D60264

llvm-svn: 357871
2019-04-07 17:52:40 +00:00
Marcello Maggioni 30eb575811 [ConstantRange] Shl considers full-set shifting to last bit position.
if we do SHL of two 16-bit ranges like [0, 30000) with [1,2) we get
"full-set" instead of what I would have expected [0, 60000) which is
still in the 16-bit unsigned range.

This patch changes the SHL algorithm to allow getting a usable range
even in this case.

Differential Revision: https://reviews.llvm.org/D57983

llvm-svn: 357854
2019-04-07 06:12:44 +00:00
Nikita Popov 7b4e9a1c7a [ConstantRange] Add isWrappedSet() and isUpperSignWrapped()
Split off from D59749. This adds isWrappedSet() and
isUpperSignWrapped() set with the same behavior as isSignWrappedSet()
and isUpperWrapped() for the respectively other domain.

The methods isWrappedSet() and isSignWrappedSet() will not consider
ranges of the form [X, Max] == [X, 0) and [X, SignedMax] == [X, SignedMin)
to be wrapping, while isUpperWrapped() and isUpperSignWrapped() will.

Also replace the checks in getUnsignedMin() and friends with method
calls that implement the same logic.

llvm-svn: 357112
2019-03-27 19:12:09 +00:00
Nikita Popov 6d855ea024 [ConstantRange] Rename isWrappedSet() to isUpperWrapped()
Split out from D59749. The current implementation of isWrappedSet()
doesn't do what it says on the tin, and treats ranges like
[X, Max] as wrapping, because they are represented as [X, 0) when
using half-inclusive ranges. This also makes it inconsistent with
the semantics of isSignWrappedSet().

This patch renames isWrappedSet() to isUpperWrapped(), in preparation
for the introduction of a new isWrappedSet() method with corrected
behavior.

llvm-svn: 357107
2019-03-27 18:19:33 +00:00
Nikita Popov e6eef49f05 [ConstantRange] Exclude full set from isSignWrappedSet()
Split off from D59749. This uses a simpler and more efficient
implementation of isSignWrappedSet(), and considers full sets
as non-wrapped, to be consistent with isWrappedSet(). Otherwise
the behavior is unchanged.

There are currently only two users of this function and both already
check for isFullSet() || isSignWrappedSet(), so this is not going to
cause a change in overall behavior.

Differential Revision: https://reviews.llvm.org/D59848

llvm-svn: 357039
2019-03-26 22:37:26 +00:00
Nikita Popov 977934f00f [ConstantRange] Add getFull() + getEmpty() named constructors; NFC
This adds ConstantRange::getFull(BitWidth) and
ConstantRange::getEmpty(BitWidth) named constructors as more readable
alternatives to the current ConstantRange(BitWidth, /* full */ false)
and similar. Additionally private getFull() and getEmpty() member
functions are added which return a full/empty range with the same bit
width -- these are commonly needed inside ConstantRange.cpp.

The IsFullSet argument in the ConstantRange(BitWidth, IsFullSet)
constructor is now mandatory for the few usages that still make use of it.

Differential Revision: https://reviews.llvm.org/D59716

llvm-svn: 356852
2019-03-24 09:34:40 +00:00
Nikita Popov 5e7b62de05 [ConstantRange] Add assertion for KnownBits validity; NFC
Following the suggestion in D59475.

llvm-svn: 356346
2019-03-17 21:25:32 +00:00
Nikita Popov ef2d979943 [ConstantRange] Add fromKnownBits() method
Following the suggestion in D59450, I'm moving the code for constructing
a ConstantRange from KnownBits out of ValueTracking, which also allows us
to test this code independently.

I'm adding this method to ConstantRange rather than KnownBits (which
would have been a bit nicer API wise) to avoid creating a dependency
from Support to IR, where ConstantRange lives.

Differential Revision: https://reviews.llvm.org/D59475

llvm-svn: 356339
2019-03-17 20:24:02 +00:00