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 = 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 delete ScalarHeader; 47 } 48 49 TEST(VPVerifierTest, VPInstructionUseBeforeDefDifferentBB) { 50 VPInstruction *DefI = new VPInstruction(Instruction::Add, {}); 51 VPInstruction *UseI = new VPInstruction(Instruction::Sub, {DefI}); 52 auto *CanIV = new VPCanonicalIVPHIRecipe(UseI, {}); 53 VPInstruction *BranchOnCond = 54 new VPInstruction(VPInstruction::BranchOnCond, {CanIV}); 55 56 VPBasicBlock *VPPH = new VPBasicBlock("ph"); 57 VPBasicBlock *VPBB1 = new VPBasicBlock(); 58 VPBasicBlock *VPBB2 = new VPBasicBlock(); 59 60 VPBB1->appendRecipe(UseI); 61 VPBB2->appendRecipe(CanIV); 62 VPBB2->appendRecipe(DefI); 63 VPBB2->appendRecipe(BranchOnCond); 64 65 VPRegionBlock *R1 = new VPRegionBlock(VPBB2, VPBB2, "R1"); 66 VPBlockUtils::connectBlocks(VPBB1, R1); 67 68 auto TC = std::make_unique<VPValue>(); 69 LLVMContext C; 70 auto *ScalarHeader = BasicBlock::Create(C, ""); 71 VPIRBasicBlock *ScalarHeaderVPBB = new VPIRBasicBlock(ScalarHeader); 72 VPBlockUtils::connectBlocks(R1, ScalarHeaderVPBB); 73 VPlan Plan(VPPH, &*TC, VPBB1, ScalarHeaderVPBB); 74 75 #if GTEST_HAS_STREAM_REDIRECTION 76 ::testing::internal::CaptureStderr(); 77 #endif 78 EXPECT_FALSE(verifyVPlanIsValid(Plan)); 79 #if GTEST_HAS_STREAM_REDIRECTION 80 EXPECT_STREQ("Use before def!\n", 81 ::testing::internal::GetCapturedStderr().c_str()); 82 #endif 83 delete ScalarHeader; 84 } 85 86 TEST(VPVerifierTest, VPBlendUseBeforeDefDifferentBB) { 87 LLVMContext C; 88 IntegerType *Int32 = IntegerType::get(C, 32); 89 auto *Phi = PHINode::Create(Int32, 1); 90 91 VPInstruction *I1 = new VPInstruction(Instruction::Add, {}); 92 VPInstruction *DefI = new VPInstruction(Instruction::Add, {}); 93 auto *CanIV = new VPCanonicalIVPHIRecipe(I1, {}); 94 VPInstruction *BranchOnCond = 95 new VPInstruction(VPInstruction::BranchOnCond, {CanIV}); 96 auto *Blend = new VPBlendRecipe(Phi, {DefI}); 97 98 VPBasicBlock *VPPH = new VPBasicBlock("ph"); 99 VPBasicBlock *VPBB1 = new VPBasicBlock(); 100 VPBasicBlock *VPBB2 = new VPBasicBlock(); 101 VPBasicBlock *VPBB3 = new VPBasicBlock(); 102 VPBasicBlock *VPBB4 = new VPBasicBlock(); 103 104 VPBB1->appendRecipe(I1); 105 VPBB2->appendRecipe(CanIV); 106 VPBB3->appendRecipe(Blend); 107 VPBB4->appendRecipe(DefI); 108 VPBB4->appendRecipe(BranchOnCond); 109 110 VPBlockUtils::connectBlocks(VPBB2, VPBB3); 111 VPBlockUtils::connectBlocks(VPBB3, VPBB4); 112 VPRegionBlock *R1 = new VPRegionBlock(VPBB2, VPBB4, "R1"); 113 VPBlockUtils::connectBlocks(VPBB1, R1); 114 VPBB3->setParent(R1); 115 116 auto TC = std::make_unique<VPValue>(); 117 auto *ScalarHeader = BasicBlock::Create(C, ""); 118 VPIRBasicBlock *ScalarHeaderVPBB = new VPIRBasicBlock(ScalarHeader); 119 VPBlockUtils::connectBlocks(R1, ScalarHeaderVPBB); 120 VPlan Plan(VPPH, &*TC, VPBB1, ScalarHeaderVPBB); 121 122 #if GTEST_HAS_STREAM_REDIRECTION 123 ::testing::internal::CaptureStderr(); 124 #endif 125 EXPECT_FALSE(verifyVPlanIsValid(Plan)); 126 #if GTEST_HAS_STREAM_REDIRECTION 127 EXPECT_STREQ("Use before def!\n", 128 ::testing::internal::GetCapturedStderr().c_str()); 129 #endif 130 131 delete Phi; 132 delete ScalarHeader; 133 } 134 135 TEST(VPVerifierTest, DuplicateSuccessorsOutsideRegion) { 136 VPInstruction *I1 = new VPInstruction(Instruction::Add, {}); 137 auto *CanIV = new VPCanonicalIVPHIRecipe(I1, {}); 138 VPInstruction *BranchOnCond = 139 new VPInstruction(VPInstruction::BranchOnCond, {CanIV}); 140 VPInstruction *BranchOnCond2 = 141 new VPInstruction(VPInstruction::BranchOnCond, {I1}); 142 143 VPBasicBlock *VPPH = new VPBasicBlock("ph"); 144 VPBasicBlock *VPBB1 = new VPBasicBlock(); 145 VPBasicBlock *VPBB2 = new VPBasicBlock(); 146 147 VPBB1->appendRecipe(I1); 148 VPBB1->appendRecipe(BranchOnCond2); 149 VPBB2->appendRecipe(CanIV); 150 VPBB2->appendRecipe(BranchOnCond); 151 152 VPRegionBlock *R1 = new VPRegionBlock(VPBB2, VPBB2, "R1"); 153 VPBlockUtils::connectBlocks(VPBB1, R1); 154 VPBlockUtils::connectBlocks(VPBB1, R1); 155 156 auto TC = std::make_unique<VPValue>(); 157 LLVMContext C; 158 auto *ScalarHeader = BasicBlock::Create(C, ""); 159 VPIRBasicBlock *ScalarHeaderVPBB = new VPIRBasicBlock(ScalarHeader); 160 VPBlockUtils::connectBlocks(R1, ScalarHeaderVPBB); 161 VPlan Plan(VPPH, &*TC, VPBB1, ScalarHeaderVPBB); 162 163 #if GTEST_HAS_STREAM_REDIRECTION 164 ::testing::internal::CaptureStderr(); 165 #endif 166 EXPECT_FALSE(verifyVPlanIsValid(Plan)); 167 #if GTEST_HAS_STREAM_REDIRECTION 168 EXPECT_STREQ("Multiple instances of the same successor.\n", 169 ::testing::internal::GetCapturedStderr().c_str()); 170 #endif 171 delete ScalarHeader; 172 } 173 174 TEST(VPVerifierTest, DuplicateSuccessorsInsideRegion) { 175 VPInstruction *I1 = new VPInstruction(Instruction::Add, {}); 176 auto *CanIV = new VPCanonicalIVPHIRecipe(I1, {}); 177 VPInstruction *BranchOnCond = 178 new VPInstruction(VPInstruction::BranchOnCond, {CanIV}); 179 VPInstruction *BranchOnCond2 = 180 new VPInstruction(VPInstruction::BranchOnCond, {I1}); 181 182 VPBasicBlock *VPPH = new VPBasicBlock("ph"); 183 VPBasicBlock *VPBB1 = new VPBasicBlock(); 184 VPBasicBlock *VPBB2 = new VPBasicBlock(); 185 VPBasicBlock *VPBB3 = new VPBasicBlock(); 186 187 VPBB1->appendRecipe(I1); 188 VPBB2->appendRecipe(CanIV); 189 VPBB2->appendRecipe(BranchOnCond2); 190 VPBB3->appendRecipe(BranchOnCond); 191 192 VPBlockUtils::connectBlocks(VPBB2, VPBB3); 193 VPBlockUtils::connectBlocks(VPBB2, VPBB3); 194 VPRegionBlock *R1 = new VPRegionBlock(VPBB2, VPBB3, "R1"); 195 VPBlockUtils::connectBlocks(VPBB1, R1); 196 VPBB3->setParent(R1); 197 198 auto TC = std::make_unique<VPValue>(); 199 LLVMContext C; 200 auto *ScalarHeader = BasicBlock::Create(C, ""); 201 VPIRBasicBlock *ScalarHeaderVPBB = new VPIRBasicBlock(ScalarHeader); 202 VPBlockUtils::connectBlocks(R1, ScalarHeaderVPBB); 203 VPlan Plan(VPPH, &*TC, VPBB1, ScalarHeaderVPBB); 204 205 #if GTEST_HAS_STREAM_REDIRECTION 206 ::testing::internal::CaptureStderr(); 207 #endif 208 EXPECT_FALSE(verifyVPlanIsValid(Plan)); 209 #if GTEST_HAS_STREAM_REDIRECTION 210 EXPECT_STREQ("Multiple instances of the same successor.\n", 211 ::testing::internal::GetCapturedStderr().c_str()); 212 #endif 213 delete ScalarHeader; 214 } 215 216 TEST(VPVerifierTest, BlockOutsideRegionWithParent) { 217 VPBasicBlock *VPPH = new VPBasicBlock("ph"); 218 VPBasicBlock *VPBB1 = new VPBasicBlock(); 219 VPBasicBlock *VPBB2 = new VPBasicBlock(); 220 221 VPInstruction *DefI = new VPInstruction(Instruction::Add, {}); 222 VPInstruction *BranchOnCond = 223 new VPInstruction(VPInstruction::BranchOnCond, {DefI}); 224 225 VPBB1->appendRecipe(DefI); 226 VPBB2->appendRecipe(BranchOnCond); 227 228 VPRegionBlock *R1 = new VPRegionBlock(VPBB2, VPBB2, "R1"); 229 VPBlockUtils::connectBlocks(VPBB1, R1); 230 VPBB1->setParent(R1); 231 232 auto TC = std::make_unique<VPValue>(); 233 LLVMContext C; 234 auto *ScalarHeader = BasicBlock::Create(C, ""); 235 VPIRBasicBlock *ScalarHeaderVPBB = new VPIRBasicBlock(ScalarHeader); 236 VPBlockUtils::connectBlocks(R1, ScalarHeaderVPBB); 237 VPlan Plan(VPPH, &*TC, VPBB1, ScalarHeaderVPBB); 238 239 #if GTEST_HAS_STREAM_REDIRECTION 240 ::testing::internal::CaptureStderr(); 241 #endif 242 EXPECT_FALSE(verifyVPlanIsValid(Plan)); 243 #if GTEST_HAS_STREAM_REDIRECTION 244 EXPECT_STREQ("Predecessor is not in the same region.\n", 245 ::testing::internal::GetCapturedStderr().c_str()); 246 #endif 247 delete ScalarHeader; 248 } 249 250 } // namespace 251