2059 Commits

Author SHA1 Message Date
David Sherwood
02ee96eca9
[Analysis] Teach isDereferenceableAndAlignedInLoop about SCEV predicates (#106562)
Currently if a loop contains loads that we can prove at compile time
are dereferenceable when certain conditions are satisfied the function
isDereferenceableAndAlignedInLoop will still return false because
getSmallConstantMaxTripCount will return 0 when SCEV predicates
are required. This patch changes getSmallConstantMaxTripCount to take
an optional Predicates pointer argument so that we can permit
functions such as isDereferenceableAndAlignedInLoop to consider more
cases.
2024-09-23 09:56:37 +01:00
Jay Foad
e03f427196
[LLVM] Use {} instead of std::nullopt to initialize empty ArrayRef (#109133)
It is almost always simpler to use {} instead of std::nullopt to
initialize an empty ArrayRef. This patch changes all occurrences I could
find in LLVM itself. In future the ArrayRef(std::nullopt_t) constructor
could be deprecated or removed.
2024-09-19 16:16:38 +01:00
Florian Hahn
4e6ec0bf6d
[SCEV] Replace redundant !Preds.empty() check with assert. (NFCI)
If there are no predicates, the predicated counts should not be
different to the non-predicated ones.
2024-09-19 13:53:30 +01:00
David Sherwood
270ee6549c
[Analysis][NFC] Clean-up in ScalarEvolution when copying predicates (#108851)
There are a few places in ScalarEvolution.cpp where we copy predicates
from one list to another and they have a similar pattern:

  for (const auto *P : ENT.Predicates)
    Predicates->push_back(P);

We can avoid the loop by writing them like this:

  Predicates->append(ENT.Predicates.begin(), ENT.Predicates.end());

which may end up being more efficient since we only have to try
reserving more space once.
2024-09-17 10:28:24 +01:00
Antonio Frighetto
e80f48986c [SCEV] BECount to zero if ((-C + (C smax %x)) /u %x), C > 0 holds
The SCEV expression `((-C + (C smax %x)) /u %x)` can be folded
to zero for any positive constant C.

Proof: https://alive2.llvm.org/ce/z/_dLm8C.
2024-09-05 17:01:56 +02:00
David Sherwood
df3d70b5a7
[Analysis] Add getPredicatedExitCount to ScalarEvolution (#105649)
Due to a reviewer request on PR #88385 I have created this patch
to add a getPredicatedExitCount function, which is similar to
getExitCount except that it uses the predicated backedge taken
information. With PR #88385 we will start to care about more
loops with multiple exits, and want the ability to query exit
counts for a particular exiting block. Such loops may require
predicates in order to be vectorised.

New tests added here:

Analysis/ScalarEvolution/predicated-exit-count.ll
2024-09-02 14:05:26 +01:00
David Sherwood
0caa909a3c
[Analysis][NFC] Use SmallVectorImpl consistently in ScalarEvolution (#105663)
Use SmallVectorImpl instead of SmallVector for function arguments
to give the caller greater flexibility in choice of initial size.
2024-08-27 09:29:14 +01:00
David Sherwood
d46812a7be
[Analysis] Teach ScalarEvolution::getRangeRef about more dereferenceable objects (#104778)
Whilst dealing with review comments on

https://github.com/llvm/llvm-project/pull/96752

I discovered that SCEV does not know about the dereferenceable attribute
on function arguments so I have updated getRangeRef to make use of it
by calling getPointerDereferenceableBytes.
2024-08-22 14:45:14 +01:00
Nikita Popov
6a84af704f
[LAA] Use computeConstantDifference() (#103725)
Use computeConstantDifference() instead of casting getMinusSCEV() to
SCEVConstant. This can be much faster in some cases, because
computeConstantDifference() computes the result without creating new
SCEV expressions.

This improves LTO/ThinLTO compile-time for lencod by more than 10%.

I've verified that computeConstantDifference() does not produce worse
results than the previous code for anything in llvm-test-suite. This
required raising the iteration cutoff to 6. I ended up increasing it to
8 just to be on the safe side (for code outside llvm-test-suite), and
because this doesn't materially affect compile-time anyway (we'll almost
always bail out earlier).
2024-08-16 12:52:57 +02:00
Kazu Hirata
1115dee248
[Analysis] Use range-based for loops (NFC) (#103540) 2024-08-14 08:23:04 -07:00
Nikita Popov
6da3361f50
[SCEV] Look through multiply in computeConstantDifference() (#103051)
Inside computeConstantDifference(), handle the case where both sides are
of the form `C * %x`, in which case we can strip off the common
multiplication (as long as we remember to multiply by it for the
following difference calculation).

There is an obvious alternative implementation here, which would be to
directly decompose multiplies inside the "Multiplicity" accumulation.
This does work, but I've found this to be both significantly slower
(because everything has to work on APInt) and more complex in
implementation (e.g. because we now need to match back the new More/Less
with an arbitrary factor) without providing more power in practice. As
such, I went for the simpler variant here.

This is the last step to make computeConstantDifference() sufficiently
powerful to replace existing uses of
`cast<SCEVConstant>(getMinusSCEV())` with it.
2024-08-14 09:37:38 +02:00
Jie Fu
b7ebb67b86 [SCEV] Fix -Wrange-loop-construct (NFC)
/llvm-project/llvm/lib/Analysis/ScalarEvolution.cpp:12009:21:
 error: loop variable '[S, Mul]' creates a copy from type 'const value_type' (aka 'const llvm::detail::DenseMapPair<const llvm::SCEV *, int>') [-Werror,-Wrange-loop-construct]
    for (const auto [S, Mul] : Multiplicity) {
                    ^
/llvm-project/llvm/lib/Analysis/ScalarEvolution.cpp:12009:10:
 note: use reference type 'const value_type &' (aka 'const llvm::detail::DenseMapPair<const llvm::SCEV *, int> &') to prevent copying
    for (const auto [S, Mul] : Multiplicity) {
         ^~~~~~~~~~~~~~~~~~~~~
                    &
2024-08-13 17:13:04 +08:00
Nikita Popov
306b9c7b48
[SCEV] Handle more add/addrec mixes in computeConstantDifference() (#101999)
computeConstantDifference() can currently look through addrecs with
identical steps, and then through adds with identical operands (apart
from constants).

However, it fails to handle minor variations, such as two nested add
recs, or an outer add with an inner addrec (rather than the other way
around).

This patch supports these cases by adding a loop over the
simplifications, limited to a small number of iterations. The motivation
is the same as in #101339, to make
computeConstantDifference() powerful enough to replace existing uses of
`dyn_cast<SCEVConstant>(getMinusSCEV())` with it. Though as the IR test
diff shows, other callers may also benefit.
2024-08-13 11:01:39 +02:00
Philip Reames
b812e57ac3
[SCEV] Consolidate code for proving wrap flags of controlling finite IVs (#101404)
The canAssumeNoSelfWrap routine in howManyLessThans was doing two subtly
inter-related things. First, it was proving no-self-wrap. This exactly
duplicates the existing logic in the caller. Second, it was establishing
the precondition for the nw->nsw/nuw inference. Specifically, we need to
know that *this* exit must be taken for the inference to be sound.
Otherwise, another (possible abnormal) exit could be taken in the
iteration where this IV would become poison.

This change moves all of that logic into the caller, and caches the
resulting nuw/nsw flags in the AddRec. This centralizes the logic in one
place, and makes it clear that it all depends on controlling the sole
exit.

We do loose a couple cases with SCEV predication. Specifically, if SCEV
predication was able to convert e.g. zext(addrec) into an addrec(zext)
using predication, but didn't record the nuw fact on the new addrec,
then the consuming code can no longer fix this up. I don't think this
case particularly matters.

---------

Co-authored-by: Nikita Popov <github@npopov.com>
2024-08-12 11:40:24 -07:00
Nikita Popov
3512bcc2e9 [SCEV] Fix incorrect extension in computeConstantDifference()
The Mul factor was zero-extended here, resulting in incorrect
results for integers larger than 64-bit.

As we currently only multiply by 1 or -1, just split this into
two cases -- there's no need for a full multiplication here.

Fixes https://github.com/llvm/llvm-project/issues/102597.
2024-08-12 15:24:37 +02:00
Kazu Hirata
b728f37121
[Analysis] Use llvm::set_is_subset (NFC) (#102766) 2024-08-10 16:33:41 -07:00
Kazu Hirata
e9a47a664a
[llvm] Construct SmallVector with ArrayRef (NFC) (#102712)
Without this patch, the constructor arguments come from
SmallVectorImpl, not ArrayRef.  This patch switches them to ArrayRef
so that we can construct SmallVector with a single argument.

Note that LLVM Programmer’s Manual prefers ArrayRef to SmallVectorImpl
for flexibility.
2024-08-09 21:39:13 -07:00
Nikita Popov
a9eb3fd79b [SCEV] Fix warning (NFC)
Produces -Wrange-loop-construct on some buildbots.
2024-08-02 14:48:29 +02:00
Nikita Popov
79af6892f8
[SCEV] Handle more adds in computeConstantDifference() (#101339)
Currently it only deals with the case where we're subtracting adds with
at most one non-constant operand. This patch extends it to cancel out
common operands for the subtraction of arbitrary add expressions.

The background here is that I want to replace a getMinusSCEV() call in
LAA with computeConstantDifference():

93fecc2577/llvm/lib/Analysis/LoopAccessAnalysis.cpp (L1602-L1603)

This particular call is very expensive in some cases (e.g. lencod with
LTO) and computeConstantDifference() could achieve this much more
cheaply, because it does not need to construct new SCEV expressions.

However, the current computeConstantDifference() implementation is too
weak for this and misses many basic cases. This is a step towards making
it more powerful while still keeping it pretty fast.
2024-08-02 13:43:02 +02:00
Nikita Popov
85c5265fea
[SCEV] Unify and optimize constant folding (NFC) (#101473)
Add a common constantFoldAndGroupOps() helper that takes care of
constant folding and grouping transforms that are common to all nary
ops. This moves the constant folding prior to grouping, which is more
efficient, and excludes any constant from the sort.

The constant folding has hooks for folding, identity constants and
absorber constants.

This gives a compile-time improvement for SCEV-heavy workloads like
lencod.
2024-08-02 09:55:02 +02:00
Philip Reames
f0944f4be0
[SCEV] Prove no-self-wrap from negative power of two step (#101416)
We have existing code which reasons about a step evenly dividing the
iteration space is a finite loop with a single exit implying
no-self-wrap. The sign of the step doesn't effect this.

---------

Co-authored-by: Nikita Popov <github@npopov.com>
2024-08-01 13:17:07 -07:00
Philip Reames
7583c484c8
[SCEV] Use power of two facts involving vscale when inferring wrap flags (#101380)
SCEV has logic for inferring wrap flags on AddRecs which are known to
control an exit based on whether the step is a power of two. This logic
only considered constants, and thus did not trigger for steps such as (4
x vscale) which are common in scalably vectorized loops.

The net effect is that we were very sensative to the preservation of
nsw/nuw flags on such IVs, and could not infer trip counts if they got
lost for any reason.

---------

Co-authored-by: Nikita Popov <github@npopov.com>
2024-07-31 14:18:20 -07:00
Nikita Popov
8d28d448e3 [SCEV] Fix outdated comment (NFC)
The EqCache parameter has been removed.
2024-07-30 14:37:52 +02:00
Johannes Reifferscheid
65697b1c7c
Remove value cache in SCEV comparator. (#100721)
The cache triggers almost never, and seems unlikely to help with
performance. However, when it does, it is likely to cause the comparator
to become inconsistent due to a bad interaction of the depth limit and
cache hits. This leads to crashes in debug builds. See the new unit test
for a reproducer.
2024-07-30 14:27:37 +02:00
Nikita Popov
5d833ee6ac [SCEV] Avoid unnecessary computeConstantDifference() call (NFC)
No need to do the second one if the first one already failed.
2024-07-30 14:04:43 +02:00
v01dXYZ
cff8d716bd
[SCEV] forgetValue: support (with-overflow-inst op0, op1) (#98015)
The use-def walk in forgetValue() was skipping instructions with
non-SCEVable types. However, SCEV may look past with.overflow
intrinsics returning aggregates.

Fixes #97586.
2024-07-09 09:14:33 +02:00
Florian Hahn
2f89d4a8c7
[SCEV] Split collecting and applying rewrite info from loop guards (NFC) (#97316)
Introduce a new LoopGuards class to track info from loop guards and split 
off collecting rewrite info to LoopGuards::collect. This allows users of 
applyLoopGuards to collect rewrite info once in cases where the same
loop guards are applied multiple times.

This is used to collect rewrite info once in howFarToZero, which saves a
bit of compile-time:
stage1-O3: -0.04%
stage1-ReleaseThinLTO: -0.02%
stage1-ReleaseLTO-g: -0.04%
stage2-O3: -0.02%

https://llvm-compile-time-tracker.com/compare.php?from=117b53ae38428ca66eaa886fb432e6f09db88fe4&to=4ffb7b2e1c99081ccebe6f236c48a0be2f64b6ff&stat=instructions:u

Notably this improves mafft by -0.9% with -O3, -0.11% with LTO and
-0.12% with stage2-O3.

PR: https://github.com/llvm/llvm-project/pull/97316
2024-07-02 19:32:28 +01:00
Nikita Popov
d23959b2f5 [SCEV] Cache DataLayout in class (NFC)
PR #96919 caused a minor compile-time regression, mostly because
SCEV now goes through an extra out-of-line function to fetch the
data layout, and does this a lot. Cache the DataLayout in SCEV
to avoid these repeated calls.
2024-06-28 12:19:27 +02:00
vaibhav
7e59b20034
[SCEV] Support addrec in right hand side in howManyLessThans (#92560)
Fixes #92554 (std::reverse will auto-vectorize now)

When calculating number of times a exit condition containing a
comparison is executed, we mostly assume that RHS of comparison should
be loop invariant, but it may be another add-recurrence.

~In that case, we can try the computation with `LHS = LHS - RHS` and
`RHS = 0`.~ (It is not valid unless proven that it doesn't wrap)

**Edit:**
We can calculate back edge count for loop structure like:

```cpp
left = left_start
right = right_start
while(left < right){
  // ...do something...
  left += s1; // the stride of left is s1 (> 0)
  right -= s2; // the stride of right is -s2 (s2 > 0)
}
// left and right converge somewhere in the middle of their start values
```
We can calculate the backedge-count as ceil((End - left_start) /u (s1-
(-s2)) where, End = max(left_start, right_start).

**Alive2**: https://alive2.llvm.org/ce/z/ggxx58
2024-06-25 14:33:57 -07:00
Kazu Hirata
1462605ab0
[Analysis] Use range-based for loops (NFC) (#96587) 2024-06-25 06:57:30 -07:00
Mohammed Keyvanzadeh
7b57a1b401
[llvm] format and terminate namespaces with closing comment (#94917)
Namespaces are terminated with a closing comment in the majority of the
codebase so do the same here for consistency. Also format code within
some namespaces to make clang-format happy.
2024-06-21 23:50:53 +03:30
Enna1
1fafa32f6e
[SCEV] Avoid unnecessary call to getExitingBlock() in computeExitLimit() (#96188)
In `computeExitLimit()`, we use `getExitingBlock()` to check if loop has
exactly one exiting block.
Since `computeExitLimit()` is only used in
`computeBackedgeTakenCount()`, and `getExitingBlocks()` is called to get
all exiting blocks in `computeBackedgeTakenCount()`, we can simply check
if loop has exactly one exiting block by checking if the number of
exiting blocks equals 1 in `computeBackedgeTakenCount()` and pass it as
an argument to `computeExitLimit()`.

This change helps to improve the compile time for files containing large
loops.
2024-06-21 09:43:34 +08:00
Nikita Popov
290a939fc3 [SCEV] Handle nusw/nuw gep flags for addrecs
Set the nw flag is gep has any nowrap flags. Transfer the nuw
flag. Also set nuw for the nusw + nneg combination.
2024-06-20 15:59:42 +02:00
Nikita Popov
7f09aa9e36 [SCEV] Transfer gep nusw and nuw flags
nusw implies nsw offset and nuw base+offset arithmetic if offset
is non-negative. nuw implies nuw offset and base+offset arithmetic.
As usual, we can only transfer is poison implies UB.
2024-06-20 14:45:02 +02:00
Philip Reames
04cd069062
[SCEV] Use context sensitive reasoning in howFarToZero (#94525)
This change builds on 0a357ad which supported non-constant strides in
howFarToZero, but used only context insensitive reasoning.

This change does two things:
1) Directly use context sensitive queries to prove facts established
   before the loop.  Note that we technically only need facts known
   at the latch, but using facts known on entry is a conservative
   approximation which will cover most everything.
2) For the non-zero check, we can usually prove non-zero from the
   finite assumption implied by mustprogress.  This eliminates the
   need to do the context sensitive query in the common case.
2024-06-19 08:59:26 -07:00
Philip Reames
cb76896d6e
[SCEVExpander] Recognize urem idiom during expansion (#96005)
If we have a urem expression, emitting it as a urem is significantly
better that letting the fully expansion kick in. We have the risk of a
udiv or mul which could have previously been shared, but loosing that
seems like a reasonable tradeoff for being able to round trip a urem w/o
modification.
2024-06-19 08:40:04 -07:00
Philip Reames
0a357adc75
[SCEV] Support non-constant step in howFarToZero (#94411)
VF * vscale is the canonical step for a scalably vectorized loop, and
LFTR canonicalizes to NE loop tests, so having our trip count logic be
unable to compute trip counts for such loops is unfortunate.

The existing code needed minimal generalization to handle non-constant
strides. The tricky cases to be sure we handle correctly are: zero, and
-1 (due to the special case of abs(-1) being non-positive).

This patch does the full generalization in terms of code structure, but
in practice, this seems unlikely to benefit
anything beyond the (C * vscale) case. I did some quick investigation,
and it seems the context free non-zero, and sign checks are basically
never disproved for arbitrary scales. I think we have alternate tactics
available for these, but I'm going to return to that in a separate
patch.
2024-06-05 08:05:07 -07:00
Florian Hahn
4812e9a487
[SCEV] Preserve flags in SCEVLoopGuardRewriter for add and mul. (#91472)
SCEVLoopGuardRewriter only replaces operands with equivalent values, so
we should be able to transfer the flags from the original expression.

PR: https://github.com/llvm/llvm-project/pull/91472
2024-06-03 13:25:55 +01:00
Florian Hahn
39e5036c0e
[SCEV] Add predicated version of getSymbolicMaxBackedgeTakenCount. (#93498)
This patch adds a predicated version of
getSymbolicMaxBackedgeTakenCount.

The intended use for this is loop access analysis for loops with
uncountable exits. When analyzing dependences and computing runtime
checks, we need the smallest upper bound on the number of iterations. In
terms of memory safety, it shouldn't matter if any uncomputable exits
leave the loop, as long as we prove that there are no dependences given
the minimum of the countable exits. The same should apply also for
generating runtime checks.

PR: https://github.com/llvm/llvm-project/pull/93498
2024-05-28 16:25:54 -07:00
Florian Hahn
ef67f31e88
[SCEV] Compute symbolic max backedge taken count in BTI directly. (NFC)
Move symbolic max backedge taken count computation to BackedgeTakenInfo,
use existing ExitNotTaken info.

In preparation for https://github.com/llvm/llvm-project/pull/93498.
2024-05-28 10:51:21 -07:00
Florian Hahn
bb4c8f9219
[SCEV] Don't add predicates already implied by UnionPredicate. (#93397)
Update SCEVUnionPredicate::add to only add predicates from another union
predicate, if they aren't alread implied by the union predicate we add
them to.

Note that there exists logic elsewhere to avoid adding predicates if
they are already implied, but this logic misses cases when only some
predicates of a union predicate are implied by the current set of
predicates.

PR: https://github.com/llvm/llvm-project/pull/93397
2024-05-26 18:31:36 -07:00
Nikita Popov
ca478bc6cc
[SCEV] Support ule/sle exit counts via widening (#92206)
If we have an exit condition of the form IV <= Limit, we will first try
to convert it into IV < Limit+1 or IV-1 < Limit based on range info (in
icmp simplification). If that fails, we try to convert it to IV < Limit
+ 1 based on controlling exits in non-infinite loops.

However, if all else fails, we can still determine the exit count by
rewriting to ext(IV) < ext(Limit) + 1, where the zero/sign extension
ensures that the addition does not overflow.

Proof: https://alive2.llvm.org/ce/z/iR-iYd
2024-05-23 07:54:08 +02:00
Nikita Popov
b6e102e08c
[SCEV] Don't use non-deterministic constant folding for trip counts (#90942)
When calculating the exit count exhaustively, if any of the involved
operations is non-deterministic, the exit count we compute at
compile-time and the exit count at run-time may differ. Using these
non-deterministic constant folding results is only correct if we
actually replace all uses of the instruction with the value. SCEV (or
its consumers) generally don't do this.

Handle this by adding a new AllowNonDeterministic flag to the constant
folding API, and disabling it in SCEV. If non-deterministic results are
not allowed, do not fold FP lib calls in general, and FP operations
returning NaNs in particular. This could be made more precise (some FP
libcalls like fabs are fully deterministic), but I don't think this that
precise handling here is worthwhile.

Fixes the interesting part of
https://github.com/llvm/llvm-project/issues/89885.
2024-05-20 07:40:54 +02:00
Florian Hahn
3f0e1d4cf0
[SCEV] Swap order of arguments to MatchBinaryAddToConst (NFCI). (#91945)
The argument order to MatchBinaryAddToConst doesn't match the comment
and also is counter-intuitive (passing RHS before LHS, C2 before C1).

This patch adjusts the order to be inline with the calls above, which
should be equivalent, but more natural:
https://alive2.llvm.org/ce/z/ZWGp-Z

PR: https://github.com/llvm/llvm-project/pull/91945
2024-05-13 13:04:22 +01:00
Eli Friedman
f893dccbba
Replace uses of ConstantExpr::getCompare. (#91558)
Use ICmpInst::compare() where possible, ConstantFoldCompareInstOperands
in other places. This only changes places where the either the fold is
guaranteed to succeed, or the code doesn't use the resulting compare if
we fail to fold.
2024-05-09 16:50:01 -07:00
Andreas Jonson
ff3523f67b
[IR] Drop poison-generating return attributes when necessary (#89138)
Rename has/dropPoisonGeneratingFlagsOrMetadata to
has/dropPoisonGeneratingAnnotations and make it also handle
nonnull, align and range return attributes on calls, similar
to the existing handling for !nonnull, !align and !range metadata.
2024-04-18 15:27:36 +09:00
Harald van Dijk
60de56c743
[ValueTracking] Restore isKnownNonZero parameter order. (#88873)
Prior to #85863, the required parameters of llvm::isKnownNonZero were
Value and DataLayout. After, they are Value, Depth, and SimplifyQuery,
where SimplifyQuery is implicitly constructible from DataLayout. The
change to move Depth before SimplifyQuery needed callers to be updated
unnecessarily, and as commented in #85863, we actually want Depth to be
after SimplifyQuery anyway so that it can be defaulted and the caller
does not need to specify it.
2024-04-16 15:21:09 +01:00
Yingwei Zheng
e0a628715a
[ValueTracking] Convert isKnownNonZero to use SimplifyQuery (#85863)
This patch converts `isKnownNonZero` to use SimplifyQuery. Then we can
use the context information from `DomCondCache`.

Fixes https://github.com/llvm/llvm-project/issues/85823.
Alive2: https://alive2.llvm.org/ce/z/QUvHVj
2024-04-12 23:47:20 +08:00
Andreas Jonson
9250aedb5c
[SCEV] Add range attribute handling (#88449) 2024-04-12 18:21:48 +09:00
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