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
);
31 VPlan
Plan(VPPH
, &*TC
, VPBB1
);
33 #if GTEST_HAS_STREAM_REDIRECTION
34 ::testing::internal::CaptureStderr();
36 EXPECT_FALSE(verifyVPlanIsValid(Plan
));
37 #if GTEST_HAS_STREAM_REDIRECTION
38 EXPECT_STREQ("Use before def!\n",
39 ::testing::internal::GetCapturedStderr().c_str());
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
});
50 VPBasicBlock
*VPPH
= new VPBasicBlock("ph");
51 VPBasicBlock
*VPBB1
= new VPBasicBlock();
52 VPBasicBlock
*VPBB2
= new VPBasicBlock();
54 VPBB1
->appendRecipe(UseI
);
55 VPBB2
->appendRecipe(CanIV
);
56 VPBB2
->appendRecipe(DefI
);
57 VPBB2
->appendRecipe(BranchOnCond
);
59 VPRegionBlock
*R1
= new VPRegionBlock(VPBB2
, VPBB2
, "R1");
60 VPBlockUtils::connectBlocks(VPBB1
, R1
);
62 auto TC
= std::make_unique
<VPValue
>();
63 VPlan
Plan(VPPH
, &*TC
, VPBB1
);
65 #if GTEST_HAS_STREAM_REDIRECTION
66 ::testing::internal::CaptureStderr();
68 EXPECT_FALSE(verifyVPlanIsValid(Plan
));
69 #if GTEST_HAS_STREAM_REDIRECTION
70 EXPECT_STREQ("Use before def!\n",
71 ::testing::internal::GetCapturedStderr().c_str());
75 TEST(VPVerifierTest
, VPBlendUseBeforeDefDifferentBB
) {
77 IntegerType
*Int32
= IntegerType::get(C
, 32);
78 auto *Phi
= PHINode::Create(Int32
, 1);
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
});
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();
93 VPBB1
->appendRecipe(I1
);
94 VPBB2
->appendRecipe(CanIV
);
95 VPBB3
->appendRecipe(Blend
);
96 VPBB4
->appendRecipe(DefI
);
97 VPBB4
->appendRecipe(BranchOnCond
);
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
);
105 auto TC
= std::make_unique
<VPValue
>();
106 VPlan
Plan(VPPH
, &*TC
, VPBB1
);
108 #if GTEST_HAS_STREAM_REDIRECTION
109 ::testing::internal::CaptureStderr();
111 EXPECT_FALSE(verifyVPlanIsValid(Plan
));
112 #if GTEST_HAS_STREAM_REDIRECTION
113 EXPECT_STREQ("Use before def!\n",
114 ::testing::internal::GetCapturedStderr().c_str());
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
});
128 VPBasicBlock
*VPPH
= new VPBasicBlock("ph");
129 VPBasicBlock
*VPBB1
= new VPBasicBlock();
130 VPBasicBlock
*VPBB2
= new VPBasicBlock();
132 VPBB1
->appendRecipe(I1
);
133 VPBB1
->appendRecipe(BranchOnCond2
);
134 VPBB2
->appendRecipe(CanIV
);
135 VPBB2
->appendRecipe(BranchOnCond
);
137 VPRegionBlock
*R1
= new VPRegionBlock(VPBB2
, VPBB2
, "R1");
138 VPBlockUtils::connectBlocks(VPBB1
, R1
);
139 VPBlockUtils::connectBlocks(VPBB1
, R1
);
141 auto TC
= std::make_unique
<VPValue
>();
142 VPlan
Plan(VPPH
, &*TC
, VPBB1
);
144 #if GTEST_HAS_STREAM_REDIRECTION
145 ::testing::internal::CaptureStderr();
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());
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
});
162 VPBasicBlock
*VPPH
= new VPBasicBlock("ph");
163 VPBasicBlock
*VPBB1
= new VPBasicBlock();
164 VPBasicBlock
*VPBB2
= new VPBasicBlock();
165 VPBasicBlock
*VPBB3
= new VPBasicBlock();
167 VPBB1
->appendRecipe(I1
);
168 VPBB2
->appendRecipe(CanIV
);
169 VPBB2
->appendRecipe(BranchOnCond2
);
170 VPBB3
->appendRecipe(BranchOnCond
);
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
);
178 auto TC
= std::make_unique
<VPValue
>();
179 VPlan
Plan(VPPH
, &*TC
, VPBB1
);
181 #if GTEST_HAS_STREAM_REDIRECTION
182 ::testing::internal::CaptureStderr();
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());
191 TEST(VPVerifierTest
, BlockOutsideRegionWithParent
) {
192 VPBasicBlock
*VPPH
= new VPBasicBlock("ph");
193 VPBasicBlock
*VPBB1
= new VPBasicBlock();
194 VPBasicBlock
*VPBB2
= new VPBasicBlock();
196 VPInstruction
*DefI
= new VPInstruction(Instruction::Add
, {});
197 VPInstruction
*BranchOnCond
=
198 new VPInstruction(VPInstruction::BranchOnCond
, {DefI
});
200 VPBB1
->appendRecipe(DefI
);
201 VPBB2
->appendRecipe(BranchOnCond
);
203 VPRegionBlock
*R1
= new VPRegionBlock(VPBB2
, VPBB2
, "R1");
204 VPBlockUtils::connectBlocks(VPBB1
, R1
);
205 VPBB1
->setParent(R1
);
207 auto TC
= std::make_unique
<VPValue
>();
208 VPlan
Plan(VPPH
, &*TC
, VPBB1
);
210 #if GTEST_HAS_STREAM_REDIRECTION
211 ::testing::internal::CaptureStderr();
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());