17591e4e9SFlorian Hahn //===- llvm/unittests/Transforms/Vectorize/VPlanTest.cpp - VPlan tests ----===//
27591e4e9SFlorian Hahn //
37591e4e9SFlorian Hahn //
42946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
52946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
62946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
77591e4e9SFlorian Hahn //
87591e4e9SFlorian Hahn //===----------------------------------------------------------------------===//
97591e4e9SFlorian Hahn
107591e4e9SFlorian Hahn #include "../lib/Transforms/Vectorize/VPlan.h"
1105776122SFlorian Hahn #include "llvm/ADT/DepthFirstIterator.h"
12d1570194SFlorian Hahn #include "llvm/ADT/PostOrderIterator.h"
13cd608dc8SFlorian Hahn #include "llvm/Analysis/VectorUtils.h"
147591e4e9SFlorian Hahn #include "llvm/IR/Instruction.h"
157591e4e9SFlorian Hahn #include "llvm/IR/Instructions.h"
167591e4e9SFlorian Hahn #include "gtest/gtest.h"
1740e7bfc4SFlorian Hahn #include <string>
187591e4e9SFlorian Hahn
197591e4e9SFlorian Hahn namespace llvm {
207591e4e9SFlorian Hahn namespace {
217591e4e9SFlorian Hahn
227591e4e9SFlorian Hahn #define CHECK_ITERATOR(Range1, ...) \
237591e4e9SFlorian Hahn do { \
247591e4e9SFlorian Hahn std::vector<VPInstruction *> Tmp = {__VA_ARGS__}; \
257591e4e9SFlorian Hahn EXPECT_EQ((size_t)std::distance(Range1.begin(), Range1.end()), \
267591e4e9SFlorian Hahn Tmp.size()); \
277591e4e9SFlorian Hahn for (auto Pair : zip(Range1, make_range(Tmp.begin(), Tmp.end()))) \
287591e4e9SFlorian Hahn EXPECT_EQ(&std::get<0>(Pair), std::get<1>(Pair)); \
297591e4e9SFlorian Hahn } while (0)
307591e4e9SFlorian Hahn
TEST(VPInstructionTest,insertBefore)317591e4e9SFlorian Hahn TEST(VPInstructionTest, insertBefore) {
327591e4e9SFlorian Hahn VPInstruction *I1 = new VPInstruction(0, {});
337591e4e9SFlorian Hahn VPInstruction *I2 = new VPInstruction(1, {});
347591e4e9SFlorian Hahn VPInstruction *I3 = new VPInstruction(2, {});
357591e4e9SFlorian Hahn
367591e4e9SFlorian Hahn VPBasicBlock VPBB1;
377591e4e9SFlorian Hahn VPBB1.appendRecipe(I1);
387591e4e9SFlorian Hahn
397591e4e9SFlorian Hahn I2->insertBefore(I1);
407591e4e9SFlorian Hahn CHECK_ITERATOR(VPBB1, I2, I1);
417591e4e9SFlorian Hahn
427591e4e9SFlorian Hahn I3->insertBefore(I2);
437591e4e9SFlorian Hahn CHECK_ITERATOR(VPBB1, I3, I2, I1);
447591e4e9SFlorian Hahn }
457591e4e9SFlorian Hahn
TEST(VPInstructionTest,eraseFromParent)4663cbcf98SFlorian Hahn TEST(VPInstructionTest, eraseFromParent) {
4763cbcf98SFlorian Hahn VPInstruction *I1 = new VPInstruction(0, {});
4863cbcf98SFlorian Hahn VPInstruction *I2 = new VPInstruction(1, {});
4963cbcf98SFlorian Hahn VPInstruction *I3 = new VPInstruction(2, {});
5063cbcf98SFlorian Hahn
5163cbcf98SFlorian Hahn VPBasicBlock VPBB1;
5263cbcf98SFlorian Hahn VPBB1.appendRecipe(I1);
5363cbcf98SFlorian Hahn VPBB1.appendRecipe(I2);
5463cbcf98SFlorian Hahn VPBB1.appendRecipe(I3);
5563cbcf98SFlorian Hahn
5663cbcf98SFlorian Hahn I2->eraseFromParent();
5763cbcf98SFlorian Hahn CHECK_ITERATOR(VPBB1, I1, I3);
5863cbcf98SFlorian Hahn
5963cbcf98SFlorian Hahn I1->eraseFromParent();
6063cbcf98SFlorian Hahn CHECK_ITERATOR(VPBB1, I3);
6163cbcf98SFlorian Hahn
6263cbcf98SFlorian Hahn I3->eraseFromParent();
6363cbcf98SFlorian Hahn EXPECT_TRUE(VPBB1.empty());
6463cbcf98SFlorian Hahn }
6563cbcf98SFlorian Hahn
TEST(VPInstructionTest,moveAfter)6639d4c9fdSFlorian Hahn TEST(VPInstructionTest, moveAfter) {
6739d4c9fdSFlorian Hahn VPInstruction *I1 = new VPInstruction(0, {});
6839d4c9fdSFlorian Hahn VPInstruction *I2 = new VPInstruction(1, {});
6939d4c9fdSFlorian Hahn VPInstruction *I3 = new VPInstruction(2, {});
7039d4c9fdSFlorian Hahn
7139d4c9fdSFlorian Hahn VPBasicBlock VPBB1;
7239d4c9fdSFlorian Hahn VPBB1.appendRecipe(I1);
7339d4c9fdSFlorian Hahn VPBB1.appendRecipe(I2);
7439d4c9fdSFlorian Hahn VPBB1.appendRecipe(I3);
7539d4c9fdSFlorian Hahn
7639d4c9fdSFlorian Hahn I1->moveAfter(I2);
7739d4c9fdSFlorian Hahn
7839d4c9fdSFlorian Hahn CHECK_ITERATOR(VPBB1, I2, I1, I3);
7939d4c9fdSFlorian Hahn
8039d4c9fdSFlorian Hahn VPInstruction *I4 = new VPInstruction(4, {});
8139d4c9fdSFlorian Hahn VPInstruction *I5 = new VPInstruction(5, {});
8239d4c9fdSFlorian Hahn VPBasicBlock VPBB2;
8339d4c9fdSFlorian Hahn VPBB2.appendRecipe(I4);
8439d4c9fdSFlorian Hahn VPBB2.appendRecipe(I5);
8539d4c9fdSFlorian Hahn
8639d4c9fdSFlorian Hahn I3->moveAfter(I4);
8739d4c9fdSFlorian Hahn
8839d4c9fdSFlorian Hahn CHECK_ITERATOR(VPBB1, I2, I1);
8939d4c9fdSFlorian Hahn CHECK_ITERATOR(VPBB2, I4, I3, I5);
907f152543SGil Rapaport EXPECT_EQ(I3->getParent(), I4->getParent());
9139d4c9fdSFlorian Hahn }
9239d4c9fdSFlorian Hahn
TEST(VPInstructionTest,moveBefore)9372fb5ba0SDavid Green TEST(VPInstructionTest, moveBefore) {
9472fb5ba0SDavid Green VPInstruction *I1 = new VPInstruction(0, {});
9572fb5ba0SDavid Green VPInstruction *I2 = new VPInstruction(1, {});
9672fb5ba0SDavid Green VPInstruction *I3 = new VPInstruction(2, {});
9772fb5ba0SDavid Green
9872fb5ba0SDavid Green VPBasicBlock VPBB1;
9972fb5ba0SDavid Green VPBB1.appendRecipe(I1);
10072fb5ba0SDavid Green VPBB1.appendRecipe(I2);
10172fb5ba0SDavid Green VPBB1.appendRecipe(I3);
10272fb5ba0SDavid Green
10372fb5ba0SDavid Green I1->moveBefore(VPBB1, I3->getIterator());
10472fb5ba0SDavid Green
10572fb5ba0SDavid Green CHECK_ITERATOR(VPBB1, I2, I1, I3);
10672fb5ba0SDavid Green
10772fb5ba0SDavid Green VPInstruction *I4 = new VPInstruction(4, {});
10872fb5ba0SDavid Green VPInstruction *I5 = new VPInstruction(5, {});
10972fb5ba0SDavid Green VPBasicBlock VPBB2;
11072fb5ba0SDavid Green VPBB2.appendRecipe(I4);
11172fb5ba0SDavid Green VPBB2.appendRecipe(I5);
11272fb5ba0SDavid Green
11372fb5ba0SDavid Green I3->moveBefore(VPBB2, I4->getIterator());
11472fb5ba0SDavid Green
11572fb5ba0SDavid Green CHECK_ITERATOR(VPBB1, I2, I1);
11672fb5ba0SDavid Green CHECK_ITERATOR(VPBB2, I3, I4, I5);
11772fb5ba0SDavid Green EXPECT_EQ(I3->getParent(), I4->getParent());
11872fb5ba0SDavid Green
11972fb5ba0SDavid Green VPBasicBlock VPBB3;
12072fb5ba0SDavid Green
12172fb5ba0SDavid Green I4->moveBefore(VPBB3, VPBB3.end());
12272fb5ba0SDavid Green
12372fb5ba0SDavid Green CHECK_ITERATOR(VPBB1, I2, I1);
12472fb5ba0SDavid Green CHECK_ITERATOR(VPBB2, I3, I5);
12572fb5ba0SDavid Green CHECK_ITERATOR(VPBB3, I4);
12672fb5ba0SDavid Green EXPECT_EQ(&VPBB3, I4->getParent());
12772fb5ba0SDavid Green }
12872fb5ba0SDavid Green
TEST(VPInstructionTest,setOperand)12982dcd383SFlorian Hahn TEST(VPInstructionTest, setOperand) {
13082dcd383SFlorian Hahn VPValue *VPV1 = new VPValue();
13182dcd383SFlorian Hahn VPValue *VPV2 = new VPValue();
13282dcd383SFlorian Hahn VPInstruction *I1 = new VPInstruction(0, {VPV1, VPV2});
13382dcd383SFlorian Hahn EXPECT_EQ(1u, VPV1->getNumUsers());
13482dcd383SFlorian Hahn EXPECT_EQ(I1, *VPV1->user_begin());
13582dcd383SFlorian Hahn EXPECT_EQ(1u, VPV2->getNumUsers());
13682dcd383SFlorian Hahn EXPECT_EQ(I1, *VPV2->user_begin());
13782dcd383SFlorian Hahn
13882dcd383SFlorian Hahn // Replace operand 0 (VPV1) with VPV3.
13982dcd383SFlorian Hahn VPValue *VPV3 = new VPValue();
14082dcd383SFlorian Hahn I1->setOperand(0, VPV3);
14182dcd383SFlorian Hahn EXPECT_EQ(0u, VPV1->getNumUsers());
14282dcd383SFlorian Hahn EXPECT_EQ(1u, VPV2->getNumUsers());
14382dcd383SFlorian Hahn EXPECT_EQ(I1, *VPV2->user_begin());
14482dcd383SFlorian Hahn EXPECT_EQ(1u, VPV3->getNumUsers());
14582dcd383SFlorian Hahn EXPECT_EQ(I1, *VPV3->user_begin());
14682dcd383SFlorian Hahn
14782dcd383SFlorian Hahn // Replace operand 1 (VPV2) with VPV3.
14882dcd383SFlorian Hahn I1->setOperand(1, VPV3);
14982dcd383SFlorian Hahn EXPECT_EQ(0u, VPV1->getNumUsers());
15082dcd383SFlorian Hahn EXPECT_EQ(0u, VPV2->getNumUsers());
15182dcd383SFlorian Hahn EXPECT_EQ(2u, VPV3->getNumUsers());
15282dcd383SFlorian Hahn EXPECT_EQ(I1, *VPV3->user_begin());
15382dcd383SFlorian Hahn EXPECT_EQ(I1, *std::next(VPV3->user_begin()));
15482dcd383SFlorian Hahn
15582dcd383SFlorian Hahn // Replace operand 0 (VPV3) with VPV4.
15682dcd383SFlorian Hahn VPValue *VPV4 = new VPValue();
15782dcd383SFlorian Hahn I1->setOperand(0, VPV4);
15882dcd383SFlorian Hahn EXPECT_EQ(1u, VPV3->getNumUsers());
15982dcd383SFlorian Hahn EXPECT_EQ(I1, *VPV3->user_begin());
16082dcd383SFlorian Hahn EXPECT_EQ(I1, *VPV4->user_begin());
16182dcd383SFlorian Hahn
16282dcd383SFlorian Hahn // Replace operand 1 (VPV3) with VPV4.
16382dcd383SFlorian Hahn I1->setOperand(1, VPV4);
16482dcd383SFlorian Hahn EXPECT_EQ(0u, VPV3->getNumUsers());
16582dcd383SFlorian Hahn EXPECT_EQ(I1, *VPV4->user_begin());
16682dcd383SFlorian Hahn EXPECT_EQ(I1, *std::next(VPV4->user_begin()));
16782dcd383SFlorian Hahn
16882dcd383SFlorian Hahn delete I1;
16982dcd383SFlorian Hahn delete VPV1;
17082dcd383SFlorian Hahn delete VPV2;
17182dcd383SFlorian Hahn delete VPV3;
17282dcd383SFlorian Hahn delete VPV4;
17382dcd383SFlorian Hahn }
17482dcd383SFlorian Hahn
TEST(VPInstructionTest,replaceAllUsesWith)17582dcd383SFlorian Hahn TEST(VPInstructionTest, replaceAllUsesWith) {
17682dcd383SFlorian Hahn VPValue *VPV1 = new VPValue();
17782dcd383SFlorian Hahn VPValue *VPV2 = new VPValue();
17882dcd383SFlorian Hahn VPInstruction *I1 = new VPInstruction(0, {VPV1, VPV2});
17982dcd383SFlorian Hahn
18082dcd383SFlorian Hahn // Replace all uses of VPV1 with VPV3.
18182dcd383SFlorian Hahn VPValue *VPV3 = new VPValue();
18282dcd383SFlorian Hahn VPV1->replaceAllUsesWith(VPV3);
18382dcd383SFlorian Hahn EXPECT_EQ(VPV3, I1->getOperand(0));
18482dcd383SFlorian Hahn EXPECT_EQ(VPV2, I1->getOperand(1));
18582dcd383SFlorian Hahn EXPECT_EQ(0u, VPV1->getNumUsers());
18682dcd383SFlorian Hahn EXPECT_EQ(1u, VPV2->getNumUsers());
18782dcd383SFlorian Hahn EXPECT_EQ(I1, *VPV2->user_begin());
18882dcd383SFlorian Hahn EXPECT_EQ(1u, VPV3->getNumUsers());
18982dcd383SFlorian Hahn EXPECT_EQ(I1, *VPV3->user_begin());
19082dcd383SFlorian Hahn
19182dcd383SFlorian Hahn // Replace all uses of VPV2 with VPV3.
19282dcd383SFlorian Hahn VPV2->replaceAllUsesWith(VPV3);
19382dcd383SFlorian Hahn EXPECT_EQ(VPV3, I1->getOperand(0));
19482dcd383SFlorian Hahn EXPECT_EQ(VPV3, I1->getOperand(1));
19582dcd383SFlorian Hahn EXPECT_EQ(0u, VPV1->getNumUsers());
19682dcd383SFlorian Hahn EXPECT_EQ(0u, VPV2->getNumUsers());
19782dcd383SFlorian Hahn EXPECT_EQ(2u, VPV3->getNumUsers());
19882dcd383SFlorian Hahn EXPECT_EQ(I1, *VPV3->user_begin());
19982dcd383SFlorian Hahn
20082dcd383SFlorian Hahn // Replace all uses of VPV3 with VPV1.
20182dcd383SFlorian Hahn VPV3->replaceAllUsesWith(VPV1);
20282dcd383SFlorian Hahn EXPECT_EQ(VPV1, I1->getOperand(0));
20382dcd383SFlorian Hahn EXPECT_EQ(VPV1, I1->getOperand(1));
20482dcd383SFlorian Hahn EXPECT_EQ(2u, VPV1->getNumUsers());
20582dcd383SFlorian Hahn EXPECT_EQ(I1, *VPV1->user_begin());
20682dcd383SFlorian Hahn EXPECT_EQ(0u, VPV2->getNumUsers());
20782dcd383SFlorian Hahn EXPECT_EQ(0u, VPV3->getNumUsers());
20882dcd383SFlorian Hahn
209f5fe7abeSFlorian Hahn VPInstruction *I2 = new VPInstruction(0, {VPV1, VPV2});
210f5fe7abeSFlorian Hahn EXPECT_EQ(3u, VPV1->getNumUsers());
211f5fe7abeSFlorian Hahn VPV1->replaceAllUsesWith(VPV3);
212f5fe7abeSFlorian Hahn EXPECT_EQ(3u, VPV3->getNumUsers());
213f5fe7abeSFlorian Hahn
21482dcd383SFlorian Hahn delete I1;
215f5fe7abeSFlorian Hahn delete I2;
21682dcd383SFlorian Hahn delete VPV1;
21782dcd383SFlorian Hahn delete VPV2;
21882dcd383SFlorian Hahn delete VPV3;
21982dcd383SFlorian Hahn }
22082dcd383SFlorian Hahn
TEST(VPInstructionTest,releaseOperandsAtDeletion)221348d85a6SFlorian Hahn TEST(VPInstructionTest, releaseOperandsAtDeletion) {
222348d85a6SFlorian Hahn VPValue *VPV1 = new VPValue();
223348d85a6SFlorian Hahn VPValue *VPV2 = new VPValue();
224348d85a6SFlorian Hahn VPInstruction *I1 = new VPInstruction(0, {VPV1, VPV2});
225348d85a6SFlorian Hahn
226348d85a6SFlorian Hahn EXPECT_EQ(1u, VPV1->getNumUsers());
227348d85a6SFlorian Hahn EXPECT_EQ(I1, *VPV1->user_begin());
228348d85a6SFlorian Hahn EXPECT_EQ(1u, VPV2->getNumUsers());
229348d85a6SFlorian Hahn EXPECT_EQ(I1, *VPV2->user_begin());
230348d85a6SFlorian Hahn
231348d85a6SFlorian Hahn delete I1;
232348d85a6SFlorian Hahn
233348d85a6SFlorian Hahn EXPECT_EQ(0u, VPV1->getNumUsers());
234348d85a6SFlorian Hahn EXPECT_EQ(0u, VPV2->getNumUsers());
235348d85a6SFlorian Hahn
236348d85a6SFlorian Hahn delete VPV1;
237348d85a6SFlorian Hahn delete VPV2;
238348d85a6SFlorian Hahn }
TEST(VPBasicBlockTest,getPlan)23905afa555SFlorian Hahn TEST(VPBasicBlockTest, getPlan) {
24005afa555SFlorian Hahn {
24105afa555SFlorian Hahn VPBasicBlock *VPBB1 = new VPBasicBlock();
24205afa555SFlorian Hahn VPBasicBlock *VPBB2 = new VPBasicBlock();
24305afa555SFlorian Hahn VPBasicBlock *VPBB3 = new VPBasicBlock();
24405afa555SFlorian Hahn VPBasicBlock *VPBB4 = new VPBasicBlock();
24505afa555SFlorian Hahn
24605afa555SFlorian Hahn // VPBB1
24705afa555SFlorian Hahn // / \
24805afa555SFlorian Hahn // VPBB2 VPBB3
24905afa555SFlorian Hahn // \ /
25005afa555SFlorian Hahn // VPBB4
25105afa555SFlorian Hahn VPBlockUtils::connectBlocks(VPBB1, VPBB2);
25205afa555SFlorian Hahn VPBlockUtils::connectBlocks(VPBB1, VPBB3);
25305afa555SFlorian Hahn VPBlockUtils::connectBlocks(VPBB2, VPBB4);
25405afa555SFlorian Hahn VPBlockUtils::connectBlocks(VPBB3, VPBB4);
25505afa555SFlorian Hahn
25605afa555SFlorian Hahn VPlan Plan;
25705afa555SFlorian Hahn Plan.setEntry(VPBB1);
25805afa555SFlorian Hahn
25905afa555SFlorian Hahn EXPECT_EQ(&Plan, VPBB1->getPlan());
26005afa555SFlorian Hahn EXPECT_EQ(&Plan, VPBB2->getPlan());
26105afa555SFlorian Hahn EXPECT_EQ(&Plan, VPBB3->getPlan());
26205afa555SFlorian Hahn EXPECT_EQ(&Plan, VPBB4->getPlan());
26305afa555SFlorian Hahn }
26405afa555SFlorian Hahn
26505afa555SFlorian Hahn {
26605afa555SFlorian Hahn // Region block is entry into VPlan.
26705afa555SFlorian Hahn VPBasicBlock *R1BB1 = new VPBasicBlock();
26805afa555SFlorian Hahn VPBasicBlock *R1BB2 = new VPBasicBlock();
26905afa555SFlorian Hahn VPRegionBlock *R1 = new VPRegionBlock(R1BB1, R1BB2, "R1");
27005afa555SFlorian Hahn VPBlockUtils::connectBlocks(R1BB1, R1BB2);
27105afa555SFlorian Hahn
27205afa555SFlorian Hahn VPlan Plan;
27305afa555SFlorian Hahn Plan.setEntry(R1);
27405afa555SFlorian Hahn EXPECT_EQ(&Plan, R1->getPlan());
27505afa555SFlorian Hahn EXPECT_EQ(&Plan, R1BB1->getPlan());
27605afa555SFlorian Hahn EXPECT_EQ(&Plan, R1BB2->getPlan());
27705afa555SFlorian Hahn }
27805afa555SFlorian Hahn
27905afa555SFlorian Hahn {
28005afa555SFlorian Hahn // VPBasicBlock is the entry into the VPlan, followed by a region.
28105afa555SFlorian Hahn VPBasicBlock *R1BB1 = new VPBasicBlock();
28205afa555SFlorian Hahn VPBasicBlock *R1BB2 = new VPBasicBlock();
28305afa555SFlorian Hahn VPRegionBlock *R1 = new VPRegionBlock(R1BB1, R1BB2, "R1");
28405afa555SFlorian Hahn VPBlockUtils::connectBlocks(R1BB1, R1BB2);
28505afa555SFlorian Hahn
28605afa555SFlorian Hahn VPBasicBlock *VPBB1 = new VPBasicBlock();
28705afa555SFlorian Hahn VPBlockUtils::connectBlocks(VPBB1, R1);
28805afa555SFlorian Hahn
28905afa555SFlorian Hahn VPlan Plan;
29005afa555SFlorian Hahn Plan.setEntry(VPBB1);
29105afa555SFlorian Hahn EXPECT_EQ(&Plan, VPBB1->getPlan());
29205afa555SFlorian Hahn EXPECT_EQ(&Plan, R1->getPlan());
29305afa555SFlorian Hahn EXPECT_EQ(&Plan, R1BB1->getPlan());
29405afa555SFlorian Hahn EXPECT_EQ(&Plan, R1BB2->getPlan());
29505afa555SFlorian Hahn }
29605afa555SFlorian Hahn
29705afa555SFlorian Hahn {
29805afa555SFlorian Hahn VPBasicBlock *R1BB1 = new VPBasicBlock();
29905afa555SFlorian Hahn VPBasicBlock *R1BB2 = new VPBasicBlock();
30005afa555SFlorian Hahn VPRegionBlock *R1 = new VPRegionBlock(R1BB1, R1BB2, "R1");
30105afa555SFlorian Hahn VPBlockUtils::connectBlocks(R1BB1, R1BB2);
30205afa555SFlorian Hahn
30305afa555SFlorian Hahn VPBasicBlock *R2BB1 = new VPBasicBlock();
30405afa555SFlorian Hahn VPBasicBlock *R2BB2 = new VPBasicBlock();
30505afa555SFlorian Hahn VPRegionBlock *R2 = new VPRegionBlock(R2BB1, R2BB2, "R2");
30605afa555SFlorian Hahn VPBlockUtils::connectBlocks(R2BB1, R2BB2);
30705afa555SFlorian Hahn
30805afa555SFlorian Hahn VPBasicBlock *VPBB1 = new VPBasicBlock();
30905afa555SFlorian Hahn VPBlockUtils::connectBlocks(VPBB1, R1);
31005afa555SFlorian Hahn VPBlockUtils::connectBlocks(VPBB1, R2);
31105afa555SFlorian Hahn
31205afa555SFlorian Hahn VPBasicBlock *VPBB2 = new VPBasicBlock();
31305afa555SFlorian Hahn VPBlockUtils::connectBlocks(R1, VPBB2);
31405afa555SFlorian Hahn VPBlockUtils::connectBlocks(R2, VPBB2);
31505afa555SFlorian Hahn
31605afa555SFlorian Hahn VPlan Plan;
31705afa555SFlorian Hahn Plan.setEntry(VPBB1);
31805afa555SFlorian Hahn EXPECT_EQ(&Plan, VPBB1->getPlan());
31905afa555SFlorian Hahn EXPECT_EQ(&Plan, R1->getPlan());
32005afa555SFlorian Hahn EXPECT_EQ(&Plan, R1BB1->getPlan());
32105afa555SFlorian Hahn EXPECT_EQ(&Plan, R1BB2->getPlan());
32205afa555SFlorian Hahn EXPECT_EQ(&Plan, R2->getPlan());
32305afa555SFlorian Hahn EXPECT_EQ(&Plan, R2BB1->getPlan());
32405afa555SFlorian Hahn EXPECT_EQ(&Plan, R2BB2->getPlan());
32505afa555SFlorian Hahn EXPECT_EQ(&Plan, VPBB2->getPlan());
32605afa555SFlorian Hahn }
32705afa555SFlorian Hahn }
32805afa555SFlorian Hahn
TEST(VPBasicBlockTest,TraversingIteratorTest)32989c4dda0SFlorian Hahn TEST(VPBasicBlockTest, TraversingIteratorTest) {
33089c4dda0SFlorian Hahn {
33189c4dda0SFlorian Hahn // VPBasicBlocks only
33289c4dda0SFlorian Hahn // VPBB1
33389c4dda0SFlorian Hahn // / \
33489c4dda0SFlorian Hahn // VPBB2 VPBB3
33589c4dda0SFlorian Hahn // \ /
33689c4dda0SFlorian Hahn // VPBB4
33789c4dda0SFlorian Hahn //
33889c4dda0SFlorian Hahn VPBasicBlock *VPBB1 = new VPBasicBlock();
33989c4dda0SFlorian Hahn VPBasicBlock *VPBB2 = new VPBasicBlock();
34089c4dda0SFlorian Hahn VPBasicBlock *VPBB3 = new VPBasicBlock();
34189c4dda0SFlorian Hahn VPBasicBlock *VPBB4 = new VPBasicBlock();
34289c4dda0SFlorian Hahn
34389c4dda0SFlorian Hahn VPBlockUtils::connectBlocks(VPBB1, VPBB2);
34489c4dda0SFlorian Hahn VPBlockUtils::connectBlocks(VPBB1, VPBB3);
34589c4dda0SFlorian Hahn VPBlockUtils::connectBlocks(VPBB2, VPBB4);
34689c4dda0SFlorian Hahn VPBlockUtils::connectBlocks(VPBB3, VPBB4);
34789c4dda0SFlorian Hahn
34889c4dda0SFlorian Hahn VPBlockRecursiveTraversalWrapper<const VPBlockBase *> Start(VPBB1);
34989c4dda0SFlorian Hahn SmallVector<const VPBlockBase *> FromIterator(depth_first(Start));
35089c4dda0SFlorian Hahn EXPECT_EQ(4u, FromIterator.size());
35189c4dda0SFlorian Hahn EXPECT_EQ(VPBB1, FromIterator[0]);
35289c4dda0SFlorian Hahn EXPECT_EQ(VPBB2, FromIterator[1]);
35389c4dda0SFlorian Hahn
35489c4dda0SFlorian Hahn // Use Plan to properly clean up created blocks.
35589c4dda0SFlorian Hahn VPlan Plan;
35689c4dda0SFlorian Hahn Plan.setEntry(VPBB1);
35789c4dda0SFlorian Hahn }
35889c4dda0SFlorian Hahn
35989c4dda0SFlorian Hahn {
36089c4dda0SFlorian Hahn // 2 consecutive regions.
36189c4dda0SFlorian Hahn // R1 {
36289c4dda0SFlorian Hahn // \
36389c4dda0SFlorian Hahn // R1BB1
36489c4dda0SFlorian Hahn // / \ |--|
36589c4dda0SFlorian Hahn // R1BB2 R1BB3 -|
36689c4dda0SFlorian Hahn // \ /
36789c4dda0SFlorian Hahn // R1BB4
36889c4dda0SFlorian Hahn // }
36989c4dda0SFlorian Hahn // |
37089c4dda0SFlorian Hahn // R2 {
37189c4dda0SFlorian Hahn // \
37289c4dda0SFlorian Hahn // R2BB1
37389c4dda0SFlorian Hahn // |
37489c4dda0SFlorian Hahn // R2BB2
37589c4dda0SFlorian Hahn //
37689c4dda0SFlorian Hahn VPBasicBlock *R1BB1 = new VPBasicBlock();
37789c4dda0SFlorian Hahn VPBasicBlock *R1BB2 = new VPBasicBlock();
37889c4dda0SFlorian Hahn VPBasicBlock *R1BB3 = new VPBasicBlock();
37989c4dda0SFlorian Hahn VPBasicBlock *R1BB4 = new VPBasicBlock();
38089c4dda0SFlorian Hahn VPRegionBlock *R1 = new VPRegionBlock(R1BB1, R1BB4, "R1");
38189c4dda0SFlorian Hahn R1BB2->setParent(R1);
38289c4dda0SFlorian Hahn R1BB3->setParent(R1);
38389c4dda0SFlorian Hahn VPBlockUtils::connectBlocks(R1BB1, R1BB2);
38489c4dda0SFlorian Hahn VPBlockUtils::connectBlocks(R1BB1, R1BB3);
38589c4dda0SFlorian Hahn VPBlockUtils::connectBlocks(R1BB2, R1BB4);
38689c4dda0SFlorian Hahn VPBlockUtils::connectBlocks(R1BB3, R1BB4);
38789c4dda0SFlorian Hahn // Cycle.
38889c4dda0SFlorian Hahn VPBlockUtils::connectBlocks(R1BB3, R1BB3);
38989c4dda0SFlorian Hahn
39089c4dda0SFlorian Hahn VPBasicBlock *R2BB1 = new VPBasicBlock();
39189c4dda0SFlorian Hahn VPBasicBlock *R2BB2 = new VPBasicBlock();
39289c4dda0SFlorian Hahn VPRegionBlock *R2 = new VPRegionBlock(R2BB1, R2BB2, "R2");
39389c4dda0SFlorian Hahn VPBlockUtils::connectBlocks(R2BB1, R2BB2);
39489c4dda0SFlorian Hahn VPBlockUtils::connectBlocks(R1, R2);
39589c4dda0SFlorian Hahn
39689c4dda0SFlorian Hahn // Depth-first.
39789c4dda0SFlorian Hahn VPBlockRecursiveTraversalWrapper<VPBlockBase *> Start(R1);
39889c4dda0SFlorian Hahn SmallVector<const VPBlockBase *> FromIterator(df_begin(Start),
39989c4dda0SFlorian Hahn df_end(Start));
40089c4dda0SFlorian Hahn EXPECT_EQ(8u, FromIterator.size());
40189c4dda0SFlorian Hahn EXPECT_EQ(R1, FromIterator[0]);
40289c4dda0SFlorian Hahn EXPECT_EQ(R1BB1, FromIterator[1]);
40389c4dda0SFlorian Hahn EXPECT_EQ(R1BB2, FromIterator[2]);
40489c4dda0SFlorian Hahn EXPECT_EQ(R1BB4, FromIterator[3]);
40589c4dda0SFlorian Hahn EXPECT_EQ(R2, FromIterator[4]);
40689c4dda0SFlorian Hahn EXPECT_EQ(R2BB1, FromIterator[5]);
40789c4dda0SFlorian Hahn EXPECT_EQ(R2BB2, FromIterator[6]);
40889c4dda0SFlorian Hahn EXPECT_EQ(R1BB3, FromIterator[7]);
40989c4dda0SFlorian Hahn
4104b9be5acSFlorian Hahn // const VPBasicBlocks only.
4114b9be5acSFlorian Hahn FromIterator.clear();
4124b9be5acSFlorian Hahn copy(VPBlockUtils::blocksOnly<const VPBasicBlock>(depth_first(Start)),
4134b9be5acSFlorian Hahn std::back_inserter(FromIterator));
4144b9be5acSFlorian Hahn EXPECT_EQ(6u, FromIterator.size());
4154b9be5acSFlorian Hahn EXPECT_EQ(R1BB1, FromIterator[0]);
4164b9be5acSFlorian Hahn EXPECT_EQ(R1BB2, FromIterator[1]);
4174b9be5acSFlorian Hahn EXPECT_EQ(R1BB4, FromIterator[2]);
4184b9be5acSFlorian Hahn EXPECT_EQ(R2BB1, FromIterator[3]);
4194b9be5acSFlorian Hahn EXPECT_EQ(R2BB2, FromIterator[4]);
4204b9be5acSFlorian Hahn EXPECT_EQ(R1BB3, FromIterator[5]);
4214b9be5acSFlorian Hahn
4224b9be5acSFlorian Hahn // VPRegionBlocks only.
4234b9be5acSFlorian Hahn SmallVector<VPRegionBlock *> FromIteratorVPRegion(
4244b9be5acSFlorian Hahn VPBlockUtils::blocksOnly<VPRegionBlock>(depth_first(Start)));
4254b9be5acSFlorian Hahn EXPECT_EQ(2u, FromIteratorVPRegion.size());
4264b9be5acSFlorian Hahn EXPECT_EQ(R1, FromIteratorVPRegion[0]);
4274b9be5acSFlorian Hahn EXPECT_EQ(R2, FromIteratorVPRegion[1]);
4284b9be5acSFlorian Hahn
42989c4dda0SFlorian Hahn // Post-order.
43089c4dda0SFlorian Hahn FromIterator.clear();
43189c4dda0SFlorian Hahn copy(post_order(Start), std::back_inserter(FromIterator));
43289c4dda0SFlorian Hahn EXPECT_EQ(8u, FromIterator.size());
43389c4dda0SFlorian Hahn EXPECT_EQ(R2BB2, FromIterator[0]);
43489c4dda0SFlorian Hahn EXPECT_EQ(R2BB1, FromIterator[1]);
43589c4dda0SFlorian Hahn EXPECT_EQ(R2, FromIterator[2]);
43689c4dda0SFlorian Hahn EXPECT_EQ(R1BB4, FromIterator[3]);
43789c4dda0SFlorian Hahn EXPECT_EQ(R1BB2, FromIterator[4]);
43889c4dda0SFlorian Hahn EXPECT_EQ(R1BB3, FromIterator[5]);
43989c4dda0SFlorian Hahn EXPECT_EQ(R1BB1, FromIterator[6]);
44089c4dda0SFlorian Hahn EXPECT_EQ(R1, FromIterator[7]);
44189c4dda0SFlorian Hahn
44289c4dda0SFlorian Hahn // Use Plan to properly clean up created blocks.
44389c4dda0SFlorian Hahn VPlan Plan;
44489c4dda0SFlorian Hahn Plan.setEntry(R1);
44589c4dda0SFlorian Hahn }
44689c4dda0SFlorian Hahn
44789c4dda0SFlorian Hahn {
44889c4dda0SFlorian Hahn // 2 nested regions.
44989c4dda0SFlorian Hahn // VPBB1
45089c4dda0SFlorian Hahn // |
45189c4dda0SFlorian Hahn // R1 {
45289c4dda0SFlorian Hahn // R1BB1
45389c4dda0SFlorian Hahn // / \
45489c4dda0SFlorian Hahn // R2 { |
45589c4dda0SFlorian Hahn // \ |
45689c4dda0SFlorian Hahn // R2BB1 |
45789c4dda0SFlorian Hahn // | \ R1BB2
45889c4dda0SFlorian Hahn // R2BB2-| |
45989c4dda0SFlorian Hahn // \ |
46089c4dda0SFlorian Hahn // R2BB3 |
46189c4dda0SFlorian Hahn // } /
46289c4dda0SFlorian Hahn // \ /
46389c4dda0SFlorian Hahn // R1BB3
46489c4dda0SFlorian Hahn // }
46589c4dda0SFlorian Hahn // |
46689c4dda0SFlorian Hahn // VPBB2
46789c4dda0SFlorian Hahn //
46889c4dda0SFlorian Hahn VPBasicBlock *R1BB1 = new VPBasicBlock("R1BB1");
46989c4dda0SFlorian Hahn VPBasicBlock *R1BB2 = new VPBasicBlock("R1BB2");
47089c4dda0SFlorian Hahn VPBasicBlock *R1BB3 = new VPBasicBlock("R1BB3");
47189c4dda0SFlorian Hahn VPRegionBlock *R1 = new VPRegionBlock(R1BB1, R1BB3, "R1");
47289c4dda0SFlorian Hahn
47389c4dda0SFlorian Hahn VPBasicBlock *R2BB1 = new VPBasicBlock("R2BB1");
47489c4dda0SFlorian Hahn VPBasicBlock *R2BB2 = new VPBasicBlock("R2BB2");
47589c4dda0SFlorian Hahn VPBasicBlock *R2BB3 = new VPBasicBlock("R2BB3");
47689c4dda0SFlorian Hahn VPRegionBlock *R2 = new VPRegionBlock(R2BB1, R2BB3, "R2");
47789c4dda0SFlorian Hahn R2BB2->setParent(R2);
47889c4dda0SFlorian Hahn VPBlockUtils::connectBlocks(R2BB1, R2BB2);
47989c4dda0SFlorian Hahn VPBlockUtils::connectBlocks(R2BB2, R2BB1);
48089c4dda0SFlorian Hahn VPBlockUtils::connectBlocks(R2BB2, R2BB3);
48189c4dda0SFlorian Hahn
48289c4dda0SFlorian Hahn R2->setParent(R1);
48389c4dda0SFlorian Hahn VPBlockUtils::connectBlocks(R1BB1, R2);
48489c4dda0SFlorian Hahn R1BB2->setParent(R1);
48589c4dda0SFlorian Hahn VPBlockUtils::connectBlocks(R1BB1, R1BB2);
48689c4dda0SFlorian Hahn VPBlockUtils::connectBlocks(R1BB2, R1BB3);
48789c4dda0SFlorian Hahn VPBlockUtils::connectBlocks(R2, R1BB3);
48889c4dda0SFlorian Hahn
48989c4dda0SFlorian Hahn VPBasicBlock *VPBB1 = new VPBasicBlock("VPBB1");
49089c4dda0SFlorian Hahn VPBlockUtils::connectBlocks(VPBB1, R1);
49189c4dda0SFlorian Hahn VPBasicBlock *VPBB2 = new VPBasicBlock("VPBB2");
49289c4dda0SFlorian Hahn VPBlockUtils::connectBlocks(R1, VPBB2);
49389c4dda0SFlorian Hahn
49489c4dda0SFlorian Hahn // Depth-first.
49589c4dda0SFlorian Hahn VPBlockRecursiveTraversalWrapper<VPBlockBase *> Start(VPBB1);
49689c4dda0SFlorian Hahn SmallVector<VPBlockBase *> FromIterator(depth_first(Start));
49789c4dda0SFlorian Hahn EXPECT_EQ(10u, FromIterator.size());
49889c4dda0SFlorian Hahn EXPECT_EQ(VPBB1, FromIterator[0]);
49989c4dda0SFlorian Hahn EXPECT_EQ(R1, FromIterator[1]);
50089c4dda0SFlorian Hahn EXPECT_EQ(R1BB1, FromIterator[2]);
50189c4dda0SFlorian Hahn EXPECT_EQ(R2, FromIterator[3]);
50289c4dda0SFlorian Hahn EXPECT_EQ(R2BB1, FromIterator[4]);
50389c4dda0SFlorian Hahn EXPECT_EQ(R2BB2, FromIterator[5]);
50489c4dda0SFlorian Hahn EXPECT_EQ(R2BB3, FromIterator[6]);
50589c4dda0SFlorian Hahn EXPECT_EQ(R1BB3, FromIterator[7]);
50689c4dda0SFlorian Hahn EXPECT_EQ(VPBB2, FromIterator[8]);
50789c4dda0SFlorian Hahn EXPECT_EQ(R1BB2, FromIterator[9]);
50889c4dda0SFlorian Hahn
50989c4dda0SFlorian Hahn // Post-order.
51089c4dda0SFlorian Hahn FromIterator.clear();
51189c4dda0SFlorian Hahn FromIterator.append(po_begin(Start), po_end(Start));
51289c4dda0SFlorian Hahn EXPECT_EQ(10u, FromIterator.size());
51389c4dda0SFlorian Hahn EXPECT_EQ(VPBB2, FromIterator[0]);
51489c4dda0SFlorian Hahn EXPECT_EQ(R1BB3, FromIterator[1]);
51589c4dda0SFlorian Hahn EXPECT_EQ(R2BB3, FromIterator[2]);
51689c4dda0SFlorian Hahn EXPECT_EQ(R2BB2, FromIterator[3]);
51789c4dda0SFlorian Hahn EXPECT_EQ(R2BB1, FromIterator[4]);
51889c4dda0SFlorian Hahn EXPECT_EQ(R2, FromIterator[5]);
51989c4dda0SFlorian Hahn EXPECT_EQ(R1BB2, FromIterator[6]);
52089c4dda0SFlorian Hahn EXPECT_EQ(R1BB1, FromIterator[7]);
52189c4dda0SFlorian Hahn EXPECT_EQ(R1, FromIterator[8]);
52289c4dda0SFlorian Hahn EXPECT_EQ(VPBB1, FromIterator[9]);
52389c4dda0SFlorian Hahn
52489c4dda0SFlorian Hahn // Use Plan to properly clean up created blocks.
52589c4dda0SFlorian Hahn VPlan Plan;
52689c4dda0SFlorian Hahn Plan.setEntry(VPBB1);
52789c4dda0SFlorian Hahn }
52889c4dda0SFlorian Hahn
52989c4dda0SFlorian Hahn {
53089c4dda0SFlorian Hahn // VPBB1
53189c4dda0SFlorian Hahn // |
53289c4dda0SFlorian Hahn // R1 {
53389c4dda0SFlorian Hahn // \
53489c4dda0SFlorian Hahn // R2 {
53589c4dda0SFlorian Hahn // R2BB1
53689c4dda0SFlorian Hahn // |
53789c4dda0SFlorian Hahn // R2BB2
53889c4dda0SFlorian Hahn // }
53989c4dda0SFlorian Hahn //
54089c4dda0SFlorian Hahn VPBasicBlock *R2BB1 = new VPBasicBlock("R2BB1");
54189c4dda0SFlorian Hahn VPBasicBlock *R2BB2 = new VPBasicBlock("R2BB2");
54289c4dda0SFlorian Hahn VPRegionBlock *R2 = new VPRegionBlock(R2BB1, R2BB2, "R2");
54389c4dda0SFlorian Hahn VPBlockUtils::connectBlocks(R2BB1, R2BB2);
54489c4dda0SFlorian Hahn
54589c4dda0SFlorian Hahn VPRegionBlock *R1 = new VPRegionBlock(R2, R2, "R1");
54689c4dda0SFlorian Hahn R2->setParent(R1);
54789c4dda0SFlorian Hahn
54889c4dda0SFlorian Hahn VPBasicBlock *VPBB1 = new VPBasicBlock("VPBB1");
54989c4dda0SFlorian Hahn VPBlockUtils::connectBlocks(VPBB1, R1);
55089c4dda0SFlorian Hahn
55189c4dda0SFlorian Hahn // Depth-first.
55289c4dda0SFlorian Hahn VPBlockRecursiveTraversalWrapper<VPBlockBase *> Start(VPBB1);
55389c4dda0SFlorian Hahn SmallVector<VPBlockBase *> FromIterator(depth_first(Start));
55489c4dda0SFlorian Hahn EXPECT_EQ(5u, FromIterator.size());
55589c4dda0SFlorian Hahn EXPECT_EQ(VPBB1, FromIterator[0]);
55689c4dda0SFlorian Hahn EXPECT_EQ(R1, FromIterator[1]);
55789c4dda0SFlorian Hahn EXPECT_EQ(R2, FromIterator[2]);
55889c4dda0SFlorian Hahn EXPECT_EQ(R2BB1, FromIterator[3]);
55989c4dda0SFlorian Hahn EXPECT_EQ(R2BB2, FromIterator[4]);
56089c4dda0SFlorian Hahn
56189c4dda0SFlorian Hahn // Post-order.
56289c4dda0SFlorian Hahn FromIterator.clear();
56389c4dda0SFlorian Hahn FromIterator.append(po_begin(Start), po_end(Start));
56489c4dda0SFlorian Hahn EXPECT_EQ(5u, FromIterator.size());
56589c4dda0SFlorian Hahn EXPECT_EQ(R2BB2, FromIterator[0]);
56689c4dda0SFlorian Hahn EXPECT_EQ(R2BB1, FromIterator[1]);
56789c4dda0SFlorian Hahn EXPECT_EQ(R2, FromIterator[2]);
56889c4dda0SFlorian Hahn EXPECT_EQ(R1, FromIterator[3]);
56989c4dda0SFlorian Hahn EXPECT_EQ(VPBB1, FromIterator[4]);
57089c4dda0SFlorian Hahn
57189c4dda0SFlorian Hahn // Use Plan to properly clean up created blocks.
57289c4dda0SFlorian Hahn VPlan Plan;
57389c4dda0SFlorian Hahn Plan.setEntry(VPBB1);
57489c4dda0SFlorian Hahn }
57589c4dda0SFlorian Hahn
57689c4dda0SFlorian Hahn {
57789c4dda0SFlorian Hahn // Nested regions with both R3 and R2 being exit nodes without successors.
57889c4dda0SFlorian Hahn // The successors of R1 should be used.
57989c4dda0SFlorian Hahn //
58089c4dda0SFlorian Hahn // VPBB1
58189c4dda0SFlorian Hahn // |
58289c4dda0SFlorian Hahn // R1 {
58389c4dda0SFlorian Hahn // \
58489c4dda0SFlorian Hahn // R2 {
58589c4dda0SFlorian Hahn // \
58689c4dda0SFlorian Hahn // R2BB1
58789c4dda0SFlorian Hahn // |
58889c4dda0SFlorian Hahn // R3 {
58989c4dda0SFlorian Hahn // R3BB1
59089c4dda0SFlorian Hahn // }
59189c4dda0SFlorian Hahn // }
59289c4dda0SFlorian Hahn // |
59389c4dda0SFlorian Hahn // VPBB2
59489c4dda0SFlorian Hahn //
59589c4dda0SFlorian Hahn VPBasicBlock *R3BB1 = new VPBasicBlock("R3BB1");
59689c4dda0SFlorian Hahn VPRegionBlock *R3 = new VPRegionBlock(R3BB1, R3BB1, "R3");
59789c4dda0SFlorian Hahn
59889c4dda0SFlorian Hahn VPBasicBlock *R2BB1 = new VPBasicBlock("R2BB1");
59989c4dda0SFlorian Hahn VPRegionBlock *R2 = new VPRegionBlock(R2BB1, R3, "R2");
60089c4dda0SFlorian Hahn R3->setParent(R2);
60189c4dda0SFlorian Hahn VPBlockUtils::connectBlocks(R2BB1, R3);
60289c4dda0SFlorian Hahn
60389c4dda0SFlorian Hahn VPRegionBlock *R1 = new VPRegionBlock(R2, R2, "R1");
60489c4dda0SFlorian Hahn R2->setParent(R1);
60589c4dda0SFlorian Hahn
60689c4dda0SFlorian Hahn VPBasicBlock *VPBB1 = new VPBasicBlock("VPBB1");
60789c4dda0SFlorian Hahn VPBasicBlock *VPBB2 = new VPBasicBlock("VPBB2");
60889c4dda0SFlorian Hahn VPBlockUtils::connectBlocks(VPBB1, R1);
60989c4dda0SFlorian Hahn VPBlockUtils::connectBlocks(R1, VPBB2);
61089c4dda0SFlorian Hahn
61189c4dda0SFlorian Hahn // Depth-first.
61289c4dda0SFlorian Hahn VPBlockRecursiveTraversalWrapper<VPBlockBase *> Start(VPBB1);
61389c4dda0SFlorian Hahn SmallVector<VPBlockBase *> FromIterator(depth_first(Start));
61489c4dda0SFlorian Hahn EXPECT_EQ(7u, FromIterator.size());
61589c4dda0SFlorian Hahn EXPECT_EQ(VPBB1, FromIterator[0]);
61689c4dda0SFlorian Hahn EXPECT_EQ(R1, FromIterator[1]);
61789c4dda0SFlorian Hahn EXPECT_EQ(R2, FromIterator[2]);
61889c4dda0SFlorian Hahn EXPECT_EQ(R2BB1, FromIterator[3]);
61989c4dda0SFlorian Hahn EXPECT_EQ(R3, FromIterator[4]);
62089c4dda0SFlorian Hahn EXPECT_EQ(R3BB1, FromIterator[5]);
62189c4dda0SFlorian Hahn EXPECT_EQ(VPBB2, FromIterator[6]);
62289c4dda0SFlorian Hahn
6234b9be5acSFlorian Hahn SmallVector<VPBlockBase *> FromIteratorVPBB;
6244b9be5acSFlorian Hahn copy(VPBlockUtils::blocksOnly<VPBasicBlock>(depth_first(Start)),
6254b9be5acSFlorian Hahn std::back_inserter(FromIteratorVPBB));
6264b9be5acSFlorian Hahn EXPECT_EQ(VPBB1, FromIteratorVPBB[0]);
6274b9be5acSFlorian Hahn EXPECT_EQ(R2BB1, FromIteratorVPBB[1]);
6284b9be5acSFlorian Hahn EXPECT_EQ(R3BB1, FromIteratorVPBB[2]);
6294b9be5acSFlorian Hahn EXPECT_EQ(VPBB2, FromIteratorVPBB[3]);
6304b9be5acSFlorian Hahn
63189c4dda0SFlorian Hahn // Post-order.
63289c4dda0SFlorian Hahn FromIterator.clear();
63389c4dda0SFlorian Hahn copy(post_order(Start), std::back_inserter(FromIterator));
63489c4dda0SFlorian Hahn EXPECT_EQ(7u, FromIterator.size());
63589c4dda0SFlorian Hahn EXPECT_EQ(VPBB2, FromIterator[0]);
63689c4dda0SFlorian Hahn EXPECT_EQ(R3BB1, FromIterator[1]);
63789c4dda0SFlorian Hahn EXPECT_EQ(R3, FromIterator[2]);
63889c4dda0SFlorian Hahn EXPECT_EQ(R2BB1, FromIterator[3]);
63989c4dda0SFlorian Hahn EXPECT_EQ(R2, FromIterator[4]);
64089c4dda0SFlorian Hahn EXPECT_EQ(R1, FromIterator[5]);
64189c4dda0SFlorian Hahn EXPECT_EQ(VPBB1, FromIterator[6]);
64289c4dda0SFlorian Hahn
6434b9be5acSFlorian Hahn // Post-order, const VPRegionBlocks only.
6447302fe43SFlorian Hahn VPBlockRecursiveTraversalWrapper<const VPBlockBase *> StartConst(VPBB1);
6454b9be5acSFlorian Hahn SmallVector<const VPRegionBlock *> FromIteratorVPRegion(
6467302fe43SFlorian Hahn VPBlockUtils::blocksOnly<const VPRegionBlock>(post_order(StartConst)));
6474b9be5acSFlorian Hahn EXPECT_EQ(3u, FromIteratorVPRegion.size());
6484b9be5acSFlorian Hahn EXPECT_EQ(R3, FromIteratorVPRegion[0]);
6494b9be5acSFlorian Hahn EXPECT_EQ(R2, FromIteratorVPRegion[1]);
6504b9be5acSFlorian Hahn EXPECT_EQ(R1, FromIteratorVPRegion[2]);
6514b9be5acSFlorian Hahn
6524b9be5acSFlorian Hahn // Post-order, VPBasicBlocks only.
6534b9be5acSFlorian Hahn FromIterator.clear();
6544b9be5acSFlorian Hahn copy(VPBlockUtils::blocksOnly<VPBasicBlock>(post_order(Start)),
6554b9be5acSFlorian Hahn std::back_inserter(FromIterator));
6564b9be5acSFlorian Hahn EXPECT_EQ(FromIterator.size(), 4u);
6574b9be5acSFlorian Hahn EXPECT_EQ(VPBB2, FromIterator[0]);
6584b9be5acSFlorian Hahn EXPECT_EQ(R3BB1, FromIterator[1]);
6594b9be5acSFlorian Hahn EXPECT_EQ(R2BB1, FromIterator[2]);
6604b9be5acSFlorian Hahn EXPECT_EQ(VPBB1, FromIterator[3]);
6614b9be5acSFlorian Hahn
66289c4dda0SFlorian Hahn // Use Plan to properly clean up created blocks.
66389c4dda0SFlorian Hahn VPlan Plan;
66489c4dda0SFlorian Hahn Plan.setEntry(VPBB1);
66589c4dda0SFlorian Hahn }
66689c4dda0SFlorian Hahn }
66789c4dda0SFlorian Hahn
66892205cb2SAndrei Elovikov #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
TEST(VPBasicBlockTest,print)66940e7bfc4SFlorian Hahn TEST(VPBasicBlockTest, print) {
670e6a74803SFlorian Hahn VPInstruction *I1 = new VPInstruction(Instruction::Add, {});
671e6a74803SFlorian Hahn VPInstruction *I2 = new VPInstruction(Instruction::Sub, {I1});
672e6a74803SFlorian Hahn VPInstruction *I3 = new VPInstruction(Instruction::Br, {I1, I2});
67340e7bfc4SFlorian Hahn
67440e7bfc4SFlorian Hahn VPBasicBlock *VPBB1 = new VPBasicBlock();
67540e7bfc4SFlorian Hahn VPBB1->appendRecipe(I1);
67640e7bfc4SFlorian Hahn VPBB1->appendRecipe(I2);
67740e7bfc4SFlorian Hahn VPBB1->appendRecipe(I3);
67893a9d2deSAndrei Elovikov VPBB1->setName("bb1");
67940e7bfc4SFlorian Hahn
680e6a74803SFlorian Hahn VPInstruction *I4 = new VPInstruction(Instruction::Mul, {I2, I1});
681e6a74803SFlorian Hahn VPInstruction *I5 = new VPInstruction(Instruction::Ret, {I4});
68240e7bfc4SFlorian Hahn VPBasicBlock *VPBB2 = new VPBasicBlock();
68340e7bfc4SFlorian Hahn VPBB2->appendRecipe(I4);
68440e7bfc4SFlorian Hahn VPBB2->appendRecipe(I5);
68593a9d2deSAndrei Elovikov VPBB2->setName("bb2");
68640e7bfc4SFlorian Hahn
68740e7bfc4SFlorian Hahn VPBlockUtils::connectBlocks(VPBB1, VPBB2);
68840e7bfc4SFlorian Hahn
68940e7bfc4SFlorian Hahn // Check printing an instruction without associated VPlan.
69040e7bfc4SFlorian Hahn {
69140e7bfc4SFlorian Hahn std::string I3Dump;
69240e7bfc4SFlorian Hahn raw_string_ostream OS(I3Dump);
693eb0371e4SFlorian Hahn VPSlotTracker SlotTracker;
694eb0371e4SFlorian Hahn I3->print(OS, "", SlotTracker);
69540e7bfc4SFlorian Hahn OS.flush();
696eb0371e4SFlorian Hahn EXPECT_EQ("EMIT br <badref> <badref>", I3Dump);
69740e7bfc4SFlorian Hahn }
69840e7bfc4SFlorian Hahn
69940e7bfc4SFlorian Hahn VPlan Plan;
70040e7bfc4SFlorian Hahn Plan.setEntry(VPBB1);
70140e7bfc4SFlorian Hahn std::string FullDump;
70293a9d2deSAndrei Elovikov raw_string_ostream OS(FullDump);
70393a9d2deSAndrei Elovikov Plan.printDOT(OS);
70440e7bfc4SFlorian Hahn
7056120cb42SFlorian Hahn const char *ExpectedStr = R"(digraph VPlan {
70640e7bfc4SFlorian Hahn graph [labelloc=t, fontsize=30; label="Vectorization Plan"]
70740e7bfc4SFlorian Hahn node [shape=rect, fontname=Courier, fontsize=30]
70840e7bfc4SFlorian Hahn edge [fontname=Courier, fontsize=30]
70940e7bfc4SFlorian Hahn compound=true
71040e7bfc4SFlorian Hahn N0 [label =
71193a9d2deSAndrei Elovikov "bb1:\l" +
71287e258bcSFlorian Hahn " EMIT vp\<%1\> = add\l" +
71387e258bcSFlorian Hahn " EMIT vp\<%2\> = sub vp\<%1\>\l" +
71487e258bcSFlorian Hahn " EMIT br vp\<%1\> vp\<%2\>\l" +
71593a9d2deSAndrei Elovikov "Successor(s): bb2\l"
71640e7bfc4SFlorian Hahn ]
71740e7bfc4SFlorian Hahn N0 -> N1 [ label=""]
71840e7bfc4SFlorian Hahn N1 [label =
71993a9d2deSAndrei Elovikov "bb2:\l" +
72087e258bcSFlorian Hahn " EMIT vp\<%4\> = mul vp\<%2\> vp\<%1\>\l" +
72187e258bcSFlorian Hahn " EMIT ret vp\<%4\>\l" +
72293a9d2deSAndrei Elovikov "No successors\l"
72340e7bfc4SFlorian Hahn ]
72440e7bfc4SFlorian Hahn }
7256120cb42SFlorian Hahn )";
7266120cb42SFlorian Hahn EXPECT_EQ(ExpectedStr, FullDump);
72740e7bfc4SFlorian Hahn
72893a9d2deSAndrei Elovikov const char *ExpectedBlock1Str = R"(bb1:
72987e258bcSFlorian Hahn EMIT vp<%1> = add
73087e258bcSFlorian Hahn EMIT vp<%2> = sub vp<%1>
73187e258bcSFlorian Hahn EMIT br vp<%1> vp<%2>
73293a9d2deSAndrei Elovikov Successor(s): bb2
73393a9d2deSAndrei Elovikov )";
73493a9d2deSAndrei Elovikov std::string Block1Dump;
73593a9d2deSAndrei Elovikov raw_string_ostream OS1(Block1Dump);
73693a9d2deSAndrei Elovikov VPBB1->print(OS1);
73793a9d2deSAndrei Elovikov EXPECT_EQ(ExpectedBlock1Str, Block1Dump);
73893a9d2deSAndrei Elovikov
73993a9d2deSAndrei Elovikov // Ensure that numbering is good when dumping the second block in isolation.
74093a9d2deSAndrei Elovikov const char *ExpectedBlock2Str = R"(bb2:
74187e258bcSFlorian Hahn EMIT vp<%4> = mul vp<%2> vp<%1>
74287e258bcSFlorian Hahn EMIT ret vp<%4>
74393a9d2deSAndrei Elovikov No successors
74493a9d2deSAndrei Elovikov )";
74593a9d2deSAndrei Elovikov std::string Block2Dump;
74693a9d2deSAndrei Elovikov raw_string_ostream OS2(Block2Dump);
74793a9d2deSAndrei Elovikov VPBB2->print(OS2);
74893a9d2deSAndrei Elovikov EXPECT_EQ(ExpectedBlock2Str, Block2Dump);
74993a9d2deSAndrei Elovikov
75040e7bfc4SFlorian Hahn {
75140e7bfc4SFlorian Hahn std::string I3Dump;
75240e7bfc4SFlorian Hahn raw_string_ostream OS(I3Dump);
753eb0371e4SFlorian Hahn VPSlotTracker SlotTracker(&Plan);
754eb0371e4SFlorian Hahn I3->print(OS, "", SlotTracker);
75540e7bfc4SFlorian Hahn OS.flush();
75687e258bcSFlorian Hahn EXPECT_EQ("EMIT br vp<%1> vp<%2>", I3Dump);
75740e7bfc4SFlorian Hahn }
75840e7bfc4SFlorian Hahn
75940e7bfc4SFlorian Hahn {
760e6a74803SFlorian Hahn std::string I4Dump;
761e6a74803SFlorian Hahn raw_string_ostream OS(I4Dump);
762e6a74803SFlorian Hahn OS << *I4;
76340e7bfc4SFlorian Hahn OS.flush();
76487e258bcSFlorian Hahn EXPECT_EQ("EMIT vp<%4> = mul vp<%2> vp<%1>", I4Dump);
76540e7bfc4SFlorian Hahn }
76640e7bfc4SFlorian Hahn }
76792205cb2SAndrei Elovikov #endif
76840e7bfc4SFlorian Hahn
TEST(VPRecipeTest,CastVPInstructionToVPUser)769357bbaabSFlorian Hahn TEST(VPRecipeTest, CastVPInstructionToVPUser) {
770357bbaabSFlorian Hahn VPValue Op1;
771357bbaabSFlorian Hahn VPValue Op2;
772357bbaabSFlorian Hahn VPInstruction Recipe(Instruction::Add, {&Op1, &Op2});
773357bbaabSFlorian Hahn EXPECT_TRUE(isa<VPUser>(&Recipe));
774357bbaabSFlorian Hahn VPRecipeBase *BaseR = &Recipe;
775357bbaabSFlorian Hahn EXPECT_TRUE(isa<VPUser>(BaseR));
776f2508923SFlorian Hahn EXPECT_EQ(&Recipe, BaseR);
777357bbaabSFlorian Hahn }
778357bbaabSFlorian Hahn
TEST(VPRecipeTest,CastVPWidenRecipeToVPUser)779d8563654SFlorian Hahn TEST(VPRecipeTest, CastVPWidenRecipeToVPUser) {
780d8563654SFlorian Hahn LLVMContext C;
781d8563654SFlorian Hahn
782d8563654SFlorian Hahn IntegerType *Int32 = IntegerType::get(C, 32);
783d8563654SFlorian Hahn auto *AI =
784d8563654SFlorian Hahn BinaryOperator::CreateAdd(UndefValue::get(Int32), UndefValue::get(Int32));
785d8563654SFlorian Hahn VPValue Op1;
786d8563654SFlorian Hahn VPValue Op2;
787d8563654SFlorian Hahn SmallVector<VPValue *, 2> Args;
788d8563654SFlorian Hahn Args.push_back(&Op1);
789d8563654SFlorian Hahn Args.push_back(&Op1);
790d8563654SFlorian Hahn VPWidenRecipe WidenR(*AI, make_range(Args.begin(), Args.end()));
791d8563654SFlorian Hahn EXPECT_TRUE(isa<VPUser>(&WidenR));
792d8563654SFlorian Hahn VPRecipeBase *WidenRBase = &WidenR;
793d8563654SFlorian Hahn EXPECT_TRUE(isa<VPUser>(WidenRBase));
794f2508923SFlorian Hahn EXPECT_EQ(&WidenR, WidenRBase);
795d8563654SFlorian Hahn delete AI;
796d8563654SFlorian Hahn }
797d8563654SFlorian Hahn
TEST(VPRecipeTest,CastVPWidenCallRecipeToVPUserAndVPDef)798f2508923SFlorian Hahn TEST(VPRecipeTest, CastVPWidenCallRecipeToVPUserAndVPDef) {
799d8563654SFlorian Hahn LLVMContext C;
800d8563654SFlorian Hahn
801d8563654SFlorian Hahn IntegerType *Int32 = IntegerType::get(C, 32);
802d8563654SFlorian Hahn FunctionType *FTy = FunctionType::get(Int32, false);
803d8563654SFlorian Hahn auto *Call = CallInst::Create(FTy, UndefValue::get(FTy));
804d8563654SFlorian Hahn VPValue Op1;
805d8563654SFlorian Hahn VPValue Op2;
806d8563654SFlorian Hahn SmallVector<VPValue *, 2> Args;
807d8563654SFlorian Hahn Args.push_back(&Op1);
808d8563654SFlorian Hahn Args.push_back(&Op2);
809d8563654SFlorian Hahn VPWidenCallRecipe Recipe(*Call, make_range(Args.begin(), Args.end()));
810d8563654SFlorian Hahn EXPECT_TRUE(isa<VPUser>(&Recipe));
811d8563654SFlorian Hahn VPRecipeBase *BaseR = &Recipe;
812d8563654SFlorian Hahn EXPECT_TRUE(isa<VPUser>(BaseR));
813f2508923SFlorian Hahn EXPECT_EQ(&Recipe, BaseR);
814f2508923SFlorian Hahn
815f2508923SFlorian Hahn VPValue *VPV = &Recipe;
816f2508923SFlorian Hahn EXPECT_TRUE(isa<VPRecipeBase>(VPV->getDef()));
817f2508923SFlorian Hahn EXPECT_EQ(&Recipe, dyn_cast<VPRecipeBase>(VPV->getDef()));
818f2508923SFlorian Hahn
819d8563654SFlorian Hahn delete Call;
820d8563654SFlorian Hahn }
821d8563654SFlorian Hahn
TEST(VPRecipeTest,CastVPWidenSelectRecipeToVPUserAndVPDef)822f2508923SFlorian Hahn TEST(VPRecipeTest, CastVPWidenSelectRecipeToVPUserAndVPDef) {
823d8563654SFlorian Hahn LLVMContext C;
824d8563654SFlorian Hahn
825d8563654SFlorian Hahn IntegerType *Int1 = IntegerType::get(C, 1);
826d8563654SFlorian Hahn IntegerType *Int32 = IntegerType::get(C, 32);
827d8563654SFlorian Hahn auto *SelectI = SelectInst::Create(
828d8563654SFlorian Hahn UndefValue::get(Int1), UndefValue::get(Int32), UndefValue::get(Int32));
829d8563654SFlorian Hahn VPValue Op1;
830d8563654SFlorian Hahn VPValue Op2;
831d8563654SFlorian Hahn VPValue Op3;
832d8563654SFlorian Hahn SmallVector<VPValue *, 4> Args;
833d8563654SFlorian Hahn Args.push_back(&Op1);
834d8563654SFlorian Hahn Args.push_back(&Op2);
835d8563654SFlorian Hahn Args.push_back(&Op3);
836d8563654SFlorian Hahn VPWidenSelectRecipe WidenSelectR(*SelectI,
837d8563654SFlorian Hahn make_range(Args.begin(), Args.end()), false);
838d8563654SFlorian Hahn EXPECT_TRUE(isa<VPUser>(&WidenSelectR));
839d8563654SFlorian Hahn VPRecipeBase *BaseR = &WidenSelectR;
840d8563654SFlorian Hahn EXPECT_TRUE(isa<VPUser>(BaseR));
841f2508923SFlorian Hahn EXPECT_EQ(&WidenSelectR, BaseR);
842f2508923SFlorian Hahn
843f2508923SFlorian Hahn VPValue *VPV = &WidenSelectR;
844f2508923SFlorian Hahn EXPECT_TRUE(isa<VPRecipeBase>(VPV->getDef()));
845f2508923SFlorian Hahn EXPECT_EQ(&WidenSelectR, dyn_cast<VPRecipeBase>(VPV->getDef()));
846f2508923SFlorian Hahn
847d8563654SFlorian Hahn delete SelectI;
848d8563654SFlorian Hahn }
849d8563654SFlorian Hahn
TEST(VPRecipeTest,CastVPWidenGEPRecipeToVPUserAndVPDef)850f2508923SFlorian Hahn TEST(VPRecipeTest, CastVPWidenGEPRecipeToVPUserAndVPDef) {
851d8563654SFlorian Hahn LLVMContext C;
852d8563654SFlorian Hahn
853d8563654SFlorian Hahn IntegerType *Int32 = IntegerType::get(C, 32);
854d8563654SFlorian Hahn PointerType *Int32Ptr = PointerType::get(Int32, 0);
855d8563654SFlorian Hahn auto *GEP = GetElementPtrInst::Create(Int32, UndefValue::get(Int32Ptr),
856d8563654SFlorian Hahn UndefValue::get(Int32));
857d8563654SFlorian Hahn VPValue Op1;
858d8563654SFlorian Hahn VPValue Op2;
859d8563654SFlorian Hahn SmallVector<VPValue *, 4> Args;
860d8563654SFlorian Hahn Args.push_back(&Op1);
861d8563654SFlorian Hahn Args.push_back(&Op2);
862d8563654SFlorian Hahn VPWidenGEPRecipe Recipe(GEP, make_range(Args.begin(), Args.end()));
863d8563654SFlorian Hahn EXPECT_TRUE(isa<VPUser>(&Recipe));
864d8563654SFlorian Hahn VPRecipeBase *BaseR = &Recipe;
865d8563654SFlorian Hahn EXPECT_TRUE(isa<VPUser>(BaseR));
866f2508923SFlorian Hahn EXPECT_EQ(&Recipe, BaseR);
867f2508923SFlorian Hahn
868f2508923SFlorian Hahn VPValue *VPV = &Recipe;
869f2508923SFlorian Hahn EXPECT_TRUE(isa<VPRecipeBase>(VPV->getDef()));
870f2508923SFlorian Hahn EXPECT_EQ(&Recipe, dyn_cast<VPRecipeBase>(VPV->getDef()));
871f2508923SFlorian Hahn
872d8563654SFlorian Hahn delete GEP;
873d8563654SFlorian Hahn }
874d8563654SFlorian Hahn
TEST(VPRecipeTest,CastVPBlendRecipeToVPUser)875d8563654SFlorian Hahn TEST(VPRecipeTest, CastVPBlendRecipeToVPUser) {
876d8563654SFlorian Hahn LLVMContext C;
877d8563654SFlorian Hahn
878d8563654SFlorian Hahn IntegerType *Int32 = IntegerType::get(C, 32);
879d8563654SFlorian Hahn auto *Phi = PHINode::Create(Int32, 1);
880d8563654SFlorian Hahn VPValue Op1;
881d8563654SFlorian Hahn VPValue Op2;
882d8563654SFlorian Hahn SmallVector<VPValue *, 4> Args;
883d8563654SFlorian Hahn Args.push_back(&Op1);
884d8563654SFlorian Hahn Args.push_back(&Op2);
885d8563654SFlorian Hahn VPBlendRecipe Recipe(Phi, Args);
886d8563654SFlorian Hahn EXPECT_TRUE(isa<VPUser>(&Recipe));
887d8563654SFlorian Hahn VPRecipeBase *BaseR = &Recipe;
888d8563654SFlorian Hahn EXPECT_TRUE(isa<VPUser>(BaseR));
889d8563654SFlorian Hahn delete Phi;
890d8563654SFlorian Hahn }
891d8563654SFlorian Hahn
TEST(VPRecipeTest,CastVPInterleaveRecipeToVPUser)892d8563654SFlorian Hahn TEST(VPRecipeTest, CastVPInterleaveRecipeToVPUser) {
893d8563654SFlorian Hahn LLVMContext C;
894d8563654SFlorian Hahn
895d8563654SFlorian Hahn VPValue Addr;
896d8563654SFlorian Hahn VPValue Mask;
897cd608dc8SFlorian Hahn InterleaveGroup<Instruction> IG(4, false, Align(4));
898cd608dc8SFlorian Hahn VPInterleaveRecipe Recipe(&IG, &Addr, {}, &Mask);
899d8563654SFlorian Hahn EXPECT_TRUE(isa<VPUser>(&Recipe));
900d8563654SFlorian Hahn VPRecipeBase *BaseR = &Recipe;
901d8563654SFlorian Hahn EXPECT_TRUE(isa<VPUser>(BaseR));
902f2508923SFlorian Hahn EXPECT_EQ(&Recipe, BaseR);
903d8563654SFlorian Hahn }
904d8563654SFlorian Hahn
TEST(VPRecipeTest,CastVPReplicateRecipeToVPUser)905d8563654SFlorian Hahn TEST(VPRecipeTest, CastVPReplicateRecipeToVPUser) {
906d8563654SFlorian Hahn LLVMContext C;
907d8563654SFlorian Hahn
908d8563654SFlorian Hahn VPValue Op1;
909d8563654SFlorian Hahn VPValue Op2;
910d8563654SFlorian Hahn SmallVector<VPValue *, 4> Args;
911d8563654SFlorian Hahn Args.push_back(&Op1);
912d8563654SFlorian Hahn Args.push_back(&Op2);
913d8563654SFlorian Hahn
914d8563654SFlorian Hahn VPReplicateRecipe Recipe(nullptr, make_range(Args.begin(), Args.end()), true,
915d8563654SFlorian Hahn false);
916d8563654SFlorian Hahn EXPECT_TRUE(isa<VPUser>(&Recipe));
917d8563654SFlorian Hahn VPRecipeBase *BaseR = &Recipe;
918d8563654SFlorian Hahn EXPECT_TRUE(isa<VPUser>(BaseR));
919d8563654SFlorian Hahn }
920d8563654SFlorian Hahn
TEST(VPRecipeTest,CastVPBranchOnMaskRecipeToVPUser)921d8563654SFlorian Hahn TEST(VPRecipeTest, CastVPBranchOnMaskRecipeToVPUser) {
922d8563654SFlorian Hahn LLVMContext C;
923d8563654SFlorian Hahn
924d8563654SFlorian Hahn VPValue Mask;
925d8563654SFlorian Hahn VPBranchOnMaskRecipe Recipe(&Mask);
926d8563654SFlorian Hahn EXPECT_TRUE(isa<VPUser>(&Recipe));
927d8563654SFlorian Hahn VPRecipeBase *BaseR = &Recipe;
928d8563654SFlorian Hahn EXPECT_TRUE(isa<VPUser>(BaseR));
929f2508923SFlorian Hahn EXPECT_EQ(&Recipe, BaseR);
930d8563654SFlorian Hahn }
931d8563654SFlorian Hahn
TEST(VPRecipeTest,CastVPWidenMemoryInstructionRecipeToVPUserAndVPDef)932f2508923SFlorian Hahn TEST(VPRecipeTest, CastVPWidenMemoryInstructionRecipeToVPUserAndVPDef) {
933d8563654SFlorian Hahn LLVMContext C;
934d8563654SFlorian Hahn
935d8563654SFlorian Hahn IntegerType *Int32 = IntegerType::get(C, 32);
936d8563654SFlorian Hahn PointerType *Int32Ptr = PointerType::get(Int32, 0);
937d8563654SFlorian Hahn auto *Load =
938d8563654SFlorian Hahn new LoadInst(Int32, UndefValue::get(Int32Ptr), "", false, Align(1));
939d8563654SFlorian Hahn VPValue Addr;
940d8563654SFlorian Hahn VPValue Mask;
9411156bd4fSGil Rapaport VPWidenMemoryInstructionRecipe Recipe(*Load, &Addr, &Mask, true, false);
942d8563654SFlorian Hahn EXPECT_TRUE(isa<VPUser>(&Recipe));
943d8563654SFlorian Hahn VPRecipeBase *BaseR = &Recipe;
944d8563654SFlorian Hahn EXPECT_TRUE(isa<VPUser>(BaseR));
945f2508923SFlorian Hahn EXPECT_EQ(&Recipe, BaseR);
946f2508923SFlorian Hahn
947a0e1313cSFlorian Hahn VPValue *VPV = Recipe.getVPSingleValue();
948f2508923SFlorian Hahn EXPECT_TRUE(isa<VPRecipeBase>(VPV->getDef()));
949f2508923SFlorian Hahn EXPECT_EQ(&Recipe, dyn_cast<VPRecipeBase>(VPV->getDef()));
950f2508923SFlorian Hahn
951d8563654SFlorian Hahn delete Load;
952d8563654SFlorian Hahn }
953d8563654SFlorian Hahn
TEST(VPRecipeTest,MayHaveSideEffectsAndMayReadWriteMemory)954e9d97d7dSFlorian Hahn TEST(VPRecipeTest, MayHaveSideEffectsAndMayReadWriteMemory) {
9556adebe3fSFlorian Hahn LLVMContext C;
9566adebe3fSFlorian Hahn IntegerType *Int1 = IntegerType::get(C, 1);
9576adebe3fSFlorian Hahn IntegerType *Int32 = IntegerType::get(C, 32);
9586adebe3fSFlorian Hahn PointerType *Int32Ptr = PointerType::get(Int32, 0);
9596adebe3fSFlorian Hahn
9606adebe3fSFlorian Hahn {
9616adebe3fSFlorian Hahn auto *AI = BinaryOperator::CreateAdd(UndefValue::get(Int32),
9626adebe3fSFlorian Hahn UndefValue::get(Int32));
9636adebe3fSFlorian Hahn VPValue Op1;
9646adebe3fSFlorian Hahn VPValue Op2;
9656adebe3fSFlorian Hahn SmallVector<VPValue *, 2> Args;
9666adebe3fSFlorian Hahn Args.push_back(&Op1);
9676adebe3fSFlorian Hahn Args.push_back(&Op1);
9686adebe3fSFlorian Hahn VPWidenRecipe Recipe(*AI, make_range(Args.begin(), Args.end()));
9696adebe3fSFlorian Hahn EXPECT_FALSE(Recipe.mayHaveSideEffects());
970e9d97d7dSFlorian Hahn EXPECT_FALSE(Recipe.mayReadFromMemory());
971e9d97d7dSFlorian Hahn EXPECT_FALSE(Recipe.mayWriteToMemory());
972e9d97d7dSFlorian Hahn EXPECT_FALSE(Recipe.mayReadOrWriteMemory());
9736adebe3fSFlorian Hahn delete AI;
9746adebe3fSFlorian Hahn }
9756adebe3fSFlorian Hahn
9766adebe3fSFlorian Hahn {
9776adebe3fSFlorian Hahn auto *SelectI = SelectInst::Create(
9786adebe3fSFlorian Hahn UndefValue::get(Int1), UndefValue::get(Int32), UndefValue::get(Int32));
9796adebe3fSFlorian Hahn VPValue Op1;
9806adebe3fSFlorian Hahn VPValue Op2;
9816adebe3fSFlorian Hahn VPValue Op3;
9826adebe3fSFlorian Hahn SmallVector<VPValue *, 4> Args;
9836adebe3fSFlorian Hahn Args.push_back(&Op1);
9846adebe3fSFlorian Hahn Args.push_back(&Op2);
9856adebe3fSFlorian Hahn Args.push_back(&Op3);
9866adebe3fSFlorian Hahn VPWidenSelectRecipe Recipe(*SelectI, make_range(Args.begin(), Args.end()),
9876adebe3fSFlorian Hahn false);
9886adebe3fSFlorian Hahn EXPECT_FALSE(Recipe.mayHaveSideEffects());
989e9d97d7dSFlorian Hahn EXPECT_FALSE(Recipe.mayReadFromMemory());
990e9d97d7dSFlorian Hahn EXPECT_FALSE(Recipe.mayWriteToMemory());
991e9d97d7dSFlorian Hahn EXPECT_FALSE(Recipe.mayReadOrWriteMemory());
9926adebe3fSFlorian Hahn delete SelectI;
9936adebe3fSFlorian Hahn }
9946adebe3fSFlorian Hahn
9956adebe3fSFlorian Hahn {
9966adebe3fSFlorian Hahn auto *GEP = GetElementPtrInst::Create(Int32, UndefValue::get(Int32Ptr),
9976adebe3fSFlorian Hahn UndefValue::get(Int32));
9986adebe3fSFlorian Hahn VPValue Op1;
9996adebe3fSFlorian Hahn VPValue Op2;
10006adebe3fSFlorian Hahn SmallVector<VPValue *, 4> Args;
10016adebe3fSFlorian Hahn Args.push_back(&Op1);
10026adebe3fSFlorian Hahn Args.push_back(&Op2);
10036adebe3fSFlorian Hahn VPWidenGEPRecipe Recipe(GEP, make_range(Args.begin(), Args.end()));
10046adebe3fSFlorian Hahn EXPECT_FALSE(Recipe.mayHaveSideEffects());
1005e9d97d7dSFlorian Hahn EXPECT_FALSE(Recipe.mayReadFromMemory());
1006e9d97d7dSFlorian Hahn EXPECT_FALSE(Recipe.mayWriteToMemory());
1007e9d97d7dSFlorian Hahn EXPECT_FALSE(Recipe.mayReadOrWriteMemory());
10086adebe3fSFlorian Hahn delete GEP;
10096adebe3fSFlorian Hahn }
10106adebe3fSFlorian Hahn
10116adebe3fSFlorian Hahn {
10126adebe3fSFlorian Hahn VPValue Mask;
10136adebe3fSFlorian Hahn VPBranchOnMaskRecipe Recipe(&Mask);
1014*96b7af68SFlorian Hahn EXPECT_TRUE(Recipe.mayHaveSideEffects());
1015e9d97d7dSFlorian Hahn EXPECT_FALSE(Recipe.mayReadFromMemory());
1016e9d97d7dSFlorian Hahn EXPECT_FALSE(Recipe.mayWriteToMemory());
1017e9d97d7dSFlorian Hahn EXPECT_FALSE(Recipe.mayReadOrWriteMemory());
10186adebe3fSFlorian Hahn }
10196adebe3fSFlorian Hahn
10206adebe3fSFlorian Hahn {
10216adebe3fSFlorian Hahn VPValue ChainOp;
10226adebe3fSFlorian Hahn VPValue VecOp;
10236adebe3fSFlorian Hahn VPValue CondOp;
10246adebe3fSFlorian Hahn VPReductionRecipe Recipe(nullptr, nullptr, &ChainOp, &CondOp, &VecOp,
10256adebe3fSFlorian Hahn nullptr);
10266adebe3fSFlorian Hahn EXPECT_FALSE(Recipe.mayHaveSideEffects());
1027e9d97d7dSFlorian Hahn EXPECT_FALSE(Recipe.mayReadFromMemory());
1028e9d97d7dSFlorian Hahn EXPECT_FALSE(Recipe.mayWriteToMemory());
1029e9d97d7dSFlorian Hahn EXPECT_FALSE(Recipe.mayReadOrWriteMemory());
10306adebe3fSFlorian Hahn }
10316adebe3fSFlorian Hahn
10326adebe3fSFlorian Hahn {
10336adebe3fSFlorian Hahn auto *Load =
10346adebe3fSFlorian Hahn new LoadInst(Int32, UndefValue::get(Int32Ptr), "", false, Align(1));
10356adebe3fSFlorian Hahn VPValue Addr;
10366adebe3fSFlorian Hahn VPValue Mask;
10371156bd4fSGil Rapaport VPWidenMemoryInstructionRecipe Recipe(*Load, &Addr, &Mask, true, false);
10386adebe3fSFlorian Hahn EXPECT_TRUE(Recipe.mayHaveSideEffects());
1039e9d97d7dSFlorian Hahn EXPECT_TRUE(Recipe.mayReadFromMemory());
1040e9d97d7dSFlorian Hahn EXPECT_FALSE(Recipe.mayWriteToMemory());
1041e9d97d7dSFlorian Hahn EXPECT_TRUE(Recipe.mayReadOrWriteMemory());
10426adebe3fSFlorian Hahn delete Load;
10436adebe3fSFlorian Hahn }
10446adebe3fSFlorian Hahn
10456adebe3fSFlorian Hahn {
1046e9d97d7dSFlorian Hahn auto *Store = new StoreInst(UndefValue::get(Int32),
1047e9d97d7dSFlorian Hahn UndefValue::get(Int32Ptr), false, Align(1));
1048e9d97d7dSFlorian Hahn VPValue Addr;
1049e9d97d7dSFlorian Hahn VPValue Mask;
1050e9d97d7dSFlorian Hahn VPValue StoredV;
10511156bd4fSGil Rapaport VPWidenMemoryInstructionRecipe Recipe(*Store, &Addr, &StoredV, &Mask, false,
10521156bd4fSGil Rapaport false);
1053e9d97d7dSFlorian Hahn EXPECT_TRUE(Recipe.mayHaveSideEffects());
1054e9d97d7dSFlorian Hahn EXPECT_FALSE(Recipe.mayReadFromMemory());
1055e9d97d7dSFlorian Hahn EXPECT_TRUE(Recipe.mayWriteToMemory());
1056e9d97d7dSFlorian Hahn EXPECT_TRUE(Recipe.mayReadOrWriteMemory());
1057e9d97d7dSFlorian Hahn delete Store;
1058e9d97d7dSFlorian Hahn }
1059e9d97d7dSFlorian Hahn
1060e9d97d7dSFlorian Hahn {
10616adebe3fSFlorian Hahn FunctionType *FTy = FunctionType::get(Int32, false);
10626adebe3fSFlorian Hahn auto *Call = CallInst::Create(FTy, UndefValue::get(FTy));
10636adebe3fSFlorian Hahn VPValue Op1;
10646adebe3fSFlorian Hahn VPValue Op2;
10656adebe3fSFlorian Hahn SmallVector<VPValue *, 2> Args;
10666adebe3fSFlorian Hahn Args.push_back(&Op1);
10676adebe3fSFlorian Hahn Args.push_back(&Op2);
10686adebe3fSFlorian Hahn VPWidenCallRecipe Recipe(*Call, make_range(Args.begin(), Args.end()));
10696adebe3fSFlorian Hahn EXPECT_TRUE(Recipe.mayHaveSideEffects());
1070e9d97d7dSFlorian Hahn EXPECT_TRUE(Recipe.mayReadFromMemory());
1071e9d97d7dSFlorian Hahn EXPECT_TRUE(Recipe.mayWriteToMemory());
1072e9d97d7dSFlorian Hahn EXPECT_TRUE(Recipe.mayReadOrWriteMemory());
10736adebe3fSFlorian Hahn delete Call;
10746adebe3fSFlorian Hahn }
10756adebe3fSFlorian Hahn
10766adebe3fSFlorian Hahn // The initial implementation is conservative with respect to VPInstructions.
10776adebe3fSFlorian Hahn {
10786adebe3fSFlorian Hahn VPValue Op1;
10796adebe3fSFlorian Hahn VPValue Op2;
1080e9d97d7dSFlorian Hahn VPInstruction VPInst(Instruction::Add, {&Op1, &Op2});
1081e9d97d7dSFlorian Hahn VPRecipeBase &Recipe = VPInst;
10826adebe3fSFlorian Hahn EXPECT_TRUE(Recipe.mayHaveSideEffects());
1083e9d97d7dSFlorian Hahn EXPECT_TRUE(Recipe.mayReadFromMemory());
1084e9d97d7dSFlorian Hahn EXPECT_TRUE(Recipe.mayWriteToMemory());
1085e9d97d7dSFlorian Hahn EXPECT_TRUE(Recipe.mayReadOrWriteMemory());
10866adebe3fSFlorian Hahn }
10876adebe3fSFlorian Hahn }
10886adebe3fSFlorian Hahn
108992205cb2SAndrei Elovikov #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
TEST(VPRecipeTest,dump)1090eb0371e4SFlorian Hahn TEST(VPRecipeTest, dump) {
1091eb0371e4SFlorian Hahn VPlan Plan;
1092eb0371e4SFlorian Hahn VPBasicBlock *VPBB1 = new VPBasicBlock();
1093eb0371e4SFlorian Hahn Plan.setEntry(VPBB1);
1094eb0371e4SFlorian Hahn
1095eb0371e4SFlorian Hahn LLVMContext C;
1096eb0371e4SFlorian Hahn
1097eb0371e4SFlorian Hahn IntegerType *Int32 = IntegerType::get(C, 32);
1098eb0371e4SFlorian Hahn auto *AI =
1099eb0371e4SFlorian Hahn BinaryOperator::CreateAdd(UndefValue::get(Int32), UndefValue::get(Int32));
1100eb0371e4SFlorian Hahn AI->setName("a");
1101eb0371e4SFlorian Hahn SmallVector<VPValue *, 2> Args;
11022c14cdf8SFlorian Hahn VPValue *ExtVPV1 = Plan.getOrAddExternalDef(ConstantInt::get(Int32, 1));
11032c14cdf8SFlorian Hahn VPValue *ExtVPV2 = Plan.getOrAddExternalDef(ConstantInt::get(Int32, 2));
1104eb0371e4SFlorian Hahn Args.push_back(ExtVPV1);
1105eb0371e4SFlorian Hahn Args.push_back(ExtVPV2);
1106eb0371e4SFlorian Hahn VPWidenRecipe *WidenR =
1107eb0371e4SFlorian Hahn new VPWidenRecipe(*AI, make_range(Args.begin(), Args.end()));
1108eb0371e4SFlorian Hahn VPBB1->appendRecipe(WidenR);
1109eb0371e4SFlorian Hahn
1110eb0371e4SFlorian Hahn {
1111eb0371e4SFlorian Hahn // Use EXPECT_EXIT to capture stderr and compare against expected output.
1112eb0371e4SFlorian Hahn //
1113eb0371e4SFlorian Hahn // Test VPValue::dump().
1114eb0371e4SFlorian Hahn VPValue *VPV = WidenR;
1115eb0371e4SFlorian Hahn EXPECT_EXIT(
1116eb0371e4SFlorian Hahn {
1117eb0371e4SFlorian Hahn VPV->dump();
1118eb0371e4SFlorian Hahn exit(0);
1119eb0371e4SFlorian Hahn },
11202c14cdf8SFlorian Hahn testing::ExitedWithCode(0), "WIDEN ir<%a> = add ir<1>, ir<2>");
1121eb0371e4SFlorian Hahn
1122eb0371e4SFlorian Hahn // Test VPRecipeBase::dump().
1123eb0371e4SFlorian Hahn VPRecipeBase *R = WidenR;
1124eb0371e4SFlorian Hahn EXPECT_EXIT(
1125eb0371e4SFlorian Hahn {
1126eb0371e4SFlorian Hahn R->dump();
1127eb0371e4SFlorian Hahn exit(0);
1128eb0371e4SFlorian Hahn },
11292c14cdf8SFlorian Hahn testing::ExitedWithCode(0), "WIDEN ir<%a> = add ir<1>, ir<2>");
1130eb0371e4SFlorian Hahn
1131eb0371e4SFlorian Hahn // Test VPDef::dump().
1132eb0371e4SFlorian Hahn VPDef *D = WidenR;
1133eb0371e4SFlorian Hahn EXPECT_EXIT(
1134eb0371e4SFlorian Hahn {
1135eb0371e4SFlorian Hahn D->dump();
1136eb0371e4SFlorian Hahn exit(0);
1137eb0371e4SFlorian Hahn },
11382c14cdf8SFlorian Hahn testing::ExitedWithCode(0), "WIDEN ir<%a> = add ir<1>, ir<2>");
1139eb0371e4SFlorian Hahn }
1140eb0371e4SFlorian Hahn
1141eb0371e4SFlorian Hahn delete AI;
1142eb0371e4SFlorian Hahn }
114392205cb2SAndrei Elovikov #endif
1144eb0371e4SFlorian Hahn
TEST(VPRecipeTest,CastVPReductionRecipeToVPUser)1145ad5b83ddSFlorian Hahn TEST(VPRecipeTest, CastVPReductionRecipeToVPUser) {
1146ad5b83ddSFlorian Hahn LLVMContext C;
1147ad5b83ddSFlorian Hahn
1148ad5b83ddSFlorian Hahn VPValue ChainOp;
1149ad5b83ddSFlorian Hahn VPValue VecOp;
1150ad5b83ddSFlorian Hahn VPValue CondOp;
1151ab93c18cSSanjay Patel VPReductionRecipe Recipe(nullptr, nullptr, &ChainOp, &CondOp, &VecOp,
1152ad5b83ddSFlorian Hahn nullptr);
1153ad5b83ddSFlorian Hahn EXPECT_TRUE(isa<VPUser>(&Recipe));
1154ad5b83ddSFlorian Hahn VPRecipeBase *BaseR = &Recipe;
1155ad5b83ddSFlorian Hahn EXPECT_TRUE(isa<VPUser>(BaseR));
1156ad5b83ddSFlorian Hahn }
1157ad5b83ddSFlorian Hahn
115885fe5c93SFlorian Hahn struct VPDoubleValueDef : public VPRecipeBase {
VPDoubleValueDefllvm::__anonf34d9e050111::VPDoubleValueDef115985fe5c93SFlorian Hahn VPDoubleValueDef(ArrayRef<VPValue *> Operands) : VPRecipeBase(99, Operands) {
116052f3714dSFlorian Hahn new VPValue(nullptr, this);
116152f3714dSFlorian Hahn new VPValue(nullptr, this);
116252f3714dSFlorian Hahn }
1163f2508923SFlorian Hahn
executellvm::__anonf34d9e050111::VPDoubleValueDef1164f2508923SFlorian Hahn void execute(struct VPTransformState &State) override{};
116592205cb2SAndrei Elovikov #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
printllvm::__anonf34d9e050111::VPDoubleValueDef1166f2508923SFlorian Hahn void print(raw_ostream &O, const Twine &Indent,
1167f2508923SFlorian Hahn VPSlotTracker &SlotTracker) const override {}
116892205cb2SAndrei Elovikov #endif
116952f3714dSFlorian Hahn };
117052f3714dSFlorian Hahn
TEST(VPDoubleValueDefTest,traverseUseLists)117152f3714dSFlorian Hahn TEST(VPDoubleValueDefTest, traverseUseLists) {
117252f3714dSFlorian Hahn // Check that the def-use chains of a multi-def can be traversed in both
117352f3714dSFlorian Hahn // directions.
117452f3714dSFlorian Hahn
117552f3714dSFlorian Hahn // Create a new VPDef which defines 2 values and has 2 operands.
117652f3714dSFlorian Hahn VPInstruction Op0(20, {});
117752f3714dSFlorian Hahn VPInstruction Op1(30, {});
117852f3714dSFlorian Hahn VPDoubleValueDef DoubleValueDef({&Op0, &Op1});
117952f3714dSFlorian Hahn
118052f3714dSFlorian Hahn // Create a new users of the defined values.
118152f3714dSFlorian Hahn VPInstruction I1(
118252f3714dSFlorian Hahn 1, {DoubleValueDef.getVPValue(0), DoubleValueDef.getVPValue(1)});
118352f3714dSFlorian Hahn VPInstruction I2(2, {DoubleValueDef.getVPValue(0)});
118452f3714dSFlorian Hahn VPInstruction I3(3, {DoubleValueDef.getVPValue(1)});
118552f3714dSFlorian Hahn
118652f3714dSFlorian Hahn // Check operands of the VPDef (traversing upwards).
118752f3714dSFlorian Hahn SmallVector<VPValue *, 4> DoubleOperands(DoubleValueDef.op_begin(),
118852f3714dSFlorian Hahn DoubleValueDef.op_end());
118952f3714dSFlorian Hahn EXPECT_EQ(2u, DoubleOperands.size());
119052f3714dSFlorian Hahn EXPECT_EQ(&Op0, DoubleOperands[0]);
119152f3714dSFlorian Hahn EXPECT_EQ(&Op1, DoubleOperands[1]);
119252f3714dSFlorian Hahn
119352f3714dSFlorian Hahn // Check users of the defined values (traversing downwards).
119452f3714dSFlorian Hahn SmallVector<VPUser *, 4> DoubleValueDefV0Users(
119552f3714dSFlorian Hahn DoubleValueDef.getVPValue(0)->user_begin(),
119652f3714dSFlorian Hahn DoubleValueDef.getVPValue(0)->user_end());
119752f3714dSFlorian Hahn EXPECT_EQ(2u, DoubleValueDefV0Users.size());
119852f3714dSFlorian Hahn EXPECT_EQ(&I1, DoubleValueDefV0Users[0]);
119952f3714dSFlorian Hahn EXPECT_EQ(&I2, DoubleValueDefV0Users[1]);
120052f3714dSFlorian Hahn
120152f3714dSFlorian Hahn SmallVector<VPUser *, 4> DoubleValueDefV1Users(
120252f3714dSFlorian Hahn DoubleValueDef.getVPValue(1)->user_begin(),
120352f3714dSFlorian Hahn DoubleValueDef.getVPValue(1)->user_end());
120452f3714dSFlorian Hahn EXPECT_EQ(2u, DoubleValueDefV1Users.size());
120552f3714dSFlorian Hahn EXPECT_EQ(&I1, DoubleValueDefV1Users[0]);
120652f3714dSFlorian Hahn EXPECT_EQ(&I3, DoubleValueDefV1Users[1]);
120752f3714dSFlorian Hahn
120852f3714dSFlorian Hahn // Now check that we can get the right VPDef for each defined value.
120952f3714dSFlorian Hahn EXPECT_EQ(&DoubleValueDef, I1.getOperand(0)->getDef());
121052f3714dSFlorian Hahn EXPECT_EQ(&DoubleValueDef, I1.getOperand(1)->getDef());
121152f3714dSFlorian Hahn EXPECT_EQ(&DoubleValueDef, I2.getOperand(0)->getDef());
121252f3714dSFlorian Hahn EXPECT_EQ(&DoubleValueDef, I3.getOperand(0)->getDef());
121352f3714dSFlorian Hahn }
121452f3714dSFlorian Hahn
12157591e4e9SFlorian Hahn } // namespace
12167591e4e9SFlorian Hahn } // namespace llvm
1217