aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/LoopAccessAnalysis.cpp
AgeCommit message (Collapse)AuthorFilesLines
2025-03-15[Analysis] Avoid repeated hash lookups (NFC) (#131421)Kazu Hirata1-2/+3
2025-03-07Revert "Reland [EquivClasses] Introduce members iterator-helper" (#130380)Vitaly Buka1-2/+3
Reverts llvm/llvm-project#130319 Multiple bot failures.
2025-03-07Reland [EquivClasses] Introduce members iterator-helper (#130319)Ramkumar Ramachandra1-3/+2
Changes: Fix the expectations in EquivalenceClassesTest.MemberIterator, also fixing a build failure.
2025-03-07Revert "[EquivClasses] Introduce members iterator-helper" (#130313)Ramkumar Ramachandra1-2/+3
This reverts commit 259624bf6d, as it causes a build failure.
2025-03-07[EquivClasses] Introduce members iterator-helper (#130139)Ramkumar Ramachandra1-3/+2
2025-02-28[LAA] Consider accessed addrspace when mapping underlying obj to access. ↵Florian Hahn1-4/+8
(#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-23[Analysis] Avoid repeated hash lookups (NFC) (#128394)Kazu Hirata1-5/+6
2025-02-20[LAA] Always require non-wrapping pointers for runtime checks. (#127543)Florian Hahn1-22/+19
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[Analysis] Avoid repeated hash lookups (NFC) (#127955)Kazu Hirata1-1/+1
2025-02-20[LAA] Scale strides using type-size (NFC) (#124529)Ramkumar Ramachandra1-37/+35
Change getDependenceDistanceStrideAndSize to scale strides by TypeByteSize, scaling the returned CommonStride and MaxStride. Even though there is a seemingly-functional change of setting CommonStride when scaled strides are equal, it ends up being a non-functional change due to aggressive HasSameSize checking.
2025-02-19[LAA] Make Ptr argument optional in isNoWrap. (#127410)Florian Hahn1-17/+24
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-18[LAA] Rework and rename stripGetElementPtr (#125315)Ramkumar Ramachandra1-44/+17
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-17[LAA] Remove unneeded hasNoOverflow call (NFC).Florian Hahn1-1/+1
The function already calls hasNoOverflow above.
2025-02-17LAA: scope responsibility of isNoWrapAddRec (NFC) (#127479)Ramkumar Ramachandra1-17/+17
Free isNoWrapAddRec from the AddRec check, and rename it to isNoWrapGEP.
2025-02-16[LAA] Inline hasComputableBounds in only caller, simplify isNoWrap.Florian Hahn1-39/+20
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-15[LAA] Replace symbolic strides for translated pointers earlier (NFC).Florian Hahn1-4/+5
Move up replaceSymbolicStrideSCEV before isNoWrap. It needs to be called after hasComputableBounds, as this may create an AddRec via PSE, which replaceSymbolicStrideSCEV will look up. This is in preparation for simplifying isNoWrap.
2025-02-15[LAA] Use getPointer/setPointer in createCheckForAccess (NFC).Florian Hahn1-5/+3
Use getPointer/setPointer to clarify we are accessing/modifying the rurrent value.
2025-02-14[Analysis] Fix a warningKazu Hirata1-2/+1
This patch fixes: llvm/lib/Analysis/LoopAccessAnalysis.cpp:1530:9: error: unused variable 'Ty' [-Werror,-Wunused-variable]
2025-02-14[LAA] Get pointer address space from AddRec (NFC).Florian Hahn1-1/+1
Retrieve the address space from the pointer AddRec instead of the IR pointer value, to prepare to make the IR pointer value optional.
2025-02-14[LAA] Perform checks for no-wrap separately from getPtrStride. (#126971)Florian Hahn1-32/+50
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-13[LAA] Split off code to compute stride from AddRec for reuse (NFC).Florian Hahn1-36/+45
Refactors to code to expose the core logic from getPtrStride to compute the stride for a given AddRec. Split off from https://github.com/llvm/llvm-project/pull/126971 as suggested.
2025-02-13LAA: fix logic for MaxTargetVectorWidth (#125487)Ramkumar Ramachandra1-13/+5
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-03LAA: simplify LoopAccessInfoManager::clear (NFC) (#125488)Ramkumar Ramachandra1-5/+1
DenseMap::erase() doesn't invalidate the iterator.
2025-01-31LAA: improve code in getStrideFromPointer (NFC) (#124780)Ramkumar Ramachandra1-18/+10
Strip dead code, inline a constant, and modernize style.
2025-01-27LAA: handle 0 return from getPtrStride correctly (#124539)Ramkumar Ramachandra1-2/+2
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-27Reland "[LoopVectorize] Add support for reverse loops in ↵David Sherwood1-35/+26
isDereferenceableAndAlignedInLoop #96752" (#123616) The last attempt failed a sanitiser build because we were creating a reference to a null Predicates pointer in isDereferenceableAndAlignedInLoop. This was exposed by the unit test IsDerefReadOnlyLoop in unittests/Analysis/LoadsTest.cpp. I fixed this by falling back on getConstantMaxBackedgeTakenCount if Predicates is null - see line 316 in llvm/lib/Analysis/Loads.cpp. There are no other changes.
2025-01-15Revert "[LoopVectorize] Add support for reverse loops in ↵David Sherwood1-26/+35
isDereferenceableAndAlignedInLoop (#96752)" (#123057) This reverts commit bfedf6460c2cad6e6f966b457d8d27084579dcd8.
2025-01-15[LoopVectorize] Add support for reverse loops in ↵David Sherwood1-35/+26
isDereferenceableAndAlignedInLoop (#96752) Currently when we encounter a negative step in the induction variable isDereferenceableAndAlignedInLoop bails out because the element size is signed greater than the step. This patch adds support for negative steps in cases where we detect the start address for the load is of the form base + offset. In this case the address decrements in each iteration so we need to calculate the access size differently. I have done this by caling getStartAndEndForAccess from LoopAccessAnalysis.cpp. The motivation for this patch comes from PR #88385 where a reviewer requested reusing isDereferenceableAndAlignedInLoop, but that PR itself does support reverse loops. The changed test in LoopVectorize/X86/load-deref-pred.ll now passes because previously we were calculating the total access size incorrectly, whereas now it is 412 bytes and fits perfectly into the alloca.
2025-01-13LAA: add missed swap when inverting src, sink (#122254)Ramkumar Ramachandra1-0/+1
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-09LAA: refactor dependence class to prep for scaled strides (NFC) (#122113)Ramkumar Ramachandra1-12/+25
Rearrange the DepDistanceAndSizeInfo struct in preparation to scale strides. getDependenceDistanceStrideAndSize now returns the data of CommonStride, MaxStride, and clarifies when to retry with runtime checks, in place of (unscaled) strides.
2024-12-10[LAA] Strip non-inbounds offset in getPointerDiff() (NFC) (#118665)Nikita Popov1-4/+4
I believe that this code doesn't care whether the offsets are known to be inbounds a priori. For the same reason the change is not testable, as the SCEV based fallback code will look through non-inbounds offsets anyway. So make it clear that there is no special inbounds requirement here.
2024-11-28LAA: improve code in a couple of routines (NFC) (#108092)Ramkumar Ramachandra1-19/+14
2024-11-05[LAA] Don't require Stride == 1/-1 for inbounds pointer AddRecs nowrap. ↵Florian Hahn1-5/+6
(#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-10-22LAA: check nusw on GEP in place of inbounds (#112223)Ramkumar Ramachandra1-4/+4
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-22LAA: be less conservative in isNoWrap (#112553)Ramkumar Ramachandra1-10/+5
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-07[Analysis] Simplify code with DenseMap::operator[] (NFC) (#111331)Kazu Hirata1-4/+2
2024-10-04[LAA] Use loop guards when checking invariant accesses.Florian Hahn1-6/+14
Apply loop guards to start and end pointers like done in other places to improve results.
2024-09-23[LAA] Don't assume libcalls with output/input pointers can be vectorized ↵Benjamin Maxwell1-5/+12
(#108980) LoopAccessAnalysis currently does not check/track aliasing from the output pointers, but assumes vectorizing library calls with a mapping is safe. This can result in incorrect codegen if something like the following is vectorized: ``` for(int i=0; i<N; i++) { // No aliasing between input and output pointers detected. sincos(cos_out[0], sin_out+i, cos_out+i); } ``` Where for VF >= 2 `cos_out[1]` to `cos_out[VF-1]` is the cosine of the original value of `cos_out[0]` not the updated value.
2024-08-27Revert "[LAA] Remove loop-invariant check added in 234cc40adc61."Florian Hahn1-58/+23
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-26[LAA] Remove loop-invariant check added in 234cc40adc61.Florian Hahn1-23/+58
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-21[LAA] Collect loop guards only once in MemoryDepChecker (NFCI).Florian Hahn1-2/+6
This on its own gives small compile-time improvements in some configs and enables using loop guards at more places in the future while keeping compile-time impact low. https://llvm-compile-time-tracker.com/compare.php?from=c44202574ff9a8c0632aba30c2765b134557435f&to=55ffc3dd920fa9af439fd39f8f9cc13509531420&stat=instructions:u
2024-08-16[LAA] Use computeConstantDifference() (#103725)Nikita Popov1-8/+6
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-03[SCEV] Use const SCEV * explicitly in more places.Florian Hahn1-4/+4
Use const SCEV * explicitly in more places to prepare for https://github.com/llvm/llvm-project/pull/91961. Split off as suggested.
2024-07-26[LAA] Refine stride checks for SCEVs during dependence analysis. (#99577)Florian Hahn1-64/+55
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-25LAA: fix style after cursory reading (NFC) (#100447)Ramkumar Ramachandra1-43/+40
2024-07-24LAA: mark LoopInfo pointer const (NFC) (#100373)Ramkumar Ramachandra1-1/+2
2024-07-18[LAA] Include IndirectUnsafe in ::isPossiblyBackward.Florian Hahn1-1/+1
Similarly to Unknown, IndirectUnsafe should also be considered possibly backward, as it may be a backwards dependency e.g. via loading different base pointers. This also brings isPossiblyBackward in line with Dependence::isSafeForVectorization. At the moment this can't be tested, as it is not possible to write a test with an AddRec that is based on a loop varying value. But this may change in the future and may cause mis-compiles in the future.
2024-07-14[LAA] Update pointer-bounds cache to also consider access type.Florian Hahn1-3/+4
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-11Revert "[LV] Autovectorization for the all-in-one histogram intrinsic" (#98493)Graham Hunter1-138/+28
Reverts llvm/llvm-project#91458 to deal with post-commit reviewer requests.
2024-07-11[LV] Autovectorization for the all-in-one histogram intrinsic (#91458)Graham Hunter1-28/+138
This patch implements limited loop vectorization support for the 'all-in-one' histogram intrinsic. The feature is disabled by default, and when enabled will only vectorize if there are no other users of values in the gather-modify-scatter sequence.