2059 Commits

Author SHA1 Message Date
Nikita Popov
2df4a3b4ac [SCEV] Remove an unnecessary switch (NFC)
Just the scevUnconditionallyPropagatesPoisonFromOperands() check
is sufficient. Also rename the flag to be more in line with the
more general predicate.
2023-03-03 14:37:40 +01:00
Dmitry Makogon
94b35eef4e [ScalarEvolution] Factor out RewriteMap utilities in applyLoopGuards (NFC)
This factors out two utilities used with RewriteMap in applyLoopGuards:
 - AddRewrite, which puts a rewrite rule in the map and if needed registers
   the rewrite in the list of rewritten expressions,
 - GetMaybeRewritten, which checks whether an expression has already been
   rewritten, and if so, returns the rewrite. Otherwise, returns the given
   expression.

This may be needed when adding new rewrite rules as not to copy-paste this
code.
2023-03-03 19:22:28 +07:00
Paul Walker
62d11b2cca Revert "Revert "[SCEV] Add SCEVType to represent vscale.""
Relanding after fixing Polly related build error.

This reverts commit 7b26dcae9eaf8cdcba7fef032fd83d060dffd4b4.
2023-03-02 13:14:07 +00:00
Paul Walker
7b26dcae9e Revert "[SCEV] Add SCEVType to represent vscale."
This reverts commit 7912f5cc92f65ad0d3c705f3683a0b69dbedcc57.
2023-03-02 11:59:50 +00:00
Paul Walker
7912f5cc92 [SCEV] Add SCEVType to represent vscale.
This is part of an effort to remove ConstantExpr based
representations of `vscale` so that its LangRef definiton can
be relaxed to accommodate a less strict definition of constant.

Differential Revision: https://reviews.llvm.org/D144891
2023-03-02 11:11:36 +00:00
Florian Hahn
2f3c748c45
[SCEV] Hoist common cleanup code to function. (NFC)
This allows for easier updating of common code in follow-on patches.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D144847
2023-02-27 20:38:39 +01:00
Nikita Popov
0805d9d5aa [SCEV] Make scalable size representation more explicit
Represent scalable type sizes using C * vscale, where vscale is
the vscale constant expression. This exposes a bit more information
to SCEV, because the vscale multiplier is explicitly modeled in SCEV
(rather than part of the sizeof expression).

This is mainly intended as an alternative to D143642.

Differential Revision: https://reviews.llvm.org/D144624
2023-02-27 10:57:53 +01:00
Simon Pilgrim
aa6dc8ec47 [ScalarEvolution] Fix unused variable warnings. NFC.
Replace dyn_cast<> with isa<> as we don't actually need the variable
2023-02-25 21:27:57 +00:00
Leonard Chan
608ee703e5 [SCEV] Ensure SCEV does not replace aliases with their aliasees
Passes in general shouldn't replace an alias with the aliasee (see
https://reviews.llvm.org/D66606). This can lead to situations where a
linkonce_odr symbol (which could be interposable if lowered to weak
linkage) can be replaced with a local aliasee which won't be
interposable. SVEC does this when the function is invoked by
FunctionPass Manager -> Loop Pass Manager -> Induction Variable Users in
the codegen pipeline. This was found in hwasan instrumented code where a
linonce_odr alias was replaced with its private aliasee.

This fixes the bug descriped at
https://github.com/llvm/llvm-project/issues/60668.

Differential Revision: https://reviews.llvm.org/D144035
2023-02-23 19:59:25 +00:00
komalon1
02e08d06aa Revert "[SCEV] Preserve divisibility and min/max information in applyLoopGuards"
This reverts commit 219ba2fb7b0ae89101f3c81a47fe4fc4aa80dea4.
2023-02-23 14:44:03 +02:00
Alon Kom
219ba2fb7b [SCEV] Preserve divisibility and min/max information in applyLoopGuards
applyLoopGuards doesn't always preserve information when there are multiple assumes.

