[llvm] [VPlan][test] Fix use-after-free in dumpRecipeInPlan/dumpRecipeUnnamedVPValuesInPlan tests (PR #199275)
Thurston Dang via llvm-commits
llvm-commits at lists.llvm.org
Fri May 22 13:23:07 PDT 2026
https://github.com/thurstond updated https://github.com/llvm/llvm-project/pull/199275
>From ab518722d3fcfe7869e7d4ed8eee941193544e98 Mon Sep 17 00:00:00 2001
From: Thurston Dang <thurston at google.com>
Date: Fri, 22 May 2026 20:14:09 +0000
Subject: [PATCH 1/2] [VPlan][test] Fix use-after-free in
dumpRecipeInPlan/dumpRecipeUnnamedVPValuesInPlan tests
https://github.com/llvm/llvm-project/pull/195891 exposed a use-after-free in the tests: `BinaryOperator *AI` [*] is deleted prior to VPlan's destructor, which expects all the operands to still be alive. This patch fixes the test (suggested by a Florian in https://github.com/llvm/llvm-project/pull/199252#pullrequestreview-4348337988), by ensuring the BinaryOperator is still at the time VPlan is deleted.
[*] No AI was harmed or used during the creation of this patch.
---
.../Transforms/Vectorize/VPlanTest.cpp | 218 +++++++++---------
1 file changed, 114 insertions(+), 104 deletions(-)
diff --git a/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp b/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp
index 9326acb8269e6..65817472e5f70 100644
--- a/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp
+++ b/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp
@@ -1510,132 +1510,142 @@ TEST_F(VPRecipeTest, MayHaveSideEffectsAndMayReadWriteMemory) {
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
TEST_F(VPRecipeTest, dumpRecipeInPlan) {
- VPlan &Plan = getPlan();
- VPBasicBlock *VPBB0 = Plan.getEntry();
- VPBasicBlock *VPBB1 = Plan.createVPBasicBlock("");
- VPBlockUtils::connectBlocks(VPBB1, Plan.getScalarHeader());
- VPBlockUtils::connectBlocks(VPBB0, VPBB1);
-
+ // AI must outlive VPlan &Plan
IntegerType *Int32 = IntegerType::get(C, 32);
auto *AI = BinaryOperator::CreateAdd(PoisonValue::get(Int32),
PoisonValue::get(Int32));
AI->setName("a");
- SmallVector<VPValue *, 2> Args;
- VPValue *ExtVPV1 = Plan.getOrAddLiveIn(ConstantInt::get(Int32, 1));
- VPValue *ExtVPV2 = Plan.getOrAddLiveIn(ConstantInt::get(Int32, 2));
- Args.push_back(ExtVPV1);
- Args.push_back(ExtVPV2);
- VPWidenRecipe *WidenR = new VPWidenRecipe(*AI, Args);
- VPBB1->appendRecipe(WidenR);
{
- // Use EXPECT_EXIT to capture stderr and compare against expected output.
- //
- // Test VPValue::dump().
- VPValue *VPV = WidenR;
- EXPECT_EXIT(
- {
- VPV->dump();
- exit(0);
- },
- testing::ExitedWithCode(0), "WIDEN ir<%a> = add ir<1>, ir<2>");
-
- VPRecipeBase *Def = WidenR;
- EXPECT_EXIT(
- {
- Def->dump();
- exit(0);
- },
- testing::ExitedWithCode(0), "WIDEN ir<%a> = add ir<1>, ir<2>");
-
- EXPECT_EXIT(
- {
- WidenR->dump();
- exit(0);
- },
- testing::ExitedWithCode(0), "WIDEN ir<%a> = add ir<1>, ir<2>");
+ VPlan &Plan = getPlan();
+ VPBasicBlock *VPBB0 = Plan.getEntry();
+ VPBasicBlock *VPBB1 = Plan.createVPBasicBlock("");
+ VPBlockUtils::connectBlocks(VPBB1, Plan.getScalarHeader());
+ VPBlockUtils::connectBlocks(VPBB0, VPBB1);
- // Test VPRecipeBase::dump().
- VPRecipeBase *R = WidenR;
- EXPECT_EXIT(
- {
- R->dump();
- exit(0);
- },
- testing::ExitedWithCode(0), "WIDEN ir<%a> = add ir<1>, ir<2>");
+ SmallVector<VPValue *, 2> Args;
+ VPValue *ExtVPV1 = Plan.getOrAddLiveIn(ConstantInt::get(Int32, 1));
+ VPValue *ExtVPV2 = Plan.getOrAddLiveIn(ConstantInt::get(Int32, 2));
+ Args.push_back(ExtVPV1);
+ Args.push_back(ExtVPV2);
+ VPWidenRecipe *WidenR = new VPWidenRecipe(*AI, Args);
+ VPBB1->appendRecipe(WidenR);
+
+ {
+ // Use EXPECT_EXIT to capture stderr and compare against expected output.
+ //
+ // Test VPValue::dump().
+ VPValue *VPV = WidenR;
+ EXPECT_EXIT(
+ {
+ VPV->dump();
+ exit(0);
+ },
+ testing::ExitedWithCode(0), "WIDEN ir<%a> = add ir<1>, ir<2>");
+
+ VPRecipeBase *Def = WidenR;
+ EXPECT_EXIT(
+ {
+ Def->dump();
+ exit(0);
+ },
+ testing::ExitedWithCode(0), "WIDEN ir<%a> = add ir<1>, ir<2>");
+
+ EXPECT_EXIT(
+ {
+ WidenR->dump();
+ exit(0);
+ },
+ testing::ExitedWithCode(0), "WIDEN ir<%a> = add ir<1>, ir<2>");
+
+ // Test VPRecipeBase::dump().
+ VPRecipeBase *R = WidenR;
+ EXPECT_EXIT(
+ {
+ R->dump();
+ exit(0);
+ },
+ testing::ExitedWithCode(0), "WIDEN ir<%a> = add ir<1>, ir<2>");
+ }
}
delete AI;
}
TEST_F(VPRecipeTest, dumpRecipeUnnamedVPValuesInPlan) {
- VPlan &Plan = getPlan();
- VPBasicBlock *VPBB0 = Plan.getEntry();
- VPBasicBlock *VPBB1 = Plan.createVPBasicBlock("");
- VPBlockUtils::connectBlocks(VPBB1, Plan.getScalarHeader());
- VPBlockUtils::connectBlocks(VPBB0, VPBB1);
-
+ // AI must outlive VPlan &Plan
IntegerType *Int32 = IntegerType::get(C, 32);
auto *AI = BinaryOperator::CreateAdd(PoisonValue::get(Int32),
PoisonValue::get(Int32));
AI->setName("a");
- SmallVector<VPValue *, 2> Args;
- VPValue *ExtVPV1 = Plan.getOrAddLiveIn(ConstantInt::get(Int32, 1));
- VPValue *ExtVPV2 = Plan.getOrAddLiveIn(AI);
- Args.push_back(ExtVPV1);
- Args.push_back(ExtVPV2);
- VPInstruction *I1 =
- new VPInstruction(Instruction::Add, {ExtVPV1, ExtVPV2},
- VPIRFlags::getDefaultFlags(Instruction::Add));
- VPInstruction *I2 = new VPInstruction(
- Instruction::Mul, {I1, I1}, VPIRFlags::getDefaultFlags(Instruction::Mul));
- VPBB1->appendRecipe(I1);
- VPBB1->appendRecipe(I2);
- // Check printing I1.
{
- // Use EXPECT_EXIT to capture stderr and compare against expected output.
- //
- // Test VPValue::dump().
- VPValue *VPV = I1;
- EXPECT_EXIT(
- {
- VPV->dump();
- exit(0);
- },
- testing::ExitedWithCode(0), "EMIT vp<%1> = add ir<1>, ir<%a>");
+ VPlan &Plan = getPlan();
+ VPBasicBlock *VPBB0 = Plan.getEntry();
+ VPBasicBlock *VPBB1 = Plan.createVPBasicBlock("");
+ VPBlockUtils::connectBlocks(VPBB1, Plan.getScalarHeader());
+ VPBlockUtils::connectBlocks(VPBB0, VPBB1);
- // Test VPRecipeBase::dump().
- VPRecipeBase *R = I1;
- EXPECT_EXIT(
- {
- R->dump();
- exit(0);
- },
- testing::ExitedWithCode(0), "EMIT vp<%1> = add ir<1>, ir<%a>");
+ SmallVector<VPValue *, 2> Args;
+ VPValue *ExtVPV1 = Plan.getOrAddLiveIn(ConstantInt::get(Int32, 1));
+ VPValue *ExtVPV2 = Plan.getOrAddLiveIn(AI);
+ Args.push_back(ExtVPV1);
+ Args.push_back(ExtVPV2);
+ VPInstruction *I1 =
+ new VPInstruction(Instruction::Add, {ExtVPV1, ExtVPV2},
+ VPIRFlags::getDefaultFlags(Instruction::Add));
+ VPInstruction *I2 =
+ new VPInstruction(Instruction::Mul, {I1, I1},
+ VPIRFlags::getDefaultFlags(Instruction::Mul));
+ VPBB1->appendRecipe(I1);
+ VPBB1->appendRecipe(I2);
+
+ // Check printing I1.
+ {
+ // Use EXPECT_EXIT to capture stderr and compare against expected output.
+ //
+ // Test VPValue::dump().
+ VPValue *VPV = I1;
+ EXPECT_EXIT(
+ {
+ VPV->dump();
+ exit(0);
+ },
+ testing::ExitedWithCode(0), "EMIT vp<%1> = add ir<1>, ir<%a>");
+
+ // Test VPRecipeBase::dump().
+ VPRecipeBase *R = I1;
+ EXPECT_EXIT(
+ {
+ R->dump();
+ exit(0);
+ },
+ testing::ExitedWithCode(0), "EMIT vp<%1> = add ir<1>, ir<%a>");
+ }
+ // Check printing I2.
+ {
+ // Use EXPECT_EXIT to capture stderr and compare against expected output.
+ //
+ // Test VPValue::dump().
+ VPValue *VPV = I2;
+ EXPECT_EXIT(
+ {
+ VPV->dump();
+ exit(0);
+ },
+ testing::ExitedWithCode(0), "EMIT vp<%2> = mul vp<%1>, vp<%1>");
+
+ // Test VPRecipeBase::dump().
+ VPRecipeBase *R = I2;
+ EXPECT_EXIT(
+ {
+ R->dump();
+ exit(0);
+ },
+ testing::ExitedWithCode(0), "EMIT vp<%2> = mul vp<%1>, vp<%1>");
+ }
}
- // Check printing I2.
- {
- // Use EXPECT_EXIT to capture stderr and compare against expected output.
- //
- // Test VPValue::dump().
- VPValue *VPV = I2;
- EXPECT_EXIT(
- {
- VPV->dump();
- exit(0);
- },
- testing::ExitedWithCode(0), "EMIT vp<%2> = mul vp<%1>, vp<%1>");
- // Test VPRecipeBase::dump().
- VPRecipeBase *R = I2;
- EXPECT_EXIT(
- {
- R->dump();
- exit(0);
- },
- testing::ExitedWithCode(0), "EMIT vp<%2> = mul vp<%1>, vp<%1>");
- }
delete AI;
}
>From a6e3e93e8df07d64017ad366f2005c078d06f2cf Mon Sep 17 00:00:00 2001
From: Thurston Dang <thurston at google.com>
Date: Fri, 22 May 2026 20:22:42 +0000
Subject: [PATCH 2/2] Address feedback from Florian Google
---
llvm/unittests/Transforms/Vectorize/VPlanTest.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp b/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp
index 65817472e5f70..1aac7df331f66 100644
--- a/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp
+++ b/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp
@@ -1510,8 +1510,8 @@ TEST_F(VPRecipeTest, MayHaveSideEffectsAndMayReadWriteMemory) {
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
TEST_F(VPRecipeTest, dumpRecipeInPlan) {
- // AI must outlive VPlan &Plan
IntegerType *Int32 = IntegerType::get(C, 32);
+ // AI must outlive VPlan &Plan
auto *AI = BinaryOperator::CreateAdd(PoisonValue::get(Int32),
PoisonValue::get(Int32));
AI->setName("a");
@@ -1573,8 +1573,8 @@ TEST_F(VPRecipeTest, dumpRecipeInPlan) {
}
TEST_F(VPRecipeTest, dumpRecipeUnnamedVPValuesInPlan) {
- // AI must outlive VPlan &Plan
IntegerType *Int32 = IntegerType::get(C, 32);
+ // AI must outlive VPlan &Plan
auto *AI = BinaryOperator::CreateAdd(PoisonValue::get(Int32),
PoisonValue::get(Int32));
AI->setName("a");
More information about the llvm-commits
mailing list