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