This patch tries to deal with multiple assumes regarding a SCEV's divisibility and min/max values, and rewrite it into a SCEV that still preserves all of the information.
For example, let the trip count of the loop be TC. Consider the 3 following assumes:

1. __builtin_assume(TC % 8 == 0);
2. __builtin_assume(TC > 0);
3. __builtin_assume(TC < 100);

Before this patch, depending on the assume processing order applyLoopGuards could create the following SCEV:
max(min((8 * (TC / 8)) , 99), 1)

Looking at this SCEV, it doesn't preserve the divisibility by 8 information.

After this patch, depending on the assume processing order applyLoopGuards could create the following SCEV:
max(min((8 * (TC / 8)) , 96), 8)

By aligning up 1 to 8, and aligning down 99 to 96, the new SCEV still preserves all of the original assumes.

Differential Revision: https://reviews.llvm.org/D141850
2023-02-23 11:11:20 +02:00
Nikita Popov
7753ae8da2 [SCEV] Remove unused alignof/offsetof print special cases (NFC)
These shouldn't really reach SCEV without being folded away first,
and we don't have any tests that hit these cases.

The sizeof case does occur with scalable types.
2023-02-22 17:00:11 +01:00
Max Kazantsev
0cbb8ec030 Revert "[AssumptionCache] caches @llvm.experimental.guard's"
This reverts commit f9599bbc7a3f831e1793a549d8a7a19265f3e504.

For some reason it caused us a huge compile time regression in downstream
workloads. Not sure whether the source of it is in upstream code ir not.
Temporarily reverting until investigated.

Differential Revision: https://reviews.llvm.org/D142330
2023-02-20 18:38:07 +07:00
Max Kazantsev
5fe915bb8c [SCEV] Canonicalize ext(min/max(x, y)) to min/max(ext(x), ext(y))
I stumbled over this while trying to improve our exit count work. These expressions
are equivalent for complementary signed/unsigned ext and min/max (including umin_seq),
but they are not canonicalized and SCEV cannot recognize them as the same.

The benefit of this canonicalization is that SCEV can prove some new equivalences which
it coudln't prove because of different forms. There is 1 test where trip count seems pessimized,
I could not directly figure out why, but it just seems an unrelated issue that we can fix.
Other changes seem neutral or positive to me.

Differential Revision: https://reviews.llvm.org/D141481
Reviewed By: nikic
2023-02-20 16:12:58 +07:00
Max Kazantsev
df9c5bd8d2 [SCEV] Support umin/smin in SCEVLoopGuardRewriter
Adds support for these SCEVs to cover more cases.

Differential Revision: https://reviews.llvm.org/D143259
Reviewed By: dmakogon, fhahn
2023-02-20 13:05:00 +07:00
Kazu Hirata
f8f3db2756 Use APInt::count{l,r}_{zero,one} (NFC) 2023-02-19 22:04:47 -08:00
Max Kazantsev
0c4a735200 [SCEV] Support sext in SCEVLoopGuardRewriter
There is no particular reason why it's not supported, and it is useful.

Differential Revision: https://reviews.llvm.org/D143257
Reviewed By: fhahn
2023-02-07 14:00:30 +07:00
Max Kazantsev
d7eda3ca10 [SCEV][NFC] Remove check for rewriteable types
I guess its only reason to exist is potential CT optimization, otherwise it is
just creating cohesion between this code and rewriter internals. We plan to
extend the rewriter. I'd rather not have this cohesion, unless there is a serious
reason to have it.

Differential Revision: https://reviews.llvm.org/D143246
2023-02-07 12:43:42 +07:00
Florian Hahn
62bd944e42
[SCEV] Use fact that B >u 0 for A <u B in applyLoopGuards.
If LHS <u RHS holds, RHS should be guaranteed to be > 0. By using
using 'umax(RHS, 1) -1' instead of 'RHS - 1' the results in
applyLoopGuards can be improved in some cases.

Note that the TODO for the tests mentioned the max BTC being 11, but
unless I am missing something 10 should be correct.

