1dc8e2ea9SFlorian Hahn //===- llvm/unittests/Transforms/Vectorize/VPlanVerifierTest.cpp ----------===// 2dc8e2ea9SFlorian Hahn // 3dc8e2ea9SFlorian Hahn // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4dc8e2ea9SFlorian Hahn // See https://llvm.org/LICENSE.txt for license information. 5dc8e2ea9SFlorian Hahn // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6dc8e2ea9SFlorian Hahn // 7dc8e2ea9SFlorian Hahn //===----------------------------------------------------------------------===// 8dc8e2ea9SFlorian Hahn 9dc8e2ea9SFlorian Hahn #include "../lib/Transforms/Vectorize/VPlanVerifier.h" 10dc8e2ea9SFlorian Hahn #include "../lib/Transforms/Vectorize/VPlan.h" 118caeb2e0SFlorian Hahn #include "VPlanTestBase.h" 12dc8e2ea9SFlorian Hahn #include "llvm/IR/Instruction.h" 13dc8e2ea9SFlorian Hahn #include "llvm/IR/Instructions.h" 14dc8e2ea9SFlorian Hahn #include "gtest/gtest.h" 15dc8e2ea9SFlorian Hahn 16dc8e2ea9SFlorian Hahn using namespace llvm; 17dc8e2ea9SFlorian Hahn 188caeb2e0SFlorian Hahn using VPVerifierTest = VPlanTestBase; 198caeb2e0SFlorian Hahn 20dc8e2ea9SFlorian Hahn namespace { 218caeb2e0SFlorian Hahn TEST_F(VPVerifierTest, VPInstructionUseBeforeDefSameBB) { 228caeb2e0SFlorian Hahn VPlan &Plan = getPlan(); 23*5c15caa8SLuke Lau VPValue *Zero = Plan.getOrAddLiveIn(ConstantInt::get(Type::getInt32Ty(C), 0)); 24*5c15caa8SLuke Lau VPInstruction *DefI = new VPInstruction(Instruction::Add, {Zero}); 25dc8e2ea9SFlorian Hahn VPInstruction *UseI = new VPInstruction(Instruction::Sub, {DefI}); 26*5c15caa8SLuke Lau auto *CanIV = new VPCanonicalIVPHIRecipe(Zero, {}); 27dc8e2ea9SFlorian Hahn 288caeb2e0SFlorian Hahn VPBasicBlock *VPBB1 = Plan.getEntry(); 29dc8e2ea9SFlorian Hahn VPBB1->appendRecipe(UseI); 30dc8e2ea9SFlorian Hahn VPBB1->appendRecipe(DefI); 31dc8e2ea9SFlorian Hahn 3216d19aaeSFlorian Hahn VPBasicBlock *VPBB2 = Plan.createVPBasicBlock(""); 33*5c15caa8SLuke Lau VPBB2->appendRecipe(CanIV); 3416d19aaeSFlorian Hahn VPRegionBlock *R1 = Plan.createVPRegionBlock(VPBB2, VPBB2, "R1"); 359923d29cSFlorian Hahn VPBlockUtils::connectBlocks(VPBB1, R1); 368caeb2e0SFlorian Hahn VPBlockUtils::connectBlocks(R1, Plan.getScalarHeader()); 37dc8e2ea9SFlorian Hahn 38dc8e2ea9SFlorian Hahn #if GTEST_HAS_STREAM_REDIRECTION 39dc8e2ea9SFlorian Hahn ::testing::internal::CaptureStderr(); 40dc8e2ea9SFlorian Hahn #endif 419923d29cSFlorian Hahn EXPECT_FALSE(verifyVPlanIsValid(Plan)); 42dc8e2ea9SFlorian Hahn #if GTEST_HAS_STREAM_REDIRECTION 43dc8e2ea9SFlorian Hahn EXPECT_STREQ("Use before def!\n", 44dc8e2ea9SFlorian Hahn ::testing::internal::GetCapturedStderr().c_str()); 45dc8e2ea9SFlorian Hahn #endif 46dc8e2ea9SFlorian Hahn } 47dc8e2ea9SFlorian Hahn 488caeb2e0SFlorian Hahn TEST_F(VPVerifierTest, VPInstructionUseBeforeDefDifferentBB) { 498caeb2e0SFlorian Hahn VPlan &Plan = getPlan(); 50*5c15caa8SLuke Lau VPValue *Zero = Plan.getOrAddLiveIn(ConstantInt::get(Type::getInt32Ty(C), 0)); 51*5c15caa8SLuke Lau VPInstruction *DefI = new VPInstruction(Instruction::Add, {Zero}); 52dc8e2ea9SFlorian Hahn VPInstruction *UseI = new VPInstruction(Instruction::Sub, {DefI}); 53*5c15caa8SLuke Lau auto *CanIV = new VPCanonicalIVPHIRecipe(Zero, {}); 54dc8e2ea9SFlorian Hahn VPInstruction *BranchOnCond = 55dc8e2ea9SFlorian Hahn new VPInstruction(VPInstruction::BranchOnCond, {CanIV}); 56dc8e2ea9SFlorian Hahn 578caeb2e0SFlorian Hahn VPBasicBlock *VPBB1 = Plan.getEntry(); 5816d19aaeSFlorian Hahn VPBasicBlock *VPBB2 = Plan.createVPBasicBlock(""); 59dc8e2ea9SFlorian Hahn 60dc8e2ea9SFlorian Hahn VPBB1->appendRecipe(UseI); 61dc8e2ea9SFlorian Hahn VPBB2->appendRecipe(CanIV); 62dc8e2ea9SFlorian Hahn VPBB2->appendRecipe(DefI); 63dc8e2ea9SFlorian Hahn VPBB2->appendRecipe(BranchOnCond); 64dc8e2ea9SFlorian Hahn 6516d19aaeSFlorian Hahn VPRegionBlock *R1 = Plan.createVPRegionBlock(VPBB2, VPBB2, "R1"); 66dc8e2ea9SFlorian Hahn VPBlockUtils::connectBlocks(VPBB1, R1); 678caeb2e0SFlorian Hahn VPBlockUtils::connectBlocks(R1, Plan.getScalarHeader()); 68dc8e2ea9SFlorian Hahn 69dc8e2ea9SFlorian Hahn #if GTEST_HAS_STREAM_REDIRECTION 70dc8e2ea9SFlorian Hahn ::testing::internal::CaptureStderr(); 71dc8e2ea9SFlorian Hahn #endif 729923d29cSFlorian Hahn EXPECT_FALSE(verifyVPlanIsValid(Plan)); 73dc8e2ea9SFlorian Hahn #if GTEST_HAS_STREAM_REDIRECTION 74b6b3d20dSFlorian Hahn EXPECT_STREQ("Use before def!\n", 75b6b3d20dSFlorian Hahn ::testing::internal::GetCapturedStderr().c_str()); 76dc8e2ea9SFlorian Hahn #endif 77dc8e2ea9SFlorian Hahn } 78dc8e2ea9SFlorian Hahn 798caeb2e0SFlorian Hahn TEST_F(VPVerifierTest, VPBlendUseBeforeDefDifferentBB) { 80*5c15caa8SLuke Lau VPlan &Plan = getPlan(); 81dc8e2ea9SFlorian Hahn IntegerType *Int32 = IntegerType::get(C, 32); 82dc8e2ea9SFlorian Hahn auto *Phi = PHINode::Create(Int32, 1); 83*5c15caa8SLuke Lau VPValue *Zero = Plan.getOrAddLiveIn(ConstantInt::get(Int32, 0)); 84dc8e2ea9SFlorian Hahn 85*5c15caa8SLuke Lau VPInstruction *DefI = new VPInstruction(Instruction::Add, {Zero}); 86*5c15caa8SLuke Lau auto *CanIV = new VPCanonicalIVPHIRecipe(Zero, {}); 87dc8e2ea9SFlorian Hahn VPInstruction *BranchOnCond = 88dc8e2ea9SFlorian Hahn new VPInstruction(VPInstruction::BranchOnCond, {CanIV}); 89dc8e2ea9SFlorian Hahn auto *Blend = new VPBlendRecipe(Phi, {DefI}); 90dc8e2ea9SFlorian Hahn 918caeb2e0SFlorian Hahn VPBasicBlock *VPBB1 = Plan.getEntry(); 9216d19aaeSFlorian Hahn VPBasicBlock *VPBB2 = Plan.createVPBasicBlock(""); 9316d19aaeSFlorian Hahn VPBasicBlock *VPBB3 = Plan.createVPBasicBlock(""); 9416d19aaeSFlorian Hahn VPBasicBlock *VPBB4 = Plan.createVPBasicBlock(""); 95dc8e2ea9SFlorian Hahn 96dc8e2ea9SFlorian Hahn VPBB2->appendRecipe(CanIV); 97dc8e2ea9SFlorian Hahn VPBB3->appendRecipe(Blend); 98dc8e2ea9SFlorian Hahn VPBB4->appendRecipe(DefI); 99dc8e2ea9SFlorian Hahn VPBB4->appendRecipe(BranchOnCond); 100dc8e2ea9SFlorian Hahn 101dc8e2ea9SFlorian Hahn VPBlockUtils::connectBlocks(VPBB2, VPBB3); 102dc8e2ea9SFlorian Hahn VPBlockUtils::connectBlocks(VPBB3, VPBB4); 10316d19aaeSFlorian Hahn VPRegionBlock *R1 = Plan.createVPRegionBlock(VPBB2, VPBB4, "R1"); 104dc8e2ea9SFlorian Hahn VPBlockUtils::connectBlocks(VPBB1, R1); 1059923d29cSFlorian Hahn VPBB3->setParent(R1); 106dc8e2ea9SFlorian Hahn 1078caeb2e0SFlorian Hahn VPBlockUtils::connectBlocks(R1, Plan.getScalarHeader()); 108dc8e2ea9SFlorian Hahn 109dc8e2ea9SFlorian Hahn #if GTEST_HAS_STREAM_REDIRECTION 110dc8e2ea9SFlorian Hahn ::testing::internal::CaptureStderr(); 111dc8e2ea9SFlorian Hahn #endif 1129923d29cSFlorian Hahn EXPECT_FALSE(verifyVPlanIsValid(Plan)); 113dc8e2ea9SFlorian Hahn #if GTEST_HAS_STREAM_REDIRECTION 114b6b3d20dSFlorian Hahn EXPECT_STREQ("Use before def!\n", 115b6b3d20dSFlorian Hahn ::testing::internal::GetCapturedStderr().c_str()); 116dc8e2ea9SFlorian Hahn #endif 117ca8b0b4aSFlorian Hahn 118ca8b0b4aSFlorian Hahn delete Phi; 119dc8e2ea9SFlorian Hahn } 1209923d29cSFlorian Hahn 1218caeb2e0SFlorian Hahn TEST_F(VPVerifierTest, DuplicateSuccessorsOutsideRegion) { 122*5c15caa8SLuke Lau VPlan &Plan = getPlan(); 123*5c15caa8SLuke Lau VPValue *Zero = Plan.getOrAddLiveIn(ConstantInt::get(Type::getInt32Ty(C), 0)); 124*5c15caa8SLuke Lau VPInstruction *I1 = new VPInstruction(Instruction::Add, {Zero}); 125*5c15caa8SLuke Lau auto *CanIV = new VPCanonicalIVPHIRecipe(Zero, {}); 1269923d29cSFlorian Hahn VPInstruction *BranchOnCond = 1279923d29cSFlorian Hahn new VPInstruction(VPInstruction::BranchOnCond, {CanIV}); 1289923d29cSFlorian Hahn VPInstruction *BranchOnCond2 = 1299923d29cSFlorian Hahn new VPInstruction(VPInstruction::BranchOnCond, {I1}); 1309923d29cSFlorian Hahn 1318caeb2e0SFlorian Hahn VPBasicBlock *VPBB1 = Plan.getEntry(); 13216d19aaeSFlorian Hahn VPBasicBlock *VPBB2 = Plan.createVPBasicBlock(""); 1339923d29cSFlorian Hahn 1349923d29cSFlorian Hahn VPBB1->appendRecipe(I1); 1359923d29cSFlorian Hahn VPBB1->appendRecipe(BranchOnCond2); 1369923d29cSFlorian Hahn VPBB2->appendRecipe(CanIV); 1379923d29cSFlorian Hahn VPBB2->appendRecipe(BranchOnCond); 1389923d29cSFlorian Hahn 13916d19aaeSFlorian Hahn VPRegionBlock *R1 = Plan.createVPRegionBlock(VPBB2, VPBB2, "R1"); 1409923d29cSFlorian Hahn VPBlockUtils::connectBlocks(VPBB1, R1); 1419923d29cSFlorian Hahn VPBlockUtils::connectBlocks(VPBB1, R1); 1429923d29cSFlorian Hahn 1438caeb2e0SFlorian Hahn VPBlockUtils::connectBlocks(R1, Plan.getScalarHeader()); 1449923d29cSFlorian Hahn 1459923d29cSFlorian Hahn #if GTEST_HAS_STREAM_REDIRECTION 1469923d29cSFlorian Hahn ::testing::internal::CaptureStderr(); 1479923d29cSFlorian Hahn #endif 1489923d29cSFlorian Hahn EXPECT_FALSE(verifyVPlanIsValid(Plan)); 1499923d29cSFlorian Hahn #if GTEST_HAS_STREAM_REDIRECTION 1509923d29cSFlorian Hahn EXPECT_STREQ("Multiple instances of the same successor.\n", 1519923d29cSFlorian Hahn ::testing::internal::GetCapturedStderr().c_str()); 1529923d29cSFlorian Hahn #endif 1539923d29cSFlorian Hahn } 1549923d29cSFlorian Hahn 1558caeb2e0SFlorian Hahn TEST_F(VPVerifierTest, DuplicateSuccessorsInsideRegion) { 156*5c15caa8SLuke Lau VPlan &Plan = getPlan(); 157*5c15caa8SLuke Lau VPValue *Zero = Plan.getOrAddLiveIn(ConstantInt::get(Type::getInt32Ty(C), 0)); 158*5c15caa8SLuke Lau VPInstruction *I1 = new VPInstruction(Instruction::Add, {Zero}); 159*5c15caa8SLuke Lau auto *CanIV = new VPCanonicalIVPHIRecipe(Zero, {}); 1609923d29cSFlorian Hahn VPInstruction *BranchOnCond = 1619923d29cSFlorian Hahn new VPInstruction(VPInstruction::BranchOnCond, {CanIV}); 1629923d29cSFlorian Hahn VPInstruction *BranchOnCond2 = 1639923d29cSFlorian Hahn new VPInstruction(VPInstruction::BranchOnCond, {I1}); 1649923d29cSFlorian Hahn 1658caeb2e0SFlorian Hahn VPBasicBlock *VPBB1 = Plan.getEntry(); 16616d19aaeSFlorian Hahn VPBasicBlock *VPBB2 = Plan.createVPBasicBlock(""); 16716d19aaeSFlorian Hahn VPBasicBlock *VPBB3 = Plan.createVPBasicBlock(""); 1689923d29cSFlorian Hahn 1699923d29cSFlorian Hahn VPBB1->appendRecipe(I1); 1709923d29cSFlorian Hahn VPBB2->appendRecipe(CanIV); 1719923d29cSFlorian Hahn VPBB2->appendRecipe(BranchOnCond2); 1729923d29cSFlorian Hahn VPBB3->appendRecipe(BranchOnCond); 1739923d29cSFlorian Hahn 1749923d29cSFlorian Hahn VPBlockUtils::connectBlocks(VPBB2, VPBB3); 1759923d29cSFlorian Hahn VPBlockUtils::connectBlocks(VPBB2, VPBB3); 17616d19aaeSFlorian Hahn VPRegionBlock *R1 = Plan.createVPRegionBlock(VPBB2, VPBB3, "R1"); 1779923d29cSFlorian Hahn VPBlockUtils::connectBlocks(VPBB1, R1); 1789923d29cSFlorian Hahn VPBB3->setParent(R1); 1799923d29cSFlorian Hahn 1808caeb2e0SFlorian Hahn VPBlockUtils::connectBlocks(R1, Plan.getScalarHeader()); 1819923d29cSFlorian Hahn 1829923d29cSFlorian Hahn #if GTEST_HAS_STREAM_REDIRECTION 1839923d29cSFlorian Hahn ::testing::internal::CaptureStderr(); 1849923d29cSFlorian Hahn #endif 1859923d29cSFlorian Hahn EXPECT_FALSE(verifyVPlanIsValid(Plan)); 1869923d29cSFlorian Hahn #if GTEST_HAS_STREAM_REDIRECTION 1879923d29cSFlorian Hahn EXPECT_STREQ("Multiple instances of the same successor.\n", 1889923d29cSFlorian Hahn ::testing::internal::GetCapturedStderr().c_str()); 1899923d29cSFlorian Hahn #endif 1909923d29cSFlorian Hahn } 1919923d29cSFlorian Hahn 1928caeb2e0SFlorian Hahn TEST_F(VPVerifierTest, BlockOutsideRegionWithParent) { 1938caeb2e0SFlorian Hahn VPlan &Plan = getPlan(); 194*5c15caa8SLuke Lau 1958caeb2e0SFlorian Hahn VPBasicBlock *VPBB1 = Plan.getEntry(); 19616d19aaeSFlorian Hahn VPBasicBlock *VPBB2 = Plan.createVPBasicBlock(""); 1979923d29cSFlorian Hahn 198*5c15caa8SLuke Lau VPValue *Zero = Plan.getOrAddLiveIn(ConstantInt::get(Type::getInt32Ty(C), 0)); 199*5c15caa8SLuke Lau auto *CanIV = new VPCanonicalIVPHIRecipe(Zero, {}); 200*5c15caa8SLuke Lau VPBB2->appendRecipe(CanIV); 201*5c15caa8SLuke Lau 202*5c15caa8SLuke Lau VPInstruction *DefI = new VPInstruction(Instruction::Add, {Zero}); 2039923d29cSFlorian Hahn VPInstruction *BranchOnCond = 2049923d29cSFlorian Hahn new VPInstruction(VPInstruction::BranchOnCond, {DefI}); 2059923d29cSFlorian Hahn 2069923d29cSFlorian Hahn VPBB1->appendRecipe(DefI); 2079923d29cSFlorian Hahn VPBB2->appendRecipe(BranchOnCond); 2089923d29cSFlorian Hahn 20916d19aaeSFlorian Hahn VPRegionBlock *R1 = Plan.createVPRegionBlock(VPBB2, VPBB2, "R1"); 2109923d29cSFlorian Hahn VPBlockUtils::connectBlocks(VPBB1, R1); 2119923d29cSFlorian Hahn 2128caeb2e0SFlorian Hahn VPBlockUtils::connectBlocks(R1, Plan.getScalarHeader()); 2136c8f41d3SFlorian Hahn VPBB1->setParent(R1); 2149923d29cSFlorian Hahn 2159923d29cSFlorian Hahn #if GTEST_HAS_STREAM_REDIRECTION 2169923d29cSFlorian Hahn ::testing::internal::CaptureStderr(); 2179923d29cSFlorian Hahn #endif 2189923d29cSFlorian Hahn EXPECT_FALSE(verifyVPlanIsValid(Plan)); 2199923d29cSFlorian Hahn #if GTEST_HAS_STREAM_REDIRECTION 2209923d29cSFlorian Hahn EXPECT_STREQ("Predecessor is not in the same region.\n", 2219923d29cSFlorian Hahn ::testing::internal::GetCapturedStderr().c_str()); 2229923d29cSFlorian Hahn #endif 2239923d29cSFlorian Hahn } 2249923d29cSFlorian Hahn 225dc8e2ea9SFlorian Hahn } // namespace 226