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