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