1 //===- llvm/unittests/Transforms/Vectorize/VPlanTest.cpp - VPlan tests ----===//
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8 //===----------------------------------------------------------------------===//
10 #include "../lib/Transforms/Vectorize/VPlan.h"
11 #include "../lib/Transforms/Vectorize/VPlanCFG.h"
12 #include "llvm/ADT/DepthFirstIterator.h"
13 #include "llvm/ADT/PostOrderIterator.h"
14 #include "llvm/Analysis/VectorUtils.h"
15 #include "llvm/IR/Instruction.h"
16 #include "llvm/IR/Instructions.h"
17 #include "gtest/gtest.h"
23 #define CHECK_ITERATOR(Range1, ...) \
25 std::vector<VPInstruction *> Tmp = {__VA_ARGS__}; \
26 EXPECT_EQ((size_t)std::distance(Range1.begin(), Range1.end()), \
28 for (auto Pair : zip(Range1, make_range(Tmp.begin(), Tmp.end()))) \
29 EXPECT_EQ(&std::get<0>(Pair), std::get<1>(Pair)); \
32 TEST(VPInstructionTest
, insertBefore
) {
33 VPInstruction
*I1
= new VPInstruction(0, {});
34 VPInstruction
*I2
= new VPInstruction(1, {});
35 VPInstruction
*I3
= new VPInstruction(2, {});
38 VPBB1
.appendRecipe(I1
);
41 CHECK_ITERATOR(VPBB1
, I2
, I1
);
44 CHECK_ITERATOR(VPBB1
, I3
, I2
, I1
);
47 TEST(VPInstructionTest
, eraseFromParent
) {
48 VPInstruction
*I1
= new VPInstruction(0, {});
49 VPInstruction
*I2
= new VPInstruction(1, {});
50 VPInstruction
*I3
= new VPInstruction(2, {});
53 VPBB1
.appendRecipe(I1
);
54 VPBB1
.appendRecipe(I2
);
55 VPBB1
.appendRecipe(I3
);
57 I2
->eraseFromParent();
58 CHECK_ITERATOR(VPBB1
, I1
, I3
);
60 I1
->eraseFromParent();
61 CHECK_ITERATOR(VPBB1
, I3
);
63 I3
->eraseFromParent();
64 EXPECT_TRUE(VPBB1
.empty());
67 TEST(VPInstructionTest
, moveAfter
) {
68 VPInstruction
*I1
= new VPInstruction(0, {});
69 VPInstruction
*I2
= new VPInstruction(1, {});
70 VPInstruction
*I3
= new VPInstruction(2, {});
73 VPBB1
.appendRecipe(I1
);
74 VPBB1
.appendRecipe(I2
);
75 VPBB1
.appendRecipe(I3
);
79 CHECK_ITERATOR(VPBB1
, I2
, I1
, I3
);
81 VPInstruction
*I4
= new VPInstruction(4, {});
82 VPInstruction
*I5
= new VPInstruction(5, {});
84 VPBB2
.appendRecipe(I4
);
85 VPBB2
.appendRecipe(I5
);
89 CHECK_ITERATOR(VPBB1
, I2
, I1
);
90 CHECK_ITERATOR(VPBB2
, I4
, I3
, I5
);
91 EXPECT_EQ(I3
->getParent(), I4
->getParent());
94 TEST(VPInstructionTest
, moveBefore
) {
95 VPInstruction
*I1
= new VPInstruction(0, {});
96 VPInstruction
*I2
= new VPInstruction(1, {});
97 VPInstruction
*I3
= new VPInstruction(2, {});
100 VPBB1
.appendRecipe(I1
);
101 VPBB1
.appendRecipe(I2
);
102 VPBB1
.appendRecipe(I3
);
104 I1
->moveBefore(VPBB1
, I3
->getIterator());
106 CHECK_ITERATOR(VPBB1
, I2
, I1
, I3
);
108 VPInstruction
*I4
= new VPInstruction(4, {});
109 VPInstruction
*I5
= new VPInstruction(5, {});
111 VPBB2
.appendRecipe(I4
);
112 VPBB2
.appendRecipe(I5
);
114 I3
->moveBefore(VPBB2
, I4
->getIterator());
116 CHECK_ITERATOR(VPBB1
, I2
, I1
);
117 CHECK_ITERATOR(VPBB2
, I3
, I4
, I5
);
118 EXPECT_EQ(I3
->getParent(), I4
->getParent());
122 I4
->moveBefore(VPBB3
, VPBB3
.end());
124 CHECK_ITERATOR(VPBB1
, I2
, I1
);
125 CHECK_ITERATOR(VPBB2
, I3
, I5
);
126 CHECK_ITERATOR(VPBB3
, I4
);
127 EXPECT_EQ(&VPBB3
, I4
->getParent());
130 TEST(VPInstructionTest
, setOperand
) {
131 VPValue
*VPV1
= new VPValue();
132 VPValue
*VPV2
= new VPValue();
133 VPInstruction
*I1
= new VPInstruction(0, {VPV1
, VPV2
});
134 EXPECT_EQ(1u, VPV1
->getNumUsers());
135 EXPECT_EQ(I1
, *VPV1
->user_begin());
136 EXPECT_EQ(1u, VPV2
->getNumUsers());
137 EXPECT_EQ(I1
, *VPV2
->user_begin());
139 // Replace operand 0 (VPV1) with VPV3.
140 VPValue
*VPV3
= new VPValue();
141 I1
->setOperand(0, VPV3
);
142 EXPECT_EQ(0u, VPV1
->getNumUsers());
143 EXPECT_EQ(1u, VPV2
->getNumUsers());
144 EXPECT_EQ(I1
, *VPV2
->user_begin());
145 EXPECT_EQ(1u, VPV3
->getNumUsers());
146 EXPECT_EQ(I1
, *VPV3
->user_begin());
148 // Replace operand 1 (VPV2) with VPV3.
149 I1
->setOperand(1, VPV3
);
150 EXPECT_EQ(0u, VPV1
->getNumUsers());
151 EXPECT_EQ(0u, VPV2
->getNumUsers());
152 EXPECT_EQ(2u, VPV3
->getNumUsers());
153 EXPECT_EQ(I1
, *VPV3
->user_begin());
154 EXPECT_EQ(I1
, *std::next(VPV3
->user_begin()));
156 // Replace operand 0 (VPV3) with VPV4.
157 VPValue
*VPV4
= new VPValue();
158 I1
->setOperand(0, VPV4
);
159 EXPECT_EQ(1u, VPV3
->getNumUsers());
160 EXPECT_EQ(I1
, *VPV3
->user_begin());
161 EXPECT_EQ(I1
, *VPV4
->user_begin());
163 // Replace operand 1 (VPV3) with VPV4.
164 I1
->setOperand(1, VPV4
);
165 EXPECT_EQ(0u, VPV3
->getNumUsers());
166 EXPECT_EQ(I1
, *VPV4
->user_begin());
167 EXPECT_EQ(I1
, *std::next(VPV4
->user_begin()));
176 TEST(VPInstructionTest
, replaceAllUsesWith
) {
177 VPValue
*VPV1
= new VPValue();
178 VPValue
*VPV2
= new VPValue();
179 VPInstruction
*I1
= new VPInstruction(0, {VPV1
, VPV2
});
181 // Replace all uses of VPV1 with VPV3.
182 VPValue
*VPV3
= new VPValue();
183 VPV1
->replaceAllUsesWith(VPV3
);
184 EXPECT_EQ(VPV3
, I1
->getOperand(0));
185 EXPECT_EQ(VPV2
, I1
->getOperand(1));
186 EXPECT_EQ(0u, VPV1
->getNumUsers());
187 EXPECT_EQ(1u, VPV2
->getNumUsers());
188 EXPECT_EQ(I1
, *VPV2
->user_begin());
189 EXPECT_EQ(1u, VPV3
->getNumUsers());
190 EXPECT_EQ(I1
, *VPV3
->user_begin());
192 // Replace all uses of VPV2 with VPV3.
193 VPV2
->replaceAllUsesWith(VPV3
);
194 EXPECT_EQ(VPV3
, I1
->getOperand(0));
195 EXPECT_EQ(VPV3
, I1
->getOperand(1));
196 EXPECT_EQ(0u, VPV1
->getNumUsers());
197 EXPECT_EQ(0u, VPV2
->getNumUsers());
198 EXPECT_EQ(2u, VPV3
->getNumUsers());
199 EXPECT_EQ(I1
, *VPV3
->user_begin());
201 // Replace all uses of VPV3 with VPV1.
202 VPV3
->replaceAllUsesWith(VPV1
);
203 EXPECT_EQ(VPV1
, I1
->getOperand(0));
204 EXPECT_EQ(VPV1
, I1
->getOperand(1));
205 EXPECT_EQ(2u, VPV1
->getNumUsers());
206 EXPECT_EQ(I1
, *VPV1
->user_begin());
207 EXPECT_EQ(0u, VPV2
->getNumUsers());
208 EXPECT_EQ(0u, VPV3
->getNumUsers());
210 VPInstruction
*I2
= new VPInstruction(0, {VPV1
, VPV2
});
211 EXPECT_EQ(3u, VPV1
->getNumUsers());
212 VPV1
->replaceAllUsesWith(VPV3
);
213 EXPECT_EQ(3u, VPV3
->getNumUsers());
222 TEST(VPInstructionTest
, releaseOperandsAtDeletion
) {
223 VPValue
*VPV1
= new VPValue();
224 VPValue
*VPV2
= new VPValue();
225 VPInstruction
*I1
= new VPInstruction(0, {VPV1
, VPV2
});
227 EXPECT_EQ(1u, VPV1
->getNumUsers());
228 EXPECT_EQ(I1
, *VPV1
->user_begin());
229 EXPECT_EQ(1u, VPV2
->getNumUsers());
230 EXPECT_EQ(I1
, *VPV2
->user_begin());
234 EXPECT_EQ(0u, VPV1
->getNumUsers());
235 EXPECT_EQ(0u, VPV2
->getNumUsers());
240 TEST(VPBasicBlockTest
, getPlan
) {
242 auto *ScalarHeader
= BasicBlock::Create(C
, "");
244 VPBasicBlock
*VPPH
= new VPBasicBlock("ph");
245 VPBasicBlock
*VPBB1
= new VPBasicBlock();
246 VPBasicBlock
*VPBB2
= new VPBasicBlock();
247 VPBasicBlock
*VPBB3
= new VPBasicBlock();
248 VPBasicBlock
*VPBB4
= new VPBasicBlock();
255 VPBlockUtils::connectBlocks(VPBB1
, VPBB2
);
256 VPBlockUtils::connectBlocks(VPBB1
, VPBB3
);
257 VPBlockUtils::connectBlocks(VPBB2
, VPBB4
);
258 VPBlockUtils::connectBlocks(VPBB3
, VPBB4
);
260 auto TC
= std::make_unique
<VPValue
>();
261 VPIRBasicBlock
*ScalarHeaderVPBB
= new VPIRBasicBlock(ScalarHeader
);
262 VPBlockUtils::connectBlocks(VPBB4
, ScalarHeaderVPBB
);
263 VPlan
Plan(VPPH
, &*TC
, VPBB1
, ScalarHeaderVPBB
);
265 EXPECT_EQ(&Plan
, VPBB1
->getPlan());
266 EXPECT_EQ(&Plan
, VPBB2
->getPlan());
267 EXPECT_EQ(&Plan
, VPBB3
->getPlan());
268 EXPECT_EQ(&Plan
, VPBB4
->getPlan());
272 VPBasicBlock
*VPPH
= new VPBasicBlock("ph");
273 // VPBasicBlock is the entry into the VPlan, followed by a region.
274 VPBasicBlock
*R1BB1
= new VPBasicBlock();
275 VPBasicBlock
*R1BB2
= new VPBasicBlock();
276 VPRegionBlock
*R1
= new VPRegionBlock(R1BB1
, R1BB2
, "R1");
277 VPBlockUtils::connectBlocks(R1BB1
, R1BB2
);
279 VPBasicBlock
*VPBB1
= new VPBasicBlock();
280 VPBlockUtils::connectBlocks(VPBB1
, R1
);
282 auto TC
= std::make_unique
<VPValue
>();
283 VPIRBasicBlock
*ScalarHeaderVPBB
= new VPIRBasicBlock(ScalarHeader
);
284 VPBlockUtils::connectBlocks(R1
, ScalarHeaderVPBB
);
285 VPlan
Plan(VPPH
, &*TC
, VPBB1
, ScalarHeaderVPBB
);
287 EXPECT_EQ(&Plan
, VPBB1
->getPlan());
288 EXPECT_EQ(&Plan
, R1
->getPlan());
289 EXPECT_EQ(&Plan
, R1BB1
->getPlan());
290 EXPECT_EQ(&Plan
, R1BB2
->getPlan());
294 VPBasicBlock
*VPPH
= new VPBasicBlock("ph");
296 VPBasicBlock
*R1BB1
= new VPBasicBlock();
297 VPBasicBlock
*R1BB2
= new VPBasicBlock();
298 VPRegionBlock
*R1
= new VPRegionBlock(R1BB1
, R1BB2
, "R1");
299 VPBlockUtils::connectBlocks(R1BB1
, R1BB2
);
301 VPBasicBlock
*R2BB1
= new VPBasicBlock();
302 VPBasicBlock
*R2BB2
= new VPBasicBlock();
303 VPRegionBlock
*R2
= new VPRegionBlock(R2BB1
, R2BB2
, "R2");
304 VPBlockUtils::connectBlocks(R2BB1
, R2BB2
);
306 VPBasicBlock
*VPBB1
= new VPBasicBlock();
307 VPBlockUtils::connectBlocks(VPBB1
, R1
);
308 VPBlockUtils::connectBlocks(VPBB1
, R2
);
310 VPBasicBlock
*VPBB2
= new VPBasicBlock();
311 VPBlockUtils::connectBlocks(R1
, VPBB2
);
312 VPBlockUtils::connectBlocks(R2
, VPBB2
);
314 auto TC
= std::make_unique
<VPValue
>();
315 VPIRBasicBlock
*ScalarHeaderVPBB
= new VPIRBasicBlock(ScalarHeader
);
316 VPBlockUtils::connectBlocks(R2
, ScalarHeaderVPBB
);
317 VPlan
Plan(VPPH
, &*TC
, VPBB1
, ScalarHeaderVPBB
);
319 EXPECT_EQ(&Plan
, VPBB1
->getPlan());
320 EXPECT_EQ(&Plan
, R1
->getPlan());
321 EXPECT_EQ(&Plan
, R1BB1
->getPlan());
322 EXPECT_EQ(&Plan
, R1BB2
->getPlan());
323 EXPECT_EQ(&Plan
, R2
->getPlan());
324 EXPECT_EQ(&Plan
, R2BB1
->getPlan());
325 EXPECT_EQ(&Plan
, R2BB2
->getPlan());
326 EXPECT_EQ(&Plan
, VPBB2
->getPlan());
331 TEST(VPBasicBlockTest
, TraversingIteratorTest
) {
333 auto *ScalarHeader
= BasicBlock::Create(C
, "");
335 // VPBasicBlocks only
342 VPBasicBlock
*VPPH
= new VPBasicBlock("ph");
343 VPBasicBlock
*VPBB1
= new VPBasicBlock();
344 VPBasicBlock
*VPBB2
= new VPBasicBlock();
345 VPBasicBlock
*VPBB3
= new VPBasicBlock();
346 VPBasicBlock
*VPBB4
= new VPBasicBlock();
348 VPBlockUtils::connectBlocks(VPBB1
, VPBB2
);
349 VPBlockUtils::connectBlocks(VPBB1
, VPBB3
);
350 VPBlockUtils::connectBlocks(VPBB2
, VPBB4
);
351 VPBlockUtils::connectBlocks(VPBB3
, VPBB4
);
353 VPBlockDeepTraversalWrapper
<const VPBlockBase
*> Start(VPBB1
);
354 SmallVector
<const VPBlockBase
*> FromIterator(depth_first(Start
));
355 EXPECT_EQ(4u, FromIterator
.size());
356 EXPECT_EQ(VPBB1
, FromIterator
[0]);
357 EXPECT_EQ(VPBB2
, FromIterator
[1]);
359 // Use Plan to properly clean up created blocks.
360 auto TC
= std::make_unique
<VPValue
>();
361 VPIRBasicBlock
*ScalarHeaderVPBB
= new VPIRBasicBlock(ScalarHeader
);
362 VPBlockUtils::connectBlocks(VPBB4
, ScalarHeaderVPBB
);
363 VPlan
Plan(VPPH
, &*TC
, VPBB1
, ScalarHeaderVPBB
);
367 // 2 consecutive regions.
385 VPBasicBlock
*VPPH
= new VPBasicBlock("ph");
386 VPBasicBlock
*VPBB0
= new VPBasicBlock("VPBB0");
387 VPBasicBlock
*R1BB1
= new VPBasicBlock();
388 VPBasicBlock
*R1BB2
= new VPBasicBlock();
389 VPBasicBlock
*R1BB3
= new VPBasicBlock();
390 VPBasicBlock
*R1BB4
= new VPBasicBlock();
391 VPRegionBlock
*R1
= new VPRegionBlock(R1BB1
, R1BB4
, "R1");
392 R1BB2
->setParent(R1
);
393 R1BB3
->setParent(R1
);
394 VPBlockUtils::connectBlocks(VPBB0
, R1
);
395 VPBlockUtils::connectBlocks(R1BB1
, R1BB2
);
396 VPBlockUtils::connectBlocks(R1BB1
, R1BB3
);
397 VPBlockUtils::connectBlocks(R1BB2
, R1BB4
);
398 VPBlockUtils::connectBlocks(R1BB3
, R1BB4
);
400 VPBlockUtils::connectBlocks(R1BB3
, R1BB3
);
402 VPBasicBlock
*R2BB1
= new VPBasicBlock();
403 VPBasicBlock
*R2BB2
= new VPBasicBlock();
404 VPRegionBlock
*R2
= new VPRegionBlock(R2BB1
, R2BB2
, "R2");
405 VPBlockUtils::connectBlocks(R2BB1
, R2BB2
);
406 VPBlockUtils::connectBlocks(R1
, R2
);
409 SmallVector
<const VPBlockBase
*> FromIterator(
410 VPAllSuccessorsIterator
<VPBlockBase
*>(R1
),
411 VPAllSuccessorsIterator
<VPBlockBase
*>::end(R1
));
412 EXPECT_EQ(1u, FromIterator
.size());
413 EXPECT_EQ(R1BB1
, FromIterator
[0]);
416 VPBlockDeepTraversalWrapper
<VPBlockBase
*> Start(R1
);
417 FromIterator
.clear();
418 copy(df_begin(Start
), df_end(Start
), std::back_inserter(FromIterator
));
419 EXPECT_EQ(8u, FromIterator
.size());
420 EXPECT_EQ(R1
, FromIterator
[0]);
421 EXPECT_EQ(R1BB1
, FromIterator
[1]);
422 EXPECT_EQ(R1BB2
, FromIterator
[2]);
423 EXPECT_EQ(R1BB4
, FromIterator
[3]);
424 EXPECT_EQ(R2
, FromIterator
[4]);
425 EXPECT_EQ(R2BB1
, FromIterator
[5]);
426 EXPECT_EQ(R2BB2
, FromIterator
[6]);
427 EXPECT_EQ(R1BB3
, FromIterator
[7]);
429 // const VPBasicBlocks only.
430 FromIterator
.clear();
431 copy(VPBlockUtils::blocksOnly
<const VPBasicBlock
>(depth_first(Start
)),
432 std::back_inserter(FromIterator
));
433 EXPECT_EQ(6u, FromIterator
.size());
434 EXPECT_EQ(R1BB1
, FromIterator
[0]);
435 EXPECT_EQ(R1BB2
, FromIterator
[1]);
436 EXPECT_EQ(R1BB4
, FromIterator
[2]);
437 EXPECT_EQ(R2BB1
, FromIterator
[3]);
438 EXPECT_EQ(R2BB2
, FromIterator
[4]);
439 EXPECT_EQ(R1BB3
, FromIterator
[5]);
441 // VPRegionBlocks only.
442 SmallVector
<VPRegionBlock
*> FromIteratorVPRegion(
443 VPBlockUtils::blocksOnly
<VPRegionBlock
>(depth_first(Start
)));
444 EXPECT_EQ(2u, FromIteratorVPRegion
.size());
445 EXPECT_EQ(R1
, FromIteratorVPRegion
[0]);
446 EXPECT_EQ(R2
, FromIteratorVPRegion
[1]);
449 FromIterator
.clear();
450 copy(post_order(Start
), std::back_inserter(FromIterator
));
451 EXPECT_EQ(8u, FromIterator
.size());
452 EXPECT_EQ(R2BB2
, FromIterator
[0]);
453 EXPECT_EQ(R2BB1
, FromIterator
[1]);
454 EXPECT_EQ(R2
, FromIterator
[2]);
455 EXPECT_EQ(R1BB4
, FromIterator
[3]);
456 EXPECT_EQ(R1BB2
, FromIterator
[4]);
457 EXPECT_EQ(R1BB3
, FromIterator
[5]);
458 EXPECT_EQ(R1BB1
, FromIterator
[6]);
459 EXPECT_EQ(R1
, FromIterator
[7]);
461 // Use Plan to properly clean up created blocks.
462 auto TC
= std::make_unique
<VPValue
>();
463 VPIRBasicBlock
*ScalarHeaderVPBB
= new VPIRBasicBlock(ScalarHeader
);
464 VPBlockUtils::connectBlocks(R2
, ScalarHeaderVPBB
);
465 VPlan
Plan(VPPH
, &*TC
, VPBB0
, ScalarHeaderVPBB
);
489 VPBasicBlock
*VPPH
= new VPBasicBlock("ph");
490 VPBasicBlock
*R1BB1
= new VPBasicBlock("R1BB1");
491 VPBasicBlock
*R1BB2
= new VPBasicBlock("R1BB2");
492 VPBasicBlock
*R1BB3
= new VPBasicBlock("R1BB3");
493 VPRegionBlock
*R1
= new VPRegionBlock(R1BB1
, R1BB3
, "R1");
495 VPBasicBlock
*R2BB1
= new VPBasicBlock("R2BB1");
496 VPBasicBlock
*R2BB2
= new VPBasicBlock("R2BB2");
497 VPBasicBlock
*R2BB3
= new VPBasicBlock("R2BB3");
498 VPRegionBlock
*R2
= new VPRegionBlock(R2BB1
, R2BB3
, "R2");
499 R2BB2
->setParent(R2
);
500 VPBlockUtils::connectBlocks(R2BB1
, R2BB2
);
501 VPBlockUtils::connectBlocks(R2BB2
, R2BB1
);
502 VPBlockUtils::connectBlocks(R2BB2
, R2BB3
);
505 VPBlockUtils::connectBlocks(R1BB1
, R2
);
506 R1BB2
->setParent(R1
);
507 VPBlockUtils::connectBlocks(R1BB1
, R1BB2
);
508 VPBlockUtils::connectBlocks(R1BB2
, R1BB3
);
509 VPBlockUtils::connectBlocks(R2
, R1BB3
);
511 VPBasicBlock
*VPBB1
= new VPBasicBlock("VPBB1");
512 VPBlockUtils::connectBlocks(VPBB1
, R1
);
513 VPBasicBlock
*VPBB2
= new VPBasicBlock("VPBB2");
514 VPBlockUtils::connectBlocks(R1
, VPBB2
);
517 VPBlockDeepTraversalWrapper
<VPBlockBase
*> Start(VPBB1
);
518 SmallVector
<VPBlockBase
*> FromIterator(depth_first(Start
));
519 EXPECT_EQ(10u, FromIterator
.size());
520 EXPECT_EQ(VPBB1
, FromIterator
[0]);
521 EXPECT_EQ(R1
, FromIterator
[1]);
522 EXPECT_EQ(R1BB1
, FromIterator
[2]);
523 EXPECT_EQ(R2
, FromIterator
[3]);
524 EXPECT_EQ(R2BB1
, FromIterator
[4]);
525 EXPECT_EQ(R2BB2
, FromIterator
[5]);
526 EXPECT_EQ(R2BB3
, FromIterator
[6]);
527 EXPECT_EQ(R1BB3
, FromIterator
[7]);
528 EXPECT_EQ(VPBB2
, FromIterator
[8]);
529 EXPECT_EQ(R1BB2
, FromIterator
[9]);
532 FromIterator
.clear();
533 FromIterator
.append(po_begin(Start
), po_end(Start
));
534 EXPECT_EQ(10u, FromIterator
.size());
535 EXPECT_EQ(VPBB2
, FromIterator
[0]);
536 EXPECT_EQ(R1BB3
, FromIterator
[1]);
537 EXPECT_EQ(R2BB3
, FromIterator
[2]);
538 EXPECT_EQ(R2BB2
, FromIterator
[3]);
539 EXPECT_EQ(R2BB1
, FromIterator
[4]);
540 EXPECT_EQ(R2
, FromIterator
[5]);
541 EXPECT_EQ(R1BB2
, FromIterator
[6]);
542 EXPECT_EQ(R1BB1
, FromIterator
[7]);
543 EXPECT_EQ(R1
, FromIterator
[8]);
544 EXPECT_EQ(VPBB1
, FromIterator
[9]);
546 // Use Plan to properly clean up created blocks.
547 auto TC
= std::make_unique
<VPValue
>();
548 VPIRBasicBlock
*ScalarHeaderVPBB
= new VPIRBasicBlock(ScalarHeader
);
549 VPBlockUtils::connectBlocks(VPBB2
, ScalarHeaderVPBB
);
550 VPlan
Plan(VPPH
, &*TC
, VPBB1
, ScalarHeaderVPBB
);
564 VPBasicBlock
*VPPH
= new VPBasicBlock("ph");
565 VPBasicBlock
*R2BB1
= new VPBasicBlock("R2BB1");
566 VPBasicBlock
*R2BB2
= new VPBasicBlock("R2BB2");
567 VPRegionBlock
*R2
= new VPRegionBlock(R2BB1
, R2BB2
, "R2");
568 VPBlockUtils::connectBlocks(R2BB1
, R2BB2
);
570 VPRegionBlock
*R1
= new VPRegionBlock(R2
, R2
, "R1");
573 VPBasicBlock
*VPBB1
= new VPBasicBlock("VPBB1");
574 VPBlockUtils::connectBlocks(VPBB1
, R1
);
577 VPBlockDeepTraversalWrapper
<VPBlockBase
*> Start(VPBB1
);
578 SmallVector
<VPBlockBase
*> FromIterator(depth_first(Start
));
579 EXPECT_EQ(5u, FromIterator
.size());
580 EXPECT_EQ(VPBB1
, FromIterator
[0]);
581 EXPECT_EQ(R1
, FromIterator
[1]);
582 EXPECT_EQ(R2
, FromIterator
[2]);
583 EXPECT_EQ(R2BB1
, FromIterator
[3]);
584 EXPECT_EQ(R2BB2
, FromIterator
[4]);
587 FromIterator
.clear();
588 FromIterator
.append(po_begin(Start
), po_end(Start
));
589 EXPECT_EQ(5u, FromIterator
.size());
590 EXPECT_EQ(R2BB2
, FromIterator
[0]);
591 EXPECT_EQ(R2BB1
, FromIterator
[1]);
592 EXPECT_EQ(R2
, FromIterator
[2]);
593 EXPECT_EQ(R1
, FromIterator
[3]);
594 EXPECT_EQ(VPBB1
, FromIterator
[4]);
596 // Use Plan to properly clean up created blocks.
597 auto TC
= std::make_unique
<VPValue
>();
598 VPIRBasicBlock
*ScalarHeaderVPBB
= new VPIRBasicBlock(ScalarHeader
);
599 VPBlockUtils::connectBlocks(R1
, ScalarHeaderVPBB
);
600 VPlan
Plan(VPPH
, &*TC
, VPBB1
, ScalarHeaderVPBB
);
604 // Nested regions with both R3 and R2 being exit nodes without successors.
605 // The successors of R1 should be used.
622 VPBasicBlock
*VPPH
= new VPBasicBlock("ph");
623 VPBasicBlock
*R3BB1
= new VPBasicBlock("R3BB1");
624 VPRegionBlock
*R3
= new VPRegionBlock(R3BB1
, R3BB1
, "R3");
626 VPBasicBlock
*R2BB1
= new VPBasicBlock("R2BB1");
627 VPRegionBlock
*R2
= new VPRegionBlock(R2BB1
, R3
, "R2");
629 VPBlockUtils::connectBlocks(R2BB1
, R3
);
631 VPRegionBlock
*R1
= new VPRegionBlock(R2
, R2
, "R1");
634 VPBasicBlock
*VPBB1
= new VPBasicBlock("VPBB1");
635 VPBasicBlock
*VPBB2
= new VPBasicBlock("VPBB2");
636 VPBlockUtils::connectBlocks(VPBB1
, R1
);
637 VPBlockUtils::connectBlocks(R1
, VPBB2
);
640 VPBlockDeepTraversalWrapper
<VPBlockBase
*> Start(VPBB1
);
641 SmallVector
<VPBlockBase
*> FromIterator(depth_first(Start
));
642 EXPECT_EQ(7u, FromIterator
.size());
643 EXPECT_EQ(VPBB1
, FromIterator
[0]);
644 EXPECT_EQ(R1
, FromIterator
[1]);
645 EXPECT_EQ(R2
, FromIterator
[2]);
646 EXPECT_EQ(R2BB1
, FromIterator
[3]);
647 EXPECT_EQ(R3
, FromIterator
[4]);
648 EXPECT_EQ(R3BB1
, FromIterator
[5]);
649 EXPECT_EQ(VPBB2
, FromIterator
[6]);
651 SmallVector
<VPBlockBase
*> FromIteratorVPBB
;
652 copy(VPBlockUtils::blocksOnly
<VPBasicBlock
>(depth_first(Start
)),
653 std::back_inserter(FromIteratorVPBB
));
654 EXPECT_EQ(VPBB1
, FromIteratorVPBB
[0]);
655 EXPECT_EQ(R2BB1
, FromIteratorVPBB
[1]);
656 EXPECT_EQ(R3BB1
, FromIteratorVPBB
[2]);
657 EXPECT_EQ(VPBB2
, FromIteratorVPBB
[3]);
660 FromIterator
.clear();
661 copy(post_order(Start
), std::back_inserter(FromIterator
));
662 EXPECT_EQ(7u, FromIterator
.size());
663 EXPECT_EQ(VPBB2
, FromIterator
[0]);
664 EXPECT_EQ(R3BB1
, FromIterator
[1]);
665 EXPECT_EQ(R3
, FromIterator
[2]);
666 EXPECT_EQ(R2BB1
, FromIterator
[3]);
667 EXPECT_EQ(R2
, FromIterator
[4]);
668 EXPECT_EQ(R1
, FromIterator
[5]);
669 EXPECT_EQ(VPBB1
, FromIterator
[6]);
671 // Post-order, const VPRegionBlocks only.
672 VPBlockDeepTraversalWrapper
<const VPBlockBase
*> StartConst(VPBB1
);
673 SmallVector
<const VPRegionBlock
*> FromIteratorVPRegion(
674 VPBlockUtils::blocksOnly
<const VPRegionBlock
>(post_order(StartConst
)));
675 EXPECT_EQ(3u, FromIteratorVPRegion
.size());
676 EXPECT_EQ(R3
, FromIteratorVPRegion
[0]);
677 EXPECT_EQ(R2
, FromIteratorVPRegion
[1]);
678 EXPECT_EQ(R1
, FromIteratorVPRegion
[2]);
680 // Post-order, VPBasicBlocks only.
681 FromIterator
.clear();
682 copy(VPBlockUtils::blocksOnly
<VPBasicBlock
>(post_order(Start
)),
683 std::back_inserter(FromIterator
));
684 EXPECT_EQ(FromIterator
.size(), 4u);
685 EXPECT_EQ(VPBB2
, FromIterator
[0]);
686 EXPECT_EQ(R3BB1
, FromIterator
[1]);
687 EXPECT_EQ(R2BB1
, FromIterator
[2]);
688 EXPECT_EQ(VPBB1
, FromIterator
[3]);
690 // Use Plan to properly clean up created blocks.
691 auto TC
= std::make_unique
<VPValue
>();
692 VPIRBasicBlock
*ScalarHeaderVPBB
= new VPIRBasicBlock(ScalarHeader
);
693 VPBlockUtils::connectBlocks(VPBB2
, ScalarHeaderVPBB
);
694 VPlan
Plan(VPPH
, &*TC
, VPBB1
, ScalarHeaderVPBB
);
699 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
700 TEST(VPBasicBlockTest
, print
) {
701 VPInstruction
*TC
= new VPInstruction(Instruction::Add
, {});
702 VPBasicBlock
*VPBB0
= new VPBasicBlock("preheader");
703 VPBB0
->appendRecipe(TC
);
705 VPInstruction
*I1
= new VPInstruction(Instruction::Add
, {});
706 VPInstruction
*I2
= new VPInstruction(Instruction::Sub
, {I1
});
707 VPInstruction
*I3
= new VPInstruction(Instruction::Br
, {I1
, I2
});
709 VPBasicBlock
*VPBB1
= new VPBasicBlock();
710 VPBB1
->appendRecipe(I1
);
711 VPBB1
->appendRecipe(I2
);
712 VPBB1
->appendRecipe(I3
);
713 VPBB1
->setName("bb1");
715 VPInstruction
*I4
= new VPInstruction(Instruction::Mul
, {I2
, I1
});
716 VPInstruction
*I5
= new VPInstruction(Instruction::Ret
, {I4
});
717 VPBasicBlock
*VPBB2
= new VPBasicBlock();
718 VPBB2
->appendRecipe(I4
);
719 VPBB2
->appendRecipe(I5
);
720 VPBB2
->setName("bb2");
722 VPBlockUtils::connectBlocks(VPBB1
, VPBB2
);
724 // Check printing an instruction without associated VPlan.
727 raw_string_ostream
OS(I3Dump
);
728 VPSlotTracker SlotTracker
;
729 I3
->print(OS
, "", SlotTracker
);
730 EXPECT_EQ("EMIT br <badref>, <badref>", I3Dump
);
734 auto *ScalarHeader
= BasicBlock::Create(C
, "scalar.header");
735 auto * ScalarHeaderVPBB
= new VPIRBasicBlock(ScalarHeader
);
736 VPBlockUtils::connectBlocks(VPBB2
, ScalarHeaderVPBB
);
737 VPlan
Plan(VPBB0
, TC
, VPBB1
, ScalarHeaderVPBB
);
738 std::string FullDump
;
739 raw_string_ostream
OS(FullDump
);
742 const char *ExpectedStr
= R
"(digraph VPlan {
743 graph [labelloc=t, fontsize=30; label="Vectorization Plan
\n for UF\
>=1\nvp\
<%1\
> = original trip
-count
\n"]
744 node [shape=rect, fontname=Courier, fontsize=30]
745 edge [fontname=Courier, fontsize=30]
749 " EMIT vp\
<%1\
> = add\l
" +
754 " EMIT vp\
<%2\
> = add\l
" +
755 " EMIT vp\
<%3\
> = sub vp\
<%2\
>\l
" +
756 " EMIT br vp\
<%2\
>, vp\
<%3\
>\l
" +
757 "Successor(s
): bb2\l
"
762 " EMIT vp\
<%5\
> = mul vp\
<%3\
>, vp\
<%2\
>\l
" +
763 " EMIT ret vp\
<%5\
>\l
" +
764 "Successor(s
): ir
-bb\
<scalar
.header\
>\l
"
768 "ir
-bb\
<scalar
.header\
>:\l
" +
773 EXPECT_EQ(ExpectedStr
, FullDump
);
775 const char *ExpectedBlock1Str
= R
"(bb1:
777 EMIT vp<%3> = sub vp<%2>
778 EMIT br vp<%2>, vp<%3>
781 std::string Block1Dump
;
782 raw_string_ostream
OS1(Block1Dump
);
784 EXPECT_EQ(ExpectedBlock1Str
, Block1Dump
);
786 // Ensure that numbering is good when dumping the second block in isolation.
787 const char *ExpectedBlock2Str
= R
"(bb2:
788 EMIT vp<%5> = mul vp<%3>, vp<%2>
790 Successor(s): ir-bb<scalar.header>
792 std::string Block2Dump
;
793 raw_string_ostream
OS2(Block2Dump
);
795 EXPECT_EQ(ExpectedBlock2Str
, Block2Dump
);
799 raw_string_ostream
OS(I3Dump
);
800 VPSlotTracker
SlotTracker(&Plan
);
801 I3
->print(OS
, "", SlotTracker
);
802 EXPECT_EQ("EMIT br vp<%2>, vp<%3>", I3Dump
);
807 raw_string_ostream
OS(I4Dump
);
809 EXPECT_EQ("EMIT vp<%5> = mul vp<%3>, vp<%2>", I4Dump
);
814 TEST(VPBasicBlockTest
, printPlanWithVFsAndUFs
) {
816 VPInstruction
*TC
= new VPInstruction(Instruction::Sub
, {});
817 VPBasicBlock
*VPBB0
= new VPBasicBlock("preheader");
818 VPBB0
->appendRecipe(TC
);
820 VPInstruction
*I1
= new VPInstruction(Instruction::Add
, {});
821 VPBasicBlock
*VPBB1
= new VPBasicBlock();
822 VPBB1
->appendRecipe(I1
);
823 VPBB1
->setName("bb1");
826 auto *ScalarHeader
= BasicBlock::Create(C
, "");
827 VPIRBasicBlock
*ScalarHeaderVPBB
= new VPIRBasicBlock(ScalarHeader
);
828 VPBlockUtils::connectBlocks(VPBB1
, ScalarHeaderVPBB
);
829 VPlan
Plan(VPBB0
, TC
, VPBB1
, ScalarHeaderVPBB
);
830 Plan
.setName("TestPlan");
831 Plan
.addVF(ElementCount::getFixed(4));
834 std::string FullDump
;
835 raw_string_ostream
OS(FullDump
);
838 const char *ExpectedStr
= R
"(VPlan 'TestPlan for VF={4},UF>=1' {
839 vp<%1> = original trip-count
847 Successor(s): ir-bb<>
853 EXPECT_EQ(ExpectedStr
, FullDump
);
857 Plan
.addVF(ElementCount::getScalable(8));
858 std::string FullDump
;
859 raw_string_ostream
OS(FullDump
);
862 const char *ExpectedStr
= R
"(VPlan 'TestPlan for VF={4,vscale x 8},UF>=1' {
863 vp<%1> = original trip-count
871 Successor(s): ir-bb<>
877 EXPECT_EQ(ExpectedStr
, FullDump
);
882 std::string FullDump
;
883 raw_string_ostream
OS(FullDump
);
886 const char *ExpectedStr
= R
"(VPlan 'TestPlan for VF={4,vscale x 8},UF={4}' {
887 vp<%1> = original trip-count
895 Successor(s): ir-bb<>
901 EXPECT_EQ(ExpectedStr
, FullDump
);
907 TEST(VPRecipeTest
, CastVPInstructionToVPUser
) {
910 VPInstruction
Recipe(Instruction::Add
, {&Op1
, &Op2
});
911 EXPECT_TRUE(isa
<VPUser
>(&Recipe
));
912 VPRecipeBase
*BaseR
= &Recipe
;
913 EXPECT_TRUE(isa
<VPUser
>(BaseR
));
914 EXPECT_EQ(&Recipe
, BaseR
);
917 TEST(VPRecipeTest
, CastVPWidenRecipeToVPUser
) {
920 IntegerType
*Int32
= IntegerType::get(C
, 32);
921 auto *AI
= BinaryOperator::CreateAdd(PoisonValue::get(Int32
),
922 PoisonValue::get(Int32
));
925 SmallVector
<VPValue
*, 2> Args
;
926 Args
.push_back(&Op1
);
927 Args
.push_back(&Op1
);
928 VPWidenRecipe
WidenR(*AI
, make_range(Args
.begin(), Args
.end()));
929 EXPECT_TRUE(isa
<VPUser
>(&WidenR
));
930 VPRecipeBase
*WidenRBase
= &WidenR
;
931 EXPECT_TRUE(isa
<VPUser
>(WidenRBase
));
932 EXPECT_EQ(&WidenR
, WidenRBase
);
936 TEST(VPRecipeTest
, CastVPWidenCallRecipeToVPUserAndVPDef
) {
939 IntegerType
*Int32
= IntegerType::get(C
, 32);
940 FunctionType
*FTy
= FunctionType::get(Int32
, false);
941 Function
*Fn
= Function::Create(FTy
, GlobalValue::ExternalLinkage
, 0);
942 auto *Call
= CallInst::Create(FTy
, Fn
);
945 VPValue
CalledFn(Call
->getCalledFunction());
946 SmallVector
<VPValue
*, 2> Args
;
947 Args
.push_back(&Op1
);
948 Args
.push_back(&Op2
);
949 Args
.push_back(&CalledFn
);
950 VPWidenCallRecipe
Recipe(Call
, Fn
, Args
);
951 EXPECT_TRUE(isa
<VPUser
>(&Recipe
));
952 VPRecipeBase
*BaseR
= &Recipe
;
953 EXPECT_TRUE(isa
<VPUser
>(BaseR
));
954 EXPECT_EQ(&Recipe
, BaseR
);
956 VPValue
*VPV
= &Recipe
;
957 EXPECT_TRUE(VPV
->getDefiningRecipe());
958 EXPECT_EQ(&Recipe
, VPV
->getDefiningRecipe());
964 TEST(VPRecipeTest
, CastVPWidenSelectRecipeToVPUserAndVPDef
) {
967 IntegerType
*Int1
= IntegerType::get(C
, 1);
968 IntegerType
*Int32
= IntegerType::get(C
, 32);
969 auto *SelectI
= SelectInst::Create(
970 PoisonValue::get(Int1
), PoisonValue::get(Int32
), PoisonValue::get(Int32
));
974 SmallVector
<VPValue
*, 4> Args
;
975 Args
.push_back(&Op1
);
976 Args
.push_back(&Op2
);
977 Args
.push_back(&Op3
);
978 VPWidenSelectRecipe
WidenSelectR(*SelectI
,
979 make_range(Args
.begin(), Args
.end()));
980 EXPECT_TRUE(isa
<VPUser
>(&WidenSelectR
));
981 VPRecipeBase
*BaseR
= &WidenSelectR
;
982 EXPECT_TRUE(isa
<VPUser
>(BaseR
));
983 EXPECT_EQ(&WidenSelectR
, BaseR
);
985 VPValue
*VPV
= &WidenSelectR
;
986 EXPECT_TRUE(isa
<VPRecipeBase
>(VPV
->getDefiningRecipe()));
987 EXPECT_EQ(&WidenSelectR
, VPV
->getDefiningRecipe());
992 TEST(VPRecipeTest
, CastVPWidenGEPRecipeToVPUserAndVPDef
) {
995 IntegerType
*Int32
= IntegerType::get(C
, 32);
996 PointerType
*Int32Ptr
= PointerType::get(Int32
, 0);
997 auto *GEP
= GetElementPtrInst::Create(Int32
, PoisonValue::get(Int32Ptr
),
998 PoisonValue::get(Int32
));
1001 SmallVector
<VPValue
*, 4> Args
;
1002 Args
.push_back(&Op1
);
1003 Args
.push_back(&Op2
);
1004 VPWidenGEPRecipe
Recipe(GEP
, make_range(Args
.begin(), Args
.end()));
1005 EXPECT_TRUE(isa
<VPUser
>(&Recipe
));
1006 VPRecipeBase
*BaseR
= &Recipe
;
1007 EXPECT_TRUE(isa
<VPUser
>(BaseR
));
1008 EXPECT_EQ(&Recipe
, BaseR
);
1010 VPValue
*VPV
= &Recipe
;
1011 EXPECT_TRUE(isa
<VPRecipeBase
>(VPV
->getDefiningRecipe()));
1012 EXPECT_EQ(&Recipe
, VPV
->getDefiningRecipe());
1017 TEST(VPRecipeTest
, CastVPBlendRecipeToVPUser
) {
1020 IntegerType
*Int32
= IntegerType::get(C
, 32);
1021 auto *Phi
= PHINode::Create(Int32
, 1);
1025 SmallVector
<VPValue
*, 4> Args
;
1026 Args
.push_back(&I1
);
1027 Args
.push_back(&I2
);
1028 Args
.push_back(&M2
);
1029 VPBlendRecipe
Recipe(Phi
, Args
);
1030 EXPECT_TRUE(isa
<VPUser
>(&Recipe
));
1031 VPRecipeBase
*BaseR
= &Recipe
;
1032 EXPECT_TRUE(isa
<VPUser
>(BaseR
));
1036 TEST(VPRecipeTest
, CastVPInterleaveRecipeToVPUser
) {
1041 InterleaveGroup
<Instruction
> IG(4, false, Align(4));
1042 VPInterleaveRecipe
Recipe(&IG
, &Addr
, {}, &Mask
, false);
1043 EXPECT_TRUE(isa
<VPUser
>(&Recipe
));
1044 VPRecipeBase
*BaseR
= &Recipe
;
1045 EXPECT_TRUE(isa
<VPUser
>(BaseR
));
1046 EXPECT_EQ(&Recipe
, BaseR
);
1049 TEST(VPRecipeTest
, CastVPReplicateRecipeToVPUser
) {
1054 SmallVector
<VPValue
*, 4> Args
;
1055 Args
.push_back(&Op1
);
1056 Args
.push_back(&Op2
);
1058 IntegerType
*Int32
= IntegerType::get(C
, 32);
1059 FunctionType
*FTy
= FunctionType::get(Int32
, false);
1060 auto *Call
= CallInst::Create(FTy
, PoisonValue::get(FTy
));
1061 VPReplicateRecipe
Recipe(Call
, make_range(Args
.begin(), Args
.end()), true);
1062 EXPECT_TRUE(isa
<VPUser
>(&Recipe
));
1063 VPRecipeBase
*BaseR
= &Recipe
;
1064 EXPECT_TRUE(isa
<VPUser
>(BaseR
));
1068 TEST(VPRecipeTest
, CastVPBranchOnMaskRecipeToVPUser
) {
1072 VPBranchOnMaskRecipe
Recipe(&Mask
);
1073 EXPECT_TRUE(isa
<VPUser
>(&Recipe
));
1074 VPRecipeBase
*BaseR
= &Recipe
;
1075 EXPECT_TRUE(isa
<VPUser
>(BaseR
));
1076 EXPECT_EQ(&Recipe
, BaseR
);
1079 TEST(VPRecipeTest
, CastVPWidenMemoryRecipeToVPUserAndVPDef
) {
1082 IntegerType
*Int32
= IntegerType::get(C
, 32);
1083 PointerType
*Int32Ptr
= PointerType::get(Int32
, 0);
1085 new LoadInst(Int32
, PoisonValue::get(Int32Ptr
), "", false, Align(1));
1088 VPWidenLoadRecipe
Recipe(*Load
, &Addr
, &Mask
, true, false, {});
1089 EXPECT_TRUE(isa
<VPUser
>(&Recipe
));
1090 VPRecipeBase
*BaseR
= &Recipe
;
1091 EXPECT_TRUE(isa
<VPUser
>(BaseR
));
1092 EXPECT_EQ(&Recipe
, BaseR
);
1094 VPValue
*VPV
= Recipe
.getVPSingleValue();
1095 EXPECT_TRUE(isa
<VPRecipeBase
>(VPV
->getDefiningRecipe()));
1096 EXPECT_EQ(&Recipe
, VPV
->getDefiningRecipe());
1101 TEST(VPRecipeTest
, MayHaveSideEffectsAndMayReadWriteMemory
) {
1103 IntegerType
*Int1
= IntegerType::get(C
, 1);
1104 IntegerType
*Int32
= IntegerType::get(C
, 32);
1105 PointerType
*Int32Ptr
= PointerType::get(Int32
, 0);
1108 auto *AI
= BinaryOperator::CreateAdd(PoisonValue::get(Int32
),
1109 PoisonValue::get(Int32
));
1112 SmallVector
<VPValue
*, 2> Args
;
1113 Args
.push_back(&Op1
);
1114 Args
.push_back(&Op1
);
1115 VPWidenRecipe
Recipe(*AI
, make_range(Args
.begin(), Args
.end()));
1116 EXPECT_FALSE(Recipe
.mayHaveSideEffects());
1117 EXPECT_FALSE(Recipe
.mayReadFromMemory());
1118 EXPECT_FALSE(Recipe
.mayWriteToMemory());
1119 EXPECT_FALSE(Recipe
.mayReadOrWriteMemory());
1125 SelectInst::Create(PoisonValue::get(Int1
), PoisonValue::get(Int32
),
1126 PoisonValue::get(Int32
));
1130 SmallVector
<VPValue
*, 4> Args
;
1131 Args
.push_back(&Op1
);
1132 Args
.push_back(&Op2
);
1133 Args
.push_back(&Op3
);
1134 VPWidenSelectRecipe
Recipe(*SelectI
, make_range(Args
.begin(), Args
.end()));
1135 EXPECT_FALSE(Recipe
.mayHaveSideEffects());
1136 EXPECT_FALSE(Recipe
.mayReadFromMemory());
1137 EXPECT_FALSE(Recipe
.mayWriteToMemory());
1138 EXPECT_FALSE(Recipe
.mayReadOrWriteMemory());
1143 auto *GEP
= GetElementPtrInst::Create(Int32
, PoisonValue::get(Int32Ptr
),
1144 PoisonValue::get(Int32
));
1147 SmallVector
<VPValue
*, 4> Args
;
1148 Args
.push_back(&Op1
);
1149 Args
.push_back(&Op2
);
1150 VPWidenGEPRecipe
Recipe(GEP
, make_range(Args
.begin(), Args
.end()));
1151 EXPECT_FALSE(Recipe
.mayHaveSideEffects());
1152 EXPECT_FALSE(Recipe
.mayReadFromMemory());
1153 EXPECT_FALSE(Recipe
.mayWriteToMemory());
1154 EXPECT_FALSE(Recipe
.mayReadOrWriteMemory());
1160 VPBranchOnMaskRecipe
Recipe(&Mask
);
1161 EXPECT_TRUE(Recipe
.mayHaveSideEffects());
1162 EXPECT_FALSE(Recipe
.mayReadFromMemory());
1163 EXPECT_FALSE(Recipe
.mayWriteToMemory());
1164 EXPECT_FALSE(Recipe
.mayReadOrWriteMemory());
1171 VPReductionRecipe
Recipe(RecurrenceDescriptor(), nullptr, &ChainOp
, &CondOp
,
1173 EXPECT_FALSE(Recipe
.mayHaveSideEffects());
1174 EXPECT_FALSE(Recipe
.mayReadFromMemory());
1175 EXPECT_FALSE(Recipe
.mayWriteToMemory());
1176 EXPECT_FALSE(Recipe
.mayReadOrWriteMemory());
1183 VPReductionRecipe
Recipe(RecurrenceDescriptor(), nullptr, &ChainOp
, &CondOp
,
1186 VPReductionEVLRecipe
EVLRecipe(Recipe
, EVL
, &CondOp
);
1187 EXPECT_FALSE(EVLRecipe
.mayHaveSideEffects());
1188 EXPECT_FALSE(EVLRecipe
.mayReadFromMemory());
1189 EXPECT_FALSE(EVLRecipe
.mayWriteToMemory());
1190 EXPECT_FALSE(EVLRecipe
.mayReadOrWriteMemory());
1195 new LoadInst(Int32
, PoisonValue::get(Int32Ptr
), "", false, Align(1));
1198 VPWidenLoadRecipe
Recipe(*Load
, &Addr
, &Mask
, true, false, {});
1199 EXPECT_FALSE(Recipe
.mayHaveSideEffects());
1200 EXPECT_TRUE(Recipe
.mayReadFromMemory());
1201 EXPECT_FALSE(Recipe
.mayWriteToMemory());
1202 EXPECT_TRUE(Recipe
.mayReadOrWriteMemory());
1207 auto *Store
= new StoreInst(PoisonValue::get(Int32
),
1208 PoisonValue::get(Int32Ptr
), false, Align(1));
1212 VPWidenStoreRecipe
Recipe(*Store
, &Addr
, &StoredV
, &Mask
, false, false, {});
1213 EXPECT_TRUE(Recipe
.mayHaveSideEffects());
1214 EXPECT_FALSE(Recipe
.mayReadFromMemory());
1215 EXPECT_TRUE(Recipe
.mayWriteToMemory());
1216 EXPECT_TRUE(Recipe
.mayReadOrWriteMemory());
1221 FunctionType
*FTy
= FunctionType::get(Int32
, false);
1222 Function
*Fn
= Function::Create(FTy
, GlobalValue::ExternalLinkage
, 0);
1223 auto *Call
= CallInst::Create(FTy
, Fn
);
1226 VPValue
CalledFn(Call
->getCalledFunction());
1227 SmallVector
<VPValue
*, 3> Args
;
1228 Args
.push_back(&Op1
);
1229 Args
.push_back(&Op2
);
1230 Args
.push_back(&CalledFn
);
1231 VPWidenCallRecipe
Recipe(Call
, Fn
, Args
);
1232 EXPECT_TRUE(Recipe
.mayHaveSideEffects());
1233 EXPECT_TRUE(Recipe
.mayReadFromMemory());
1234 EXPECT_TRUE(Recipe
.mayWriteToMemory());
1235 EXPECT_TRUE(Recipe
.mayReadOrWriteMemory());
1241 // Test for a call to a function without side-effects.
1245 Intrinsic::getOrInsertDeclaration(&M
, Intrinsic::thread_pointer
);
1247 auto *Call
= CallInst::Create(TheFn
->getFunctionType(), TheFn
);
1250 VPValue
CalledFn(TheFn
);
1251 SmallVector
<VPValue
*, 3> Args
;
1252 Args
.push_back(&Op1
);
1253 Args
.push_back(&Op2
);
1254 Args
.push_back(&CalledFn
);
1255 VPWidenCallRecipe
Recipe(Call
, TheFn
, Args
);
1256 EXPECT_FALSE(Recipe
.mayHaveSideEffects());
1257 EXPECT_FALSE(Recipe
.mayReadFromMemory());
1258 EXPECT_FALSE(Recipe
.mayWriteToMemory());
1259 EXPECT_FALSE(Recipe
.mayReadOrWriteMemory());
1266 InductionDescriptor IndDesc
;
1267 VPScalarIVStepsRecipe
Recipe(IndDesc
, &Op1
, &Op2
);
1268 EXPECT_FALSE(Recipe
.mayHaveSideEffects());
1269 EXPECT_FALSE(Recipe
.mayReadFromMemory());
1270 EXPECT_FALSE(Recipe
.mayWriteToMemory());
1271 EXPECT_FALSE(Recipe
.mayReadOrWriteMemory());
1274 // The initial implementation is conservative with respect to VPInstructions.
1278 VPInstruction
VPInst(Instruction::Add
, {&Op1
, &Op2
});
1279 VPRecipeBase
&Recipe
= VPInst
;
1280 EXPECT_FALSE(Recipe
.mayHaveSideEffects());
1281 EXPECT_TRUE(Recipe
.mayReadFromMemory());
1282 EXPECT_FALSE(Recipe
.mayWriteToMemory());
1283 EXPECT_TRUE(Recipe
.mayReadOrWriteMemory());
1287 VPPredInstPHIRecipe
Recipe(&Op1
);
1288 EXPECT_FALSE(Recipe
.mayHaveSideEffects());
1289 EXPECT_FALSE(Recipe
.mayReadFromMemory());
1290 EXPECT_FALSE(Recipe
.mayWriteToMemory());
1291 EXPECT_FALSE(Recipe
.mayReadOrWriteMemory());
1295 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1296 TEST(VPRecipeTest
, dumpRecipeInPlan
) {
1297 VPBasicBlock
*VPBB0
= new VPBasicBlock("preheader");
1298 VPBasicBlock
*VPBB1
= new VPBasicBlock();
1300 auto *ScalarHeader
= BasicBlock::Create(C
, "");
1301 VPIRBasicBlock
*ScalarHeaderVPBB
= new VPIRBasicBlock(ScalarHeader
);
1302 VPBlockUtils::connectBlocks(VPBB1
, ScalarHeaderVPBB
);
1303 VPlan
Plan(VPBB0
, VPBB1
, ScalarHeaderVPBB
);
1305 IntegerType
*Int32
= IntegerType::get(C
, 32);
1306 auto *AI
= BinaryOperator::CreateAdd(PoisonValue::get(Int32
),
1307 PoisonValue::get(Int32
));
1309 SmallVector
<VPValue
*, 2> Args
;
1310 VPValue
*ExtVPV1
= Plan
.getOrAddLiveIn(ConstantInt::get(Int32
, 1));
1311 VPValue
*ExtVPV2
= Plan
.getOrAddLiveIn(ConstantInt::get(Int32
, 2));
1312 Args
.push_back(ExtVPV1
);
1313 Args
.push_back(ExtVPV2
);
1314 VPWidenRecipe
*WidenR
=
1315 new VPWidenRecipe(*AI
, make_range(Args
.begin(), Args
.end()));
1316 VPBB1
->appendRecipe(WidenR
);
1319 // Use EXPECT_EXIT to capture stderr and compare against expected output.
1321 // Test VPValue::dump().
1322 VPValue
*VPV
= WidenR
;
1328 testing::ExitedWithCode(0), "WIDEN ir<%a> = add ir<1>, ir<2>");
1330 VPDef
*Def
= WidenR
;
1336 testing::ExitedWithCode(0), "WIDEN ir<%a> = add ir<1>, ir<2>");
1343 testing::ExitedWithCode(0), "WIDEN ir<%a> = add ir<1>, ir<2>");
1345 // Test VPRecipeBase::dump().
1346 VPRecipeBase
*R
= WidenR
;
1352 testing::ExitedWithCode(0), "WIDEN ir<%a> = add ir<1>, ir<2>");
1354 // Test VPDef::dump().
1361 testing::ExitedWithCode(0), "WIDEN ir<%a> = add ir<1>, ir<2>");
1365 delete ScalarHeader
;
1368 TEST(VPRecipeTest
, dumpRecipeUnnamedVPValuesInPlan
) {
1369 VPBasicBlock
*VPBB0
= new VPBasicBlock("preheader");
1370 VPBasicBlock
*VPBB1
= new VPBasicBlock();
1372 auto *ScalarHeader
= BasicBlock::Create(C
, "");
1373 VPIRBasicBlock
*ScalarHeaderVPBB
= new VPIRBasicBlock(ScalarHeader
);
1374 VPBlockUtils::connectBlocks(VPBB1
, ScalarHeaderVPBB
);
1375 VPlan
Plan(VPBB0
, VPBB1
, ScalarHeaderVPBB
);
1377 IntegerType
*Int32
= IntegerType::get(C
, 32);
1378 auto *AI
= BinaryOperator::CreateAdd(PoisonValue::get(Int32
),
1379 PoisonValue::get(Int32
));
1381 SmallVector
<VPValue
*, 2> Args
;
1382 VPValue
*ExtVPV1
= Plan
.getOrAddLiveIn(ConstantInt::get(Int32
, 1));
1383 VPValue
*ExtVPV2
= Plan
.getOrAddLiveIn(AI
);
1384 Args
.push_back(ExtVPV1
);
1385 Args
.push_back(ExtVPV2
);
1386 VPInstruction
*I1
= new VPInstruction(Instruction::Add
, {ExtVPV1
, ExtVPV2
});
1387 VPInstruction
*I2
= new VPInstruction(Instruction::Mul
, {I1
, I1
});
1388 VPBB1
->appendRecipe(I1
);
1389 VPBB1
->appendRecipe(I2
);
1391 // Check printing I1.
1393 // Use EXPECT_EXIT to capture stderr and compare against expected output.
1395 // Test VPValue::dump().
1402 testing::ExitedWithCode(0), "EMIT vp<%1> = add ir<1>, ir<%a>");
1404 // Test VPRecipeBase::dump().
1405 VPRecipeBase
*R
= I1
;
1411 testing::ExitedWithCode(0), "EMIT vp<%1> = add ir<1>, ir<%a>");
1413 // Test VPDef::dump().
1420 testing::ExitedWithCode(0), "EMIT vp<%1> = add ir<1>, ir<%a>");
1422 // Check printing I2.
1424 // Use EXPECT_EXIT to capture stderr and compare against expected output.
1426 // Test VPValue::dump().
1433 testing::ExitedWithCode(0), "EMIT vp<%2> = mul vp<%1>, vp<%1>");
1435 // Test VPRecipeBase::dump().
1436 VPRecipeBase
*R
= I2
;
1442 testing::ExitedWithCode(0), "EMIT vp<%2> = mul vp<%1>, vp<%1>");
1444 // Test VPDef::dump().
1451 testing::ExitedWithCode(0), "EMIT vp<%2> = mul vp<%1>, vp<%1>");
1454 delete ScalarHeader
;
1457 TEST(VPRecipeTest
, dumpRecipeUnnamedVPValuesNotInPlanOrBlock
) {
1459 IntegerType
*Int32
= IntegerType::get(C
, 32);
1460 auto *AI
= BinaryOperator::CreateAdd(PoisonValue::get(Int32
),
1461 PoisonValue::get(Int32
));
1463 VPValue
*ExtVPV1
= new VPValue(ConstantInt::get(Int32
, 1));
1464 VPValue
*ExtVPV2
= new VPValue(AI
);
1466 VPInstruction
*I1
= new VPInstruction(Instruction::Add
, {ExtVPV1
, ExtVPV2
});
1467 VPInstruction
*I2
= new VPInstruction(Instruction::Mul
, {I1
, I1
});
1469 // Check printing I1.
1471 // Use EXPECT_EXIT to capture stderr and compare against expected output.
1473 // Test VPValue::dump().
1480 testing::ExitedWithCode(0), "EMIT <badref> = add ir<1>, ir<%a>");
1482 // Test VPRecipeBase::dump().
1483 VPRecipeBase
*R
= I1
;
1489 testing::ExitedWithCode(0), "EMIT <badref> = add ir<1>, ir<%a>");
1491 // Test VPDef::dump().
1498 testing::ExitedWithCode(0), "EMIT <badref> = add ir<1>, ir<%a>");
1500 // Check printing I2.
1502 // Use EXPECT_EXIT to capture stderr and compare against expected output.
1504 // Test VPValue::dump().
1511 testing::ExitedWithCode(0), "EMIT <badref> = mul <badref>, <badref>");
1513 // Test VPRecipeBase::dump().
1514 VPRecipeBase
*R
= I2
;
1520 testing::ExitedWithCode(0), "EMIT <badref> = mul <badref>, <badref>");
1522 // Test VPDef::dump().
1529 testing::ExitedWithCode(0), "EMIT <badref> = mul <badref>, <badref>");
1541 TEST(VPRecipeTest
, CastVPReductionRecipeToVPUser
) {
1547 VPReductionRecipe
Recipe(RecurrenceDescriptor(), nullptr, &ChainOp
, &CondOp
,
1549 EXPECT_TRUE(isa
<VPUser
>(&Recipe
));
1550 VPRecipeBase
*BaseR
= &Recipe
;
1551 EXPECT_TRUE(isa
<VPUser
>(BaseR
));
1554 TEST(VPRecipeTest
, CastVPReductionEVLRecipeToVPUser
) {
1560 VPReductionRecipe
Recipe(RecurrenceDescriptor(), nullptr, &ChainOp
, &CondOp
,
1563 VPReductionEVLRecipe
EVLRecipe(Recipe
, EVL
, &CondOp
);
1564 EXPECT_TRUE(isa
<VPUser
>(&EVLRecipe
));
1565 VPRecipeBase
*BaseR
= &EVLRecipe
;
1566 EXPECT_TRUE(isa
<VPUser
>(BaseR
));
1569 struct VPDoubleValueDef
: public VPRecipeBase
{
1570 VPDoubleValueDef(ArrayRef
<VPValue
*> Operands
) : VPRecipeBase(99, Operands
) {
1571 new VPValue(nullptr, this);
1572 new VPValue(nullptr, this);
1575 VPRecipeBase
*clone() override
{ return nullptr; }
1577 void execute(struct VPTransformState
&State
) override
{}
1578 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1579 void print(raw_ostream
&O
, const Twine
&Indent
,
1580 VPSlotTracker
&SlotTracker
) const override
{}
1584 TEST(VPDoubleValueDefTest
, traverseUseLists
) {
1585 // Check that the def-use chains of a multi-def can be traversed in both
1588 // Create a new VPDef which defines 2 values and has 2 operands.
1589 VPInstruction
Op0(20, {});
1590 VPInstruction
Op1(30, {});
1591 VPDoubleValueDef
DoubleValueDef({&Op0
, &Op1
});
1593 // Create a new users of the defined values.
1595 1, {DoubleValueDef
.getVPValue(0), DoubleValueDef
.getVPValue(1)});
1596 VPInstruction
I2(2, {DoubleValueDef
.getVPValue(0)});
1597 VPInstruction
I3(3, {DoubleValueDef
.getVPValue(1)});
1599 // Check operands of the VPDef (traversing upwards).
1600 SmallVector
<VPValue
*, 4> DoubleOperands(DoubleValueDef
.op_begin(),
1601 DoubleValueDef
.op_end());
1602 EXPECT_EQ(2u, DoubleOperands
.size());
1603 EXPECT_EQ(&Op0
, DoubleOperands
[0]);
1604 EXPECT_EQ(&Op1
, DoubleOperands
[1]);
1606 // Check users of the defined values (traversing downwards).
1607 SmallVector
<VPUser
*, 4> DoubleValueDefV0Users(
1608 DoubleValueDef
.getVPValue(0)->user_begin(),
1609 DoubleValueDef
.getVPValue(0)->user_end());
1610 EXPECT_EQ(2u, DoubleValueDefV0Users
.size());
1611 EXPECT_EQ(&I1
, DoubleValueDefV0Users
[0]);
1612 EXPECT_EQ(&I2
, DoubleValueDefV0Users
[1]);
1614 SmallVector
<VPUser
*, 4> DoubleValueDefV1Users(
1615 DoubleValueDef
.getVPValue(1)->user_begin(),
1616 DoubleValueDef
.getVPValue(1)->user_end());
1617 EXPECT_EQ(2u, DoubleValueDefV1Users
.size());
1618 EXPECT_EQ(&I1
, DoubleValueDefV1Users
[0]);
1619 EXPECT_EQ(&I3
, DoubleValueDefV1Users
[1]);
1621 // Now check that we can get the right VPDef for each defined value.
1622 EXPECT_EQ(&DoubleValueDef
, I1
.getOperand(0)->getDefiningRecipe());
1623 EXPECT_EQ(&DoubleValueDef
, I1
.getOperand(1)->getDefiningRecipe());
1624 EXPECT_EQ(&DoubleValueDef
, I2
.getOperand(0)->getDefiningRecipe());
1625 EXPECT_EQ(&DoubleValueDef
, I3
.getOperand(0)->getDefiningRecipe());
1628 TEST(VPRecipeTest
, CastToVPSingleDefRecipe
) {
1630 VPEVLBasedIVPHIRecipe
R(&Start
, {});
1631 VPRecipeBase
*B
= &R
;
1632 EXPECT_TRUE(isa
<VPSingleDefRecipe
>(B
));
1633 // TODO: check other VPSingleDefRecipes.