https://alive2.llvm.org/ce/z/44nP7F

Reviewed By: mkazantsev

Differential Revision: https://reviews.llvm.org/D126503
2023-02-01 16:51:18 +00:00
Joshua Cao
f9599bbc7a [AssumptionCache] caches @llvm.experimental.guard's
As discussed in https://github.com/llvm/llvm-project/issues/59901

This change is not NFC. There is one SCEV and EarlyCSE test that have an
improved analysis/optimization case. Rest of the tests are not failing.

I've mostly only added cleanup to SCEV since that is where this issue
started. As a follow up, I believe there is more cleanup opportunity in
SCEV and other affected passes.

There could be cases where there are missed registerAssumption of
guards, but this case is not so bad because there will be no
miscompilation. AssumptionCacheTracker should take care of deleted
guards.

Differential Revision: https://reviews.llvm.org/D142330
2023-01-24 20:16:46 -08:00
Roman Lebedev
0cdf030cf8
[SCEV] getRangeRefIter(): don't forget to recurse into casts
I'm not really sure the problem can be nicely exposed via a lit test,
since we don't give up on range calculation for deeply nested ranges,
but if i add an assertion that those opcodes are never encountered,
the assertion fails in a number of existing tests.

In reality, the iterative approach is still pretty partial:
1. `Seen` should not be there. We want the last instance of expression, not the first one
2. There should be a check that `getRangeRefIter()` does not self-recurse
2023-01-22 23:28:02 +03:00
Roman Lebedev
4f9f0b480f
[NFC][SCEV] Reflow getRangeRefIter() into an exhaustive switch
And, this shows a bug in the original code:
why do we not recurse into casts?

If i add an assertion that those opcodes are never encountered,
the assertion fails in a number of existing tests.
2023-01-22 23:28:02 +03:00
Roman Lebedev
42aaab3b45
[NFC][SCEV] GetMinTrailingZerosImpl(): deduplicate handling
`scPtrToInt` recieves same treatment as normal n-ary ops.
2023-01-22 23:28:01 +03:00
Roman Lebedev
a09b5a0cfc
[NFC][SCEV] Reflow GetMinTrailingZerosImpl() into an exhaustive switch 2023-01-22 23:28:01 +03:00
Roman Lebedev
493bab8867
[NFC][SCEV] Reflow impliesPoison() into an exhaustive switch 2023-01-22 18:57:22 +03:00
Roman Lebedev
418f780f1f
[NFC][SCEV] Reflow computeSCEVAtScope() into an exhaustive switch 2023-01-22 17:48:49 +03:00
Roman Lebedev
a81e070061
[NFC][SCEV] getBlockDisposition(): deduplicate handling 2023-01-22 17:40:52 +03:00
Roman Lebedev
cc016e6f8f
[NFC][SCEV] getLoopDisposition(): deduplicate handling 2023-01-22 17:40:52 +03:00
Roman Lebedev
906e99574e
[NFC][SCEV] computeSCEVAtScope(): deduplicate handling
Casts and udiv get the exactly the same handling as n-ary,
there is no point in special-handling anything.
2023-01-22 17:40:52 +03:00
Roman Lebedev
1f4f55de5a
[NFC][SCEV] CompareSCEVComplexity: deduplicate handling
For all but unknown/constant/recurrences, the handling is identical,
there is no point in special-casing anything.
2023-01-22 05:03:42 +03:00
Roman Lebedev
aa12133637
[NFC][SCEV] createNodeForSelectOrPHIInstWithICmpInstCond(): directly take Type, not Instruction
We don't use the `Instruction` itself, only it's type anyways.
2023-01-22 05:03:42 +03:00
Roman Lebedev
d10adf6142
[NFC][SCEV] createNodeForSelectOrPHIInstWithICmpInstCond(): return optional
We only want about the result if it succeeds, and don't want `SCEVUnknown`.
2023-01-22 05:03:42 +03:00
Roman Lebedev
d486fdffda
[NFC][SCEV] Reflow getRangeRef() into an exhaustive switch 2023-01-22 01:34:22 +03:00
Roman Lebedev
898fcfac21
[NFC][SCEV] computeSCEVAtScope(): reserve vector size upfront 2023-01-21 23:52:51 +03:00
Roman Lebedev
4b4e3fbca9
[NFC][SCEV] computeSCEVAtScope(): scUnknown: use early-returns 2023-01-21 23:38:24 +03:00
Roman Lebedev
f8eeeffada
[NFC][SCEV] Reflow computeSCEVAtScope() into an exhaustive switch
Otherwise instead of a compile-time error that you forgot to modify it,
you'd get a run-time error, which happened every time i've added new expr.

