1d6de5f12SFrancesco Petrogalli //===- InjectTLIMAppings.cpp - TLI to VFABI attribute injection  ----------===//
2d6de5f12SFrancesco Petrogalli //
3d6de5f12SFrancesco Petrogalli // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4d6de5f12SFrancesco Petrogalli // See https://llvm.org/LICENSE.txt for license information.
5d6de5f12SFrancesco Petrogalli // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6d6de5f12SFrancesco Petrogalli //
7d6de5f12SFrancesco Petrogalli //===----------------------------------------------------------------------===//
8d6de5f12SFrancesco Petrogalli //
9d6de5f12SFrancesco Petrogalli // Populates the VFABI attribute with the scalar-to-vector mappings
10d6de5f12SFrancesco Petrogalli // from the TargetLibraryInfo.
11d6de5f12SFrancesco Petrogalli //
12d6de5f12SFrancesco Petrogalli //===----------------------------------------------------------------------===//
13d6de5f12SFrancesco Petrogalli 
14d6de5f12SFrancesco Petrogalli #include "llvm/Transforms/Utils/InjectTLIMappings.h"
15d6de5f12SFrancesco Petrogalli #include "llvm/ADT/Statistic.h"
1666c120f0SFrancesco Petrogalli #include "llvm/Analysis/DemandedBits.h"
17f64dc4e6SRyan Santhiraraja #include "llvm/Analysis/GlobalsModRef.h"
1866c120f0SFrancesco Petrogalli #include "llvm/Analysis/OptimizationRemarkEmitter.h"
192ce38b3fSdfukalov #include "llvm/Analysis/TargetLibraryInfo.h"
20d6de5f12SFrancesco Petrogalli #include "llvm/Analysis/VectorUtils.h"
21d6de5f12SFrancesco Petrogalli #include "llvm/IR/InstIterator.h"
22d6de5f12SFrancesco Petrogalli #include "llvm/Transforms/Utils.h"
23d6de5f12SFrancesco Petrogalli #include "llvm/Transforms/Utils/ModuleUtils.h"
24d6de5f12SFrancesco Petrogalli 
25d6de5f12SFrancesco Petrogalli using namespace llvm;
26d6de5f12SFrancesco Petrogalli 
27d6de5f12SFrancesco Petrogalli #define DEBUG_TYPE "inject-tli-mappings"
28d6de5f12SFrancesco Petrogalli 
29d6de5f12SFrancesco Petrogalli STATISTIC(NumCallInjected,
30d6de5f12SFrancesco Petrogalli           "Number of calls in which the mappings have been injected.");
31d6de5f12SFrancesco Petrogalli 
32d6de5f12SFrancesco Petrogalli STATISTIC(NumVFDeclAdded,
33d6de5f12SFrancesco Petrogalli           "Number of function declarations that have been added.");
34d6de5f12SFrancesco Petrogalli STATISTIC(NumCompUsedAdded,
35d6de5f12SFrancesco Petrogalli           "Number of `@llvm.compiler.used` operands that have been added.");
36d6de5f12SFrancesco Petrogalli 
37d6de5f12SFrancesco Petrogalli /// A helper function that adds the vector function declaration that
38d6de5f12SFrancesco Petrogalli /// vectorizes the CallInst CI with a vectorization factor of VF
39d6de5f12SFrancesco Petrogalli /// lanes. The TLI assumes that all parameters and the return type of
40d6de5f12SFrancesco Petrogalli /// CI (other than void) need to be widened to a VectorType of VF
41d6de5f12SFrancesco Petrogalli /// lanes.
addVariantDeclaration(CallInst & CI,const ElementCount & VF,const StringRef VFName)4201b87444SDavid Sherwood static void addVariantDeclaration(CallInst &CI, const ElementCount &VF,
43d6de5f12SFrancesco Petrogalli                                   const StringRef VFName) {
44d6de5f12SFrancesco Petrogalli   Module *M = CI.getModule();
45d6de5f12SFrancesco Petrogalli 
46d6de5f12SFrancesco Petrogalli   // Add function declaration.
47d6de5f12SFrancesco Petrogalli   Type *RetTy = ToVectorTy(CI.getType(), VF);
48d6de5f12SFrancesco Petrogalli   SmallVector<Type *, 4> Tys;
49f631173dSKazu Hirata   for (Value *ArgOperand : CI.args())
50d6de5f12SFrancesco Petrogalli     Tys.push_back(ToVectorTy(ArgOperand->getType(), VF));
51d6de5f12SFrancesco Petrogalli   assert(!CI.getFunctionType()->isVarArg() &&
52d6de5f12SFrancesco Petrogalli          "VarArg functions are not supported.");
53d6de5f12SFrancesco Petrogalli   FunctionType *FTy = FunctionType::get(RetTy, Tys, /*isVarArg=*/false);
54d6de5f12SFrancesco Petrogalli   Function *VectorF =
55d6de5f12SFrancesco Petrogalli       Function::Create(FTy, Function::ExternalLinkage, VFName, M);
56d6de5f12SFrancesco Petrogalli   VectorF->copyAttributesFrom(CI.getCalledFunction());
57d6de5f12SFrancesco Petrogalli   ++NumVFDeclAdded;
58d6de5f12SFrancesco Petrogalli   LLVM_DEBUG(dbgs() << DEBUG_TYPE << ": Added to the module: `" << VFName
59d6de5f12SFrancesco Petrogalli                     << "` of type " << *(VectorF->getType()) << "\n");
60d6de5f12SFrancesco Petrogalli 
61d6de5f12SFrancesco Petrogalli   // Make function declaration (without a body) "sticky" in the IR by
62d6de5f12SFrancesco Petrogalli   // listing it in the @llvm.compiler.used intrinsic.
63d6de5f12SFrancesco Petrogalli   assert(!VectorF->size() && "VFABI attribute requires `@llvm.compiler.used` "
64d6de5f12SFrancesco Petrogalli                              "only on declarations.");
65d6de5f12SFrancesco Petrogalli   appendToCompilerUsed(*M, {VectorF});
66d6de5f12SFrancesco Petrogalli   LLVM_DEBUG(dbgs() << DEBUG_TYPE << ": Adding `" << VFName
67d6de5f12SFrancesco Petrogalli                     << "` to `@llvm.compiler.used`.\n");
68d6de5f12SFrancesco Petrogalli   ++NumCompUsedAdded;
69d6de5f12SFrancesco Petrogalli }
70d6de5f12SFrancesco Petrogalli 
addMappingsFromTLI(const TargetLibraryInfo & TLI,CallInst & CI)71d6de5f12SFrancesco Petrogalli static void addMappingsFromTLI(const TargetLibraryInfo &TLI, CallInst &CI) {
72d6de5f12SFrancesco Petrogalli   // This is needed to make sure we don't query the TLI for calls to
73d6de5f12SFrancesco Petrogalli   // bitcast of function pointers, like `%call = call i32 (i32*, ...)
74d6de5f12SFrancesco Petrogalli   // bitcast (i32 (...)* @goo to i32 (i32*, ...)*)(i32* nonnull %i)`,
75d6de5f12SFrancesco Petrogalli   // as such calls make the `isFunctionVectorizable` raise an
76d6de5f12SFrancesco Petrogalli   // exception.
77d6de5f12SFrancesco Petrogalli   if (CI.isNoBuiltin() || !CI.getCalledFunction())
78d6de5f12SFrancesco Petrogalli     return;
79d6de5f12SFrancesco Petrogalli 
808f0a8ed4SNadav Rotem   StringRef ScalarName = CI.getCalledFunction()->getName();
818f0a8ed4SNadav Rotem 
82d6de5f12SFrancesco Petrogalli   // Nothing to be done if the TLI thinks the function is not
83d6de5f12SFrancesco Petrogalli   // vectorizable.
84d6de5f12SFrancesco Petrogalli   if (!TLI.isFunctionVectorizable(ScalarName))
85d6de5f12SFrancesco Petrogalli     return;
86d6de5f12SFrancesco Petrogalli   SmallVector<std::string, 8> Mappings;
87d6de5f12SFrancesco Petrogalli   VFABI::getVectorVariantNames(CI, Mappings);
88d6de5f12SFrancesco Petrogalli   Module *M = CI.getModule();
89d6de5f12SFrancesco Petrogalli   const SetVector<StringRef> OriginalSetOfMappings(Mappings.begin(),
90d6de5f12SFrancesco Petrogalli                                                    Mappings.end());
9101b87444SDavid Sherwood 
9201b87444SDavid Sherwood   auto AddVariantDecl = [&](const ElementCount &VF) {
93adcd0268SBenjamin Kramer     const std::string TLIName =
94adcd0268SBenjamin Kramer         std::string(TLI.getVectorizedFunction(ScalarName, VF));
95d6de5f12SFrancesco Petrogalli     if (!TLIName.empty()) {
96*4f0225f6SKazu Hirata       std::string MangledName =
97*4f0225f6SKazu Hirata           VFABI::mangleTLIVectorName(TLIName, ScalarName, CI.arg_size(), VF);
98d6de5f12SFrancesco Petrogalli       if (!OriginalSetOfMappings.count(MangledName)) {
99d6de5f12SFrancesco Petrogalli         Mappings.push_back(MangledName);
100d6de5f12SFrancesco Petrogalli         ++NumCallInjected;
101d6de5f12SFrancesco Petrogalli       }
102d6de5f12SFrancesco Petrogalli       Function *VariantF = M->getFunction(TLIName);
103d6de5f12SFrancesco Petrogalli       if (!VariantF)
104d6de5f12SFrancesco Petrogalli         addVariantDeclaration(CI, VF, TLIName);
105d6de5f12SFrancesco Petrogalli     }
10601b87444SDavid Sherwood   };
10701b87444SDavid Sherwood 
10801b87444SDavid Sherwood   //  All VFs in the TLI are powers of 2.
10901b87444SDavid Sherwood   ElementCount WidestFixedVF, WidestScalableVF;
11001b87444SDavid Sherwood   TLI.getWidestVF(ScalarName, WidestFixedVF, WidestScalableVF);
11101b87444SDavid Sherwood 
11201b87444SDavid Sherwood   for (ElementCount VF = ElementCount::getFixed(2);
11301b87444SDavid Sherwood        ElementCount::isKnownLE(VF, WidestFixedVF); VF *= 2)
11401b87444SDavid Sherwood     AddVariantDecl(VF);
11501b87444SDavid Sherwood 
11601b87444SDavid Sherwood   // TODO: Add scalable variants once we're able to test them.
11701b87444SDavid Sherwood   assert(WidestScalableVF.isZero() &&
11801b87444SDavid Sherwood          "Scalable vector mappings not yet supported");
119d6de5f12SFrancesco Petrogalli 
120d6de5f12SFrancesco Petrogalli   VFABI::setVectorVariantNames(&CI, Mappings);
121d6de5f12SFrancesco Petrogalli }
122d6de5f12SFrancesco Petrogalli 
runImpl(const TargetLibraryInfo & TLI,Function & F)123d6de5f12SFrancesco Petrogalli static bool runImpl(const TargetLibraryInfo &TLI, Function &F) {
124d6de5f12SFrancesco Petrogalli   for (auto &I : instructions(F))
125d6de5f12SFrancesco Petrogalli     if (auto CI = dyn_cast<CallInst>(&I))
126d6de5f12SFrancesco Petrogalli       addMappingsFromTLI(TLI, *CI);
127d6de5f12SFrancesco Petrogalli   // Even if the pass adds IR attributes, the analyses are preserved.
128d6de5f12SFrancesco Petrogalli   return false;
129d6de5f12SFrancesco Petrogalli }
130d6de5f12SFrancesco Petrogalli 
131d6de5f12SFrancesco Petrogalli ////////////////////////////////////////////////////////////////////////////////
132d6de5f12SFrancesco Petrogalli // New pass manager implementation.
133d6de5f12SFrancesco Petrogalli ////////////////////////////////////////////////////////////////////////////////
run(Function & F,FunctionAnalysisManager & AM)134d6de5f12SFrancesco Petrogalli PreservedAnalyses InjectTLIMappings::run(Function &F,
135d6de5f12SFrancesco Petrogalli                                          FunctionAnalysisManager &AM) {
136d6de5f12SFrancesco Petrogalli   const TargetLibraryInfo &TLI = AM.getResult<TargetLibraryAnalysis>(F);
137d6de5f12SFrancesco Petrogalli   runImpl(TLI, F);
138d6de5f12SFrancesco Petrogalli   // Even if the pass adds IR attributes, the analyses are preserved.
139d6de5f12SFrancesco Petrogalli   return PreservedAnalyses::all();
140d6de5f12SFrancesco Petrogalli }
141d6de5f12SFrancesco Petrogalli 
142d6de5f12SFrancesco Petrogalli ////////////////////////////////////////////////////////////////////////////////
143d6de5f12SFrancesco Petrogalli // Legacy PM Implementation.
144d6de5f12SFrancesco Petrogalli ////////////////////////////////////////////////////////////////////////////////
runOnFunction(Function & F)145d6de5f12SFrancesco Petrogalli bool InjectTLIMappingsLegacy::runOnFunction(Function &F) {
146d6de5f12SFrancesco Petrogalli   const TargetLibraryInfo &TLI =
147d6de5f12SFrancesco Petrogalli       getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F);
148d6de5f12SFrancesco Petrogalli   return runImpl(TLI, F);
149d6de5f12SFrancesco Petrogalli }
150d6de5f12SFrancesco Petrogalli 
getAnalysisUsage(AnalysisUsage & AU) const151d6de5f12SFrancesco Petrogalli void InjectTLIMappingsLegacy::getAnalysisUsage(AnalysisUsage &AU) const {
152d6de5f12SFrancesco Petrogalli   AU.setPreservesCFG();
153d6de5f12SFrancesco Petrogalli   AU.addRequired<TargetLibraryInfoWrapperPass>();
154d6de5f12SFrancesco Petrogalli   AU.addPreserved<TargetLibraryInfoWrapperPass>();
15566c120f0SFrancesco Petrogalli   AU.addPreserved<ScalarEvolutionWrapperPass>();
15666c120f0SFrancesco Petrogalli   AU.addPreserved<AAResultsWrapperPass>();
15766c120f0SFrancesco Petrogalli   AU.addPreserved<LoopAccessLegacyAnalysis>();
15866c120f0SFrancesco Petrogalli   AU.addPreserved<DemandedBitsWrapperPass>();
15966c120f0SFrancesco Petrogalli   AU.addPreserved<OptimizationRemarkEmitterWrapperPass>();
160f64dc4e6SRyan Santhiraraja   AU.addPreserved<GlobalsAAWrapperPass>();
161d6de5f12SFrancesco Petrogalli }
162d6de5f12SFrancesco Petrogalli 
163d6de5f12SFrancesco Petrogalli ////////////////////////////////////////////////////////////////////////////////
164d6de5f12SFrancesco Petrogalli // Legacy Pass manager initialization
165d6de5f12SFrancesco Petrogalli ////////////////////////////////////////////////////////////////////////////////
166d6de5f12SFrancesco Petrogalli char InjectTLIMappingsLegacy::ID = 0;
167d6de5f12SFrancesco Petrogalli 
168d6de5f12SFrancesco Petrogalli INITIALIZE_PASS_BEGIN(InjectTLIMappingsLegacy, DEBUG_TYPE,
169d6de5f12SFrancesco Petrogalli                       "Inject TLI Mappings", false, false)
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)170d6de5f12SFrancesco Petrogalli INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
171d6de5f12SFrancesco Petrogalli INITIALIZE_PASS_END(InjectTLIMappingsLegacy, DEBUG_TYPE, "Inject TLI Mappings",
172d6de5f12SFrancesco Petrogalli                     false, false)
173d6de5f12SFrancesco Petrogalli 
174d6de5f12SFrancesco Petrogalli FunctionPass *llvm::createInjectTLIMappingsLegacyPass() {
175d6de5f12SFrancesco Petrogalli   return new InjectTLIMappingsLegacy();
176d6de5f12SFrancesco Petrogalli }
177