1 //===- llvm/unittests/Transforms/Vectorize/VPlanTest.cpp - VPlan tests ----===// 2 // 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "../lib/Transforms/Vectorize/VPlan.h" 11 #include "llvm/IR/Instruction.h" 12 #include "llvm/IR/Instructions.h" 13 #include "gtest/gtest.h" 14 15 namespace llvm { 16 namespace { 17 18 #define CHECK_ITERATOR(Range1, ...) \ 19 do { \ 20 std::vector<VPInstruction *> Tmp = {__VA_ARGS__}; \ 21 EXPECT_EQ((size_t)std::distance(Range1.begin(), Range1.end()), \ 22 Tmp.size()); \ 23 for (auto Pair : zip(Range1, make_range(Tmp.begin(), Tmp.end()))) \ 24 EXPECT_EQ(&std::get<0>(Pair), std::get<1>(Pair)); \ 25 } while (0) 26 27 TEST(VPInstructionTest, insertBefore) { 28 VPInstruction *I1 = new VPInstruction(0, {}); 29 VPInstruction *I2 = new VPInstruction(1, {}); 30 VPInstruction *I3 = new VPInstruction(2, {}); 31 32 VPBasicBlock VPBB1; 33 VPBB1.appendRecipe(I1); 34 35 I2->insertBefore(I1); 36 CHECK_ITERATOR(VPBB1, I2, I1); 37 38 I3->insertBefore(I2); 39 CHECK_ITERATOR(VPBB1, I3, I2, I1); 40 } 41 42 TEST(VPInstructionTest, eraseFromParent) { 43 VPInstruction *I1 = new VPInstruction(0, {}); 44 VPInstruction *I2 = new VPInstruction(1, {}); 45 VPInstruction *I3 = new VPInstruction(2, {}); 46 47 VPBasicBlock VPBB1; 48 VPBB1.appendRecipe(I1); 49 VPBB1.appendRecipe(I2); 50 VPBB1.appendRecipe(I3); 51 52 I2->eraseFromParent(); 53 CHECK_ITERATOR(VPBB1, I1, I3); 54 55 I1->eraseFromParent(); 56 CHECK_ITERATOR(VPBB1, I3); 57 58 I3->eraseFromParent(); 59 EXPECT_TRUE(VPBB1.empty()); 60 } 61 62 TEST(VPInstructionTest, moveAfter) { 63 VPInstruction *I1 = new VPInstruction(0, {}); 64 VPInstruction *I2 = new VPInstruction(1, {}); 65 VPInstruction *I3 = new VPInstruction(2, {}); 66 67 VPBasicBlock VPBB1; 68 VPBB1.appendRecipe(I1); 69 VPBB1.appendRecipe(I2); 70 VPBB1.appendRecipe(I3); 71 72 I1->moveAfter(I2); 73 74 CHECK_ITERATOR(VPBB1, I2, I1, I3); 75 76 VPInstruction *I4 = new VPInstruction(4, {}); 77 VPInstruction *I5 = new VPInstruction(5, {}); 78 VPBasicBlock VPBB2; 79 VPBB2.appendRecipe(I4); 80 VPBB2.appendRecipe(I5); 81 82 I3->moveAfter(I4); 83 84 CHECK_ITERATOR(VPBB1, I2, I1); 85 CHECK_ITERATOR(VPBB2, I4, I3, I5); 86 EXPECT_EQ(I3->getParent(), I4->getParent()); 87 } 88 89 TEST(VPBasicBlockTest, getPlan) { 90 { 91 VPBasicBlock *VPBB1 = new VPBasicBlock(); 92 VPBasicBlock *VPBB2 = new VPBasicBlock(); 93 VPBasicBlock *VPBB3 = new VPBasicBlock(); 94 VPBasicBlock *VPBB4 = new VPBasicBlock(); 95 96 // VPBB1 97 // / \ 98 // VPBB2 VPBB3 99 // \ / 100 // VPBB4 101 VPBlockUtils::connectBlocks(VPBB1, VPBB2); 102 VPBlockUtils::connectBlocks(VPBB1, VPBB3); 103 VPBlockUtils::connectBlocks(VPBB2, VPBB4); 104 VPBlockUtils::connectBlocks(VPBB3, VPBB4); 105 106 VPlan Plan; 107 Plan.setEntry(VPBB1); 108 109 EXPECT_EQ(&Plan, VPBB1->getPlan()); 110 EXPECT_EQ(&Plan, VPBB2->getPlan()); 111 EXPECT_EQ(&Plan, VPBB3->getPlan()); 112 EXPECT_EQ(&Plan, VPBB4->getPlan()); 113 } 114 115 { 116 // Region block is entry into VPlan. 117 VPBasicBlock *R1BB1 = new VPBasicBlock(); 118 VPBasicBlock *R1BB2 = new VPBasicBlock(); 119 VPRegionBlock *R1 = new VPRegionBlock(R1BB1, R1BB2, "R1"); 120 VPBlockUtils::connectBlocks(R1BB1, R1BB2); 121 122 VPlan Plan; 123 Plan.setEntry(R1); 124 EXPECT_EQ(&Plan, R1->getPlan()); 125 EXPECT_EQ(&Plan, R1BB1->getPlan()); 126 EXPECT_EQ(&Plan, R1BB2->getPlan()); 127 } 128 129 { 130 // VPBasicBlock is the entry into the VPlan, followed by a region. 131 VPBasicBlock *R1BB1 = new VPBasicBlock(); 132 VPBasicBlock *R1BB2 = new VPBasicBlock(); 133 VPRegionBlock *R1 = new VPRegionBlock(R1BB1, R1BB2, "R1"); 134 VPBlockUtils::connectBlocks(R1BB1, R1BB2); 135 136 VPBasicBlock *VPBB1 = new VPBasicBlock(); 137 VPBlockUtils::connectBlocks(VPBB1, R1); 138 139 VPlan Plan; 140 Plan.setEntry(VPBB1); 141 EXPECT_EQ(&Plan, VPBB1->getPlan()); 142 EXPECT_EQ(&Plan, R1->getPlan()); 143 EXPECT_EQ(&Plan, R1BB1->getPlan()); 144 EXPECT_EQ(&Plan, R1BB2->getPlan()); 145 } 146 147 { 148 VPBasicBlock *R1BB1 = new VPBasicBlock(); 149 VPBasicBlock *R1BB2 = new VPBasicBlock(); 150 VPRegionBlock *R1 = new VPRegionBlock(R1BB1, R1BB2, "R1"); 151 VPBlockUtils::connectBlocks(R1BB1, R1BB2); 152 153 VPBasicBlock *R2BB1 = new VPBasicBlock(); 154 VPBasicBlock *R2BB2 = new VPBasicBlock(); 155 VPRegionBlock *R2 = new VPRegionBlock(R2BB1, R2BB2, "R2"); 156 VPBlockUtils::connectBlocks(R2BB1, R2BB2); 157 158 VPBasicBlock *VPBB1 = new VPBasicBlock(); 159 VPBlockUtils::connectBlocks(VPBB1, R1); 160 VPBlockUtils::connectBlocks(VPBB1, R2); 161 162 VPBasicBlock *VPBB2 = new VPBasicBlock(); 163 VPBlockUtils::connectBlocks(R1, VPBB2); 164 VPBlockUtils::connectBlocks(R2, VPBB2); 165 166 VPlan Plan; 167 Plan.setEntry(VPBB1); 168 EXPECT_EQ(&Plan, VPBB1->getPlan()); 169 EXPECT_EQ(&Plan, R1->getPlan()); 170 EXPECT_EQ(&Plan, R1BB1->getPlan()); 171 EXPECT_EQ(&Plan, R1BB2->getPlan()); 172 EXPECT_EQ(&Plan, R2->getPlan()); 173 EXPECT_EQ(&Plan, R2BB1->getPlan()); 174 EXPECT_EQ(&Plan, R2BB2->getPlan()); 175 EXPECT_EQ(&Plan, VPBB2->getPlan()); 176 } 177 } 178 179 } // namespace 180 } // namespace llvm 181