1*480093f4SDimitry Andric //===-- PPCLowerMASSVEntries.cpp ------------------------------------------===// 2*480093f4SDimitry Andric // 3*480093f4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*480093f4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*480093f4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*480093f4SDimitry Andric // 7*480093f4SDimitry Andric //===----------------------------------------------------------------------===// 8*480093f4SDimitry Andric // 9*480093f4SDimitry Andric // This file implements lowering of MASSV (SIMD) entries for specific PowerPC 10*480093f4SDimitry Andric // subtargets. 11*480093f4SDimitry Andric // Following is an example of a conversion specific to Power9 subtarget: 12*480093f4SDimitry Andric // __sind2_massv ---> __sind2_P9 13*480093f4SDimitry Andric // 14*480093f4SDimitry Andric //===----------------------------------------------------------------------===// 15*480093f4SDimitry Andric 16*480093f4SDimitry Andric #include "PPC.h" 17*480093f4SDimitry Andric #include "PPCSubtarget.h" 18*480093f4SDimitry Andric #include "PPCTargetMachine.h" 19*480093f4SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h" 20*480093f4SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h" 21*480093f4SDimitry Andric #include "llvm/IR/Instructions.h" 22*480093f4SDimitry Andric #include "llvm/IR/Module.h" 23*480093f4SDimitry Andric 24*480093f4SDimitry Andric #define DEBUG_TYPE "ppc-lower-massv-entries" 25*480093f4SDimitry Andric 26*480093f4SDimitry Andric using namespace llvm; 27*480093f4SDimitry Andric 28*480093f4SDimitry Andric namespace { 29*480093f4SDimitry Andric 30*480093f4SDimitry Andric // Length of the suffix "massv", which is specific to IBM MASSV library entries. 31*480093f4SDimitry Andric const unsigned MASSVSuffixLength = 5; 32*480093f4SDimitry Andric 33*480093f4SDimitry Andric static StringRef MASSVFuncs[] = { 34*480093f4SDimitry Andric #define TLI_DEFINE_MASSV_VECFUNCS_NAMES 35*480093f4SDimitry Andric #include "llvm/Analysis/VecFuncs.def" 36*480093f4SDimitry Andric }; 37*480093f4SDimitry Andric 38*480093f4SDimitry Andric class PPCLowerMASSVEntries : public ModulePass { 39*480093f4SDimitry Andric public: 40*480093f4SDimitry Andric static char ID; 41*480093f4SDimitry Andric 42*480093f4SDimitry Andric PPCLowerMASSVEntries() : ModulePass(ID) {} 43*480093f4SDimitry Andric 44*480093f4SDimitry Andric bool runOnModule(Module &M) override; 45*480093f4SDimitry Andric 46*480093f4SDimitry Andric StringRef getPassName() const override { return "PPC Lower MASS Entries"; } 47*480093f4SDimitry Andric 48*480093f4SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 49*480093f4SDimitry Andric AU.addRequired<TargetTransformInfoWrapperPass>(); 50*480093f4SDimitry Andric } 51*480093f4SDimitry Andric 52*480093f4SDimitry Andric private: 53*480093f4SDimitry Andric static bool isMASSVFunc(StringRef Name); 54*480093f4SDimitry Andric static StringRef getCPUSuffix(const PPCSubtarget *Subtarget); 55*480093f4SDimitry Andric static std::string createMASSVFuncName(Function &Func, 56*480093f4SDimitry Andric const PPCSubtarget *Subtarget); 57*480093f4SDimitry Andric bool lowerMASSVCall(CallInst *CI, Function &Func, Module &M, 58*480093f4SDimitry Andric const PPCSubtarget *Subtarget); 59*480093f4SDimitry Andric }; 60*480093f4SDimitry Andric 61*480093f4SDimitry Andric } // namespace 62*480093f4SDimitry Andric 63*480093f4SDimitry Andric /// Checks if the specified function name represents an entry in the MASSV 64*480093f4SDimitry Andric /// library. 65*480093f4SDimitry Andric bool PPCLowerMASSVEntries::isMASSVFunc(StringRef Name) { 66*480093f4SDimitry Andric auto Iter = std::find(std::begin(MASSVFuncs), std::end(MASSVFuncs), Name); 67*480093f4SDimitry Andric return Iter != std::end(MASSVFuncs); 68*480093f4SDimitry Andric } 69*480093f4SDimitry Andric 70*480093f4SDimitry Andric // FIXME: 71*480093f4SDimitry Andric /// Returns a string corresponding to the specified PowerPC subtarget. e.g.: 72*480093f4SDimitry Andric /// "P8" for Power8, "P9" for Power9. The string is used as a suffix while 73*480093f4SDimitry Andric /// generating subtarget-specific MASSV library functions. Current support 74*480093f4SDimitry Andric /// includes Power8 and Power9 subtargets. 75*480093f4SDimitry Andric StringRef PPCLowerMASSVEntries::getCPUSuffix(const PPCSubtarget *Subtarget) { 76*480093f4SDimitry Andric // Assume Power8 when Subtarget is unavailable. 77*480093f4SDimitry Andric if (!Subtarget) 78*480093f4SDimitry Andric return "P8"; 79*480093f4SDimitry Andric if (Subtarget->hasP9Vector()) 80*480093f4SDimitry Andric return "P9"; 81*480093f4SDimitry Andric if (Subtarget->hasP8Vector()) 82*480093f4SDimitry Andric return "P8"; 83*480093f4SDimitry Andric 84*480093f4SDimitry Andric report_fatal_error("Unsupported Subtarget: MASSV is supported only on " 85*480093f4SDimitry Andric "Power8 and Power9 subtargets."); 86*480093f4SDimitry Andric } 87*480093f4SDimitry Andric 88*480093f4SDimitry Andric /// Creates PowerPC subtarget-specific name corresponding to the specified 89*480093f4SDimitry Andric /// generic MASSV function, and the PowerPC subtarget. 90*480093f4SDimitry Andric std::string 91*480093f4SDimitry Andric PPCLowerMASSVEntries::createMASSVFuncName(Function &Func, 92*480093f4SDimitry Andric const PPCSubtarget *Subtarget) { 93*480093f4SDimitry Andric StringRef Suffix = getCPUSuffix(Subtarget); 94*480093f4SDimitry Andric auto GenericName = Func.getName().drop_back(MASSVSuffixLength).str(); 95*480093f4SDimitry Andric std::string MASSVEntryName = GenericName + Suffix.str(); 96*480093f4SDimitry Andric return MASSVEntryName; 97*480093f4SDimitry Andric } 98*480093f4SDimitry Andric 99*480093f4SDimitry Andric /// Lowers generic MASSV entries to PowerPC subtarget-specific MASSV entries. 100*480093f4SDimitry Andric /// e.g.: __sind2_massv --> __sind2_P9 for a Power9 subtarget. 101*480093f4SDimitry Andric /// Both function prototypes and their callsites are updated during lowering. 102*480093f4SDimitry Andric bool PPCLowerMASSVEntries::lowerMASSVCall(CallInst *CI, Function &Func, 103*480093f4SDimitry Andric Module &M, 104*480093f4SDimitry Andric const PPCSubtarget *Subtarget) { 105*480093f4SDimitry Andric if (CI->use_empty()) 106*480093f4SDimitry Andric return false; 107*480093f4SDimitry Andric 108*480093f4SDimitry Andric std::string MASSVEntryName = createMASSVFuncName(Func, Subtarget); 109*480093f4SDimitry Andric FunctionCallee FCache = M.getOrInsertFunction( 110*480093f4SDimitry Andric MASSVEntryName, Func.getFunctionType(), Func.getAttributes()); 111*480093f4SDimitry Andric 112*480093f4SDimitry Andric CallSite CS(CI); 113*480093f4SDimitry Andric CI->setCalledFunction(FCache); 114*480093f4SDimitry Andric 115*480093f4SDimitry Andric return true; 116*480093f4SDimitry Andric } 117*480093f4SDimitry Andric 118*480093f4SDimitry Andric bool PPCLowerMASSVEntries::runOnModule(Module &M) { 119*480093f4SDimitry Andric bool Changed = false; 120*480093f4SDimitry Andric 121*480093f4SDimitry Andric auto *TPC = getAnalysisIfAvailable<TargetPassConfig>(); 122*480093f4SDimitry Andric if (!TPC) 123*480093f4SDimitry Andric return Changed; 124*480093f4SDimitry Andric 125*480093f4SDimitry Andric auto &TM = TPC->getTM<PPCTargetMachine>(); 126*480093f4SDimitry Andric const PPCSubtarget *Subtarget; 127*480093f4SDimitry Andric 128*480093f4SDimitry Andric for (Function &Func : M) { 129*480093f4SDimitry Andric if (!Func.isDeclaration()) 130*480093f4SDimitry Andric continue; 131*480093f4SDimitry Andric 132*480093f4SDimitry Andric if (!isMASSVFunc(Func.getName())) 133*480093f4SDimitry Andric continue; 134*480093f4SDimitry Andric 135*480093f4SDimitry Andric // Call to lowerMASSVCall() invalidates the iterator over users upon 136*480093f4SDimitry Andric // replacing the users. Precomputing the current list of users allows us to 137*480093f4SDimitry Andric // replace all the call sites. 138*480093f4SDimitry Andric SmallVector<User *, 4> MASSVUsers; 139*480093f4SDimitry Andric for (auto *User: Func.users()) 140*480093f4SDimitry Andric MASSVUsers.push_back(User); 141*480093f4SDimitry Andric 142*480093f4SDimitry Andric for (auto *User : MASSVUsers) { 143*480093f4SDimitry Andric auto *CI = dyn_cast<CallInst>(User); 144*480093f4SDimitry Andric if (!CI) 145*480093f4SDimitry Andric continue; 146*480093f4SDimitry Andric 147*480093f4SDimitry Andric Subtarget = &TM.getSubtarget<PPCSubtarget>(*CI->getParent()->getParent()); 148*480093f4SDimitry Andric Changed |= lowerMASSVCall(CI, Func, M, Subtarget); 149*480093f4SDimitry Andric } 150*480093f4SDimitry Andric } 151*480093f4SDimitry Andric 152*480093f4SDimitry Andric return Changed; 153*480093f4SDimitry Andric } 154*480093f4SDimitry Andric 155*480093f4SDimitry Andric char PPCLowerMASSVEntries::ID = 0; 156*480093f4SDimitry Andric 157*480093f4SDimitry Andric char &llvm::PPCLowerMASSVEntriesID = PPCLowerMASSVEntries::ID; 158*480093f4SDimitry Andric 159*480093f4SDimitry Andric INITIALIZE_PASS(PPCLowerMASSVEntries, DEBUG_TYPE, "Lower MASSV entries", false, 160*480093f4SDimitry Andric false) 161*480093f4SDimitry Andric 162*480093f4SDimitry Andric ModulePass *llvm::createPPCLowerMASSVEntriesPass() { 163*480093f4SDimitry Andric return new PPCLowerMASSVEntries(); 164*480093f4SDimitry Andric } 165