Skip to content

Conversation

@fhahn
Copy link
Contributor

@fhahn fhahn commented Nov 17, 2025

mplement printing for VPIRMetadata, using generic dyn_cast to VPIRMetadata.

Depends on #166245 (included in the PR)

@llvmbot
Copy link
Member

llvmbot commented Nov 17, 2025

@llvm/pr-subscribers-vectorizers

@llvm/pr-subscribers-llvm-transforms

Author: Florian Hahn (fhahn)

Changes

mplement printing for VPIRMetadata, using generic dyn_cast to VPIRMetadata.

Depends on #166245 (included in the PR)


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

5 Files Affected:

  • (modified) llvm/lib/Transforms/Vectorize/VPlan.h (+81)
  • (modified) llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp (+24)
  • (modified) llvm/test/Transforms/LoopVectorize/vplan-printing-metadata.ll (+9-9)
  • (modified) llvm/unittests/Transforms/Vectorize/VPlanTest.cpp (+31-26)
  • (modified) llvm/unittests/Transforms/Vectorize/VPlanTestBase.h (+10-3)
diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h index 13131a2b61722..e1fbce731c31c 100644 --- a/llvm/lib/Transforms/Vectorize/VPlan.h +++ b/llvm/lib/Transforms/Vectorize/VPlan.h @@ -983,6 +983,11 @@ class VPIRMetadata { /// Intersect this VPIRMetada object with \p MD, keeping only metadata /// nodes that are common to both. void intersect(const VPIRMetadata &MD); + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) + /// Print metadata with node IDs. + void print(raw_ostream &O, const Module &M) const; +#endif }; /// This is a concrete Recipe that models a single VPlan-level instruction. @@ -3869,6 +3874,77 @@ template <> struct CastInfo<VPPhiAccessors, const VPRecipeBase *> : CastInfoVPPhiAccessors<const VPRecipeBase *> {}; +/// Casting from VPRecipeBase -> VPIRMetadata is supported for all recipe types +/// implementing VPIRMetadata. Used by isa<> & co. +namespace detail { +/// Returns const VPIRMetadata* if input is const, and VPIRMetadata* otherwise. +template <typename RecipeBasePtrTy> +static inline auto castToVPIRMetadata(RecipeBasePtrTy R) -> std::conditional_t< + std::is_const_v<std::remove_pointer_t<RecipeBasePtrTy>>, + const VPIRMetadata *, VPIRMetadata *> { + switch (R->getVPDefID()) { + case VPDef::VPInstructionSC: + return cast<VPInstruction>(R); + case VPDef::VPWidenSC: + return cast<VPWidenRecipe>(R); + case VPDef::VPWidenCastSC: + return cast<VPWidenCastRecipe>(R); + case VPDef::VPWidenIntrinsicSC: + return cast<VPWidenIntrinsicRecipe>(R); + case VPDef::VPWidenCallSC: + return cast<VPWidenCallRecipe>(R); + case VPDef::VPWidenSelectSC: + return cast<VPWidenSelectRecipe>(R); + case VPDef::VPReplicateSC: + return cast<VPReplicateRecipe>(R); + case VPDef::VPInterleaveSC: + return cast<VPInterleaveRecipe>(R); + case VPDef::VPInterleaveEVLSC: + return cast<VPInterleaveEVLRecipe>(R); + case VPDef::VPWidenLoadSC: + return cast<VPWidenLoadRecipe>(R); + case VPDef::VPWidenLoadEVLSC: + return cast<VPWidenLoadEVLRecipe>(R); + case VPDef::VPWidenStoreSC: + return cast<VPWidenStoreRecipe>(R); + case VPDef::VPWidenStoreEVLSC: + return cast<VPWidenStoreEVLRecipe>(R); + default: + llvm_unreachable("invalid recipe for VPIRMetadata cast"); + } +} +} // namespace detail + +/// Support casting from VPRecipeBase -> VPIRMetadata, by down-casting to the +/// recipe types implementing VPIRMetadata. Used by cast<>, dyn_cast<> & co. +template <typename SrcTy> +struct CastInfoVPIRMetadata : public CastIsPossible<VPIRMetadata, SrcTy> { + static inline bool isPossible(SrcTy R) { + return isa<VPInstruction, VPWidenRecipe, VPWidenCastRecipe, + VPWidenIntrinsicRecipe, VPWidenCallRecipe, VPWidenSelectRecipe, + VPReplicateRecipe, VPInterleaveRecipe, VPInterleaveEVLRecipe, + VPWidenLoadRecipe, VPWidenLoadEVLRecipe, VPWidenStoreRecipe, + VPWidenStoreEVLRecipe>(R); + } + + using Self = CastInfo<VPIRMetadata, SrcTy>; + using RetTy = decltype(detail::castToVPIRMetadata(std::declval<SrcTy>())); + + static inline RetTy doCast(SrcTy R) { return detail::castToVPIRMetadata(R); } + + static inline RetTy doCastIfPossible(SrcTy R) { + if (!Self::isPossible(R)) + return nullptr; + return doCast(R); + } +}; +template <> +struct CastInfo<VPIRMetadata, VPRecipeBase *> + : CastInfoVPIRMetadata<VPRecipeBase *> {}; +template <> +struct CastInfo<VPIRMetadata, const VPRecipeBase *> + : CastInfoVPIRMetadata<const VPRecipeBase *> {}; + /// VPBasicBlock serves as the leaf of the Hierarchical Control-Flow Graph. It /// holds a sequence of zero or more VPRecipe's each representing a sequence of /// output IR instructions. All PHI-like recipes must come before any non-PHI recipes. @@ -4333,6 +4409,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 cf95b4eac9d75..246292b9d9d61 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp @@ -489,6 +489,9 @@ void VPSingleDefRecipe::dump() const { VPDef::dump(); } void VPRecipeBase::print(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const { printRecipe(O, Indent, SlotTracker); + + if (auto *Metadata = dyn_cast<VPIRMetadata>(this)) + Metadata->print(O, getParent()->getPlan()->getModule()); } #endif @@ -1703,6 +1706,27 @@ void VPIRMetadata::intersect(const VPIRMetadata &Other) { Metadata = std::move(MetadataIntersection); } +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +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 << ")"; +} +#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 diff --git a/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp b/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp index ee7fa175ca918..7cea64625fe5f 100644 --- a/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp +++ b/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp @@ -743,8 +743,10 @@ TEST_F(VPBasicBlockTest, print) { VPBB2->setName("bb2"); VPBlockUtils::connectBlocks(VPBB1, VPBB2); + VPBlockUtils::connectBlocks(VPBB2, Plan.getScalarHeader()); + VPBlockUtils::connectBlocks(VPBB0, VPBB1); - // Check printing an instruction without associated VPlan. + // Check printing an instruction with associated VPlan. { std::string I3Dump; raw_string_ostream OS(I3Dump); @@ -753,8 +755,6 @@ TEST_F(VPBasicBlockTest, print) { EXPECT_EQ("EMIT store <badref>, <badref>", I3Dump); } - VPBlockUtils::connectBlocks(VPBB2, Plan.getScalarHeader()); - VPBlockUtils::connectBlocks(VPBB0, VPBB1); std::string FullDump; raw_string_ostream OS(FullDump); Plan.printDOT(OS); @@ -996,7 +996,7 @@ TEST_F(VPRecipeTest, CastVPInstructionToVPUser) { VPValue *Op2 = Plan.getOrAddLiveIn(ConstantInt::get(Int32, 2)); VPInstruction Recipe(Instruction::Add, {Op1, Op2}); - checkVPRecipeCastImpl<VPInstruction, VPUser>(&Recipe); + checkVPRecipeCastImpl<VPInstruction, VPUser, VPIRMetadata>(&Recipe); } TEST_F(VPRecipeTest, CastVPWidenRecipeToVPUser) { @@ -1011,7 +1011,7 @@ TEST_F(VPRecipeTest, CastVPWidenRecipeToVPUser) { Args.push_back(Op2); VPWidenRecipe WidenR(*AI, make_range(Args.begin(), Args.end())); - checkVPRecipeCastImpl<VPWidenRecipe, VPUser>(&WidenR); + checkVPRecipeCastImpl<VPWidenRecipe, VPUser, VPIRMetadata>(&WidenR); delete AI; } @@ -1030,7 +1030,7 @@ TEST_F(VPRecipeTest, CastVPWidenCallRecipeToVPUserAndVPDef) { Args.push_back(CalledFn); VPWidenCallRecipe Recipe(Call, Fn, Args); - checkVPRecipeCastImpl<VPWidenCallRecipe, VPUser>(&Recipe); + checkVPRecipeCastImpl<VPWidenCallRecipe, VPUser, VPIRMetadata>(&Recipe); VPValue *VPV = &Recipe; EXPECT_TRUE(VPV->getDefiningRecipe()); @@ -1056,7 +1056,8 @@ TEST_F(VPRecipeTest, CastVPWidenSelectRecipeToVPUserAndVPDef) { VPWidenSelectRecipe WidenSelectR(*SelectI, make_range(Args.begin(), Args.end())); - checkVPRecipeCastImpl<VPWidenSelectRecipe, VPUser>(&WidenSelectR); + checkVPRecipeCastImpl<VPWidenSelectRecipe, VPUser, VPIRMetadata>( + &WidenSelectR); VPValue *VPV = &WidenSelectR; EXPECT_EQ(&WidenSelectR, VPV->getDefiningRecipe()); @@ -1094,7 +1095,7 @@ TEST_F(VPRecipeTest, CastVPWidenCastRecipeToVPUser) { VPValue *Op1 = Plan.getOrAddLiveIn(ConstantInt::get(Int32, 1)); VPWidenCastRecipe Recipe(Instruction::ZExt, Op1, Int64, *Cast); - checkVPRecipeCastImpl<VPWidenCastRecipe, VPUser>(&Recipe); + checkVPRecipeCastImpl<VPWidenCastRecipe, VPUser, VPIRMetadata>(&Recipe); delete Cast; } @@ -1105,7 +1106,7 @@ TEST_F(VPRecipeTest, CastVPWidenIntrinsicRecipeToVPUser) { VPValue *Op2 = Plan.getOrAddLiveIn(ConstantInt::get(Int32, 2)); VPWidenIntrinsicRecipe Recipe(Intrinsic::smax, {Op1, Op2}, Int32); - checkVPRecipeCastImpl<VPWidenIntrinsicRecipe, VPUser>(&Recipe); + checkVPRecipeCastImpl<VPWidenIntrinsicRecipe, VPUser, VPIRMetadata>(&Recipe); } TEST_F(VPRecipeTest, CastVPBlendRecipeToVPUser) { @@ -1135,7 +1136,7 @@ TEST_F(VPRecipeTest, CastVPInterleaveRecipeToVPUser) { InterleaveGroup<Instruction> IG(4, false, Align(4)); VPInterleaveRecipe Recipe(&IG, Addr, {}, Mask, false, {}, DebugLoc()); - checkVPRecipeCastImpl<VPInterleaveRecipe, VPUser>(&Recipe); + checkVPRecipeCastImpl<VPInterleaveRecipe, VPUser, VPIRMetadata>(&Recipe); } TEST_F(VPRecipeTest, CastVPReplicateRecipeToVPUser) { @@ -1151,7 +1152,7 @@ TEST_F(VPRecipeTest, CastVPReplicateRecipeToVPUser) { auto *Call = CallInst::Create(FTy, PoisonValue::get(FTy)); VPReplicateRecipe Recipe(Call, make_range(Args.begin(), Args.end()), true); - checkVPRecipeCastImpl<VPReplicateRecipe, VPUser>(&Recipe); + checkVPRecipeCastImpl<VPReplicateRecipe, VPUser, VPIRMetadata>(&Recipe); delete Call; } @@ -1175,7 +1176,7 @@ TEST_F(VPRecipeTest, CastVPWidenMemoryRecipeToVPUserAndVPDef) { VPValue *Mask = Plan.getOrAddLiveIn(ConstantInt::get(Int32, 2)); VPWidenLoadRecipe Recipe(*Load, Addr, Mask, true, false, {}, {}); - checkVPRecipeCastImpl<VPWidenLoadRecipe, VPUser>(&Recipe); + checkVPRecipeCastImpl<VPWidenLoadRecipe, VPUser, VPIRMetadata>(&Recipe); VPValue *VPV = Recipe.getVPSingleValue(); EXPECT_TRUE(isa<VPRecipeBase>(VPV->getDefiningRecipe())); @@ -1194,7 +1195,7 @@ TEST_F(VPRecipeTest, CastVPInterleaveEVLRecipeToVPUser) { VPInterleaveRecipe BaseRecipe(&IG, Addr, {}, Mask, false, {}, DebugLoc()); VPInterleaveEVLRecipe Recipe(BaseRecipe, *EVL, Mask); - checkVPRecipeCastImpl<VPInterleaveEVLRecipe, VPUser>(&Recipe); + checkVPRecipeCastImpl<VPInterleaveEVLRecipe, VPUser, VPIRMetadata>(&Recipe); } TEST_F(VPRecipeTest, CastVPWidenLoadEVLRecipeToVPUser) { @@ -1209,7 +1210,7 @@ TEST_F(VPRecipeTest, CastVPWidenLoadEVLRecipeToVPUser) { VPWidenLoadRecipe BaseLoad(*Load, Addr, Mask, true, false, {}, {}); VPWidenLoadEVLRecipe Recipe(BaseLoad, Addr, *EVL, Mask); - checkVPRecipeCastImpl<VPWidenLoadEVLRecipe, VPUser>(&Recipe); + checkVPRecipeCastImpl<VPWidenLoadEVLRecipe, VPUser, VPIRMetadata>(&Recipe); delete Load; } @@ -1225,7 +1226,7 @@ TEST_F(VPRecipeTest, CastVPWidenStoreRecipeToVPUser) { VPValue *Mask = Plan.getOrAddLiveIn(ConstantInt::get(Int32, 2)); VPWidenStoreRecipe Recipe(*Store, Addr, StoredVal, Mask, true, false, {}, {}); - checkVPRecipeCastImpl<VPWidenStoreRecipe, VPUser>(&Recipe); + checkVPRecipeCastImpl<VPWidenStoreRecipe, VPUser, VPIRMetadata>(&Recipe); delete Store; } @@ -1244,7 +1245,7 @@ TEST_F(VPRecipeTest, CastVPWidenStoreEVLRecipeToVPUser) { {}); VPWidenStoreEVLRecipe Recipe(BaseStore, Addr, *EVL, Mask); - checkVPRecipeCastImpl<VPWidenStoreEVLRecipe, VPUser>(&Recipe); + checkVPRecipeCastImpl<VPWidenStoreEVLRecipe, VPUser, VPIRMetadata>(&Recipe); delete Store; } @@ -1611,12 +1612,18 @@ TEST_F(VPRecipeTest, dumpRecipeUnnamedVPValuesNotInPlanOrBlock) { auto *AI = BinaryOperator::CreateAdd(PoisonValue::get(Int32), PoisonValue::get(Int32)); AI->setName("a"); - VPValue *ExtVPV1 = getPlan().getOrAddLiveIn(ConstantInt::get(Int32, 1)); - VPValue *ExtVPV2 = getPlan().getOrAddLiveIn(AI); + VPlan &Plan = getPlan(); + VPValue *ExtVPV1 = Plan.getOrAddLiveIn(ConstantInt::get(Int32, 1)); + VPValue *ExtVPV2 = Plan.getOrAddLiveIn(AI); VPInstruction *I1 = new VPInstruction(Instruction::Add, {ExtVPV1, ExtVPV2}); VPInstruction *I2 = new VPInstruction(Instruction::Mul, {I1, I1}); + // Add instructions to a block in the plan so they have access to Module + VPBasicBlock *VPBB = Plan.getEntry(); + VPBB->appendRecipe(I1); + VPBB->appendRecipe(I2); + // Check printing I1. { // Use EXPECT_EXIT to capture stderr and compare against expected output. @@ -1628,7 +1635,7 @@ TEST_F(VPRecipeTest, dumpRecipeUnnamedVPValuesNotInPlanOrBlock) { VPV->dump(); exit(0); }, - testing::ExitedWithCode(0), "EMIT <badref> = add ir<1>, ir<%a>"); + testing::ExitedWithCode(0), "EMIT vp<%1> = add ir<1>, ir<%a>"); // Test VPRecipeBase::dump(). VPRecipeBase *R = I1; @@ -1637,7 +1644,7 @@ TEST_F(VPRecipeTest, dumpRecipeUnnamedVPValuesNotInPlanOrBlock) { R->dump(); exit(0); }, - testing::ExitedWithCode(0), "EMIT <badref> = add ir<1>, ir<%a>"); + testing::ExitedWithCode(0), "EMIT vp<%1> = add ir<1>, ir<%a>"); // Test VPDef::dump(). VPDef *D = I1; @@ -1646,7 +1653,7 @@ TEST_F(VPRecipeTest, dumpRecipeUnnamedVPValuesNotInPlanOrBlock) { D->dump(); exit(0); }, - testing::ExitedWithCode(0), "EMIT <badref> = add ir<1>, ir<%a>"); + testing::ExitedWithCode(0), "EMIT vp<%1> = add ir<1>, ir<%a>"); } // Check printing I2. { @@ -1659,7 +1666,7 @@ TEST_F(VPRecipeTest, dumpRecipeUnnamedVPValuesNotInPlanOrBlock) { VPV->dump(); exit(0); }, - testing::ExitedWithCode(0), "EMIT <badref> = mul <badref>, <badref>"); + testing::ExitedWithCode(0), "EMIT vp<%2> = mul vp<%1>, vp<%1>"); // Test VPRecipeBase::dump(). VPRecipeBase *R = I2; @@ -1668,7 +1675,7 @@ TEST_F(VPRecipeTest, dumpRecipeUnnamedVPValuesNotInPlanOrBlock) { R->dump(); exit(0); }, - testing::ExitedWithCode(0), "EMIT <badref> = mul <badref>, <badref>"); + testing::ExitedWithCode(0), "EMIT vp<%2> = mul vp<%1>, vp<%1>"); // Test VPDef::dump(). VPDef *D = I2; @@ -1677,11 +1684,9 @@ TEST_F(VPRecipeTest, dumpRecipeUnnamedVPValuesNotInPlanOrBlock) { D->dump(); exit(0); }, - testing::ExitedWithCode(0), "EMIT <badref> = mul <badref>, <badref>"); + testing::ExitedWithCode(0), "EMIT vp<%2> = mul vp<%1>, vp<%1>"); } - delete I2; - delete I1; delete AI; } diff --git a/llvm/unittests/Transforms/Vectorize/VPlanTestBase.h b/llvm/unittests/Transforms/Vectorize/VPlanTestBase.h index 21090c0716d46..84bf3b60b0296 100644 --- a/llvm/unittests/Transforms/Vectorize/VPlanTestBase.h +++ b/llvm/unittests/Transforms/Vectorize/VPlanTestBase.h @@ -86,11 +86,18 @@ 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>("VPlanTest", C); + FunctionType *FTy = FunctionType::get(Type::getVoidTy(C), false); + F = Function::Create(FTy, GlobalValue::ExternalLinkage, "test_function", + M.get()); + ScalarHeader = BasicBlock::Create(C, "scalar.header", F); + BranchInst::Create(ScalarHeader, ScalarHeader); } VPlan &getPlan() { 
Implement and use debug printing for VPIRMetadata. !fixup address comments, thanks!
@fhahn fhahn force-pushed the vplan-print-metadata branch from beae906 to 96de4eb Compare November 17, 2025 20:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment