152dca6ffSvporpo //===- SandboxVectorizer.cpp - Vectorizer based on Sandbox IR -------------===// 252dca6ffSvporpo // 352dca6ffSvporpo // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 452dca6ffSvporpo // See https://llvm.org/LICENSE.txt for license information. 552dca6ffSvporpo // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 652dca6ffSvporpo // 752dca6ffSvporpo //===----------------------------------------------------------------------===// 852dca6ffSvporpo 952dca6ffSvporpo #include "llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h" 107ea9f0d8SVasileios Porpodas #include "llvm/Analysis/TargetTransformInfo.h" 112018f4ccSVasileios Porpodas #include "llvm/SandboxIR/Constant.h" 122e8ad49eSJorge Gorbe Moya #include "llvm/Support/CommandLine.h" 132e8ad49eSJorge Gorbe Moya #include "llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerPassBuilder.h" 1452dca6ffSvporpo 1552dca6ffSvporpo using namespace llvm; 1652dca6ffSvporpo 1752dca6ffSvporpo #define SV_NAME "sandbox-vectorizer" 1852dca6ffSvporpo #define DEBUG_TYPE SV_NAME 1952dca6ffSvporpo 202e8ad49eSJorge Gorbe Moya static cl::opt<bool> 212e8ad49eSJorge Gorbe Moya PrintPassPipeline("sbvec-print-pass-pipeline", cl::init(false), cl::Hidden, 222e8ad49eSJorge Gorbe Moya cl::desc("Prints the pass pipeline and returns.")); 232e8ad49eSJorge Gorbe Moya 242e8ad49eSJorge Gorbe Moya /// A magic string for the default pass pipeline. 252e8ad49eSJorge Gorbe Moya static const char *DefaultPipelineMagicStr = "*"; 262e8ad49eSJorge Gorbe Moya 272e8ad49eSJorge Gorbe Moya static cl::opt<std::string> UserDefinedPassPipeline( 282e8ad49eSJorge Gorbe Moya "sbvec-passes", cl::init(DefaultPipelineMagicStr), cl::Hidden, 292e8ad49eSJorge Gorbe Moya cl::desc("Comma-separated list of vectorizer passes. If not set " 302e8ad49eSJorge Gorbe Moya "we run the predefined pipeline.")); 312e8ad49eSJorge Gorbe Moya 322e8ad49eSJorge Gorbe Moya SandboxVectorizerPass::SandboxVectorizerPass() : FPM("fpm") { 332e8ad49eSJorge Gorbe Moya if (UserDefinedPassPipeline == DefaultPipelineMagicStr) { 342e8ad49eSJorge Gorbe Moya // TODO: Add region passes to the default pipeline. 352e8ad49eSJorge Gorbe Moya FPM.setPassPipeline( 362e8ad49eSJorge Gorbe Moya "bottom-up-vec<>", 372e8ad49eSJorge Gorbe Moya sandboxir::SandboxVectorizerPassBuilder::createFunctionPass); 382e8ad49eSJorge Gorbe Moya } else { 392e8ad49eSJorge Gorbe Moya // Create the user-defined pipeline. 402e8ad49eSJorge Gorbe Moya FPM.setPassPipeline( 412e8ad49eSJorge Gorbe Moya UserDefinedPassPipeline, 422e8ad49eSJorge Gorbe Moya sandboxir::SandboxVectorizerPassBuilder::createFunctionPass); 432e8ad49eSJorge Gorbe Moya } 442e8ad49eSJorge Gorbe Moya } 45102c384bSJorge Gorbe Moya 46756ec99cSJorge Gorbe Moya SandboxVectorizerPass::SandboxVectorizerPass(SandboxVectorizerPass &&) = 47756ec99cSJorge Gorbe Moya default; 48102c384bSJorge Gorbe Moya 49756ec99cSJorge Gorbe Moya SandboxVectorizerPass::~SandboxVectorizerPass() = default; 50102c384bSJorge Gorbe Moya 5152dca6ffSvporpo PreservedAnalyses SandboxVectorizerPass::run(Function &F, 5252dca6ffSvporpo FunctionAnalysisManager &AM) { 5352dca6ffSvporpo TTI = &AM.getResult<TargetIRAnalysis>(F); 54ce0d0858Svporpo AA = &AM.getResult<AAManager>(F); 55a461869dSvporpo SE = &AM.getResult<ScalarEvolutionAnalysis>(F); 5652dca6ffSvporpo 5752dca6ffSvporpo bool Changed = runImpl(F); 5852dca6ffSvporpo if (!Changed) 5952dca6ffSvporpo return PreservedAnalyses::all(); 6052dca6ffSvporpo 6152dca6ffSvporpo PreservedAnalyses PA; 6252dca6ffSvporpo PA.preserveSet<CFGAnalyses>(); 6352dca6ffSvporpo return PA; 6452dca6ffSvporpo } 6552dca6ffSvporpo 66d5bc1f4aSVasileios Porpodas bool SandboxVectorizerPass::runImpl(Function &LLVMF) { 675942a99fSvporpo if (Ctx == nullptr) 685942a99fSvporpo Ctx = std::make_unique<sandboxir::Context>(LLVMF.getContext()); 695942a99fSvporpo 702e8ad49eSJorge Gorbe Moya if (PrintPassPipeline) { 712e8ad49eSJorge Gorbe Moya FPM.printPipeline(outs()); 722e8ad49eSJorge Gorbe Moya return false; 732e8ad49eSJorge Gorbe Moya } 742e8ad49eSJorge Gorbe Moya 75c1c42518Svporpo // If the target claims to have no vector registers early return. 76c1c42518Svporpo if (!TTI->getNumberOfRegisters(TTI->getRegisterClassForType(true))) { 77c1c42518Svporpo LLVM_DEBUG(dbgs() << "SBVec: Target has no vector registers, return.\n"); 78c1c42518Svporpo return false; 79c1c42518Svporpo } 80d5bc1f4aSVasileios Porpodas LLVM_DEBUG(dbgs() << "SBVec: Analyzing " << LLVMF.getName() << ".\n"); 81c1c42518Svporpo // Early return if the attribute NoImplicitFloat is used. 82d5bc1f4aSVasileios Porpodas if (LLVMF.hasFnAttribute(Attribute::NoImplicitFloat)) { 83c1c42518Svporpo LLVM_DEBUG(dbgs() << "SBVec: NoImplicitFloat attribute, return.\n"); 84c1c42518Svporpo return false; 85c1c42518Svporpo } 86c1c42518Svporpo 87756ec99cSJorge Gorbe Moya // Create SandboxIR for LLVMF and run BottomUpVec on it. 885942a99fSvporpo sandboxir::Function &F = *Ctx->createFunction(&LLVMF); 896312beefSvporpo sandboxir::Analyses A(*AA, *SE, *TTI); 90334a1cdbSvporpo bool Change = FPM.runOnFunction(F, A); 91*79cbad18Svporpo // Given that sandboxir::Context `Ctx` is defined at a pass-level scope, the 92*79cbad18Svporpo // maps from LLVM IR to Sandbox IR may go stale as later passes remove LLVM IR 93*79cbad18Svporpo // objects. To avoid issues caused by this clear the context's state. 94*79cbad18Svporpo // NOTE: The alternative would be to define Ctx and FPM within runOnFunction() 95*79cbad18Svporpo Ctx->clear(); 96334a1cdbSvporpo return Change; 9739f2d2f1Svporpo } 98