xref: /llvm-project/llvm/lib/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.cpp (revision 79cbad188afd5268235b00267d37ce39544dbd3c)
1 //===- SandboxVectorizer.cpp - Vectorizer based on Sandbox IR -------------===//
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 "llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h"
10 #include "llvm/Analysis/TargetTransformInfo.h"
11 #include "llvm/SandboxIR/Constant.h"
12 #include "llvm/Support/CommandLine.h"
13 #include "llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerPassBuilder.h"
14 
15 using namespace llvm;
16 
17 #define SV_NAME "sandbox-vectorizer"
18 #define DEBUG_TYPE SV_NAME
19 
20 static cl::opt<bool>
21     PrintPassPipeline("sbvec-print-pass-pipeline", cl::init(false), cl::Hidden,
22                       cl::desc("Prints the pass pipeline and returns."));
23 
24 /// A magic string for the default pass pipeline.
25 static const char *DefaultPipelineMagicStr = "*";
26 
27 static cl::opt<std::string> UserDefinedPassPipeline(
28     "sbvec-passes", cl::init(DefaultPipelineMagicStr), cl::Hidden,
29     cl::desc("Comma-separated list of vectorizer passes. If not set "
30              "we run the predefined pipeline."));
31 
32 SandboxVectorizerPass::SandboxVectorizerPass() : FPM("fpm") {
33   if (UserDefinedPassPipeline == DefaultPipelineMagicStr) {
34     // TODO: Add region passes to the default pipeline.
35     FPM.setPassPipeline(
36         "bottom-up-vec<>",
37         sandboxir::SandboxVectorizerPassBuilder::createFunctionPass);
38   } else {
39     // Create the user-defined pipeline.
40     FPM.setPassPipeline(
41         UserDefinedPassPipeline,
42         sandboxir::SandboxVectorizerPassBuilder::createFunctionPass);
43   }
44 }
45 
46 SandboxVectorizerPass::SandboxVectorizerPass(SandboxVectorizerPass &&) =
47     default;
48 
49 SandboxVectorizerPass::~SandboxVectorizerPass() = default;
50 
51 PreservedAnalyses SandboxVectorizerPass::run(Function &F,
52                                              FunctionAnalysisManager &AM) {
53   TTI = &AM.getResult<TargetIRAnalysis>(F);
54   AA = &AM.getResult<AAManager>(F);
55   SE = &AM.getResult<ScalarEvolutionAnalysis>(F);
56 
57   bool Changed = runImpl(F);
58   if (!Changed)
59     return PreservedAnalyses::all();
60 
61   PreservedAnalyses PA;
62   PA.preserveSet<CFGAnalyses>();
63   return PA;
64 }
65 
66 bool SandboxVectorizerPass::runImpl(Function &LLVMF) {
67   if (Ctx == nullptr)
68     Ctx = std::make_unique<sandboxir::Context>(LLVMF.getContext());
69 
70   if (PrintPassPipeline) {
71     FPM.printPipeline(outs());
72     return false;
73   }
74 
75   // If the target claims to have no vector registers early return.
76   if (!TTI->getNumberOfRegisters(TTI->getRegisterClassForType(true))) {
77     LLVM_DEBUG(dbgs() << "SBVec: Target has no vector registers, return.\n");
78     return false;
79   }
80   LLVM_DEBUG(dbgs() << "SBVec: Analyzing " << LLVMF.getName() << ".\n");
81   // Early return if the attribute NoImplicitFloat is used.
82   if (LLVMF.hasFnAttribute(Attribute::NoImplicitFloat)) {
83     LLVM_DEBUG(dbgs() << "SBVec: NoImplicitFloat attribute, return.\n");
84     return false;
85   }
86 
87   // Create SandboxIR for LLVMF and run BottomUpVec on it.
88   sandboxir::Function &F = *Ctx->createFunction(&LLVMF);
89   sandboxir::Analyses A(*AA, *SE, *TTI);
90   bool Change = FPM.runOnFunction(F, A);
91   // Given that sandboxir::Context `Ctx` is defined at a pass-level scope, the
92   // maps from LLVM IR to Sandbox IR may go stale as later passes remove LLVM IR
93   // objects. To avoid issues caused by this clear the context's state.
94   // NOTE: The alternative would be to define Ctx and FPM within runOnFunction()
95   Ctx->clear();
96   return Change;
97 }
98