2010 Commits

Author SHA1 Message Date
annamthomas
54a9f0007c
[SCEV] Fix BinomialCoefficient Iteration to fit in W bits (#88010)
BinomialCoefficient computes the value of W-bit IV at iteration It of a loop. When W is 1, we can call multiplicative inverse on 0 which triggers an assert since 1b76120.
    
Since the arithmetic is supposed to wrap if It or K does not fit in W bits, do the truncation into W bits after we do the shift.
    
 Fixes #87798
2024-04-10 09:02:23 -04:00
Jay Foad
1b761205f2
[APInt] Add a simpler overload of multiplicativeInverse (#87610)
The current APInt::multiplicativeInverse takes a modulus which can be
any value, but all in-tree callers use a power of two. Moreover, most
callers want to use two to the power of the width of an existing APInt,
which is awkward because 2^N is not representable as an N-bit APInt.

Add a new overload of multiplicativeInverse which implicitly uses
2^BitWidth as the modulus.
2024-04-04 16:11:06 +01:00
Justin Lebar
fab2bb8bfd
Add llvm::min/max_element and use it in llvm/ and mlir/ directories. (#84678)
For some reason this was missing from STLExtras.
2024-03-10 20:00:13 -07:00
Philip Reames
1a37147af5
[SCEV] Match both (-1)b + a and a + (-1)b as a - b (#84247)
In our analysis of guarding conditions, we were converting a-b == 0 into
a == b alternate form, but we were only checking for one of the two
forms for the sub. There's no requirement that the multiply only be on
the LHS of the add.
2024-03-06 15:57:34 -08:00
Philip Reames
0d38f21e4a [SCEV] Extend type hint in analysis output to all backedge kinds
This extends the work from 7755c26 to all of the different backend
taken count kinds that we print for the scev analysis printer.  As
before, the goal is to cut down on confusion as i4 -1 is a very
different (unsigned) value from i32 -1.
2024-03-06 13:08:05 -08:00
Philip Reames
8b5b294ec2 [SCEV] Print predicate backedge count only if new information available
When printing the result of SCEV's analysis, we can avoid printing
the predicated backedge taken count and the predicates if the predicates
are empty and no new information is provided.  This helps to reduce the
verbosity of the output.
2024-03-06 10:24:32 -08:00
Philip Reames
7755c26195 [SCEV] Include type when printing constant max backedge taken count
When printing the result of the analysis, i8 -1 and i64 -1 are quite
different in terms of analysis quality.  In a recent conversion with
a new contributor, we ran into exactly this confusion.

Adding the type for constant scevs more globally seems worthwhile, but
introduces a much larger test diff.  I'm splitting this off first since
it addresses the immediate need, and then going to do some further
changes to clarify a few related bits of analysis result output.
2024-03-06 08:48:25 -08:00
Philip Reames
df9ba13579
[LV] Handle scalable VFs in optimizeForVFAndUF (#82669)
Given a scalable VF of the form <NumElts * VScale>, this patch adds the
ability to discharge a backedge test for a loop whose trip count is
between (NumElts, MinVScale*NumElts).

A couple of notes on this:
* Annoyingly, I could not figure out to write a test for this case. My
attempt is checked in as test32_i8 in f67ef1a, but LV uses a fixed
vector in that case, and ignored the force flags.
* This depends on 9eb5f94f to avoid appearing like a regression. Since
SCEV doesn't know any upper bound on vscale without the vscale_range
attribute (it doesn't query TTI), the ranges overflow on the multiply.
Arguably, this is fixing a bug in the current LV code since in theory
vscale can be large enough to overflow for real, but no actual target is
going to see that case.
2024-03-04 13:49:35 -08:00
Nikita Popov
43dd1e84df [SCEV] Move canReuseInstruction() helper into SCEV (NFC)
To allow reusing it in IndVars.
2024-02-02 16:48:00 +01:00
Philip Reames
e4d01bb227
[SCEV] Special case sext in isKnownNonZero (#77834)
The existing logic in isKnownNonZero relies on unsigned ranges, which
can be problematic when our range calculation is imprecise. Consider the
following:
  %offset.nonzero = or i32 %offset, 1
  -->  %offset.nonzero U: [1,0) S: [1,0)
  %offset.i64 = sext i32 %offset.nonzero to i64
  -->  (sext i32 %offset.nonzero to i64) U: [-2147483648,2147483648)
                                         S: [-2147483648,2147483648)

Note that the unsigned range for the sext does contain zero in this case
despite the fact that it can never actually be zero.

Instead, we can push the query down one level - relying on the fact that
the sext is an invertible operation and that the result can only be zero
if the input is. We could likely generalize this reasoning for other
invertible operations, but special casing sext seems worthwhile.
2024-01-12 07:45:28 -08:00
Simon Pilgrim
3736e1d1cd [SCEV] Ensure shift amount is in range before calling getZExtValue()
Fixes #76234
2023-12-22 14:16:54 +00:00
Nikita Popov
90d82412ea
[SCEV] Use loop guards when checking that RHS >= Start (#75039)
Loop guards tend to provide better results when it comes to reasoning
about ranges than isLoopEntryGuardedByCond(). See the test change for
the motivating case.

I have retained both the loop guard check and the implied cond based
check for now, though the latter only seems to impact a single test and
only via side effects (nowrap flag calculation) at that.
2023-12-12 09:41:54 +01:00
Nikita Popov
ff0e4fb89a
[SCEV] Use or disjoint flag (#74467)
Use the disjoint flag to convert or to add instead of calling the
haveNoCommonBitsSet() ValueTracking query. This ensures that we can
reliably undo add -> or canonicalization, even in cases where the
necessary information has been lost or is too complex to reinfer in
SCEV.

I have updated the bulk of the test coverage to add the necessary
disjoint flags in advance.
2023-12-05 17:01:46 +01:00
Nikita Popov
de176d8c54
[SCEV][LV] Invalidate LCSSA exit phis more thoroughly (#69909)
This an alternative to #69886. The basic problem is that SCEV can look
through trivial LCSSA phis. When the phi node later becomes non-trivial,
we do invalidate it, but this doesn't catch uses that are not covered by
the IR use-def walk, such as those in BECounts.

Fix this by adding a special invalidation method for LCSSA phis, which
will also invalidate all the SCEVUnknowns/SCEVAddRecExprs used by the
LCSSA phi node and defined in the loop.

We should probably also use this invalidation method in other places
that add predecessors to exit blocks, such as loop unrolling and loop
peeling.

Fixes #69097.
Fixes #66616.
Fixes #63970.
2023-11-17 09:34:24 +01:00
Björn Pettersson
8fc0aca5d1
[SCEV] Support larger than 64-bit types in ashr(add(shl(x, n), c), m) (#71600)
In commit 5a9a02f67b771fb2edcf06 scalar evolution got support for
computing SCEV:s for (ashr(add(shl(x, n), c), m)) constructs. The code
however used APInt::getZExtValue without first checking that the APInt
would fit inside an uint64_t. When for example using 128-bit types we
ended up in assertion failures (or maybe miscompiles in non-assert
builds).
This patch simply avoid converting from APInt to uint64_t when creating
the truncated constant. We can just truncate the APInt instead.
2023-11-08 11:29:12 +01:00
Philip Reames
a7f35d54ee
[SCEV] Extend isImpliedCondOperandsViaRanges to independent predicates (#71110)
As far as I can tell, there's nothing in this code which actually
assumes the two predicates in (FoundLHS FoundPred FoundRHS) => (LHS Pred
RHS) are the same.

Noticed while investigating something else, this is purely an
oppurtunistic optimization while I'm looking at the code. Unfortunately,
this doesn't solve my original problem. :)
2023-11-07 07:25:47 -08:00
Nikita Popov
8f76522a61 [SCEV] Remove mul handling from BuildConstantFromSCEV()
We can't support this once mul constant expressions are removed,
and this is not useful in any practical sense (as this code is
primarily intended for GEP expressions).
2023-11-06 16:58:04 +01:00
Nikita Popov
a8ac6a9868 [SCEV] Remove newline after predicates in dump
update_analyze_test_checks.py will now insert check lines for
empty lines, which means that all the existing test coverage will
have a spurious change to check for the newline after "Predicates:".

I don't think we actually want to have that newline, so drop it
before it gets into more test coverage.
2023-11-03 15:43:30 +01:00
Daniil Suchkov
1344b65c90
[SCEV] Fix incorrect NUW inference (#70521)
This patch fixes a miscompile in LSR caused by incorrect inference of
NUW flag for AddRec: we shouldn't infer no-wrap flags based on a
comparison which doesn't fully control the loop exit.
2023-10-31 11:43:57 -07:00
Danila Malyutin
ba1349fc31
[SCEV] Fix "quick and dirty" difference that could lead to assert (#70688)
The old algorithm would remove all operands matching %step SCEV when it
intended to only remove a single one. This lead to assert when
SCEVAddExpr was of the form %step + %step and potential miscompiles in
similar cases. Such SCEVs could be created when construction reached
depth thresholds.

Fixes #70348
2023-10-31 00:50:57 +03:00
Kazu Hirata
f9306f6de3
[ADT] Rename llvm::erase_value to llvm::erase (NFC) (#70156)
C++20 comes with std::erase to erase a value from std::vector.  This
patch renames llvm::erase_value to llvm::erase for consistency with
C++20.

We could make llvm::erase more similar to std::erase by having it
return the number of elements removed, but I'm not doing that for now
because nobody seems to care about that in our code base.

Since there are only 50 occurrences of erase_value in our code base,
this patch replaces all of them with llvm::erase and deprecates
llvm::erase_value.
2023-10-24 23:03:13 -07:00
Nikita Popov
d4300154b6 Revert "[ValueTracking] Remove by-ref computeKnownBits() overloads (NFC)"
This reverts commit b5743d4798b250506965e07ebab806a3c2d767cc.

This causes some minor compile-time impact. Revert for now, better
to do the change more gradually.
2023-10-16 14:04:09 +02:00
Nikita Popov
b5743d4798 [ValueTracking] Remove by-ref computeKnownBits() overloads (NFC)
Remove the old overloads that accept KnownBits by reference, in
favor of those that return it by value.
2023-10-16 13:00:31 +02:00
Nikita Popov
80fa5a6377 [ValueTracking] Use SimplifyQuery in haveNoCommonBitsSet() (NFC)
Pass SimplifyQuery instead of unpacked list of arguments.
2023-10-10 11:39:59 +02:00
Nikita Popov
32ec6d91a1
[SCEV] Make invalidation in SCEVCallbackVH more thorough (#68316)
When a SCEVCallbackVH is RAUWed, we currently do a def-use walk and
remove dependent instructions from the ValueExprMap. However, unlike
SCEVs usual invalidation, this does not forget memoized values.

The end result is that we might end up removing a SCEVUnknown from the
map, while that expression still has users. Due to that, we may later
fail to invalide those expressions. In particular, invalidation of loop
dispositions only does something if there is an expression for the
value, which would not be the case here.

Fix this by using the standard forgetValue() API, instead of rolling a
custom variant.

Fixes https://github.com/llvm/llvm-project/issues/68285.
2023-10-10 10:55:57 +02:00
Nikita Popov
1c3fdb3d1e Revert "[SCEV] Don't invalidate past dependency-breaking instructions"
Unforuntately, the assumption underlying this optimization is
incorrect for getSCEVAtScope(): A SCEVUnknown instruction with
operands that have constant loop exit values can evaluate to
a constant, thus creating a dependency from an "always unknown"
instruction.

Losing this optimization is quite unfortunate, but it doesn't
seem like there is any simple workaround for this.

Fixes #68260.

This reverts commit 3ddd1ffb721dd0ac3faa4a53c76b6904e862b7ab.
2023-10-09 16:35:01 +02:00
Nikita Popov
a56071ffb7 [SCEV] Don't require positive BTC when non-zero is sufficient
The only thing we care about here is that we don't exit on the
first iteration. Whether the BTC is large enough to overflow the
signed integer space is not relevant.
2023-10-09 14:42:09 +02:00
Nikita Popov
15b687131f [SCEV] Remove unnecessary cast code (NFC)
The types should always match here. Possibly this is a leftover
from pre-opaque-pointers times.
2023-09-29 10:38:12 +02:00
Nikita Popov
c887700f3b [SCEV] Remove zext/sext from BuildConstantForSCEV
In preparation for removing these constant expressions.
2023-09-28 15:23:58 +02:00
Nikita Popov
6dd8ec6465 [SCEV] Work on APInt instead of ConstantExpr (NFC)
Avoid an unnecessary use of ConstantExpr::getZExt() when
APInt::zext() is sufficient.
2023-09-28 15:23:58 +02:00
Kazu Hirata
619c50125b [Analysis] Use drop_begin (NFC) 2023-09-22 00:46:32 -07:00
Nikita Popov
2d8d622c73 [SCEV] Require that addrec operands dominate the loop
SCEVExpander currently has special handling for the case where the
start or the step of an addrec do not dominate the loop header,
which is not used by any lit test.

Initially I thought that this is entirely dead code, because
addrec operands are required to be loop invariant. However,
SCEV currently allows creating an addrec with operands that are
loop invariant but defined *after* the loop.

This doesn't seem like a useful case to allow, and we don't
appear to be using this outside a single easy to adjust unit test.
2023-09-22 09:02:54 +02:00
Nikita Popov
efe4e7a026
[SCEV] Fix incorrect nsw inference for multiply of addrec (#66500)
SCEV currently preserves the nsw flag when performing an nsw multiply of
an nsw addrec. While this is legal for nuw, this is not generally the
case for nsw.

This is because nsw mul does not distribute over nsw add:
https://alive2.llvm.org/ce/z/mergCt

Instead, we need either both nuw and nsw to be set
(https://alive2.llvm.org/ce/z/7wpgGc) or explicitly prove that the
distributed multiplications are also nsw
(https://alive2.llvm.org/ce/z/wef9su).

Fixes https://github.com/llvm/llvm-project/issues/66066.
2023-09-18 08:23:10 +02:00
Tejas Joshi
0609b65aaf
[SCEV] Fix potentially empty set for unsigned ranges
The following commit enabled the analysis of ranges for heap allocations:
22ca38da25e19a7c5fcfeb3f22159aba92ec381e

The range turns out to be empty in cases such as the one in test (which
is [1,1)), leading to an assertion failure. This patch fixes for the
same case.

Fixes https://github.com/llvm/llvm-project/issues/63856

Reviewed By: fhahn

Differential Revision: https://reviews.llvm.org/D159160
2023-09-04 10:46:53 +01:00
Vedant Paranjape
5a9a02f67b [SCEV] Compute SCEV for ashr(add(shl(x, n), c), m) instr triplet
%x = shl i64 %w, n
%y = add i64 %x, c
%z = ashr i64 %y, m

The above given instruction triplet is seen many times in the generated
LLVM IR, but SCEV model is not able to compute the SCEV value of AShr
instruction in this case.

This patch models the two cases of the above instruction pattern using
the following expression:

=> sext(add(mul(trunc(w), 2^(n-m)), c >> m))

1) when n = m the expression reduces to sext(add(trunc(w), c >> n))
as n-m=0, and multiplying with 2^0 gives the same result.

2) when n > m the expression works as given above.

It also adds several unittest to verify that SCEV is able to compute
the value.

$ opt sext-add-inreg.ll -passes="print<scalar-evolution>"

Comparing the snippets of the result of SCEV analysis:

* SCEV of ashr before change
----------------------------
%idxprom = ashr exact i64 %sext, 32
  -->  %idxprom U: [-2147483648,2147483648) S: [-2147483648,2147483648)
  Exits: 8                LoopDispositions: { %for.body: Variant }

* SCEV of ashr after change
---------------------------
%idxprom = ashr exact i64 %sext, 32
  -->  {0,+,1}<nuw><nsw><%for.body> U: [0,9) S: [0,9)
  Exits: 8                LoopDispositions: { %for.body: Computable }

LoopDisposition of the given SCEV was LoopVariant before, after adding
the new way to model the instruction, the LoopDisposition becomes
LoopComputable as it is able to compute the SCEV of the instruction.

Differential Revision: https://reviews.llvm.org/D152278
2023-08-25 05:42:08 +00:00
Nikita Popov
1c6e6432ca [SCEVExpander] Fix incorrect reuse of more poisonous instructions (PR63763)
SCEVExpander tries to reuse existing instruction with the same
SCEV expression. However, doing this replacement blindly is not
safe, because the instruction might be more poisonous.

What we were already doing is to drop poison-generating flags on
the reused instruction. But this is not the only way that more
poison can be introduced. The poison-generating flag might not
be directly on the reused instruction, or the poison contribution
might come from something like 0 * %var, which folds to 0 but can
still introduce poison.

This patch fixes the issue in a principled way, by determining which
values can contribute poison to the SCEV expression, and then
checking whether any additional values can contribute poison to the
instruction being reused. Poison-generating flags are dropped if
doing that enables reuse.

This is a pretty big hammer and does cause some regressions in
tests, but less than I would have expected. I wasn't able to come
up with a less intrusive fix that still satisfies the correctness
requirements.

Fixes https://github.com/llvm/llvm-project/issues/63763.
Fixes https://github.com/llvm/llvm-project/issues/63926.
Fixes https://github.com/llvm/llvm-project/issues/64333.
Fixes https://github.com/llvm/llvm-project/issues/63727.

Differential Revision: https://reviews.llvm.org/D158181
2023-08-22 09:27:07 +02:00
Nikita Popov
b108c11e46 [SCEV] Move SCEVPoisonCollector outside function (NFC)
To allow reusing it. Also switch it to store SCEVUnknown rather
than SCEV, as only these can produce poison.
2023-08-11 16:41:31 +02:00
Nikita Popov
bbc8079906 [SCEV] Remove unnecessary bitcast (NFC) 2023-08-09 16:21:54 +02:00
Maksim Kita
96cae819cb [ScalarEvolution][NFC] Typo fix
Fix typo in ScalarEvolution public method.

Differential Revision: https://reviews.llvm.org/D156621
2023-07-31 20:16:15 +03:00
Ivan Kosarev
e9df4c9892 [ADT] Support iterating size-based integer ranges.
It seems the ranges start with 0 in most cases.

Reviewed By: dblaikie, gchatelet

Differential Revision: https://reviews.llvm.org/D156135
2023-07-26 16:28:41 +01:00
Arthur Eubanks
b4d9cd2d61 [NFC] Update stale comment after D154001 2023-06-29 09:36:10 -07:00
Arthur Eubanks
22ca38da25 [ScalarEvolution] Analyze ranges for heap allocations
Followup to D153624. Allows for better exit count calculations for loops checking heap allocations against null.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D154001
2023-06-29 09:35:20 -07:00
Liren Peng
75a73c983f Revert "[ScalarEvolution] Infer loop max trip count from array accesses"
This reverts commit 57e093162e27334730d8ed8f7b25b1b6f65ec8c8.
2023-06-29 17:27:38 +08:00
Nikita Popov
3cd4571405 [SCEV] Make use of non-null pointers for range calculation
We know that certain pointers (e.g. non-extern-weak globals or
allocas in default address space) are not null, in which case the
lowest address they can be allocated at is their alignment.

This allows us to calculate better exit counts for loops that have
an additional null check in the guarding condition
(see alloca_icmp_null_exit_count).

Differential Revision: https://reviews.llvm.org/D153624
2023-06-29 09:09:17 +02:00
Vitaly Buka
1764924f39 [SCEV] Optimize FoldID
Improve compile time

https://llvm-compile-time-tracker.com/compare.php?from=773e5dfbc6bf4d4c5be568a039661e9baad80d15&to=7ba15f3a4b59181110e73dc397a9fe56165a2b73&stat=instructions:u

Reviewed By: MaskRay

Differential Revision: https://reviews.llvm.org/D144335
2023-06-27 16:59:34 -07:00
Nikita Popov
dac973226a [SCEV] Print block dispositions on mismatch (NFC) 2023-06-26 15:26:44 +02:00
Elliot Goodrich
b0abd4893f [llvm] Add missing StringExtras.h includes
In preparation for removing the `#include "llvm/ADT/StringExtras.h"`
from the header to source file of `llvm/Support/Error.h`, first add in
all the missing includes that were previously included transitively
through this header.
2023-06-25 15:42:22 +01:00
Nikita Popov
406e9c9372 [SCEV] Use object size for allocas as well
The object size and alignment based restriction on the possible
allocation range also applies to allocas, not just globals, so
handle them as well.

We shouldn't really need any type restriction here at all, but
for now stay conservative.
2023-06-23 12:38:12 +02:00
Nikita Popov
6555b5dc99 [SCEV] Store getValue() result in variable (NFC) 2023-06-23 12:31:36 +02:00
Dmitry Makogon
ce1ac1cf18 [SCEV] Don't store AddRec loop when simplifying multiplication of AddRecs
When multiplying several AddRecs, we do the following simplification:

{A1,+,A2,+,...,+,An}<L> * {B1,+,B2,+,...,+,Bn}<L> = {x=1 in [ sum y=x..2x
	[ sum z=max(y-x, y-n)..min(x,n) [
		choose(x, 2x)*choose(2x-y, x-z)*A_{y-z}*B_z]]
	],+,...up to x=2n}

This is done iteratively, pair by pair. So if we try to multiply three AddRecs
A1, A2, A3, then we'd try to simplify A1 * A2 to A1' and then try to
simplify A1' * A3 if A1' is also an AddRec.
The transform is only legal if the loops of the two AddRecs are the same.
It is checked in the code, but the loop of one of the AddRecs is stored
in a local variable and doesn't get updated when we simplify a pair to a new AddRec.
In the motivating test the new AddRec A1' was created for a different loop and,
as the loop variable didn't get updated, the check for different loops passed and
the transform worked for two AddRecs from different loops.
So it created a wrong SCEV. And it caused LSR to replace an instruction with another
one that had the same SCEV as the incorrectly computed one.

Differential Revision: https://reviews.llvm.org/D153254
2023-06-22 15:49:15 +07:00