1919 Commits

Author SHA1 Message Date
Nikita Popov
2f3dc5fa8b [SCEV] Rename ControlsExit -> ControlsOnlyExit (NFC)
As suggested in https://reviews.llvm.org/D145510#4192162.
2023-03-14 11:04:54 +01:00
Nikita Popov
660403940c [SCEV] Fix finite loop non-strict predicate simplification (PR60944)
There are a number of issues with the current code for converting
ule -> ult (etc) predicates for comparisons controlling finite loops:

* It sets nowrap flags, which may only hold for that particular
  comparison, not globally. (PR60944)
* It doesn't check that the RHS is invariant. (I'm not sure this
  can cause practical issues independently of the previous point.)
* It runs before simplifications that may be more profitable. (PR54191)

This patch moves the handling for this into computeExitLimitFromICmp(),
because it is somewhat tightly coupled with assumptions in that code,
and addresses the aforementioned issues.

Fixes https://github.com/llvm/llvm-project/issues/60944.
Fixes https://github.com/llvm/llvm-project/issues/54191.

Differential Revision: https://reviews.llvm.org/D145510
2023-03-14 10:55:02 +01:00
Kazu Hirata
11efd1cb04 [Analysis] Use *{Set,Map}::contains (NFC) 2023-03-14 00:32:40 -07:00
Dmitry Makogon
b60758374b [SCEV] Apply loop guards against min/max for its arguments
This replaces several rewriting rules in ScalarEvolution::applyLoopGuards
that are applied to min/max expressions with the equivalent ones but
applied to its arguments.
So previously given we had a loop guard min(a, b) >= c,
the min expression would get rewritten as max(c, min(a, b)).
With such approach, we were unable to apply the rewrite if min operands
were zext for example (min(zext(a), zext(b))), however it's equivalent
to the expression zext(min(a, b)) for which we could apply the rewrite.

Now we'd rewrite the min operands also with these expressions:
a -> max(c, a) and
b -> max(c, b).
and this would allow us to apply the loop guard in this and similar cases:
min(zext(a), zext(b)) would get rewritten as min(zext(max(c, a)), zext(max(c, b)))
instead of just being skipped.

The list of added rules (omitting predicates signedness for simplicity):
1. Guard:     min(a, b) >= c
   Old rule:  min(a, b) -> max(c, min(a, b))
   New rules: a -> max(a, c) and b -> max(b, c)
2. Guard:     min(a, b) > c
   Old rule:  min(a, b) -> max(c + 1, min(a, b))
   New rules: a -> max(a, c + 1) and b -> max(b, c + 1)
3. Guard:     max(a, b) <= c
   Old rule:  max(a, b) -> min(c, max(a, b))
   New rules: a -> min(a, c) and b -> min(b, c)
4. Guard:     max(a, b) < c
   Old rule:  max(a, b) -> min(c - 1, max(a, b))
   New rules: a -> min(a, c - 1) and b -> min(b, c - 1)
The old rewrites still hold.

Differential Revision: https://reviews.llvm.org/D145230
2023-03-14 00:06:08 +07:00
Dmitry Makogon
bcda7db5e5 [SCEV] Rename variables in applyLoopGuards (NFC) 2023-03-14 00:06:07 +07:00
Florian Hahn
7019624ee1
[SCEV] Strengthen nowrap flags via ranges for ARs on construction.
At the moment, proveNoWrapViaConstantRanges is only used when creating
SCEV[Zero,Sign]ExtendExprs. We can get significant improvements by
strengthening flags after creating the AddRec.

I'll also share a follow-up patch that removes the code to strengthen
flags when creating SCEV[Zero,Sign]ExtendExprs. Modifying AddRecs while
creating those can lead to surprising changes.

Compile-time looks neutral:
https://llvm-compile-time-tracker.com/compare.php?from=94676cf8a13c511a9acfc24ed53c98964a87bde3&to=aced434e8b103109104882776824c4136c90030d&stat=instructions:u

Reviewed By: mkazantsev, nikic

Differential Revision: https://reviews.llvm.org/D144050
2023-03-07 17:10:34 +01:00
Nikita Popov
ffe8f47d72 [IR] Add operator<< overload for CmpInst::Predicate (NFC)
I regularly try and fail to use this while debugging.
2023-03-07 15:10:56 +01:00
Dmitry Makogon
30496bf645 [SCEV] Use fallthoughs in predicate switch when collecting rewrites for loop guard (NFC) 2023-03-07 15:59:50 +07:00
Nikita Popov
3228a501c4 [SCEV] Fix control flow warning (NFC) 2023-03-03 15:03:51 +01:00
Nikita Popov
e00c73c856 [SCEV] Extract a helper to create a SCEV with new operands (NFC) 2023-03-03 14:50:25 +01:00
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