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