1893 Commits

Author SHA1 Message Date
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
Nikita Popov
fe2ca62e92 [SCEV] Track SymbolicMaxNotTaken in BECountUsers 2022-12-08 08:51:30 +01:00
Nikita Popov
4d97a914d7 [SCEV] Use umin_seq for symbolic max BE count
We were using umin_seq when computing the exact BE count, but not
when computing the symbolic max BE count.
2022-12-07 15:32:49 +01:00
Max Kazantsev
07de5d18c9 [SCEV] Remember blocks for which we know symbolic exit count but not exact
The old code didn't bother to memoize blocks for which exact exit count is not
known. As result, in situation when exact isn't known but symbolic is known, this
info was lost. This patch fixes the situation: now we memoize when symbolic is
known (exact always implies symbolic, so this is a strict superset of what was before).

Differential Revision: https://reviews.llvm.org/D139515
Reviewed By: nikic
2022-12-07 17:51:30 +07:00
Max Kazantsev
49e928bee8 [SCEV][NFC] Sink initialization of SymbolicMaxNotTaken from ExitLimit constructor to its callers
Preserves current behavior (always select Exact if known, otherwise select Constant Max).
This is the final preparation step before letting each particular computation way to decide
how exactly it should be computed. Functional improvement is coming shortly as follow-up.

Differential Revision: https://reviews.llvm.org/D139402
Reviewed By: nikic, fhahn
2022-12-07 15:33:03 +07:00
Kazu Hirata
1f421b6d7e [llvm] Use std::nullopt instead of None in comments (NFC)
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-06 22:45:17 -08:00
Roman Lebedev
46db90cc71
[SCEV] MatchBinaryOp(): try to recognize or as add-in-disguise (w/ no common bits set)
LLVM *loves* to convert `add` of operands with no common bits
into an `or`. But SCEV really doesn't deal with `or` that well,
so try extra hard to recognize this `or` as an `add`.

I believe, previously this wasn't being done because of the recursive
of this, but now that the `createSCEV()` is not recursive,
this should be fine. Unless this is *too* costly compile-time wise...

https://alive2.llvm.org/ce/z/EfapCo
2022-12-06 20:26:53 +03:00
Max Kazantsev
0c7910eab9 [NFC] Rename variable MaxBECount -> ConstantMaxBECount
Just to distinguish it from symbolic max which we plan to compute
here as well.
2022-12-05 17:48:36 +07:00
Kazu Hirata
3c09ed006a [llvm] Use std::nullopt instead of None in comments (NFC)
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-04 17:12:44 -08:00
Benjamin Kramer
856f7937c7 Compress a few pairs using PointerIntPairs
Use the uniform structured bindings interface where possible. NFCI.
2022-12-04 16:55:16 +01:00
Kazu Hirata
19aff0f37d [Analysis] 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 19:43:04 -08:00
Jan Svoboda
abf0c6c0c0 Use CTAD on llvm::SaveAndRestore
Reviewed By: dblaikie

Differential Revision: https://reviews.llvm.org/D139229
2022-12-02 15:36:12 -08:00
Max Kazantsev
0b74cb4231 [SCEV] Introduce field for storing SymbolicMaxNotTaken. NFCI
ritht is initialized with either exact (if available) or
with constant max exit count. In the future, this can be improved.

Hypothetically this is not an NFC (it is possible that exact is not
known and max is known for a particular exit), but for how we use
it now it seems be an NFC (or at least I could not find an example
where it differs). constant max exit count. In the future, this can
be improved.

Differential Revision: https://reviews.llvm.org/D138699
Reviewed By: lebedev.ri
2022-11-28 17:07:33 +07:00
Kazu Hirata
ee8959d098 [Analysis] Use std::optional in ScalarEvolution.cpp (NFC)
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-11-25 11:25:45 -08:00
Max Kazantsev
eb95ab5745 Revert "[Test] Add couple more tests where we can compute symbolic max exit count"
This reverts commit 7e3373c9e174eff6edb1214efb3e67d7b7ad447d.

Some changes that were not supposed to be commited came with it.
2022-11-25 13:37:24 +07:00
Max Kazantsev
7e3373c9e1 [Test] Add couple more tests where we can compute symbolic max exit count 2022-11-25 13:35:16 +07:00
Max Kazantsev
98307381d4 [SCEV][NFC] Rename constructor parameter to match its field name 2022-11-25 12:59:05 +07:00