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(MASSVFuncs, 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 "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>(CI->getArgOperand(1))) 111 if (ConstantFP *CFP = dyn_cast_or_null<ConstantFP>(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(0.75) && !CFP->isExactlyValue(0.25)) 118 return false; 119 120 if (CFP->isExactlyValue(0.25) && !CI->hasNoSignedZeros()) 121 return false; 122 123 CI->setCalledFunction( 124 Intrinsic::getDeclaration(&M, Intrinsic::pow, 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 MASSVEntryName, Func.getFunctionType(), 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(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>(User); 177 if (!CI) 178 continue; 179 180 Subtarget = &TM.getSubtarget<PPCSubtarget>(*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