[llvm] [DA][Delinearization] Move validation logic into Delinearization (PR #169047)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Nov 21 07:25:55 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-analysis
Author: Ryotaro Kasuga (kasuga-fj)
<details>
<summary>Changes</summary>
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.
---
Patch is 28.81 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/169047.diff
19 Files Affected:
- (modified) llvm/include/llvm/Analysis/Delinearization.h (+10)
- (modified) llvm/lib/Analysis/Delinearization.cpp (+107)
- (modified) llvm/lib/Analysis/DependenceAnalysis.cpp (+4-130)
- (modified) llvm/test/Analysis/Delinearization/a.ll (+1)
- (modified) llvm/test/Analysis/Delinearization/constant_functions_multi_dim.ll (+2)
- (modified) llvm/test/Analysis/Delinearization/divide_by_one.ll (+2)
- (modified) llvm/test/Analysis/Delinearization/fixed_size_array.ll (+8)
- (modified) llvm/test/Analysis/Delinearization/himeno_1.ll (+1)
- (modified) llvm/test/Analysis/Delinearization/himeno_2.ll (+1)
- (modified) llvm/test/Analysis/Delinearization/iv_times_constant_in_subscript.ll (+1)
- (modified) llvm/test/Analysis/Delinearization/multidim_ivs_and_integer_offsets_3d.ll (+1)
- (modified) llvm/test/Analysis/Delinearization/multidim_ivs_and_integer_offsets_nts_3d.ll (+1)
- (modified) llvm/test/Analysis/Delinearization/multidim_ivs_and_parameteric_offsets_3d.ll (+1)
- (modified) llvm/test/Analysis/Delinearization/multidim_only_ivs_2d.ll (+2)
- (modified) llvm/test/Analysis/Delinearization/multidim_only_ivs_3d.ll (+1)
- (modified) llvm/test/Analysis/Delinearization/multidim_only_ivs_3d_cast.ll (+1)
- (modified) llvm/test/Analysis/Delinearization/multidim_two_accesses_different_delinearization.ll (+2)
- (modified) llvm/test/Analysis/Delinearization/parameter_addrec_product.ll (+2)
- (modified) llvm/test/Analysis/Delinearization/terms_with_identity_factor.ll (+2)
``````````diff
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<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 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<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,
@@ -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<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.
@@ -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<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;
@@ -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}<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)] wi...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/169047
More information about the llvm-commits
mailing list