[llvm] 7f1423e - [DA][Delinearization] Move validation logic into Delinearization (#169047)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Nov 27 07:06:39 PST 2025
Author: Ryotaro Kasuga
Date: 2025-11-27T15:06:35Z
New Revision: 7f1423e58ac894e7225625f34d90806ce5f052b3
URL: https://github.com/llvm/llvm-project/commit/7f1423e58ac894e7225625f34d90806ce5f052b3
DIFF: https://github.com/llvm/llvm-project/commit/7f1423e58ac894e7225625f34d90806ce5f052b3.diff
LOG: [DA][Delinearization] Move validation logic into Delinearization (#169047)
This patch moves the validation logic of delinearization results from DA
to Delinearization. Also call it in `printDelinearization` to test its
behavior. The motivation is as follows:
- Almost the same code exists in `tryDelinearizeFixedSize` and
`tryDelinearizeParametricSize`. Consolidating it in Delinearization
avoids code duplication.
- Currently this validation logic is not well tested. Moving it to
Delinearization allows us to write regression tests easily.
This patch changes the test outputs and debug messages, but otherwise
NFCI.
Added:
Modified:
llvm/include/llvm/Analysis/Delinearization.h
llvm/lib/Analysis/Delinearization.cpp
llvm/lib/Analysis/DependenceAnalysis.cpp
llvm/test/Analysis/Delinearization/a.ll
llvm/test/Analysis/Delinearization/constant_functions_multi_dim.ll
llvm/test/Analysis/Delinearization/divide_by_one.ll
llvm/test/Analysis/Delinearization/fixed_size_array.ll
llvm/test/Analysis/Delinearization/himeno_1.ll
llvm/test/Analysis/Delinearization/himeno_2.ll
llvm/test/Analysis/Delinearization/iv_times_constant_in_subscript.ll
llvm/test/Analysis/Delinearization/multidim_ivs_and_integer_offsets_3d.ll
llvm/test/Analysis/Delinearization/multidim_ivs_and_integer_offsets_nts_3d.ll
llvm/test/Analysis/Delinearization/multidim_ivs_and_parameteric_offsets_3d.ll
llvm/test/Analysis/Delinearization/multidim_only_ivs_2d.ll
llvm/test/Analysis/Delinearization/multidim_only_ivs_3d.ll
llvm/test/Analysis/Delinearization/multidim_only_ivs_3d_cast.ll
llvm/test/Analysis/Delinearization/multidim_two_accesses_different_delinearization.ll
llvm/test/Analysis/Delinearization/parameter_addrec_product.ll
llvm/test/Analysis/Delinearization/terms_with_identity_factor.ll
Removed:
################################################################################
diff --git a/llvm/include/llvm/Analysis/Delinearization.h b/llvm/include/llvm/Analysis/Delinearization.h
index e2be91ba84c53..b9fc0bcf47430 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;
@@ -140,6 +141,15 @@ bool delinearizeFixedSizeArray(ScalarEvolution &SE, const SCEV *Expr,
SmallVectorImpl<const SCEV *> &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<const SCEV *> Sizes,
+ ArrayRef<const SCEV *> 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 8a8c2277012ec..0c3b02ae09f47 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<GetElementPtrInst>(Ptr))
+ Inbounds = SrcGEP->isInBounds();
+ if (Inbounds) {
+ if (const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(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<IntegerType>(S->getType());
+ auto *SizeType = dyn_cast<IntegerType>(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<SCEVAddRecExpr>(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<SCEVCouldNotCompute>(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<const SCEV *> Sizes,
+ ArrayRef<const SCEV *> 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<const SCEV *> &Subscripts,
@@ -766,6 +868,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 b0398fe7e93b3..77b09fb15316e 100644
--- a/llvm/lib/Analysis/DependenceAnalysis.cpp
+++ b/llvm/lib/Analysis/DependenceAnalysis.cpp
@@ -1176,83 +1176,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<IntegerType>(S->getType());
- auto *SizeType = dyn_cast<IntegerType>(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<SCEVAddRecExpr>(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<SCEVCouldNotCompute>(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<GetElementPtrInst>(Ptr))
- Inbounds = SrcGEP->isInBounds();
- if (Inbounds) {
- if (const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(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.
@@ -3360,35 +3283,8 @@ bool DependenceInfo::tryDelinearizeFixedSize(
// iff the subscripts are positive and are less than the range of the
// dimension.
if (!DisableDelinearizationChecks) {
- auto AllIndicesInRange = [&](ArrayRef<const SCEV *> DimensionSizes,
- SmallVectorImpl<const SCEV *> &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;
@@ -3446,8 +3342,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
@@ -3455,29 +3349,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}<nuw><%for.i>][{-4,+,3}<nw><%for.j>][{7,+,5}<nw><%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}<nuw><nsw><%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}<nuw><nsw><%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}<nw><%for.cond1.preheader>][{-1,+,1}<nw><%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}<nsw><%for.body3>
; CHECK-NEXT: Base offset: %dst
; CHECK-NEXT: ArrayDecl[UnknownSize][%stride] with elements of 1 bytes.
; CHECK-NEXT: ArrayRef[{%bs,+,-1}<nsw><%for.cond1.preheader>][{0,+,1}<nuw><nsw><%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}<nuw><nsw><%for.i.header>][{0,+,1}<nuw><nsw><%for.j.header>][{0,+,1}<nuw><nsw><%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}<nuw><nsw><%for.i.header>][{7,+,-1}<nsw><%for.j.header>][{0,+,1}<nuw><nsw><%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}<nuw><nsw><%for.i.header>][{0,+,1}<nuw><nsw><%for.j.header>][{0,+,1}<nuw><nsw><%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}<nuw><nsw><%for.i.header>,+,256}<nw><%for.j.header>,+,4}<nw><%for.k>
; CHECK-NEXT: Base offset: %b
; CHECK-NEXT: ArrayDecl[UnknownSize][4][64] with elements of 4 bytes.
; CHECK-NEXT: ArrayRef[{0,+,1}<nuw><nsw><%for.i.header>][{0,+,1}<nuw><nsw><%for.j.header>][{0,+,1}<nuw><nsw><%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}<nuw><nsw><%for.i.header>][{0,+,1}<nuw><%for.j.header>][{32,+,1}<nw><%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}<nuw><nsw><%for.i.header>][{0,+,1}<nuw><nsw><%for.j.header>][{0,+,3}<nuw><nsw><%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}<nuw><nsw><%for.i.header>][{{\{\{}}0,+,1}<nuw><nsw><%for.j.header>,+,1}<nuw><nsw><%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}<nuw><nsw><%for.i.header>][{{\{\{}}0,+,1}<nuw><nsw><%for.j.header>,+,1}<nuw><nsw><%for.k.header>][{0,+,1}<nuw><nsw><%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}<nuw><nsw><%for.i>][{1,+,1}<nuw><nsw><%for.j>][{1,+,1}<nuw><nsw><%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}<nuw><nsw><%for.i>][{1,+,1}<nuw><nsw><%for.j>][{1,+,1}<nuw><nsw><%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}<nsw><%for.i>][{0,+,2}<nuw><%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}<nuw><%for.i>][{-4,+,1}<nsw><%for.j>][{7,+,1}<nuw><nsw><%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}<nuw><%for.cond4.preheader.lr.ph.us>][{-4,+,1}<nw><%for.body6.lr.ph.us.us>][{7,+,1}<nw><%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}<nw><%for.i>][{%q,+,1}<nsw><%for.j>][{%r,+,1}<nsw><%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}<nuw><nsw><%for.i>][{0,+,1}<nuw><nsw><%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}<nuw><nsw><%for.i>][{0,+,1}<nuw><nsw><%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}<nuw><nsw><%for.i>][{0,+,1}<nuw><nsw><%for.j>][{0,+,1}<nuw><nsw><%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}<nuw><nsw><%for.i>][{0,+,1}<nuw><nsw><%for.j>][{0,+,1}<nuw><nsw><%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_
diff erent_delinearization.ll b/llvm/test/Analysis/Delinearization/multidim_two_accesses_
diff erent_delinearization.ll
index da77cd37fede5..011dc40697cb5 100644
--- a/llvm/test/Analysis/Delinearization/multidim_two_accesses_
diff erent_delinearization.ll
+++ b/llvm/test/Analysis/Delinearization/multidim_two_accesses_
diff erent_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}<nuw><nsw><%for.i>][{0,+,1}<nuw><nsw><%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}<nuw><nsw><%for.j>][{0,+,1}<nuw><nsw><%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}<nuw><nsw><%bb2>][{0,+,1}<nuw><nsw><%bb4>]
+; CHECK-NEXT: Delinearization validation: Failed
; CHECK-EMPTY:
; CHECK-NEXT: Inst: store float %tmp12, ptr %tmp10, align 4
; CHECK-NEXT: AccessFunction: (4 * (({0,+,1}<nuw><nsw><%bb2> * %pval)<nsw> + {0,+,1}<nuw><nsw><%bb4>)<nsw>)<nsw>
; CHECK-NEXT: Base offset: %A
; CHECK-NEXT: ArrayDecl[UnknownSize][%pval] with elements of 4 bytes.
; CHECK-NEXT: ArrayRef[{0,+,1}<nuw><nsw><%bb2>][{0,+,1}<nuw><nsw><%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}<nuw><nsw><%for.body3.lr.ph.us>][{0,+,1}<nuw><nsw><%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)}<nsw><%for.body3.lr.ph.us>,+,1}<nsw><%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}<nuw><nsw><%for.body3.lr.ph.us>][{0,+,1}<nuw><nsw><%for.body3.us>]
+; CHECK-NEXT: Delinearization validation: Failed
;
entry:
br label %entry.split
More information about the llvm-commits
mailing list