From aa02f859021e6829fe672f95d1ce904f9c349269 Mon Sep 17 00:00:00 2001 From: Ryotaro Kasuga Date: Fri, 21 Nov 2025 12:54:44 +0000 Subject: [PATCH] [DA][Delinearization] Move validation logic into Delinearization --- llvm/include/llvm/Analysis/Delinearization.h | 10 ++ llvm/lib/Analysis/Delinearization.cpp | 107 ++++++++++++++ llvm/lib/Analysis/DependenceAnalysis.cpp | 134 +----------------- llvm/test/Analysis/Delinearization/a.ll | 1 + .../constant_functions_multi_dim.ll | 2 + .../Analysis/Delinearization/divide_by_one.ll | 2 + .../Delinearization/fixed_size_array.ll | 8 ++ .../test/Analysis/Delinearization/himeno_1.ll | 1 + .../test/Analysis/Delinearization/himeno_2.ll | 1 + .../iv_times_constant_in_subscript.ll | 1 + .../multidim_ivs_and_integer_offsets_3d.ll | 1 + ...multidim_ivs_and_integer_offsets_nts_3d.ll | 1 + ...multidim_ivs_and_parameteric_offsets_3d.ll | 1 + .../Delinearization/multidim_only_ivs_2d.ll | 2 + .../Delinearization/multidim_only_ivs_3d.ll | 1 + .../multidim_only_ivs_3d_cast.ll | 1 + ..._two_accesses_different_delinearization.ll | 2 + .../parameter_addrec_product.ll | 2 + .../terms_with_identity_factor.ll | 2 + 19 files changed, 150 insertions(+), 130 deletions(-) diff --git a/llvm/include/llvm/Analysis/Delinearization.h b/llvm/include/llvm/Analysis/Delinearization.h index 434cfb61699d6..500d62188b161 100644 --- a/llvm/include/llvm/Analysis/Delinearization.h +++ b/llvm/include/llvm/Analysis/Delinearization.h @@ -17,6 +17,7 @@ #define LLVM_ANALYSIS_DELINEARIZATION_H #include "llvm/IR/PassManager.h" +#include "llvm/IR/Value.h" namespace llvm { class raw_ostream; @@ -141,6 +142,15 @@ bool delinearizeFixedSizeArray(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl &Sizes, const SCEV *ElementSize); +/// Check that each subscript in \p Subscripts is within the corresponding size +/// in \p Sizes. For the outermost dimension, the subscript being negative is +/// allowed. If \p Ptr is not nullptr, it may be used to get information from +/// the IR pointer value, which may help in the validation. +bool validateDelinearizationResult(ScalarEvolution &SE, + ArrayRef Sizes, + ArrayRef Subscripts, + const Value *Ptr = nullptr); + /// Gathers the individual index expressions from a GEP instruction. /// /// This function optimistically assumes the GEP references into a fixed size diff --git a/llvm/lib/Analysis/Delinearization.cpp b/llvm/lib/Analysis/Delinearization.cpp index 4064b25d9d4e7..0fe8244a11e85 100644 --- a/llvm/lib/Analysis/Delinearization.cpp +++ b/llvm/lib/Analysis/Delinearization.cpp @@ -656,6 +656,108 @@ bool llvm::delinearizeFixedSizeArray(ScalarEvolution &SE, const SCEV *Expr, return !Subscripts.empty(); } +static bool isKnownNonNegative(ScalarEvolution *SE, const SCEV *S, + const Value *Ptr) { + bool Inbounds = false; + if (auto *SrcGEP = dyn_cast(Ptr)) + Inbounds = SrcGEP->isInBounds(); + if (Inbounds) { + if (const SCEVAddRecExpr *AddRec = dyn_cast(S)) { + if (AddRec->isAffine()) { + // We know S is for Ptr, the operand on a load/store, so doesn't wrap. + // If both parts are NonNegative, the end result will be NonNegative + if (SE->isKnownNonNegative(AddRec->getStart()) && + SE->isKnownNonNegative(AddRec->getOperand(1))) + return true; + } + } + } + + return SE->isKnownNonNegative(S); +} + +/// Compare to see if S is less than Size, using +/// +/// isKnownNegative(S - Size) +/// +/// with some extra checking if S is an AddRec and we can prove less-than using +/// the loop bounds. +static bool isKnownLessThan(ScalarEvolution *SE, const SCEV *S, + const SCEV *Size) { + // First unify to the same type + auto *SType = dyn_cast(S->getType()); + auto *SizeType = dyn_cast(Size->getType()); + if (!SType || !SizeType) + return false; + Type *MaxType = + (SType->getBitWidth() >= SizeType->getBitWidth()) ? SType : SizeType; + S = SE->getTruncateOrZeroExtend(S, MaxType); + Size = SE->getTruncateOrZeroExtend(Size, MaxType); + + auto CollectUpperBound = [&](const Loop *L, Type *T) -> const SCEV * { + if (SE->hasLoopInvariantBackedgeTakenCount(L)) { + const SCEV *UB = SE->getBackedgeTakenCount(L); + return SE->getTruncateOrZeroExtend(UB, T); + } + return nullptr; + }; + + auto CheckAddRecBECount = [&]() { + const SCEVAddRecExpr *AddRec = dyn_cast(S); + if (!AddRec || !AddRec->isAffine() || !AddRec->hasNoSignedWrap()) + return false; + const SCEV *BECount = CollectUpperBound(AddRec->getLoop(), MaxType); + // If the BTC cannot be computed, check the base case for S. + if (!BECount || isa(BECount)) + return false; + const SCEV *Start = AddRec->getStart(); + const SCEV *Step = AddRec->getStepRecurrence(*SE); + const SCEV *End = AddRec->evaluateAtIteration(BECount, *SE); + const SCEV *Diff0 = SE->getMinusSCEV(Start, Size); + const SCEV *Diff1 = SE->getMinusSCEV(End, Size); + + // If the value of Step is non-negative and the AddRec is non-wrap, it + // reaches its maximum at the last iteration. So it's enouth to check + // whether End - Size is negative. + if (SE->isKnownNonNegative(Step) && SE->isKnownNegative(Diff1)) + return true; + + // If the value of Step is non-positive and the AddRec is non-wrap, the + // initial value is its maximum. + if (SE->isKnownNonPositive(Step) && SE->isKnownNegative(Diff0)) + return true; + + // Even if we don't know the sign of Step, either Start or End must be + // the maximum value of the AddRec since it is non-wrap. + if (SE->isKnownNegative(Diff0) && SE->isKnownNegative(Diff1)) + return true; + + return false; + }; + + if (CheckAddRecBECount()) + return true; + + // Check using normal isKnownNegative + const SCEV *LimitedBound = SE->getMinusSCEV(S, Size); + return SE->isKnownNegative(LimitedBound); +} + +bool llvm::validateDelinearizationResult(ScalarEvolution &SE, + ArrayRef Sizes, + ArrayRef Subscripts, + const Value *Ptr) { + for (size_t I = 1; I < Sizes.size(); ++I) { + const SCEV *Size = Sizes[I - 1]; + const SCEV *Subscript = Subscripts[I]; + if (!isKnownNonNegative(&SE, Subscript, Ptr)) + return false; + if (!isKnownLessThan(&SE, Subscript, Size)) + return false; + } + return true; +} + bool llvm::getIndexExpressionsFromGEP(ScalarEvolution &SE, const GetElementPtrInst *GEP, SmallVectorImpl &Subscripts, @@ -804,6 +906,11 @@ void printDelinearization(raw_ostream &O, Function *F, LoopInfo *LI, for (int i = 0; i < Size; i++) O << "[" << *Subscripts[i] << "]"; O << "\n"; + + bool IsValid = validateDelinearizationResult( + *SE, Sizes, Subscripts, getLoadStorePointerOperand(&Inst)); + O << "Delinearization validation: " << (IsValid ? "Succeeded" : "Failed") + << "\n"; } } diff --git a/llvm/lib/Analysis/DependenceAnalysis.cpp b/llvm/lib/Analysis/DependenceAnalysis.cpp index ea261820fb2e6..f366a5d592f30 100644 --- a/llvm/lib/Analysis/DependenceAnalysis.cpp +++ b/llvm/lib/Analysis/DependenceAnalysis.cpp @@ -1476,83 +1476,6 @@ bool DependenceInfo::isKnownPredicate(ICmpInst::Predicate Pred, const SCEV *X, } } -/// Compare to see if S is less than Size, using -/// -/// isKnownNegative(S - Size) -/// -/// with some extra checking if S is an AddRec and we can prove less-than using -/// the loop bounds. -bool DependenceInfo::isKnownLessThan(const SCEV *S, const SCEV *Size) const { - // First unify to the same type - auto *SType = dyn_cast(S->getType()); - auto *SizeType = dyn_cast(Size->getType()); - if (!SType || !SizeType) - return false; - Type *MaxType = - (SType->getBitWidth() >= SizeType->getBitWidth()) ? SType : SizeType; - S = SE->getTruncateOrZeroExtend(S, MaxType); - Size = SE->getTruncateOrZeroExtend(Size, MaxType); - - auto CheckAddRecBECount = [&]() { - const SCEVAddRecExpr *AddRec = dyn_cast(S); - if (!AddRec || !AddRec->isAffine() || !AddRec->hasNoSignedWrap()) - return false; - const SCEV *BECount = collectUpperBound(AddRec->getLoop(), MaxType); - // If the BTC cannot be computed, check the base case for S. - if (!BECount || isa(BECount)) - return false; - const SCEV *Start = AddRec->getStart(); - const SCEV *Step = AddRec->getStepRecurrence(*SE); - const SCEV *End = AddRec->evaluateAtIteration(BECount, *SE); - const SCEV *Diff0 = SE->getMinusSCEV(Start, Size); - const SCEV *Diff1 = SE->getMinusSCEV(End, Size); - - // If the value of Step is non-negative and the AddRec is non-wrap, it - // reaches its maximum at the last iteration. So it's enouth to check - // whether End - Size is negative. - if (SE->isKnownNonNegative(Step) && SE->isKnownNegative(Diff1)) - return true; - - // If the value of Step is non-positive and the AddRec is non-wrap, the - // initial value is its maximum. - if (SE->isKnownNonPositive(Step) && SE->isKnownNegative(Diff0)) - return true; - - // Even if we don't know the sign of Step, either Start or End must be - // the maximum value of the AddRec since it is non-wrap. - if (SE->isKnownNegative(Diff0) && SE->isKnownNegative(Diff1)) - return true; - - return false; - }; - - if (CheckAddRecBECount()) - return true; - - // Check using normal isKnownNegative - const SCEV *LimitedBound = SE->getMinusSCEV(S, Size); - return SE->isKnownNegative(LimitedBound); -} - -bool DependenceInfo::isKnownNonNegative(const SCEV *S, const Value *Ptr) const { - bool Inbounds = false; - if (auto *SrcGEP = dyn_cast(Ptr)) - Inbounds = SrcGEP->isInBounds(); - if (Inbounds) { - if (const SCEVAddRecExpr *AddRec = dyn_cast(S)) { - if (AddRec->isAffine()) { - // We know S is for Ptr, the operand on a load/store, so doesn't wrap. - // If both parts are NonNegative, the end result will be NonNegative - if (SE->isKnownNonNegative(AddRec->getStart()) && - SE->isKnownNonNegative(AddRec->getOperand(1))) - return true; - } - } - } - - return SE->isKnownNonNegative(S); -} - // All subscripts are all the same type. // Loop bound may be smaller (e.g., a char). // Should zero extend loop bound, since it's always >= 0. @@ -3788,35 +3711,8 @@ bool DependenceInfo::tryDelinearizeFixedSize( // iff the subscripts are positive and are less than the range of the // dimension. if (!DisableDelinearizationChecks) { - auto AllIndicesInRange = [&](ArrayRef DimensionSizes, - SmallVectorImpl &Subscripts, - Value *Ptr) { - size_t SSize = Subscripts.size(); - for (size_t I = 1; I < SSize; ++I) { - const SCEV *S = Subscripts[I]; - if (!isKnownNonNegative(S, Ptr)) { - LLVM_DEBUG({ - dbgs() << "Check failed: !isKnownNonNegative(S, Ptr)\n"; - dbgs() << " S: " << *S << "\n" << " Ptr: " << *Ptr << "\n"; - }); - return false; - } - const SCEV *Range = DimensionSizes[I - 1]; - if (!isKnownLessThan(S, Range)) { - LLVM_DEBUG({ - dbgs() << "Check failed: !isKnownLessThan(S, Range)\n"; - dbgs() << " S: " << *S << "\n" - << " Range: " << *Range << "\n"; - }); - return false; - } - } - return true; - }; - - if (!AllIndicesInRange(SrcSizes, SrcSubscripts, SrcPtr) || - !AllIndicesInRange(DstSizes, DstSubscripts, DstPtr)) { - LLVM_DEBUG(dbgs() << "Check failed: AllIndicesInRange.\n"); + if (!validateDelinearizationResult(*SE, SrcSizes, SrcSubscripts, SrcPtr) || + !validateDelinearizationResult(*SE, DstSizes, DstSubscripts, DstPtr)) { SrcSubscripts.clear(); DstSubscripts.clear(); return false; @@ -3874,8 +3770,6 @@ bool DependenceInfo::tryDelinearizeParametricSize( SrcSubscripts.size() != DstSubscripts.size()) return false; - size_t Size = SrcSubscripts.size(); - // Statically check that the array bounds are in-range. The first subscript we // don't have a size for and it cannot overflow into another subscript, so is // always safe. The others need to be 0 <= subscript[i] < bound, for both src @@ -3883,29 +3777,9 @@ bool DependenceInfo::tryDelinearizeParametricSize( // FIXME: It may be better to record these sizes and add them as constraints // to the dependency checks. if (!DisableDelinearizationChecks) - for (size_t I = 1; I < Size; ++I) { - bool SNN = isKnownNonNegative(SrcSubscripts[I], SrcPtr); - bool DNN = isKnownNonNegative(DstSubscripts[I], DstPtr); - bool SLT = isKnownLessThan(SrcSubscripts[I], Sizes[I - 1]); - bool DLT = isKnownLessThan(DstSubscripts[I], Sizes[I - 1]); - if (SNN && DNN && SLT && DLT) - continue; - - LLVM_DEBUG({ - dbgs() << "Delinearization checks failed: can't prove the following\n"; - if (!SNN) - dbgs() << " isKnownNonNegative(" << *SrcSubscripts[I] << ")\n"; - if (!DNN) - dbgs() << " isKnownNonNegative(" << *DstSubscripts[I] << ")\n"; - if (!SLT) - dbgs() << " isKnownLessThan(" << *SrcSubscripts[I] << ", " - << *Sizes[I - 1] << ")\n"; - if (!DLT) - dbgs() << " isKnownLessThan(" << *DstSubscripts[I] << ", " - << *Sizes[I - 1] << ")\n"; - }); + if (!validateDelinearizationResult(*SE, Sizes, SrcSubscripts, SrcPtr) || + !validateDelinearizationResult(*SE, Sizes, DstSubscripts, DstPtr)) return false; - } return true; } diff --git a/llvm/test/Analysis/Delinearization/a.ll b/llvm/test/Analysis/Delinearization/a.ll index 1830a3da77857..5d2d4dc29206e 100644 --- a/llvm/test/Analysis/Delinearization/a.ll +++ b/llvm/test/Analysis/Delinearization/a.ll @@ -15,6 +15,7 @@ define void @foo(i64 %n, i64 %m, i64 %o, ptr nocapture %A) #0 { ; CHECK-NEXT: Base offset: %A ; CHECK-NEXT: ArrayDecl[UnknownSize][%m][%o] with elements of 4 bytes. ; CHECK-NEXT: ArrayRef[{3,+,2}<%for.i>][{-4,+,3}<%for.j>][{7,+,5}<%for.k>] +; CHECK-NEXT: Delinearization validation: Failed ; entry: %cmp32 = icmp sgt i64 %n, 0 diff --git a/llvm/test/Analysis/Delinearization/constant_functions_multi_dim.ll b/llvm/test/Analysis/Delinearization/constant_functions_multi_dim.ll index 891d604f5cf13..9e6a4221f8eda 100644 --- a/llvm/test/Analysis/Delinearization/constant_functions_multi_dim.ll +++ b/llvm/test/Analysis/Delinearization/constant_functions_multi_dim.ll @@ -11,12 +11,14 @@ define void @mat_mul(ptr %C, ptr %A, ptr %B, i64 %N) !kernel_arg_addr_space !2 ! ; CHECK-NEXT: Base offset: %A ; CHECK-NEXT: ArrayDecl[UnknownSize][%N] with elements of 4 bytes. ; CHECK-NEXT: ArrayRef[%call][{0,+,1}<%for.inc>] +; CHECK-NEXT: Delinearization validation: Succeeded ; CHECK-EMPTY: ; CHECK-NEXT: Inst: %tmp5 = load float, ptr %arrayidx4, align 4 ; CHECK-NEXT: AccessFunction: {(4 * %call1),+,(4 * %N)}<%for.inc> ; CHECK-NEXT: Base offset: %B ; CHECK-NEXT: ArrayDecl[UnknownSize][%N] with elements of 4 bytes. ; CHECK-NEXT: ArrayRef[{0,+,1}<%for.inc>][%call1] +; CHECK-NEXT: Delinearization validation: Failed ; entry: br label %entry.split diff --git a/llvm/test/Analysis/Delinearization/divide_by_one.ll b/llvm/test/Analysis/Delinearization/divide_by_one.ll index e812e65ba7fd7..3d8e55984291e 100644 --- a/llvm/test/Analysis/Delinearization/divide_by_one.ll +++ b/llvm/test/Analysis/Delinearization/divide_by_one.ll @@ -18,12 +18,14 @@ define void @test(ptr nocapture %dst, i32 %stride, i32 %bs) { ; CHECK-NEXT: Base offset: %dst ; CHECK-NEXT: ArrayDecl[UnknownSize][%stride] with elements of 1 bytes. ; CHECK-NEXT: ArrayRef[{(1 + %bs),+,-1}<%for.cond1.preheader>][{-1,+,1}<%for.body3>] +; CHECK-NEXT: Delinearization validation: Failed ; CHECK-EMPTY: ; CHECK-NEXT: Inst: store i8 %0, ptr %arrayidx7, align 1 ; CHECK-NEXT: AccessFunction: {{\{\{}}(%stride * %bs),+,(-1 * %stride)}<%for.cond1.preheader>,+,1}<%for.body3> ; CHECK-NEXT: Base offset: %dst ; CHECK-NEXT: ArrayDecl[UnknownSize][%stride] with elements of 1 bytes. ; CHECK-NEXT: ArrayRef[{%bs,+,-1}<%for.cond1.preheader>][{0,+,1}<%for.body3>] +; CHECK-NEXT: Delinearization validation: Failed ; entry: %cmp20 = icmp sgt i32 %bs, -1 diff --git a/llvm/test/Analysis/Delinearization/fixed_size_array.ll b/llvm/test/Analysis/Delinearization/fixed_size_array.ll index cecd1eacb1437..250d46c81a25b 100644 --- a/llvm/test/Analysis/Delinearization/fixed_size_array.ll +++ b/llvm/test/Analysis/Delinearization/fixed_size_array.ll @@ -15,6 +15,7 @@ define void @a_i_j_k(ptr %a) { ; CHECK-NEXT: Base offset: %a ; CHECK-NEXT: ArrayDecl[UnknownSize][8][32] with elements of 4 bytes. ; CHECK-NEXT: ArrayRef[{0,+,1}<%for.i.header>][{0,+,1}<%for.j.header>][{0,+,1}<%for.k>] +; CHECK-NEXT: Delinearization validation: Succeeded ; entry: br label %for.i.header @@ -63,6 +64,7 @@ define void @a_i_nj_k(ptr %a) { ; CHECK-NEXT: Base offset: %a ; CHECK-NEXT: ArrayDecl[UnknownSize][8][32] with elements of 4 bytes. ; CHECK-NEXT: ArrayRef[{0,+,1}<%for.i.header>][{7,+,-1}<%for.j.header>][{0,+,1}<%for.k>] +; CHECK-NEXT: Delinearization validation: Succeeded ; entry: br label %for.i.header @@ -118,12 +120,14 @@ define void @a_ijk_b_i2jk(ptr %a, ptr %b) { ; CHECK-NEXT: Base offset: %a ; CHECK-NEXT: ArrayDecl[UnknownSize][4][64] with elements of 4 bytes. ; CHECK-NEXT: ArrayRef[{0,+,1}<%for.i.header>][{0,+,1}<%for.j.header>][{0,+,1}<%for.k>] +; CHECK-NEXT: Delinearization validation: Succeeded ; CHECK-EMPTY: ; CHECK-NEXT: Inst: store i32 1, ptr %b.idx, align 4 ; CHECK-NEXT: AccessFunction: {{\{\{\{}}0,+,1024}<%for.i.header>,+,256}<%for.j.header>,+,4}<%for.k> ; CHECK-NEXT: Base offset: %b ; CHECK-NEXT: ArrayDecl[UnknownSize][4][64] with elements of 4 bytes. ; CHECK-NEXT: ArrayRef[{0,+,1}<%for.i.header>][{0,+,1}<%for.j.header>][{0,+,1}<%for.k>] +; CHECK-NEXT: Delinearization validation: Succeeded ; entry: br label %for.i.header @@ -180,6 +184,7 @@ define void @a_i_2j1_k(ptr %a) { ; CHECK-NEXT: Base offset: %a ; CHECK-NEXT: ArrayDecl[UnknownSize][4][64] with elements of 4 bytes. ; CHECK-NEXT: ArrayRef[{0,+,1}<%for.i.header>][{0,+,1}<%for.j.header>][{32,+,1}<%for.k>] +; CHECK-NEXT: Delinearization validation: Succeeded ; entry: br label %for.i.header @@ -284,6 +289,7 @@ define void @a_i_j_3k(ptr %a) { ; CHECK-NEXT: Base offset: %a ; CHECK-NEXT: ArrayDecl[UnknownSize][8][32] with elements of 4 bytes. ; CHECK-NEXT: ArrayRef[{0,+,1}<%for.i.header>][{0,+,1}<%for.j.header>][{0,+,3}<%for.k>] +; CHECK-NEXT: Delinearization validation: Succeeded ; entry: br label %for.i.header @@ -386,6 +392,7 @@ define void @a_i_i_jk(ptr %a) { ; CHECK-NEXT: Base offset: %a ; CHECK-NEXT: ArrayDecl[UnknownSize][288] with elements of 4 bytes. ; CHECK-NEXT: ArrayRef[{0,+,1}<%for.i.header>][{{\{\{}}0,+,1}<%for.j.header>,+,1}<%for.k>] +; CHECK-NEXT: Delinearization validation: Succeeded ; entry: br label %for.i.header @@ -436,6 +443,7 @@ define void @a_i_jk_l(ptr %a) { ; CHECK-NEXT: Base offset: %a ; CHECK-NEXT: ArrayDecl[UnknownSize][8][32] with elements of 4 bytes. ; CHECK-NEXT: ArrayRef[{0,+,1}<%for.i.header>][{{\{\{}}0,+,1}<%for.j.header>,+,1}<%for.k.header>][{0,+,1}<%for.l>] +; CHECK-NEXT: Delinearization validation: Succeeded ; entry: br label %for.i.header diff --git a/llvm/test/Analysis/Delinearization/himeno_1.ll b/llvm/test/Analysis/Delinearization/himeno_1.ll index 5ae5d04505b8c..8655a257d8b74 100644 --- a/llvm/test/Analysis/Delinearization/himeno_1.ll +++ b/llvm/test/Analysis/Delinearization/himeno_1.ll @@ -36,6 +36,7 @@ define void @jacobi(i32 %nn, ptr nocapture %a, ptr nocapture %p) nounwind uwtabl ; CHECK-NEXT: Base offset: %a.base ; CHECK-NEXT: ArrayDecl[UnknownSize][(sext i32 %a.cols to i64)][(sext i32 %a.deps to i64)] with elements of 4 bytes. ; CHECK-NEXT: ArrayRef[{1,+,1}<%for.i>][{1,+,1}<%for.j>][{1,+,1}<%for.k>] +; CHECK-NEXT: Delinearization validation: Failed ; entry: %p.rows.ptr = getelementptr inbounds %struct.Mat, ptr %p, i64 0, i32 2 diff --git a/llvm/test/Analysis/Delinearization/himeno_2.ll b/llvm/test/Analysis/Delinearization/himeno_2.ll index 75e4f027c4c6c..21a445eeaf841 100644 --- a/llvm/test/Analysis/Delinearization/himeno_2.ll +++ b/llvm/test/Analysis/Delinearization/himeno_2.ll @@ -36,6 +36,7 @@ define void @jacobi(i32 %nn, ptr nocapture %a, ptr nocapture %p) nounwind uwtabl ; CHECK-NEXT: Base offset: %a.base ; CHECK-NEXT: ArrayDecl[UnknownSize][(sext i32 %a.cols to i64)][(sext i32 %a.deps to i64)] with elements of 4 bytes. ; CHECK-NEXT: ArrayRef[{1,+,1}<%for.i>][{1,+,1}<%for.j>][{1,+,1}<%for.k>] +; CHECK-NEXT: Delinearization validation: Failed ; entry: %p.rows.ptr = getelementptr inbounds %struct.Mat, ptr %p, i64 0, i32 2 diff --git a/llvm/test/Analysis/Delinearization/iv_times_constant_in_subscript.ll b/llvm/test/Analysis/Delinearization/iv_times_constant_in_subscript.ll index fc0a6c4e8b952..da993fc35ce7c 100644 --- a/llvm/test/Analysis/Delinearization/iv_times_constant_in_subscript.ll +++ b/llvm/test/Analysis/Delinearization/iv_times_constant_in_subscript.ll @@ -16,6 +16,7 @@ define void @foo(i64 %n, i64 %m, i64 %b, ptr %A) { ; CHECK-NEXT: Base offset: %A ; CHECK-NEXT: ArrayDecl[UnknownSize][%m] with elements of 8 bytes. ; CHECK-NEXT: ArrayRef[{%b,+,2}<%for.i>][{0,+,2}<%for.j>] +; CHECK-NEXT: Delinearization validation: Failed ; entry: br label %for.i diff --git a/llvm/test/Analysis/Delinearization/multidim_ivs_and_integer_offsets_3d.ll b/llvm/test/Analysis/Delinearization/multidim_ivs_and_integer_offsets_3d.ll index 0493a93dfee9d..c3d21de28fa65 100644 --- a/llvm/test/Analysis/Delinearization/multidim_ivs_and_integer_offsets_3d.ll +++ b/llvm/test/Analysis/Delinearization/multidim_ivs_and_integer_offsets_3d.ll @@ -16,6 +16,7 @@ define void @foo(i64 %n, i64 %m, i64 %o, ptr %A) { ; CHECK-NEXT: Base offset: %A ; CHECK-NEXT: ArrayDecl[UnknownSize][%m][%o] with elements of 8 bytes. ; CHECK-NEXT: ArrayRef[{3,+,1}<%for.i>][{-4,+,1}<%for.j>][{7,+,1}<%for.k>] +; CHECK-NEXT: Delinearization validation: Failed ; entry: br label %for.i diff --git a/llvm/test/Analysis/Delinearization/multidim_ivs_and_integer_offsets_nts_3d.ll b/llvm/test/Analysis/Delinearization/multidim_ivs_and_integer_offsets_nts_3d.ll index 2e9c3d77f3281..96ea88df56a9f 100644 --- a/llvm/test/Analysis/Delinearization/multidim_ivs_and_integer_offsets_nts_3d.ll +++ b/llvm/test/Analysis/Delinearization/multidim_ivs_and_integer_offsets_nts_3d.ll @@ -16,6 +16,7 @@ define void @foo(i64 %n, i64 %m, i64 %o, i64 %p, ptr nocapture %A) nounwind uwta ; CHECK-NEXT: Base offset: %A ; CHECK-NEXT: ArrayDecl[UnknownSize][%m][(%o + %p)] with elements of 8 bytes. ; CHECK-NEXT: ArrayRef[{3,+,1}<%for.cond4.preheader.lr.ph.us>][{-4,+,1}<%for.body6.lr.ph.us.us>][{7,+,1}<%for.body6.us.us>] +; CHECK-NEXT: Delinearization validation: Failed ; entry: %add = add nsw i64 %p, %o diff --git a/llvm/test/Analysis/Delinearization/multidim_ivs_and_parameteric_offsets_3d.ll b/llvm/test/Analysis/Delinearization/multidim_ivs_and_parameteric_offsets_3d.ll index a31192ef72f04..4d95e2f117e6a 100644 --- a/llvm/test/Analysis/Delinearization/multidim_ivs_and_parameteric_offsets_3d.ll +++ b/llvm/test/Analysis/Delinearization/multidim_ivs_and_parameteric_offsets_3d.ll @@ -16,6 +16,7 @@ define void @foo(i64 %n, i64 %m, i64 %o, ptr %A, i64 %p, i64 %q, i64 %r) { ; CHECK-NEXT: Base offset: %A ; CHECK-NEXT: ArrayDecl[UnknownSize][%m][%o] with elements of 8 bytes. ; CHECK-NEXT: ArrayRef[{%p,+,1}<%for.i>][{%q,+,1}<%for.j>][{%r,+,1}<%for.k>] +; CHECK-NEXT: Delinearization validation: Failed ; entry: br label %for.i diff --git a/llvm/test/Analysis/Delinearization/multidim_only_ivs_2d.ll b/llvm/test/Analysis/Delinearization/multidim_only_ivs_2d.ll index 432f7af7e0698..e1ad1c55313a4 100644 --- a/llvm/test/Analysis/Delinearization/multidim_only_ivs_2d.ll +++ b/llvm/test/Analysis/Delinearization/multidim_only_ivs_2d.ll @@ -16,12 +16,14 @@ define void @foo(i64 %n, i64 %m, ptr %A) { ; CHECK-NEXT: Base offset: %A ; CHECK-NEXT: ArrayDecl[UnknownSize][%m] with elements of 8 bytes. ; CHECK-NEXT: ArrayRef[{0,+,1}<%for.i>][{0,+,1}<%for.j>] +; CHECK-NEXT: Delinearization validation: Succeeded ; CHECK-EMPTY: ; CHECK-NEXT: Inst: store double %val, ptr %arrayidx, align 8 ; CHECK-NEXT: AccessFunction: {{\{\{}}0,+,(8 * %m)}<%for.i>,+,8}<%for.j> ; CHECK-NEXT: Base offset: %A ; CHECK-NEXT: ArrayDecl[UnknownSize][%m] with elements of 8 bytes. ; CHECK-NEXT: ArrayRef[{0,+,1}<%for.i>][{0,+,1}<%for.j>] +; CHECK-NEXT: Delinearization validation: Succeeded ; entry: br label %for.i diff --git a/llvm/test/Analysis/Delinearization/multidim_only_ivs_3d.ll b/llvm/test/Analysis/Delinearization/multidim_only_ivs_3d.ll index 966a8222d8a15..d5213e5afb33c 100644 --- a/llvm/test/Analysis/Delinearization/multidim_only_ivs_3d.ll +++ b/llvm/test/Analysis/Delinearization/multidim_only_ivs_3d.ll @@ -16,6 +16,7 @@ define void @foo(i64 %n, i64 %m, i64 %o, ptr %A) { ; CHECK-NEXT: Base offset: %A ; CHECK-NEXT: ArrayDecl[UnknownSize][%m][%o] with elements of 8 bytes. ; CHECK-NEXT: ArrayRef[{0,+,1}<%for.i>][{0,+,1}<%for.j>][{0,+,1}<%for.k>] +; CHECK-NEXT: Delinearization validation: Succeeded ; entry: br label %for.i diff --git a/llvm/test/Analysis/Delinearization/multidim_only_ivs_3d_cast.ll b/llvm/test/Analysis/Delinearization/multidim_only_ivs_3d_cast.ll index da40825984663..1dae34f785be4 100644 --- a/llvm/test/Analysis/Delinearization/multidim_only_ivs_3d_cast.ll +++ b/llvm/test/Analysis/Delinearization/multidim_only_ivs_3d_cast.ll @@ -18,6 +18,7 @@ define void @foo(i32 %n, i32 %m, i32 %o, ptr %A) { ; CHECK-NEXT: Base offset: %A ; CHECK-NEXT: ArrayDecl[UnknownSize][(zext i32 %m to i64)][(zext i32 %o to i64)] with elements of 8 bytes. ; CHECK-NEXT: ArrayRef[{0,+,1}<%for.i>][{0,+,1}<%for.j>][{0,+,1}<%for.k>] +; CHECK-NEXT: Delinearization validation: Failed ; entry: %m_zext = zext i32 %m to i64 diff --git a/llvm/test/Analysis/Delinearization/multidim_two_accesses_different_delinearization.ll b/llvm/test/Analysis/Delinearization/multidim_two_accesses_different_delinearization.ll index da77cd37fede5..011dc40697cb5 100644 --- a/llvm/test/Analysis/Delinearization/multidim_two_accesses_different_delinearization.ll +++ b/llvm/test/Analysis/Delinearization/multidim_two_accesses_different_delinearization.ll @@ -19,12 +19,14 @@ define void @foo(i64 %n, i64 %m, ptr %A) { ; CHECK-NEXT: Base offset: %A ; CHECK-NEXT: ArrayDecl[UnknownSize][%m] with elements of 8 bytes. ; CHECK-NEXT: ArrayRef[{0,+,1}<%for.i>][{0,+,1}<%for.j>] +; CHECK-NEXT: Delinearization validation: Succeeded ; CHECK-EMPTY: ; CHECK-NEXT: Inst: store double 1.000000e+00, ptr %arrayidx1, align 8 ; CHECK-NEXT: AccessFunction: {{\{\{}}0,+,8}<%for.i>,+,(8 * %n)}<%for.j> ; CHECK-NEXT: Base offset: %A ; CHECK-NEXT: ArrayDecl[UnknownSize][%n] with elements of 8 bytes. ; CHECK-NEXT: ArrayRef[{0,+,1}<%for.j>][{0,+,1}<%for.i>] +; CHECK-NEXT: Delinearization validation: Succeeded ; entry: br label %for.i diff --git a/llvm/test/Analysis/Delinearization/parameter_addrec_product.ll b/llvm/test/Analysis/Delinearization/parameter_addrec_product.ll index 49eeee3bd2119..4ef29701bdf49 100644 --- a/llvm/test/Analysis/Delinearization/parameter_addrec_product.ll +++ b/llvm/test/Analysis/Delinearization/parameter_addrec_product.ll @@ -19,12 +19,14 @@ define void @foo(ptr %A, ptr %p) { ; CHECK-NEXT: Base offset: %A ; CHECK-NEXT: ArrayDecl[UnknownSize][%pval] with elements of 4 bytes. ; CHECK-NEXT: ArrayRef[{0,+,1}<%bb2>][{0,+,1}<%bb4>] +; CHECK-NEXT: Delinearization validation: Failed ; CHECK-EMPTY: ; CHECK-NEXT: Inst: store float %tmp12, ptr %tmp10, align 4 ; CHECK-NEXT: AccessFunction: (4 * (({0,+,1}<%bb2> * %pval) + {0,+,1}<%bb4>)) ; CHECK-NEXT: Base offset: %A ; CHECK-NEXT: ArrayDecl[UnknownSize][%pval] with elements of 4 bytes. ; CHECK-NEXT: ArrayRef[{0,+,1}<%bb2>][{0,+,1}<%bb4>] +; CHECK-NEXT: Delinearization validation: Failed ; bb: br label %bb2 diff --git a/llvm/test/Analysis/Delinearization/terms_with_identity_factor.ll b/llvm/test/Analysis/Delinearization/terms_with_identity_factor.ll index 5b0465f7fb75e..323cce3dff05b 100644 --- a/llvm/test/Analysis/Delinearization/terms_with_identity_factor.ll +++ b/llvm/test/Analysis/Delinearization/terms_with_identity_factor.ll @@ -13,12 +13,14 @@ define void @foo(i32 %m, i32 %n, ptr nocapture %A) #0 { ; CHECK-NEXT: Base offset: %A ; CHECK-NEXT: ArrayDecl[UnknownSize][(sext i32 %n to i64)] with elements of 1 bytes. ; CHECK-NEXT: ArrayRef[{0,+,1}<%for.body3.lr.ph.us>][{0,+,1}<%for.body3.us>] +; CHECK-NEXT: Delinearization validation: Failed ; CHECK-EMPTY: ; CHECK-NEXT: Inst: store i8 %add4.us, ptr %arrayidx.us, align 1 ; CHECK-NEXT: AccessFunction: {{\{\{}}0,+,(sext i32 %n to i64)}<%for.body3.lr.ph.us>,+,1}<%for.body3.us> ; CHECK-NEXT: Base offset: %A ; CHECK-NEXT: ArrayDecl[UnknownSize][(sext i32 %n to i64)] with elements of 1 bytes. ; CHECK-NEXT: ArrayRef[{0,+,1}<%for.body3.lr.ph.us>][{0,+,1}<%for.body3.us>] +; CHECK-NEXT: Delinearization validation: Failed ; entry: br label %entry.split