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