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" 19*e8d8bef9SDimitry 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 // Length of the suffix "massv", which is specific to IBM MASSV library entries. 32480093f4SDimitry Andric const unsigned MASSVSuffixLength = 5; 33480093f4SDimitry Andric 34480093f4SDimitry Andric static StringRef MASSVFuncs[] = { 35480093f4SDimitry Andric #define TLI_DEFINE_MASSV_VECFUNCS_NAMES 36480093f4SDimitry Andric #include "llvm/Analysis/VecFuncs.def" 37480093f4SDimitry Andric }; 38480093f4SDimitry Andric 39480093f4SDimitry Andric class PPCLowerMASSVEntries : public ModulePass { 40480093f4SDimitry Andric public: 41480093f4SDimitry Andric static char ID; 42480093f4SDimitry Andric 43480093f4SDimitry Andric PPCLowerMASSVEntries() : ModulePass(ID) {} 44480093f4SDimitry Andric 45480093f4SDimitry Andric bool runOnModule(Module &M) override; 46480093f4SDimitry Andric 47480093f4SDimitry Andric StringRef getPassName() const override { return "PPC Lower MASS Entries"; } 48480093f4SDimitry Andric 49480093f4SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 50480093f4SDimitry Andric AU.addRequired<TargetTransformInfoWrapperPass>(); 51480093f4SDimitry Andric } 52480093f4SDimitry Andric 53480093f4SDimitry Andric private: 54480093f4SDimitry Andric static bool isMASSVFunc(StringRef Name); 55480093f4SDimitry Andric static StringRef getCPUSuffix(const PPCSubtarget *Subtarget); 56480093f4SDimitry Andric static std::string createMASSVFuncName(Function &Func, 57480093f4SDimitry Andric const PPCSubtarget *Subtarget); 585ffd83dbSDimitry Andric bool handlePowSpecialCases(CallInst *CI, Function &Func, Module &M); 59480093f4SDimitry Andric bool lowerMASSVCall(CallInst *CI, Function &Func, Module &M, 60480093f4SDimitry Andric const PPCSubtarget *Subtarget); 61480093f4SDimitry Andric }; 62480093f4SDimitry Andric 63480093f4SDimitry Andric } // namespace 64480093f4SDimitry Andric 65480093f4SDimitry Andric /// Checks if the specified function name represents an entry in the MASSV 66480093f4SDimitry Andric /// library. 67480093f4SDimitry Andric bool PPCLowerMASSVEntries::isMASSVFunc(StringRef Name) { 68*e8d8bef9SDimitry Andric return llvm::is_contained(MASSVFuncs, Name); 69480093f4SDimitry Andric } 70480093f4SDimitry Andric 71480093f4SDimitry Andric // FIXME: 72480093f4SDimitry Andric /// Returns a string corresponding to the specified PowerPC subtarget. e.g.: 73480093f4SDimitry Andric /// "P8" for Power8, "P9" for Power9. The string is used as a suffix while 74480093f4SDimitry Andric /// generating subtarget-specific MASSV library functions. Current support 75480093f4SDimitry Andric /// includes Power8 and Power9 subtargets. 76480093f4SDimitry Andric StringRef PPCLowerMASSVEntries::getCPUSuffix(const PPCSubtarget *Subtarget) { 77480093f4SDimitry Andric // Assume Power8 when Subtarget is unavailable. 78480093f4SDimitry Andric if (!Subtarget) 79480093f4SDimitry Andric return "P8"; 80480093f4SDimitry Andric if (Subtarget->hasP9Vector()) 81480093f4SDimitry Andric return "P9"; 82480093f4SDimitry Andric if (Subtarget->hasP8Vector()) 83480093f4SDimitry Andric return "P8"; 84480093f4SDimitry Andric 85480093f4SDimitry Andric report_fatal_error("Unsupported Subtarget: MASSV is supported only on " 86480093f4SDimitry Andric "Power8 and Power9 subtargets."); 87480093f4SDimitry Andric } 88480093f4SDimitry Andric 89480093f4SDimitry Andric /// Creates PowerPC subtarget-specific name corresponding to the specified 90480093f4SDimitry Andric /// generic MASSV function, and the PowerPC subtarget. 91480093f4SDimitry Andric std::string 92480093f4SDimitry Andric PPCLowerMASSVEntries::createMASSVFuncName(Function &Func, 93480093f4SDimitry Andric const PPCSubtarget *Subtarget) { 94480093f4SDimitry Andric StringRef Suffix = getCPUSuffix(Subtarget); 95480093f4SDimitry Andric auto GenericName = Func.getName().drop_back(MASSVSuffixLength).str(); 96480093f4SDimitry Andric std::string MASSVEntryName = GenericName + Suffix.str(); 97480093f4SDimitry Andric return MASSVEntryName; 98480093f4SDimitry Andric } 99480093f4SDimitry Andric 1005ffd83dbSDimitry Andric /// If there are proper fast-math flags, this function creates llvm.pow 1015ffd83dbSDimitry Andric /// intrinsics when the exponent is 0.25 or 0.75. 1025ffd83dbSDimitry Andric bool PPCLowerMASSVEntries::handlePowSpecialCases(CallInst *CI, Function &Func, 1035ffd83dbSDimitry Andric Module &M) { 1045ffd83dbSDimitry Andric if (Func.getName() != "__powf4_massv" && Func.getName() != "__powd2_massv") 1055ffd83dbSDimitry Andric return false; 1065ffd83dbSDimitry Andric 1075ffd83dbSDimitry Andric if (Constant *Exp = dyn_cast<Constant>(CI->getArgOperand(1))) 108*e8d8bef9SDimitry Andric if (ConstantFP *CFP = dyn_cast_or_null<ConstantFP>(Exp->getSplatValue())) { 1095ffd83dbSDimitry Andric // If the argument is 0.75 or 0.25 it is cheaper to turn it into pow 1105ffd83dbSDimitry Andric // intrinsic so that it could be optimzed as sequence of sqrt's. 1115ffd83dbSDimitry Andric if (!CI->hasNoInfs() || !CI->hasApproxFunc()) 1125ffd83dbSDimitry Andric return false; 1135ffd83dbSDimitry Andric 1145ffd83dbSDimitry Andric if (!CFP->isExactlyValue(0.75) && !CFP->isExactlyValue(0.25)) 1155ffd83dbSDimitry Andric return false; 1165ffd83dbSDimitry Andric 1175ffd83dbSDimitry Andric if (CFP->isExactlyValue(0.25) && !CI->hasNoSignedZeros()) 1185ffd83dbSDimitry Andric return false; 1195ffd83dbSDimitry Andric 1205ffd83dbSDimitry Andric CI->setCalledFunction( 1215ffd83dbSDimitry Andric Intrinsic::getDeclaration(&M, Intrinsic::pow, CI->getType())); 1225ffd83dbSDimitry Andric return true; 1235ffd83dbSDimitry Andric } 1245ffd83dbSDimitry Andric 1255ffd83dbSDimitry Andric return false; 1265ffd83dbSDimitry Andric } 1275ffd83dbSDimitry Andric 128480093f4SDimitry Andric /// Lowers generic MASSV entries to PowerPC subtarget-specific MASSV entries. 129480093f4SDimitry Andric /// e.g.: __sind2_massv --> __sind2_P9 for a Power9 subtarget. 130480093f4SDimitry Andric /// Both function prototypes and their callsites are updated during lowering. 131480093f4SDimitry Andric bool PPCLowerMASSVEntries::lowerMASSVCall(CallInst *CI, Function &Func, 132480093f4SDimitry Andric Module &M, 133480093f4SDimitry Andric const PPCSubtarget *Subtarget) { 134480093f4SDimitry Andric if (CI->use_empty()) 135480093f4SDimitry Andric return false; 136480093f4SDimitry Andric 1375ffd83dbSDimitry Andric // Handling pow(x, 0.25), pow(x, 0.75), powf(x, 0.25), powf(x, 0.75) 1385ffd83dbSDimitry Andric if (handlePowSpecialCases(CI, Func, M)) 1395ffd83dbSDimitry Andric return true; 1405ffd83dbSDimitry Andric 141480093f4SDimitry Andric std::string MASSVEntryName = createMASSVFuncName(Func, Subtarget); 142480093f4SDimitry Andric FunctionCallee FCache = M.getOrInsertFunction( 143480093f4SDimitry Andric MASSVEntryName, Func.getFunctionType(), Func.getAttributes()); 144480093f4SDimitry Andric 145480093f4SDimitry Andric CI->setCalledFunction(FCache); 146480093f4SDimitry Andric 147480093f4SDimitry Andric return true; 148480093f4SDimitry Andric } 149480093f4SDimitry Andric 150480093f4SDimitry Andric bool PPCLowerMASSVEntries::runOnModule(Module &M) { 151480093f4SDimitry Andric bool Changed = false; 152480093f4SDimitry Andric 153480093f4SDimitry Andric auto *TPC = getAnalysisIfAvailable<TargetPassConfig>(); 154480093f4SDimitry Andric if (!TPC) 155480093f4SDimitry Andric return Changed; 156480093f4SDimitry Andric 157480093f4SDimitry Andric auto &TM = TPC->getTM<PPCTargetMachine>(); 158480093f4SDimitry Andric const PPCSubtarget *Subtarget; 159480093f4SDimitry Andric 160480093f4SDimitry Andric for (Function &Func : M) { 161480093f4SDimitry Andric if (!Func.isDeclaration()) 162480093f4SDimitry Andric continue; 163480093f4SDimitry Andric 164480093f4SDimitry Andric if (!isMASSVFunc(Func.getName())) 165480093f4SDimitry Andric continue; 166480093f4SDimitry Andric 167480093f4SDimitry Andric // Call to lowerMASSVCall() invalidates the iterator over users upon 168480093f4SDimitry Andric // replacing the users. Precomputing the current list of users allows us to 169480093f4SDimitry Andric // replace all the call sites. 170480093f4SDimitry Andric SmallVector<User *, 4> MASSVUsers; 171480093f4SDimitry Andric for (auto *User: Func.users()) 172480093f4SDimitry Andric MASSVUsers.push_back(User); 173480093f4SDimitry Andric 174480093f4SDimitry Andric for (auto *User : MASSVUsers) { 175480093f4SDimitry Andric auto *CI = dyn_cast<CallInst>(User); 176480093f4SDimitry Andric if (!CI) 177480093f4SDimitry Andric continue; 178480093f4SDimitry Andric 179480093f4SDimitry Andric Subtarget = &TM.getSubtarget<PPCSubtarget>(*CI->getParent()->getParent()); 180480093f4SDimitry Andric Changed |= lowerMASSVCall(CI, Func, M, Subtarget); 181480093f4SDimitry Andric } 182480093f4SDimitry Andric } 183480093f4SDimitry Andric 184480093f4SDimitry Andric return Changed; 185480093f4SDimitry Andric } 186480093f4SDimitry Andric 187480093f4SDimitry Andric char PPCLowerMASSVEntries::ID = 0; 188480093f4SDimitry Andric 189480093f4SDimitry Andric char &llvm::PPCLowerMASSVEntriesID = PPCLowerMASSVEntries::ID; 190480093f4SDimitry Andric 191480093f4SDimitry Andric INITIALIZE_PASS(PPCLowerMASSVEntries, DEBUG_TYPE, "Lower MASSV entries", false, 192480093f4SDimitry Andric false) 193480093f4SDimitry Andric 194480093f4SDimitry Andric ModulePass *llvm::createPPCLowerMASSVEntriesPass() { 195480093f4SDimitry Andric return new PPCLowerMASSVEntries(); 196480093f4SDimitry Andric } 197