This is completely NFC, there are no other changes here.
2023-01-21 23:38:14 +03:00
Roman Lebedev
8885420b6d
[NFC][SCEV] computeSCEVAtScope(): clang-format 2023-01-21 23:37:00 +03:00
Joshua Cao
2f9f11180f [SCEV] Support all Min/Max SCEVs for GetMinTrailingZeros
There is already support for U/SMax. No reason why Min and SequentialMin
should not be supported.

NFC: code in GetMinTrailingZeroes is copied for a couple node types.
Refactor them into a single code block.

Differential Revision: https://reviews.llvm.org/D141568
2023-01-13 02:31:33 -08:00
Joshua Cao
8d92a8226e [SCEV] Add llvm.experimental.guard conditions to applyLoopGuards()
Conditions for dominating branches and llvm.assumes are already
collected. This also adds conditions from guards.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D141243
2023-01-09 19:35:16 -08:00
Florian Hahn
a564048899
[SCEV] Properly clean up duplicated FoldCacheUser ID entries.
The current code did not properly handled duplicated FoldCacheUser ID
entries when overwriting an existing entry in the FoldCache.

This triggered verification failures reported by @uabelho and #59721.

The patch fixes that by removing stale IDs when overwriting an existing
entry in the cache.

Fixes #59721.
2022-12-28 00:09:52 +00:00
Max Kazantsev
9a7286b61f [SCEV] Help getLoopInvariantExitCondDuringFirstIterations deal with complex umin exit counts. PR59615
Recent improvements in symbolic exit count computation revealed some problems with
SCEV's ability to find invariant predicate during first iterations. Ultimately it is based on its
ability to prove some facts for value on the last iteration. This last value, when it includes
`umin` as part of exit count, isn't always simplified enough. The motivating example is following:

https://github.com/llvm/llvm-project/issues/59615

Could not prove:
```
        Pred = 36, LHS = (-1 + (-1 * (2147483645 umin (-1 + %var)<nsw>))<nsw> + %var), RHS = %var
        FoundPred = 36, FoundLHS = {1,+,1}<nuw><nsw><%bb3>, FoundRHS = %var
```
Can prove:
```
        Pred = 36, LHS = (-1 + (-1 * (-1 + %var)<nsw>)<nsw> + %var), RHS = %var
        FoundPred = 36, FoundLHS = {1,+,1}<nuw><nsw><%bb3>, FoundRHS = %var
```

Here ` (2147483645 umin (-1 + %var)<nsw>)` is exit count composed of two parts from
two different exits: `2147483645 ` and `(-1 + %var)<nsw>`. When it was only one (latter)
analyzeable exit, for it everything was easily provable. Unfortunately, in general case `umin`
in one of `add`'s operands doesn't guarantee that the whole sum reduces, especially in presence
of negative steps and lack of `nuw`. I don't think there is a generic legal way to somehow play
around this `umin`.

So the ad-hoc solution is following: if we failed to find an equivalent predicate that is invariant
during first `MaxIter` iterations, and `MaxIter = umin(a, b, c...)`, try to find solution for at least one
of `a`, `b`, `c`... Because they all are `uge` than `MaxIter`, whatever is true during `a (b, c)` iterations
is also true during `MaxIter` iterations.

