1 //===- llvm/unittests/Transforms/Vectorize/VPlanVerifierTest.cpp ----------===//
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
7 //===----------------------------------------------------------------------===//
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"
18 TEST(VPVerifierTest
, VPInstructionUseBeforeDefSameBB
) {
19 VPInstruction
*DefI
= new VPInstruction(Instruction::Add
, {});
20 VPInstruction
*UseI
= new VPInstruction(Instruction::Sub
, {DefI
});
22 VPBasicBlock
*VPPH
= new VPBasicBlock("ph");
23 VPBasicBlock
*VPBB1
= new VPBasicBlock();
24 VPBB1
->appendRecipe(UseI
);
25 VPBB1
->appendRecipe(DefI
);
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
);
33 auto *ScalarHeader
= BasicBlock::Create(C
, "");
34 VPIRBasicBlock
*ScalarHeaderVPBB
= new VPIRBasicBlock(ScalarHeader
);
35 VPBlockUtils::connectBlocks(R1
, ScalarHeaderVPBB
);
36 VPlan
Plan(VPPH
, &*TC
, VPBB1
, ScalarHeaderVPBB
);
38 #if GTEST_HAS_STREAM_REDIRECTION
39 ::testing::internal::CaptureStderr();
41 EXPECT_FALSE(verifyVPlanIsValid(Plan
));
42 #if GTEST_HAS_STREAM_REDIRECTION
43 EXPECT_STREQ("Use before def!\n",
44 ::testing::internal::GetCapturedStderr().c_str());
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
});
56 VPBasicBlock
*VPPH
= new VPBasicBlock("ph");
57 VPBasicBlock
*VPBB1
= new VPBasicBlock();
58 VPBasicBlock
*VPBB2
= new VPBasicBlock();
60 VPBB1
->appendRecipe(UseI
);
61 VPBB2
->appendRecipe(CanIV
);
62 VPBB2
->appendRecipe(DefI
);
63 VPBB2
->appendRecipe(BranchOnCond
);
65 VPRegionBlock
*R1
= new VPRegionBlock(VPBB2
, VPBB2
, "R1");
66 VPBlockUtils::connectBlocks(VPBB1
, R1
);
68 auto TC
= std::make_unique
<VPValue
>();
70 auto *ScalarHeader
= BasicBlock::Create(C
, "");
71 VPIRBasicBlock
*ScalarHeaderVPBB
= new VPIRBasicBlock(ScalarHeader
);
72 VPBlockUtils::connectBlocks(R1
, ScalarHeaderVPBB
);
73 VPlan
Plan(VPPH
, &*TC
, VPBB1
, ScalarHeaderVPBB
);
75 #if GTEST_HAS_STREAM_REDIRECTION
76 ::testing::internal::CaptureStderr();
78 EXPECT_FALSE(verifyVPlanIsValid(Plan
));
79 #if GTEST_HAS_STREAM_REDIRECTION
80 EXPECT_STREQ("Use before def!\n",
81 ::testing::internal::GetCapturedStderr().c_str());
86 TEST(VPVerifierTest
, VPBlendUseBeforeDefDifferentBB
) {
88 IntegerType
*Int32
= IntegerType::get(C
, 32);
89 auto *Phi
= PHINode::Create(Int32
, 1);
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
});
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();
104 VPBB1
->appendRecipe(I1
);
105 VPBB2
->appendRecipe(CanIV
);
106 VPBB3
->appendRecipe(Blend
);
107 VPBB4
->appendRecipe(DefI
);
108 VPBB4
->appendRecipe(BranchOnCond
);
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
);
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
);
122 #if GTEST_HAS_STREAM_REDIRECTION
123 ::testing::internal::CaptureStderr();
125 EXPECT_FALSE(verifyVPlanIsValid(Plan
));
126 #if GTEST_HAS_STREAM_REDIRECTION
127 EXPECT_STREQ("Use before def!\n",
128 ::testing::internal::GetCapturedStderr().c_str());
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
});
143 VPBasicBlock
*VPPH
= new VPBasicBlock("ph");
144 VPBasicBlock
*VPBB1
= new VPBasicBlock();
145 VPBasicBlock
*VPBB2
= new VPBasicBlock();
147 VPBB1
->appendRecipe(I1
);
148 VPBB1
->appendRecipe(BranchOnCond2
);
149 VPBB2
->appendRecipe(CanIV
);
150 VPBB2
->appendRecipe(BranchOnCond
);
152 VPRegionBlock
*R1
= new VPRegionBlock(VPBB2
, VPBB2
, "R1");
153 VPBlockUtils::connectBlocks(VPBB1
, R1
);
154 VPBlockUtils::connectBlocks(VPBB1
, R1
);
156 auto TC
= std::make_unique
<VPValue
>();
158 auto *ScalarHeader
= BasicBlock::Create(C
, "");
159 VPIRBasicBlock
*ScalarHeaderVPBB
= new VPIRBasicBlock(ScalarHeader
);
160 VPBlockUtils::connectBlocks(R1
, ScalarHeaderVPBB
);
161 VPlan
Plan(VPPH
, &*TC
, VPBB1
, ScalarHeaderVPBB
);
163 #if GTEST_HAS_STREAM_REDIRECTION
164 ::testing::internal::CaptureStderr();
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());
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
});
182 VPBasicBlock
*VPPH
= new VPBasicBlock("ph");
183 VPBasicBlock
*VPBB1
= new VPBasicBlock();
184 VPBasicBlock
*VPBB2
= new VPBasicBlock();
185 VPBasicBlock
*VPBB3
= new VPBasicBlock();
187 VPBB1
->appendRecipe(I1
);
188 VPBB2
->appendRecipe(CanIV
);
189 VPBB2
->appendRecipe(BranchOnCond2
);
190 VPBB3
->appendRecipe(BranchOnCond
);
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
);
198 auto TC
= std::make_unique
<VPValue
>();
200 auto *ScalarHeader
= BasicBlock::Create(C
, "");
201 VPIRBasicBlock
*ScalarHeaderVPBB
= new VPIRBasicBlock(ScalarHeader
);
202 VPBlockUtils::connectBlocks(R1
, ScalarHeaderVPBB
);
203 VPlan
Plan(VPPH
, &*TC
, VPBB1
, ScalarHeaderVPBB
);
205 #if GTEST_HAS_STREAM_REDIRECTION
206 ::testing::internal::CaptureStderr();
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());
216 TEST(VPVerifierTest
, BlockOutsideRegionWithParent
) {
217 VPBasicBlock
*VPPH
= new VPBasicBlock("ph");
218 VPBasicBlock
*VPBB1
= new VPBasicBlock();
219 VPBasicBlock
*VPBB2
= new VPBasicBlock();
221 VPInstruction
*DefI
= new VPInstruction(Instruction::Add
, {});
222 VPInstruction
*BranchOnCond
=
223 new VPInstruction(VPInstruction::BranchOnCond
, {DefI
});
225 VPBB1
->appendRecipe(DefI
);
226 VPBB2
->appendRecipe(BranchOnCond
);
228 VPRegionBlock
*R1
= new VPRegionBlock(VPBB2
, VPBB2
, "R1");
229 VPBlockUtils::connectBlocks(VPBB1
, R1
);
230 VPBB1
->setParent(R1
);
232 auto TC
= std::make_unique
<VPValue
>();
234 auto *ScalarHeader
= BasicBlock::Create(C
, "");
235 VPIRBasicBlock
*ScalarHeaderVPBB
= new VPIRBasicBlock(ScalarHeader
);
236 VPBlockUtils::connectBlocks(R1
, ScalarHeaderVPBB
);
237 VPlan
Plan(VPPH
, &*TC
, VPBB1
, ScalarHeaderVPBB
);
239 #if GTEST_HAS_STREAM_REDIRECTION
240 ::testing::internal::CaptureStderr();
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());