xref: /llvm-project/llvm/unittests/Transforms/Vectorize/VPlanVerifierTest.cpp (revision edd6b1f4fe4838a7a656b2e8c5ac2de3a358d41a)
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 "llvm/IR/Instruction.h"
12 #include "llvm/IR/Instructions.h"
13 #include "gtest/gtest.h"
14 
15 using namespace llvm;
16 
17 namespace {
18 TEST(VPVerifierTest, VPInstructionUseBeforeDefSameBB) {
19   VPInstruction *DefI = new VPInstruction(Instruction::Add, {});
20   VPInstruction *UseI = new VPInstruction(Instruction::Sub, {DefI});
21 
22   VPBasicBlock *VPPH = new VPBasicBlock("ph");
23   VPBasicBlock *VPBB1 = new VPBasicBlock();
24   VPBB1->appendRecipe(UseI);
25   VPBB1->appendRecipe(DefI);
26 
27   auto TC = std::make_unique<VPValue>();
28   VPBasicBlock *VPBB2 = new VPBasicBlock();
29   VPRegionBlock *R1 = new VPRegionBlock(VPBB2, VPBB2, "R1");
30   VPBlockUtils::connectBlocks(VPBB1, R1);
31 
32   LLVMContext C;
33   auto *ScalarHeader = BasicBlock::Create(C, "");
34   VPIRBasicBlock *ScalarHeaderVPBB = new VPIRBasicBlock(ScalarHeader);
35   VPBlockUtils::connectBlocks(R1, ScalarHeaderVPBB);
36   VPlan Plan(VPPH, &*TC, VPBB1, ScalarHeaderVPBB);
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   delete ScalarHeader;
47 }
48 
49 TEST(VPVerifierTest, VPInstructionUseBeforeDefDifferentBB) {
50   VPInstruction *DefI = new VPInstruction(Instruction::Add, {});
51   VPInstruction *UseI = new VPInstruction(Instruction::Sub, {DefI});
52   auto *CanIV = new VPCanonicalIVPHIRecipe(UseI, {});
53   VPInstruction *BranchOnCond =
54       new VPInstruction(VPInstruction::BranchOnCond, {CanIV});
55 
56   VPBasicBlock *VPPH = new VPBasicBlock("ph");
57   VPBasicBlock *VPBB1 = new VPBasicBlock();
58   VPBasicBlock *VPBB2 = new VPBasicBlock();
59 
60   VPBB1->appendRecipe(UseI);
61   VPBB2->appendRecipe(CanIV);
62   VPBB2->appendRecipe(DefI);
63   VPBB2->appendRecipe(BranchOnCond);
64 
65   VPRegionBlock *R1 = new VPRegionBlock(VPBB2, VPBB2, "R1");
66   VPBlockUtils::connectBlocks(VPBB1, R1);
67 
68   auto TC = std::make_unique<VPValue>();
69   LLVMContext C;
70   auto *ScalarHeader = BasicBlock::Create(C, "");
71   VPIRBasicBlock *ScalarHeaderVPBB = new VPIRBasicBlock(ScalarHeader);
72   VPBlockUtils::connectBlocks(R1, ScalarHeaderVPBB);
73   VPlan Plan(VPPH, &*TC, VPBB1, ScalarHeaderVPBB);
74 
75 #if GTEST_HAS_STREAM_REDIRECTION
76   ::testing::internal::CaptureStderr();
77 #endif
78   EXPECT_FALSE(verifyVPlanIsValid(Plan));
79 #if GTEST_HAS_STREAM_REDIRECTION
80   EXPECT_STREQ("Use before def!\n",
81                ::testing::internal::GetCapturedStderr().c_str());
82 #endif
83   delete ScalarHeader;
84 }
85 
86 TEST(VPVerifierTest, VPBlendUseBeforeDefDifferentBB) {
87   LLVMContext C;
88   IntegerType *Int32 = IntegerType::get(C, 32);
89   auto *Phi = PHINode::Create(Int32, 1);
90 
91   VPInstruction *I1 = new VPInstruction(Instruction::Add, {});
92   VPInstruction *DefI = new VPInstruction(Instruction::Add, {});
93   auto *CanIV = new VPCanonicalIVPHIRecipe(I1, {});
94   VPInstruction *BranchOnCond =
95       new VPInstruction(VPInstruction::BranchOnCond, {CanIV});
96   auto *Blend = new VPBlendRecipe(Phi, {DefI});
97 
98   VPBasicBlock *VPPH = new VPBasicBlock("ph");
99   VPBasicBlock *VPBB1 = new VPBasicBlock();
100   VPBasicBlock *VPBB2 = new VPBasicBlock();
101   VPBasicBlock *VPBB3 = new VPBasicBlock();
102   VPBasicBlock *VPBB4 = new VPBasicBlock();
103 
104   VPBB1->appendRecipe(I1);
105   VPBB2->appendRecipe(CanIV);
106   VPBB3->appendRecipe(Blend);
107   VPBB4->appendRecipe(DefI);
108   VPBB4->appendRecipe(BranchOnCond);
109 
110   VPBlockUtils::connectBlocks(VPBB2, VPBB3);
111   VPBlockUtils::connectBlocks(VPBB3, VPBB4);
112   VPRegionBlock *R1 = new VPRegionBlock(VPBB2, VPBB4, "R1");
113   VPBlockUtils::connectBlocks(VPBB1, R1);
114   VPBB3->setParent(R1);
115 
116   auto TC = std::make_unique<VPValue>();
117   auto *ScalarHeader = BasicBlock::Create(C, "");
118   VPIRBasicBlock *ScalarHeaderVPBB = new VPIRBasicBlock(ScalarHeader);
119   VPBlockUtils::connectBlocks(R1, ScalarHeaderVPBB);
120   VPlan Plan(VPPH, &*TC, VPBB1, ScalarHeaderVPBB);
121 
122 #if GTEST_HAS_STREAM_REDIRECTION
123   ::testing::internal::CaptureStderr();
124 #endif
125   EXPECT_FALSE(verifyVPlanIsValid(Plan));
126 #if GTEST_HAS_STREAM_REDIRECTION
127   EXPECT_STREQ("Use before def!\n",
128                ::testing::internal::GetCapturedStderr().c_str());
129 #endif
130 
131   delete Phi;
132   delete ScalarHeader;
133 }
134 
135 TEST(VPVerifierTest, DuplicateSuccessorsOutsideRegion) {
136   VPInstruction *I1 = new VPInstruction(Instruction::Add, {});
137   auto *CanIV = new VPCanonicalIVPHIRecipe(I1, {});
138   VPInstruction *BranchOnCond =
139       new VPInstruction(VPInstruction::BranchOnCond, {CanIV});
140   VPInstruction *BranchOnCond2 =
141       new VPInstruction(VPInstruction::BranchOnCond, {I1});
142 
143   VPBasicBlock *VPPH = new VPBasicBlock("ph");
144   VPBasicBlock *VPBB1 = new VPBasicBlock();
145   VPBasicBlock *VPBB2 = new VPBasicBlock();
146 
147   VPBB1->appendRecipe(I1);
148   VPBB1->appendRecipe(BranchOnCond2);
149   VPBB2->appendRecipe(CanIV);
150   VPBB2->appendRecipe(BranchOnCond);
151 
152   VPRegionBlock *R1 = new VPRegionBlock(VPBB2, VPBB2, "R1");
153   VPBlockUtils::connectBlocks(VPBB1, R1);
154   VPBlockUtils::connectBlocks(VPBB1, R1);
155 
156   auto TC = std::make_unique<VPValue>();
157   LLVMContext C;
158   auto *ScalarHeader = BasicBlock::Create(C, "");
159   VPIRBasicBlock *ScalarHeaderVPBB = new VPIRBasicBlock(ScalarHeader);
160   VPBlockUtils::connectBlocks(R1, ScalarHeaderVPBB);
161   VPlan Plan(VPPH, &*TC, VPBB1, ScalarHeaderVPBB);
162 
163 #if GTEST_HAS_STREAM_REDIRECTION
164   ::testing::internal::CaptureStderr();
165 #endif
166   EXPECT_FALSE(verifyVPlanIsValid(Plan));
167 #if GTEST_HAS_STREAM_REDIRECTION
168   EXPECT_STREQ("Multiple instances of the same successor.\n",
169                ::testing::internal::GetCapturedStderr().c_str());
170 #endif
171   delete ScalarHeader;
172 }
173 
174 TEST(VPVerifierTest, DuplicateSuccessorsInsideRegion) {
175   VPInstruction *I1 = new VPInstruction(Instruction::Add, {});
176   auto *CanIV = new VPCanonicalIVPHIRecipe(I1, {});
177   VPInstruction *BranchOnCond =
178       new VPInstruction(VPInstruction::BranchOnCond, {CanIV});
179   VPInstruction *BranchOnCond2 =
180       new VPInstruction(VPInstruction::BranchOnCond, {I1});
181 
182   VPBasicBlock *VPPH = new VPBasicBlock("ph");
183   VPBasicBlock *VPBB1 = new VPBasicBlock();
184   VPBasicBlock *VPBB2 = new VPBasicBlock();
185   VPBasicBlock *VPBB3 = new VPBasicBlock();
186 
187   VPBB1->appendRecipe(I1);
188   VPBB2->appendRecipe(CanIV);
189   VPBB2->appendRecipe(BranchOnCond2);
190   VPBB3->appendRecipe(BranchOnCond);
191 
192   VPBlockUtils::connectBlocks(VPBB2, VPBB3);
193   VPBlockUtils::connectBlocks(VPBB2, VPBB3);
194   VPRegionBlock *R1 = new VPRegionBlock(VPBB2, VPBB3, "R1");
195   VPBlockUtils::connectBlocks(VPBB1, R1);
196   VPBB3->setParent(R1);
197 
198   auto TC = std::make_unique<VPValue>();
199   LLVMContext C;
200   auto *ScalarHeader = BasicBlock::Create(C, "");
201   VPIRBasicBlock *ScalarHeaderVPBB = new VPIRBasicBlock(ScalarHeader);
202   VPBlockUtils::connectBlocks(R1, ScalarHeaderVPBB);
203   VPlan Plan(VPPH, &*TC, VPBB1, ScalarHeaderVPBB);
204 
205 #if GTEST_HAS_STREAM_REDIRECTION
206   ::testing::internal::CaptureStderr();
207 #endif
208   EXPECT_FALSE(verifyVPlanIsValid(Plan));
209 #if GTEST_HAS_STREAM_REDIRECTION
210   EXPECT_STREQ("Multiple instances of the same successor.\n",
211                ::testing::internal::GetCapturedStderr().c_str());
212 #endif
213   delete ScalarHeader;
214 }
215 
216 TEST(VPVerifierTest, BlockOutsideRegionWithParent) {
217   VPBasicBlock *VPPH = new VPBasicBlock("ph");
218   VPBasicBlock *VPBB1 = new VPBasicBlock();
219   VPBasicBlock *VPBB2 = new VPBasicBlock();
220 
221   VPInstruction *DefI = new VPInstruction(Instruction::Add, {});
222   VPInstruction *BranchOnCond =
223       new VPInstruction(VPInstruction::BranchOnCond, {DefI});
224 
225   VPBB1->appendRecipe(DefI);
226   VPBB2->appendRecipe(BranchOnCond);
227 
228   VPRegionBlock *R1 = new VPRegionBlock(VPBB2, VPBB2, "R1");
229   VPBlockUtils::connectBlocks(VPBB1, R1);
230   VPBB1->setParent(R1);
231 
232   auto TC = std::make_unique<VPValue>();
233   LLVMContext C;
234   auto *ScalarHeader = BasicBlock::Create(C, "");
235   VPIRBasicBlock *ScalarHeaderVPBB = new VPIRBasicBlock(ScalarHeader);
236   VPBlockUtils::connectBlocks(R1, ScalarHeaderVPBB);
237   VPlan Plan(VPPH, &*TC, VPBB1, ScalarHeaderVPBB);
238 
239 #if GTEST_HAS_STREAM_REDIRECTION
240   ::testing::internal::CaptureStderr();
241 #endif
242   EXPECT_FALSE(verifyVPlanIsValid(Plan));
243 #if GTEST_HAS_STREAM_REDIRECTION
244   EXPECT_STREQ("Predecessor is not in the same region.\n",
245                ::testing::internal::GetCapturedStderr().c_str());
246 #endif
247   delete ScalarHeader;
248 }
249 
250 } // namespace
251