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