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