1 | //===-- PPCLowerMASSVEntries.cpp ------------------------------------------===// |
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 | // This file implements lowering of MASSV (SIMD) entries for specific PowerPC |
10 | // subtargets. |
11 | // Following is an example of a conversion specific to Power9 subtarget: |
12 | // __sind2_massv ---> __sind2_P9 |
13 | // |
14 | //===----------------------------------------------------------------------===// |
15 | |
16 | #include "PPC.h" |
17 | #include "PPCSubtarget.h" |
18 | #include "PPCTargetMachine.h" |
19 | #include "llvm/ADT/STLExtras.h" |
20 | #include "llvm/Analysis/TargetTransformInfo.h" |
21 | #include "llvm/CodeGen/TargetPassConfig.h" |
22 | #include "llvm/IR/Instructions.h" |
23 | #include "llvm/IR/Module.h" |
24 | |
25 | #define DEBUG_TYPE "ppc-lower-massv-entries" |
26 | |
27 | using namespace llvm; |
28 | |
29 | namespace { |
30 | |
31 | static StringRef MASSVFuncs[] = { |
32 | #define TLI_DEFINE_MASSV_VECFUNCS |
33 | #define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, VABI_PREFIX) VEC, |
34 | #include "llvm/Analysis/VecFuncs.def" |
35 | #undef TLI_DEFINE_MASSV_VECFUNCS |
36 | }; |
37 | |
38 | class PPCLowerMASSVEntries : public ModulePass { |
39 | public: |
40 | static char ID; |
41 | |
42 | PPCLowerMASSVEntries() : ModulePass(ID) {} |
43 | |
44 | bool runOnModule(Module &M) override; |
45 | |
46 | StringRef getPassName() const override { return "PPC Lower MASS Entries" ; } |
47 | |
48 | void getAnalysisUsage(AnalysisUsage &AU) const override { |
49 | AU.addRequired<TargetTransformInfoWrapperPass>(); |
50 | } |
51 | |
52 | private: |
53 | static bool isMASSVFunc(StringRef Name); |
54 | static StringRef getCPUSuffix(const PPCSubtarget *Subtarget); |
55 | static std::string createMASSVFuncName(Function &Func, |
56 | const PPCSubtarget *Subtarget); |
57 | bool handlePowSpecialCases(CallInst *CI, Function &Func, Module &M); |
58 | bool lowerMASSVCall(CallInst *CI, Function &Func, Module &M, |
59 | const PPCSubtarget *Subtarget); |
60 | }; |
61 | |
62 | } // namespace |
63 | |
64 | /// Checks if the specified function name represents an entry in the MASSV |
65 | /// library. |
66 | bool PPCLowerMASSVEntries::isMASSVFunc(StringRef Name) { |
67 | return llvm::is_contained(Range&: MASSVFuncs, Element: Name); |
68 | } |
69 | |
70 | // FIXME: |
71 | /// Returns a string corresponding to the specified PowerPC subtarget. e.g.: |
72 | /// "_P8" for Power8, "_P9" for Power9. The string is used as a suffix while |
73 | /// generating subtarget-specific MASSV library functions. Current support |
74 | /// includes minimum subtarget Power8 for Linux and Power7 for AIX. |
75 | StringRef PPCLowerMASSVEntries::getCPUSuffix(const PPCSubtarget *Subtarget) { |
76 | // Assume generic when Subtarget is unavailable. |
77 | if (!Subtarget) |
78 | return "" ; |
79 | // TODO: add _P10 enties to Linux MASS lib and remove the check for AIX |
80 | if (Subtarget->isAIXABI() && Subtarget->hasP10Vector()) |
81 | return "_P10" ; |
82 | if (Subtarget->hasP9Vector()) |
83 | return "_P9" ; |
84 | if (Subtarget->hasP8Vector()) |
85 | return "_P8" ; |
86 | if (Subtarget->isAIXABI()) |
87 | return "_P7" ; |
88 | |
89 | report_fatal_error( |
90 | reason: "Mininum subtarget for -vector-library=MASSV option is Power8 on Linux " |
91 | "and Power7 on AIX when vectorization is not disabled." ); |
92 | } |
93 | |
94 | /// Creates PowerPC subtarget-specific name corresponding to the specified |
95 | /// generic MASSV function, and the PowerPC subtarget. |
96 | std::string |
97 | PPCLowerMASSVEntries::createMASSVFuncName(Function &Func, |
98 | const PPCSubtarget *Subtarget) { |
99 | StringRef Suffix = getCPUSuffix(Subtarget); |
100 | auto GenericName = Func.getName().str(); |
101 | std::string MASSVEntryName = GenericName + Suffix.str(); |
102 | return MASSVEntryName; |
103 | } |
104 | |
105 | /// If there are proper fast-math flags, this function creates llvm.pow |
106 | /// intrinsics when the exponent is 0.25 or 0.75. |
107 | bool PPCLowerMASSVEntries::handlePowSpecialCases(CallInst *CI, Function &Func, |
108 | Module &M) { |
109 | if (Func.getName() != "__powf4" && Func.getName() != "__powd2" ) |
110 | return false; |
111 | |
112 | if (Constant *Exp = dyn_cast<Constant>(Val: CI->getArgOperand(i: 1))) |
113 | if (ConstantFP *CFP = dyn_cast_or_null<ConstantFP>(Val: Exp->getSplatValue())) { |
114 | // If the argument is 0.75 or 0.25 it is cheaper to turn it into pow |
115 | // intrinsic so that it could be optimzed as sequence of sqrt's. |
116 | if (!CI->hasNoInfs() || !CI->hasApproxFunc()) |
117 | return false; |
118 | |
119 | if (!CFP->isExactlyValue(V: 0.75) && !CFP->isExactlyValue(V: 0.25)) |
120 | return false; |
121 | |
122 | if (CFP->isExactlyValue(V: 0.25) && !CI->hasNoSignedZeros()) |
123 | return false; |
124 | |
125 | CI->setCalledFunction( |
126 | Intrinsic::getDeclaration(M: &M, id: Intrinsic::pow, Tys: CI->getType())); |
127 | return true; |
128 | } |
129 | |
130 | return false; |
131 | } |
132 | |
133 | /// Lowers generic MASSV entries to PowerPC subtarget-specific MASSV entries. |
134 | /// e.g.: __sind2_massv --> __sind2_P9 for a Power9 subtarget. |
135 | /// Both function prototypes and their callsites are updated during lowering. |
136 | bool PPCLowerMASSVEntries::lowerMASSVCall(CallInst *CI, Function &Func, |
137 | Module &M, |
138 | const PPCSubtarget *Subtarget) { |
139 | if (CI->use_empty()) |
140 | return false; |
141 | |
142 | // Handling pow(x, 0.25), pow(x, 0.75), powf(x, 0.25), powf(x, 0.75) |
143 | if (handlePowSpecialCases(CI, Func, M)) |
144 | return true; |
145 | |
146 | std::string MASSVEntryName = createMASSVFuncName(Func, Subtarget); |
147 | FunctionCallee FCache = M.getOrInsertFunction( |
148 | Name: MASSVEntryName, T: Func.getFunctionType(), AttributeList: Func.getAttributes()); |
149 | |
150 | CI->setCalledFunction(FCache); |
151 | |
152 | return true; |
153 | } |
154 | |
155 | bool PPCLowerMASSVEntries::runOnModule(Module &M) { |
156 | bool Changed = false; |
157 | |
158 | auto *TPC = getAnalysisIfAvailable<TargetPassConfig>(); |
159 | if (!TPC) |
160 | return Changed; |
161 | |
162 | auto &TM = TPC->getTM<PPCTargetMachine>(); |
163 | const PPCSubtarget *Subtarget; |
164 | |
165 | for (Function &Func : M) { |
166 | if (!Func.isDeclaration()) |
167 | continue; |
168 | |
169 | if (!isMASSVFunc(Name: Func.getName())) |
170 | continue; |
171 | |
172 | // Call to lowerMASSVCall() invalidates the iterator over users upon |
173 | // replacing the users. Precomputing the current list of users allows us to |
174 | // replace all the call sites. |
175 | SmallVector<User *, 4> MASSVUsers(Func.users()); |
176 | |
177 | for (auto *User : MASSVUsers) { |
178 | auto *CI = dyn_cast<CallInst>(Val: User); |
179 | if (!CI) |
180 | continue; |
181 | |
182 | Subtarget = &TM.getSubtarget<PPCSubtarget>(F: *CI->getParent()->getParent()); |
183 | Changed |= lowerMASSVCall(CI, Func, M, Subtarget); |
184 | } |
185 | } |
186 | |
187 | return Changed; |
188 | } |
189 | |
190 | char PPCLowerMASSVEntries::ID = 0; |
191 | |
192 | char &llvm::PPCLowerMASSVEntriesID = PPCLowerMASSVEntries::ID; |
193 | |
194 | INITIALIZE_PASS(PPCLowerMASSVEntries, DEBUG_TYPE, "Lower MASSV entries" , false, |
195 | false) |
196 | |
197 | ModulePass *llvm::createPPCLowerMASSVEntriesPass() { |
198 | return new PPCLowerMASSVEntries(); |
199 | } |
200 | |