| //===- llvm/unittest/Transforms/Vectorize/VPlanTestBase.h -----------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| /// \file |
| /// This file defines a VPlanTestBase class, which provides helpers to parse |
| /// a LLVM IR string and create VPlans given a loop entry block. |
| //===----------------------------------------------------------------------===// |
| #ifndef LLVM_UNITTESTS_TRANSFORMS_VECTORIZE_VPLANTESTBASE_H |
| #define LLVM_UNITTESTS_TRANSFORMS_VECTORIZE_VPLANTESTBASE_H |
| |
| #include "../lib/Transforms/Vectorize/VPlan.h" |
| #include "../lib/Transforms/Vectorize/VPlanHelpers.h" |
| #include "../lib/Transforms/Vectorize/VPlanTransforms.h" |
| #include "llvm/Analysis/AssumptionCache.h" |
| #include "llvm/Analysis/BasicAliasAnalysis.h" |
| #include "llvm/Analysis/IVDescriptors.h" |
| #include "llvm/Analysis/LoopInfo.h" |
| #include "llvm/Analysis/TargetLibraryInfo.h" |
| #include "llvm/AsmParser/Parser.h" |
| #include "llvm/IR/Dominators.h" |
| #include "llvm/IR/Verifier.h" |
| #include "llvm/Support/SourceMgr.h" |
| #include "gtest/gtest.h" |
| |
| namespace llvm { |
| |
| /// Helper class to create a module from an assembly string and VPlans for a |
| /// given loop entry block. |
| class VPlanTestIRBase : public testing::Test { |
| protected: |
| DataLayout DL; |
| |
| std::unique_ptr<LLVMContext> Ctx; |
| std::unique_ptr<Module> M; |
| std::unique_ptr<LoopInfo> LI; |
| std::unique_ptr<DominatorTree> DT; |
| std::unique_ptr<AssumptionCache> AC; |
| std::unique_ptr<ScalarEvolution> SE; |
| std::unique_ptr<TargetLibraryInfoImpl> TLII; |
| std::unique_ptr<TargetLibraryInfo> TLI; |
| |
| MapVector<PHINode *, InductionDescriptor> Inductions; |
| |
| VPlanTestIRBase() |
| : DL("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-" |
| "f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:" |
| "16:32:64-S128"), |
| Ctx(new LLVMContext) {} |
| |
| Module &parseModule(const char *ModuleString) { |
| SMDiagnostic Err; |
| M = parseAssemblyString(ModuleString, Err, *Ctx); |
| EXPECT_TRUE(M); |
| TLII = std::make_unique<TargetLibraryInfoImpl>(M->getTargetTriple()); |
| TLI = std::make_unique<TargetLibraryInfo>(*TLII); |
| return *M; |
| } |
| |
| void doAnalysis(Function &F) { |
| DT.reset(new DominatorTree(F)); |
| LI.reset(new LoopInfo(*DT)); |
| AC.reset(new AssumptionCache(F)); |
| SE.reset(new ScalarEvolution(F, *TLI, *AC, *DT, *LI)); |
| } |
| |
| /// Build the VPlan for the loop starting from \p LoopHeader. |
| VPlanPtr buildVPlan( |
| BasicBlock *LoopHeader, |
| UncountableExitStyle Style = UncountableExitStyle::NoUncountableExit, |
| bool CreateLoopRegions = true) { |
| Function &F = *LoopHeader->getParent(); |
| assert(!verifyFunction(F) && "input function must be valid"); |
| doAnalysis(F); |
| |
| Loop *L = LI->getLoopFor(LoopHeader); |
| PredicatedScalarEvolution PSE(*SE, *L); |
| auto Plan = VPlanTransforms::buildVPlan0(L, *LI, IntegerType::get(*Ctx, 64), |
| {}, PSE); |
| |
| if (Style != UncountableExitStyle::NoUncountableExit) { |
| Inductions.clear(); |
| // handleEarlyExits requires induction phi recipes. |
| for (PHINode &Phi : LoopHeader->phis()) { |
| InductionDescriptor ID; |
| if (InductionDescriptor::isInductionPHI(&Phi, L, PSE, ID)) |
| Inductions[&Phi] = ID; |
| } |
| VPlanTransforms::createHeaderPhiRecipes( |
| *Plan, PSE, *L, Inductions, |
| MapVector<PHINode *, RecurrenceDescriptor>(), |
| SmallPtrSet<const PHINode *, 1>(), SmallPtrSet<PHINode *, 1>(), |
| /*AllowReordering=*/false); |
| } |
| |
| VPlanTransforms::handleEarlyExits(*Plan, Style, L, PSE, *DT, AC.get()); |
| VPlanTransforms::addMiddleCheck(*Plan, false); |
| |
| if (CreateLoopRegions) |
| VPlanTransforms::createLoopRegions(*Plan); |
| return Plan; |
| } |
| |
| VPlanPtr buildVPlan0(BasicBlock *LoopHeader) { |
| Function &F = *LoopHeader->getParent(); |
| assert(!verifyFunction(F) && "input function must be valid"); |
| doAnalysis(F); |
| |
| Loop *L = LI->getLoopFor(LoopHeader); |
| PredicatedScalarEvolution PSE(*SE, *L); |
| return VPlanTransforms::buildVPlan0(L, *LI, IntegerType::get(*Ctx, 64), {}, |
| PSE); |
| } |
| }; |
| |
| class VPlanTestBase : public testing::Test { |
| protected: |
| LLVMContext C; |
| std::unique_ptr<Module> M; |
| Function *F; |
| BasicBlock *ScalarHeader; |
| SmallVector<std::unique_ptr<VPlan>> Plans; |
| |
| VPlanTestBase() { |
| M = std::make_unique<Module>("VPlanTestModule", C); |
| FunctionType *FTy = FunctionType::get(Type::getVoidTy(C), false); |
| F = Function::Create(FTy, GlobalValue::ExternalLinkage, "f", M.get()); |
| ScalarHeader = BasicBlock::Create(C, "scalar.header", F); |
| UncondBrInst::Create(ScalarHeader, ScalarHeader); |
| } |
| |
| VPlan &getPlan() { |
| Plans.push_back(std::make_unique<VPlan>(ScalarHeader)); |
| VPlan &Plan = *Plans.back(); |
| VPValue *DefaultTC = Plan.getConstantInt(32, 1024); |
| Plan.setTripCount(DefaultTC); |
| return Plan; |
| } |
| }; |
| |
| } // namespace llvm |
| |
| #endif // LLVM_UNITTESTS_TRANSFORMS_VECTORIZE_VPLANTESTBASE_H |