xref: /llvm-project/llvm/unittests/Transforms/Vectorize/VPlanVerifierTest.cpp (revision 5c15caa83fec6aaae7827b9406adf8ab9fac7eac)
1 //===- llvm/unittests/Transforms/Vectorize/VPlanVerifierTest.cpp ----------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "../lib/Transforms/Vectorize/VPlanVerifier.h"
10 #include "../lib/Transforms/Vectorize/VPlan.h"
11 #include "VPlanTestBase.h"
12 #include "llvm/IR/Instruction.h"
13 #include "llvm/IR/Instructions.h"
14 #include "gtest/gtest.h"
15 
16 using namespace llvm;
17 
18 using VPVerifierTest = VPlanTestBase;
19 
20 namespace {
21 TEST_F(VPVerifierTest, VPInstructionUseBeforeDefSameBB) {
22   VPlan &Plan = getPlan();
23   VPValue *Zero = Plan.getOrAddLiveIn(ConstantInt::get(Type::getInt32Ty(C), 0));
24   VPInstruction *DefI = new VPInstruction(Instruction::Add, {Zero});
25   VPInstruction *UseI = new VPInstruction(Instruction::Sub, {DefI});
26   auto *CanIV = new VPCanonicalIVPHIRecipe(Zero, {});
27 
28   VPBasicBlock *VPBB1 = Plan.getEntry();
29   VPBB1->appendRecipe(UseI);
30   VPBB1->appendRecipe(DefI);
31 
32   VPBasicBlock *VPBB2 = Plan.createVPBasicBlock("");
33   VPBB2->appendRecipe(CanIV);
34   VPRegionBlock *R1 = Plan.createVPRegionBlock(VPBB2, VPBB2, "R1");
35   VPBlockUtils::connectBlocks(VPBB1, R1);
36   VPBlockUtils::connectBlocks(R1, Plan.getScalarHeader());
37 
38 #if GTEST_HAS_STREAM_REDIRECTION
39   ::testing::internal::CaptureStderr();
40 #endif
41   EXPECT_FALSE(verifyVPlanIsValid(Plan));
42 #if GTEST_HAS_STREAM_REDIRECTION
43   EXPECT_STREQ("Use before def!\n",
44                ::testing::internal::GetCapturedStderr().c_str());
45 #endif
46 }
47 
48 TEST_F(VPVerifierTest, VPInstructionUseBeforeDefDifferentBB) {
49   VPlan &Plan = getPlan();
50   VPValue *Zero = Plan.getOrAddLiveIn(ConstantInt::get(Type::getInt32Ty(C), 0));
51   VPInstruction *DefI = new VPInstruction(Instruction::Add, {Zero});
52   VPInstruction *UseI = new VPInstruction(Instruction::Sub, {DefI});
53   auto *CanIV = new VPCanonicalIVPHIRecipe(Zero, {});
54   VPInstruction *BranchOnCond =
55       new VPInstruction(VPInstruction::BranchOnCond, {CanIV});
56 
57   VPBasicBlock *VPBB1 = Plan.getEntry();
58   VPBasicBlock *VPBB2 = Plan.createVPBasicBlock("");
59 
60   VPBB1->appendRecipe(UseI);
61   VPBB2->appendRecipe(CanIV);
62   VPBB2->appendRecipe(DefI);
63   VPBB2->appendRecipe(BranchOnCond);
64 
65   VPRegionBlock *R1 = Plan.createVPRegionBlock(VPBB2, VPBB2, "R1");
66   VPBlockUtils::connectBlocks(VPBB1, R1);
67   VPBlockUtils::connectBlocks(R1, Plan.getScalarHeader());
68 
69 #if GTEST_HAS_STREAM_REDIRECTION
70   ::testing::internal::CaptureStderr();
71 #endif
72   EXPECT_FALSE(verifyVPlanIsValid(Plan));
73 #if GTEST_HAS_STREAM_REDIRECTION
74   EXPECT_STREQ("Use before def!\n",
75                ::testing::internal::GetCapturedStderr().c_str());
76 #endif
77 }
78 
79 TEST_F(VPVerifierTest, VPBlendUseBeforeDefDifferentBB) {
80   VPlan &Plan = getPlan();
81   IntegerType *Int32 = IntegerType::get(C, 32);
82   auto *Phi = PHINode::Create(Int32, 1);
83   VPValue *Zero = Plan.getOrAddLiveIn(ConstantInt::get(Int32, 0));
84 
85   VPInstruction *DefI = new VPInstruction(Instruction::Add, {Zero});
86   auto *CanIV = new VPCanonicalIVPHIRecipe(Zero, {});
87   VPInstruction *BranchOnCond =
88       new VPInstruction(VPInstruction::BranchOnCond, {CanIV});
89   auto *Blend = new VPBlendRecipe(Phi, {DefI});
90 
91   VPBasicBlock *VPBB1 = Plan.getEntry();
92   VPBasicBlock *VPBB2 = Plan.createVPBasicBlock("");
93   VPBasicBlock *VPBB3 = Plan.createVPBasicBlock("");
94   VPBasicBlock *VPBB4 = Plan.createVPBasicBlock("");
95 
96   VPBB2->appendRecipe(CanIV);
97   VPBB3->appendRecipe(Blend);
98   VPBB4->appendRecipe(DefI);
99   VPBB4->appendRecipe(BranchOnCond);
100 
101   VPBlockUtils::connectBlocks(VPBB2, VPBB3);
102   VPBlockUtils::connectBlocks(VPBB3, VPBB4);
103   VPRegionBlock *R1 = Plan.createVPRegionBlock(VPBB2, VPBB4, "R1");
104   VPBlockUtils::connectBlocks(VPBB1, R1);
105   VPBB3->setParent(R1);
106 
107   VPBlockUtils::connectBlocks(R1, Plan.getScalarHeader());
108 
109 #if GTEST_HAS_STREAM_REDIRECTION
110   ::testing::internal::CaptureStderr();
111 #endif
112   EXPECT_FALSE(verifyVPlanIsValid(Plan));
113 #if GTEST_HAS_STREAM_REDIRECTION
114   EXPECT_STREQ("Use before def!\n",
115                ::testing::internal::GetCapturedStderr().c_str());
116 #endif
117 
118   delete Phi;
119 }
120 
121 TEST_F(VPVerifierTest, DuplicateSuccessorsOutsideRegion) {
122   VPlan &Plan = getPlan();
123   VPValue *Zero = Plan.getOrAddLiveIn(ConstantInt::get(Type::getInt32Ty(C), 0));
124   VPInstruction *I1 = new VPInstruction(Instruction::Add, {Zero});
125   auto *CanIV = new VPCanonicalIVPHIRecipe(Zero, {});
126   VPInstruction *BranchOnCond =
127       new VPInstruction(VPInstruction::BranchOnCond, {CanIV});
128   VPInstruction *BranchOnCond2 =
129       new VPInstruction(VPInstruction::BranchOnCond, {I1});
130 
131   VPBasicBlock *VPBB1 = Plan.getEntry();
132   VPBasicBlock *VPBB2 = Plan.createVPBasicBlock("");
133 
134   VPBB1->appendRecipe(I1);
135   VPBB1->appendRecipe(BranchOnCond2);
136   VPBB2->appendRecipe(CanIV);
137   VPBB2->appendRecipe(BranchOnCond);
138 
139   VPRegionBlock *R1 = Plan.createVPRegionBlock(VPBB2, VPBB2, "R1");
140   VPBlockUtils::connectBlocks(VPBB1, R1);
141   VPBlockUtils::connectBlocks(VPBB1, R1);
142 
143   VPBlockUtils::connectBlocks(R1, Plan.getScalarHeader());
144 
145 #if GTEST_HAS_STREAM_REDIRECTION
146   ::testing::internal::CaptureStderr();
147 #endif
148   EXPECT_FALSE(verifyVPlanIsValid(Plan));
149 #if GTEST_HAS_STREAM_REDIRECTION
150   EXPECT_STREQ("Multiple instances of the same successor.\n",
151                ::testing::internal::GetCapturedStderr().c_str());
152 #endif
153 }
154 
155 TEST_F(VPVerifierTest, DuplicateSuccessorsInsideRegion) {
156   VPlan &Plan = getPlan();
157   VPValue *Zero = Plan.getOrAddLiveIn(ConstantInt::get(Type::getInt32Ty(C), 0));
158   VPInstruction *I1 = new VPInstruction(Instruction::Add, {Zero});
159   auto *CanIV = new VPCanonicalIVPHIRecipe(Zero, {});
160   VPInstruction *BranchOnCond =
161       new VPInstruction(VPInstruction::BranchOnCond, {CanIV});
162   VPInstruction *BranchOnCond2 =
163       new VPInstruction(VPInstruction::BranchOnCond, {I1});
164 
165   VPBasicBlock *VPBB1 = Plan.getEntry();
166   VPBasicBlock *VPBB2 = Plan.createVPBasicBlock("");
167   VPBasicBlock *VPBB3 = Plan.createVPBasicBlock("");
168 
169   VPBB1->appendRecipe(I1);
170   VPBB2->appendRecipe(CanIV);
171   VPBB2->appendRecipe(BranchOnCond2);
172   VPBB3->appendRecipe(BranchOnCond);
173 
174   VPBlockUtils::connectBlocks(VPBB2, VPBB3);
175   VPBlockUtils::connectBlocks(VPBB2, VPBB3);
176   VPRegionBlock *R1 = Plan.createVPRegionBlock(VPBB2, VPBB3, "R1");
177   VPBlockUtils::connectBlocks(VPBB1, R1);
178   VPBB3->setParent(R1);
179 
180   VPBlockUtils::connectBlocks(R1, Plan.getScalarHeader());
181 
182 #if GTEST_HAS_STREAM_REDIRECTION
183   ::testing::internal::CaptureStderr();
184 #endif
185   EXPECT_FALSE(verifyVPlanIsValid(Plan));
186 #if GTEST_HAS_STREAM_REDIRECTION
187   EXPECT_STREQ("Multiple instances of the same successor.\n",
188                ::testing::internal::GetCapturedStderr().c_str());
189 #endif
190 }
191 
192 TEST_F(VPVerifierTest, BlockOutsideRegionWithParent) {
193   VPlan &Plan = getPlan();
194 
195   VPBasicBlock *VPBB1 = Plan.getEntry();
196   VPBasicBlock *VPBB2 = Plan.createVPBasicBlock("");
197 
198   VPValue *Zero = Plan.getOrAddLiveIn(ConstantInt::get(Type::getInt32Ty(C), 0));
199   auto *CanIV = new VPCanonicalIVPHIRecipe(Zero, {});
200   VPBB2->appendRecipe(CanIV);
201 
202   VPInstruction *DefI = new VPInstruction(Instruction::Add, {Zero});
203   VPInstruction *BranchOnCond =
204       new VPInstruction(VPInstruction::BranchOnCond, {DefI});
205 
206   VPBB1->appendRecipe(DefI);
207   VPBB2->appendRecipe(BranchOnCond);
208 
209   VPRegionBlock *R1 = Plan.createVPRegionBlock(VPBB2, VPBB2, "R1");
210   VPBlockUtils::connectBlocks(VPBB1, R1);
211 
212   VPBlockUtils::connectBlocks(R1, Plan.getScalarHeader());
213   VPBB1->setParent(R1);
214 
215 #if GTEST_HAS_STREAM_REDIRECTION
216   ::testing::internal::CaptureStderr();
217 #endif
218   EXPECT_FALSE(verifyVPlanIsValid(Plan));
219 #if GTEST_HAS_STREAM_REDIRECTION
220   EXPECT_STREQ("Predecessor is not in the same region.\n",
221                ::testing::internal::GetCapturedStderr().c_str());
222 #endif
223 }
224 
225 } // namespace
226