1 //===- llvm/unittests/Transforms/Vectorize/VPlanVerifierTest.cpp ----------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "../lib/Transforms/Vectorize/VPlanVerifier.h" 10 #include "../lib/Transforms/Vectorize/VPlan.h" 11 #include "llvm/IR/Instruction.h" 12 #include "llvm/IR/Instructions.h" 13 #include "gtest/gtest.h" 14 15 using namespace llvm; 16 17 namespace { 18 TEST(VPVerifierTest, VPInstructionUseBeforeDefSameBB) { 19 VPInstruction *DefI = new VPInstruction(Instruction::Add, {}); 20 VPInstruction *UseI = new VPInstruction(Instruction::Sub, {DefI}); 21 22 VPBasicBlock *VPPH = new VPBasicBlock("ph"); 23 VPBasicBlock *VPBB1 = new VPBasicBlock(); 24 VPBB1->appendRecipe(UseI); 25 VPBB1->appendRecipe(DefI); 26 27 auto TC = std::make_unique<VPValue>(); 28 VPBasicBlock *VPBB2 = new VPBasicBlock(); 29 VPRegionBlock *R1 = new VPRegionBlock(VPBB2, VPBB2, "R1"); 30 VPBlockUtils::connectBlocks(VPBB1, R1); 31 32 LLVMContext C; 33 auto ScalarHeader = std::make_unique<BasicBlock *>(BasicBlock::Create(C, "")); 34 VPIRBasicBlock *ScalarHeaderVPBB = new VPIRBasicBlock(*ScalarHeader); 35 VPBlockUtils::connectBlocks(R1, ScalarHeaderVPBB); 36 VPlan Plan(VPPH, &*TC, VPBB1, ScalarHeaderVPBB); 37 38 #if GTEST_HAS_STREAM_REDIRECTION 39 ::testing::internal::CaptureStderr(); 40 #endif 41 EXPECT_FALSE(verifyVPlanIsValid(Plan)); 42 #if GTEST_HAS_STREAM_REDIRECTION 43 EXPECT_STREQ("Use before def!\n", 44 ::testing::internal::GetCapturedStderr().c_str()); 45 #endif 46 } 47 48 TEST(VPVerifierTest, VPInstructionUseBeforeDefDifferentBB) { 49 VPInstruction *DefI = new VPInstruction(Instruction::Add, {}); 50 VPInstruction *UseI = new VPInstruction(Instruction::Sub, {DefI}); 51 auto *CanIV = new VPCanonicalIVPHIRecipe(UseI, {}); 52 VPInstruction *BranchOnCond = 53 new VPInstruction(VPInstruction::BranchOnCond, {CanIV}); 54 55 VPBasicBlock *VPPH = new VPBasicBlock("ph"); 56 VPBasicBlock *VPBB1 = new VPBasicBlock(); 57 VPBasicBlock *VPBB2 = new VPBasicBlock(); 58 59 VPBB1->appendRecipe(UseI); 60 VPBB2->appendRecipe(CanIV); 61 VPBB2->appendRecipe(DefI); 62 VPBB2->appendRecipe(BranchOnCond); 63 64 VPRegionBlock *R1 = new VPRegionBlock(VPBB2, VPBB2, "R1"); 65 VPBlockUtils::connectBlocks(VPBB1, R1); 66 67 auto TC = std::make_unique<VPValue>(); 68 LLVMContext C; 69 auto ScalarHeader = std::make_unique<BasicBlock *>(BasicBlock::Create(C, "")); 70 VPIRBasicBlock *ScalarHeaderVPBB = new VPIRBasicBlock(*ScalarHeader); 71 VPBlockUtils::connectBlocks(R1, ScalarHeaderVPBB); 72 VPlan Plan(VPPH, &*TC, VPBB1, ScalarHeaderVPBB); 73 74 #if GTEST_HAS_STREAM_REDIRECTION 75 ::testing::internal::CaptureStderr(); 76 #endif 77 EXPECT_FALSE(verifyVPlanIsValid(Plan)); 78 #if GTEST_HAS_STREAM_REDIRECTION 79 EXPECT_STREQ("Use before def!\n", 80 ::testing::internal::GetCapturedStderr().c_str()); 81 #endif 82 } 83 84 TEST(VPVerifierTest, VPBlendUseBeforeDefDifferentBB) { 85 LLVMContext C; 86 IntegerType *Int32 = IntegerType::get(C, 32); 87 auto *Phi = PHINode::Create(Int32, 1); 88 89 VPInstruction *I1 = new VPInstruction(Instruction::Add, {}); 90 VPInstruction *DefI = new VPInstruction(Instruction::Add, {}); 91 auto *CanIV = new VPCanonicalIVPHIRecipe(I1, {}); 92 VPInstruction *BranchOnCond = 93 new VPInstruction(VPInstruction::BranchOnCond, {CanIV}); 94 auto *Blend = new VPBlendRecipe(Phi, {DefI}); 95 96 VPBasicBlock *VPPH = new VPBasicBlock("ph"); 97 VPBasicBlock *VPBB1 = new VPBasicBlock(); 98 VPBasicBlock *VPBB2 = new VPBasicBlock(); 99 VPBasicBlock *VPBB3 = new VPBasicBlock(); 100 VPBasicBlock *VPBB4 = new VPBasicBlock(); 101 102 VPBB1->appendRecipe(I1); 103 VPBB2->appendRecipe(CanIV); 104 VPBB3->appendRecipe(Blend); 105 VPBB4->appendRecipe(DefI); 106 VPBB4->appendRecipe(BranchOnCond); 107 108 VPBlockUtils::connectBlocks(VPBB2, VPBB3); 109 VPBlockUtils::connectBlocks(VPBB3, VPBB4); 110 VPRegionBlock *R1 = new VPRegionBlock(VPBB2, VPBB4, "R1"); 111 VPBlockUtils::connectBlocks(VPBB1, R1); 112 VPBB3->setParent(R1); 113 114 auto TC = std::make_unique<VPValue>(); 115 auto ScalarHeader = std::make_unique<BasicBlock *>(BasicBlock::Create(C, "")); 116 VPIRBasicBlock *ScalarHeaderVPBB = new VPIRBasicBlock(*ScalarHeader); 117 VPBlockUtils::connectBlocks(R1, ScalarHeaderVPBB); 118 VPlan Plan(VPPH, &*TC, VPBB1, ScalarHeaderVPBB); 119 120 #if GTEST_HAS_STREAM_REDIRECTION 121 ::testing::internal::CaptureStderr(); 122 #endif 123 EXPECT_FALSE(verifyVPlanIsValid(Plan)); 124 #if GTEST_HAS_STREAM_REDIRECTION 125 EXPECT_STREQ("Use before def!\n", 126 ::testing::internal::GetCapturedStderr().c_str()); 127 #endif 128 129 delete Phi; 130 } 131 132 TEST(VPVerifierTest, DuplicateSuccessorsOutsideRegion) { 133 VPInstruction *I1 = new VPInstruction(Instruction::Add, {}); 134 auto *CanIV = new VPCanonicalIVPHIRecipe(I1, {}); 135 VPInstruction *BranchOnCond = 136 new VPInstruction(VPInstruction::BranchOnCond, {CanIV}); 137 VPInstruction *BranchOnCond2 = 138 new VPInstruction(VPInstruction::BranchOnCond, {I1}); 139 140 VPBasicBlock *VPPH = new VPBasicBlock("ph"); 141 VPBasicBlock *VPBB1 = new VPBasicBlock(); 142 VPBasicBlock *VPBB2 = new VPBasicBlock(); 143 144 VPBB1->appendRecipe(I1); 145 VPBB1->appendRecipe(BranchOnCond2); 146 VPBB2->appendRecipe(CanIV); 147 VPBB2->appendRecipe(BranchOnCond); 148 149 VPRegionBlock *R1 = new VPRegionBlock(VPBB2, VPBB2, "R1"); 150 VPBlockUtils::connectBlocks(VPBB1, R1); 151 VPBlockUtils::connectBlocks(VPBB1, R1); 152 153 auto TC = std::make_unique<VPValue>(); 154 LLVMContext C; 155 auto ScalarHeader = std::make_unique<BasicBlock *>(BasicBlock::Create(C, "")); 156 VPIRBasicBlock *ScalarHeaderVPBB = new VPIRBasicBlock(*ScalarHeader); 157 VPBlockUtils::connectBlocks(R1, ScalarHeaderVPBB); 158 VPlan Plan(VPPH, &*TC, VPBB1, ScalarHeaderVPBB); 159 160 #if GTEST_HAS_STREAM_REDIRECTION 161 ::testing::internal::CaptureStderr(); 162 #endif 163 EXPECT_FALSE(verifyVPlanIsValid(Plan)); 164 #if GTEST_HAS_STREAM_REDIRECTION 165 EXPECT_STREQ("Multiple instances of the same successor.\n", 166 ::testing::internal::GetCapturedStderr().c_str()); 167 #endif 168 } 169 170 TEST(VPVerifierTest, DuplicateSuccessorsInsideRegion) { 171 VPInstruction *I1 = new VPInstruction(Instruction::Add, {}); 172 auto *CanIV = new VPCanonicalIVPHIRecipe(I1, {}); 173 VPInstruction *BranchOnCond = 174 new VPInstruction(VPInstruction::BranchOnCond, {CanIV}); 175 VPInstruction *BranchOnCond2 = 176 new VPInstruction(VPInstruction::BranchOnCond, {I1}); 177 178 VPBasicBlock *VPPH = new VPBasicBlock("ph"); 179 VPBasicBlock *VPBB1 = new VPBasicBlock(); 180 VPBasicBlock *VPBB2 = new VPBasicBlock(); 181 VPBasicBlock *VPBB3 = new VPBasicBlock(); 182 183 VPBB1->appendRecipe(I1); 184 VPBB2->appendRecipe(CanIV); 185 VPBB2->appendRecipe(BranchOnCond2); 186 VPBB3->appendRecipe(BranchOnCond); 187 188 VPBlockUtils::connectBlocks(VPBB2, VPBB3); 189 VPBlockUtils::connectBlocks(VPBB2, VPBB3); 190 VPRegionBlock *R1 = new VPRegionBlock(VPBB2, VPBB3, "R1"); 191 VPBlockUtils::connectBlocks(VPBB1, R1); 192 VPBB3->setParent(R1); 193 194 auto TC = std::make_unique<VPValue>(); 195 LLVMContext C; 196 auto ScalarHeader = std::make_unique<BasicBlock *>(BasicBlock::Create(C, "")); 197 VPIRBasicBlock *ScalarHeaderVPBB = new VPIRBasicBlock(*ScalarHeader); 198 VPBlockUtils::connectBlocks(R1, ScalarHeaderVPBB); 199 VPlan Plan(VPPH, &*TC, VPBB1, ScalarHeaderVPBB); 200 201 #if GTEST_HAS_STREAM_REDIRECTION 202 ::testing::internal::CaptureStderr(); 203 #endif 204 EXPECT_FALSE(verifyVPlanIsValid(Plan)); 205 #if GTEST_HAS_STREAM_REDIRECTION 206 EXPECT_STREQ("Multiple instances of the same successor.\n", 207 ::testing::internal::GetCapturedStderr().c_str()); 208 #endif 209 } 210 211 TEST(VPVerifierTest, BlockOutsideRegionWithParent) { 212 VPBasicBlock *VPPH = new VPBasicBlock("ph"); 213 VPBasicBlock *VPBB1 = new VPBasicBlock(); 214 VPBasicBlock *VPBB2 = new VPBasicBlock(); 215 216 VPInstruction *DefI = new VPInstruction(Instruction::Add, {}); 217 VPInstruction *BranchOnCond = 218 new VPInstruction(VPInstruction::BranchOnCond, {DefI}); 219 220 VPBB1->appendRecipe(DefI); 221 VPBB2->appendRecipe(BranchOnCond); 222 223 VPRegionBlock *R1 = new VPRegionBlock(VPBB2, VPBB2, "R1"); 224 VPBlockUtils::connectBlocks(VPBB1, R1); 225 VPBB1->setParent(R1); 226 227 auto TC = std::make_unique<VPValue>(); 228 LLVMContext C; 229 auto ScalarHeader = std::make_unique<BasicBlock *>(BasicBlock::Create(C, "")); 230 VPIRBasicBlock *ScalarHeaderVPBB = new VPIRBasicBlock(*ScalarHeader); 231 VPBlockUtils::connectBlocks(R1, ScalarHeaderVPBB); 232 VPlan Plan(VPPH, &*TC, VPBB1, ScalarHeaderVPBB); 233 234 #if GTEST_HAS_STREAM_REDIRECTION 235 ::testing::internal::CaptureStderr(); 236 #endif 237 EXPECT_FALSE(verifyVPlanIsValid(Plan)); 238 #if GTEST_HAS_STREAM_REDIRECTION 239 EXPECT_STREQ("Predecessor is not in the same region.\n", 240 ::testing::internal::GetCapturedStderr().c_str()); 241 #endif 242 } 243 244 } // namespace 245