From e783ed3ed40aa46e34904ee0ceb8604a7849aa68 Mon Sep 17 00:00:00 2001 From: Florian Hahn 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 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(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 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: 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: 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: 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 2a2cb7dbbe1d02cc97c661ac3908b9e73a7f367a Mon Sep 17 00:00:00 2001 From: Florian Hahn 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 | 19 +++++------- .../LoopVectorize/vplan-printing-metadata.ll | 30 +++++++++++++------ .../Transforms/Vectorize/VPlanTestBase.h | 14 ++++++--- 5 files changed, 59 insertions(+), 32 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 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 MST; + /// Cached metadata kind names from the Module's LLVMContext. + SmallVector 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 /// . std::string getOrCreateName(const VPValue *V) const; + + /// Returns the cached metadata kind names. + ArrayRef 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..e1d35c55fef06 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp @@ -508,10 +508,8 @@ void VPRecipeBase::print(raw_ostream &O, const Twine &Indent, DL.print(O); } - if (auto *Metadata = dyn_cast(this)) { - if (const VPBasicBlock *Parent = getParent()) - Metadata->print(O, Parent->getPlan()); - } + if (auto *Metadata = dyn_cast(this)) + Metadata->print(O, SlotTracker); } #endif @@ -1712,22 +1710,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 MDNames; - M.getContext().getMDKindNames(MDNames); - + ArrayRef 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: 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: +; 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: 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: +; 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: 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: +; 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 ScalarHeader; + std::unique_ptr M; + Function *F; + BasicBlock *ScalarHeader; SmallVector> Plans; - VPlanTestBase() : ScalarHeader(BasicBlock::Create(C, "scalar.header")) { - BranchInst::Create(&*ScalarHeader, &*ScalarHeader); + VPlanTestBase() { + M = std::make_unique("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(&*ScalarHeader)); + Plans.push_back(std::make_unique(ScalarHeader)); VPlan &Plan = *Plans.back(); VPValue *DefaultTC = Plan.getConstantInt(32, 1024); Plan.setTripCount(DefaultTC);