[llvm] [VPlan][UTC] Add `-vplan-print-instance` filter option (PR #211424)

Andrei Elovikov via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 28 08:54:07 PDT 2026


https://github.com/eas updated https://github.com/llvm/llvm-project/pull/211424

>From 9716a5c07a8436fbd4dc633d5e68359231d68c83 Mon Sep 17 00:00:00 2001
From: Andrei Elovikov <andrei.elovikov at sifive.com>
Date: Wed, 22 Jul 2026 15:39:42 -0700
Subject: [PATCH 1/3] [VPlan][UTC] Add `-vplan-print-instance` filter option

Allows to use UTC-generated CHECKs in more tests. Might be helpful in
debugging as well, I was able to use this to narrow down a pass causing
non-deterministic behavior downstream.
---
 .../Transforms/Vectorize/LoopVectorize.cpp    |   5 +
 .../Transforms/Vectorize/VPlanTransforms.h    |  21 +-
 .../VPlan/AArch64/vplan-printing.ll           | 356 +++++++++---------
 .../PowerPC/vplan-force-tail-with-evl.ll      | 129 ++++---
 .../LoopVectorize/VPlan/constant-fold.ll      |  73 +++-
 .../VPlan/vplan-print-instance.ll             |  81 ++++
 6 files changed, 403 insertions(+), 262 deletions(-)
 create mode 100644 llvm/test/Transforms/LoopVectorize/VPlan/vplan-print-instance.ll

diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index f9e4eb45f9783..6a9309a6bed0b 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -382,6 +382,11 @@ cl::opt<bool> llvm::VPlanPrintVectorRegionScope(
     "vplan-print-vector-region-scope", cl::init(false), cl::Hidden,
     cl::desc("Limit VPlan printing to vector loop region in "
              "`-vplan-print-after*` if the plan has one."));
+
+cl::opt<unsigned> llvm::VPlanPrintInstance(
+    "vplan-print-instance", cl::init(0), cl::Hidden,
+    cl::desc("Only print Nth instance of the specified VPlan "
+             "transformation(s), zero - print all instances."));
 #endif
 
 // This flag enables the stress testing of the VPlan H-CFG construction in the
diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.h b/llvm/lib/Transforms/Vectorize/VPlanTransforms.h
index 8e3d29eece7dd..c4e6361540c81 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.h
@@ -22,6 +22,10 @@
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Regex.h"
 
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+#include <map>
+#endif
+
 namespace llvm {
 
 class InductionDescriptor;
@@ -47,6 +51,7 @@ LLVM_ABI_FOR_TEST extern cl::opt<bool> VPlanPrintAfterAll;
 LLVM_ABI_FOR_TEST extern cl::list<std::string> VPlanPrintBeforePasses;
 LLVM_ABI_FOR_TEST extern cl::list<std::string> VPlanPrintAfterPasses;
 LLVM_ABI_FOR_TEST extern cl::opt<bool> VPlanPrintVectorRegionScope;
+LLVM_ABI_FOR_TEST extern cl::opt<unsigned> VPlanPrintInstance;
 #endif
 
 struct VPlanTransforms {
@@ -57,11 +62,19 @@ struct VPlanTransforms {
   static decltype(auto) runPass(StringRef PassName, PassTy &&Pass, VPlan &Plan,
                                 ArgsTy &&...Args) {
 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+    static std::map<
+        std::pair<std::string /* Function */, std::string /* Pass */>, unsigned>
+        PassCounter;
+    StringRef FnName =
+        Plan.getScalarHeader()->getIRBasicBlock()->getParent()->getName();
+    unsigned Instance = ++PassCounter[{FnName.str(), PassName.str()}];
+
     auto PrintPlan = [&](StringRef BeforeOrAfterStr) {
-      dbgs()
-          << "VPlan for loop in '"
-          << Plan.getScalarHeader()->getIRBasicBlock()->getParent()->getName()
-          << "' " << BeforeOrAfterStr << " " << PassName << '\n';
+      if (VPlanPrintInstance != 0 && VPlanPrintInstance != Instance)
+        return;
+
+      dbgs() << "VPlan for loop in '" << FnName << "' " << BeforeOrAfterStr
+             << " " << PassName << '\n';
       if (VPlanPrintVectorRegionScope && Plan.getVectorLoopRegion())
         Plan.getVectorLoopRegion()->print(dbgs());
       else
diff --git a/llvm/test/Transforms/LoopVectorize/VPlan/AArch64/vplan-printing.ll b/llvm/test/Transforms/LoopVectorize/VPlan/AArch64/vplan-printing.ll
index 33b44d49f6be7..88bbd9dfc0f90 100644
--- a/llvm/test/Transforms/LoopVectorize/VPlan/AArch64/vplan-printing.ll
+++ b/llvm/test/Transforms/LoopVectorize/VPlan/AArch64/vplan-printing.ll
@@ -1,4 +1,5 @@
-; RUN: opt -passes=loop-vectorize -debug-only=loop-vectorize -disable-output %s 2>&1 | FileCheck %s
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -passes=loop-vectorize -vplan-print-after=printOptimizedVPlan -vplan-print-instance=3 -disable-output %s 2>&1 | FileCheck %s
 
 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
 target triple = "aarch64-none-unknown-elf"
@@ -6,102 +7,70 @@ target triple = "aarch64-none-unknown-elf"
 ; Tests for printing VPlans that are enabled under AArch64
 
 define i32 @print_partial_reduction(ptr %a, ptr %b) "target-features"="+neon,+dotprod" {
-; CHECK:      VPlan 'Initial VPlan for VF={8,16},UF>=1' {
-; CHECK-NEXT: Live-in vp<[[VF:%.]]> = VF
-; CHECK-NEXT: Live-in vp<[[VFxUF:%.]]> = VF * UF
-; CHECK-NEXT: Live-in vp<[[VEC_TC:%.+]]> = vector-trip-count
-; CHECK-NEXT: Live-in ir<1024> = original trip-count
+; CHECK-LABEL: VPlan for loop in 'print_partial_reduction'
+; CHECK:  VPlan 'Initial VPlan for VF={8,16},UF>=1' {
+; CHECK-NEXT:  Live-in vp<[[VP0:%[0-9]+]]> = VF
+; CHECK-NEXT:  Live-in vp<[[VP1:%[0-9]+]]> = VF * UF
+; CHECK-NEXT:  Live-in vp<[[VP2:%[0-9]+]]> = vector-trip-count
+; CHECK-NEXT:  Live-in ir<1024> = original trip-count
 ; CHECK-EMPTY:
-; CHECK-NEXT: ir-bb<entry>:
-; CHECK-NEXT: Successor(s): scalar.ph, vector.ph
+; CHECK-NEXT:  ir-bb<entry>:
+; CHECK-NEXT:  Successor(s): scalar.ph, vector.ph
 ; CHECK-EMPTY:
-; CHECK-NEXT: vector.ph:
-; CHECK-NEXT:   EMIT vp<[[RDX_START:%.+]]> = reduction-start-vector ir<0>, ir<0>, ir<4>
-; CHECK-NEXT: Successor(s): vector loop
+; CHECK-NEXT:  vector.ph:
+; CHECK-NEXT:    EMIT vp<[[VP3:%[0-9]+]]> = reduction-start-vector ir<0>, ir<0>, ir<4>
+; CHECK-NEXT:  Successor(s): vector loop
 ; CHECK-EMPTY:
-; CHECK-NEXT: <x1> vector loop: {
-; CHECK-NEXT:   vp<[[CAN_IV:%.+]]> = CANONICAL-IV
+; CHECK-NEXT:  <x1> vector loop: {
+; CHECK-NEXT:  vp<[[VP4:%[0-9]+]]> = CANONICAL-IV
 ; CHECK-EMPTY:
-; CHECK-NEXT:   vector.body:
-; CHECK-NEXT:   WIDEN-REDUCTION-PHI ir<[[ACC:%.+]]> = phi (add) vp<[[RDX_START]]>, vp<[[REDUCE:%.+]]> (VF scaled by 1/4)
-; CHECK-NEXT:   vp<[[STEPS:%.+]]> = SCALAR-STEPS vp<[[CAN_IV]]>, ir<1>, vp<[[VF]]>
-; CHECK-NEXT:   CLONE ir<%gep.a> = getelementptr ir<%a>, vp<[[STEPS]]>
-; CHECK-NEXT:   vp<[[PTR_A:%.+]]> = vector-pointer ir<%gep.a>
-; CHECK-NEXT:   WIDEN ir<%load.a> = load vp<[[PTR_A]]>
-; CHECK-NEXT:   CLONE ir<%gep.b> = getelementptr ir<%b>, vp<[[STEPS]]>
-; CHECK-NEXT:   vp<[[PTR_B:%.+]]> = vector-pointer ir<%gep.b>
-; CHECK-NEXT:   WIDEN ir<%load.b> = load vp<[[PTR_B]]>
-; CHECK-NEXT:   EXPRESSION vp<[[REDUCE]]> = ir<[[ACC]]> + partial.reduce.add (mul (ir<%load.b> zext to i32), (ir<%load.a> zext to i32))
-; CHECK-NEXT:   EMIT vp<[[CAN_IV_NEXT:%.+]]> = add nuw vp<[[CAN_IV]]>, vp<[[VFxUF]]>
-; CHECK-NEXT:   EMIT branch-on-count vp<[[CAN_IV_NEXT]]>, vp<[[VEC_TC]]>
-; CHECK-NEXT: No successors
-; CHECK-NEXT: }
-; CHECK-NEXT: Successor(s): middle.block
+; CHECK-NEXT:    vector.body:
+; CHECK-NEXT:      WIDEN-REDUCTION-PHI ir<%accum> = phi (add) vp<[[VP3]]>, vp<[[VP8:%[0-9]+]]> (VF scaled by 1/4)
+; CHECK-NEXT:      vp<[[VP5:%[0-9]+]]> = SCALAR-STEPS vp<[[VP4]]>, ir<1>, vp<[[VP0]]>
+; CHECK-NEXT:      CLONE ir<%gep.a> = getelementptr ir<%a>, vp<[[VP5]]>
+; CHECK-NEXT:      vp<[[VP6:%[0-9]+]]> = vector-pointer ir<%gep.a>, ir<1>
+; CHECK-NEXT:      WIDEN ir<%load.a> = load vp<[[VP6]]>
+; CHECK-NEXT:      CLONE ir<%gep.b> = getelementptr ir<%b>, vp<[[VP5]]>
+; CHECK-NEXT:      vp<[[VP7:%[0-9]+]]> = vector-pointer ir<%gep.b>, ir<1>
+; CHECK-NEXT:      WIDEN ir<%load.b> = load vp<[[VP7]]>
+; CHECK-NEXT:      EXPRESSION vp<[[VP8]]> = ir<%accum> + partial.reduce.add (mul (ir<%load.b> zext to i32), (ir<%load.a> zext to i32))
+; CHECK-NEXT:      EMIT vp<%index.next> = add nuw vp<[[VP4]]>, vp<[[VP1]]>
+; CHECK-NEXT:      EMIT branch-on-count vp<%index.next>, vp<[[VP2]]>
+; CHECK-NEXT:    No successors
+; CHECK-NEXT:  }
+; CHECK-NEXT:  Successor(s): middle.block
 ; CHECK-EMPTY:
-; CHECK-NEXT: middle.block:
-; CHECK-NEXT:   EMIT vp<[[RED_RESULT:%.+]]> = compute-reduction-result (add) vp<[[REDUCE]]>
-; CHECK-NEXT:   EMIT vp<[[CMP:%.+]]> = icmp eq ir<1024>, vp<[[VEC_TC]]>
-; CHECK-NEXT:   EMIT branch-on-cond vp<[[CMP]]>
-; CHECK-NEXT: Successor(s): ir-bb<exit>, scalar.ph
+; CHECK-NEXT:  middle.block:
+; CHECK-NEXT:    EMIT vp<[[VP10:%[0-9]+]]> = compute-reduction-result (add) vp<[[VP8]]>
+; CHECK-NEXT:    EMIT vp<%cmp.n> = icmp eq ir<1024>, vp<[[VP2]]>
+; CHECK-NEXT:    EMIT branch-on-cond vp<%cmp.n>
+; CHECK-NEXT:  Successor(s): ir-bb<exit>, scalar.ph
 ; CHECK-EMPTY:
-; CHECK-NEXT: ir-bb<exit>:
-; CHECK-NEXT:   IR   %add.lcssa = phi i32 [ %add, %for.body ] (extra operand: vp<[[RED_RESULT]]> from middle.block)
-; CHECK-NEXT: No successors
+; CHECK-NEXT:  ir-bb<exit>:
+; CHECK-NEXT:    IR   %add.lcssa = phi i32 [ %add, %for.body ] (extra operand: vp<[[VP10]]> from middle.block)
+; CHECK-NEXT:  No successors
 ; CHECK-EMPTY:
-; CHECK-NEXT: scalar.ph:
-; CHECK-NEXT:   EMIT-SCALAR vp<%bc.resume.val> = phi [ vp<[[VEC_TC]]>, middle.block ], [ ir<0>, ir-bb<entry> ]
-; CHECK-NEXT:   EMIT-SCALAR vp<%bc.merge.rdx> = phi [ vp<[[RED_RESULT]]>, middle.block ], [ ir<0>, ir-bb<entry> ]
-; CHECK-NEXT: Successor(s): ir-bb<for.body>
+; CHECK-NEXT:  scalar.ph:
+; CHECK-NEXT:    EMIT-SCALAR vp<%bc.resume.val> = phi [ vp<[[VP2]]>, middle.block ], [ ir<0>, ir-bb<entry> ]
+; CHECK-NEXT:    EMIT-SCALAR vp<%bc.merge.rdx> = phi [ vp<[[VP10]]>, middle.block ], [ ir<0>, ir-bb<entry> ]
+; CHECK-NEXT:  Successor(s): ir-bb<for.body>
 ; CHECK-EMPTY:
-; CHECK-NEXT: ir-bb<for.body>:
-; CHECK-NEXT:   IR   %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ]
-; CHECK-NEXT:   IR   %accum = phi i32 [ 0, %entry ], [ %add, %for.body ] (extra operand: vp<%bc.merge.rdx> from scalar.ph)
-; CHECK-NEXT:   IR   %gep.a = getelementptr i8, ptr %a, i64 %iv
-; CHECK-NEXT:   IR   %load.a = load i8, ptr %gep.a, align 1
-; CHECK-NEXT:   IR   %ext.a = zext i8 %load.a to i32
-; CHECK-NEXT:   IR   %gep.b = getelementptr i8, ptr %b, i64 %iv
-; CHECK-NEXT:   IR   %load.b = load i8, ptr %gep.b, align 1
-; CHECK-NEXT:   IR   %ext.b = zext i8 %load.b to i32
-; CHECK-NEXT:   IR   %mul = mul i32 %ext.b, %ext.a
-; CHECK-NEXT:   IR   %add = add i32 %mul, %accum
-; CHECK-NEXT:   IR   %iv.next = add i64 %iv, 1
-; CHECK-NEXT:   IR   %exitcond.not = icmp eq i64 %iv.next, 1024
-; CHECK-NEXT: No successors
-; CHECK-NEXT: }
-; CHECK: VPlan 'Final VPlan for VF={8,16},UF={1}' {
-; CHECK-NEXT: Live-in ir<1024> = vector-trip-count
-; CHECK-EMPTY:
-; CHECK-NEXT: ir-bb<entry>:
-; CHECK-NEXT: Successor(s): vector.ph
-; CHECK-EMPTY:
-; CHECK-NEXT: vector.ph:
-; CHECK-NEXT:   EMIT vp<[[RDX_START:%[0-9]+]]> = reduction-start-vector ir<0>, ir<0>, ir<4>
-; CHECK-NEXT: Successor(s): vector.body
-; CHECK-EMPTY:
-; CHECK-NEXT: vector.body:
-; CHECK-NEXT:   EMIT-SCALAR vp<[[EP_IV:%.+]]> = phi [ ir<0>, vector.ph ], [ vp<%index.next>, vector.body ]
-; CHECK-NEXT:   WIDEN-REDUCTION-PHI ir<[[RDX:%.+]]> = phi (add) vp<[[RDX_START]]>, ir<[[RDX_NEXT:%.+]]> (VF scaled by 1/4)
-; CHECK-NEXT:   CLONE ir<%gep.a> = getelementptr ir<%a>, vp<%index>
-; CHECK-NEXT:   WIDEN ir<%load.a> = load ir<%gep.a>
-; CHECK-NEXT:   CLONE ir<%gep.b> = getelementptr ir<%b>, vp<%index>
-; CHECK-NEXT:   WIDEN ir<%load.b> = load ir<%gep.b>
-; CHECK-NEXT:   WIDEN-CAST ir<%ext.b> = zext ir<%load.b> to i32
-; CHECK-NEXT:   WIDEN-CAST ir<%ext.a> = zext ir<%load.a> to i32
-; CHECK-NEXT:   WIDEN ir<%mul> = mul ir<%ext.b>, ir<%ext.a>
-; CHECK-NEXT:   PARTIAL-REDUCE ir<[[RDX_NEXT]]> = ir<[[RDX]]> + reduce.add (ir<%mul>)
-; CHECK-NEXT:   EMIT vp<[[EP_IV_NEXT:%.+]]> = add nuw vp<[[EP_IV]]>, ir<16>
-; CHECK-NEXT:   EMIT vp<{{%.+}}> = icmp eq vp<%index.next>, ir<1024>
-; CHECK-NEXT:   EMIT branch-on-cond vp<{{%.+}}>
-; CHECK-NEXT: Successor(s): middle.block, vector.body
-; CHECK-EMPTY:
-; CHECK-NEXT: middle.block:
-; CHECK-NEXT:   EMIT vp<[[RED_RESULT:%[0-9]+]]> = compute-reduction-result (add) ir<[[RDX_NEXT]]>
-; CHECK-NEXT: Successor(s): ir-bb<exit>
-; CHECK-EMPTY:
-; CHECK-NEXT: ir-bb<exit>:
-; CHECK-NEXT:   IR   %add.lcssa = phi i32 [ %add, %for.body ] (extra operand: vp<[[RED_RESULT]]> from middle.block)
-; CHECK-NEXT: No successors
-; CHECK-NEXT: }
+; CHECK-NEXT:  ir-bb<for.body>:
+; CHECK-NEXT:    IR   %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ] (extra operand: vp<%bc.resume.val> from scalar.ph)
+; CHECK-NEXT:    IR   %accum = phi i32 [ 0, %entry ], [ %add, %for.body ] (extra operand: vp<%bc.merge.rdx> from scalar.ph)
+; CHECK-NEXT:    IR   %gep.a = getelementptr i8, ptr %a, i64 %iv
+; CHECK-NEXT:    IR   %load.a = load i8, ptr %gep.a, align 1
+; CHECK-NEXT:    IR   %ext.a = zext i8 %load.a to i32
+; CHECK-NEXT:    IR   %gep.b = getelementptr i8, ptr %b, i64 %iv
+; CHECK-NEXT:    IR   %load.b = load i8, ptr %gep.b, align 1
+; CHECK-NEXT:    IR   %ext.b = zext i8 %load.b to i32
+; CHECK-NEXT:    IR   %mul = mul i32 %ext.b, %ext.a
+; CHECK-NEXT:    IR   %add = add i32 %mul, %accum
+; CHECK-NEXT:    IR   %iv.next = add i64 %iv, 1
+; CHECK-NEXT:    IR   %exitcond.not = icmp eq i64 %iv.next, 1024
+; CHECK-NEXT:  No successors
+; CHECK-NEXT:  }
+;
 entry:
   br label %for.body
 
@@ -126,50 +95,71 @@ exit:
 
 ; Test that we also get VPExpressions when there is predication.
 define i32 @print_partial_reduction_predication(ptr %a, ptr %b, i64 %N) "target-features"="+sve" {
-; CHECK: VPlan 'Initial VPlan for VF={8,16},UF>=1' {
-; CHECK-NEXT: Live-in vp<[[VF:%[0-9]+]]> = VF
-; CHECK-NEXT: Live-in vp<[[VFxUF:%[0-9]+]]> = VF * UF
-; CHECK-NEXT: Live-in ir<%N> = original trip-count
+; CHECK-LABEL: VPlan for loop in 'print_partial_reduction_predication'
+; CHECK:  VPlan 'Initial VPlan for VF={8,16},UF>=1' {
+; CHECK-NEXT:  Live-in vp<[[VP0:%[0-9]+]]> = VF
+; CHECK-NEXT:  Live-in vp<[[VP1:%[0-9]+]]> = VF * UF
+; CHECK-NEXT:  Live-in ir<%N> = original trip-count
+; CHECK-EMPTY:
+; CHECK-NEXT:  ir-bb<entry>:
+; CHECK-NEXT:  Successor(s): scalar.ph, vector.ph
+; CHECK-EMPTY:
+; CHECK-NEXT:  vector.ph:
+; CHECK-NEXT:    EMIT vp<[[VP3:%[0-9]+]]> = reduction-start-vector ir<0>, ir<0>, ir<4>
+; CHECK-NEXT:    EMIT vp<%index.part.next> = VF * Part + ir<0>, vp<[[VP0]]>
+; CHECK-NEXT:    EMIT vp<%active.lane.mask.entry> = active lane mask vp<%index.part.next>, ir<%N>, ir<1>
+; CHECK-NEXT:  Successor(s): vector loop
 ; CHECK-EMPTY:
-; CHECK-NEXT: ir-bb<entry>:
-; CHECK-NEXT: Successor(s): scalar.ph, vector.ph
+; CHECK-NEXT:  <x1> vector loop: {
+; CHECK-NEXT:  vp<[[VP4:%[0-9]+]]> = CANONICAL-IV
 ; CHECK-EMPTY:
-; CHECK-NEXT: vector.ph:
-; CHECK-NEXT:   EMIT vp<[[RDX_START:%[0-9]+]]> = reduction-start-vector ir<0>, ir<0>, ir<4>
-; CHECK-NEXT:   EMIT vp<%index.part.next> = VF * Part + ir<0>
-; CHECK-NEXT:   EMIT vp<%active.lane.mask.entry> = active lane mask vp<%index.part.next>, ir<%N>, ir<1>
-; CHECK-NEXT: Successor(s): vector loop
+; CHECK-NEXT:    vector.body:
+; CHECK-NEXT:      ACTIVE-LANE-MASK-PHI vp<[[VP6:%[0-9]+]]> = phi vp<%active.lane.mask.entry>, vp<%active.lane.mask.next>
+; CHECK-NEXT:      WIDEN-REDUCTION-PHI ir<%accum> = phi (add) vp<[[VP3]]>, vp<[[VP10:%[0-9]+]]> (VF scaled by 1/4)
+; CHECK-NEXT:      vp<[[VP7:%[0-9]+]]> = SCALAR-STEPS vp<[[VP4]]>, ir<1>, vp<[[VP0]]>
+; CHECK-NEXT:      CLONE ir<%gep.a> = getelementptr ir<%a>, vp<[[VP7]]>
+; CHECK-NEXT:      vp<[[VP8:%[0-9]+]]> = vector-pointer ir<%gep.a>, ir<1>
+; CHECK-NEXT:      WIDEN ir<%load.a> = load vp<[[VP8]]>, vp<[[VP6]]>
+; CHECK-NEXT:      CLONE ir<%gep.b> = getelementptr ir<%b>, vp<[[VP7]]>
+; CHECK-NEXT:      vp<[[VP9:%[0-9]+]]> = vector-pointer ir<%gep.b>, ir<1>
+; CHECK-NEXT:      WIDEN ir<%load.b> = load vp<[[VP9]]>, vp<[[VP6]]>
+; CHECK-NEXT:      EXPRESSION vp<[[VP10]]> = ir<%accum> + partial.reduce.add (mul (ir<%load.b> zext to i32), (ir<%load.a> zext to i32), vp<[[VP6]]>)
+; CHECK-NEXT:      EMIT vp<%index.next> = add vp<[[VP4]]>, vp<[[VP1]]>
+; CHECK-NEXT:      EMIT vp<[[VP11:%[0-9]+]]> = VF * Part + vp<%index.next>, vp<[[VP0]]>
+; CHECK-NEXT:      EMIT vp<%active.lane.mask.next> = active lane mask vp<[[VP11]]>, ir<%N>, ir<1>
+; CHECK-NEXT:      EMIT vp<[[VP12:%[0-9]+]]> = not vp<%active.lane.mask.next>
+; CHECK-NEXT:      EMIT branch-on-cond vp<[[VP12]]>
+; CHECK-NEXT:    No successors
+; CHECK-NEXT:  }
+; CHECK-NEXT:  Successor(s): middle.block
 ; CHECK-EMPTY:
-; CHECK-NEXT: <x1> vector loop: {
-; CHECK-NEXT:   vp<[[CAN_IV:%.+]]> = CANONICAL-IV
+; CHECK-NEXT:  middle.block:
+; CHECK-NEXT:    EMIT vp<[[VP14:%[0-9]+]]> = compute-reduction-result (add) vp<[[VP10]]>
+; CHECK-NEXT:  Successor(s): ir-bb<exit>
 ; CHECK-EMPTY:
-; CHECK-NEXT:   vector.body:
-; CHECK-NEXT:     ACTIVE-LANE-MASK-PHI vp<[[MASK:%[0-9]+]]> = phi vp<%active.lane.mask.entry>, vp<%active.lane.mask.next>
-; CHECK-NEXT:     WIDEN-REDUCTION-PHI ir<%accum> = phi (add) vp<[[RDX_START]]>, vp<[[REDUCE:%[0-9]+]]> (VF scaled by 1/4)
-; CHECK-NEXT:     vp<[[STEPS:%[0-9]+]]> = SCALAR-STEPS vp<[[CAN_IV]]>, ir<1>, vp<[[VF]]>
-; CHECK-NEXT:     CLONE ir<%gep.a> = getelementptr ir<%a>, vp<[[STEPS]]>
-; CHECK-NEXT:     vp<[[PTR_A:%[0-9]+]]> = vector-pointer ir<%gep.a>
-; CHECK-NEXT:     WIDEN ir<%load.a> = load vp<[[PTR_A]]>, vp<[[MASK]]>
-; CHECK-NEXT:     CLONE ir<%gep.b> = getelementptr ir<%b>, vp<[[STEPS]]>
-; CHECK-NEXT:     vp<[[PTR_B:%[0-9]+]]> = vector-pointer ir<%gep.b>
-; CHECK-NEXT:     WIDEN ir<%load.b> = load vp<[[PTR_B]]>, vp<[[MASK]]>
-; CHECK-NEXT:     EXPRESSION vp<[[REDUCE]]> = ir<%accum> + partial.reduce.add (mul (ir<%load.b> zext to i32), (ir<%load.a> zext to i32), vp<[[MASK]]>)
-; CHECK-NEXT:     EMIT vp<%index.next> = add vp<[[CAN_IV]]>, vp<[[VFxUF]]>
-; CHECK-NEXT:     EMIT vp<[[PART_IDX:%[0-9]+]]> = VF * Part + vp<%index.next>, vp<[[VF]]>
-; CHECK-NEXT:     EMIT vp<%active.lane.mask.next> = active lane mask vp<[[PART_IDX]]>, ir<%N>, ir<1>
-; CHECK-NEXT:     EMIT vp<[[NOT_MASK:%[0-9]+]]> = not vp<%active.lane.mask.next>
-; CHECK-NEXT:     EMIT branch-on-cond vp<[[NOT_MASK]]>
-; CHECK-NEXT:   No successors
-; CHECK-NEXT: }
-; CHECK-NEXT: Successor(s): middle.block
+; CHECK-NEXT:  ir-bb<exit>:
+; CHECK-NEXT:    IR   %add.lcssa = phi i32 [ %add, %for.body ] (extra operand: vp<[[VP14]]> from middle.block)
+; CHECK-NEXT:  No successors
 ; CHECK-EMPTY:
-; CHECK-NEXT: middle.block:
-; CHECK-NEXT:   EMIT vp<[[RED_RESULT:%[0-9]+]]> = compute-reduction-result (add) vp<[[REDUCE]]>
-; CHECK-NEXT: Successor(s): ir-bb<exit>
+; CHECK-NEXT:  scalar.ph:
+; CHECK-NEXT:  Successor(s): ir-bb<for.body>
 ; CHECK-EMPTY:
-; CHECK-NEXT: ir-bb<exit>:
-; CHECK-NEXT:   IR   %add.lcssa = phi i32 [ %add, %for.body ] (extra operand: vp<[[RED_RESULT]]> from middle.block)
-; CHECK-NEXT: No successors
+; CHECK-NEXT:  ir-bb<for.body>:
+; CHECK-NEXT:    IR   %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ] (extra operand: ir<0> from scalar.ph)
+; CHECK-NEXT:    IR   %accum = phi i32 [ 0, %entry ], [ %add, %for.body ] (extra operand: ir<0> from scalar.ph)
+; CHECK-NEXT:    IR   %gep.a = getelementptr i8, ptr %a, i64 %iv
+; CHECK-NEXT:    IR   %load.a = load i8, ptr %gep.a, align 1
+; CHECK-NEXT:    IR   %ext.a = zext i8 %load.a to i32
+; CHECK-NEXT:    IR   %gep.b = getelementptr i8, ptr %b, i64 %iv
+; CHECK-NEXT:    IR   %load.b = load i8, ptr %gep.b, align 1
+; CHECK-NEXT:    IR   %ext.b = zext i8 %load.b to i32
+; CHECK-NEXT:    IR   %mul = mul i32 %ext.b, %ext.a
+; CHECK-NEXT:    IR   %add = add i32 %mul, %accum
+; CHECK-NEXT:    IR   %iv.next = add i64 %iv, 1
+; CHECK-NEXT:    IR   %exitcond.not = icmp eq i64 %iv.next, %N
+; CHECK-NEXT:  No successors
+; CHECK-NEXT:  }
+;
 entry:
   br label %for.body
 
@@ -193,69 +183,71 @@ exit:
 }
 
 define i32 @print_partial_reduction_ext_mul(ptr %a, ptr %b) "target-features"="+neon,+dotprod" {
-; CHECK:      VPlan 'Initial VPlan for VF={8,16},UF>=1' {
-; CHECK-NEXT: Live-in vp<[[VF:%.]]> = VF
-; CHECK-NEXT: Live-in vp<[[VFxUF:%.]]> = VF * UF
-; CHECK-NEXT: Live-in vp<[[VEC_TC:%.+]]> = vector-trip-count
-; CHECK-NEXT: Live-in ir<1024> = original trip-count
+; CHECK-LABEL: VPlan for loop in 'print_partial_reduction_ext_mul'
+; CHECK:  VPlan 'Initial VPlan for VF={8,16},UF>=1' {
+; CHECK-NEXT:  Live-in vp<[[VP0:%[0-9]+]]> = VF
+; CHECK-NEXT:  Live-in vp<[[VP1:%[0-9]+]]> = VF * UF
+; CHECK-NEXT:  Live-in vp<[[VP2:%[0-9]+]]> = vector-trip-count
+; CHECK-NEXT:  Live-in ir<1024> = original trip-count
 ; CHECK-EMPTY:
-; CHECK-NEXT: ir-bb<entry>:
-; CHECK-NEXT: Successor(s): scalar.ph, vector.ph
+; CHECK-NEXT:  ir-bb<entry>:
+; CHECK-NEXT:  Successor(s): scalar.ph, vector.ph
 ; CHECK-EMPTY:
-; CHECK-NEXT: vector.ph:
-; CHECK-NEXT:   EMIT vp<[[RDX_START:%.+]]> = reduction-start-vector ir<0>, ir<0>, ir<4>
-; CHECK-NEXT: Successor(s): vector loop
+; CHECK-NEXT:  vector.ph:
+; CHECK-NEXT:    EMIT vp<[[VP3:%[0-9]+]]> = reduction-start-vector ir<0>, ir<0>, ir<4>
+; CHECK-NEXT:  Successor(s): vector loop
 ; CHECK-EMPTY:
-; CHECK-NEXT: <x1> vector loop: {
-; CHECK-NEXT:   vp<[[CAN_IV:%.+]]> = CANONICAL-IV
+; CHECK-NEXT:  <x1> vector loop: {
+; CHECK-NEXT:  vp<[[VP4:%[0-9]+]]> = CANONICAL-IV
 ; CHECK-EMPTY:
-; CHECK-NEXT: vector.body:
-; CHECK-NEXT:   WIDEN-REDUCTION-PHI ir<[[ACC:%.+]]> = phi (add) vp<[[RDX_START]]>, vp<[[REDUCE:%.+]]> (VF scaled by 1/4)
-; CHECK-NEXT:   vp<[[STEPS:%.+]]> = SCALAR-STEPS vp<[[CAN_IV]]>, ir<1>, vp<[[VF]]>
-; CHECK-NEXT:   CLONE ir<%gep.a> = getelementptr ir<%a>, vp<[[STEPS]]>
-; CHECK-NEXT:   vp<[[PTR_A:%.+]]> = vector-pointer ir<%gep.a>
-; CHECK-NEXT:   WIDEN ir<%load.a> = load vp<[[PTR_A]]>
-; CHECK-NEXT:   CLONE ir<%gep.b> = getelementptr ir<%b>, vp<[[STEPS]]>
-; CHECK-NEXT:   vp<[[PTR_B:%.+]]> = vector-pointer ir<%gep.b>
-; CHECK-NEXT:   WIDEN ir<%load.b> = load vp<[[PTR_B]]>
-; CHECK-NEXT:   EXPRESSION vp<[[REDUCE]]> = ir<[[ACC]]> + partial.reduce.add (mul (ir<%load.b> zext to i32), (ir<%load.a> zext to i32))
-; CHECK-NEXT:   EMIT vp<[[CAN_IV_NEXT:%.+]]> = add nuw vp<[[CAN_IV]]>, vp<[[VFxUF]]>
-; CHECK-NEXT:   EMIT branch-on-count vp<[[CAN_IV_NEXT]]>, vp<[[VEC_TC]]>
-; CHECK-NEXT: No successors
-; CHECK-NEXT: }
-; CHECK-NEXT: Successor(s): middle.block
+; CHECK-NEXT:    vector.body:
+; CHECK-NEXT:      WIDEN-REDUCTION-PHI ir<%accum> = phi (add) vp<[[VP3]]>, vp<[[VP8:%[0-9]+]]> (VF scaled by 1/4)
+; CHECK-NEXT:      vp<[[VP5:%[0-9]+]]> = SCALAR-STEPS vp<[[VP4]]>, ir<1>, vp<[[VP0]]>
+; CHECK-NEXT:      CLONE ir<%gep.a> = getelementptr ir<%a>, vp<[[VP5]]>
+; CHECK-NEXT:      vp<[[VP6:%[0-9]+]]> = vector-pointer ir<%gep.a>, ir<1>
+; CHECK-NEXT:      WIDEN ir<%load.a> = load vp<[[VP6]]>
+; CHECK-NEXT:      CLONE ir<%gep.b> = getelementptr ir<%b>, vp<[[VP5]]>
+; CHECK-NEXT:      vp<[[VP7:%[0-9]+]]> = vector-pointer ir<%gep.b>, ir<1>
+; CHECK-NEXT:      WIDEN ir<%load.b> = load vp<[[VP7]]>
+; CHECK-NEXT:      EXPRESSION vp<[[VP8]]> = ir<%accum> + partial.reduce.add (mul (ir<%load.b> zext to i32), (ir<%load.a> zext to i32))
+; CHECK-NEXT:      EMIT vp<%index.next> = add nuw vp<[[VP4]]>, vp<[[VP1]]>
+; CHECK-NEXT:      EMIT branch-on-count vp<%index.next>, vp<[[VP2]]>
+; CHECK-NEXT:    No successors
+; CHECK-NEXT:  }
+; CHECK-NEXT:  Successor(s): middle.block
 ; CHECK-EMPTY:
-; CHECK-NEXT: middle.block:
-; CHECK-NEXT:   EMIT vp<[[RED_RESULT:%.+]]> = compute-reduction-result (add) vp<[[REDUCE]]>
-; CHECK-NEXT:   EMIT vp<[[CMP:%.+]]> = icmp eq ir<1024>, vp<[[VEC_TC]]>
-; CHECK-NEXT:   EMIT branch-on-cond vp<[[CMP]]>
-; CHECK-NEXT: Successor(s): ir-bb<exit>, scalar.ph
+; CHECK-NEXT:  middle.block:
+; CHECK-NEXT:    EMIT vp<[[VP10:%[0-9]+]]> = compute-reduction-result (add) vp<[[VP8]]>
+; CHECK-NEXT:    EMIT vp<%cmp.n> = icmp eq ir<1024>, vp<[[VP2]]>
+; CHECK-NEXT:    EMIT branch-on-cond vp<%cmp.n>
+; CHECK-NEXT:  Successor(s): ir-bb<exit>, scalar.ph
 ; CHECK-EMPTY:
-; CHECK-NEXT: ir-bb<exit>:
-; CHECK-NEXT:   IR   %add.lcssa = phi i32 [ %add, %for.body ] (extra operand: vp<[[RED_RESULT]]> from middle.block)
-; CHECK-NEXT: No successors
+; CHECK-NEXT:  ir-bb<exit>:
+; CHECK-NEXT:    IR   %add.lcssa = phi i32 [ %add, %for.body ] (extra operand: vp<[[VP10]]> from middle.block)
+; CHECK-NEXT:  No successors
 ; CHECK-EMPTY:
-; CHECK-NEXT: scalar.ph:
-; CHECK-NEXT:   EMIT-SCALAR vp<%bc.resume.val> = phi [ vp<[[VEC_TC]]>, middle.block ], [ ir<0>, ir-bb<entry> ]
-; CHECK-NEXT:   EMIT-SCALAR vp<%bc.merge.rdx> = phi [ vp<[[RED_RESULT]]>, middle.block ], [ ir<0>, ir-bb<entry> ]
-; CHECK-NEXT: Successor(s): ir-bb<for.body>
+; CHECK-NEXT:  scalar.ph:
+; CHECK-NEXT:    EMIT-SCALAR vp<%bc.resume.val> = phi [ vp<[[VP2]]>, middle.block ], [ ir<0>, ir-bb<entry> ]
+; CHECK-NEXT:    EMIT-SCALAR vp<%bc.merge.rdx> = phi [ vp<[[VP10]]>, middle.block ], [ ir<0>, ir-bb<entry> ]
+; CHECK-NEXT:  Successor(s): ir-bb<for.body>
 ; CHECK-EMPTY:
-; CHECK-NEXT: ir-bb<for.body>:
-; CHECK-NEXT:   IR   %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ]
-; CHECK-NEXT:   IR   %accum = phi i32 [ 0, %entry ], [ %add, %for.body ] (extra operand: vp<%bc.merge.rdx> from scalar.ph)
-; CHECK-NEXT:   IR   %gep.a = getelementptr i8, ptr %a, i64 %iv
-; CHECK-NEXT:   IR   %load.a = load i8, ptr %gep.a, align 1
-; CHECK-NEXT:   IR   %ext.a = zext i8 %load.a to i16
-; CHECK-NEXT:   IR   %gep.b = getelementptr i8, ptr %b, i64 %iv
-; CHECK-NEXT:   IR   %load.b = load i8, ptr %gep.b, align 1
-; CHECK-NEXT:   IR   %ext.b = zext i8 %load.b to i16
-; CHECK-NEXT:   IR   %mul = mul i16 %ext.b, %ext.a
-; CHECK-NEXT:   IR   %mul.ext = zext i16 %mul to i32
-; CHECK-NEXT:   IR   %add = add i32 %mul.ext, %accum
-; CHECK-NEXT:   IR   %iv.next = add i64 %iv, 1
-; CHECK-NEXT:   IR   %exitcond.not = icmp eq i64 %iv.next, 1024
-; CHECK-NEXT: No successors
-; CHECK-NEXT: }
+; CHECK-NEXT:  ir-bb<for.body>:
+; CHECK-NEXT:    IR   %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ] (extra operand: vp<%bc.resume.val> from scalar.ph)
+; CHECK-NEXT:    IR   %accum = phi i32 [ 0, %entry ], [ %add, %for.body ] (extra operand: vp<%bc.merge.rdx> from scalar.ph)
+; CHECK-NEXT:    IR   %gep.a = getelementptr i8, ptr %a, i64 %iv
+; CHECK-NEXT:    IR   %load.a = load i8, ptr %gep.a, align 1
+; CHECK-NEXT:    IR   %ext.a = zext i8 %load.a to i16
+; CHECK-NEXT:    IR   %gep.b = getelementptr i8, ptr %b, i64 %iv
+; CHECK-NEXT:    IR   %load.b = load i8, ptr %gep.b, align 1
+; CHECK-NEXT:    IR   %ext.b = zext i8 %load.b to i16
+; CHECK-NEXT:    IR   %mul = mul i16 %ext.b, %ext.a
+; CHECK-NEXT:    IR   %mul.ext = zext i16 %mul to i32
+; CHECK-NEXT:    IR   %add = add i32 %mul.ext, %accum
+; CHECK-NEXT:    IR   %iv.next = add i64 %iv, 1
+; CHECK-NEXT:    IR   %exitcond.not = icmp eq i64 %iv.next, 1024
+; CHECK-NEXT:  No successors
+; CHECK-NEXT:  }
+;
 entry:
   br label %for.body
 
diff --git a/llvm/test/Transforms/LoopVectorize/VPlan/PowerPC/vplan-force-tail-with-evl.ll b/llvm/test/Transforms/LoopVectorize/VPlan/PowerPC/vplan-force-tail-with-evl.ll
index c6c36f3c103a7..56f2da2d50047 100644
--- a/llvm/test/Transforms/LoopVectorize/VPlan/PowerPC/vplan-force-tail-with-evl.ll
+++ b/llvm/test/Transforms/LoopVectorize/VPlan/PowerPC/vplan-force-tail-with-evl.ll
@@ -1,56 +1,59 @@
-; RUN: opt -passes=loop-vectorize -vplan-print-after=printOptimizedVPlan \
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --filter-out-after "middle.block" --version 6
+; RUN: opt -passes=loop-vectorize -vplan-print-after=printOptimizedVPlan -vplan-print-instance=2 \
 ; RUN: -force-tail-folding-style=data-with-evl \
 ; RUN: -tail-folding-policy=must-fold-tail \
 ; RUN: -mtriple=powerpc64le-unknown-linux-gnu \
 ; RUN: -mcpu=pwr10 -disable-output < %s 2>&1 | FileCheck %s
 
 define void @foo(ptr noalias %a, ptr noalias %b, ptr noalias %c, i64 %N) {
-; CHECK-LABEL: VPlan 'Initial VPlan for VF={2,4},UF>=1' {
-; CHECK-NEXT: Live-in vp<[[VF:%.+]]> = VF
-; CHECK-NEXT: Live-in vp<[[VFxUF:%.+]]> = VF * UF
-; CHECK-NEXT: Live-in vp<[[VTC:%.+]]> = vector-trip-count
-; CHECK-NEXT: Live-in vp<[[BTC:%.+]]> = backedge-taken count
+; CHECK-LABEL: VPlan for loop in 'foo'
+; CHECK:  VPlan 'Initial VPlan for VF={2,4},UF>=1' {
+; CHECK-NEXT:  Live-in vp<[[VP0:%[0-9]+]]> = VF
+; CHECK-NEXT:  Live-in vp<[[VP1:%[0-9]+]]> = VF * UF
+; CHECK-NEXT:  Live-in vp<[[VP2:%[0-9]+]]> = vector-trip-count
+; CHECK-NEXT:  Live-in vp<[[VP3:%[0-9]+]]> = backedge-taken count
 ; CHECK-EMPTY:
-; CHECK-NEXT: ir-bb<entry>:
-; CHECK-NEXT: Successor(s): scalar.ph, vector.ph
+; CHECK-NEXT:  ir-bb<entry>:
+; CHECK-NEXT:  Successor(s): scalar.ph, vector.ph
 ; CHECK-EMPTY:
-; CHECK-NEXT: vector.ph:
-; CHECK-NEXT: Successor(s): vector loop
+; CHECK-NEXT:  vector.ph:
+; CHECK-NEXT:  Successor(s): vector loop
 ; CHECK-EMPTY:
-; CHECK-NEXT: <x1> vector loop: {
-; CHECK-NEXT:   vp<[[CAN_IV:%.+]]> = CANONICAL-IV
+; CHECK-NEXT:  <x1> vector loop: {
+; CHECK-NEXT:  vp<[[VP4:%[0-9]+]]> = CANONICAL-IV
 ; CHECK-EMPTY:
-; CHECK-NEXT:   vector.body:
-; CHECK-NEXT:     EMIT vp<[[WIDEN_CAN_IV:%.+]]> = WIDEN-CANONICAL-INDUCTION nuw vp<[[CAN_IV]]>
-; CHECK-NEXT:     EMIT vp<[[CMP:%.+]]> = icmp ule vp<[[WIDEN_CAN_IV]]>, vp<[[BTC]]>
-; CHECK-NEXT:   Successor(s): pred.store
+; CHECK-NEXT:    vector.body:
+; CHECK-NEXT:      EMIT vp<[[VP6:%[0-9]+]]> = WIDEN-CANONICAL-INDUCTION nuw vp<[[VP4]]>
+; CHECK-NEXT:      EMIT vp<[[VP7:%[0-9]+]]> = icmp ule vp<[[VP6]]>, vp<[[VP3]]>
+; CHECK-NEXT:    Successor(s): pred.store
 ; CHECK-EMPTY:
-; CHECK-NEXT:  <xVFxUF> pred.store: {
-; CHECK-NEXT:    pred.store.entry:
-; CHECK-NEXT:      BRANCH-ON-MASK vp<[[CMP]]>
-; CHECK-NEXT:    Successor(s): pred.store.if, pred.store.continue
+; CHECK-NEXT:    <xVFxUF> pred.store: {
+; CHECK-NEXT:      pred.store.entry:
+; CHECK-NEXT:        BRANCH-ON-MASK vp<[[VP7]]>
+; CHECK-NEXT:      Successor(s): pred.store.if, pred.store.continue
 ; CHECK-EMPTY:
-; CHECK-NEXT:    pred.store.if:
-; CHECK-NEXT:      vp<[[STEPS:%.+]]> = SCALAR-STEPS vp<[[CAN_IV]]>, ir<1>, vp<[[VF]]>
-; CHECK-NEXT:      REPLICATE ir<%arrayidx> = getelementptr inbounds ir<%b>, vp<[[STEPS]]>
-; CHECK-NEXT:      REPLICATE ir<%0> = load ir<%arrayidx>
-; CHECK-NEXT:      REPLICATE ir<%arrayidx2> = getelementptr inbounds ir<%c>, vp<[[STEPS]]>
-; CHECK-NEXT:      REPLICATE ir<%1> = load ir<%arrayidx2>
-; CHECK-NEXT:      REPLICATE ir<%arrayidx4> = getelementptr inbounds ir<%a>, vp<[[STEPS]]>
-; CHECK-NEXT:      REPLICATE ir<%add> = add nsw ir<%1>, ir<%0>
-; CHECK-NEXT:      REPLICATE store ir<%add>, ir<%arrayidx4>
-; CHECK-NEXT:    Successor(s): pred.store.continue
+; CHECK-NEXT:      pred.store.if:
+; CHECK-NEXT:        vp<[[VP8:%[0-9]+]]> = SCALAR-STEPS vp<[[VP4]]>, ir<1>, vp<[[VP0]]>
+; CHECK-NEXT:        REPLICATE ir<%arrayidx> = getelementptr inbounds ir<%b>, vp<[[VP8]]>
+; CHECK-NEXT:        REPLICATE ir<%0> = load ir<%arrayidx>
+; CHECK-NEXT:        REPLICATE ir<%arrayidx2> = getelementptr inbounds ir<%c>, vp<[[VP8]]>
+; CHECK-NEXT:        REPLICATE ir<%1> = load ir<%arrayidx2>
+; CHECK-NEXT:        REPLICATE ir<%arrayidx4> = getelementptr inbounds ir<%a>, vp<[[VP8]]>
+; CHECK-NEXT:        REPLICATE ir<%add> = add nsw ir<%1>, ir<%0>
+; CHECK-NEXT:        REPLICATE store ir<%add>, ir<%arrayidx4>
+; CHECK-NEXT:      Successor(s): pred.store.continue
 ; CHECK-EMPTY:
-; CHECK-NEXT:    pred.store.continue:
+; CHECK-NEXT:      pred.store.continue:
+; CHECK-NEXT:      No successors
+; CHECK-NEXT:    }
+; CHECK-NEXT:    Successor(s): for.body.2
+; CHECK-EMPTY:
+; CHECK-NEXT:    for.body.2:
+; CHECK-NEXT:      EMIT vp<%index.next> = add vp<[[VP4]]>, vp<[[VP1]]>
+; CHECK-NEXT:      EMIT branch-on-count vp<%index.next>, vp<[[VP2]]>
 ; CHECK-NEXT:    No successors
 ; CHECK-NEXT:  }
-; CHECK-NEXT:  Successor(s): for.body.2
-; CHECK-EMPTY:
-; CHECK-NEXT:  for.body.2:
-; CHECK-NEXT:     EMIT vp<[[CAN_INC:%.+]]> = add vp<[[CAN_IV]]>, vp<[[VFxUF]]>
-; CHECK-NEXT:     EMIT branch-on-count vp<[[CAN_INC]]>, vp<[[VTC]]>
-; CHECK-NEXT:   No successors
-; CHECK-NEXT: }
+; CHECK-NEXT:  Successor(s): middle.block
 ;
 entry:
   br label %for.body
@@ -73,34 +76,36 @@ for.cond.cleanup:
 }
 
 define void @safe_dep(ptr %p) {
-; CHECK-LABEL: VPlan 'Initial VPlan for VF={2},UF>=1' {
-; CHECK-NEXT: Live-in vp<[[VF:%.+]]> = VF
-; CHECK-NEXT: Live-in vp<[[VFxUF:%.+]]> = VF * UF
-; CHECK-NEXT: Live-in vp<[[VTC:%.+]]> = vector-trip-count
-; CHECK-NEXT: Live-in ir<512> = original trip-count
+; CHECK-LABEL: VPlan for loop in 'safe_dep'
+; CHECK:  VPlan 'Initial VPlan for VF={2},UF>=1' {
+; CHECK-NEXT:  Live-in vp<[[VP0:%[0-9]+]]> = VF
+; CHECK-NEXT:  Live-in vp<[[VP1:%[0-9]+]]> = VF * UF
+; CHECK-NEXT:  Live-in vp<[[VP2:%[0-9]+]]> = vector-trip-count
+; CHECK-NEXT:  Live-in ir<512> = original trip-count
 ; CHECK-EMPTY:
-; CHECK-NEXT: ir-bb<entry>:
-; CHECK-NEXT: Successor(s): scalar.ph, vector.ph
+; CHECK-NEXT:  ir-bb<entry>:
+; CHECK-NEXT:  Successor(s): scalar.ph, vector.ph
 ; CHECK-EMPTY:
-; CHECK-NEXT: vector.ph:
-; CHECK-NEXT: Successor(s): vector loop
+; CHECK-NEXT:  vector.ph:
+; CHECK-NEXT:  Successor(s): vector loop
 ; CHECK-EMPTY:
-; CHECK-NEXT: <x1> vector loop: {
-; CHECK-NEXT:   vp<[[CAN_IV:%.+]]> = CANONICAL-IV
+; CHECK-NEXT:  <x1> vector loop: {
+; CHECK-NEXT:  vp<[[VP3:%[0-9]+]]> = CANONICAL-IV
 ; CHECK-EMPTY:
-; CHECK-NEXT:   vector.body:
-; CHECK-NEXT:     vp<[[STEPS:%.+]]> = SCALAR-STEPS vp<[[CAN_IV]]>, ir<1>, vp<[[VF]]>
-; CHECK-NEXT:     CLONE ir<%a1> = getelementptr ir<%p>, vp<[[STEPS]]>
-; CHECK-NEXT:     vp<[[VPTR1:%.+]]> = vector-pointer ir<%a1>
-; CHECK-NEXT:     WIDEN ir<%v> = load vp<[[VPTR1]]>
-; CHECK-NEXT:     CLONE ir<%offset> = add vp<[[STEPS]]>, ir<100>
-; CHECK-NEXT:     CLONE ir<%a2> = getelementptr ir<%p>, ir<%offset>
-; CHECK-NEXT:     vp<[[VPTR2:%.+]]> = vector-pointer ir<%a2>
-; CHECK-NEXT:     WIDEN store vp<[[VPTR2]]>, ir<%v>
-; CHECK-NEXT:     EMIT vp<[[CAN_INC:%.+]]> = add nuw vp<[[CAN_IV]]>, vp<[[VFxUF]]>
-; CHECK-NEXT:     EMIT branch-on-count vp<[[CAN_INC]]>, vp<[[VTC]]>
-; CHECK-NEXT:   No successors
-; CHECK-NEXT: }
+; CHECK-NEXT:    vector.body:
+; CHECK-NEXT:      vp<[[VP4:%[0-9]+]]> = SCALAR-STEPS vp<[[VP3]]>, ir<1>, vp<[[VP0]]>
+; CHECK-NEXT:      CLONE ir<%a1> = getelementptr ir<%p>, vp<[[VP4]]>
+; CHECK-NEXT:      vp<[[VP5:%[0-9]+]]> = vector-pointer ir<%a1>, ir<1>
+; CHECK-NEXT:      WIDEN ir<%v> = load vp<[[VP5]]>
+; CHECK-NEXT:      CLONE ir<%offset> = add vp<[[VP4]]>, ir<100>
+; CHECK-NEXT:      CLONE ir<%a2> = getelementptr ir<%p>, ir<%offset>
+; CHECK-NEXT:      vp<[[VP6:%[0-9]+]]> = vector-pointer ir<%a2>, ir<1>
+; CHECK-NEXT:      WIDEN store vp<[[VP6]]>, ir<%v>
+; CHECK-NEXT:      EMIT vp<%index.next> = add nuw vp<[[VP3]]>, vp<[[VP1]]>
+; CHECK-NEXT:      EMIT branch-on-count vp<%index.next>, vp<[[VP2]]>
+; CHECK-NEXT:    No successors
+; CHECK-NEXT:  }
+; CHECK-NEXT:  Successor(s): middle.block
 ;
 entry:
   br label %loop
diff --git a/llvm/test/Transforms/LoopVectorize/VPlan/constant-fold.ll b/llvm/test/Transforms/LoopVectorize/VPlan/constant-fold.ll
index 92bb9704c4fd2..e937887977809 100644
--- a/llvm/test/Transforms/LoopVectorize/VPlan/constant-fold.ll
+++ b/llvm/test/Transforms/LoopVectorize/VPlan/constant-fold.ll
@@ -1,5 +1,6 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --filter-out-after "middle.block" --version 6
 ; RUN: opt -passes=loop-vectorize -force-vector-width=4 -force-vector-interleave=1 \
-; RUN:     -vplan-print-after=simplifyRecipes -disable-output %s 2>&1 \
+; RUN:     -vplan-print-after=VPlanTransforms::simplifyRecipes -vplan-print-instance=1 -disable-output %s 2>&1 \
 ; RUN:   | FileCheck --strict-whitespace %s
 ; REQUIRES: asserts
 
@@ -13,8 +14,8 @@
 
 ; %_tmp2 = getelementptr @a, 0, 0 folds to @a, so the store stores @a directly.
 define void @f1() {
-; CHECK-LABEL: VPlan for loop in 'f1' after VPlanTransforms::simplifyRecipes
-; CHECK-NEXT:  VPlan ' for UF>=1' {
+; CHECK-LABEL: VPlan for loop in 'f1'
+; CHECK:  VPlan ' for UF>=1' {
 ; CHECK-EMPTY:
 ; CHECK-NEXT:  ir-bb<bb1>:
 ; CHECK-NEXT:  Successor(s): scalar.ph, vector.ph
@@ -31,7 +32,7 @@ define void @f1() {
 ; CHECK-NEXT:    EMIT store ir<@a>, ir<%_tmp7>
 ; CHECK-NEXT:    EMIT ir<%_tmp9> = add nsw ir<%c.1.0>, ir<1>
 ; CHECK-NEXT:    EMIT ir<%_tmp11> = icmp sge ir<%_tmp9>, ir<2>
-; CHECK-NEXT:    EMIT vp<{{.+}}> = not ir<%_tmp11>
+; CHECK-NEXT:    EMIT vp<[[VP1:%[0-9]+]]> = not ir<%_tmp11>
 ; CHECK-NEXT:    EMIT branch-on-cond ir<%_tmp11>
 ; CHECK-NEXT:  Successor(s): middle.block, bb2
 ;
@@ -57,8 +58,8 @@ bb3:
 ; %or = or %cmp, true folds to true, simplifying the dependent select and
 ; branch-on-cond to use %c.1 directly.
 define void @redundant_or_1(ptr %dst, i1 %c.0, i1 %c.1) {
-; CHECK-LABEL: VPlan for loop in 'redundant_or_1' after VPlanTransforms::simplifyRecipes
-; CHECK-NEXT:  VPlan ' for UF>=1' {
+; CHECK-LABEL: VPlan for loop in 'redundant_or_1'
+; CHECK:  VPlan ' for UF>=1' {
 ; CHECK-NEXT:  Live-in ir<3> = original trip-count
 ; CHECK-EMPTY:
 ; CHECK-NEXT:  ir-bb<entry>:
@@ -78,6 +79,17 @@ define void @redundant_or_1(ptr %dst, i1 %c.0, i1 %c.1) {
 ; CHECK-NEXT:    EMIT ir<%cond> = select ir<true>, ir<%c.1>, ir<false>
 ; CHECK-NEXT:    EMIT branch-on-cond ir<%c.1>
 ; CHECK-NEXT:  Successor(s): then.2, loop.latch
+; CHECK-EMPTY:
+; CHECK-NEXT:  then.2:
+; CHECK-NEXT:    EMIT ir<%gep> = getelementptr inbounds ir<%dst>, ir<%iv>
+; CHECK-NEXT:    EMIT store ir<0>, ir<%gep>
+; CHECK-NEXT:  Successor(s): loop.latch
+; CHECK-EMPTY:
+; CHECK-NEXT:  loop.latch:
+; CHECK-NEXT:    EMIT ir<%iv.next> = add nuw nsw ir<%iv>, ir<1>
+; CHECK-NEXT:    EMIT ir<%ec> = icmp eq ir<%iv.next>, ir<3>
+; CHECK-NEXT:    EMIT branch-on-cond ir<%ec>
+; CHECK-NEXT:  Successor(s): middle.block, loop.header
 ;
 entry:
   br label %loop.header
@@ -108,8 +120,8 @@ exit:
 
 ; %or = or true, %cmp folds to true (commuted form of redundant_or_1).
 define void @redundant_or_2(ptr %dst, i1 %c.0, i1 %c.1) {
-; CHECK-LABEL: VPlan for loop in 'redundant_or_2' after VPlanTransforms::simplifyRecipes
-; CHECK-NEXT:  VPlan ' for UF>=1' {
+; CHECK-LABEL: VPlan for loop in 'redundant_or_2'
+; CHECK:  VPlan ' for UF>=1' {
 ; CHECK-NEXT:  Live-in ir<3> = original trip-count
 ; CHECK-EMPTY:
 ; CHECK-NEXT:  ir-bb<entry>:
@@ -129,6 +141,17 @@ define void @redundant_or_2(ptr %dst, i1 %c.0, i1 %c.1) {
 ; CHECK-NEXT:    EMIT ir<%cond> = select ir<true>, ir<%c.1>, ir<false>
 ; CHECK-NEXT:    EMIT branch-on-cond ir<%c.1>
 ; CHECK-NEXT:  Successor(s): then.2, loop.latch
+; CHECK-EMPTY:
+; CHECK-NEXT:  then.2:
+; CHECK-NEXT:    EMIT ir<%gep> = getelementptr inbounds ir<%dst>, ir<%iv>
+; CHECK-NEXT:    EMIT store ir<0>, ir<%gep>
+; CHECK-NEXT:  Successor(s): loop.latch
+; CHECK-EMPTY:
+; CHECK-NEXT:  loop.latch:
+; CHECK-NEXT:    EMIT ir<%iv.next> = add nuw nsw ir<%iv>, ir<1>
+; CHECK-NEXT:    EMIT ir<%ec> = icmp eq ir<%iv.next>, ir<3>
+; CHECK-NEXT:    EMIT branch-on-cond ir<%ec>
+; CHECK-NEXT:  Successor(s): middle.block, loop.header
 ;
 entry:
   br label %loop.header
@@ -159,8 +182,8 @@ exit:
 
 ; %or = or %cmp, false folds to %cmp, propagated into the dependent select.
 define void @redundant_and_1(ptr %dst, i1 %c.0, i1 %c.1) {
-; CHECK-LABEL: VPlan for loop in 'redundant_and_1' after VPlanTransforms::simplifyRecipes
-; CHECK-NEXT:  VPlan ' for UF>=1' {
+; CHECK-LABEL: VPlan for loop in 'redundant_and_1'
+; CHECK:  VPlan ' for UF>=1' {
 ; CHECK-NEXT:  Live-in ir<3> = original trip-count
 ; CHECK-EMPTY:
 ; CHECK-NEXT:  ir-bb<entry>:
@@ -180,6 +203,17 @@ define void @redundant_and_1(ptr %dst, i1 %c.0, i1 %c.1) {
 ; CHECK-NEXT:    EMIT ir<%cond> = select ir<%cmp>, ir<%c.1>, ir<false>
 ; CHECK-NEXT:    EMIT branch-on-cond ir<%cond>
 ; CHECK-NEXT:  Successor(s): then.2, loop.latch
+; CHECK-EMPTY:
+; CHECK-NEXT:  then.2:
+; CHECK-NEXT:    EMIT ir<%gep> = getelementptr inbounds ir<%dst>, ir<%iv>
+; CHECK-NEXT:    EMIT store ir<0>, ir<%gep>
+; CHECK-NEXT:  Successor(s): loop.latch
+; CHECK-EMPTY:
+; CHECK-NEXT:  loop.latch:
+; CHECK-NEXT:    EMIT ir<%iv.next> = add nuw nsw ir<%iv>, ir<1>
+; CHECK-NEXT:    EMIT ir<%ec> = icmp eq ir<%iv.next>, ir<3>
+; CHECK-NEXT:    EMIT branch-on-cond ir<%ec>
+; CHECK-NEXT:  Successor(s): middle.block, loop.header
 ;
 entry:
   br label %loop.header
@@ -211,8 +245,8 @@ exit:
 ; %or = and false, %cmp folds to false, simplifying the dependent select and
 ; branch-on-cond to false directly.
 define void @redundant_and_2(ptr %dst, i1 %c.0, i1 %c.1) {
-; CHECK-LABEL: VPlan for loop in 'redundant_and_2' after VPlanTransforms::simplifyRecipes
-; CHECK-NEXT:  VPlan ' for UF>=1' {
+; CHECK-LABEL: VPlan for loop in 'redundant_and_2'
+; CHECK:  VPlan ' for UF>=1' {
 ; CHECK-NEXT:  Live-in ir<3> = original trip-count
 ; CHECK-EMPTY:
 ; CHECK-NEXT:  ir-bb<entry>:
@@ -232,6 +266,17 @@ define void @redundant_and_2(ptr %dst, i1 %c.0, i1 %c.1) {
 ; CHECK-NEXT:    EMIT ir<%cond> = select ir<false>, ir<%c.1>, ir<false>
 ; CHECK-NEXT:    EMIT branch-on-cond ir<false>
 ; CHECK-NEXT:  Successor(s): then.2, loop.latch
+; CHECK-EMPTY:
+; CHECK-NEXT:  then.2:
+; CHECK-NEXT:    EMIT ir<%gep> = getelementptr inbounds ir<%dst>, ir<%iv>
+; CHECK-NEXT:    EMIT store ir<0>, ir<%gep>
+; CHECK-NEXT:  Successor(s): loop.latch
+; CHECK-EMPTY:
+; CHECK-NEXT:  loop.latch:
+; CHECK-NEXT:    EMIT ir<%iv.next> = add nuw nsw ir<%iv>, ir<1>
+; CHECK-NEXT:    EMIT ir<%ec> = icmp eq ir<%iv.next>, ir<3>
+; CHECK-NEXT:    EMIT branch-on-cond ir<%ec>
+; CHECK-NEXT:  Successor(s): middle.block, loop.header
 ;
 entry:
   br label %loop.header
@@ -261,8 +306,8 @@ exit:
 }
 
 define void @fold_replicating_umax_equal_live_ins(ptr noalias %dst, ptr %cond, i32 %x) {
-; CHECK-LABEL: VPlan for loop in 'fold_replicating_umax_equal_live_ins' after VPlanTransforms::simplifyRecipes
-; CHECK-NEXT:  VPlan ' for UF>=1' {
+; CHECK-LABEL: VPlan for loop in 'fold_replicating_umax_equal_live_ins'
+; CHECK:  VPlan ' for UF>=1' {
 ; CHECK-NEXT:  Live-in ir<1024> = original trip-count
 ; CHECK-EMPTY:
 ; CHECK-NEXT:  ir-bb<entry>:
diff --git a/llvm/test/Transforms/LoopVectorize/VPlan/vplan-print-instance.ll b/llvm/test/Transforms/LoopVectorize/VPlan/vplan-print-instance.ll
new file mode 100644
index 0000000000000..e5181ebf1a052
--- /dev/null
+++ b/llvm/test/Transforms/LoopVectorize/VPlan/vplan-print-instance.ll
@@ -0,0 +1,81 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
+
+; Normally UTC script can't generate CHECKs if a given VPlan pass is run
+; multiple times. However, --vplan-print-instance can be used to specify which
+; one we're interested in.
+
+; RUN: opt -passes=loop-vectorize -disable-output -vplan-print-after=VPlanTransforms::simplifyRecipes -vplan-print-instance=1 -vplan-print-vector-region-scope -force-vector-width=4 -vplan-verify-each < %s 2>&1 | FileCheck %s -check-prefixes=CHECK-FIRST
+; RUN: opt -passes=loop-vectorize -disable-output -vplan-print-after=VPlanTransforms::simplifyRecipes -vplan-print-instance=2 -vplan-print-vector-region-scope -force-vector-width=4 -vplan-verify-each < %s 2>&1 | FileCheck %s -check-prefixes=CHECK-SECOND
+
+define void @foo(ptr %ptr, i64 %n) {
+; CHECK-FIRST-LABEL: VPlan for loop in 'foo'
+; CHECK-FIRST:  VPlan ' for UF>=1' {
+; CHECK-FIRST-EMPTY:
+; CHECK-FIRST-NEXT:  ir-bb<entry>:
+; CHECK-FIRST-NEXT:    EMIT vp<[[VP1:%[0-9]+]]> = EXPAND SCEV (1 smax %n)
+; CHECK-FIRST-NEXT:  Successor(s): scalar.ph, vector.ph
+; CHECK-FIRST-EMPTY:
+; CHECK-FIRST-NEXT:  vector.ph:
+; CHECK-FIRST-NEXT:  Successor(s): header
+; CHECK-FIRST-EMPTY:
+; CHECK-FIRST-NEXT:  header:
+; CHECK-FIRST-NEXT:    EMIT-SCALAR ir<%iv> = phi [ ir<0>, vector.ph ], [ ir<%iv.next>, header ]
+; CHECK-FIRST-NEXT:    EMIT ir<%gep> = getelementptr ir<%ptr>, ir<%iv>
+; CHECK-FIRST-NEXT:    EMIT store ir<%iv>, ir<%gep>
+; CHECK-FIRST-NEXT:    EMIT ir<%iv.next> = add nsw ir<%iv>, ir<1>
+; CHECK-FIRST-NEXT:    EMIT ir<%exitcond> = icmp sge ir<%iv.next>, ir<%n>
+; CHECK-FIRST-NEXT:    EMIT vp<[[VP2:%[0-9]+]]> = not ir<%exitcond>
+; CHECK-FIRST-NEXT:    EMIT branch-on-cond ir<%exitcond>
+; CHECK-FIRST-NEXT:  Successor(s): middle.block, header
+; CHECK-FIRST-EMPTY:
+; CHECK-FIRST-NEXT:  middle.block:
+; CHECK-FIRST-NEXT:    EMIT vp<[[VP3:%[0-9]+]]> = extract-last-part ir<%iv.next>
+; CHECK-FIRST-NEXT:    EMIT vp<[[VP4:%[0-9]+]]> = extract-last-lane vp<[[VP3]]>
+; CHECK-FIRST-NEXT:  Successor(s): ir-bb<exit>, scalar.ph
+; CHECK-FIRST-EMPTY:
+; CHECK-FIRST-NEXT:  ir-bb<exit>:
+; CHECK-FIRST-NEXT:  No successors
+; CHECK-FIRST-EMPTY:
+; CHECK-FIRST-NEXT:  scalar.ph:
+; CHECK-FIRST-NEXT:    EMIT-SCALAR vp<[[VP5:%[0-9]+]]> = phi [ vp<[[VP4]]>, middle.block ], [ ir<0>, ir-bb<entry> ]
+; CHECK-FIRST-NEXT:  Successor(s): ir-bb<header>
+; CHECK-FIRST-EMPTY:
+; CHECK-FIRST-NEXT:  ir-bb<header>:
+; CHECK-FIRST-NEXT:    IR   %iv = phi i64 [ 0, %entry ], [ %iv.next, %header ] (extra operand: vp<[[VP5]]> from scalar.ph)
+; CHECK-FIRST-NEXT:    IR   %gep = getelementptr i64, ptr %ptr, i64 %iv
+; CHECK-FIRST-NEXT:    IR   store i64 %iv, ptr %gep, align 4
+; CHECK-FIRST-NEXT:    IR   %iv.next = add nsw i64 %iv, 1
+; CHECK-FIRST-NEXT:    IR   %exitcond = icmp slt i64 %iv.next, %n
+; CHECK-FIRST-NEXT:  No successors
+; CHECK-FIRST-NEXT:  }
+;
+; CHECK-SECOND-LABEL: VPlan for loop in 'foo'
+; CHECK-SECOND-NEXT:  <x1> vector loop: {
+; CHECK-SECOND-NEXT:  vp<[[VP5:%[0-9]+]]> = CANONICAL-IV
+; CHECK-SECOND-EMPTY:
+; CHECK-SECOND-NEXT:    vector.body:
+; CHECK-SECOND-NEXT:      ir<%iv> = WIDEN-INDUCTION nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
+; CHECK-SECOND-NEXT:      vp<[[VP6:%[0-9]+]]> = SCALAR-STEPS vp<[[VP5]]>, ir<1>, vp<[[VP0]]>
+; CHECK-SECOND-NEXT:      CLONE ir<%gep> = getelementptr ir<%ptr>, vp<[[VP5]]>
+; CHECK-SECOND-NEXT:      vp<[[VP7:%[0-9]+]]> = vector-pointer ir<%gep>, ir<1>
+; CHECK-SECOND-NEXT:      WIDEN store ir<%gep>, ir<%iv>
+; CHECK-SECOND-NEXT:      EMIT vp<%index.next> = add nuw vp<[[VP5]]>, vp<[[VP1:%[0-9]+]]>
+; CHECK-SECOND-NEXT:      EMIT branch-on-count vp<%index.next>, vp<[[VP2:%[0-9]+]]>
+; CHECK-SECOND-NEXT:    No successors
+; CHECK-SECOND-NEXT:  }
+; CHECK-SECOND-NEXT:  Successor(s): middle.block
+;
+entry:
+  br label %header
+
+header:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %header ]
+  %gep = getelementptr i64, ptr %ptr, i64 %iv
+  store i64 %iv, ptr %gep
+  %iv.next = add nsw i64 %iv, 1
+  %exitcond = icmp slt i64 %iv.next, %n
+  br i1 %exitcond, label %header, label %exit
+
+exit:
+  ret void
+}

>From 900c74a143172e682cd5269f424ab46d8cebd14b Mon Sep 17 00:00:00 2001
From: Andrei Elovikov <andrei.elovikov at sifive.com>
Date: Thu, 23 Jul 2026 09:59:25 -0700
Subject: [PATCH 2/3] Use `DenseMap<std::pair<Function *, StringRef /* Pass
 */>, unsigned>`

---
 llvm/lib/Transforms/Vectorize/VPlanTransforms.h | 16 +++++-----------
 1 file changed, 5 insertions(+), 11 deletions(-)

diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.h b/llvm/lib/Transforms/Vectorize/VPlanTransforms.h
index c4e6361540c81..092ad2097bb9c 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.h
@@ -22,10 +22,6 @@
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Regex.h"
 
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-#include <map>
-#endif
-
 namespace llvm {
 
 class InductionDescriptor;
@@ -62,19 +58,17 @@ struct VPlanTransforms {
   static decltype(auto) runPass(StringRef PassName, PassTy &&Pass, VPlan &Plan,
                                 ArgsTy &&...Args) {
 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-    static std::map<
-        std::pair<std::string /* Function */, std::string /* Pass */>, unsigned>
+    static DenseMap<std::pair<Function *, StringRef /* Pass */>, unsigned>
         PassCounter;
-    StringRef FnName =
-        Plan.getScalarHeader()->getIRBasicBlock()->getParent()->getName();
-    unsigned Instance = ++PassCounter[{FnName.str(), PassName.str()}];
+    Function *Fn = Plan.getScalarHeader()->getIRBasicBlock()->getParent();
+    unsigned Instance = ++PassCounter[{Fn, PassName}];
 
     auto PrintPlan = [&](StringRef BeforeOrAfterStr) {
       if (VPlanPrintInstance != 0 && VPlanPrintInstance != Instance)
         return;
 
-      dbgs() << "VPlan for loop in '" << FnName << "' " << BeforeOrAfterStr
-             << " " << PassName << '\n';
+      dbgs() << "VPlan for loop in '" << Fn->getName() << "' "
+             << BeforeOrAfterStr << " " << PassName << '\n';
       if (VPlanPrintVectorRegionScope && Plan.getVectorLoopRegion())
         Plan.getVectorLoopRegion()->print(dbgs());
       else

>From e8c15d3efec731c57ff88b5a58e252068bb5b12e Mon Sep 17 00:00:00 2001
From: Andrei Elovikov <andrei.elovikov at sifive.com>
Date: Tue, 28 Jul 2026 08:53:30 -0700
Subject: [PATCH 3/3] Number pass names instead

---
 .../Transforms/Vectorize/LoopVectorize.cpp    |  5 --
 .../Transforms/Vectorize/VPlanTransforms.h    | 14 ++--
 .../VPlan/AArch64/vplan-printing.ll           |  2 +-
 .../PowerPC/vplan-force-tail-with-evl.ll      |  2 +-
 .../LoopVectorize/VPlan/constant-fold.ll      |  2 +-
 .../VPlan/vplan-print-before-after-all.ll     | 18 ++---
 .../VPlan/vplan-print-instance.ll             | 81 -------------------
 7 files changed, 19 insertions(+), 105 deletions(-)
 delete mode 100644 llvm/test/Transforms/LoopVectorize/VPlan/vplan-print-instance.ll

diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index f7dd83b9ec404..aa099b84ed61b 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -382,11 +382,6 @@ cl::opt<bool> llvm::VPlanPrintVectorRegionScope(
     "vplan-print-vector-region-scope", cl::init(false), cl::Hidden,
     cl::desc("Limit VPlan printing to vector loop region in "
              "`-vplan-print-after*` if the plan has one."));
-
-cl::opt<unsigned> llvm::VPlanPrintInstance(
-    "vplan-print-instance", cl::init(0), cl::Hidden,
-    cl::desc("Only print Nth instance of the specified VPlan "
-             "transformation(s), zero - print all instances."));
 #endif
 
 // This flag enables the stress testing of the VPlan H-CFG construction in the
diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.h b/llvm/lib/Transforms/Vectorize/VPlanTransforms.h
index 1f31361ea174f..69ea02c7d3b17 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.h
@@ -47,7 +47,6 @@ LLVM_ABI_FOR_TEST extern cl::opt<bool> VPlanPrintAfterAll;
 LLVM_ABI_FOR_TEST extern cl::list<std::string> VPlanPrintBeforePasses;
 LLVM_ABI_FOR_TEST extern cl::list<std::string> VPlanPrintAfterPasses;
 LLVM_ABI_FOR_TEST extern cl::opt<bool> VPlanPrintVectorRegionScope;
-LLVM_ABI_FOR_TEST extern cl::opt<unsigned> VPlanPrintInstance;
 #endif
 
 struct VPlanTransforms {
@@ -63,12 +62,13 @@ struct VPlanTransforms {
     Function *Fn = Plan.getScalarHeader()->getIRBasicBlock()->getParent();
     unsigned Instance = ++PassCounter[{Fn, PassName}];
 
-    auto PrintPlan = [&](StringRef BeforeOrAfterStr) {
-      if (VPlanPrintInstance != 0 && VPlanPrintInstance != Instance)
-        return;
+    std::string NumberedPassName =
+        Instance == 1 ? PassName.str()
+                      : (PassName + "@" + Twine(Instance)).str();
 
+    auto PrintPlan = [&](StringRef BeforeOrAfterStr) {
       dbgs() << "VPlan for loop in '" << Fn->getName() << "' "
-             << BeforeOrAfterStr << " " << PassName << '\n';
+             << BeforeOrAfterStr << " " << NumberedPassName << '\n';
       if (VPlanPrintVectorRegionScope && Plan.getVectorLoopRegion())
         Plan.getVectorLoopRegion()->print(dbgs());
       else
@@ -77,8 +77,8 @@ struct VPlanTransforms {
 
     auto MatchesPassListOption = [&](const cl::list<std::string> &ListOpt) {
       return (ListOpt.getNumOccurrences() > 0 &&
-              any_of(ListOpt, [PassName](StringRef Entry) {
-                return Regex(Entry).match(PassName);
+              any_of(ListOpt, [&](StringRef Entry) {
+                return Regex(Entry).match(NumberedPassName);
               }));
     };
 
diff --git a/llvm/test/Transforms/LoopVectorize/VPlan/AArch64/vplan-printing.ll b/llvm/test/Transforms/LoopVectorize/VPlan/AArch64/vplan-printing.ll
index 88bbd9dfc0f90..b69b04db8a03a 100644
--- a/llvm/test/Transforms/LoopVectorize/VPlan/AArch64/vplan-printing.ll
+++ b/llvm/test/Transforms/LoopVectorize/VPlan/AArch64/vplan-printing.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
-; RUN: opt -passes=loop-vectorize -vplan-print-after=printOptimizedVPlan -vplan-print-instance=3 -disable-output %s 2>&1 | FileCheck %s
+; RUN: opt -passes=loop-vectorize -vplan-print-after=printOptimizedVPlan at 3 -disable-output %s 2>&1 | FileCheck %s
 
 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
 target triple = "aarch64-none-unknown-elf"
diff --git a/llvm/test/Transforms/LoopVectorize/VPlan/PowerPC/vplan-force-tail-with-evl.ll b/llvm/test/Transforms/LoopVectorize/VPlan/PowerPC/vplan-force-tail-with-evl.ll
index 56f2da2d50047..a7989a1b1c02a 100644
--- a/llvm/test/Transforms/LoopVectorize/VPlan/PowerPC/vplan-force-tail-with-evl.ll
+++ b/llvm/test/Transforms/LoopVectorize/VPlan/PowerPC/vplan-force-tail-with-evl.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --filter-out-after "middle.block" --version 6
-; RUN: opt -passes=loop-vectorize -vplan-print-after=printOptimizedVPlan -vplan-print-instance=2 \
+; RUN: opt -passes=loop-vectorize -vplan-print-after=printOptimizedVPlan at 2 \
 ; RUN: -force-tail-folding-style=data-with-evl \
 ; RUN: -tail-folding-policy=must-fold-tail \
 ; RUN: -mtriple=powerpc64le-unknown-linux-gnu \
diff --git a/llvm/test/Transforms/LoopVectorize/VPlan/constant-fold.ll b/llvm/test/Transforms/LoopVectorize/VPlan/constant-fold.ll
index e937887977809..21a0f6f15d902 100644
--- a/llvm/test/Transforms/LoopVectorize/VPlan/constant-fold.ll
+++ b/llvm/test/Transforms/LoopVectorize/VPlan/constant-fold.ll
@@ -1,6 +1,6 @@
 ; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --filter-out-after "middle.block" --version 6
 ; RUN: opt -passes=loop-vectorize -force-vector-width=4 -force-vector-interleave=1 \
-; RUN:     -vplan-print-after=VPlanTransforms::simplifyRecipes -vplan-print-instance=1 -disable-output %s 2>&1 \
+; RUN:     -vplan-print-after=VPlanTransforms::simplifyRecipes$ -disable-output %s 2>&1 \
 ; RUN:   | FileCheck --strict-whitespace %s
 ; REQUIRES: asserts
 
diff --git a/llvm/test/Transforms/LoopVectorize/VPlan/vplan-print-before-after-all.ll b/llvm/test/Transforms/LoopVectorize/VPlan/vplan-print-before-after-all.ll
index a7271524f0191..bcab64d330a99 100644
--- a/llvm/test/Transforms/LoopVectorize/VPlan/vplan-print-before-after-all.ll
+++ b/llvm/test/Transforms/LoopVectorize/VPlan/vplan-print-before-after-all.ll
@@ -1,6 +1,6 @@
-; RUN: opt -passes=loop-vectorize -disable-output -vplan-print-before-all -force-vector-width=4 -vplan-verify-each < %s 2>&1 | FileCheck %s -check-prefixes=CHECK,CHECK-BEFORE -DBEFORE_OR_AFTER=before --implicit-check-not "VPlan for loop in 'foo' before"
+; RUN: opt -passes=loop-vectorize -disable-output -vplan-print-before-all -force-vector-width=4 -vplan-verify-each < %s 2>&1 | FileCheck %s --match-full-lines -check-prefixes=CHECK,CHECK-BEFORE -DBEFORE_OR_AFTER=before --implicit-check-not "VPlan for loop in 'foo' before"
 ; RUN: opt -passes=loop-vectorize -disable-output -vplan-print-before-all -force-vector-width=4 -vplan-verify-each < %s 2>&1 | FileCheck %s -DBEFORE_OR_AFTER=before --check-prefix CHECK-DUMP
-; RUN: opt -passes=loop-vectorize -disable-output -vplan-print-after-all -force-vector-width=4 -vplan-verify-each < %s 2>&1 | FileCheck %s -check-prefixes=CHECK,CHECK-AFTER -DBEFORE_OR_AFTER=after --implicit-check-not "VPlan for loop in 'foo' after"
+; RUN: opt -passes=loop-vectorize -disable-output -vplan-print-after-all -force-vector-width=4 -vplan-verify-each < %s 2>&1 | FileCheck %s --match-full-lines -check-prefixes=CHECK,CHECK-AFTER -DBEFORE_OR_AFTER=after --implicit-check-not "VPlan for loop in 'foo' after"
 ; RUN: opt -passes=loop-vectorize -disable-output -vplan-print-after-all -force-vector-width=4 -vplan-verify-each < %s 2>&1 | FileCheck %s -DBEFORE_OR_AFTER=after --check-prefix CHECK-DUMP
 
 ; Verify that `-vplan-print-before/after-all` option works.
@@ -10,7 +10,7 @@
 ; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] VPlanTransforms::simplifyRecipes
 ; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] VPlanTransforms::removeDeadRecipes
 ; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] VPlanTransforms::createHeaderPhiRecipes
-; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] VPlanTransforms::replaceSymbolicStrides
+; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] VPlanTransforms::replaceSymbolicStrides at 2
 ; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] VPlanTransforms::finalizeSCEVPredicates
 ; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] VPlanTransforms::addMiddleCheck
 ; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] VPlanTransforms::handleEarlyExits
@@ -50,11 +50,11 @@
 ; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] legalizeAndOptimizeInductions
 ; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] narrowToSingleScalarRecipes
 ; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] removeRedundantExpandSCEVRecipes
-; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] reassociateHeaderMask
-; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] simplifyRecipes
+; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] reassociateHeaderMask at 2
+; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] simplifyRecipes at 2
 ; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] removeBranchOnConst
 ; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] simplifyReverses
-; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] removeDeadRecipes
+; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] removeDeadRecipes at 2
 ; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] createAndOptimizeReplicateRegions
 ; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] mergeBlocksIntoPredecessors
 ; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] licm
@@ -70,9 +70,9 @@
 ; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] VPlanTransforms::replicateByVF
 ; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] VPlanTransforms::materializeConstantVectorTripCount
 ; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] VPlanTransforms::optimizeForVFAndUF
-; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] VPlanTransforms::simplifyRecipes
-; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] VPlanTransforms::removeBranchOnConst
-; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] VPlanTransforms::removeDeadRecipes
+; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] VPlanTransforms::simplifyRecipes at 2
+; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] VPlanTransforms::removeBranchOnConst at 2
+; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] VPlanTransforms::removeDeadRecipes at 2
 ; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] VPlanTransforms::convertToConcreteRecipes
 ; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] VPlanTransforms::convertEVLExitCond
 ; CHECK: VPlan for loop in 'foo' [[BEFORE_OR_AFTER]] VPlanTransforms::dissolveLoopRegions
diff --git a/llvm/test/Transforms/LoopVectorize/VPlan/vplan-print-instance.ll b/llvm/test/Transforms/LoopVectorize/VPlan/vplan-print-instance.ll
deleted file mode 100644
index e5181ebf1a052..0000000000000
--- a/llvm/test/Transforms/LoopVectorize/VPlan/vplan-print-instance.ll
+++ /dev/null
@@ -1,81 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
-
-; Normally UTC script can't generate CHECKs if a given VPlan pass is run
-; multiple times. However, --vplan-print-instance can be used to specify which
-; one we're interested in.
-
-; RUN: opt -passes=loop-vectorize -disable-output -vplan-print-after=VPlanTransforms::simplifyRecipes -vplan-print-instance=1 -vplan-print-vector-region-scope -force-vector-width=4 -vplan-verify-each < %s 2>&1 | FileCheck %s -check-prefixes=CHECK-FIRST
-; RUN: opt -passes=loop-vectorize -disable-output -vplan-print-after=VPlanTransforms::simplifyRecipes -vplan-print-instance=2 -vplan-print-vector-region-scope -force-vector-width=4 -vplan-verify-each < %s 2>&1 | FileCheck %s -check-prefixes=CHECK-SECOND
-
-define void @foo(ptr %ptr, i64 %n) {
-; CHECK-FIRST-LABEL: VPlan for loop in 'foo'
-; CHECK-FIRST:  VPlan ' for UF>=1' {
-; CHECK-FIRST-EMPTY:
-; CHECK-FIRST-NEXT:  ir-bb<entry>:
-; CHECK-FIRST-NEXT:    EMIT vp<[[VP1:%[0-9]+]]> = EXPAND SCEV (1 smax %n)
-; CHECK-FIRST-NEXT:  Successor(s): scalar.ph, vector.ph
-; CHECK-FIRST-EMPTY:
-; CHECK-FIRST-NEXT:  vector.ph:
-; CHECK-FIRST-NEXT:  Successor(s): header
-; CHECK-FIRST-EMPTY:
-; CHECK-FIRST-NEXT:  header:
-; CHECK-FIRST-NEXT:    EMIT-SCALAR ir<%iv> = phi [ ir<0>, vector.ph ], [ ir<%iv.next>, header ]
-; CHECK-FIRST-NEXT:    EMIT ir<%gep> = getelementptr ir<%ptr>, ir<%iv>
-; CHECK-FIRST-NEXT:    EMIT store ir<%iv>, ir<%gep>
-; CHECK-FIRST-NEXT:    EMIT ir<%iv.next> = add nsw ir<%iv>, ir<1>
-; CHECK-FIRST-NEXT:    EMIT ir<%exitcond> = icmp sge ir<%iv.next>, ir<%n>
-; CHECK-FIRST-NEXT:    EMIT vp<[[VP2:%[0-9]+]]> = not ir<%exitcond>
-; CHECK-FIRST-NEXT:    EMIT branch-on-cond ir<%exitcond>
-; CHECK-FIRST-NEXT:  Successor(s): middle.block, header
-; CHECK-FIRST-EMPTY:
-; CHECK-FIRST-NEXT:  middle.block:
-; CHECK-FIRST-NEXT:    EMIT vp<[[VP3:%[0-9]+]]> = extract-last-part ir<%iv.next>
-; CHECK-FIRST-NEXT:    EMIT vp<[[VP4:%[0-9]+]]> = extract-last-lane vp<[[VP3]]>
-; CHECK-FIRST-NEXT:  Successor(s): ir-bb<exit>, scalar.ph
-; CHECK-FIRST-EMPTY:
-; CHECK-FIRST-NEXT:  ir-bb<exit>:
-; CHECK-FIRST-NEXT:  No successors
-; CHECK-FIRST-EMPTY:
-; CHECK-FIRST-NEXT:  scalar.ph:
-; CHECK-FIRST-NEXT:    EMIT-SCALAR vp<[[VP5:%[0-9]+]]> = phi [ vp<[[VP4]]>, middle.block ], [ ir<0>, ir-bb<entry> ]
-; CHECK-FIRST-NEXT:  Successor(s): ir-bb<header>
-; CHECK-FIRST-EMPTY:
-; CHECK-FIRST-NEXT:  ir-bb<header>:
-; CHECK-FIRST-NEXT:    IR   %iv = phi i64 [ 0, %entry ], [ %iv.next, %header ] (extra operand: vp<[[VP5]]> from scalar.ph)
-; CHECK-FIRST-NEXT:    IR   %gep = getelementptr i64, ptr %ptr, i64 %iv
-; CHECK-FIRST-NEXT:    IR   store i64 %iv, ptr %gep, align 4
-; CHECK-FIRST-NEXT:    IR   %iv.next = add nsw i64 %iv, 1
-; CHECK-FIRST-NEXT:    IR   %exitcond = icmp slt i64 %iv.next, %n
-; CHECK-FIRST-NEXT:  No successors
-; CHECK-FIRST-NEXT:  }
-;
-; CHECK-SECOND-LABEL: VPlan for loop in 'foo'
-; CHECK-SECOND-NEXT:  <x1> vector loop: {
-; CHECK-SECOND-NEXT:  vp<[[VP5:%[0-9]+]]> = CANONICAL-IV
-; CHECK-SECOND-EMPTY:
-; CHECK-SECOND-NEXT:    vector.body:
-; CHECK-SECOND-NEXT:      ir<%iv> = WIDEN-INDUCTION nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
-; CHECK-SECOND-NEXT:      vp<[[VP6:%[0-9]+]]> = SCALAR-STEPS vp<[[VP5]]>, ir<1>, vp<[[VP0]]>
-; CHECK-SECOND-NEXT:      CLONE ir<%gep> = getelementptr ir<%ptr>, vp<[[VP5]]>
-; CHECK-SECOND-NEXT:      vp<[[VP7:%[0-9]+]]> = vector-pointer ir<%gep>, ir<1>
-; CHECK-SECOND-NEXT:      WIDEN store ir<%gep>, ir<%iv>
-; CHECK-SECOND-NEXT:      EMIT vp<%index.next> = add nuw vp<[[VP5]]>, vp<[[VP1:%[0-9]+]]>
-; CHECK-SECOND-NEXT:      EMIT branch-on-count vp<%index.next>, vp<[[VP2:%[0-9]+]]>
-; CHECK-SECOND-NEXT:    No successors
-; CHECK-SECOND-NEXT:  }
-; CHECK-SECOND-NEXT:  Successor(s): middle.block
-;
-entry:
-  br label %header
-
-header:
-  %iv = phi i64 [ 0, %entry ], [ %iv.next, %header ]
-  %gep = getelementptr i64, ptr %ptr, i64 %iv
-  store i64 %iv, ptr %gep
-  %iv.next = add nsw i64 %iv, 1
-  %exitcond = icmp slt i64 %iv.next, %n
-  br i1 %exitcond, label %header, label %exit
-
-exit:
-  ret void
-}



More information about the llvm-commits mailing list