[llvm] [VPlan] Implement printing VPIRMetadata. (PR #168385)

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 25 04:02:08 PST 2025


https://github.com/fhahn updated https://github.com/llvm/llvm-project/pull/168385

>From e783ed3ed40aa46e34904ee0ceb8604a7849aa68 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Wed, 19 Nov 2025 15:44:09 +0000
Subject: [PATCH 1/2] [VPlan] Implement printing VPIRMetadata.

Implement and use debug printing for VPIRMetadata.
---
 llvm/lib/Transforms/Vectorize/VPlan.h         | 10 +++++++
 .../lib/Transforms/Vectorize/VPlanRecipes.cpp | 27 +++++++++++++++++++
 .../LoopVectorize/vplan-printing-metadata.ll  | 18 ++++++-------
 3 files changed, 46 insertions(+), 9 deletions(-)

diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h
index 0c7d9c0193a03..952a8427ec94c 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.h
+++ b/llvm/lib/Transforms/Vectorize/VPlan.h
@@ -1020,6 +1020,11 @@ class VPIRMetadata {
         find_if(Metadata, [Kind](const auto &P) { return P.first == Kind; });
     return It != Metadata.end() ? It->second : nullptr;
   }
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+  /// Print metadata with node IDs.
+  void print(raw_ostream &O, const VPlan *Plan) const;
+#endif
 };
 
 /// This is a concrete Recipe that models a single VPlan-level instruction.
@@ -4433,6 +4438,11 @@ class VPlan {
   /// Return the VPIRBasicBlock wrapping the header of the scalar loop.
   VPIRBasicBlock *getScalarHeader() const { return ScalarHeader; }
 
+  /// Return the Module from the scalar header.
+  const Module &getModule() const {
+    return *ScalarHeader->getIRBasicBlock()->getModule();
+  }
+
   /// Return an ArrayRef containing VPIRBasicBlocks wrapping the exit blocks of
   /// the original scalar loop.
   ArrayRef<VPIRBasicBlock *> getExitBlocks() const { return ExitBlocks; }
diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
index e41f67103e096..8dacda072b1ba 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
@@ -507,6 +507,11 @@ void VPRecipeBase::print(raw_ostream &O, const Twine &Indent,
     O << ", !dbg ";
     DL.print(O);
   }
+
+  if (auto *Metadata = dyn_cast<VPIRMetadata>(this)) {
+    if (const VPBasicBlock *Parent = getParent())
+      Metadata->print(O, Parent->getPlan());
+  }
 }
 #endif
 
@@ -1706,6 +1711,28 @@ void VPIRMetadata::intersect(const VPIRMetadata &Other) {
   Metadata = std::move(MetadataIntersection);
 }
 
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+void VPIRMetadata::print(raw_ostream &O, const VPlan *Plan) const {
+  if (Metadata.empty() || !Plan)
+    return;
+
+  const Module &M = Plan->getModule();
+  SmallVector<StringRef, 8> MDNames;
+  M.getContext().getMDKindNames(MDNames);
+
+  O << " (";
+  interleaveComma(Metadata, O, [&](const auto &KindNodePair) {
+    auto [Kind, Node] = KindNodePair;
+    assert(Kind != 0 && "Debug metadata should not be managed by VPIRMetadata");
+    assert(Kind < MDNames.size() && !MDNames[Kind].empty() &&
+           "Unexpected unnamed metadata kind");
+    O << "!" << MDNames[Kind] << " ";
+    Node->printAsOperand(O, &M);
+  });
+  O << ")";
+}
+#endif
+
 void VPWidenCallRecipe::execute(VPTransformState &State) {
   assert(State.VF.isVector() && "not widening");
   assert(Variant != nullptr && "Can't create vector function.");
diff --git a/llvm/test/Transforms/LoopVectorize/vplan-printing-metadata.ll b/llvm/test/Transforms/LoopVectorize/vplan-printing-metadata.ll
index 857b9131a0b8c..fb49e94ee67bc 100644
--- a/llvm/test/Transforms/LoopVectorize/vplan-printing-metadata.ll
+++ b/llvm/test/Transforms/LoopVectorize/vplan-printing-metadata.ll
@@ -7,11 +7,11 @@ define void @test_widen_metadata(ptr noalias %A, ptr noalias %B, i32 %n) {
 ; CHECK:      VPlan 'Initial VPlan for VF={4},UF>=1' {
 ; CHECK:      <x1> vector loop: {
 ; CHECK:        vector.body:
-; CHECK:          WIDEN ir<%lv> = load vp<{{.*}}>
-; CHECK:          WIDEN-CAST ir<%conv> = sitofp ir<%lv> to float
-; CHECK:          WIDEN ir<%mul> = fmul ir<%conv>, ir<2.000000e+00>
+; CHECK:          WIDEN ir<%lv> = load vp<{{.*}}> (!tbaa !{{[0-9]+}})
+; CHECK:          WIDEN-CAST ir<%conv> = sitofp ir<%lv> to float (!fpmath !{{[0-9]+}})
+; CHECK:          WIDEN ir<%mul> = fmul ir<%conv>, ir<2.000000e+00> (!fpmath !{{[0-9]+}})
 ; CHECK:          WIDEN-CAST ir<%conv.back> = fptosi ir<%mul> to i32
-; CHECK:          WIDEN store vp<{{.*}}>, ir<%conv.back>
+; CHECK:          WIDEN store vp<{{.*}}>, ir<%conv.back> (!tbaa !{{[0-9]+}})
 ;
 entry:
   br label %loop
@@ -40,9 +40,9 @@ define void @test_intrinsic_with_metadata(ptr noalias %A, ptr noalias %B, i32 %n
 ; CHECK:      VPlan 'Initial VPlan for VF={4},UF>=1' {
 ; CHECK:      <x1> vector loop: {
 ; CHECK:        vector.body:
-; CHECK:          WIDEN ir<%lv> = load vp<{{.*}}>
-; CHECK:          WIDEN-INTRINSIC ir<%sqrt> = call llvm.sqrt(ir<%lv>)
-; CHECK:          WIDEN store vp<{{.*}}>, ir<%sqrt>
+; CHECK:          WIDEN ir<%lv> = load vp<{{.*}}> (!tbaa !{{[0-9]+}})
+; CHECK:          WIDEN-INTRINSIC ir<%sqrt> = call llvm.sqrt(ir<%lv>) (!fpmath !{{[0-9]+}})
+; CHECK:          WIDEN store vp<{{.*}}>, ir<%sqrt> (!tbaa !{{[0-9]+}})
 ;
 entry:
   br label %loop
@@ -67,11 +67,11 @@ define void @test_widen_with_multiple_metadata(ptr noalias %A, ptr noalias %B, i
 ; CHECK:      VPlan 'Initial VPlan for VF={4},UF>=1' {
 ; CHECK:      <x1> vector loop: {
 ; CHECK:        vector.body:
-; CHECK:          WIDEN ir<%lv> = load vp<{{.*}}>
+; CHECK:          WIDEN ir<%lv> = load vp<{{.*}}> (!tbaa !{{[0-9]+}})
 ; CHECK:          WIDEN-CAST ir<%conv> = sitofp ir<%lv> to float
 ; CHECK:          WIDEN ir<%mul> = fmul ir<%conv>, ir<2.000000e+00>
 ; CHECK:          WIDEN-CAST ir<%conv.back> = fptosi ir<%mul> to i32
-; CHECK:          WIDEN store vp<{{.*}}>, ir<%conv.back>
+; CHECK:          WIDEN store vp<{{.*}}>, ir<%conv.back> (!tbaa !{{[0-9]+}})
 ;
 entry:
   br label %loop

>From 5e8f93bbca66dded0932026a2d3773f93e666b98 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Tue, 25 Nov 2025 11:39:21 +0000
Subject: [PATCH 2/2] !fixup use SlotTracker

---
 llvm/lib/Transforms/Vectorize/VPlan.h         |  7 +----
 llvm/lib/Transforms/Vectorize/VPlanHelpers.h  | 21 ++++++++++++-
 .../lib/Transforms/Vectorize/VPlanRecipes.cpp | 15 ++++------
 .../LoopVectorize/vplan-printing-metadata.ll  | 30 +++++++++++++------
 .../Transforms/Vectorize/VPlanTestBase.h      | 14 ++++++---
 5 files changed, 58 insertions(+), 29 deletions(-)

diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h
index 952a8427ec94c..7aca437fc8c38 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.h
+++ b/llvm/lib/Transforms/Vectorize/VPlan.h
@@ -1023,7 +1023,7 @@ class VPIRMetadata {
 
 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
   /// Print metadata with node IDs.
-  void print(raw_ostream &O, const VPlan *Plan) const;
+  void print(raw_ostream &O, VPSlotTracker &SlotTracker) const;
 #endif
 };
 
@@ -4438,11 +4438,6 @@ class VPlan {
   /// Return the VPIRBasicBlock wrapping the header of the scalar loop.
   VPIRBasicBlock *getScalarHeader() const { return ScalarHeader; }
 
-  /// Return the Module from the scalar header.
-  const Module &getModule() const {
-    return *ScalarHeader->getIRBasicBlock()->getModule();
-  }
-
   /// Return an ArrayRef containing VPIRBasicBlocks wrapping the exit blocks of
   /// the original scalar loop.
   ArrayRef<VPIRBasicBlock *> getExitBlocks() const { return ExitBlocks; }
diff --git a/llvm/lib/Transforms/Vectorize/VPlanHelpers.h b/llvm/lib/Transforms/Vectorize/VPlanHelpers.h
index b19a1ea92fb7e..c84e62059c64b 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanHelpers.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanHelpers.h
@@ -394,6 +394,12 @@ class VPSlotTracker {
   /// require slot tracking.
   std::unique_ptr<ModuleSlotTracker> MST;
 
+  /// Cached metadata kind names from the Module's LLVMContext.
+  SmallVector<StringRef> MDNames;
+
+  /// Cached Module pointer for printing metadata.
+  const Module *M = nullptr;
+
   void assignName(const VPValue *V);
   LLVM_ABI_FOR_TEST void assignNames(const VPlan &Plan);
   void assignNames(const VPBasicBlock *VPBB);
@@ -401,14 +407,27 @@ class VPSlotTracker {
 
 public:
   VPSlotTracker(const VPlan *Plan = nullptr) {
-    if (Plan)
+    if (Plan) {
       assignNames(*Plan);
+      if (auto *ScalarHeader = Plan->getScalarHeader())
+        M = ScalarHeader->getIRBasicBlock()->getModule();
+    }
   }
 
   /// Returns the name assigned to \p V, if there is one, otherwise try to
   /// construct one from the underlying value, if there's one; else return
   /// <badref>.
   std::string getOrCreateName(const VPValue *V) const;
+
+  /// Returns the cached metadata kind names.
+  ArrayRef<StringRef> getMDNames() {
+    if (MDNames.empty() && M)
+      M->getContext().getMDKindNames(MDNames);
+    return MDNames;
+  }
+
+  /// Returns the cached Module pointer.
+  const Module *getModule() const { return M; }
 };
 
 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
index 8dacda072b1ba..9fe92a4972def 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
@@ -510,7 +510,7 @@ void VPRecipeBase::print(raw_ostream &O, const Twine &Indent,
 
   if (auto *Metadata = dyn_cast<VPIRMetadata>(this)) {
     if (const VPBasicBlock *Parent = getParent())
-      Metadata->print(O, Parent->getPlan());
+      Metadata->print(O, SlotTracker);
   }
 }
 #endif
@@ -1712,22 +1712,19 @@ void VPIRMetadata::intersect(const VPIRMetadata &Other) {
 }
 
 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-void VPIRMetadata::print(raw_ostream &O, const VPlan *Plan) const {
-  if (Metadata.empty() || !Plan)
+void VPIRMetadata::print(raw_ostream &O, VPSlotTracker &SlotTracker) const {
+  const Module *M = SlotTracker.getModule();
+  if (Metadata.empty() || !M)
     return;
 
-  const Module &M = Plan->getModule();
-  SmallVector<StringRef, 8> MDNames;
-  M.getContext().getMDKindNames(MDNames);
-
+  ArrayRef<StringRef> MDNames = SlotTracker.getMDNames();
   O << " (";
   interleaveComma(Metadata, O, [&](const auto &KindNodePair) {
     auto [Kind, Node] = KindNodePair;
-    assert(Kind != 0 && "Debug metadata should not be managed by VPIRMetadata");
     assert(Kind < MDNames.size() && !MDNames[Kind].empty() &&
            "Unexpected unnamed metadata kind");
     O << "!" << MDNames[Kind] << " ";
-    Node->printAsOperand(O, &M);
+    Node->printAsOperand(O, M);
   });
   O << ")";
 }
diff --git a/llvm/test/Transforms/LoopVectorize/vplan-printing-metadata.ll b/llvm/test/Transforms/LoopVectorize/vplan-printing-metadata.ll
index fb49e94ee67bc..5fbc12448400d 100644
--- a/llvm/test/Transforms/LoopVectorize/vplan-printing-metadata.ll
+++ b/llvm/test/Transforms/LoopVectorize/vplan-printing-metadata.ll
@@ -7,11 +7,16 @@ define void @test_widen_metadata(ptr noalias %A, ptr noalias %B, i32 %n) {
 ; CHECK:      VPlan 'Initial VPlan for VF={4},UF>=1' {
 ; CHECK:      <x1> vector loop: {
 ; CHECK:        vector.body:
-; CHECK:          WIDEN ir<%lv> = load vp<{{.*}}> (!tbaa !{{[0-9]+}})
-; CHECK:          WIDEN-CAST ir<%conv> = sitofp ir<%lv> to float (!fpmath !{{[0-9]+}})
-; CHECK:          WIDEN ir<%mul> = fmul ir<%conv>, ir<2.000000e+00> (!fpmath !{{[0-9]+}})
+; CHECK:          WIDEN ir<%lv> = load vp<{{.*}}> (!tbaa ![[TBAA:[0-9]+]])
+; CHECK:          WIDEN-CAST ir<%conv> = sitofp ir<%lv> to float (!fpmath ![[FPMATH:[0-9]+]])
+; CHECK:          WIDEN ir<%mul> = fmul ir<%conv>, ir<2.000000e+00> (!fpmath ![[FPMATH]])
 ; CHECK:          WIDEN-CAST ir<%conv.back> = fptosi ir<%mul> to i32
-; CHECK:          WIDEN store vp<{{.*}}>, ir<%conv.back> (!tbaa !{{[0-9]+}})
+; CHECK:          WIDEN store vp<{{.*}}>, ir<%conv.back> (!tbaa ![[TBAA]])
+; CHECK:      ir-bb<loop>:
+; CHECK:        IR   %lv = load i32, ptr %gep.A, align 4, !tbaa ![[TBAA]]
+; CHECK:        IR   %conv = sitofp i32 %lv to float, !fpmath ![[FPMATH]]
+; CHECK:        IR   %mul = fmul float %conv, 2.000000e+00, !fpmath ![[FPMATH]]
+; CHECK:        IR   store i32 %conv.back, ptr %gep.B, align 4, !tbaa ![[TBAA]]
 ;
 entry:
   br label %loop
@@ -40,9 +45,13 @@ define void @test_intrinsic_with_metadata(ptr noalias %A, ptr noalias %B, i32 %n
 ; CHECK:      VPlan 'Initial VPlan for VF={4},UF>=1' {
 ; CHECK:      <x1> vector loop: {
 ; CHECK:        vector.body:
-; CHECK:          WIDEN ir<%lv> = load vp<{{.*}}> (!tbaa !{{[0-9]+}})
-; CHECK:          WIDEN-INTRINSIC ir<%sqrt> = call llvm.sqrt(ir<%lv>) (!fpmath !{{[0-9]+}})
-; CHECK:          WIDEN store vp<{{.*}}>, ir<%sqrt> (!tbaa !{{[0-9]+}})
+; CHECK:          WIDEN ir<%lv> = load vp<{{.*}}> (!tbaa ![[TBAA2:[0-9]+]])
+; CHECK:          WIDEN-INTRINSIC ir<%sqrt> = call llvm.sqrt(ir<%lv>) (!fpmath ![[FPMATH2:[0-9]+]])
+; CHECK:          WIDEN store vp<{{.*}}>, ir<%sqrt> (!tbaa ![[TBAA2]])
+; CHECK:      ir-bb<loop>:
+; CHECK:        IR   %lv = load float, ptr %gep.A, align 4, !tbaa ![[TBAA2]]
+; CHECK:        IR   %sqrt = call float @llvm.sqrt.f32(float %lv), !fpmath ![[FPMATH2]]
+; CHECK:        IR   store float %sqrt, ptr %gep.B, align 4, !tbaa ![[TBAA2]]
 ;
 entry:
   br label %loop
@@ -67,11 +76,14 @@ define void @test_widen_with_multiple_metadata(ptr noalias %A, ptr noalias %B, i
 ; CHECK:      VPlan 'Initial VPlan for VF={4},UF>=1' {
 ; CHECK:      <x1> vector loop: {
 ; CHECK:        vector.body:
-; CHECK:          WIDEN ir<%lv> = load vp<{{.*}}> (!tbaa !{{[0-9]+}})
+; CHECK:          WIDEN ir<%lv> = load vp<{{.*}}> (!tbaa ![[TBAA3:[0-9]+]])
 ; CHECK:          WIDEN-CAST ir<%conv> = sitofp ir<%lv> to float
 ; CHECK:          WIDEN ir<%mul> = fmul ir<%conv>, ir<2.000000e+00>
 ; CHECK:          WIDEN-CAST ir<%conv.back> = fptosi ir<%mul> to i32
-; CHECK:          WIDEN store vp<{{.*}}>, ir<%conv.back> (!tbaa !{{[0-9]+}})
+; CHECK:          WIDEN store vp<{{.*}}>, ir<%conv.back> (!tbaa ![[TBAA3]])
+; CHECK:      ir-bb<loop>:
+; CHECK:        IR   %lv = load i32, ptr %gep.A, align 4, !tbaa ![[TBAA3]]
+; CHECK:        IR   store i32 %conv.back, ptr %gep.B, align 4, !tbaa ![[TBAA3]]
 ;
 entry:
   br label %loop
diff --git a/llvm/unittests/Transforms/Vectorize/VPlanTestBase.h b/llvm/unittests/Transforms/Vectorize/VPlanTestBase.h
index 21090c0716d46..3a585e958c3f3 100644
--- a/llvm/unittests/Transforms/Vectorize/VPlanTestBase.h
+++ b/llvm/unittests/Transforms/Vectorize/VPlanTestBase.h
@@ -86,15 +86,21 @@ class VPlanTestIRBase : public testing::Test {
 class VPlanTestBase : public testing::Test {
 protected:
   LLVMContext C;
-  std::unique_ptr<BasicBlock> ScalarHeader;
+  std::unique_ptr<Module> M;
+  Function *F;
+  BasicBlock *ScalarHeader;
   SmallVector<std::unique_ptr<VPlan>> Plans;
 
-  VPlanTestBase() : ScalarHeader(BasicBlock::Create(C, "scalar.header")) {
-    BranchInst::Create(&*ScalarHeader, &*ScalarHeader);
+  VPlanTestBase() {
+    M = std::make_unique<Module>("VPlanTestModule", C);
+    FunctionType *FTy = FunctionType::get(Type::getVoidTy(C), false);
+    F = Function::Create(FTy, GlobalValue::ExternalLinkage, "f", M.get());
+    ScalarHeader = BasicBlock::Create(C, "scalar.header", F);
+    BranchInst::Create(ScalarHeader, ScalarHeader);
   }
 
   VPlan &getPlan() {
-    Plans.push_back(std::make_unique<VPlan>(&*ScalarHeader));
+    Plans.push_back(std::make_unique<VPlan>(ScalarHeader));
     VPlan &Plan = *Plans.back();
     VPValue *DefaultTC = Plan.getConstantInt(32, 1024);
     Plan.setTripCount(DefaultTC);



More information about the llvm-commits mailing list