Differential Revision: https://reviews.llvm.org/D140456
Reviewed By: nikic
2022-12-21 18:12:17 +07:00
Florian Hahn
8a3efcd40b
[ValueTracking] Consider single poison operands in propgatesPoison.
This patch updates propgatesPoison to take a Use as argument and
propagatesPoison now returns true if the passed in operand causes the
user to yield poison if the operand is poison

This allows propagating poison if the condition of a select is poison.
This helps improve results for programUndefinedIfUndefOrPoison.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D111643
2022-12-19 11:47:51 +00:00
Fangrui Song
2fa744e631 std::optional::value => operator*/operator->
value() has undesired exception checking semantics and calls
__throw_bad_optional_access in libc++. Moreover, the API is unavailable without
_LIBCPP_NO_EXCEPTIONS on older Mach-O platforms (see
_LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS).

This commit fixes LLVMAnalysis and its dependencies.
2022-12-16 22:44:08 +00:00
Nikita Popov
29fa062f0a [SCEV] Add SCEV::operands() method (NFC)
Add an operands() method on SCEV, which forwards to the operands()
method of individual SCEV expressions.
2022-12-16 15:50:42 +01:00
Nikita Popov
04d652994d [SCEV] Return ArrayRef for SCEV operands() (NFC)
Use a consistent type for the operands() methods of different SCEV
types. Also make the API consistent by only providing operands(),
rather than also providin op_begin() and op_end() for some of them.
2022-12-16 15:36:19 +01:00
Florian Hahn
6e86b544dd
[SCEV] Cache folded SExt SCEV expressions.
Use FoldID to cache SignExtendExprs that get folded to a different
SCEV.

Depends on D137505.

Reviewed By: mkazantsev

Differential Revision: https://reviews.llvm.org/D137849
2022-12-14 11:59:19 +00:00
Kazu Hirata
f7dffc28b3 Don't include None.h (NFC)
I've converted all known uses of None to std::nullopt, so we no longer
need to include None.h.

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-10 11:24:26 -08:00
Florian Hahn
afe3558a0b
[SCEV] Cache ZExt SCEV expressions.
When creating SCEV expressions for ZExt, there's quite a bit of
reasoning done and in many places the reasoning in turn will try to
create new SCEVs for other ZExts.

This can have a huge compile-time impact. The attached test from #58402
takes an excessive amount of compile time; without the patch, the test
doesn't complete in 1500+ seconds, but with the patch it completes in 1
second.

To speed up this case, cache created ZExt expressions for given (SCEV, Ty) pairs.
Caching just ZExts is relatively straight-forward, but it might make
sense to extend it to other expressions in the future.

This has a slight positive impact on CTMark:
* O3: -0.03%
* ReleaseThinLTO: -0.03%
* ReleaseLTO-g: 0.00%

https://llvm-compile-time-tracker.com/compare.php?from=bf9de7464946c65f488fe86ea61bfdecb8c654c1&to=5ac0108553992fb3d58bc27b1518e8cf06658a32&stat=instructions:u

The patch also improves compile-time for some internal real-world workloads
where time spent in SCEV goes from ~300 seconds to ~3 seconds.

There are a few cases where computing & caching the result earlier may
return more pessimistic results, but the compile-time savings seem to
outweigh that.

Fixes #58402.

Reviewed By: mkazantsev

Differential Revision: https://reviews.llvm.org/D137505
2022-12-09 22:14:04 +00:00
Krzysztof Parzyszek
ea6ed399b2 [SCEV] Convert Optional to std::optional 2022-12-08 08:35:11 -06:00
Max Kazantsev
0130d0ed35 [SCEV] Compute symbolic exit count for 'and' conditions
If loop exits by condition like `A < B && X < Y`, and at least one of symbolic max
exit counts for these conditions is known, it can be used as estimate of symbolic
max exit count for whole branch. If both are known, then we can use their umin
as the estimate.

Differential Revision: https://reviews.llvm.org/D139403
Reviewed By: nikic
2022-12-08 16:04:42 +07:00