[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