1480093f4SDimitry Andric //===-- PPCLowerMASSVEntries.cpp ------------------------------------------===// 2480093f4SDimitry Andric // 3480093f4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4480093f4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5480093f4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6480093f4SDimitry Andric // 7480093f4SDimitry Andric //===----------------------------------------------------------------------===// 8480093f4SDimitry Andric // 9480093f4SDimitry Andric // This file implements lowering of MASSV (SIMD) entries for specific PowerPC 10480093f4SDimitry Andric // subtargets. 11480093f4SDimitry Andric // Following is an example of a conversion specific to Power9 subtarget: 12480093f4SDimitry Andric // __sind2_massv ---> __sind2_P9 13480093f4SDimitry Andric // 14480093f4SDimitry Andric //===----------------------------------------------------------------------===// 15480093f4SDimitry Andric 16480093f4SDimitry Andric #include "PPC.h" 17480093f4SDimitry Andric #include "PPCSubtarget.h" 18480093f4SDimitry Andric #include "PPCTargetMachine.h" 19e8d8bef9SDimitry Andric #include "llvm/ADT/STLExtras.h" 20480093f4SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h" 21480093f4SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h" 22480093f4SDimitry Andric #include "llvm/IR/Instructions.h" 23480093f4SDimitry Andric #include "llvm/IR/Module.h" 24480093f4SDimitry Andric 25480093f4SDimitry Andric #define DEBUG_TYPE "ppc-lower-massv-entries" 26480093f4SDimitry Andric 27480093f4SDimitry Andric using namespace llvm; 28480093f4SDimitry Andric 29480093f4SDimitry Andric namespace { 30480093f4SDimitry Andric 31480093f4SDimitry Andric static StringRef MASSVFuncs[] = { 32*0fca6ea1SDimitry Andric #define TLI_DEFINE_MASSV_VECFUNCS 33*0fca6ea1SDimitry Andric #define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, VABI_PREFIX) VEC, 34480093f4SDimitry Andric #include "llvm/Analysis/VecFuncs.def" 35*0fca6ea1SDimitry Andric #undef TLI_DEFINE_MASSV_VECFUNCS 36480093f4SDimitry Andric }; 37480093f4SDimitry Andric 38480093f4SDimitry Andric class PPCLowerMASSVEntries : public ModulePass { 39480093f4SDimitry Andric public: 40480093f4SDimitry Andric static char ID; 41480093f4SDimitry Andric 42480093f4SDimitry Andric PPCLowerMASSVEntries() : ModulePass(ID) {} 43480093f4SDimitry Andric 44480093f4SDimitry Andric bool runOnModule(Module &M) override; 45480093f4SDimitry Andric 46480093f4SDimitry Andric StringRef getPassName() const override { return "PPC Lower MASS Entries"; } 47480093f4SDimitry Andric 48480093f4SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 49480093f4SDimitry Andric AU.addRequired<TargetTransformInfoWrapperPass>(); 50480093f4SDimitry Andric } 51480093f4SDimitry Andric 52480093f4SDimitry Andric private: 53480093f4SDimitry Andric static bool isMASSVFunc(StringRef Name); 54480093f4SDimitry Andric static StringRef getCPUSuffix(const PPCSubtarget *Subtarget); 55480093f4SDimitry Andric static std::string createMASSVFuncName(Function &Func, 56480093f4SDimitry Andric const PPCSubtarget *Subtarget); 575ffd83dbSDimitry Andric bool handlePowSpecialCases(CallInst *CI, Function &Func, Module &M); 58480093f4SDimitry Andric bool lowerMASSVCall(CallInst *CI, Function &Func, Module &M, 59480093f4SDimitry Andric const PPCSubtarget *Subtarget); 60480093f4SDimitry Andric }; 61480093f4SDimitry Andric 62480093f4SDimitry Andric } // namespace 63480093f4SDimitry Andric 64480093f4SDimitry Andric /// Checks if the specified function name represents an entry in the MASSV 65480093f4SDimitry Andric /// library. 66480093f4SDimitry Andric bool PPCLowerMASSVEntries::isMASSVFunc(StringRef Name) { 67e8d8bef9SDimitry Andric return llvm::is_contained(MASSVFuncs, Name); 68480093f4SDimitry Andric } 69480093f4SDimitry Andric 70480093f4SDimitry Andric // FIXME: 71480093f4SDimitry Andric /// Returns a string corresponding to the specified PowerPC subtarget. e.g.: 72fe6060f1SDimitry Andric /// "_P8" for Power8, "_P9" for Power9. The string is used as a suffix while 73480093f4SDimitry Andric /// generating subtarget-specific MASSV library functions. Current support 74fe6060f1SDimitry Andric /// includes minimum subtarget Power8 for Linux and Power7 for AIX. 75480093f4SDimitry Andric StringRef PPCLowerMASSVEntries::getCPUSuffix(const PPCSubtarget *Subtarget) { 76fe6060f1SDimitry Andric // Assume generic when Subtarget is unavailable. 77480093f4SDimitry Andric if (!Subtarget) 78fe6060f1SDimitry Andric return ""; 79fe6060f1SDimitry Andric // TODO: add _P10 enties to Linux MASS lib and remove the check for AIX 80fe6060f1SDimitry Andric if (Subtarget->isAIXABI() && Subtarget->hasP10Vector()) 81fe6060f1SDimitry Andric return "_P10"; 82480093f4SDimitry Andric if (Subtarget->hasP9Vector()) 83fe6060f1SDimitry Andric return "_P9"; 84480093f4SDimitry Andric if (Subtarget->hasP8Vector()) 85fe6060f1SDimitry Andric return "_P8"; 86fe6060f1SDimitry Andric if (Subtarget->isAIXABI()) 87fe6060f1SDimitry Andric return "_P7"; 88480093f4SDimitry Andric 89fe6060f1SDimitry Andric report_fatal_error( 90fe6060f1SDimitry Andric "Mininum subtarget for -vector-library=MASSV option is Power8 on Linux " 91fe6060f1SDimitry Andric "and Power7 on AIX when vectorization is not disabled."); 92480093f4SDimitry Andric } 93480093f4SDimitry Andric 94480093f4SDimitry Andric /// Creates PowerPC subtarget-specific name corresponding to the specified 95480093f4SDimitry Andric /// generic MASSV function, and the PowerPC subtarget. 96480093f4SDimitry Andric std::string 97480093f4SDimitry Andric PPCLowerMASSVEntries::createMASSVFuncName(Function &Func, 98480093f4SDimitry Andric const PPCSubtarget *Subtarget) { 99480093f4SDimitry Andric StringRef Suffix = getCPUSuffix(Subtarget); 100fe6060f1SDimitry Andric auto GenericName = Func.getName().str(); 101480093f4SDimitry Andric std::string MASSVEntryName = GenericName + Suffix.str(); 102480093f4SDimitry Andric return MASSVEntryName; 103480093f4SDimitry Andric } 104480093f4SDimitry Andric 1055ffd83dbSDimitry Andric /// If there are proper fast-math flags, this function creates llvm.pow 1065ffd83dbSDimitry Andric /// intrinsics when the exponent is 0.25 or 0.75. 1075ffd83dbSDimitry Andric bool PPCLowerMASSVEntries::handlePowSpecialCases(CallInst *CI, Function &Func, 1085ffd83dbSDimitry Andric Module &M) { 109fe6060f1SDimitry Andric if (Func.getName() != "__powf4" && Func.getName() != "__powd2") 1105ffd83dbSDimitry Andric return false; 1115ffd83dbSDimitry Andric 1125ffd83dbSDimitry Andric if (Constant *Exp = dyn_cast<Constant>(CI->getArgOperand(1))) 113e8d8bef9SDimitry Andric if (ConstantFP *CFP = dyn_cast_or_null<ConstantFP>(Exp->getSplatValue())) { 1145ffd83dbSDimitry Andric // If the argument is 0.75 or 0.25 it is cheaper to turn it into pow 1155ffd83dbSDimitry Andric // intrinsic so that it could be optimzed as sequence of sqrt's. 1165ffd83dbSDimitry Andric if (!CI->hasNoInfs() || !CI->hasApproxFunc()) 1175ffd83dbSDimitry Andric return false; 1185ffd83dbSDimitry Andric 1195ffd83dbSDimitry Andric if (!CFP->isExactlyValue(0.75) && !CFP->isExactlyValue(0.25)) 1205ffd83dbSDimitry Andric return false; 1215ffd83dbSDimitry Andric 1225ffd83dbSDimitry Andric if (CFP->isExactlyValue(0.25) && !CI->hasNoSignedZeros()) 1235ffd83dbSDimitry Andric return false; 1245ffd83dbSDimitry Andric 1255ffd83dbSDimitry Andric CI->setCalledFunction( 1265ffd83dbSDimitry Andric Intrinsic::getDeclaration(&M, Intrinsic::pow, CI->getType())); 1275ffd83dbSDimitry Andric return true; 1285ffd83dbSDimitry Andric } 1295ffd83dbSDimitry Andric 1305ffd83dbSDimitry Andric return false; 1315ffd83dbSDimitry Andric } 1325ffd83dbSDimitry Andric 133480093f4SDimitry Andric /// Lowers generic MASSV entries to PowerPC subtarget-specific MASSV entries. 134480093f4SDimitry Andric /// e.g.: __sind2_massv --> __sind2_P9 for a Power9 subtarget. 135480093f4SDimitry Andric /// Both function prototypes and their callsites are updated during lowering. 136480093f4SDimitry Andric bool PPCLowerMASSVEntries::lowerMASSVCall(CallInst *CI, Function &Func, 137480093f4SDimitry Andric Module &M, 138480093f4SDimitry Andric const PPCSubtarget *Subtarget) { 139480093f4SDimitry Andric if (CI->use_empty()) 140480093f4SDimitry Andric return false; 141480093f4SDimitry Andric 1425ffd83dbSDimitry Andric // Handling pow(x, 0.25), pow(x, 0.75), powf(x, 0.25), powf(x, 0.75) 1435ffd83dbSDimitry Andric if (handlePowSpecialCases(CI, Func, M)) 1445ffd83dbSDimitry Andric return true; 1455ffd83dbSDimitry Andric 146480093f4SDimitry Andric std::string MASSVEntryName = createMASSVFuncName(Func, Subtarget); 147480093f4SDimitry Andric FunctionCallee FCache = M.getOrInsertFunction( 148480093f4SDimitry Andric MASSVEntryName, Func.getFunctionType(), Func.getAttributes()); 149480093f4SDimitry Andric 150480093f4SDimitry Andric CI->setCalledFunction(FCache); 151480093f4SDimitry Andric 152480093f4SDimitry Andric return true; 153480093f4SDimitry Andric } 154480093f4SDimitry Andric 155480093f4SDimitry Andric bool PPCLowerMASSVEntries::runOnModule(Module &M) { 156480093f4SDimitry Andric bool Changed = false; 157480093f4SDimitry Andric 158480093f4SDimitry Andric auto *TPC = getAnalysisIfAvailable<TargetPassConfig>(); 159480093f4SDimitry Andric if (!TPC) 160480093f4SDimitry Andric return Changed; 161480093f4SDimitry Andric 162480093f4SDimitry Andric auto &TM = TPC->getTM<PPCTargetMachine>(); 163480093f4SDimitry Andric const PPCSubtarget *Subtarget; 164480093f4SDimitry Andric 165480093f4SDimitry Andric for (Function &Func : M) { 166480093f4SDimitry Andric if (!Func.isDeclaration()) 167480093f4SDimitry Andric continue; 168480093f4SDimitry Andric 169480093f4SDimitry Andric if (!isMASSVFunc(Func.getName())) 170480093f4SDimitry Andric continue; 171480093f4SDimitry Andric 172480093f4SDimitry Andric // Call to lowerMASSVCall() invalidates the iterator over users upon 173480093f4SDimitry Andric // replacing the users. Precomputing the current list of users allows us to 174480093f4SDimitry Andric // replace all the call sites. 175fe6060f1SDimitry Andric SmallVector<User *, 4> MASSVUsers(Func.users()); 176480093f4SDimitry Andric 177480093f4SDimitry Andric for (auto *User : MASSVUsers) { 178480093f4SDimitry Andric auto *CI = dyn_cast<CallInst>(User); 179480093f4SDimitry Andric if (!CI) 180480093f4SDimitry Andric continue; 181480093f4SDimitry Andric 182480093f4SDimitry Andric Subtarget = &TM.getSubtarget<PPCSubtarget>(*CI->getParent()->getParent()); 183480093f4SDimitry Andric Changed |= lowerMASSVCall(CI, Func, M, Subtarget); 184480093f4SDimitry Andric } 185480093f4SDimitry Andric } 186480093f4SDimitry Andric 187480093f4SDimitry Andric return Changed; 188480093f4SDimitry Andric } 189480093f4SDimitry Andric 190480093f4SDimitry Andric char PPCLowerMASSVEntries::ID = 0; 191480093f4SDimitry Andric 192480093f4SDimitry Andric char &llvm::PPCLowerMASSVEntriesID = PPCLowerMASSVEntries::ID; 193480093f4SDimitry Andric 194480093f4SDimitry Andric INITIALIZE_PASS(PPCLowerMASSVEntries, DEBUG_TYPE, "Lower MASSV entries", false, 195480093f4SDimitry Andric false) 196480093f4SDimitry Andric 197480093f4SDimitry Andric ModulePass *llvm::createPPCLowerMASSVEntriesPass() { 198480093f4SDimitry Andric return new PPCLowerMASSVEntries(); 199480093f4SDimitry Andric } 200