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[] = { 32480093f4SDimitry Andric #define TLI_DEFINE_MASSV_VECFUNCS_NAMES 33480093f4SDimitry Andric #include "llvm/Analysis/VecFuncs.def" 34480093f4SDimitry Andric }; 35480093f4SDimitry Andric 36480093f4SDimitry Andric class PPCLowerMASSVEntries : public ModulePass { 37480093f4SDimitry Andric public: 38480093f4SDimitry Andric static char ID; 39480093f4SDimitry Andric 40480093f4SDimitry Andric PPCLowerMASSVEntries() : ModulePass(ID) {} 41480093f4SDimitry Andric 42480093f4SDimitry Andric bool runOnModule(Module &M) override; 43480093f4SDimitry Andric 44480093f4SDimitry Andric StringRef getPassName() const override { return "PPC Lower MASS Entries"; } 45480093f4SDimitry Andric 46480093f4SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 47480093f4SDimitry Andric AU.addRequired<TargetTransformInfoWrapperPass>(); 48480093f4SDimitry Andric } 49480093f4SDimitry Andric 50480093f4SDimitry Andric private: 51480093f4SDimitry Andric static bool isMASSVFunc(StringRef Name); 52480093f4SDimitry Andric static StringRef getCPUSuffix(const PPCSubtarget *Subtarget); 53480093f4SDimitry Andric static std::string createMASSVFuncName(Function &Func, 54480093f4SDimitry Andric const PPCSubtarget *Subtarget); 555ffd83dbSDimitry Andric bool handlePowSpecialCases(CallInst *CI, Function &Func, Module &M); 56480093f4SDimitry Andric bool lowerMASSVCall(CallInst *CI, Function &Func, Module &M, 57480093f4SDimitry Andric const PPCSubtarget *Subtarget); 58480093f4SDimitry Andric }; 59480093f4SDimitry Andric 60480093f4SDimitry Andric } // namespace 61480093f4SDimitry Andric 62480093f4SDimitry Andric /// Checks if the specified function name represents an entry in the MASSV 63480093f4SDimitry Andric /// library. 64480093f4SDimitry Andric bool PPCLowerMASSVEntries::isMASSVFunc(StringRef Name) { 65e8d8bef9SDimitry Andric return llvm::is_contained(MASSVFuncs, Name); 66480093f4SDimitry Andric } 67480093f4SDimitry Andric 68480093f4SDimitry Andric // FIXME: 69480093f4SDimitry Andric /// Returns a string corresponding to the specified PowerPC subtarget. e.g.: 70*fe6060f1SDimitry Andric /// "_P8" for Power8, "_P9" for Power9. The string is used as a suffix while 71480093f4SDimitry Andric /// generating subtarget-specific MASSV library functions. Current support 72*fe6060f1SDimitry Andric /// includes minimum subtarget Power8 for Linux and Power7 for AIX. 73480093f4SDimitry Andric StringRef PPCLowerMASSVEntries::getCPUSuffix(const PPCSubtarget *Subtarget) { 74*fe6060f1SDimitry Andric // Assume generic when Subtarget is unavailable. 75480093f4SDimitry Andric if (!Subtarget) 76*fe6060f1SDimitry Andric return ""; 77*fe6060f1SDimitry Andric // TODO: add _P10 enties to Linux MASS lib and remove the check for AIX 78*fe6060f1SDimitry Andric if (Subtarget->isAIXABI() && Subtarget->hasP10Vector()) 79*fe6060f1SDimitry Andric return "_P10"; 80480093f4SDimitry Andric if (Subtarget->hasP9Vector()) 81*fe6060f1SDimitry Andric return "_P9"; 82480093f4SDimitry Andric if (Subtarget->hasP8Vector()) 83*fe6060f1SDimitry Andric return "_P8"; 84*fe6060f1SDimitry Andric if (Subtarget->isAIXABI()) 85*fe6060f1SDimitry Andric return "_P7"; 86480093f4SDimitry Andric 87*fe6060f1SDimitry Andric report_fatal_error( 88*fe6060f1SDimitry Andric "Mininum subtarget for -vector-library=MASSV option is Power8 on Linux " 89*fe6060f1SDimitry Andric "and Power7 on AIX when vectorization is not disabled."); 90480093f4SDimitry Andric } 91480093f4SDimitry Andric 92480093f4SDimitry Andric /// Creates PowerPC subtarget-specific name corresponding to the specified 93480093f4SDimitry Andric /// generic MASSV function, and the PowerPC subtarget. 94480093f4SDimitry Andric std::string 95480093f4SDimitry Andric PPCLowerMASSVEntries::createMASSVFuncName(Function &Func, 96480093f4SDimitry Andric const PPCSubtarget *Subtarget) { 97480093f4SDimitry Andric StringRef Suffix = getCPUSuffix(Subtarget); 98*fe6060f1SDimitry Andric auto GenericName = Func.getName().str(); 99480093f4SDimitry Andric std::string MASSVEntryName = GenericName + Suffix.str(); 100480093f4SDimitry Andric return MASSVEntryName; 101480093f4SDimitry Andric } 102480093f4SDimitry Andric 1035ffd83dbSDimitry Andric /// If there are proper fast-math flags, this function creates llvm.pow 1045ffd83dbSDimitry Andric /// intrinsics when the exponent is 0.25 or 0.75. 1055ffd83dbSDimitry Andric bool PPCLowerMASSVEntries::handlePowSpecialCases(CallInst *CI, Function &Func, 1065ffd83dbSDimitry Andric Module &M) { 107*fe6060f1SDimitry Andric if (Func.getName() != "__powf4" && Func.getName() != "__powd2") 1085ffd83dbSDimitry Andric return false; 1095ffd83dbSDimitry Andric 1105ffd83dbSDimitry Andric if (Constant *Exp = dyn_cast<Constant>(CI->getArgOperand(1))) 111e8d8bef9SDimitry Andric if (ConstantFP *CFP = dyn_cast_or_null<ConstantFP>(Exp->getSplatValue())) { 1125ffd83dbSDimitry Andric // If the argument is 0.75 or 0.25 it is cheaper to turn it into pow 1135ffd83dbSDimitry Andric // intrinsic so that it could be optimzed as sequence of sqrt's. 1145ffd83dbSDimitry Andric if (!CI->hasNoInfs() || !CI->hasApproxFunc()) 1155ffd83dbSDimitry Andric return false; 1165ffd83dbSDimitry Andric 1175ffd83dbSDimitry Andric if (!CFP->isExactlyValue(0.75) && !CFP->isExactlyValue(0.25)) 1185ffd83dbSDimitry Andric return false; 1195ffd83dbSDimitry Andric 1205ffd83dbSDimitry Andric if (CFP->isExactlyValue(0.25) && !CI->hasNoSignedZeros()) 1215ffd83dbSDimitry Andric return false; 1225ffd83dbSDimitry Andric 1235ffd83dbSDimitry Andric CI->setCalledFunction( 1245ffd83dbSDimitry Andric Intrinsic::getDeclaration(&M, Intrinsic::pow, CI->getType())); 1255ffd83dbSDimitry Andric return true; 1265ffd83dbSDimitry Andric } 1275ffd83dbSDimitry Andric 1285ffd83dbSDimitry Andric return false; 1295ffd83dbSDimitry Andric } 1305ffd83dbSDimitry Andric 131480093f4SDimitry Andric /// Lowers generic MASSV entries to PowerPC subtarget-specific MASSV entries. 132480093f4SDimitry Andric /// e.g.: __sind2_massv --> __sind2_P9 for a Power9 subtarget. 133480093f4SDimitry Andric /// Both function prototypes and their callsites are updated during lowering. 134480093f4SDimitry Andric bool PPCLowerMASSVEntries::lowerMASSVCall(CallInst *CI, Function &Func, 135480093f4SDimitry Andric Module &M, 136480093f4SDimitry Andric const PPCSubtarget *Subtarget) { 137480093f4SDimitry Andric if (CI->use_empty()) 138480093f4SDimitry Andric return false; 139480093f4SDimitry Andric 1405ffd83dbSDimitry Andric // Handling pow(x, 0.25), pow(x, 0.75), powf(x, 0.25), powf(x, 0.75) 1415ffd83dbSDimitry Andric if (handlePowSpecialCases(CI, Func, M)) 1425ffd83dbSDimitry Andric return true; 1435ffd83dbSDimitry Andric 144480093f4SDimitry Andric std::string MASSVEntryName = createMASSVFuncName(Func, Subtarget); 145480093f4SDimitry Andric FunctionCallee FCache = M.getOrInsertFunction( 146480093f4SDimitry Andric MASSVEntryName, Func.getFunctionType(), Func.getAttributes()); 147480093f4SDimitry Andric 148480093f4SDimitry Andric CI->setCalledFunction(FCache); 149480093f4SDimitry Andric 150480093f4SDimitry Andric return true; 151480093f4SDimitry Andric } 152480093f4SDimitry Andric 153480093f4SDimitry Andric bool PPCLowerMASSVEntries::runOnModule(Module &M) { 154480093f4SDimitry Andric bool Changed = false; 155480093f4SDimitry Andric 156480093f4SDimitry Andric auto *TPC = getAnalysisIfAvailable<TargetPassConfig>(); 157480093f4SDimitry Andric if (!TPC) 158480093f4SDimitry Andric return Changed; 159480093f4SDimitry Andric 160480093f4SDimitry Andric auto &TM = TPC->getTM<PPCTargetMachine>(); 161480093f4SDimitry Andric const PPCSubtarget *Subtarget; 162480093f4SDimitry Andric 163480093f4SDimitry Andric for (Function &Func : M) { 164480093f4SDimitry Andric if (!Func.isDeclaration()) 165480093f4SDimitry Andric continue; 166480093f4SDimitry Andric 167480093f4SDimitry Andric if (!isMASSVFunc(Func.getName())) 168480093f4SDimitry Andric continue; 169480093f4SDimitry Andric 170480093f4SDimitry Andric // Call to lowerMASSVCall() invalidates the iterator over users upon 171480093f4SDimitry Andric // replacing the users. Precomputing the current list of users allows us to 172480093f4SDimitry Andric // replace all the call sites. 173*fe6060f1SDimitry Andric SmallVector<User *, 4> MASSVUsers(Func.users()); 174480093f4SDimitry Andric 175480093f4SDimitry Andric for (auto *User : MASSVUsers) { 176480093f4SDimitry Andric auto *CI = dyn_cast<CallInst>(User); 177480093f4SDimitry Andric if (!CI) 178480093f4SDimitry Andric continue; 179480093f4SDimitry Andric 180480093f4SDimitry Andric Subtarget = &TM.getSubtarget<PPCSubtarget>(*CI->getParent()->getParent()); 181480093f4SDimitry Andric Changed |= lowerMASSVCall(CI, Func, M, Subtarget); 182480093f4SDimitry Andric } 183480093f4SDimitry Andric } 184480093f4SDimitry Andric 185480093f4SDimitry Andric return Changed; 186480093f4SDimitry Andric } 187480093f4SDimitry Andric 188480093f4SDimitry Andric char PPCLowerMASSVEntries::ID = 0; 189480093f4SDimitry Andric 190480093f4SDimitry Andric char &llvm::PPCLowerMASSVEntriesID = PPCLowerMASSVEntries::ID; 191480093f4SDimitry Andric 192480093f4SDimitry Andric INITIALIZE_PASS(PPCLowerMASSVEntries, DEBUG_TYPE, "Lower MASSV entries", false, 193480093f4SDimitry Andric false) 194480093f4SDimitry Andric 195480093f4SDimitry Andric ModulePass *llvm::createPPCLowerMASSVEntriesPass() { 196480093f4SDimitry Andric return new PPCLowerMASSVEntries(); 197480093f4SDimitry Andric } 198