xref: /llvm-project/llvm/unittests/Transforms/Vectorize/VPlanVerifierTest.cpp (revision 5c15caa83fec6aaae7827b9406adf8ab9fac7eac)
1dc8e2ea9SFlorian Hahn //===- llvm/unittests/Transforms/Vectorize/VPlanVerifierTest.cpp ----------===//
2dc8e2ea9SFlorian Hahn //
3dc8e2ea9SFlorian Hahn // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4dc8e2ea9SFlorian Hahn // See https://llvm.org/LICENSE.txt for license information.
5dc8e2ea9SFlorian Hahn // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6dc8e2ea9SFlorian Hahn //
7dc8e2ea9SFlorian Hahn //===----------------------------------------------------------------------===//
8dc8e2ea9SFlorian Hahn 
9dc8e2ea9SFlorian Hahn #include "../lib/Transforms/Vectorize/VPlanVerifier.h"
10dc8e2ea9SFlorian Hahn #include "../lib/Transforms/Vectorize/VPlan.h"
118caeb2e0SFlorian Hahn #include "VPlanTestBase.h"
12dc8e2ea9SFlorian Hahn #include "llvm/IR/Instruction.h"
13dc8e2ea9SFlorian Hahn #include "llvm/IR/Instructions.h"
14dc8e2ea9SFlorian Hahn #include "gtest/gtest.h"
15dc8e2ea9SFlorian Hahn 
16dc8e2ea9SFlorian Hahn using namespace llvm;
17dc8e2ea9SFlorian Hahn 
188caeb2e0SFlorian Hahn using VPVerifierTest = VPlanTestBase;
198caeb2e0SFlorian Hahn 
20dc8e2ea9SFlorian Hahn namespace {
218caeb2e0SFlorian Hahn TEST_F(VPVerifierTest, VPInstructionUseBeforeDefSameBB) {
228caeb2e0SFlorian Hahn   VPlan &Plan = getPlan();
23*5c15caa8SLuke Lau   VPValue *Zero = Plan.getOrAddLiveIn(ConstantInt::get(Type::getInt32Ty(C), 0));
24*5c15caa8SLuke Lau   VPInstruction *DefI = new VPInstruction(Instruction::Add, {Zero});
25dc8e2ea9SFlorian Hahn   VPInstruction *UseI = new VPInstruction(Instruction::Sub, {DefI});
26*5c15caa8SLuke Lau   auto *CanIV = new VPCanonicalIVPHIRecipe(Zero, {});
27dc8e2ea9SFlorian Hahn 
288caeb2e0SFlorian Hahn   VPBasicBlock *VPBB1 = Plan.getEntry();
29dc8e2ea9SFlorian Hahn   VPBB1->appendRecipe(UseI);
30dc8e2ea9SFlorian Hahn   VPBB1->appendRecipe(DefI);
31dc8e2ea9SFlorian Hahn 
3216d19aaeSFlorian Hahn   VPBasicBlock *VPBB2 = Plan.createVPBasicBlock("");
33*5c15caa8SLuke Lau   VPBB2->appendRecipe(CanIV);
3416d19aaeSFlorian Hahn   VPRegionBlock *R1 = Plan.createVPRegionBlock(VPBB2, VPBB2, "R1");
359923d29cSFlorian Hahn   VPBlockUtils::connectBlocks(VPBB1, R1);
368caeb2e0SFlorian Hahn   VPBlockUtils::connectBlocks(R1, Plan.getScalarHeader());
37dc8e2ea9SFlorian Hahn 
38dc8e2ea9SFlorian Hahn #if GTEST_HAS_STREAM_REDIRECTION
39dc8e2ea9SFlorian Hahn   ::testing::internal::CaptureStderr();
40dc8e2ea9SFlorian Hahn #endif
419923d29cSFlorian Hahn   EXPECT_FALSE(verifyVPlanIsValid(Plan));
42dc8e2ea9SFlorian Hahn #if GTEST_HAS_STREAM_REDIRECTION
43dc8e2ea9SFlorian Hahn   EXPECT_STREQ("Use before def!\n",
44dc8e2ea9SFlorian Hahn                ::testing::internal::GetCapturedStderr().c_str());
45dc8e2ea9SFlorian Hahn #endif
46dc8e2ea9SFlorian Hahn }
47dc8e2ea9SFlorian Hahn 
488caeb2e0SFlorian Hahn TEST_F(VPVerifierTest, VPInstructionUseBeforeDefDifferentBB) {
498caeb2e0SFlorian Hahn   VPlan &Plan = getPlan();
50*5c15caa8SLuke Lau   VPValue *Zero = Plan.getOrAddLiveIn(ConstantInt::get(Type::getInt32Ty(C), 0));
51*5c15caa8SLuke Lau   VPInstruction *DefI = new VPInstruction(Instruction::Add, {Zero});
52dc8e2ea9SFlorian Hahn   VPInstruction *UseI = new VPInstruction(Instruction::Sub, {DefI});
53*5c15caa8SLuke Lau   auto *CanIV = new VPCanonicalIVPHIRecipe(Zero, {});
54dc8e2ea9SFlorian Hahn   VPInstruction *BranchOnCond =
55dc8e2ea9SFlorian Hahn       new VPInstruction(VPInstruction::BranchOnCond, {CanIV});
56dc8e2ea9SFlorian Hahn 
578caeb2e0SFlorian Hahn   VPBasicBlock *VPBB1 = Plan.getEntry();
5816d19aaeSFlorian Hahn   VPBasicBlock *VPBB2 = Plan.createVPBasicBlock("");
59dc8e2ea9SFlorian Hahn 
60dc8e2ea9SFlorian Hahn   VPBB1->appendRecipe(UseI);
61dc8e2ea9SFlorian Hahn   VPBB2->appendRecipe(CanIV);
62dc8e2ea9SFlorian Hahn   VPBB2->appendRecipe(DefI);
63dc8e2ea9SFlorian Hahn   VPBB2->appendRecipe(BranchOnCond);
64dc8e2ea9SFlorian Hahn 
6516d19aaeSFlorian Hahn   VPRegionBlock *R1 = Plan.createVPRegionBlock(VPBB2, VPBB2, "R1");
66dc8e2ea9SFlorian Hahn   VPBlockUtils::connectBlocks(VPBB1, R1);
678caeb2e0SFlorian Hahn   VPBlockUtils::connectBlocks(R1, Plan.getScalarHeader());
68dc8e2ea9SFlorian Hahn 
69dc8e2ea9SFlorian Hahn #if GTEST_HAS_STREAM_REDIRECTION
70dc8e2ea9SFlorian Hahn   ::testing::internal::CaptureStderr();
71dc8e2ea9SFlorian Hahn #endif
729923d29cSFlorian Hahn   EXPECT_FALSE(verifyVPlanIsValid(Plan));
73dc8e2ea9SFlorian Hahn #if GTEST_HAS_STREAM_REDIRECTION
74b6b3d20dSFlorian Hahn   EXPECT_STREQ("Use before def!\n",
75b6b3d20dSFlorian Hahn                ::testing::internal::GetCapturedStderr().c_str());
76dc8e2ea9SFlorian Hahn #endif
77dc8e2ea9SFlorian Hahn }
78dc8e2ea9SFlorian Hahn 
798caeb2e0SFlorian Hahn TEST_F(VPVerifierTest, VPBlendUseBeforeDefDifferentBB) {
80*5c15caa8SLuke Lau   VPlan &Plan = getPlan();
81dc8e2ea9SFlorian Hahn   IntegerType *Int32 = IntegerType::get(C, 32);
82dc8e2ea9SFlorian Hahn   auto *Phi = PHINode::Create(Int32, 1);
83*5c15caa8SLuke Lau   VPValue *Zero = Plan.getOrAddLiveIn(ConstantInt::get(Int32, 0));
84dc8e2ea9SFlorian Hahn 
85*5c15caa8SLuke Lau   VPInstruction *DefI = new VPInstruction(Instruction::Add, {Zero});
86*5c15caa8SLuke Lau   auto *CanIV = new VPCanonicalIVPHIRecipe(Zero, {});
87dc8e2ea9SFlorian Hahn   VPInstruction *BranchOnCond =
88dc8e2ea9SFlorian Hahn       new VPInstruction(VPInstruction::BranchOnCond, {CanIV});
89dc8e2ea9SFlorian Hahn   auto *Blend = new VPBlendRecipe(Phi, {DefI});
90dc8e2ea9SFlorian Hahn 
918caeb2e0SFlorian Hahn   VPBasicBlock *VPBB1 = Plan.getEntry();
9216d19aaeSFlorian Hahn   VPBasicBlock *VPBB2 = Plan.createVPBasicBlock("");
9316d19aaeSFlorian Hahn   VPBasicBlock *VPBB3 = Plan.createVPBasicBlock("");
9416d19aaeSFlorian Hahn   VPBasicBlock *VPBB4 = Plan.createVPBasicBlock("");
95dc8e2ea9SFlorian Hahn 
96dc8e2ea9SFlorian Hahn   VPBB2->appendRecipe(CanIV);
97dc8e2ea9SFlorian Hahn   VPBB3->appendRecipe(Blend);
98dc8e2ea9SFlorian Hahn   VPBB4->appendRecipe(DefI);
99dc8e2ea9SFlorian Hahn   VPBB4->appendRecipe(BranchOnCond);
100dc8e2ea9SFlorian Hahn 
101dc8e2ea9SFlorian Hahn   VPBlockUtils::connectBlocks(VPBB2, VPBB3);
102dc8e2ea9SFlorian Hahn   VPBlockUtils::connectBlocks(VPBB3, VPBB4);
10316d19aaeSFlorian Hahn   VPRegionBlock *R1 = Plan.createVPRegionBlock(VPBB2, VPBB4, "R1");
104dc8e2ea9SFlorian Hahn   VPBlockUtils::connectBlocks(VPBB1, R1);
1059923d29cSFlorian Hahn   VPBB3->setParent(R1);
106dc8e2ea9SFlorian Hahn 
1078caeb2e0SFlorian Hahn   VPBlockUtils::connectBlocks(R1, Plan.getScalarHeader());
108dc8e2ea9SFlorian Hahn 
109dc8e2ea9SFlorian Hahn #if GTEST_HAS_STREAM_REDIRECTION
110dc8e2ea9SFlorian Hahn   ::testing::internal::CaptureStderr();
111dc8e2ea9SFlorian Hahn #endif
1129923d29cSFlorian Hahn   EXPECT_FALSE(verifyVPlanIsValid(Plan));
113dc8e2ea9SFlorian Hahn #if GTEST_HAS_STREAM_REDIRECTION
114b6b3d20dSFlorian Hahn   EXPECT_STREQ("Use before def!\n",
115b6b3d20dSFlorian Hahn                ::testing::internal::GetCapturedStderr().c_str());
116dc8e2ea9SFlorian Hahn #endif
117ca8b0b4aSFlorian Hahn 
118ca8b0b4aSFlorian Hahn   delete Phi;
119dc8e2ea9SFlorian Hahn }
1209923d29cSFlorian Hahn 
1218caeb2e0SFlorian Hahn TEST_F(VPVerifierTest, DuplicateSuccessorsOutsideRegion) {
122*5c15caa8SLuke Lau   VPlan &Plan = getPlan();
123*5c15caa8SLuke Lau   VPValue *Zero = Plan.getOrAddLiveIn(ConstantInt::get(Type::getInt32Ty(C), 0));
124*5c15caa8SLuke Lau   VPInstruction *I1 = new VPInstruction(Instruction::Add, {Zero});
125*5c15caa8SLuke Lau   auto *CanIV = new VPCanonicalIVPHIRecipe(Zero, {});
1269923d29cSFlorian Hahn   VPInstruction *BranchOnCond =
1279923d29cSFlorian Hahn       new VPInstruction(VPInstruction::BranchOnCond, {CanIV});
1289923d29cSFlorian Hahn   VPInstruction *BranchOnCond2 =
1299923d29cSFlorian Hahn       new VPInstruction(VPInstruction::BranchOnCond, {I1});
1309923d29cSFlorian Hahn 
1318caeb2e0SFlorian Hahn   VPBasicBlock *VPBB1 = Plan.getEntry();
13216d19aaeSFlorian Hahn   VPBasicBlock *VPBB2 = Plan.createVPBasicBlock("");
1339923d29cSFlorian Hahn 
1349923d29cSFlorian Hahn   VPBB1->appendRecipe(I1);
1359923d29cSFlorian Hahn   VPBB1->appendRecipe(BranchOnCond2);
1369923d29cSFlorian Hahn   VPBB2->appendRecipe(CanIV);
1379923d29cSFlorian Hahn   VPBB2->appendRecipe(BranchOnCond);
1389923d29cSFlorian Hahn 
13916d19aaeSFlorian Hahn   VPRegionBlock *R1 = Plan.createVPRegionBlock(VPBB2, VPBB2, "R1");
1409923d29cSFlorian Hahn   VPBlockUtils::connectBlocks(VPBB1, R1);
1419923d29cSFlorian Hahn   VPBlockUtils::connectBlocks(VPBB1, R1);
1429923d29cSFlorian Hahn 
1438caeb2e0SFlorian Hahn   VPBlockUtils::connectBlocks(R1, Plan.getScalarHeader());
1449923d29cSFlorian Hahn 
1459923d29cSFlorian Hahn #if GTEST_HAS_STREAM_REDIRECTION
1469923d29cSFlorian Hahn   ::testing::internal::CaptureStderr();
1479923d29cSFlorian Hahn #endif
1489923d29cSFlorian Hahn   EXPECT_FALSE(verifyVPlanIsValid(Plan));
1499923d29cSFlorian Hahn #if GTEST_HAS_STREAM_REDIRECTION
1509923d29cSFlorian Hahn   EXPECT_STREQ("Multiple instances of the same successor.\n",
1519923d29cSFlorian Hahn                ::testing::internal::GetCapturedStderr().c_str());
1529923d29cSFlorian Hahn #endif
1539923d29cSFlorian Hahn }
1549923d29cSFlorian Hahn 
1558caeb2e0SFlorian Hahn TEST_F(VPVerifierTest, DuplicateSuccessorsInsideRegion) {
156*5c15caa8SLuke Lau   VPlan &Plan = getPlan();
157*5c15caa8SLuke Lau   VPValue *Zero = Plan.getOrAddLiveIn(ConstantInt::get(Type::getInt32Ty(C), 0));
158*5c15caa8SLuke Lau   VPInstruction *I1 = new VPInstruction(Instruction::Add, {Zero});
159*5c15caa8SLuke Lau   auto *CanIV = new VPCanonicalIVPHIRecipe(Zero, {});
1609923d29cSFlorian Hahn   VPInstruction *BranchOnCond =
1619923d29cSFlorian Hahn       new VPInstruction(VPInstruction::BranchOnCond, {CanIV});
1629923d29cSFlorian Hahn   VPInstruction *BranchOnCond2 =
1639923d29cSFlorian Hahn       new VPInstruction(VPInstruction::BranchOnCond, {I1});
1649923d29cSFlorian Hahn 
1658caeb2e0SFlorian Hahn   VPBasicBlock *VPBB1 = Plan.getEntry();
16616d19aaeSFlorian Hahn   VPBasicBlock *VPBB2 = Plan.createVPBasicBlock("");
16716d19aaeSFlorian Hahn   VPBasicBlock *VPBB3 = Plan.createVPBasicBlock("");
1689923d29cSFlorian Hahn 
1699923d29cSFlorian Hahn   VPBB1->appendRecipe(I1);
1709923d29cSFlorian Hahn   VPBB2->appendRecipe(CanIV);
1719923d29cSFlorian Hahn   VPBB2->appendRecipe(BranchOnCond2);
1729923d29cSFlorian Hahn   VPBB3->appendRecipe(BranchOnCond);
1739923d29cSFlorian Hahn 
1749923d29cSFlorian Hahn   VPBlockUtils::connectBlocks(VPBB2, VPBB3);
1759923d29cSFlorian Hahn   VPBlockUtils::connectBlocks(VPBB2, VPBB3);
17616d19aaeSFlorian Hahn   VPRegionBlock *R1 = Plan.createVPRegionBlock(VPBB2, VPBB3, "R1");
1779923d29cSFlorian Hahn   VPBlockUtils::connectBlocks(VPBB1, R1);
1789923d29cSFlorian Hahn   VPBB3->setParent(R1);
1799923d29cSFlorian Hahn 
1808caeb2e0SFlorian Hahn   VPBlockUtils::connectBlocks(R1, Plan.getScalarHeader());
1819923d29cSFlorian Hahn 
1829923d29cSFlorian Hahn #if GTEST_HAS_STREAM_REDIRECTION
1839923d29cSFlorian Hahn   ::testing::internal::CaptureStderr();
1849923d29cSFlorian Hahn #endif
1859923d29cSFlorian Hahn   EXPECT_FALSE(verifyVPlanIsValid(Plan));
1869923d29cSFlorian Hahn #if GTEST_HAS_STREAM_REDIRECTION
1879923d29cSFlorian Hahn   EXPECT_STREQ("Multiple instances of the same successor.\n",
1889923d29cSFlorian Hahn                ::testing::internal::GetCapturedStderr().c_str());
1899923d29cSFlorian Hahn #endif
1909923d29cSFlorian Hahn }
1919923d29cSFlorian Hahn 
1928caeb2e0SFlorian Hahn TEST_F(VPVerifierTest, BlockOutsideRegionWithParent) {
1938caeb2e0SFlorian Hahn   VPlan &Plan = getPlan();
194*5c15caa8SLuke Lau 
1958caeb2e0SFlorian Hahn   VPBasicBlock *VPBB1 = Plan.getEntry();
19616d19aaeSFlorian Hahn   VPBasicBlock *VPBB2 = Plan.createVPBasicBlock("");
1979923d29cSFlorian Hahn 
198*5c15caa8SLuke Lau   VPValue *Zero = Plan.getOrAddLiveIn(ConstantInt::get(Type::getInt32Ty(C), 0));
199*5c15caa8SLuke Lau   auto *CanIV = new VPCanonicalIVPHIRecipe(Zero, {});
200*5c15caa8SLuke Lau   VPBB2->appendRecipe(CanIV);
201*5c15caa8SLuke Lau 
202*5c15caa8SLuke Lau   VPInstruction *DefI = new VPInstruction(Instruction::Add, {Zero});
2039923d29cSFlorian Hahn   VPInstruction *BranchOnCond =
2049923d29cSFlorian Hahn       new VPInstruction(VPInstruction::BranchOnCond, {DefI});
2059923d29cSFlorian Hahn 
2069923d29cSFlorian Hahn   VPBB1->appendRecipe(DefI);
2079923d29cSFlorian Hahn   VPBB2->appendRecipe(BranchOnCond);
2089923d29cSFlorian Hahn 
20916d19aaeSFlorian Hahn   VPRegionBlock *R1 = Plan.createVPRegionBlock(VPBB2, VPBB2, "R1");
2109923d29cSFlorian Hahn   VPBlockUtils::connectBlocks(VPBB1, R1);
2119923d29cSFlorian Hahn 
2128caeb2e0SFlorian Hahn   VPBlockUtils::connectBlocks(R1, Plan.getScalarHeader());
2136c8f41d3SFlorian Hahn   VPBB1->setParent(R1);
2149923d29cSFlorian Hahn 
2159923d29cSFlorian Hahn #if GTEST_HAS_STREAM_REDIRECTION
2169923d29cSFlorian Hahn   ::testing::internal::CaptureStderr();
2179923d29cSFlorian Hahn #endif
2189923d29cSFlorian Hahn   EXPECT_FALSE(verifyVPlanIsValid(Plan));
2199923d29cSFlorian Hahn #if GTEST_HAS_STREAM_REDIRECTION
2209923d29cSFlorian Hahn   EXPECT_STREQ("Predecessor is not in the same region.\n",
2219923d29cSFlorian Hahn                ::testing::internal::GetCapturedStderr().c_str());
2229923d29cSFlorian Hahn #endif
2239923d29cSFlorian Hahn }
2249923d29cSFlorian Hahn 
225dc8e2ea9SFlorian Hahn } // namespace
226