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