Skip to content

Conversation

@sebpop
Copy link
Contributor

@sebpop sebpop commented Aug 15, 2025

In this patch:

  1. Adapt the output of printDelinearization() to match what the script expects to see, "Printing analysis 'Delinearization' for function".
  2. Register the "Delinearization" pass in the update script,
  3. Automatically remove the existing CHECK statements
  4. Update the tests with a run of:
$ ~/llvm-project/llvm/utils/update_analyze_test_checks.py --opt=~/llvm-project/build/bin/opt ~/llvm-project/llvm/test/Analysis/Delinearization/*.ll
  1. Drop llvm/test/Analysis/Delinearization/undef.ll because the test does not pass the github-actions "undef deprecator."
  2. Only run delinearization pretty-print pass on the most internal loop.
  3. Only run delinearization pretty-print pass on load and store instructions.

@llvmbot llvmbot added testing-tools llvm:analysis Includes value tracking, cost tables and constant folding labels Aug 15, 2025
@llvmbot
Copy link
Member

llvmbot commented Aug 15, 2025

@llvm/pr-subscribers-testing-tools

Author: Sebastian Pop (sebpop)

Changes

After adapting the output of printDelinearization() to match what the script expects to see, "Printing analysis 'Delinearization' for function", the rest of the patch is the automatic run of:

$ /llvm-project/llvm/utils/update_analyze_test_checks.py --opt=/llvm-project/build/bin/opt ~/llvm-project/llvm/test/Analysis/Delinearization/*.ll


Patch is 107.43 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/153831.diff

23 Files Affected:

  • (modified) llvm/lib/Analysis/Delinearization.cpp (+2-1)
  • (modified) llvm/test/Analysis/Delinearization/a.ll (+38-5)
  • (modified) llvm/test/Analysis/Delinearization/byte_offset.ll (+12-3)
  • (modified) llvm/test/Analysis/Delinearization/constant_functions_multi_dim.ll (+27-15)
  • (modified) llvm/test/Analysis/Delinearization/divide_by_one.ll (+50-12)
  • (modified) llvm/test/Analysis/Delinearization/fixed_size_array.ll (+409-41)
  • (modified) llvm/test/Analysis/Delinearization/gcd_multiply_expr.ll (+368-1)
  • (modified) llvm/test/Analysis/Delinearization/himeno_1.ll (+38-5)
  • (modified) llvm/test/Analysis/Delinearization/himeno_2.ll (+38-5)
  • (modified) llvm/test/Analysis/Delinearization/iv_times_constant_in_subscript.ll (+26-6)
  • (modified) llvm/test/Analysis/Delinearization/multidim_ivs_and_integer_offsets_3d.ll (+38-5)
  • (modified) llvm/test/Analysis/Delinearization/multidim_ivs_and_integer_offsets_nts_3d.ll (+38-5)
  • (modified) llvm/test/Analysis/Delinearization/multidim_ivs_and_parameteric_offsets_3d.ll (+38-5)
  • (modified) llvm/test/Analysis/Delinearization/multidim_only_ivs_2d.ll (+40-14)
  • (modified) llvm/test/Analysis/Delinearization/multidim_only_ivs_2d_nested.ll (+44-6)
  • (modified) llvm/test/Analysis/Delinearization/multidim_only_ivs_3d.ll (+38-5)
  • (modified) llvm/test/Analysis/Delinearization/multidim_only_ivs_3d_cast.ll (+38-5)
  • (modified) llvm/test/Analysis/Delinearization/multidim_two_accesses_different_delinearization.ll (+49-1)
  • (modified) llvm/test/Analysis/Delinearization/parameter_addrec_product.ll (+50-4)
  • (modified) llvm/test/Analysis/Delinearization/terms_with_identity_factor.ll (+154-11)
  • (modified) llvm/test/Analysis/Delinearization/type_mismatch.ll (+18-1)
  • (modified) llvm/test/Analysis/Delinearization/undef.ll (+33-1)
  • (modified) llvm/utils/UpdateTestChecks/common.py (+1)
diff --git a/llvm/lib/Analysis/Delinearization.cpp b/llvm/lib/Analysis/Delinearization.cpp
index 761c566eae794..3481e572c43e6 100644
--- a/llvm/lib/Analysis/Delinearization.cpp
+++ b/llvm/lib/Analysis/Delinearization.cpp
@@ -744,7 +744,8 @@ namespace {
 
 void printDelinearization(raw_ostream &O, Function *F, LoopInfo *LI,
                           ScalarEvolution *SE) {
-  O << "Delinearization on function " << F->getName() << ":\n";
+  O << "Printing analysis 'Delinearization' for function '" << F->getName()
+    << "':";
   for (Instruction &Inst : instructions(F)) {
     // Only analyze loads and stores.
     if (!isa<StoreInst>(&Inst) && !isa<LoadInst>(&Inst) &&
diff --git a/llvm/test/Analysis/Delinearization/a.ll b/llvm/test/Analysis/Delinearization/a.ll
index 02ba3fde695c3..fd96e778ea1bf 100644
--- a/llvm/test/Analysis/Delinearization/a.ll
+++ b/llvm/test/Analysis/Delinearization/a.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5
 ; RUN: opt < %s -passes='print<delinearization>' -disable-output 2>&1 | FileCheck %s
 ;
 ; void foo(long n, long m, long o, int A[n][m][o]) {
@@ -7,12 +8,44 @@
 ;         A[2*i+3][3*j-4][5*k+7] = 1;
 ; }
 
-; AddRec: {{{(28 + (4 * (-4 + (3 * %m)) * %o) + %A),+,(8 * %m * %o)}<%for.i>,+,(12 * %o)}<%for.j>,+,20}<%for.k>
-; CHECK: Base offset: %A
-; CHECK: ArrayDecl[UnknownSize][%m][%o] with elements of 4 bytes.
-; CHECK: ArrayRef[{3,+,2}<nuw><%for.i>][{-4,+,3}<nw><%for.j>][{7,+,5}<nw><%for.k>]
-
 define void @foo(i64 %n, i64 %m, i64 %o, ptr nocapture %A) #0 {
+; CHECK-LABEL: 'foo'
+; CHECK-NEXT:  Inst: %arrayidx11.us.us = getelementptr inbounds i32, ptr %A, i64 %arrayidx10.sum.us.us
+; CHECK-NEXT:  In Loop with Header: for.k
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %arrayidx11.us.us = getelementptr inbounds i32, ptr %A, i64 %arrayidx10.sum.us.us
+; CHECK-NEXT:  In Loop with Header: for.j
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %arrayidx11.us.us = getelementptr inbounds i32, ptr %A, i64 %arrayidx10.sum.us.us
+; CHECK-NEXT:  In Loop with Header: for.i
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: store i32 1, ptr %arrayidx11.us.us, align 4
+; CHECK-NEXT:  In Loop with Header: for.k
+; CHECK-NEXT:  AccessFunction: {{\{\{\{}}(28 + (4 * (-4 + (3 * %m)) * %o)),+,(8 * %m * %o)}<%for.i>,+,(12 * %o)}<%for.j>,+,20}<%for.k>
+; 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-EMPTY:
+; CHECK-NEXT:  Inst: store i32 1, ptr %arrayidx11.us.us, align 4
+; CHECK-NEXT:  In Loop with Header: for.j
+; CHECK-NEXT:  AccessFunction: {{\{\{}}(8 + ((4 + (12 * %m)) * %o)),+,(8 * %m * %o)}<%for.i>,+,(12 * %o)}<%for.j>
+; CHECK-NEXT:  Base offset: %A
+; CHECK-NEXT:  ArrayDecl[UnknownSize][%m][%o] with elements of 4 bytes.
+; CHECK-NEXT:  ArrayRef[{3,+,2}<nuw><%for.i>][{1,+,3}<%for.j>][2]
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: store i32 1, ptr %arrayidx11.us.us, align 4
+; CHECK-NEXT:  In Loop with Header: for.i
+; CHECK-NEXT:  AccessFunction: {(8 + ((-8 + (24 * %m)) * %o)),+,(8 * %m * %o)}<%for.i>
+; CHECK-NEXT:  Base offset: %A
+; CHECK-NEXT:  ArrayDecl[UnknownSize][(%m * %o)] with elements of 4 bytes.
+; CHECK-NEXT:  ArrayRef[0][{(2 + ((-2 + (6 * %m)) * %o)),+,(2 * %m * %o)}<%for.i>]
+;
 entry:
   %cmp32 = icmp sgt i64 %n, 0
   br i1 %cmp32, label %for.cond1.preheader.lr.ph, label %for.end17
diff --git a/llvm/test/Analysis/Delinearization/byte_offset.ll b/llvm/test/Analysis/Delinearization/byte_offset.ll
index 6534d3ea6c05b..04b0dcd2ee1d8 100644
--- a/llvm/test/Analysis/Delinearization/byte_offset.ll
+++ b/llvm/test/Analysis/Delinearization/byte_offset.ll
@@ -1,8 +1,6 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5
 ; RUN: opt < %s -passes='print<delinearization>' -disable-output 2>&1 | FileCheck %s
 
-; CHECK: AccessFunction: ({0,+,%i2}<%outer.loop> + %unknown)
-; CHECK-NEXT: failed to delinearize
-
 ; void foo(char A[], long i2, bool c) {
 ;   for (long i = 0; ; ++i) {
 ;     char *tmp = &A[i * i2];
@@ -13,6 +11,17 @@
 ; }
 
 define void @foo(ptr %A, i64 %i2, i64 %arg, i1 %c) {
+; CHECK-LABEL: 'foo'
+; CHECK-NEXT:  Inst: %tmp = getelementptr inbounds i8, ptr %A, i64 %i414
+; CHECK-NEXT:  In Loop with Header: outer.loop
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: store float 0.000000e+00, ptr %arrayidx, align 4
+; CHECK-NEXT:  In Loop with Header: inner.loop
+; CHECK-NEXT:  AccessFunction: ({0,+,%i2}<%outer.loop> + %unknown)
+; CHECK-NEXT:  failed to delinearize
+;
 entry:
   br label %outer.loop
 
diff --git a/llvm/test/Analysis/Delinearization/constant_functions_multi_dim.ll b/llvm/test/Analysis/Delinearization/constant_functions_multi_dim.ll
index 3044a4868260b..0ea499fc55352 100644
--- a/llvm/test/Analysis/Delinearization/constant_functions_multi_dim.ll
+++ b/llvm/test/Analysis/Delinearization/constant_functions_multi_dim.ll
@@ -1,23 +1,35 @@
-; RUN: opt -passes='print<delinearization>' -disable-output < %s 2>&1 | FileCheck %s
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -passes='print<delinearization>' -disable-output 2>&1 | FileCheck %s
 
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 
-; CHECK:      Inst:  %tmp = load float, ptr %arrayidx, align 4
-; CHECK-NEXT: In Loop with Header: for.inc
-; CHECK-NEXT: AccessFunction: {(4 * %N * %call),+,4}<%for.inc>
-; 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:      Inst:  %tmp5 = load float, ptr %arrayidx4, align 4
-; CHECK-NEXT: In Loop with Header: for.inc
-; 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]
-
 ; Function Attrs: noinline nounwind uwtable
 define void @mat_mul(ptr %C, ptr %A, ptr %B, i64 %N) #0 !kernel_arg_addr_space !2 !kernel_arg_access_qual !3 !kernel_arg_type !4 !kernel_arg_base_type !4 !kernel_arg_type_qual !5 {
+; CHECK-LABEL: 'mat_mul'
+; CHECK-NEXT:  Inst: %arrayidx = getelementptr inbounds float, ptr %A, i64 %add
+; CHECK-NEXT:  In Loop with Header: for.inc
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %tmp = load float, ptr %arrayidx, align 4
+; CHECK-NEXT:  In Loop with Header: for.inc
+; CHECK-NEXT:  AccessFunction: {(4 * %N * %call),+,4}<%for.inc>
+; 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-EMPTY:
+; CHECK-NEXT:  Inst: %arrayidx4 = getelementptr inbounds float, ptr %B, i64 %add3
+; CHECK-NEXT:  In Loop with Header: for.inc
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %tmp5 = load float, ptr %arrayidx4, align 4
+; CHECK-NEXT:  In Loop with Header: for.inc
+; 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]
+;
 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 8c531b78f2bcf..ff5f178d5a88b 100644
--- a/llvm/test/Analysis/Delinearization/divide_by_one.ll
+++ b/llvm/test/Analysis/Delinearization/divide_by_one.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5
 ; RUN: opt < %s -passes='print<delinearization>' -disable-output 2>&1 | FileCheck %s
 
 target datalayout = "e-m:e-p:32:32-i1:32-i64:64-a:0-n32"
@@ -10,19 +11,56 @@ target datalayout = "e-m:e-p:32:32-i1:32-i64:64-a:0-n32"
 ;       dst[r * stride + c] = dst[(r + 1) * stride + c - 1];
 ; }
 
-; AddRec: {{(-1 + ((1 + %bs) * %stride)),+,(-1 * %stride)}<%for.cond1.preheader>,+,1}<nw><%for.body3>
-; CHECK: Inst:  %0 = load i8, ptr %arrayidx, align 1
-; CHECK: Base offset: %dst
-; CHECK: ArrayDecl[UnknownSize][%stride] with elements of 1 bytes.
-; CHECK: ArrayRef[{(1 + %bs),+,-1}<nw><%for.cond1.preheader>][{-1,+,1}<nw><%for.body3>]
-
-; AddRec: {{(ptr %bs),+,(-1 * %stride)}<%for.cond1.preheader>,+,1}<nw><%for.body3>
-; CHECK: Inst:  store i8 %0, ptr %arrayidx7, align 1
-; CHECK: Base offset: %dst
-; CHECK: ArrayDecl[UnknownSize][%stride] with elements of 1 bytes.
-; CHECK: ArrayRef[{%bs,+,-1}<nsw><%for.cond1.preheader>][{0,+,1}<nuw><nsw><%for.body3>]
-
 define void @test(ptr nocapture %dst, i32 %stride, i32 %bs) {
+; CHECK-LABEL: 'test'
+; CHECK-NEXT:  Inst: %arrayidx = getelementptr inbounds i8, ptr %dst, i32 %sub
+; CHECK-NEXT:  In Loop with Header: for.body3
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %arrayidx = getelementptr inbounds i8, ptr %dst, i32 %sub
+; CHECK-NEXT:  In Loop with Header: for.cond1.preheader
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %0 = load i8, ptr %arrayidx, align 1
+; CHECK-NEXT:  In Loop with Header: for.body3
+; CHECK-NEXT:  AccessFunction: {{\{\{}}(-1 + ((1 + %bs) * %stride)),+,(-1 * %stride)}<%for.cond1.preheader>,+,1}<nw><%for.body3>
+; 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-EMPTY:
+; CHECK-NEXT:  Inst: %0 = load i8, ptr %arrayidx, align 1
+; CHECK-NEXT:  In Loop with Header: for.cond1.preheader
+; CHECK-NEXT:  AccessFunction: {(-2 + ((1 + %bs) * %stride) + %bs),+,(-1 * %stride)}<%for.cond1.preheader>
+; 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>][(-2 + %bs)]
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %arrayidx7 = getelementptr inbounds i8, ptr %dst, i32 %add6
+; CHECK-NEXT:  In Loop with Header: for.body3
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %arrayidx7 = getelementptr inbounds i8, ptr %dst, i32 %add6
+; CHECK-NEXT:  In Loop with Header: for.cond1.preheader
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: store i8 %0, ptr %arrayidx7, align 1
+; CHECK-NEXT:  In Loop with Header: for.body3
+; 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-EMPTY:
+; CHECK-NEXT:  Inst: store i8 %0, ptr %arrayidx7, align 1
+; CHECK-NEXT:  In Loop with Header: for.cond1.preheader
+; CHECK-NEXT:  AccessFunction: {(-1 + ((1 + %stride) * %bs)),+,(-1 * %stride)}<%for.cond1.preheader>
+; CHECK-NEXT:  Base offset: %dst
+; CHECK-NEXT:  ArrayDecl[UnknownSize][%stride] with elements of 1 bytes.
+; CHECK-NEXT:  ArrayRef[{%bs,+,-1}<nsw><%for.cond1.preheader>][(-1 + %bs)]
+;
 entry:
   %cmp20 = icmp sgt i32 %bs, -1
   br i1 %cmp20, label %for.cond1.preheader.lr.ph, label %for.end9
diff --git a/llvm/test/Analysis/Delinearization/fixed_size_array.ll b/llvm/test/Analysis/Delinearization/fixed_size_array.ll
index 0512044990163..d22d9b106e53a 100644
--- a/llvm/test/Analysis/Delinearization/fixed_size_array.ll
+++ b/llvm/test/Analysis/Delinearization/fixed_size_array.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5
 ; RUN: opt < %s -passes='print<delinearization>' -disable-output -delinearize-use-fixed-size-array-heuristic 2>&1 | FileCheck %s
 
 ; void f(int A[][8][32]) {
@@ -7,11 +8,44 @@
 ;       A[i][j][k] = 1;
 ; }
 
-; CHECK:      Delinearization on function a_i_j_k:
-; CHECK:      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>]
 define void @a_i_j_k(ptr %a) {
+; CHECK-LABEL: 'a_i_j_k'
+; CHECK-NEXT:  Inst: %idx = getelementptr [8 x [32 x i32]], ptr %a, i32 %i, i32 %j, i32 %k
+; CHECK-NEXT:  In Loop with Header: for.k
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %idx = getelementptr [8 x [32 x i32]], ptr %a, i32 %i, i32 %j, i32 %k
+; CHECK-NEXT:  In Loop with Header: for.j.header
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %idx = getelementptr [8 x [32 x i32]], ptr %a, i32 %i, i32 %j, i32 %k
+; CHECK-NEXT:  In Loop with Header: for.i.header
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: store i32 1, ptr %idx, align 4
+; CHECK-NEXT:  In Loop with Header: for.k
+; CHECK-NEXT:  AccessFunction: {{\{\{\{}}0,+,1024}<nuw><nsw><%for.i.header>,+,128}<nw><%for.j.header>,+,4}<nw><%for.k>
+; 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-EMPTY:
+; CHECK-NEXT:  Inst: store i32 1, ptr %idx, align 4
+; CHECK-NEXT:  In Loop with Header: for.j.header
+; CHECK-NEXT:  AccessFunction: {{\{\{}}124,+,1024}<%for.i.header>,+,128}<%for.j.header>
+; CHECK-NEXT:  Base offset: %a
+; CHECK-NEXT:  ArrayDecl[UnknownSize][256] with elements of 4 bytes.
+; CHECK-NEXT:  ArrayRef[{0,+,1}<nuw><nsw><%for.i.header>][{31,+,32}<%for.j.header>]
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: store i32 1, ptr %idx, align 4
+; CHECK-NEXT:  In Loop with Header: for.i.header
+; CHECK-NEXT:  AccessFunction: {1020,+,1024}<%for.i.header>
+; CHECK-NEXT:  Base offset: %a
+; CHECK-NEXT:  ArrayDecl[UnknownSize] with elements of 4 bytes.
+; CHECK-NEXT:  ArrayRef[{255,+,256}<%for.i.header>]
+;
 entry:
   br label %for.i.header
 
@@ -52,11 +86,44 @@ exit:
 ;       A[i][7-j][k] = 1;
 ; }
 
-; CHECK:      Delinearization on function a_i_nj_k:
-; CHECK:      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>]
 define void @a_i_nj_k(ptr %a) {
+; CHECK-LABEL: 'a_i_nj_k'
+; CHECK-NEXT:  Inst: %idx = getelementptr [8 x [32 x i32]], ptr %a, i32 %i, i32 %j.subscript, i32 %k
+; CHECK-NEXT:  In Loop with Header: for.k
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %idx = getelementptr [8 x [32 x i32]], ptr %a, i32 %i, i32 %j.subscript, i32 %k
+; CHECK-NEXT:  In Loop with Header: for.j.header
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %idx = getelementptr [8 x [32 x i32]], ptr %a, i32 %i, i32 %j.subscript, i32 %k
+; CHECK-NEXT:  In Loop with Header: for.i.header
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: store i32 1, ptr %idx, align 4
+; CHECK-NEXT:  In Loop with Header: for.k
+; CHECK-NEXT:  AccessFunction: {{\{\{\{}}896,+,1024}<nuw><nsw><%for.i.header>,+,-128}<nw><%for.j.header>,+,4}<nw><%for.k>
+; 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-EMPTY:
+; CHECK-NEXT:  Inst: store i32 1, ptr %idx, align 4
+; CHECK-NEXT:  In Loop with Header: for.j.header
+; CHECK-NEXT:  AccessFunction: {{\{\{}}1020,+,1024}<%for.i.header>,+,-128}<%for.j.header>
+; CHECK-NEXT:  Base offset: %a
+; CHECK-NEXT:  ArrayDecl[UnknownSize][256] with elements of 4 bytes.
+; CHECK-NEXT:  ArrayRef[{0,+,1}<nuw><nsw><%for.i.header>][{255,+,-32}<%for.j.header>]
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: store i32 1, ptr %idx, align 4
+; CHECK-NEXT:  In Loop with Header: for.i.header
+; CHECK-NEXT:  AccessFunction: {124,+,1024}<%for.i.header>
+; CHECK-NEXT:  Base offset: %a
+; CHECK-NEXT:  ArrayDecl[UnknownSize] with elements of 4 bytes.
+; CHECK-NEXT:  ArrayRef[{31,+,256}<%for.i.header>]
+;
 entry:
   br label %for.i.header
 
@@ -104,14 +171,80 @@ exit:
 ;     }
 ; }
 
-; CHECK:      Delinearization on function a_ijk_b_i2jk:
-; CHECK:      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:      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>]
 define void @a_ijk_b_i2jk(ptr %a, ptr %b) {
+; CHECK-LABEL: 'a_ijk_b_i2jk'
+; CHECK-NEXT:  Inst: %a.idx = getelementptr [4 x [64 x i32]], ptr %a, i32 %i, i32 %j, i32 %k
+; CHECK-NEXT:  In Loop with Header: for.k
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %a.idx = getelementptr [4 x [64 x i32]], ptr %a, i32 %i, i32 %j, i32 %k
+; CHECK-NEXT:  In Loop with Header: for.j.header
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %a.idx = getelementptr [4 x [64 x i32]], ptr %a, i32 %i, i32 %j, i32 %k
+; CHECK-NEXT:  In Loop with Header: for.i.header
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %b.idx = getelementptr [8 x [32 x i32]], ptr %b, i32 %i, i32 %j2, i32 %k
+; CHECK-NEXT:  In Loop with Header: for.k
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %b.idx = getelementptr [8 x [32 x i32]], ptr %b, i32 %i, i32 %j2, i32 %k
+; CHECK-NEXT:  In Loop with Header: for.j.header
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %b.idx = getelementptr [8 x [32 x i32]], ptr %b, i32 %i, i32 %j2, i32 %k
+; CHECK-NEXT:  In Loop with Header: for.i.header
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: store i32 1, ptr %a.idx, align 4
+; CHECK-NEXT:  In Loop with Header: for.k
+; CHECK-NEXT:  AccessFunction: {{\{\{\{}}0,+,1024}<nuw><nsw><%for.i.header>,+,256}<nw><%for.j.header>,+,4}<nw><%for.k>
+; 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-EMPTY:
+; CHECK-NEXT:  Inst: store i32 1, ptr %a.idx, align 4
+; CHECK-NEXT:  In Loop with Header: for.j.header
+; CHECK-NEXT:  AccessFunction: {{\{\{}}124,+,1024}<%for.i.header>,+,256}<%for.j.header>
+; CHECK-NEXT:  Base offset: %a
+; CHECK-NEXT:  ArrayDecl[UnknownSize][256] with elements of 4 bytes.
+; CHECK-NEXT:  ArrayRef[{0,+,1}<nuw><nsw><%for.i.header>][{31,+,64}<%for.j.header>]
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: store i32 1, ptr %a.idx, align 4
+; CHECK-NEXT:  In Loop with Header: for.i.header
+; CHECK-NEXT:  AccessFunction: {892,+,1024}<%for.i.header>
+; CHECK-NEXT:  Base offset: %a
+; CHECK-NEXT:  ArrayDecl[UnknownSize] with elements of 4 bytes.
+; CHECK-NEXT:  ArrayRef[{223,+,256}<%for.i.header>]
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: store i32 1, ptr %b.idx, align 4
+; CHECK-NEXT:  In Loop with Header: for.k
+; CHECK-NEXT:  AccessFunction: {{\{\{\{}}0,+,1024}<nuw><nsw><%for.i.header>,+,256}<nw><%for.j.header>,+,4}<nw><%for.k>
+; CHECK-NEXT:  Base offset: %b
+; C...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Aug 15, 2025

@llvm/pr-subscribers-llvm-analysis

Author: Sebastian Pop (sebpop)

Changes

After adapting the output of printDelinearization() to match what the script expects to see, "Printing analysis 'Delinearization' for function", the rest of the patch is the automatic run of:

$ /llvm-project/llvm/utils/update_analyze_test_checks.py --opt=/llvm-project/build/bin/opt ~/llvm-project/llvm/test/Analysis/Delinearization/*.ll


Patch is 107.43 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/153831.diff

23 Files Affected:

  • (modified) llvm/lib/Analysis/Delinearization.cpp (+2-1)
  • (modified) llvm/test/Analysis/Delinearization/a.ll (+38-5)
  • (modified) llvm/test/Analysis/Delinearization/byte_offset.ll (+12-3)
  • (modified) llvm/test/Analysis/Delinearization/constant_functions_multi_dim.ll (+27-15)
  • (modified) llvm/test/Analysis/Delinearization/divide_by_one.ll (+50-12)
  • (modified) llvm/test/Analysis/Delinearization/fixed_size_array.ll (+409-41)
  • (modified) llvm/test/Analysis/Delinearization/gcd_multiply_expr.ll (+368-1)
  • (modified) llvm/test/Analysis/Delinearization/himeno_1.ll (+38-5)
  • (modified) llvm/test/Analysis/Delinearization/himeno_2.ll (+38-5)
  • (modified) llvm/test/Analysis/Delinearization/iv_times_constant_in_subscript.ll (+26-6)
  • (modified) llvm/test/Analysis/Delinearization/multidim_ivs_and_integer_offsets_3d.ll (+38-5)
  • (modified) llvm/test/Analysis/Delinearization/multidim_ivs_and_integer_offsets_nts_3d.ll (+38-5)
  • (modified) llvm/test/Analysis/Delinearization/multidim_ivs_and_parameteric_offsets_3d.ll (+38-5)
  • (modified) llvm/test/Analysis/Delinearization/multidim_only_ivs_2d.ll (+40-14)
  • (modified) llvm/test/Analysis/Delinearization/multidim_only_ivs_2d_nested.ll (+44-6)
  • (modified) llvm/test/Analysis/Delinearization/multidim_only_ivs_3d.ll (+38-5)
  • (modified) llvm/test/Analysis/Delinearization/multidim_only_ivs_3d_cast.ll (+38-5)
  • (modified) llvm/test/Analysis/Delinearization/multidim_two_accesses_different_delinearization.ll (+49-1)
  • (modified) llvm/test/Analysis/Delinearization/parameter_addrec_product.ll (+50-4)
  • (modified) llvm/test/Analysis/Delinearization/terms_with_identity_factor.ll (+154-11)
  • (modified) llvm/test/Analysis/Delinearization/type_mismatch.ll (+18-1)
  • (modified) llvm/test/Analysis/Delinearization/undef.ll (+33-1)
  • (modified) llvm/utils/UpdateTestChecks/common.py (+1)
diff --git a/llvm/lib/Analysis/Delinearization.cpp b/llvm/lib/Analysis/Delinearization.cpp
index 761c566eae794..3481e572c43e6 100644
--- a/llvm/lib/Analysis/Delinearization.cpp
+++ b/llvm/lib/Analysis/Delinearization.cpp
@@ -744,7 +744,8 @@ namespace {
 
 void printDelinearization(raw_ostream &O, Function *F, LoopInfo *LI,
                           ScalarEvolution *SE) {
-  O << "Delinearization on function " << F->getName() << ":\n";
+  O << "Printing analysis 'Delinearization' for function '" << F->getName()
+    << "':";
   for (Instruction &Inst : instructions(F)) {
     // Only analyze loads and stores.
     if (!isa<StoreInst>(&Inst) && !isa<LoadInst>(&Inst) &&
diff --git a/llvm/test/Analysis/Delinearization/a.ll b/llvm/test/Analysis/Delinearization/a.ll
index 02ba3fde695c3..fd96e778ea1bf 100644
--- a/llvm/test/Analysis/Delinearization/a.ll
+++ b/llvm/test/Analysis/Delinearization/a.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5
 ; RUN: opt < %s -passes='print<delinearization>' -disable-output 2>&1 | FileCheck %s
 ;
 ; void foo(long n, long m, long o, int A[n][m][o]) {
@@ -7,12 +8,44 @@
 ;         A[2*i+3][3*j-4][5*k+7] = 1;
 ; }
 
-; AddRec: {{{(28 + (4 * (-4 + (3 * %m)) * %o) + %A),+,(8 * %m * %o)}<%for.i>,+,(12 * %o)}<%for.j>,+,20}<%for.k>
-; CHECK: Base offset: %A
-; CHECK: ArrayDecl[UnknownSize][%m][%o] with elements of 4 bytes.
-; CHECK: ArrayRef[{3,+,2}<nuw><%for.i>][{-4,+,3}<nw><%for.j>][{7,+,5}<nw><%for.k>]
-
 define void @foo(i64 %n, i64 %m, i64 %o, ptr nocapture %A) #0 {
+; CHECK-LABEL: 'foo'
+; CHECK-NEXT:  Inst: %arrayidx11.us.us = getelementptr inbounds i32, ptr %A, i64 %arrayidx10.sum.us.us
+; CHECK-NEXT:  In Loop with Header: for.k
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %arrayidx11.us.us = getelementptr inbounds i32, ptr %A, i64 %arrayidx10.sum.us.us
+; CHECK-NEXT:  In Loop with Header: for.j
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %arrayidx11.us.us = getelementptr inbounds i32, ptr %A, i64 %arrayidx10.sum.us.us
+; CHECK-NEXT:  In Loop with Header: for.i
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: store i32 1, ptr %arrayidx11.us.us, align 4
+; CHECK-NEXT:  In Loop with Header: for.k
+; CHECK-NEXT:  AccessFunction: {{\{\{\{}}(28 + (4 * (-4 + (3 * %m)) * %o)),+,(8 * %m * %o)}<%for.i>,+,(12 * %o)}<%for.j>,+,20}<%for.k>
+; 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-EMPTY:
+; CHECK-NEXT:  Inst: store i32 1, ptr %arrayidx11.us.us, align 4
+; CHECK-NEXT:  In Loop with Header: for.j
+; CHECK-NEXT:  AccessFunction: {{\{\{}}(8 + ((4 + (12 * %m)) * %o)),+,(8 * %m * %o)}<%for.i>,+,(12 * %o)}<%for.j>
+; CHECK-NEXT:  Base offset: %A
+; CHECK-NEXT:  ArrayDecl[UnknownSize][%m][%o] with elements of 4 bytes.
+; CHECK-NEXT:  ArrayRef[{3,+,2}<nuw><%for.i>][{1,+,3}<%for.j>][2]
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: store i32 1, ptr %arrayidx11.us.us, align 4
+; CHECK-NEXT:  In Loop with Header: for.i
+; CHECK-NEXT:  AccessFunction: {(8 + ((-8 + (24 * %m)) * %o)),+,(8 * %m * %o)}<%for.i>
+; CHECK-NEXT:  Base offset: %A
+; CHECK-NEXT:  ArrayDecl[UnknownSize][(%m * %o)] with elements of 4 bytes.
+; CHECK-NEXT:  ArrayRef[0][{(2 + ((-2 + (6 * %m)) * %o)),+,(2 * %m * %o)}<%for.i>]
+;
 entry:
   %cmp32 = icmp sgt i64 %n, 0
   br i1 %cmp32, label %for.cond1.preheader.lr.ph, label %for.end17
diff --git a/llvm/test/Analysis/Delinearization/byte_offset.ll b/llvm/test/Analysis/Delinearization/byte_offset.ll
index 6534d3ea6c05b..04b0dcd2ee1d8 100644
--- a/llvm/test/Analysis/Delinearization/byte_offset.ll
+++ b/llvm/test/Analysis/Delinearization/byte_offset.ll
@@ -1,8 +1,6 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5
 ; RUN: opt < %s -passes='print<delinearization>' -disable-output 2>&1 | FileCheck %s
 
-; CHECK: AccessFunction: ({0,+,%i2}<%outer.loop> + %unknown)
-; CHECK-NEXT: failed to delinearize
-
 ; void foo(char A[], long i2, bool c) {
 ;   for (long i = 0; ; ++i) {
 ;     char *tmp = &A[i * i2];
@@ -13,6 +11,17 @@
 ; }
 
 define void @foo(ptr %A, i64 %i2, i64 %arg, i1 %c) {
+; CHECK-LABEL: 'foo'
+; CHECK-NEXT:  Inst: %tmp = getelementptr inbounds i8, ptr %A, i64 %i414
+; CHECK-NEXT:  In Loop with Header: outer.loop
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: store float 0.000000e+00, ptr %arrayidx, align 4
+; CHECK-NEXT:  In Loop with Header: inner.loop
+; CHECK-NEXT:  AccessFunction: ({0,+,%i2}<%outer.loop> + %unknown)
+; CHECK-NEXT:  failed to delinearize
+;
 entry:
   br label %outer.loop
 
diff --git a/llvm/test/Analysis/Delinearization/constant_functions_multi_dim.ll b/llvm/test/Analysis/Delinearization/constant_functions_multi_dim.ll
index 3044a4868260b..0ea499fc55352 100644
--- a/llvm/test/Analysis/Delinearization/constant_functions_multi_dim.ll
+++ b/llvm/test/Analysis/Delinearization/constant_functions_multi_dim.ll
@@ -1,23 +1,35 @@
-; RUN: opt -passes='print<delinearization>' -disable-output < %s 2>&1 | FileCheck %s
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -passes='print<delinearization>' -disable-output 2>&1 | FileCheck %s
 
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 
-; CHECK:      Inst:  %tmp = load float, ptr %arrayidx, align 4
-; CHECK-NEXT: In Loop with Header: for.inc
-; CHECK-NEXT: AccessFunction: {(4 * %N * %call),+,4}<%for.inc>
-; 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:      Inst:  %tmp5 = load float, ptr %arrayidx4, align 4
-; CHECK-NEXT: In Loop with Header: for.inc
-; 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]
-
 ; Function Attrs: noinline nounwind uwtable
 define void @mat_mul(ptr %C, ptr %A, ptr %B, i64 %N) #0 !kernel_arg_addr_space !2 !kernel_arg_access_qual !3 !kernel_arg_type !4 !kernel_arg_base_type !4 !kernel_arg_type_qual !5 {
+; CHECK-LABEL: 'mat_mul'
+; CHECK-NEXT:  Inst: %arrayidx = getelementptr inbounds float, ptr %A, i64 %add
+; CHECK-NEXT:  In Loop with Header: for.inc
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %tmp = load float, ptr %arrayidx, align 4
+; CHECK-NEXT:  In Loop with Header: for.inc
+; CHECK-NEXT:  AccessFunction: {(4 * %N * %call),+,4}<%for.inc>
+; 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-EMPTY:
+; CHECK-NEXT:  Inst: %arrayidx4 = getelementptr inbounds float, ptr %B, i64 %add3
+; CHECK-NEXT:  In Loop with Header: for.inc
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %tmp5 = load float, ptr %arrayidx4, align 4
+; CHECK-NEXT:  In Loop with Header: for.inc
+; 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]
+;
 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 8c531b78f2bcf..ff5f178d5a88b 100644
--- a/llvm/test/Analysis/Delinearization/divide_by_one.ll
+++ b/llvm/test/Analysis/Delinearization/divide_by_one.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5
 ; RUN: opt < %s -passes='print<delinearization>' -disable-output 2>&1 | FileCheck %s
 
 target datalayout = "e-m:e-p:32:32-i1:32-i64:64-a:0-n32"
@@ -10,19 +11,56 @@ target datalayout = "e-m:e-p:32:32-i1:32-i64:64-a:0-n32"
 ;       dst[r * stride + c] = dst[(r + 1) * stride + c - 1];
 ; }
 
-; AddRec: {{(-1 + ((1 + %bs) * %stride)),+,(-1 * %stride)}<%for.cond1.preheader>,+,1}<nw><%for.body3>
-; CHECK: Inst:  %0 = load i8, ptr %arrayidx, align 1
-; CHECK: Base offset: %dst
-; CHECK: ArrayDecl[UnknownSize][%stride] with elements of 1 bytes.
-; CHECK: ArrayRef[{(1 + %bs),+,-1}<nw><%for.cond1.preheader>][{-1,+,1}<nw><%for.body3>]
-
-; AddRec: {{(ptr %bs),+,(-1 * %stride)}<%for.cond1.preheader>,+,1}<nw><%for.body3>
-; CHECK: Inst:  store i8 %0, ptr %arrayidx7, align 1
-; CHECK: Base offset: %dst
-; CHECK: ArrayDecl[UnknownSize][%stride] with elements of 1 bytes.
-; CHECK: ArrayRef[{%bs,+,-1}<nsw><%for.cond1.preheader>][{0,+,1}<nuw><nsw><%for.body3>]
-
 define void @test(ptr nocapture %dst, i32 %stride, i32 %bs) {
+; CHECK-LABEL: 'test'
+; CHECK-NEXT:  Inst: %arrayidx = getelementptr inbounds i8, ptr %dst, i32 %sub
+; CHECK-NEXT:  In Loop with Header: for.body3
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %arrayidx = getelementptr inbounds i8, ptr %dst, i32 %sub
+; CHECK-NEXT:  In Loop with Header: for.cond1.preheader
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %0 = load i8, ptr %arrayidx, align 1
+; CHECK-NEXT:  In Loop with Header: for.body3
+; CHECK-NEXT:  AccessFunction: {{\{\{}}(-1 + ((1 + %bs) * %stride)),+,(-1 * %stride)}<%for.cond1.preheader>,+,1}<nw><%for.body3>
+; 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-EMPTY:
+; CHECK-NEXT:  Inst: %0 = load i8, ptr %arrayidx, align 1
+; CHECK-NEXT:  In Loop with Header: for.cond1.preheader
+; CHECK-NEXT:  AccessFunction: {(-2 + ((1 + %bs) * %stride) + %bs),+,(-1 * %stride)}<%for.cond1.preheader>
+; 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>][(-2 + %bs)]
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %arrayidx7 = getelementptr inbounds i8, ptr %dst, i32 %add6
+; CHECK-NEXT:  In Loop with Header: for.body3
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %arrayidx7 = getelementptr inbounds i8, ptr %dst, i32 %add6
+; CHECK-NEXT:  In Loop with Header: for.cond1.preheader
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: store i8 %0, ptr %arrayidx7, align 1
+; CHECK-NEXT:  In Loop with Header: for.body3
+; 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-EMPTY:
+; CHECK-NEXT:  Inst: store i8 %0, ptr %arrayidx7, align 1
+; CHECK-NEXT:  In Loop with Header: for.cond1.preheader
+; CHECK-NEXT:  AccessFunction: {(-1 + ((1 + %stride) * %bs)),+,(-1 * %stride)}<%for.cond1.preheader>
+; CHECK-NEXT:  Base offset: %dst
+; CHECK-NEXT:  ArrayDecl[UnknownSize][%stride] with elements of 1 bytes.
+; CHECK-NEXT:  ArrayRef[{%bs,+,-1}<nsw><%for.cond1.preheader>][(-1 + %bs)]
+;
 entry:
   %cmp20 = icmp sgt i32 %bs, -1
   br i1 %cmp20, label %for.cond1.preheader.lr.ph, label %for.end9
diff --git a/llvm/test/Analysis/Delinearization/fixed_size_array.ll b/llvm/test/Analysis/Delinearization/fixed_size_array.ll
index 0512044990163..d22d9b106e53a 100644
--- a/llvm/test/Analysis/Delinearization/fixed_size_array.ll
+++ b/llvm/test/Analysis/Delinearization/fixed_size_array.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5
 ; RUN: opt < %s -passes='print<delinearization>' -disable-output -delinearize-use-fixed-size-array-heuristic 2>&1 | FileCheck %s
 
 ; void f(int A[][8][32]) {
@@ -7,11 +8,44 @@
 ;       A[i][j][k] = 1;
 ; }
 
-; CHECK:      Delinearization on function a_i_j_k:
-; CHECK:      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>]
 define void @a_i_j_k(ptr %a) {
+; CHECK-LABEL: 'a_i_j_k'
+; CHECK-NEXT:  Inst: %idx = getelementptr [8 x [32 x i32]], ptr %a, i32 %i, i32 %j, i32 %k
+; CHECK-NEXT:  In Loop with Header: for.k
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %idx = getelementptr [8 x [32 x i32]], ptr %a, i32 %i, i32 %j, i32 %k
+; CHECK-NEXT:  In Loop with Header: for.j.header
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %idx = getelementptr [8 x [32 x i32]], ptr %a, i32 %i, i32 %j, i32 %k
+; CHECK-NEXT:  In Loop with Header: for.i.header
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: store i32 1, ptr %idx, align 4
+; CHECK-NEXT:  In Loop with Header: for.k
+; CHECK-NEXT:  AccessFunction: {{\{\{\{}}0,+,1024}<nuw><nsw><%for.i.header>,+,128}<nw><%for.j.header>,+,4}<nw><%for.k>
+; 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-EMPTY:
+; CHECK-NEXT:  Inst: store i32 1, ptr %idx, align 4
+; CHECK-NEXT:  In Loop with Header: for.j.header
+; CHECK-NEXT:  AccessFunction: {{\{\{}}124,+,1024}<%for.i.header>,+,128}<%for.j.header>
+; CHECK-NEXT:  Base offset: %a
+; CHECK-NEXT:  ArrayDecl[UnknownSize][256] with elements of 4 bytes.
+; CHECK-NEXT:  ArrayRef[{0,+,1}<nuw><nsw><%for.i.header>][{31,+,32}<%for.j.header>]
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: store i32 1, ptr %idx, align 4
+; CHECK-NEXT:  In Loop with Header: for.i.header
+; CHECK-NEXT:  AccessFunction: {1020,+,1024}<%for.i.header>
+; CHECK-NEXT:  Base offset: %a
+; CHECK-NEXT:  ArrayDecl[UnknownSize] with elements of 4 bytes.
+; CHECK-NEXT:  ArrayRef[{255,+,256}<%for.i.header>]
+;
 entry:
   br label %for.i.header
 
@@ -52,11 +86,44 @@ exit:
 ;       A[i][7-j][k] = 1;
 ; }
 
-; CHECK:      Delinearization on function a_i_nj_k:
-; CHECK:      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>]
 define void @a_i_nj_k(ptr %a) {
+; CHECK-LABEL: 'a_i_nj_k'
+; CHECK-NEXT:  Inst: %idx = getelementptr [8 x [32 x i32]], ptr %a, i32 %i, i32 %j.subscript, i32 %k
+; CHECK-NEXT:  In Loop with Header: for.k
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %idx = getelementptr [8 x [32 x i32]], ptr %a, i32 %i, i32 %j.subscript, i32 %k
+; CHECK-NEXT:  In Loop with Header: for.j.header
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %idx = getelementptr [8 x [32 x i32]], ptr %a, i32 %i, i32 %j.subscript, i32 %k
+; CHECK-NEXT:  In Loop with Header: for.i.header
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: store i32 1, ptr %idx, align 4
+; CHECK-NEXT:  In Loop with Header: for.k
+; CHECK-NEXT:  AccessFunction: {{\{\{\{}}896,+,1024}<nuw><nsw><%for.i.header>,+,-128}<nw><%for.j.header>,+,4}<nw><%for.k>
+; 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-EMPTY:
+; CHECK-NEXT:  Inst: store i32 1, ptr %idx, align 4
+; CHECK-NEXT:  In Loop with Header: for.j.header
+; CHECK-NEXT:  AccessFunction: {{\{\{}}1020,+,1024}<%for.i.header>,+,-128}<%for.j.header>
+; CHECK-NEXT:  Base offset: %a
+; CHECK-NEXT:  ArrayDecl[UnknownSize][256] with elements of 4 bytes.
+; CHECK-NEXT:  ArrayRef[{0,+,1}<nuw><nsw><%for.i.header>][{255,+,-32}<%for.j.header>]
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: store i32 1, ptr %idx, align 4
+; CHECK-NEXT:  In Loop with Header: for.i.header
+; CHECK-NEXT:  AccessFunction: {124,+,1024}<%for.i.header>
+; CHECK-NEXT:  Base offset: %a
+; CHECK-NEXT:  ArrayDecl[UnknownSize] with elements of 4 bytes.
+; CHECK-NEXT:  ArrayRef[{31,+,256}<%for.i.header>]
+;
 entry:
   br label %for.i.header
 
@@ -104,14 +171,80 @@ exit:
 ;     }
 ; }
 
-; CHECK:      Delinearization on function a_ijk_b_i2jk:
-; CHECK:      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:      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>]
 define void @a_ijk_b_i2jk(ptr %a, ptr %b) {
+; CHECK-LABEL: 'a_ijk_b_i2jk'
+; CHECK-NEXT:  Inst: %a.idx = getelementptr [4 x [64 x i32]], ptr %a, i32 %i, i32 %j, i32 %k
+; CHECK-NEXT:  In Loop with Header: for.k
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %a.idx = getelementptr [4 x [64 x i32]], ptr %a, i32 %i, i32 %j, i32 %k
+; CHECK-NEXT:  In Loop with Header: for.j.header
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %a.idx = getelementptr [4 x [64 x i32]], ptr %a, i32 %i, i32 %j, i32 %k
+; CHECK-NEXT:  In Loop with Header: for.i.header
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %b.idx = getelementptr [8 x [32 x i32]], ptr %b, i32 %i, i32 %j2, i32 %k
+; CHECK-NEXT:  In Loop with Header: for.k
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %b.idx = getelementptr [8 x [32 x i32]], ptr %b, i32 %i, i32 %j2, i32 %k
+; CHECK-NEXT:  In Loop with Header: for.j.header
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: %b.idx = getelementptr [8 x [32 x i32]], ptr %b, i32 %i, i32 %j2, i32 %k
+; CHECK-NEXT:  In Loop with Header: for.i.header
+; CHECK-NEXT:  AccessFunction: 0
+; CHECK-NEXT:  failed to delinearize
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: store i32 1, ptr %a.idx, align 4
+; CHECK-NEXT:  In Loop with Header: for.k
+; CHECK-NEXT:  AccessFunction: {{\{\{\{}}0,+,1024}<nuw><nsw><%for.i.header>,+,256}<nw><%for.j.header>,+,4}<nw><%for.k>
+; 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-EMPTY:
+; CHECK-NEXT:  Inst: store i32 1, ptr %a.idx, align 4
+; CHECK-NEXT:  In Loop with Header: for.j.header
+; CHECK-NEXT:  AccessFunction: {{\{\{}}124,+,1024}<%for.i.header>,+,256}<%for.j.header>
+; CHECK-NEXT:  Base offset: %a
+; CHECK-NEXT:  ArrayDecl[UnknownSize][256] with elements of 4 bytes.
+; CHECK-NEXT:  ArrayRef[{0,+,1}<nuw><nsw><%for.i.header>][{31,+,64}<%for.j.header>]
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: store i32 1, ptr %a.idx, align 4
+; CHECK-NEXT:  In Loop with Header: for.i.header
+; CHECK-NEXT:  AccessFunction: {892,+,1024}<%for.i.header>
+; CHECK-NEXT:  Base offset: %a
+; CHECK-NEXT:  ArrayDecl[UnknownSize] with elements of 4 bytes.
+; CHECK-NEXT:  ArrayRef[{223,+,256}<%for.i.header>]
+; CHECK-EMPTY:
+; CHECK-NEXT:  Inst: store i32 1, ptr %b.idx, align 4
+; CHECK-NEXT:  In Loop with Header: for.k
+; CHECK-NEXT:  AccessFunction: {{\{\{\{}}0,+,1024}<nuw><nsw><%for.i.header>,+,256}<nw><%for.j.header>,+,4}<nw><%for.k>
+; CHECK-NEXT:  Base offset: %b
+; C...
[truncated]

@github-actions
Copy link

github-actions bot commented Aug 15, 2025

✅ With the latest revision this PR passed the undef deprecator.

@@ -1,4 +1,5 @@
; RUN: opt -aa-pipeline=basic-aa -passes='require<da>,print<delinearization>' -disable-output < %s
; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5
; RUN: opt < %s -aa-pipeline=basic-aa -passes='require<da>,print<delinearization>' -disable-output 2>&1 | FileCheck %s
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
; RUN: opt < %s -aa-pipeline=basic-aa -passes='require<da>,print<delinearization>' -disable-output 2>&1 | FileCheck %s
; RUN: opt < %s -passes='print<delinearization>' -disable-output 2>&1 | FileCheck %s

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not applied? I'm okay if you dismiss my suggestion for some reason.

@sebpop sebpop force-pushed the update-delin-tests branch 2 times, most recently from c1f0b72 to d3ff1bc Compare August 16, 2025 02:56
Copy link
Collaborator

@sjoerdmeijer sjoerdmeijer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a few more things going on in this patch besides changes in printing delinearization: there are also test fixes and changes in the test scripts (common.py).
They are probably small enough, so one patch is okay, but maybe this at least deserves a mention in the description. Other than that, LGTM.

Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

Comment on lines -5 to -38
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this IR doesn't contain UB, I believe this test is useful to ensure that nothing unexpected occurs when undef is present.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with your recommendation.

In this revision of the patch I removed all uses of undef, however the linter still triggered a warning, maybe because the file name was undef?
Let me reinstate the file without the undefs and this time I will also rename it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I don't know if we can force the lint checker to accept the testcase with undefs.

@@ -1,4 +1,5 @@
; RUN: opt -aa-pipeline=basic-aa -passes='require<da>,print<delinearization>' -disable-output < %s
; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5
; RUN: opt < %s -aa-pipeline=basic-aa -passes='require<da>,print<delinearization>' -disable-output 2>&1 | FileCheck %s
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not applied? I'm okay if you dismiss my suggestion for some reason.

After adapting the output of printDelinearization() to match what the script
expects to see, "Printing analysis 'Delinearization' for function", and
registering the "Delinearization" pass in the update script, the rest of the
patch automatically removes the existing CHECK statements and update the tests
with a run of:

```
$ ~/llvm-project/llvm/utils/update_analyze_test_checks.py
  --opt=~/llvm-project/build/bin/opt
  ~/llvm-project/llvm/test/Analysis/Delinearization/*.ll
```

The patch also drops llvm/test/Analysis/Delinearization/undef.ll because the
test does not pass the github-actions "undef deprecator."
@sebpop sebpop force-pushed the update-delin-tests branch from dd89345 to a2541ca Compare August 21, 2025 16:49
@sebpop sebpop merged commit e42ef80 into llvm:main Aug 21, 2025
9 checks passed
@sebpop sebpop deleted the update-delin-tests branch August 21, 2025 18:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

llvm:analysis Includes value tracking, cost tables and constant folding testing-tools

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants