Skip to content

Conversation

@fhahn
Copy link
Contributor

@fhahn fhahn commented Oct 31, 2025

Implement and use debug printing for VPIRMetadata.

@github-actions
Copy link

github-actions bot commented Oct 31, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@llvmbot
Copy link
Member

llvmbot commented Oct 31, 2025

@llvm/pr-subscribers-vectorizers

@llvm/pr-subscribers-llvm-transforms

Author: Florian Hahn (fhahn)

Changes

Implement and use debug printing for VPIRMetadata.


Full diff: https://github.com/llvm/llvm-project/pull/165825.diff

2 Files Affected:

  • (modified) llvm/lib/Transforms/Vectorize/VPlan.h (+8)
  • (modified) llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp (+27)
diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h index 1f10058ab4a9a..79583ce34c74d 100644 --- a/llvm/lib/Transforms/Vectorize/VPlan.h +++ b/llvm/lib/Transforms/Vectorize/VPlan.h @@ -968,6 +968,9 @@ class VPIRMetadata { /// Intersect this VPIRMetada object with \p MD, keeping only metadata /// nodes that are common to both. void intersect(const VPIRMetadata &MD); + + /// Print metadata with node IDs. + void print(raw_ostream &O, const Module &M) const; }; /// This is a concrete Recipe that models a single VPlan-level instruction. @@ -4268,6 +4271,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 bde62dd6dd4bc..132bb50e92a7f 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp @@ -1443,6 +1443,7 @@ void VPInstruction::print(raw_ostream &O, const Twine &Indent, printFlags(O); printOperands(O, SlotTracker); + VPIRMetadata::print(O, getParent()->getPlan()->getModule()); if (auto DL = getDebugLoc()) { O << ", !dbg "; @@ -1669,6 +1670,26 @@ void VPIRMetadata::intersect(const VPIRMetadata &Other) { Metadata = std::move(MetadataIntersection); } +void VPIRMetadata::print(raw_ostream &O, const Module &M) const { + if (Metadata.empty()) + return; + + 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 << ")"; +} + + void VPWidenCallRecipe::execute(VPTransformState &State) { assert(State.VF.isVector() && "not widening"); assert(Variant != nullptr && "Can't create vector function."); @@ -1729,6 +1750,7 @@ void VPWidenCallRecipe::print(raw_ostream &O, const Twine &Indent, Op->printAsOperand(O, SlotTracker); }); O << ")"; + VPIRMetadata::print(O, getParent()->getPlan()->getModule()); O << " (using library function"; if (Variant->hasName()) @@ -1863,6 +1885,7 @@ void VPWidenIntrinsicRecipe::print(raw_ostream &O, const Twine &Indent, Op->printAsOperand(O, SlotTracker); }); O << ")"; + VPIRMetadata::print(O, getParent()->getPlan()->getModule()); } #endif @@ -2255,6 +2278,7 @@ void VPWidenRecipe::print(raw_ostream &O, const Twine &Indent, O << " = " << Instruction::getOpcodeName(Opcode); printFlags(O); printOperands(O, SlotTracker); + VPIRMetadata::print(O, getParent()->getPlan()->getModule()); } #endif @@ -2336,6 +2360,7 @@ void VPWidenCastRecipe::print(raw_ostream &O, const Twine &Indent, printFlags(O); printOperands(O, SlotTracker); O << " to " << *getResultType(); + VPIRMetadata::print(O, getParent()->getPlan()->getModule()); } #endif @@ -3618,6 +3643,7 @@ void VPWidenLoadRecipe::print(raw_ostream &O, const Twine &Indent, printAsOperand(O, SlotTracker); O << " = load "; printOperands(O, SlotTracker); + VPIRMetadata::print(O, getParent()->getPlan()->getModule()); } #endif @@ -3739,6 +3765,7 @@ void VPWidenStoreRecipe::print(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const { O << Indent << "WIDEN store "; printOperands(O, SlotTracker); + VPIRMetadata::print(O, getParent()->getPlan()->getModule()); } #endif 
@fhahn fhahn force-pushed the vplan-print-metadata branch 2 times, most recently from bcd6751 to 368bacd Compare November 1, 2025 22:08
Implement and use debug printing for VPIRMetadata.
@fhahn fhahn force-pushed the vplan-print-metadata branch from 368bacd to 6cf1ed5 Compare November 2, 2025 15:18
Copy link
Contributor

@Mel-Chen Mel-Chen left a comment

Choose a reason for hiding this comment

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

LG, but it seems some recipes were missed, such as the interleave recipe.

@ayalz
Copy link
Collaborator

ayalz commented Nov 3, 2025

LG, but it seems some recipes were missed, such as the interleave recipe.

Wonder if there's a way to catch/enforce all derived recipes to print their metadata; seems difficult by intercepting VPValue::printAsOperand() due to multiple inheritance(?)

/// Intersect this VPIRMetada object with \p MD, keeping only metadata
/// nodes that are common to both.
void intersect(const VPIRMetadata &MD);

Copy link
Collaborator

Choose a reason for hiding this comment

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

Under

Suggested change
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)

?

Comment on lines +974 to +976

/// Return true if there is any metadata to print.
bool empty() const { return Metadata.empty(); }
Copy link
Collaborator

Choose a reason for hiding this comment

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

Redundant - print() checks anyhow if there is any metadata to print?

Comment on lines +4291 to +4295
/// Return the Module from the scalar header.
const Module &getModule() const {
return *ScalarHeader->getIRBasicBlock()->getModule();
}

Copy link
Collaborator

Choose a reason for hiding this comment

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

Have VPlan return Module only for VPIRMetadata to print itself (under DEBUG)?
Could (the Module of) VPSlotTracker's MST be used instead?

Comment on lines +1675 to +1676
if (Metadata.empty())
return;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Empty checked anyhow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment