brintos

brintos / llvm-project-archived public Read only

0
0
Text · 13.6 KiB · ec8f06a Raw
404 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "../lib/Transforms/Vectorize/VPlanVerifier.h"10#include "../lib/Transforms/Vectorize/VPlan.h"11#include "../lib/Transforms/Vectorize/VPlanCFG.h"12#include "VPlanTestBase.h"13#include "llvm/IR/Instruction.h"14#include "llvm/IR/Instructions.h"15#include "gtest/gtest.h"16 17using namespace llvm;18 19using VPVerifierTest = VPlanTestBase;20 21namespace {22TEST_F(VPVerifierTest, VPInstructionUseBeforeDefSameBB) {23  VPlan &Plan = getPlan();24  VPValue *Zero = Plan.getConstantInt(32, 0);25  VPInstruction *DefI = new VPInstruction(Instruction::Add, {Zero, Zero});26  VPInstruction *UseI = new VPInstruction(Instruction::Sub, {DefI, Zero});27  auto *CanIV = new VPCanonicalIVPHIRecipe(Zero, {});28 29  VPBasicBlock *VPBB1 = Plan.getEntry();30  VPBB1->appendRecipe(UseI);31  VPBB1->appendRecipe(DefI);32 33  VPBasicBlock *VPBB2 = Plan.createVPBasicBlock("");34  VPBB2->appendRecipe(CanIV);35  VPRegionBlock *R1 = Plan.createLoopRegion("R1", VPBB2, VPBB2);36  VPBlockUtils::connectBlocks(VPBB1, R1);37  VPBlockUtils::connectBlocks(R1, Plan.getScalarHeader());38 39#if GTEST_HAS_STREAM_REDIRECTION40  ::testing::internal::CaptureStderr();41#endif42  EXPECT_FALSE(verifyVPlanIsValid(Plan));43#if GTEST_HAS_STREAM_REDIRECTION44#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)45  EXPECT_STREQ("Use before def!\n"46               "  EMIT vp<%1> = sub vp<%2>, ir<0>\n"47               "  before\n"48               "  EMIT vp<%2> = add ir<0>, ir<0>\n",49               ::testing::internal::GetCapturedStderr().c_str());50#else51  EXPECT_STREQ("Use before def!\n",52               ::testing::internal::GetCapturedStderr().c_str());53#endif54#endif55}56 57TEST_F(VPVerifierTest, VPInstructionUseBeforeDefDifferentBB) {58  VPlan &Plan = getPlan();59  VPValue *Zero = Plan.getConstantInt(32, 0);60  VPInstruction *DefI = new VPInstruction(Instruction::Add, {Zero, Zero});61  VPInstruction *UseI = new VPInstruction(Instruction::Sub, {DefI, Zero});62  auto *CanIV = new VPCanonicalIVPHIRecipe(Zero, {});63  VPInstruction *BranchOnCond =64      new VPInstruction(VPInstruction::BranchOnCond, {CanIV});65 66  VPBasicBlock *VPBB1 = Plan.getEntry();67  VPBasicBlock *VPBB2 = Plan.createVPBasicBlock("");68 69  VPBB1->appendRecipe(UseI);70  VPBB2->appendRecipe(CanIV);71  VPBB2->appendRecipe(DefI);72  VPBB2->appendRecipe(BranchOnCond);73 74  VPRegionBlock *R1 = Plan.createLoopRegion("R1", VPBB2, VPBB2);75  VPBlockUtils::connectBlocks(VPBB1, R1);76  VPBlockUtils::connectBlocks(R1, Plan.getScalarHeader());77 78#if GTEST_HAS_STREAM_REDIRECTION79  ::testing::internal::CaptureStderr();80#endif81  EXPECT_FALSE(verifyVPlanIsValid(Plan));82#if GTEST_HAS_STREAM_REDIRECTION83#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)84  EXPECT_STREQ("Use before def!\n"85               "  EMIT vp<%1> = sub vp<%3>, ir<0>\n"86               "  before\n"87               "  EMIT vp<%3> = add ir<0>, ir<0>\n",88               ::testing::internal::GetCapturedStderr().c_str());89#else90  EXPECT_STREQ("Use before def!\n",91               ::testing::internal::GetCapturedStderr().c_str());92#endif93#endif94}95 96TEST_F(VPVerifierTest, VPBlendUseBeforeDefDifferentBB) {97  VPlan &Plan = getPlan();98  IntegerType *Int32 = IntegerType::get(C, 32);99  auto *Phi = PHINode::Create(Int32, 1);100  VPValue *Zero = Plan.getOrAddLiveIn(ConstantInt::get(Int32, 0));101 102  VPInstruction *DefI = new VPInstruction(Instruction::Add, {Zero, Zero});103  auto *CanIV = new VPCanonicalIVPHIRecipe(Zero, {});104  VPInstruction *BranchOnCond =105      new VPInstruction(VPInstruction::BranchOnCond, {CanIV});106  auto *Blend = new VPBlendRecipe(Phi, {DefI}, {});107 108  VPBasicBlock *VPBB1 = Plan.getEntry();109  VPBasicBlock *VPBB2 = Plan.createVPBasicBlock("");110  VPBasicBlock *VPBB3 = Plan.createVPBasicBlock("");111  VPBasicBlock *VPBB4 = Plan.createVPBasicBlock("");112 113  VPBB2->appendRecipe(CanIV);114  VPBB3->appendRecipe(Blend);115  VPBB4->appendRecipe(DefI);116  VPBB4->appendRecipe(BranchOnCond);117 118  VPBlockUtils::connectBlocks(VPBB2, VPBB3);119  VPBlockUtils::connectBlocks(VPBB3, VPBB4);120  VPRegionBlock *R1 = Plan.createLoopRegion("R1", VPBB2, VPBB4);121  VPBlockUtils::connectBlocks(VPBB1, R1);122  VPBB3->setParent(R1);123 124  VPBlockUtils::connectBlocks(R1, Plan.getScalarHeader());125 126#if GTEST_HAS_STREAM_REDIRECTION127  ::testing::internal::CaptureStderr();128#endif129  EXPECT_FALSE(verifyVPlanIsValid(Plan));130#if GTEST_HAS_STREAM_REDIRECTION131#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)132  EXPECT_STREQ("Use before def!\n"133               "  BLEND ir<<badref>> = vp<%2>\n"134               "  before\n"135               "  EMIT vp<%2> = add ir<0>, ir<0>\n",136               ::testing::internal::GetCapturedStderr().c_str());137#else138  EXPECT_STREQ("Use before def!\n",139               ::testing::internal::GetCapturedStderr().c_str());140#endif141#endif142 143  delete Phi;144}145 146TEST_F(VPVerifierTest, VPPhiIncomingValueDoesntDominateIncomingBlock) {147  VPlan &Plan = getPlan();148  IntegerType *Int32 = IntegerType::get(C, 32);149  VPValue *Zero = Plan.getOrAddLiveIn(ConstantInt::get(Int32, 0));150 151  VPBasicBlock *VPBB1 = Plan.getEntry();152  VPBasicBlock *VPBB2 = Plan.createVPBasicBlock("");153  VPBasicBlock *VPBB3 = Plan.createVPBasicBlock("");154  VPBasicBlock *VPBB4 = Plan.createVPBasicBlock("");155 156  VPInstruction *DefI = new VPInstruction(Instruction::Add, {Zero, Zero});157  VPPhi *Phi = new VPPhi({DefI}, {});158  VPBB2->appendRecipe(Phi);159  VPBB2->appendRecipe(DefI);160  auto *CanIV = new VPCanonicalIVPHIRecipe(Zero, {});161  VPBB3->appendRecipe(CanIV);162 163  VPRegionBlock *R1 = Plan.createLoopRegion("R1", VPBB3, VPBB3);164  VPBlockUtils::connectBlocks(VPBB1, VPBB2);165  VPBlockUtils::connectBlocks(VPBB2, R1);166  VPBlockUtils::connectBlocks(VPBB4, Plan.getScalarHeader());167#if GTEST_HAS_STREAM_REDIRECTION168  ::testing::internal::CaptureStderr();169#endif170  EXPECT_FALSE(verifyVPlanIsValid(Plan));171#if GTEST_HAS_STREAM_REDIRECTION172#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)173  EXPECT_STREQ("Incoming def does not dominate incoming block!\n"174               "  EMIT vp<%2> = add ir<0>, ir<0>\n"175               "  does not dominate preheader for\n"176               "  EMIT-SCALAR vp<%1> = phi [ vp<%2>, preheader ]",177               ::testing::internal::GetCapturedStderr().c_str());178#else179  EXPECT_STREQ("Incoming def does not dominate incoming block!\n",180               ::testing::internal::GetCapturedStderr().c_str());181#endif182#endif183}184 185TEST_F(VPVerifierTest, DuplicateSuccessorsOutsideRegion) {186  VPlan &Plan = getPlan();187  VPValue *Zero = Plan.getConstantInt(32, 0);188  VPInstruction *I1 = new VPInstruction(Instruction::Add, {Zero, Zero});189  auto *CanIV = new VPCanonicalIVPHIRecipe(Zero, {});190  VPInstruction *BranchOnCond =191      new VPInstruction(VPInstruction::BranchOnCond, {CanIV});192  VPInstruction *BranchOnCond2 =193      new VPInstruction(VPInstruction::BranchOnCond, {I1});194 195  VPBasicBlock *VPBB1 = Plan.getEntry();196  VPBasicBlock *VPBB2 = Plan.createVPBasicBlock("");197 198  VPBB1->appendRecipe(I1);199  VPBB1->appendRecipe(BranchOnCond2);200  VPBB2->appendRecipe(CanIV);201  VPBB2->appendRecipe(BranchOnCond);202 203  VPRegionBlock *R1 = Plan.createLoopRegion("R1", VPBB2, VPBB2);204  VPBlockUtils::connectBlocks(VPBB1, R1);205  VPBlockUtils::connectBlocks(VPBB1, R1);206 207  VPBlockUtils::connectBlocks(R1, Plan.getScalarHeader());208 209#if GTEST_HAS_STREAM_REDIRECTION210  ::testing::internal::CaptureStderr();211#endif212  EXPECT_FALSE(verifyVPlanIsValid(Plan));213#if GTEST_HAS_STREAM_REDIRECTION214  EXPECT_STREQ("Multiple instances of the same successor.\n",215               ::testing::internal::GetCapturedStderr().c_str());216#endif217}218 219TEST_F(VPVerifierTest, DuplicateSuccessorsInsideRegion) {220  VPlan &Plan = getPlan();221  VPValue *Zero = Plan.getConstantInt(32, 0);222  VPInstruction *I1 = new VPInstruction(Instruction::Add, {Zero, Zero});223  auto *CanIV = new VPCanonicalIVPHIRecipe(Zero, {});224  VPInstruction *BranchOnCond =225      new VPInstruction(VPInstruction::BranchOnCond, {CanIV});226  VPInstruction *BranchOnCond2 =227      new VPInstruction(VPInstruction::BranchOnCond, {I1});228 229  VPBasicBlock *VPBB1 = Plan.getEntry();230  VPBasicBlock *VPBB2 = Plan.createVPBasicBlock("");231  VPBasicBlock *VPBB3 = Plan.createVPBasicBlock("");232 233  VPBB1->appendRecipe(I1);234  VPBB2->appendRecipe(CanIV);235  VPBB2->appendRecipe(BranchOnCond2);236  VPBB3->appendRecipe(BranchOnCond);237 238  VPBlockUtils::connectBlocks(VPBB2, VPBB3);239  VPBlockUtils::connectBlocks(VPBB2, VPBB3);240  VPRegionBlock *R1 = Plan.createLoopRegion("R1", VPBB2, VPBB3);241  VPBlockUtils::connectBlocks(VPBB1, R1);242  VPBB3->setParent(R1);243 244  VPBlockUtils::connectBlocks(R1, Plan.getScalarHeader());245 246#if GTEST_HAS_STREAM_REDIRECTION247  ::testing::internal::CaptureStderr();248#endif249  EXPECT_FALSE(verifyVPlanIsValid(Plan));250#if GTEST_HAS_STREAM_REDIRECTION251  EXPECT_STREQ("Multiple instances of the same successor.\n",252               ::testing::internal::GetCapturedStderr().c_str());253#endif254}255 256TEST_F(VPVerifierTest, BlockOutsideRegionWithParent) {257  VPlan &Plan = getPlan();258 259  VPBasicBlock *VPBB1 = Plan.getEntry();260  VPBasicBlock *VPBB2 = Plan.createVPBasicBlock("");261 262  VPValue *Zero = Plan.getConstantInt(32, 0);263  auto *CanIV = new VPCanonicalIVPHIRecipe(Zero, {});264  VPBB2->appendRecipe(CanIV);265 266  VPInstruction *DefI = new VPInstruction(Instruction::Add, {Zero, Zero});267  VPInstruction *BranchOnCond =268      new VPInstruction(VPInstruction::BranchOnCond, {DefI});269 270  VPBB1->appendRecipe(DefI);271  VPBB2->appendRecipe(BranchOnCond);272 273  VPRegionBlock *R1 = Plan.createLoopRegion("R1", VPBB2, VPBB2);274  VPBlockUtils::connectBlocks(VPBB1, R1);275 276  VPBlockUtils::connectBlocks(R1, Plan.getScalarHeader());277  VPBB1->setParent(R1);278 279#if GTEST_HAS_STREAM_REDIRECTION280  ::testing::internal::CaptureStderr();281#endif282  EXPECT_FALSE(verifyVPlanIsValid(Plan));283#if GTEST_HAS_STREAM_REDIRECTION284  EXPECT_STREQ("Predecessor is not in the same region.\n",285               ::testing::internal::GetCapturedStderr().c_str());286#endif287}288 289TEST_F(VPVerifierTest, NonHeaderPHIInHeader) {290  VPlan &Plan = getPlan();291  VPValue *Zero = Plan.getConstantInt(32, 0);292  auto *CanIV = new VPCanonicalIVPHIRecipe(Zero, {});293  auto *BranchOnCond = new VPInstruction(VPInstruction::BranchOnCond, {CanIV});294 295  VPBasicBlock *VPBB1 = Plan.getEntry();296  VPBasicBlock *VPBB2 = Plan.createVPBasicBlock("header");297 298  VPBB2->appendRecipe(CanIV);299 300  PHINode *PHINode = PHINode::Create(Type::getInt32Ty(C), 2);301  auto *IRPhi = new VPIRPhi(*PHINode);302  VPBB2->appendRecipe(IRPhi);303  VPBB2->appendRecipe(BranchOnCond);304 305  VPRegionBlock *R1 = Plan.createLoopRegion("R1", VPBB2, VPBB2);306  VPBlockUtils::connectBlocks(VPBB1, R1);307  VPBlockUtils::connectBlocks(R1, Plan.getScalarHeader());308 309#if GTEST_HAS_STREAM_REDIRECTION310  ::testing::internal::CaptureStderr();311#endif312  EXPECT_FALSE(verifyVPlanIsValid(Plan));313#if GTEST_HAS_STREAM_REDIRECTION314#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)315  EXPECT_STREQ(316      "Found non-header PHI recipe in header VPBB: IR   <badref> = phi i32 \n",317      ::testing::internal::GetCapturedStderr().c_str());318#else319  EXPECT_STREQ("Found non-header PHI recipe in header VPBB",320               ::testing::internal::GetCapturedStderr().c_str());321#endif322#endif323 324  delete PHINode;325}326 327class VPIRVerifierTest : public VPlanTestIRBase {};328 329TEST_F(VPIRVerifierTest, testVerifyIRPhiInScalarHeaderVPIRBB) {330  const char *ModuleString =331      "define void @f(ptr %A, i64 %N) {\n"332      "entry:\n"333      "  br label %loop\n"334      "loop:\n"335      "  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]\n"336      "  %iv.next = add i64 %iv, 1\n"337      "  %exitcond = icmp ne i64 %iv.next, %N\n"338      "  br i1 %exitcond, label %loop, label %for.end\n"339      "for.end:\n"340      "  %p = phi i64 [ %iv, %loop ]\n"341      "  ret void\n"342      "}\n";343 344  Module &M = parseModule(ModuleString);345 346  Function *F = M.getFunction("f");347  BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor();348  auto Plan = buildVPlan(LoopHeader);349  VPValue *Zero = Plan->getConstantInt(32, 0);350  Plan->getScalarHeader()->front().addOperand(Zero);351 352#if GTEST_HAS_STREAM_REDIRECTION353  ::testing::internal::CaptureStderr();354#endif355  EXPECT_FALSE(verifyVPlanIsValid(*Plan));356#if GTEST_HAS_STREAM_REDIRECTION357  EXPECT_STREQ(358      "Phi-like recipe with different number of operands and predecessors.\n",359      ::testing::internal::GetCapturedStderr().c_str());360#endif361}362 363TEST_F(VPIRVerifierTest, testVerifyIRPhiInExitVPIRBB) {364  const char *ModuleString =365      "define void @f(ptr %A, i64 %N) {\n"366      "entry:\n"367      "  br label %loop\n"368      "loop:\n"369      "  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]\n"370      "  %iv.next = add i64 %iv, 1\n"371      "  %exitcond = icmp ne i64 %iv.next, %N\n"372      "  br i1 %exitcond, label %loop, label %for.end\n"373      "for.end:\n"374      "  %p = phi i64 [ %iv, %loop ]\n"375      "  ret void\n"376      "}\n";377 378  Module &M = parseModule(ModuleString);379 380  Function *F = M.getFunction("f");381  BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor();382  auto Plan = buildVPlan(LoopHeader);383 384  // Create a definition in the vector loop header that will be used by the phi.385  auto *HeaderBlock =386      cast<VPBasicBlock>(Plan->getVectorLoopRegion()->getEntry());387  VPInstruction *DefI =388      new VPInstruction(VPInstruction::ExtractLastElement,389                        {HeaderBlock->front().getVPSingleValue()});390  DefI->insertBefore(Plan->getMiddleBlock()->getTerminator());391  Plan->getExitBlocks()[0]->front().addOperand(DefI);392 393#if GTEST_HAS_STREAM_REDIRECTION394  ::testing::internal::CaptureStderr();395#endif396  EXPECT_FALSE(verifyVPlanIsValid(*Plan));397#if GTEST_HAS_STREAM_REDIRECTION398  EXPECT_STREQ(399      "Phi-like recipe with different number of operands and predecessors.\n",400      ::testing::internal::GetCapturedStderr().c_str());401#endif402}403} // namespace404