[llvm] [LAA] Collect no-wrap predicates separately in getPtrStride/isNoWrap. (PR #203787)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Jun 14 13:15:48 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-analysis
Author: Florian Hahn (fhahn)
<details>
<summary>Changes</summary>
Add an overload of getPtrStride and update isNoWrap to collect no-wrap SCEV predicates in a vector, and have the caller add them to PSE if needed.
This also requires to explicitly build the wrap predicate via ScalarEvolution::getWrapPredicate (clearing statically implied flags) rather than going through PredicatedScalarEvolution::setNoOverflow, which can now be removed together with the flags map.
This also requires generalizing SCEVUnionPredicate::implies so a wrap predicate can be recognized as implied by an existing wrap predicate after applying equal predicates, avoiding redundant predicates when the collected predicates are committed.
The only functional changes is re-ordering of runtime check groups in a single test case; no functional IR changes across a large IR corpus (32k modules)
To be used to avoid adding unnecessary wrap predicates during interleave group analysis: https://github.com/llvm/llvm-project/pull/200807
---
Full diff: https://github.com/llvm/llvm-project/pull/203787.diff
5 Files Affected:
- (modified) llvm/include/llvm/Analysis/LoopAccessAnalysis.h (+13-3)
- (modified) llvm/include/llvm/Analysis/ScalarEvolution.h (+3-10)
- (modified) llvm/lib/Analysis/LoopAccessAnalysis.cpp (+53-21)
- (modified) llvm/lib/Analysis/ScalarEvolution.cpp (+20-27)
- (modified) llvm/test/Analysis/LoopAccessAnalysis/retry-runtime-checks-after-dependence-analysis.ll (+24-24)
``````````diff
diff --git a/llvm/include/llvm/Analysis/LoopAccessAnalysis.h b/llvm/include/llvm/Analysis/LoopAccessAnalysis.h
index 6c9097c92a86d..7b4db1c471be1 100644
--- a/llvm/include/llvm/Analysis/LoopAccessAnalysis.h
+++ b/llvm/include/llvm/Analysis/LoopAccessAnalysis.h
@@ -886,8 +886,8 @@ replaceSymbolicStrideSCEV(PredicatedScalarEvolution &PSE,
///
/// If necessary this method will version the stride of the pointer according
/// to \p PtrToStride and therefore add further predicates to \p PSE.
-/// The \p Assume parameter indicates if we are allowed to make additional
-/// run-time assumptions.
+///
+/// If \p Predicates is non-null, add no-wrap SCEV predicates if needed.
///
/// Note that the analysis results are defined if-and-only-if the original
/// memory access was defined. If that access was dead, or UB, then the
@@ -897,7 +897,17 @@ getPtrStride(PredicatedScalarEvolution &PSE, Type *AccessTy, Value *Ptr,
const Loop *Lp, const DominatorTree &DT,
const DenseMap<Value *, const SCEV *> &StridesMap =
DenseMap<Value *, const SCEV *>(),
- bool Assume = false, bool ShouldCheckWrap = true);
+ bool ShouldCheckWrap = true,
+ SmallVectorImpl<const SCEVPredicate *> *Predicates = nullptr);
+
+/// Overload of \ref getPtrStride that adds the no-wrap predicates directly to
+/// \p PSE. The \p Assume parameter indicates whether such additional run-time
+/// assumptions are allowed.
+LLVM_ABI std::optional<int64_t>
+getPtrStride(PredicatedScalarEvolution &PSE, Type *AccessTy, Value *Ptr,
+ const Loop *Lp, const DominatorTree &DT,
+ const DenseMap<Value *, const SCEV *> &StridesMap, bool Assume,
+ bool ShouldCheckWrap = true);
/// Returns the distance between the pointers \p PtrA and \p PtrB iff they are
/// compatible and it is possible to calculate the distance between them. This
diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
index 50af763614a31..a78b0e26f1ad3 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -2653,19 +2653,15 @@ class PredicatedScalarEvolution {
getAsAddRec(Value *V,
SmallVectorImpl<const SCEVPredicate *> *WrapPredsAdded = nullptr);
- /// Proves that V doesn't overflow by adding SCEV predicate.
- LLVM_ABI void setNoOverflow(Value *V,
- SCEVWrapPredicate::IncrementWrapFlags Flags);
-
- /// Returns true if we've proved that V doesn't wrap by means of a SCEV
- /// predicate.
+ /// Returns true if we've statically proved that V doesn't wrap.
LLVM_ABI bool hasNoOverflow(Value *V,
SCEVWrapPredicate::IncrementWrapFlags Flags);
/// Returns the ScalarEvolution analysis used.
ScalarEvolution *getSE() const { return &SE; }
- /// We need to explicitly define the copy constructor because of FlagsMap.
+ /// We need to explicitly define the copy constructor because of the unique
+ /// SCEVUnionPredicate owned by Preds.
LLVM_ABI PredicatedScalarEvolution(const PredicatedScalarEvolution &);
/// Print the SCEV mappings done by the Predicated Scalar Evolution.
@@ -2694,9 +2690,6 @@ class PredicatedScalarEvolution {
/// SCEV.
DenseMap<const SCEV *, RewriteEntry> RewriteMap;
- /// Records what NoWrap flags we've added to a Value *.
- ValueMap<Value *, SCEVWrapPredicate::IncrementWrapFlags> FlagsMap;
-
/// The ScalarEvolution analysis.
ScalarEvolution &SE;
diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
index a2c2b0ef88da4..0046ba2472274 100644
--- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp
+++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
@@ -1021,16 +1021,19 @@ getStrideFromAddRec(const SCEVAddRecExpr *AR, const Loop *Lp, Type *AccessTy,
}
/// Check whether \p AR is a non-wrapping AddRec. If \p Ptr is not nullptr, use
-/// informating from the IR pointer value to determine no-wrap.
-static bool isNoWrap(PredicatedScalarEvolution &PSE, const SCEVAddRecExpr *AR,
- Value *Ptr, Type *AccessTy, const Loop *L, bool Assume,
- const DominatorTree &DT,
- std::optional<int64_t> Stride = std::nullopt) {
+/// information from the IR pointer value to determine no-wrap. If \p Predicates
+/// is not nullptr add no-wrap assumptions if needed.
+static bool
+isNoWrap(PredicatedScalarEvolution &PSE, const SCEVAddRecExpr *AR, Value *Ptr,
+ Type *AccessTy, const Loop *L, const DominatorTree &DT,
+ std::optional<int64_t> Stride = std::nullopt,
+ SmallVectorImpl<const SCEVPredicate *> *Predicates = nullptr) {
// FIXME: This should probably only return true for NUW.
if (any(AR->getNoWrapFlags(SCEV::NoWrapMask)))
return true;
- if (Ptr && PSE.hasNoOverflow(Ptr, SCEVWrapPredicate::IncrementNUSW))
+ if (Ptr && isa<SCEVAddRecExpr>(PSE.getSCEV(Ptr)) &&
+ PSE.hasNoOverflow(Ptr, SCEVWrapPredicate::IncrementNUSW))
return true;
// An nusw getelementptr that is an AddRec cannot wrap. If it would wrap,
@@ -1066,8 +1069,12 @@ static bool isNoWrap(PredicatedScalarEvolution &PSE, const SCEVAddRecExpr *AR,
return true;
}
- if (Ptr && Assume) {
- PSE.setNoOverflow(Ptr, SCEVWrapPredicate::IncrementNUSW);
+ if (Ptr && Predicates) {
+ ScalarEvolution *SE = PSE.getSE();
+ SCEVWrapPredicate::IncrementWrapFlags Flags = SCEVWrapPredicate::clearFlags(
+ SCEVWrapPredicate::IncrementNUSW,
+ SCEVWrapPredicate::getImpliedFlags(AR, *SE));
+ Predicates->push_back(SE->getWrapPredicate(AR, Flags));
LLVM_DEBUG(dbgs() << "LAA: Pointer may wrap:\n"
<< "LAA: Pointer: " << *Ptr << "\n"
<< "LAA: SCEV: " << *AR << "\n"
@@ -1295,6 +1302,7 @@ bool AccessAnalysis::createCheckForAccess(
/// Check whether all pointers can participate in a runtime bounds check. They
/// must either be invariant or non-wrapping affine AddRecs.
+ SmallVector<const SCEVPredicate *> Predicates;
for (auto &P : RTCheckPtrs) {
// The bounds for loop-invariant pointer is trivial.
if (SE->isLoopInvariant(P.getPointer(), TheLoop))
@@ -1315,9 +1323,12 @@ bool AccessAnalysis::createCheckForAccess(
}
if (!isNoWrap(PSE, AR, RTCheckPtrs.size() == 1 ? Ptr : nullptr, AccessTy,
- TheLoop, Assume, DT))
+ TheLoop, DT, /*Stride=*/std::nullopt,
+ Assume ? &Predicates : nullptr))
return false;
}
+ for (const SCEVPredicate *P : Predicates)
+ PSE.addPredicate(*P);
for (const auto &[PtrExpr, NeedsFreeze] : RTCheckPtrs) {
// The id of the dependence set.
@@ -1646,11 +1657,10 @@ void AccessAnalysis::buildDependenceSets() {
}
/// Check whether the access through \p Ptr has a constant stride.
-std::optional<int64_t>
-llvm::getPtrStride(PredicatedScalarEvolution &PSE, Type *AccessTy, Value *Ptr,
- const Loop *Lp, const DominatorTree &DT,
- const DenseMap<Value *, const SCEV *> &StridesMap,
- bool Assume, bool ShouldCheckWrap) {
+std::optional<int64_t> llvm::getPtrStride(
+ PredicatedScalarEvolution &PSE, Type *AccessTy, Value *Ptr, const Loop *Lp,
+ const DominatorTree &DT, const DenseMap<Value *, const SCEV *> &StridesMap,
+ bool ShouldCheckWrap, SmallVectorImpl<const SCEVPredicate *> *Predicates) {
const SCEV *PtrScev = replaceSymbolicStrideSCEV(PSE, StridesMap, Ptr);
if (PSE.getSE()->isLoopInvariant(PtrScev, Lp))
return 0;
@@ -1658,8 +1668,10 @@ llvm::getPtrStride(PredicatedScalarEvolution &PSE, Type *AccessTy, Value *Ptr,
assert(Ptr->getType()->isPointerTy() && "Unexpected non-ptr");
const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(PtrScev);
- if (Assume && !AR)
- AR = PSE.getAsAddRec(Ptr);
+ if (Predicates && !AR) {
+ AR = PSE.getSE()->convertSCEVToAddRecWithPredicates(PtrScev, Lp,
+ *Predicates);
+ }
if (!AR) {
LLVM_DEBUG(dbgs() << "LAA: Bad stride - Not an AddRecExpr pointer " << *Ptr
@@ -1672,7 +1684,7 @@ llvm::getPtrStride(PredicatedScalarEvolution &PSE, Type *AccessTy, Value *Ptr,
if (!ShouldCheckWrap || !Stride)
return Stride;
- if (isNoWrap(PSE, AR, Ptr, AccessTy, Lp, Assume, DT, Stride))
+ if (isNoWrap(PSE, AR, Ptr, AccessTy, Lp, DT, Stride, Predicates))
return Stride;
LLVM_DEBUG(
@@ -1681,6 +1693,21 @@ llvm::getPtrStride(PredicatedScalarEvolution &PSE, Type *AccessTy, Value *Ptr,
return std::nullopt;
}
+/// Check whether the access through \p Ptr has a constant stride.
+std::optional<int64_t>
+llvm::getPtrStride(PredicatedScalarEvolution &PSE, Type *AccessTy, Value *Ptr,
+ const Loop *Lp, const DominatorTree &DT,
+ const DenseMap<Value *, const SCEV *> &StridesMap,
+ bool Assume, bool ShouldCheckWrap) {
+ SmallVector<const SCEVPredicate *> Predicates;
+ std::optional<int64_t> Stride =
+ getPtrStride(PSE, AccessTy, Ptr, Lp, DT, StridesMap, ShouldCheckWrap,
+ Assume ? &Predicates : nullptr);
+ for (const SCEVPredicate *P : Predicates)
+ PSE.addPredicate(*P);
+ return Stride;
+}
+
std::optional<int64_t> llvm::getPointersDiff(Type *ElemTyA, Value *PtrA,
Type *ElemTyB, Value *PtrB,
const DataLayout &DL,
@@ -2093,10 +2120,15 @@ MemoryDepChecker::getDependenceDistanceStrideAndSize(
BPtr->getType()->getPointerAddressSpace())
return MemoryDepChecker::Dependence::Unknown;
- std::optional<int64_t> StrideAPtr = getPtrStride(
- PSE, ATy, APtr, InnermostLoop, *DT, SymbolicStrides, true, true);
- std::optional<int64_t> StrideBPtr = getPtrStride(
- PSE, BTy, BPtr, InnermostLoop, *DT, SymbolicStrides, true, true);
+ SmallVector<const SCEVPredicate *> Predicates;
+ std::optional<int64_t> StrideAPtr =
+ getPtrStride(PSE, ATy, APtr, InnermostLoop, *DT, SymbolicStrides,
+ /*ShouldCheckWrap=*/true, &Predicates);
+ std::optional<int64_t> StrideBPtr =
+ getPtrStride(PSE, BTy, BPtr, InnermostLoop, *DT, SymbolicStrides,
+ /*ShouldCheckWrap=*/true, &Predicates);
+ for (const SCEVPredicate *P : Predicates)
+ PSE.addPredicate(*P);
const SCEV *Src = PSE.getSCEV(APtr);
const SCEV *Sink = PSE.getSCEV(BPtr);
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index c0cdce982e623..88030f19bd315 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -15476,8 +15476,25 @@ bool SCEVUnionPredicate::implies(const SCEVPredicate *N,
return this->implies(I, SE);
});
- return any_of(Preds,
- [N, &SE](const SCEVPredicate *I) { return I->implies(N, SE); });
+ if (any_of(Preds,
+ [N, &SE](const SCEVPredicate *I) { return I->implies(N, SE); }))
+ return true;
+
+ // A wrap predicate may be implied by a wrap predicate in Preds after applying
+ // equal predicates.
+ const auto *NWrap = dyn_cast<SCEVWrapPredicate>(N);
+ if (!NWrap)
+ return false;
+ const Loop *L = NWrap->getExpr()->getLoop();
+ return any_of(Preds, [&](const SCEVPredicate *I) {
+ const auto *IWrap = dyn_cast<SCEVWrapPredicate>(I);
+ if (!IWrap)
+ return false;
+ const auto *RewrittenAR = dyn_cast<SCEVAddRecExpr>(
+ SE.rewriteUsingPredicate(IWrap->getExpr(), L, *this));
+ return RewrittenAR &&
+ SE.getWrapPredicate(RewrittenAR, IWrap->getFlags())->implies(N, SE);
+ });
}
void SCEVUnionPredicate::print(raw_ostream &OS, unsigned Depth) const {
@@ -15617,22 +15634,6 @@ void PredicatedScalarEvolution::updateGeneration() {
}
}
-void PredicatedScalarEvolution::setNoOverflow(
- Value *V, SCEVWrapPredicate::IncrementWrapFlags Flags) {
- const SCEV *Expr = getSCEV(V);
- const auto *AR = cast<SCEVAddRecExpr>(Expr);
-
- auto ImpliedFlags = SCEVWrapPredicate::getImpliedFlags(AR, SE);
-
- // Clear the statically implied flags.
- Flags = SCEVWrapPredicate::clearFlags(Flags, ImpliedFlags);
- addPredicate(*SE.getWrapPredicate(AR, Flags));
-
- auto II = FlagsMap.insert({V, Flags});
- if (!II.second)
- II.first->second = SCEVWrapPredicate::setFlags(Flags, II.first->second);
-}
-
bool PredicatedScalarEvolution::hasNoOverflow(
Value *V, SCEVWrapPredicate::IncrementWrapFlags Flags) {
const SCEV *Expr = getSCEV(V);
@@ -15641,11 +15642,6 @@ bool PredicatedScalarEvolution::hasNoOverflow(
Flags = SCEVWrapPredicate::clearFlags(
Flags, SCEVWrapPredicate::getImpliedFlags(AR, SE));
- auto II = FlagsMap.find(V);
-
- if (II != FlagsMap.end())
- Flags = SCEVWrapPredicate::clearFlags(Flags, II->second);
-
return Flags == SCEVWrapPredicate::IncrementAnyWrap;
}
@@ -15675,10 +15671,7 @@ PredicatedScalarEvolution::PredicatedScalarEvolution(
: RewriteMap(Init.RewriteMap), SE(Init.SE), L(Init.L),
Preds(std::make_unique<SCEVUnionPredicate>(Init.Preds->getPredicates(),
SE)),
- Generation(Init.Generation), BackedgeCount(Init.BackedgeCount) {
- for (auto I : Init.FlagsMap)
- FlagsMap.insert(I);
-}
+ Generation(Init.Generation), BackedgeCount(Init.BackedgeCount) {}
void PredicatedScalarEvolution::print(raw_ostream &OS, unsigned Depth) const {
// For each block.
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/retry-runtime-checks-after-dependence-analysis.ll b/llvm/test/Analysis/LoopAccessAnalysis/retry-runtime-checks-after-dependence-analysis.ll
index 63abd4ef70d63..88b16d0f32534 100644
--- a/llvm/test/Analysis/LoopAccessAnalysis/retry-runtime-checks-after-dependence-analysis.ll
+++ b/llvm/test/Analysis/LoopAccessAnalysis/retry-runtime-checks-after-dependence-analysis.ll
@@ -72,27 +72,27 @@ define void @dependency_check_and_runtime_checks_needed_gepb_not_inbounds_iv2_st
; CHECK-NEXT: Comparing group GRP0:
; CHECK-NEXT: %gep.a.iv = getelementptr inbounds float, ptr %a, i64 %iv
; CHECK-NEXT: Against group GRP1:
-; CHECK-NEXT: %gep.b = getelementptr i8, ptr %b, i64 %iv2
+; CHECK-NEXT: %gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
; CHECK-NEXT: Check 1:
; CHECK-NEXT: Comparing group GRP0:
; CHECK-NEXT: %gep.a.iv = getelementptr inbounds float, ptr %a, i64 %iv
; CHECK-NEXT: Against group GRP2:
-; CHECK-NEXT: %gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
+; CHECK-NEXT: %gep.b = getelementptr i8, ptr %b, i64 %iv2
; CHECK-NEXT: Check 2:
; CHECK-NEXT: Comparing group GRP1:
-; CHECK-NEXT: %gep.b = getelementptr i8, ptr %b, i64 %iv2
-; CHECK-NEXT: Against group GRP2:
; CHECK-NEXT: %gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
+; CHECK-NEXT: Against group GRP2:
+; CHECK-NEXT: %gep.b = getelementptr i8, ptr %b, i64 %iv2
; CHECK-NEXT: Grouped accesses:
; CHECK-NEXT: Group GRP0:
; CHECK-NEXT: (Low: %a High: ((4 * %n) + %a))
; CHECK-NEXT: Member: {%a,+,4}<nuw><%loop>
; CHECK-NEXT: Group GRP1:
-; CHECK-NEXT: (Low: %b High: (-1 + (5 * %n) + %b))
-; CHECK-NEXT: Member: {%b,+,5}<%loop>
-; CHECK-NEXT: Group GRP2:
; CHECK-NEXT: (Low: ((4 * %offset) + %a) High: ((4 * %offset) + (4 * %n) + %a))
; CHECK-NEXT: Member: {((4 * %offset) + %a),+,4}<%loop>
+; CHECK-NEXT: Group GRP2:
+; CHECK-NEXT: (Low: %b High: (-1 + (5 * %n) + %b))
+; CHECK-NEXT: Member: {%b,+,5}<%loop>
; CHECK-EMPTY:
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
; CHECK-NEXT: SCEV assumptions:
@@ -265,27 +265,27 @@ define void @dependency_check_and_runtime_checks_needed_gepb_may_wrap(ptr %a, pt
; CHECK-NEXT: Comparing group GRP0:
; CHECK-NEXT: %gep.a.iv = getelementptr inbounds float, ptr %a, i64 %iv
; CHECK-NEXT: Against group GRP1:
-; CHECK-NEXT: %gep.b = getelementptr float, ptr %b, i64 %iv2
+; CHECK-NEXT: %gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
; CHECK-NEXT: Check 1:
; CHECK-NEXT: Comparing group GRP0:
; CHECK-NEXT: %gep.a.iv = getelementptr inbounds float, ptr %a, i64 %iv
; CHECK-NEXT: Against group GRP2:
-; CHECK-NEXT: %gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
+; CHECK-NEXT: %gep.b = getelementptr float, ptr %b, i64 %iv2
; CHECK-NEXT: Check 2:
; CHECK-NEXT: Comparing group GRP1:
-; CHECK-NEXT: %gep.b = getelementptr float, ptr %b, i64 %iv2
-; CHECK-NEXT: Against group GRP2:
; CHECK-NEXT: %gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
+; CHECK-NEXT: Against group GRP2:
+; CHECK-NEXT: %gep.b = getelementptr float, ptr %b, i64 %iv2
; CHECK-NEXT: Grouped accesses:
; CHECK-NEXT: Group GRP0:
; CHECK-NEXT: (Low: %a High: ((4 * %n) + %a))
; CHECK-NEXT: Member: {%a,+,4}<nuw><%loop>
; CHECK-NEXT: Group GRP1:
-; CHECK-NEXT: (Low: %b High: (-4 + (8 * %n) + %b))
-; CHECK-NEXT: Member: {%b,+,8}<%loop>
-; CHECK-NEXT: Group GRP2:
; CHECK-NEXT: (Low: ((4 * %offset) + %a) High: ((4 * %offset) + (4 * %n) + %a))
; CHECK-NEXT: Member: {((4 * %offset) + %a),+,4}<%loop>
+; CHECK-NEXT: Group GRP2:
+; CHECK-NEXT: (Low: %b High: (-4 + (8 * %n) + %b))
+; CHECK-NEXT: Member: {%b,+,8}<%loop>
; CHECK-EMPTY:
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
; CHECK-NEXT: SCEV assumptions:
@@ -325,29 +325,29 @@ define void @retry_after_dep_check_with_unknown_offset(ptr %A, i32 %offset) {
; CHECK-NEXT: Run-time memory checks:
; CHECK-NEXT: Check 0:
; CHECK-NEXT: Comparing group GRP0:
-; CHECK-NEXT: %A.100.iv = getelementptr { float, float }, ptr %A.100, i64 %iv
+; CHECK-NEXT: ptr %A
; CHECK-NEXT: Against group GRP1:
-; CHECK-NEXT: %A.100.iv.offset.3 = getelementptr i8, ptr %A.100, i64 %iv.offset.3
+; CHECK-NEXT: %A.100.iv = getelementptr { float, float }, ptr %A.100, i64 %iv
; CHECK-NEXT: Check 1:
; CHECK-NEXT: Comparing group GRP0:
-; CHECK-NEXT: %A.100.iv = getelementptr { float, float }, ptr %A.100, i64 %iv
-; CHECK-NEXT: Against group GRP2:
; CHECK-NEXT: ptr %A
+; CHECK-NEXT: Against group GRP2:
+; CHECK-NEXT: %A.100.iv.offset.3 = getelementptr i8, ptr %A.100, i64 %iv.offset.3
; CHECK-NEXT: Check 2:
; CHECK-NEXT: Comparing group GRP1:
-; CHECK-NEXT: %A.100.iv.offset.3 = getelementptr i8, ptr %A.100, i64 %iv.offset.3
+; CHECK-NEXT: %A.100.iv = getelementptr { float, float }, ptr %A.100, i64 %iv
; CHECK-NEXT: Against group GRP2:
-; CHECK-NEXT: ptr %A
+; CHECK-NEXT: %A.100.iv.offset.3 = getelementptr i8, ptr %A.100, i64 %iv.offset.3
; CHECK-NEXT: Grouped accesses:
; CHECK-NEXT: Group GRP0:
+; CHECK-NEXT: (Low: %A High: (4 + %A))
+; CHECK-NEXT: Member: %A
+; CHECK-NEXT: Group GRP1:
; CHECK-NEXT: (Low: (100 + %A) High: (96 + (8 * (zext i32 %offset to i64))<nuw><nsw> + %A))
; CHECK-NEXT: Member: {(100 + %A),+,8}<%loop>
-; CHECK-NEXT: Group GRP1:
+; CHECK-NEXT: Group GRP2:
; CHECK-NEXT: (Low: (100 + (8 * (zext i32 %offset to i64))<nuw><nsw> + %A) High: (96 + (16 * (zext i32 %offset to i64))<nuw><nsw> + %A))
; CHECK-NEXT: Member: {(100 + (8 * (zext i32 %offset to i64))<nuw><nsw> + %A),+,8}<%loop>
-; CHECK-NEXT: Group GRP2:
-; CHECK-NEXT: (Low: %A High: (4 + %A))
-; CHECK-NEXT: Member: %A
; CHECK-EMPTY:
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
; CHECK-NEXT: SCEV assumptions:
``````````
</details>
https://github.com/llvm/llvm-project/pull/203787
More information about the llvm-commits
mailing list