227 Commits

Author SHA1 Message Date
John Brawn
81d3189891
[LAA] Keep pointer checks on partial analysis (#139719)
Currently if there's any memory access that AccessAnalysis couldn't
analyze then all of the runtime pointer check results are discarded.
This patch makes this able to be controlled with the AllowPartial
option, which makes it so we generate the runtime check information
for those pointers that we could analyze, as transformations may still
be able to make use of the partial information.

Of the transformations that use LoopAccessAnalysis, only
LoopVersioningLICM changes behaviour as a result of this change. This is
because the others either:
* Check canVectorizeMemory, which will return false when we have partial
pointer information as analyzeLoop() will return false.
* Examine the dependencies returned by getDepChecker(), which will be
empty as we exit analyzeLoop if we have partial pointer information
before calling areDepsSafe(), which is what fills in the dependency
information.
2025-06-04 16:47:20 +01:00
Florian Hahn
0ba63b2f22
[SCEV] Add additional test coverage for loop-guards reasoning.
Add additional tests showing missed opportunities when using loop guards
for reasoning in SCEV, depending on the order the guards appear in the
IR.
2025-06-01 22:39:37 +01:00
Ramkumar Ramachandra
bb2791609d
[LAA] Tweak debug output for UTC stability (#140764)
UpdateTestChecks has a make_analyzer_generalizer to replace pointer
addressess from the debug output of LAA with a pattern, which is an
acceptable solution when there is one RUN line. However, when there are
multiple RUN lines with a common pattern, UTC fails to recognize common
output due to mismatched pointer addresses. Instead of hacking UTC scrub
the output before comparing the outputs from the different RUN lines,
fix the issue once and for all by making LAA not output unstable pointer
addresses in the first place.

The removal of the now-dead make_analyzer_generalizer is left as a
non-trivial exercise for a follow-up.
2025-05-21 12:01:49 +01:00
Ramkumar Ramachandra
b18ebd17b8
[LAA] Improve forked-pointers.ll test (#140383) 2025-05-18 09:34:27 +01:00
Florian Hahn
9da103ab9e
[LAA] Update remaining tests after 384a5b00a7. 2025-05-07 21:02:44 +01:00
vaibhav
384a5b00a7
[LAA] Use MaxStride instead of CommonStride to calculate MaxVF (#98142)
We bail out from MaxVF calculation if the strides are not the same.
Instead, we are dependent on runtime checks, though not yet implemented.
We could instead use the MaxStride to conservatively use an upper bound.

This handles cases like the following:
```c
#define LEN 256 * 256
float a[LEN];

void gather() {
  for (int i = 0; i < LEN - 1024 - 255; i++) {
  #pragma clang loop interleave(disable)
  #pragma clang loop unroll(disable)
    for (int j = 0; j < 256; j++)
      a[i + j + 1024] += a[j * 4 + i];
  }
}
```

---------

Co-authored-by: Florian Hahn <flo@fhahn.com>
2025-05-07 21:02:21 +01:00
Vikram Hegde
f91a6e6dab
[SCEV] Reject comparision of pointers to different address spaces in SCEVWrapPredicate::implies (#137935) 2025-04-30 21:03:31 +05:30
Ramkumar Ramachandra
13b443f2ef
[LAA] Improve convergent tests (#136758)
LoopAccessAnalysis has code for handling function calls where the
function is marked with the 'convergent' attribute, but the test
coverage is insufficient. Fix this by adding a test showing the case of
no-runtime-checks adapted from LoopDistribute, and clean up the existing
test with runtime-checks. Also regenerate the test file with
UpdateTestChecks.
2025-04-29 09:50:33 +01:00
Alexey Bataev
ea1b525ceb [LAA] Add tests with non-power-of-2 store-load forward distance (#136710) 2025-04-28 15:10:55 -07:00
Alexey Bataev
88f8637d22 Revert "[LAA] Add tests with non-power-of-2 store-load forward distance (#136710)"
This reverts commit 51bbebb6677bb0ea14ca62cc140492965c2a6e19 to fix
buildbots https://lab.llvm.org/buildbot/#/builders/137/builds/17662
2025-04-28 14:36:44 -07:00
Alexey Bataev
51bbebb667
[LAA] Add tests with non-power-of-2 store-load forward distance (#136710) 2025-04-28 17:02:02 -04:00
Alexey Bataev
78777a204a
[LV]Split store-load forward distance analysis from other checks, NFC (#121156)
The patch splits the store-load forwarding distance analysis from other
dependency analysis in LAA. Currently it supports only power-of-2
distances, required to support non-power-of-2 distances in future.

Part of #100755
2025-03-31 07:28:44 -04:00
Florian Hahn
8bdcd0a96e
[LAA] Add missing test coverage for retrying with runtime checks.
Adds extra test coverage showing change by
https://github.com/llvm/llvm-project/pull/128045.
2025-03-27 19:09:10 +00:00
Florian Hahn
dfb661cd1c
[LAA] Add extra tests for #128061.
Extend test coverage for
https://github.com/llvm/llvm-project/pull/128061.
2025-03-13 21:42:32 +00:00
Florian Hahn
275baedfde
[LAA] Consider accessed addrspace when mapping underlying obj to access. (#129087)
In some cases, it is possible for the same underlying object to be
accessed via pointers to different address spaces. This could lead to
pointers from different address spaces ending up in the same dependency
set, which isn't allowed (and triggers an assertion).

Update the mapping from underlying object -> last access to also include
the accessing address space.

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

PR: https://github.com/llvm/llvm-project/pull/129087
2025-02-28 20:56:12 +00:00
Florian Hahn
52ded67249
[LAA] Always require non-wrapping pointers for runtime checks. (#127543)
Currently we only check if the pointers involved in runtime checks do
not wrap if we need to perform dependency checks. If that's not the
case, we generate runtime checks, even if the pointers may wrap (see
test/Analysis/LoopAccessAnalysis/runtime-checks-may-wrap.ll).

If the pointer wraps, then we swap start and end of the runtime check,
leading to incorrect checks.

An Alive2 proof of what the runtime checks are checking conceptually (on
i4 to have it complete in reasonable time) showing the incorrect result
should be https://alive2.llvm.org/ce/z/KsHzn8

Depends on https://github.com/llvm/llvm-project/pull/127410 to avoid
more regressions.

PR: https://github.com/llvm/llvm-project/pull/127543
2025-02-20 19:00:23 +01:00
Florian Hahn
01d0793a69
[LAA] Make Ptr argument optional in isNoWrap. (#127410)
Update isNoWrap to make the IR Ptr argument optional. This allows using
isNoWrap when dealing with things like pointer-selects, where a select
is translated to multiple pointer SCEV expressions, but there is no IR
value that can be used. We don't try to retrieve pointer values for the
pointer SCEVs and using info from the IR would not be safe. For example,
we cannot use inbounds, because the pointer may never be accessed.

PR: https://github.com/llvm/llvm-project/pull/127410
2025-02-19 14:51:19 +01:00
Ramkumar Ramachandra
6646b65082
[LAA] Rework and rename stripGetElementPtr (#125315)
The stripGetElementPtr function is mysteriously named, and calls into
another mysterious getGEPInductionOperand which does something
complicated with GEP indices. The real purpose of the badly-named
stripGetElementPtr function is to get a loop-variant GEP index, if there
is one. The getGEPInductionOperand is totally redundant, as stripping
off zeros from the end of GEP indices has no effect on computing the
loop-variant GEP index, as constant zeros are always loop-invariant.
Moreover, the GEP induction operand is simply the first non-zero index
from the end, which stripGetElementPtr returns when it finds that any of
the GEP indices are loop-variant: this is a completely unrelated value
to the GEP index that is loop-variant. The implicit assumption here is
that there is only ever one loop-variant index, and it is the first
non-zero one from the end.

The logic is unnecessarily complicated for what stripGetElementPtr wants
to achieve, and the header comments are confusing as well. Strip
getGEPInductionOperand, rework and rename stripGetElementPtr.
2025-02-18 10:25:47 +00:00
Florian Hahn
88e72c401b [LAA] Add test where GEPs may wrap. 2025-02-17 21:49:40 +01:00
Florian Hahn
e080366a76 [LAA] Inline hasComputableBounds in only caller, simplify isNoWrap.
Inline hasComputableBounds into createCheckForAccess. This removes a
level of indirection and allows for passing the AddRec directly to
isNoWrap, removing the need to retrieve the AddRec for the pointer
again.

The early continue for invariant SCEVs now also applies to forked
pointers (i.e. when there's more than one entry in TranslatedPtrs) when
ShouldCheckWrap is true, as those trivially won't wrap.

The change is NFC otherwise. replaceSymbolicStrideSCEV is now called
earlier.
2025-02-16 19:56:13 +01:00
Florian Hahn
044b52832a
[LAA] Perform checks for no-wrap separately from getPtrStride. (#126971)
Reorganize the code in isNoWrap to perform the no-wrap checks without
relying on getPtrStride directly. getPtrStride now uses isNoWrap.

The new structure allows deriving no-wrap in more cases in LAA, because
there are some cases where getPtrStride bails out early because it
cannot return a constant stride, but we can still prove no-wrap for the
pointer.

An example are AddRecs with non-ConstantInt strides with inbound GEPs,
in the improved test cases.

This enables vectorization with runtime checks in a few more cases.

PR: https://github.com/llvm/llvm-project/pull/126971
2025-02-14 20:06:37 +01:00
Florian Hahn
1199bbb396 [LAA] Add forked pointers tests with dep checks and runtime checks (NFC)
Add missing test coverage where generating runtime checks is tried again
after dependence analysis.
2025-02-14 19:45:52 +01:00
Ramkumar Ramachandra
8327c2cfdb
LAA: fix logic for MaxTargetVectorWidth (#125487)
Uses the fixed register width if scalable vectorization is not enabled
(via TargetTransformInfo::enableScalableVectorization) and improves
results if there are scalable vector registers, but they shouldn't be
used.
2025-02-13 11:40:05 +00:00
Florian Hahn
82605285b8 [LAA] Also clear CheckingGroups in RuntimePointerChecking::reset.
This fixes a crash when trying to print access-info in the newly added
test cases.
2025-02-12 21:49:22 +01:00
Ramkumar Ramachandra
8fe7860610
LAA/test: cover invariant stores with unit stride (#124586)
LoopAccessAnalysis is missing coverage of the special-case of invariant
stores with unit stride. It was previously determined that
stride-versioning for stores is not profitable, but test coverage is
missing. Fix this.
2025-01-28 10:02:28 +00:00
Ramkumar Ramachandra
3a4376b8f9
LAA: handle 0 return from getPtrStride correctly (#124539)
getPtrStride returns 0 when the PtrScev is loop-invariant, and this is
not an erroneous value: it returns std::nullopt to communicate that it
was not able to find a valid pointer stride. In analyzeLoop, we call
getPtrStride with a value_or(0) conflating the zero return value with
std::nullopt. Fix this, handling loop-invariant loads correctly.
2025-01-27 14:21:14 +00:00
Ramkumar Ramachandra
a94f08174c
LAA: regen a test with UTC (NFC) (#122748) 2025-01-14 09:02:33 +00:00
Ramkumar Ramachandra
8b4561467e
LAA: add missed swap when inverting src, sink (#122254)
When inverting source and sink on a negative induction step, the types
of the source and sink should also be swapped. This fixes a bug in the
code that follows, that computes properties based on these types. With
234cc40 ([LAA] Limit no-overlap check to at least one loop-invariant
accesses.), that code is guarded by a loop-invariant condition: however,
the commit did not add any new tests exercising the guarded code, and
hence the bugfix in this patch requires additional tests to exercise
that guarded codepath.
2025-01-13 13:07:19 +00:00
Florian Hahn
8fce5d96a7
[SCEV] Update changed test after df8efbdbb.
Test needed updating due to changes on main since branch was tested.
2024-12-20 21:13:35 +00:00
Florian Hahn
df8efbdbbf
[SCEV] Remove existing predicates implied by newly added ones. (#118185)
When adding a new predicate to a union predicate, some of the existing
predicates may be implied by the new predicate. Remove any existing
predicates that are already implied by the new predicate.

Depends on https://github.com/llvm/llvm-project/pull/118184 to show the
main benefit.

PR: https://github.com/llvm/llvm-project/pull/118185
2024-12-20 20:49:37 +00:00
Florian Hahn
95eb49a090
[SCEV] Bail out on mixed int/pointer in SCEVWrapPredicate::implies.
Fixes a crash when trying to extend the pointer start value to a narrow
integer type after b6c29fdffd65.
2024-12-18 11:22:39 +00:00
Florian Hahn
7bfcf93527
[SCEV] Use Step and Start to check if SCEVWrapPredicate is implied. (#118184)
A SCEVWrapPredicate A implies B, if
 * they have the same flag,
 * both steps are positive and
 * B's start and step are ULE/SLE (for NSUW/NSSW) than A's.

See https://alive2.llvm.org/ce/z/n2T4ss (first pair with known constants
as strides, second pair with variable strides).

Note that this is limited to steps of the same size, due to NSUW having
slightly different semantics than regular NUW. We should be able to
remove this restriction for NSSW (which matches NSW) in the future.

PR: https://github.com/llvm/llvm-project/pull/118184
2024-12-16 15:51:22 +00:00
Florian Hahn
1c702d3854
[SCEV] Add tests where one wrap predicate implies another. 2024-11-30 14:12:54 +00:00
Nikita Popov
e636434bdf
[BasicAA][LAA] Don't use same-block phis in cross iteration mode (#116802)
In 4de3184f07fd8c548125d315dd306d4afa7c9698 we exposed BasicAA's
cross-iteration mode for use in LAA, so we can handle selects with equal
conditions correctly (where the select condition is not actually equal
across iterations).

However, if we replace the selects with equivalent phis, the issue still
exists. In the phi case, we effectively still have an assumption that
the condition(s) that control which phi arg is used will be the same
across iterations. Fix this by disabling this phi handling in
cross-iteration mode.

(I'm not entirely sure whether this is also needed when BasicAA enables
cross-iteration mode during internal phi recursion, but I wouldn't be
surprised if that's the case.)
2024-11-27 09:38:51 +01:00
Nikita Popov
681939e154 [LAA] Add phi test variant for cross-iteration dependence (NFC) 2024-11-19 14:28:25 +01:00
Florian Hahn
a353e258ba
[LAA] Don't require Stride == 1/-1 for inbounds pointer AddRecs nowrap. (#113126)
If we have a pointer AddRec, the maximum increment is
2^(pointer-index-wdith - 1) - 1. This means that if incrementing the
AddRec wraps, the distance between the previously accessed location and
the wrapped location is > 2^(pointer-index-wdith - 1), i.e. if the GEP
for the AddRec is inbounds, this would be poison due to the object being
larger than half the pointer index type space. The poison would be
immediate UB when the memory access gets executed..

Similar reasoning can be applied for decrements.

PR: https://github.com/llvm/llvm-project/pull/113126
2024-11-05 22:45:56 +01:00
Ramkumar Ramachandra
d897ea37db
LAA: check nusw on GEP in place of inbounds (#112223)
With the introduction of the nusw flag in GEPNoWrapFlags, it should be
safe to weaken the check in LoopAccessAnalysis to just check the nusw
flag on the GEP, instead of inbounds.
2024-10-22 09:58:54 +01:00
Ramkumar Ramachandra
f719cfa868
LAA: be less conservative in isNoWrap (#112553)
isNoWrap has exactly one caller which handles Assume = true separately,
but too conservatively. Instead, pass Assume to isNoWrap, so it is
threaded into getPtrStride, which has the correct handling for the
Assume flag. Also note that the Stride == 1 check in isNoWrap is
incorrect: getPtrStride returns Strides == 1 or -1, except when
isNoWrapAddRec or Assume are true, assuming ShouldCheckWrap is true; we
can include the case of -1 Stride, and when isNoWrapAddRec is true. With
this change, passing Assume = true to getPtrStride could return a
non-unit stride, and we correctly handle that case as well.
2024-10-22 09:55:51 +01:00
Florian Hahn
dec4cfdb09
[LAA] Use loop guards when checking invariant accesses.
Apply loop guards to start and end pointers like done in other places to
improve results.
2024-10-04 12:23:13 +01:00
Florian Hahn
972353fdfa
[LAA] Add tests where results can be improved using loop guards. 2024-10-04 11:26:16 +01:00
Ramkumar Ramachandra
7eea55fd4b
LoopLoadElim: re-org tests after invalid #96656 (#97598)
After pr96656.ll were added to LAA and LoopVersioning, it was decided
that the bug is in a caller of LoopVersioning, not in LAA or
LoopVersioning itself. The new candidate was LoopLoadElim, but #96656
has since been marked invalid. Hence, re-organize the added tests to
avoid confusion, and the testcase from the investigation to
LoopLoadElim.
2024-09-30 15:46:34 +01:00
Florian Hahn
606a9342f1
[LAA] Add test cases where evaluating AddRecs at symbolic max BTC wraps.
The underlying issue was discovered by an assert added in
a80053322b765eec939 by a test case provided by @mstorsjo.
2024-08-29 12:29:10 +01:00
Florian Hahn
d43a80936d
Revert "[LAA] Remove loop-invariant check added in 234cc40adc61."
This reverts commit a80053322b765eec93951e21db490c55521da2d8.

The new asserts exposed an underlying issue where the expanded bounds
could wrap, causing the parts of the code to incorrectly determine that
accesses do not overlap.

Reproducer below based on @mstorsjo's test case.

opt -passes='print<access-info>'

target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"

define i32 @j(ptr %P, i32 %x, i32 %y) {
entry:
  %gep.P.4 = getelementptr inbounds nuw i8, ptr %P, i32 4
  %gep.P.8 = getelementptr inbounds nuw i8, ptr %P, i32 8
  br label %loop

loop:
  %1 = phi i32 [ %x, %entry ], [ %sel, %loop.latch ]
  %iv = phi i32 [ %y, %entry ], [ %iv.next, %loop.latch ]
  %gep.iv = getelementptr inbounds i64, ptr %gep.P.8, i32 %iv
  %l = load i32, ptr %gep.iv, align 4
  %c.1 = icmp eq i32 %l, 3
  br i1 %c.1, label %loop.latch, label %if.then

if.then:                                          ; preds = %for.body
  store i64 0, ptr %gep.iv, align 4
  %l.2 = load i32, ptr %gep.P.4
  br label %loop.latch

loop.latch:
  %sel = phi i32 [ %l.2, %if.then ], [ %1, %loop ]
  %iv.next = add nsw i32 %iv, 1
  %c.2 = icmp slt i32 %iv.next, %sel
  br i1 %c.2, label %loop, label %exit

exit:
  %res = phi i32 [ %iv.next, %loop.latch ]
  ret i32 %res
}
2024-08-27 11:55:47 +01:00
Florian Hahn
a80053322b
[LAA] Remove loop-invariant check added in 234cc40adc61.
234cc40adc61 introduced a loop-invariance check to limit the
compile-time impact of the newly added checks.

This patch removes the restriction and avoids extra compile-time impact
by sinking the check to exits where we would return an unknown
dependence. This notably reduces the amount the extra checks are
executed while not missing out on any improvements from them.

https://llvm-compile-time-tracker.com/compare.php?from=33e7cd6ff23f6c904314d17c68dc58168fd32d09&to=7c55e66d4f31ce8262b90c119a8e84e1f9515ff1&stat=instructions:u
2024-08-26 10:24:00 +01:00
Ramkumar Ramachandra
a80dd44b0d
LAA: pre-commit tests for stride-versioning (#97570)
Add tests for when the Stride is unknown and equal to TC, with different
kinds of casts. In these cases, LAA should not speculate on Stride.
2024-08-21 12:11:19 +01:00
Florian Hahn
844c188c79
[LAA] Refine stride checks for SCEVs during dependence analysis. (#99577)
Update getDependenceDistanceStrideAndSize to reason about different
combinations of strides directly and explicitly.

Update getPtrStride to return 0 for invariant pointers.

Then proceed by checking the strides.

If either source or sink are not strided by a constant (i.e. not a
non-wrapping AddRec) or invariant, the accesses may overlap
with earlier or later iterations and we cannot generate runtime
checks to disambiguate them.

Otherwise they are either loop invariant or strided. In that case, we
can generate a runtime check to disambiguate them.

If both are strided by constants, we proceed as previously.

This is an alternative to
https://github.com/llvm/llvm-project/pull/99239 and also replaces
additional checks if the underlying object is loop-invariant.

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

PR: https://github.com/llvm/llvm-project/pull/99577
2024-07-26 13:10:16 +01:00
Jay Foad
8ebe499e07 [LLVM] Fix typo "depedent" 2024-07-23 12:52:20 +01:00
Florian Hahn
4199f80df5
[LAA] Adjust test from a4f8705b05 so RT checks aren't always false.
Updated @B_indices_loaded_in_loop_A_stored to use a different offset
for one of the accesses we create runtime checks for; the original
version had a runtime check that was always true as the accesses always
overlapped.
2024-07-16 21:56:57 +01:00
Florian Hahn
3ccda93671
[LAA] Update pointer-bounds cache to also consider access type.
The same pointer may be accessed with different types and the bound
includes the size of the accessed type to compute the end. Update the
cache to correctly disambiguate between different accessed types.
2024-07-14 17:24:12 +01:00
Florian Hahn
41209075da
[LAA] Add tests accesses to same pointer with different types.
Add tests with accesses to the same pointer with different types. At the
moment, runtime checks for those accesses are incorrectly based on the
smaller type.
2024-07-14 15:01:44 +01:00