[llvm] [VPlan] Add unit test for createAndOptimizeReplicateRegions. NFC (PR #164652)
Luke Lau via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 22 09:21:47 PDT 2025
https://github.com/lukel97 updated https://github.com/llvm/llvm-project/pull/164652
>From 8e02164ba179038eb8022db307cc0bafe763496b Mon Sep 17 00:00:00 2001
From: Luke Lau <luke at igalia.com>
Date: Thu, 23 Oct 2025 00:00:27 +0800
Subject: [PATCH 1/2] [VPlan] Add unit test for
createAndOptimizeReplicateRegions. NFC
In #160449 some of the tests end up merging less blocks so we end up losing test coverage.
This adds a unit test to try and cover it elsewhere in a more predictable way, so it won't be influenced by e.g. whether or not the cost model decides to scalarize an instruction.
Two parts in createReplicateRegion/addReplicateRegions had to be relaxed to allow using a fake Instruction with no BasicBlock parent. I wasn't able to create a fake BasicBlock in the test without hitting iterator assertions.
---
.../Transforms/Vectorize/VPlanTransforms.cpp | 6 +-
.../Transforms/Vectorize/CMakeLists.txt | 1 +
.../Vectorize/VPlanTransformsTest.cpp | 77 +++++++++++++++++++
3 files changed, 81 insertions(+), 3 deletions(-)
create mode 100644 llvm/unittests/Transforms/Vectorize/VPlanTransformsTest.cpp
diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
index 7bf8d83d2550c..90d8cfc791097 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
@@ -345,7 +345,6 @@ static VPRegionBlock *createReplicateRegion(VPReplicateRecipe *PredRecipe,
Instruction *Instr = PredRecipe->getUnderlyingInstr();
// Build the triangular if-then region.
std::string RegionName = (Twine("pred.") + Instr->getOpcodeName()).str();
- assert(Instr->getParent() && "Predicated instruction not in any basic block");
auto *BlockInMask = PredRecipe->getMask();
auto *MaskDef = BlockInMask->getDefiningRecipe();
auto *BOMRecipe = new VPBranchOnMaskRecipe(
@@ -399,8 +398,9 @@ static void addReplicateRegions(VPlan &Plan) {
VPBasicBlock *SplitBlock = CurrentBlock->splitAt(RepR->getIterator());
BasicBlock *OrigBB = RepR->getUnderlyingInstr()->getParent();
- SplitBlock->setName(
- OrigBB->hasName() ? OrigBB->getName() + "." + Twine(BBNum++) : "");
+ SplitBlock->setName((OrigBB && OrigBB->hasName())
+ ? OrigBB->getName() + "." + Twine(BBNum++)
+ : "");
// Record predicated instructions for above packing optimizations.
VPRegionBlock *Region = createReplicateRegion(RepR, Plan);
Region->setParent(CurrentBlock->getParent());
diff --git a/llvm/unittests/Transforms/Vectorize/CMakeLists.txt b/llvm/unittests/Transforms/Vectorize/CMakeLists.txt
index af111a29b90e5..3564bd140c971 100644
--- a/llvm/unittests/Transforms/Vectorize/CMakeLists.txt
+++ b/llvm/unittests/Transforms/Vectorize/CMakeLists.txt
@@ -14,6 +14,7 @@ add_llvm_unittest(VectorizeTests
VPlanHCFGTest.cpp
VPlanPatternMatchTest.cpp
VPlanSlpTest.cpp
+ VPlanTransformsTest.cpp
VPlanUncountableExitTest.cpp
VPlanVerifierTest.cpp
)
diff --git a/llvm/unittests/Transforms/Vectorize/VPlanTransformsTest.cpp b/llvm/unittests/Transforms/Vectorize/VPlanTransformsTest.cpp
new file mode 100644
index 0000000000000..ab94337d61e39
--- /dev/null
+++ b/llvm/unittests/Transforms/Vectorize/VPlanTransformsTest.cpp
@@ -0,0 +1,77 @@
+//===- llvm/unittests/Transforms/Vectorize/VPlanTransformsTest.cpp --------===//
+//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "../lib/Transforms/Vectorize/VPlanTransforms.h"
+#include "../lib/Transforms/Vectorize/VPlan.h"
+#include "VPlanTestBase.h"
+#include "gtest/gtest.h"
+
+namespace llvm {
+
+namespace {
+using VPlanTransformsTest = VPlanTestBase;
+
+// Test we create and merge replicate regions:
+// VPBB1:
+// REPLICATE %Rep0 = add
+// REPLICATE %Rep1 = add
+// REPLICATE %Rep2 = add
+// No successors
+//
+// ->
+//
+// <xVFxUF> pred.add: {
+// pred.add.entry:
+// BRANCH-ON-MASK %Mask
+// Successor(s): pred.add.if, pred.add.continue
+//
+// pred.add.if:
+// REPLICATE %Rep0 = add
+// REPLICATE %Rep1 = add
+// REPLICATE %Rep2 = add
+// Successor(s): pred.add.continue
+//
+// pred.add.continue:
+// No successors
+// }
+TEST_F(VPlanTransformsTest, createAndOptimizeReplicateRegions) {
+ VPlan &Plan = getPlan();
+
+ IntegerType *Int32 = IntegerType::get(C, 32);
+ auto *AI = BinaryOperator::CreateAdd(PoisonValue::get(Int32),
+ PoisonValue::get(Int32));
+
+ auto *VPBB0 = Plan.getEntry();
+ auto *VPBB1 = Plan.createVPBasicBlock("VPBB1");
+ VPRegionBlock *R1 = Plan.createVPRegionBlock(VPBB1, VPBB1, "R1");
+ VPBlockUtils::connectBlocks(VPBB0, R1);
+ auto *Mask = new VPInstruction(0, {});
+ auto *Rep0 = new VPReplicateRecipe(AI, {}, false, Mask);
+ auto *Rep1 = new VPReplicateRecipe(AI, {}, false, Mask);
+ auto *Rep2 = new VPReplicateRecipe(AI, {}, false, Mask);
+ VPBB1->appendRecipe(Rep0);
+ VPBB1->appendRecipe(Rep1);
+ VPBB1->appendRecipe(Rep2);
+
+ VPlanTransforms::createAndOptimizeReplicateRegions(Plan);
+
+ auto *Replicator = cast<VPRegionBlock>(R1->getEntry()->getSingleSuccessor());
+ EXPECT_TRUE(Replicator->isReplicator());
+ auto *ReplicatorEntry = cast<VPBasicBlock>(Replicator->getEntry());
+ EXPECT_EQ(ReplicatorEntry->size(), 1u);
+ EXPECT_TRUE(isa<VPBranchOnMaskRecipe>(ReplicatorEntry->front()));
+ auto *ReplicatorIf = cast<VPBasicBlock>(ReplicatorEntry->getSuccessors()[0]);
+ EXPECT_EQ(ReplicatorIf->size(), 3u);
+ EXPECT_EQ(ReplicatorEntry->getSuccessors()[1],
+ ReplicatorIf->getSingleSuccessor());
+ EXPECT_EQ(ReplicatorIf->getSingleSuccessor(), Replicator->getExiting());
+}
+
+} // namespace
+} // namespace llvm
>From 4a88cc7c92004260d7613b1c88052ee94e22b6d1 Mon Sep 17 00:00:00 2001
From: Luke Lau <luke at igalia.com>
Date: Thu, 23 Oct 2025 00:21:24 +0800
Subject: [PATCH 2/2] Test sinkScalarOperands
---
.../Transforms/Vectorize/VPlanTransformsTest.cpp | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/llvm/unittests/Transforms/Vectorize/VPlanTransformsTest.cpp b/llvm/unittests/Transforms/Vectorize/VPlanTransformsTest.cpp
index ab94337d61e39..dec5effc2bafa 100644
--- a/llvm/unittests/Transforms/Vectorize/VPlanTransformsTest.cpp
+++ b/llvm/unittests/Transforms/Vectorize/VPlanTransformsTest.cpp
@@ -20,8 +20,9 @@ using VPlanTransformsTest = VPlanTestBase;
// Test we create and merge replicate regions:
// VPBB1:
// REPLICATE %Rep0 = add
-// REPLICATE %Rep1 = add
-// REPLICATE %Rep2 = add
+// REPLICATE %Rep1 = add, %Mask
+// REPLICATE %Rep2 = add, %Mask
+// REPLICATE %Rep3 = add, %Mask
// No successors
//
// ->
@@ -35,6 +36,7 @@ using VPlanTransformsTest = VPlanTestBase;
// REPLICATE %Rep0 = add
// REPLICATE %Rep1 = add
// REPLICATE %Rep2 = add
+// REPLICATE %Rep3 = add %Rep0
// Successor(s): pred.add.continue
//
// pred.add.continue:
@@ -42,6 +44,7 @@ using VPlanTransformsTest = VPlanTestBase;
// }
TEST_F(VPlanTransformsTest, createAndOptimizeReplicateRegions) {
VPlan &Plan = getPlan();
+ Plan.addVF(ElementCount::getFixed(4));
IntegerType *Int32 = IntegerType::get(C, 32);
auto *AI = BinaryOperator::CreateAdd(PoisonValue::get(Int32),
@@ -52,12 +55,16 @@ TEST_F(VPlanTransformsTest, createAndOptimizeReplicateRegions) {
VPRegionBlock *R1 = Plan.createVPRegionBlock(VPBB1, VPBB1, "R1");
VPBlockUtils::connectBlocks(VPBB0, R1);
auto *Mask = new VPInstruction(0, {});
- auto *Rep0 = new VPReplicateRecipe(AI, {}, false, Mask);
+ // Not masked, but should still be sunk into Rep3's region.
+ auto *Rep0 = new VPReplicateRecipe(AI, {}, false);
+ // Masked, should each create a replicate region and get merged.
auto *Rep1 = new VPReplicateRecipe(AI, {}, false, Mask);
auto *Rep2 = new VPReplicateRecipe(AI, {}, false, Mask);
+ auto *Rep3 = new VPReplicateRecipe(AI, {Rep0}, false, Mask);
VPBB1->appendRecipe(Rep0);
VPBB1->appendRecipe(Rep1);
VPBB1->appendRecipe(Rep2);
+ VPBB1->appendRecipe(Rep3);
VPlanTransforms::createAndOptimizeReplicateRegions(Plan);
@@ -67,7 +74,7 @@ TEST_F(VPlanTransformsTest, createAndOptimizeReplicateRegions) {
EXPECT_EQ(ReplicatorEntry->size(), 1u);
EXPECT_TRUE(isa<VPBranchOnMaskRecipe>(ReplicatorEntry->front()));
auto *ReplicatorIf = cast<VPBasicBlock>(ReplicatorEntry->getSuccessors()[0]);
- EXPECT_EQ(ReplicatorIf->size(), 3u);
+ EXPECT_EQ(ReplicatorIf->size(), 4u);
EXPECT_EQ(ReplicatorEntry->getSuccessors()[1],
ReplicatorIf->getSingleSuccessor());
EXPECT_EQ(ReplicatorIf->getSingleSuccessor(), Replicator->getExiting());
More information about the llvm-commits
mailing list