Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update_analyze_test_checks: support output from LAA #67584

Merged
merged 1 commit into from
Oct 31, 2023

Conversation

artagnon
Copy link
Contributor

@artagnon artagnon commented Sep 27, 2023

update_analyze_test_checks.py is an invaluable tool in updating tests. Unfortunately, it only supports output from the CostModel, ScalarEvolution, and LoopVectorize analyses. Many LoopAccessAnalysis tests use hand-crafted CHECK lines, and it is moreover tedious to generate these CHECK lines, as the output fom the analysis is not stable, and requires the test-writer to hand-craft FileCheck matches. Alleviate this pain, and support output from:

  $ opt -passes='print<loop-accesses>'

This patch includes several non-trivial changes including:

  • Preserving whitespace at the beginning of the line, so that the LAA output can be properly indented.
  • Regexes matching the unstable output, which is basically a pointer address hex.
  • Separating is_analyze from preserve_names clearly, as the former was formerly used as an overload for the latter.

To demonstate the utility of this patch, several tests in LoopAccessAnalysis have been auto-generated by
update_analyze_test_checks.py.

@llvmbot
Copy link
Collaborator

llvmbot commented Sep 27, 2023

@llvm/pr-subscribers-testing-tools
@llvm/pr-subscribers-llvm-transforms

@llvm/pr-subscribers-llvm-analysis

Changes

update_analyze_test_checks.py is an invaluable tool in updating tests. Unfortunately, it only supports output from the CostModel, ScalarEvolution, and LoopVectorize analyses. Many LoopAccessAnalysis tests use hand-crafted CHECK lines, and it is moreover tedious to generate these CHECK lines, as the output fom the analysis is not stable, and requires the test-writer to hand-craft FileCheck matches. Alleviate this pain, and support output from:

  $ opt -passes='print&lt;loop-accesses&gt;'

This patch includes several non-trivial changes including:

  • Preserving whitespace at the beginning of the line, so that the LAA output can be properly indented.
  • Regexes matching the unstable output, which is basically a pointer address hex.

To demonstate the utility of this patch, several tests in LoopAccessAnalysis have been auto-generated by
update_analyze_test_checks.py.


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

15 Files Affected:

  • (modified) llvm/lib/Transforms/Scalar/LoopAccessAnalysisPrinter.cpp (+2-1)
  • (modified) llvm/test/Analysis/LoopAccessAnalysis/forked-pointers.ll (+873-507)
  • (modified) llvm/test/Analysis/LoopAccessAnalysis/loop-invariant-dep-with-backedge-taken-count.ll (+89-71)
  • (modified) llvm/test/Analysis/LoopAccessAnalysis/max_safe_dep_dist_non_unit_stride.ll (+13-15)
  • (modified) llvm/test/Analysis/LoopAccessAnalysis/pointer-phis.ll (+230-182)
  • (modified) llvm/test/Analysis/LoopAccessAnalysis/symbolic-stride.ll (+56-64)
  • (modified) llvm/test/Transforms/LoopUnroll/unroll-loop-invalidation.ll (+1-1)
  • (added) llvm/test/tools/UpdateTestChecks/update_analyze_test_checks/Inputs/dotvariable-laa.ll (+23)
  • (added) llvm/test/tools/UpdateTestChecks/update_analyze_test_checks/Inputs/dotvariable-laa.ll.expected (+62)
  • (added) llvm/test/tools/UpdateTestChecks/update_analyze_test_checks/Inputs/loop-access-analysis.ll (+23)
  • (added) llvm/test/tools/UpdateTestChecks/update_analyze_test_checks/Inputs/loop-access-analysis.ll.expected (+56)
  • (added) llvm/test/tools/UpdateTestChecks/update_analyze_test_checks/dotvariable-laa.test (+6)
  • (added) llvm/test/tools/UpdateTestChecks/update_analyze_test_checks/loop-access-analysis.test (+6)
  • (modified) llvm/utils/UpdateTestChecks/common.py (+57-15)
  • (modified) llvm/utils/update_analyze_test_checks.py (-4)
diff --git a/llvm/lib/Transforms/Scalar/LoopAccessAnalysisPrinter.cpp b/llvm/lib/Transforms/Scalar/LoopAccessAnalysisPrinter.cpp
index 9ae55b9018dad34..3d3f22d686e32ed 100644
--- a/llvm/lib/Transforms/Scalar/LoopAccessAnalysisPrinter.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopAccessAnalysisPrinter.cpp
@@ -20,7 +20,8 @@ PreservedAnalyses LoopAccessInfoPrinterPass::run(Function &F,
                                                  FunctionAnalysisManager &AM) {
   auto &LAIs = AM.getResult<LoopAccessAnalysis>(F);
   auto &LI = AM.getResult<LoopAnalysis>(F);
-  OS << "Loop access info in function '" << F.getName() << "':\n";
+  OS << "Printing analysis 'Loop Access Analysis' for function '" << F.getName()
+     << "':\n";
 
   SmallPriorityWorklist<Loop *, 4> Worklist;
   appendLoopsToWorklist(LI, Worklist);
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/forked-pointers.ll b/llvm/test/Analysis/LoopAccessAnalysis/forked-pointers.ll
index 30ffc4cb5e1e85f..51a11809cf4e333 100644
--- a/llvm/test/Analysis/LoopAccessAnalysis/forked-pointers.ll
+++ b/llvm/test/Analysis/LoopAccessAnalysis/forked-pointers.ll
@@ -1,43 +1,74 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 3
 ; RUN: opt -disable-output -passes='print<access-info>' %s 2>&1 | FileCheck %s
 ; RUN: opt -disable-output -passes='print<access-info>' -max-forked-scev-depth=2 %s 2>&1 | FileCheck -check-prefix=RECURSE %s
 
 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
 
-; CHECK-LABEL: function 'forked_ptrs_simple':
-; CHECK-NEXT:  loop:
-; CHECK-NEXT:    Memory dependences are safe with run-time checks
-; CHECK-NEXT:    Dependences:
-; CHECK-NEXT:    Run-time memory checks:
-; CHECK-NEXT:    Check 0:
-; CHECK-NEXT:      Comparing group ([[G1:.+]]):
-; CHECK-NEXT:        %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv
-; CHECK-NEXT:        %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv
-; CHECK-NEXT:      Against group ([[G2:.+]]):
-; CHECK-NEXT:        %select = select i1 %cmp, ptr %gep.1, ptr %gep.2
-; CHECK-NEXT:    Check 1:
-; CHECK-NEXT:      Comparing group ([[G1]]):
-; CHECK-NEXT:        %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv
-; CHECK-NEXT:        %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv
-; CHECK-NEXT:      Against group ([[G3:.+]]):
-; CHECK-NEXT:        %select = select i1 %cmp, ptr %gep.1, ptr %gep.2
-; CHECK-NEXT:    Grouped accesses:
-; CHECK-NEXT:      Group [[G1]]
-; CHECK-NEXT:        (Low: %Dest High: (400 + %Dest))
-; CHECK-NEXT:          Member: {%Dest,+,4}<nuw><%loop>
-; CHECK-NEXT:          Member: {%Dest,+,4}<nuw><%loop>
-; CHECK-NEXT:      Group [[G2]]:
-; CHECK-NEXT:        (Low: %Base1 High: (400 + %Base1))
-; CHECK-NEXT:          Member: {%Base1,+,4}<nw><%loop>
-; CHECK-NEXT:      Group [[G3]]:
-; CHECK-NEXT:        (Low: %Base2 High: (400 + %Base2))
-; CHECK-NEXT:          Member: {%Base2,+,4}<nw><%loop>
-; CHECK-EMPTY:
-; CHECK-NEXT:    Non vectorizable stores to invariant address were not found in loop.
-; CHECK-NEXT:    SCEV assumptions:
-; CHECK-EMPTY:
-; CHECK-NEXT:    Expressions re-written:
-
 define void @forked_ptrs_simple(ptr nocapture readonly %Base1, ptr nocapture readonly %Base2, ptr %Dest) {
+; CHECK-LABEL: 'forked_ptrs_simple'
+; CHECK-NEXT:    loop:
+; CHECK-NEXT:      Memory dependences are safe with run-time checks
+; CHECK-NEXT:      Dependences:
+; CHECK-NEXT:      Run-time memory checks:
+; CHECK-NEXT:      Check 0:
+; CHECK-NEXT:        Comparing group ([[GRP1:0x[0-9a-f]+]]):
+; CHECK-NEXT:          %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv
+; CHECK-NEXT:          %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv
+; CHECK-NEXT:        Against group ([[GRP2:0x[0-9a-f]+]]):
+; CHECK-NEXT:          %select = select i1 %cmp, ptr %gep.1, ptr %gep.2
+; CHECK-NEXT:      Check 1:
+; CHECK-NEXT:        Comparing group ([[GRP1]]):
+; CHECK-NEXT:          %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv
+; CHECK-NEXT:          %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv
+; CHECK-NEXT:        Against group ([[GRP3:0x[0-9a-f]+]]):
+; CHECK-NEXT:          %select = select i1 %cmp, ptr %gep.1, ptr %gep.2
+; CHECK-NEXT:      Grouped accesses:
+; CHECK-NEXT:        Group [[GRP1]]:
+; CHECK-NEXT:          (Low: %Dest High: (400 + %Dest))
+; CHECK-NEXT:            Member: {%Dest,+,4}<nuw><%loop>
+; CHECK-NEXT:            Member: {%Dest,+,4}<nuw><%loop>
+; CHECK-NEXT:        Group [[GRP2]]:
+; CHECK-NEXT:          (Low: %Base1 High: (400 + %Base1))
+; CHECK-NEXT:            Member: {%Base1,+,4}<nw><%loop>
+; CHECK-NEXT:        Group [[GRP3]]:
+; CHECK-NEXT:          (Low: %Base2 High: (400 + %Base2))
+; CHECK-NEXT:            Member: {%Base2,+,4}<nw><%loop>
+; CHECK:           Non vectorizable stores to invariant address were not found in loop.
+; CHECK-NEXT:      SCEV assumptions:
+; CHECK:           Expressions re-written:
+;
+; RECURSE-LABEL: 'forked_ptrs_simple'
+; RECURSE-NEXT:    loop:
+; RECURSE-NEXT:      Memory dependences are safe with run-time checks
+; RECURSE-NEXT:      Dependences:
+; RECURSE-NEXT:      Run-time memory checks:
+; RECURSE-NEXT:      Check 0:
+; RECURSE-NEXT:        Comparing group ([[GRP4:0x[0-9a-f]+]]):
+; RECURSE-NEXT:          %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv
+; RECURSE-NEXT:          %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv
+; RECURSE-NEXT:        Against group ([[GRP5:0x[0-9a-f]+]]):
+; RECURSE-NEXT:          %select = select i1 %cmp, ptr %gep.1, ptr %gep.2
+; RECURSE-NEXT:      Check 1:
+; RECURSE-NEXT:        Comparing group ([[GRP4]]):
+; RECURSE-NEXT:          %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv
+; RECURSE-NEXT:          %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv
+; RECURSE-NEXT:        Against group ([[GRP6:0x[0-9a-f]+]]):
+; RECURSE-NEXT:          %select = select i1 %cmp, ptr %gep.1, ptr %gep.2
+; RECURSE-NEXT:      Grouped accesses:
+; RECURSE-NEXT:        Group [[GRP4]]:
+; RECURSE-NEXT:          (Low: %Dest High: (400 + %Dest))
+; RECURSE-NEXT:            Member: {%Dest,+,4}<nuw><%loop>
+; RECURSE-NEXT:            Member: {%Dest,+,4}<nuw><%loop>
+; RECURSE-NEXT:        Group [[GRP5]]:
+; RECURSE-NEXT:          (Low: %Base1 High: (400 + %Base1))
+; RECURSE-NEXT:            Member: {%Base1,+,4}<nw><%loop>
+; RECURSE-NEXT:        Group [[GRP6]]:
+; RECURSE-NEXT:          (Low: %Base2 High: (400 + %Base2))
+; RECURSE-NEXT:            Member: {%Base2,+,4}<nw><%loop>
+; RECURSE:           Non vectorizable stores to invariant address were not found in loop.
+; RECURSE-NEXT:      SCEV assumptions:
+; RECURSE:           Expressions re-written:
+;
 entry:
   br label %loop
 
@@ -59,59 +90,9 @@ exit:
   ret void
 }
 
-; CHECK-LABEL: function 'forked_ptrs_different_base_same_offset':
-; CHECK-NEXT:  for.body:
-; CHECK-NEXT:    Memory dependences are safe with run-time checks
-; CHECK-NEXT:    Dependences:
-; CHECK-NEXT:    Run-time memory checks:
-; CHECK-NEXT:    Check 0:
-; CHECK-NEXT:      Comparing group ([[G1:.+]]):
-; CHECK-NEXT:        %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
-; CHECK-NEXT:      Against group ([[G2:.+]]):
-; CHECK-NEXT:        %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
-; CHECK-NEXT:    Check 1:
-; CHECK-NEXT:      Comparing group ([[G1]]):
-; CHECK-NEXT:        %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
-; CHECK-NEXT:      Against group ([[G3:.+]]):
-; CHECK-NEXT:        %.sink.in = getelementptr inbounds float, ptr %spec.select, i64 %indvars.iv
-; CHECK-NEXT:    Check 2:
-; CHECK-NEXT:      Comparing group ([[G1]]):
-; CHECK-NEXT:        %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
-; CHECK-NEXT:      Against group ([[G4:.+]]):
-; CHECK-NEXT:        %.sink.in = getelementptr inbounds float, ptr %spec.select, i64 %indvars.iv
-; CHECK-NEXT:    Grouped accesses:
-; CHECK-NEXT:      Group [[G1]]:
-; CHECK-NEXT:        (Low: %Dest High: (400 + %Dest))
-; CHECK-NEXT:          Member: {%Dest,+,4}<nuw><%for.body>
-; CHECK-NEXT:      Group [[G2]]:
-; CHECK-NEXT:        (Low: %Preds High: (400 + %Preds))
-; CHECK-NEXT:          Member: {%Preds,+,4}<nuw><%for.body>
-; CHECK-NEXT:      Group [[G3]]:
-; CHECK-NEXT:        (Low: %Base2 High: (400 + %Base2))
-; CHECK-NEXT:          Member: {%Base2,+,4}<nw><%for.body>
-; CHECK-NEXT:      Group [[G4]]:
-; CHECK-NEXT:        (Low: %Base1 High: (400 + %Base1))
-; CHECK-NEXT:          Member: {%Base1,+,4}<nw><%for.body>
-; CHECK-EMPTY:
-; CHECK-NEXT:   Non vectorizable stores to invariant address were not found in loop.
-; CHECK-NEXT:   SCEV assumptions:
-; CHECK-EMPTY:
-; CHECK-NEXT:   Expressions re-written:
-
 ;; We have a limit on the recursion depth for finding a loop invariant or
 ;; addrec term; confirm we won't exceed that depth by forcing a lower
 ;; limit via -max-forked-scev-depth=2
-; RECURSE-LABEL: Loop access info in function 'forked_ptrs_same_base_different_offset':
-; RECURSE-NEXT:   for.body:
-; RECURSE-NEXT:     Report: cannot identify array bounds
-; RECURSE-NEXT:     Dependences:
-; RECURSE-NEXT:     Run-time memory checks:
-; RECURSE-NEXT:     Grouped accesses:
-; RECURSE-EMPTY:
-; RECURSE-NEXT:     Non vectorizable stores to invariant address were not found in loop.
-; RECURSE-NEXT:     SCEV assumptions:
-; RECURSE-EMPTY:
-; RECURSE-NEXT:     Expressions re-written:
 
 ;;;; Derived from the following C code
 ;; void forked_ptrs_different_base_same_offset(float *A, float *B, float *C, int *D) {
@@ -125,6 +106,80 @@ exit:
 ;; }
 
 define dso_local void @forked_ptrs_different_base_same_offset(ptr nocapture readonly nonnull %Base1, ptr nocapture readonly %Base2, ptr nocapture %Dest, ptr nocapture readonly %Preds) {
+; CHECK-LABEL: 'forked_ptrs_different_base_same_offset'
+; CHECK-NEXT:    for.body:
+; CHECK-NEXT:      Memory dependences are safe with run-time checks
+; CHECK-NEXT:      Dependences:
+; CHECK-NEXT:      Run-time memory checks:
+; CHECK-NEXT:      Check 0:
+; CHECK-NEXT:        Comparing group ([[GRP7:0x[0-9a-f]+]]):
+; CHECK-NEXT:          %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
+; CHECK-NEXT:        Against group ([[GRP8:0x[0-9a-f]+]]):
+; CHECK-NEXT:          %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
+; CHECK-NEXT:      Check 1:
+; CHECK-NEXT:        Comparing group ([[GRP7]]):
+; CHECK-NEXT:          %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
+; CHECK-NEXT:        Against group ([[GRP9:0x[0-9a-f]+]]):
+; CHECK-NEXT:          %.sink.in = getelementptr inbounds float, ptr %spec.select, i64 %indvars.iv
+; CHECK-NEXT:      Check 2:
+; CHECK-NEXT:        Comparing group ([[GRP7]]):
+; CHECK-NEXT:          %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
+; CHECK-NEXT:        Against group ([[GRP10:0x[0-9a-f]+]]):
+; CHECK-NEXT:          %.sink.in = getelementptr inbounds float, ptr %spec.select, i64 %indvars.iv
+; CHECK-NEXT:      Grouped accesses:
+; CHECK-NEXT:        Group [[GRP7]]:
+; CHECK-NEXT:          (Low: %Dest High: (400 + %Dest))
+; CHECK-NEXT:            Member: {%Dest,+,4}<nuw><%for.body>
+; CHECK-NEXT:        Group [[GRP8]]:
+; CHECK-NEXT:          (Low: %Preds High: (400 + %Preds))
+; CHECK-NEXT:            Member: {%Preds,+,4}<nuw><%for.body>
+; CHECK-NEXT:        Group [[GRP9]]:
+; CHECK-NEXT:          (Low: %Base2 High: (400 + %Base2))
+; CHECK-NEXT:            Member: {%Base2,+,4}<nw><%for.body>
+; CHECK-NEXT:        Group [[GRP10]]:
+; CHECK-NEXT:          (Low: %Base1 High: (400 + %Base1))
+; CHECK-NEXT:            Member: {%Base1,+,4}<nw><%for.body>
+; CHECK:           Non vectorizable stores to invariant address were not found in loop.
+; CHECK-NEXT:      SCEV assumptions:
+; CHECK:           Expressions re-written:
+;
+; RECURSE-LABEL: 'forked_ptrs_different_base_same_offset'
+; RECURSE-NEXT:    for.body:
+; RECURSE-NEXT:      Memory dependences are safe with run-time checks
+; RECURSE-NEXT:      Dependences:
+; RECURSE-NEXT:      Run-time memory checks:
+; RECURSE-NEXT:      Check 0:
+; RECURSE-NEXT:        Comparing group ([[GRP11:0x[0-9a-f]+]]):
+; RECURSE-NEXT:          %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
+; RECURSE-NEXT:        Against group ([[GRP12:0x[0-9a-f]+]]):
+; RECURSE-NEXT:          %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
+; RECURSE-NEXT:      Check 1:
+; RECURSE-NEXT:        Comparing group ([[GRP11]]):
+; RECURSE-NEXT:          %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
+; RECURSE-NEXT:        Against group ([[GRP13:0x[0-9a-f]+]]):
+; RECURSE-NEXT:          %.sink.in = getelementptr inbounds float, ptr %spec.select, i64 %indvars.iv
+; RECURSE-NEXT:      Check 2:
+; RECURSE-NEXT:        Comparing group ([[GRP11]]):
+; RECURSE-NEXT:          %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
+; RECURSE-NEXT:        Against group ([[GRP14:0x[0-9a-f]+]]):
+; RECURSE-NEXT:          %.sink.in = getelementptr inbounds float, ptr %spec.select, i64 %indvars.iv
+; RECURSE-NEXT:      Grouped accesses:
+; RECURSE-NEXT:        Group [[GRP11]]:
+; RECURSE-NEXT:          (Low: %Dest High: (400 + %Dest))
+; RECURSE-NEXT:            Member: {%Dest,+,4}<nuw><%for.body>
+; RECURSE-NEXT:        Group [[GRP12]]:
+; RECURSE-NEXT:          (Low: %Preds High: (400 + %Preds))
+; RECURSE-NEXT:            Member: {%Preds,+,4}<nuw><%for.body>
+; RECURSE-NEXT:        Group [[GRP13]]:
+; RECURSE-NEXT:          (Low: %Base2 High: (400 + %Base2))
+; RECURSE-NEXT:            Member: {%Base2,+,4}<nw><%for.body>
+; RECURSE-NEXT:        Group [[GRP14]]:
+; RECURSE-NEXT:          (Low: %Base1 High: (400 + %Base1))
+; RECURSE-NEXT:            Member: {%Base1,+,4}<nw><%for.body>
+; RECURSE:           Non vectorizable stores to invariant address were not found in loop.
+; RECURSE-NEXT:      SCEV assumptions:
+; RECURSE:           Expressions re-written:
+;
 entry:
   br label %for.body
 
@@ -146,46 +201,81 @@ for.body:
   br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
 }
 
-; CHECK-LABEL: function 'forked_ptrs_different_base_same_offset_64b':
-; CHECK-NEXT:  for.body:
-; CHECK-NEXT:    Memory dependences are safe with run-time checks
-; CHECK-NEXT:    Dependences:
-; CHECK-NEXT:    Run-time memory checks:
-; CHECK-NEXT:    Check 0:
-; CHECK-NEXT:      Comparing group ([[G1:.+]]):
-; CHECK-NEXT:        %1 = getelementptr inbounds double, ptr %Dest, i64 %indvars.iv
-; CHECK-NEXT:      Against group ([[G2:.+]]):
-; CHECK-NEXT:        %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
-; CHECK-NEXT:    Check 1:
-; CHECK-NEXT:      Comparing group ([[G1]]):
-; CHECK-NEXT:        %1 = getelementptr inbounds double, ptr %Dest, i64 %indvars.iv
-; CHECK-NEXT:      Against group ([[G3:.+]]):
-; CHECK-NEXT:        %.sink.in = getelementptr inbounds double, ptr %spec.select, i64 %indvars.iv
-; CHECK-NEXT:    Check 2:
-; CHECK-NEXT:      Comparing group ([[G1]]):
-; CHECK-NEXT:        %1 = getelementptr inbounds double, ptr %Dest, i64 %indvars.iv
-; CHECK-NEXT:      Against group ([[G4:.+]]):
-; CHECK-NEXT:        %.sink.in = getelementptr inbounds double, ptr %spec.select, i64 %indvars.iv
-; CHECK-NEXT:    Grouped accesses:
-; CHECK-NEXT:      Group [[G1]]:
-; CHECK-NEXT:        (Low: %Dest High: (800 + %Dest))
-; CHECK-NEXT:          Member: {%Dest,+,8}<nuw><%for.body>
-; CHECK-NEXT:      Group [[G2]]:
-; CHECK-NEXT:        (Low: %Preds High: (400 + %Preds))
-; CHECK-NEXT:          Member: {%Preds,+,4}<nuw><%for.body>
-; CHECK-NEXT:      Group [[G3]]:
-; CHECK-NEXT:        (Low: %Base2 High: (800 + %Base2))
-; CHECK-NEXT:          Member: {%Base2,+,8}<nw><%for.body>
-; CHECK-NEXT:      Group [[G4]]:
-; CHECK-NEXT:        (Low: %Base1 High: (800 + %Base1))
-; CHECK-NEXT:          Member: {%Base1,+,8}<nw><%for.body>
-; CHECK-EMPTY:
-; CHECK-NEXT:    Non vectorizable stores to invariant address were not found in loop.
-; CHECK-NEXT:    SCEV assumptions:
-; CHECK-EMPTY:
-; CHECK-NEXT:    Expressions re-written:
-
 define dso_local void @forked_ptrs_different_base_same_offset_64b(ptr nocapture readonly nonnull %Base1, ptr nocapture readonly %Base2, ptr nocapture %Dest, ptr nocapture readonly %Preds) {
+; CHECK-LABEL: 'forked_ptrs_different_base_same_offset_64b'
+; CHECK-NEXT:    for.body:
+; CHECK-NEXT:      Memory dependences are safe with run-time checks
+; CHECK-NEXT:      Dependences:
+; CHECK-NEXT:      Run-time memory checks:
+; CHECK-NEXT:      Check 0:
+; CHECK-NEXT:        Comparing group ([[GRP15:0x[0-9a-f]+]]):
+; CHECK-NEXT:          %1 = getelementptr inbounds double, ptr %Dest, i64 %indvars.iv
+; CHECK-NEXT:        Against group ([[GRP16:0x[0-9a-f]+]]):
+; CHECK-NEXT:          %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
+; CHECK-NEXT:      Check 1:
+; CHECK-NEXT:        Comparing group ([[GRP15]]):
+; CHECK-NEXT:          %1 = getelementptr inbounds double, ptr %Dest, i64 %indvars.iv
+; CHECK-NEXT:        Against group ([[GRP17:0x[0-9a-f]+]]):
+; CHECK-NEXT:          %.sink.in = getelementptr inbounds double, ptr %spec.select, i64 %indvars.iv
+; CHECK-NEXT:      Check 2:
+; CHECK-NEXT:        Comparing group ([[GRP15]]):
+; CHECK-NEXT:          %1 = getelementptr inbounds double, ptr %Dest, i64 %indvars.iv
+; CHECK-NEXT:        Against group ([[GRP18:0x[0-9a-f]+]]):
+; CHECK-NEXT:          %.sink.in = getelementptr inbounds double, ptr %spec.select, i64 %indvars.iv
+; CHECK-NEXT:      Grouped accesses:
+; CHECK-NEXT:        Group [[GRP15]]:
+; CHECK-NEXT:          (Low: %Dest High: (800 + %Dest))
+; CHECK-NEXT:            Member: {%Dest,+,8}<nuw><%for.body>
+; CHECK-NEXT:        Group [[GRP16]]:
+; CHECK-NEXT:          (Low: %Preds High: (400 + %Preds))
+; CHECK-NEXT:            Member: {%Preds,+,4}<nuw><%for.body>
+; CHECK-NEXT:        Group [[GRP17]]:
+; CHECK-NEXT:          (Low: %Base2 High: (800 + %Base2))
+; CHECK-NEXT:            Member: {%Base2,+,8}<nw><%for.body>
+; CHECK-NEXT:        Group [[GRP18]]:
+; CHECK-NEXT:          (Low: %Base1 High: (800 + %Base1))
+; CHECK-NEXT:            Member: {%Base1,+,8}<nw><%for.body>
+; CHECK:           Non vectorizable stores to invariant address were not found in loop.
+; CHECK-NEXT:      SCEV assumptions:
+; CHECK:           Expressions re-written:
+;
+; RECURSE-LABEL: 'forked_ptrs_different_base_same_offset_64b'
+; RECURSE-NEXT:    for.body:
+; RECURSE-NEXT:      Memory dependences are safe with run-time checks
+; RECURSE-NEXT:      Dependences:
+; RECURSE-NEXT:      Run-time memory checks:
+; RECURSE-NEXT:      Check 0:
+; RECURSE-NEXT:        Comparing group ([[GRP19:0x[0-9a-f]+]]):
+; RECURSE-NEXT:          %1 = getelementptr inbounds double, ptr %Dest, i64 %indvars.iv
+; RECURSE-NEXT:        Against group ([[GRP20:0x[0-9a-f]+]]):
+; RECURSE-NEXT:          %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
+; RECURSE-NEXT:      Check 1:
+; RECURSE-NEXT:        Comparing group ([[GRP19]]):
+; RECURSE-NEXT:          %1 = getelementptr inbounds double, ptr %Dest, i64 %indvars.iv
+; RECURSE-NEXT:        Against group ([[GRP21:0x[0-9a-f]+]]):
+; RECURSE-NEXT:          %.sink.in = getelementptr inbounds double, ptr %spec.select, i64 %indvars.iv
+; RECURSE-NEXT:      Check 2:
+; RECURSE-NEXT:        Comparing group ([[GRP19]]):
+; RECURSE-NEXT:          %1 = getelementptr inbounds double, ptr %Dest, i64 %indvars.iv
+; RECURSE-NEXT:        Against group ([[GRP22:0x[0-9a-f]+]]):
+; RECURSE-NEXT:          %.sink.in = getelementptr inbounds double, ptr %spec.select, i64 %indvars.iv
+; RECURSE-NEXT:      Grouped accesses:
+; RECURSE-NEXT:        Group [[GRP19]]:
+; RECURSE-NEXT:          (Low: %Dest High: (800 + %Dest))
+; RECURSE-NEXT:            Member: {%Dest,+,8}<nuw><%for.body>
+; RECURSE-NEXT:        Group [[GRP20]]:
+; RECURSE-NEXT:          (Low: %Preds High: (400 + %Preds))
+; RECURSE-NEXT:            Member: {%Preds,+,4}<nuw><%for.body>
+; RECURSE-NEXT:        Group [[GRP21]]:
+; RECURSE-NEXT:          (Low: %Base2 High: (800 + %Base2))
+; RECURSE-NEXT:            Member: {%Base2,+,8}<nw><%for.body>
+; RECURSE-NEXT:        Group [[GRP22]]:
+; RECURSE-NEXT:          (Low: %Base1 High: (800 + %Base1))
+; RECURSE-NEXT:            Member: {%Base1,+,8}<nw><%for.body>
+; RECURSE:           Non vectorizable stores to invariant address wer...
[truncated]

@artagnon artagnon force-pushed the laa-update-analyze-test branch 3 times, most recently from 4ae2899 to 15b3fa2 Compare September 28, 2023 12:38
@artagnon artagnon requested a review from fhahn September 28, 2023 12:39
Copy link
Member

@jdoerfert jdoerfert left a comment

Choose a reason for hiding this comment

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

Can you update all the test in, for example, llvm/test/Transforms/Attributor and check if there is churn.
clang/test/OpenMP is another good place to check that.

@artagnon
Copy link
Contributor Author

artagnon commented Oct 3, 2023

Can you update all the test in, for example, llvm/test/Transforms/Attributor and check if there is churn.
clang/test/OpenMP is another good place to check that.

There's a very small diff produced when I update all tests in llvm/test/Transforms/Attributor, and it's identical to the diff produced on main. clang/test/OpenMP is trickier, as very few of the tests have been auto-generated by update_cc_test_checks.py: nevertheless, I ran it on a few files by hand, and verified that the diff produced is identical to the one produced on main.

Thanks for suggesting the exercise: I'm now fairly confident that my patch doesn't generate churn.

@artagnon
Copy link
Contributor Author

artagnon commented Oct 6, 2023

Gentle ping.

@artagnon
Copy link
Contributor Author

Gentle ping.

@jdoerfert
Copy link
Member

I'm fine with this, but not a regular user of the analyze script.

update_analyze_test_checks.py is an invaluable tool in updating tests.
Unfortunately, it only supports output from the CostModel,
ScalarEvolution, and LoopVectorize analyses. Many LoopAccessAnalysis
tests use hand-crafted CHECK lines, and it is moreover tedious to
generate these CHECK lines, as the output fom the analysis is not
stable, and requires the test-writer to hand-craft FileCheck matches.
Alleviate this pain, and support output from:

  $ opt -passes='print<loop-accesses>'

This patch includes several non-trivial changes including:

- Preserving whitespace at the beginning of the line, so that the LAA
  output can be properly indented.
- Regexes matching the unstable output, which is basically a pointer
  address hex.
- Separate is_analyze from preserve_names clearly, as the former was
  formerly used as an overload for the latter.

To demonstate the utility of this patch, several tests in
LoopAccessAnalysis have been auto-generated by
update_analyze_test_checks.py.
@artagnon
Copy link
Contributor Author

@fhahn Are you happy with these CHECK-EMPTY lines?

Copy link
Collaborator

@RKSimon RKSimon left a comment

Choose a reason for hiding this comment

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

LGTM - cheers (adding CHECK-EMPTY lines sgtm)

@artagnon artagnon merged commit 4c01a58 into llvm:main Oct 31, 2023
3 checks passed
@artagnon artagnon deleted the laa-update-analyze-test branch October 31, 2023 14:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants