| 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/ADT/STLExtras.h" |
| 20 | #include "llvm/Analysis/TargetTransformInfo.h" |
| 21 | #include "llvm/CodeGen/TargetPassConfig.h" |
| 22 | #include "llvm/IR/Instructions.h" |
| 23 | #include "llvm/IR/Module.h" |
| 24 | |
| 25 | #define DEBUG_TYPE "ppc-lower-massv-entries" |
| 26 | |
| 27 | using namespace llvm; |
| 28 | |
| 29 | namespace { |
| 30 | |
| 31 | static StringRef MASSVFuncs[] = { |
| 32 | #define TLI_DEFINE_MASSV_VECFUNCS |
| 33 | #define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, VABI_PREFIX) VEC, |
| 34 | #include "llvm/Analysis/VecFuncs.def" |
| 35 | #undef TLI_DEFINE_MASSV_VECFUNCS |
| 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 handlePowSpecialCases(CallInst *CI, Function &Func, Module &M); |
| 58 | bool lowerMASSVCall(CallInst *CI, Function &Func, Module &M, |
| 59 | const PPCSubtarget *Subtarget); |
| 60 | }; |
| 61 | |
| 62 | } // namespace |
| 63 | |
| 64 | /// Checks if the specified function name represents an entry in the MASSV |
| 65 | /// library. |
| 66 | bool PPCLowerMASSVEntries::isMASSVFunc(StringRef Name) { |
| 67 | return llvm::is_contained(Range&: MASSVFuncs, Element: Name); |
| 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 minimum subtarget Power8 for Linux and Power7 for AIX. |
| 75 | StringRef PPCLowerMASSVEntries::getCPUSuffix(const PPCSubtarget *Subtarget) { |
| 76 | // Assume generic when Subtarget is unavailable. |
| 77 | if (!Subtarget) |
| 78 | return "" ; |
| 79 | // TODO: add _P10 enties to Linux MASS lib and remove the check for AIX |
| 80 | if (Subtarget->isAIXABI() && Subtarget->hasP10Vector()) |
| 81 | return "_P10" ; |
| 82 | if (Subtarget->hasP9Vector()) |
| 83 | return "_P9" ; |
| 84 | if (Subtarget->hasP8Vector()) |
| 85 | return "_P8" ; |
| 86 | if (Subtarget->isAIXABI()) |
| 87 | return "_P7" ; |
| 88 | |
| 89 | report_fatal_error( |
| 90 | reason: "Mininum subtarget for -vector-library=MASSV option is Power8 on Linux " |
| 91 | "and Power7 on AIX when vectorization is not disabled." ); |
| 92 | } |
| 93 | |
| 94 | /// Creates PowerPC subtarget-specific name corresponding to the specified |
| 95 | /// generic MASSV function, and the PowerPC subtarget. |
| 96 | std::string |
| 97 | PPCLowerMASSVEntries::createMASSVFuncName(Function &Func, |
| 98 | const PPCSubtarget *Subtarget) { |
| 99 | StringRef Suffix = getCPUSuffix(Subtarget); |
| 100 | auto GenericName = Func.getName().str(); |
| 101 | std::string MASSVEntryName = GenericName + Suffix.str(); |
| 102 | return MASSVEntryName; |
| 103 | } |
| 104 | |
| 105 | /// If there are proper fast-math flags, this function creates llvm.pow |
| 106 | /// intrinsics when the exponent is 0.25 or 0.75. |
| 107 | bool PPCLowerMASSVEntries::handlePowSpecialCases(CallInst *CI, Function &Func, |
| 108 | Module &M) { |
| 109 | if (Func.getName() != "__powf4" && Func.getName() != "__powd2" ) |
| 110 | return false; |
| 111 | |
| 112 | if (Constant *Exp = dyn_cast<Constant>(Val: CI->getArgOperand(i: 1))) |
| 113 | if (ConstantFP *CFP = dyn_cast_or_null<ConstantFP>(Val: Exp->getSplatValue())) { |
| 114 | // If the argument is 0.75 or 0.25 it is cheaper to turn it into pow |
| 115 | // intrinsic so that it could be optimzed as sequence of sqrt's. |
| 116 | if (!CI->hasNoInfs() || !CI->hasApproxFunc()) |
| 117 | return false; |
| 118 | |
| 119 | if (!CFP->isExactlyValue(V: 0.75) && !CFP->isExactlyValue(V: 0.25)) |
| 120 | return false; |
| 121 | |
| 122 | if (CFP->isExactlyValue(V: 0.25) && !CI->hasNoSignedZeros()) |
| 123 | return false; |
| 124 | |
| 125 | CI->setCalledFunction( |
| 126 | Intrinsic::getOrInsertDeclaration(M: &M, id: Intrinsic::pow, Tys: CI->getType())); |
| 127 | return true; |
| 128 | } |
| 129 | |
| 130 | return false; |
| 131 | } |
| 132 | |
| 133 | /// Lowers generic MASSV entries to PowerPC subtarget-specific MASSV entries. |
| 134 | /// e.g.: __sind2_massv --> __sind2_P9 for a Power9 subtarget. |
| 135 | /// Both function prototypes and their callsites are updated during lowering. |
| 136 | bool PPCLowerMASSVEntries::lowerMASSVCall(CallInst *CI, Function &Func, |
| 137 | Module &M, |
| 138 | const PPCSubtarget *Subtarget) { |
| 139 | if (CI->use_empty()) |
| 140 | return false; |
| 141 | |
| 142 | // Handling pow(x, 0.25), pow(x, 0.75), powf(x, 0.25), powf(x, 0.75) |
| 143 | if (handlePowSpecialCases(CI, Func, M)) |
| 144 | return true; |
| 145 | |
| 146 | std::string MASSVEntryName = createMASSVFuncName(Func, Subtarget); |
| 147 | FunctionCallee FCache = M.getOrInsertFunction( |
| 148 | Name: MASSVEntryName, T: Func.getFunctionType(), AttributeList: Func.getAttributes()); |
| 149 | |
| 150 | CI->setCalledFunction(FCache); |
| 151 | |
| 152 | return true; |
| 153 | } |
| 154 | |
| 155 | bool PPCLowerMASSVEntries::runOnModule(Module &M) { |
| 156 | bool Changed = false; |
| 157 | |
| 158 | auto *TPC = getAnalysisIfAvailable<TargetPassConfig>(); |
| 159 | if (!TPC) |
| 160 | return Changed; |
| 161 | |
| 162 | auto &TM = TPC->getTM<PPCTargetMachine>(); |
| 163 | const PPCSubtarget *Subtarget; |
| 164 | |
| 165 | for (Function &Func : M) { |
| 166 | if (!Func.isDeclaration()) |
| 167 | continue; |
| 168 | |
| 169 | if (!isMASSVFunc(Name: Func.getName())) |
| 170 | continue; |
| 171 | |
| 172 | // Call to lowerMASSVCall() invalidates the iterator over users upon |
| 173 | // replacing the users. Precomputing the current list of users allows us to |
| 174 | // replace all the call sites. |
| 175 | SmallVector<User *, 4> MASSVUsers(Func.users()); |
| 176 | |
| 177 | for (auto *User : MASSVUsers) { |
| 178 | auto *CI = dyn_cast<CallInst>(Val: User); |
| 179 | if (!CI) |
| 180 | continue; |
| 181 | |
| 182 | Subtarget = &TM.getSubtarget<PPCSubtarget>(F: *CI->getParent()->getParent()); |
| 183 | Changed |= lowerMASSVCall(CI, Func, M, Subtarget); |
| 184 | } |
| 185 | } |
| 186 | |
| 187 | return Changed; |
| 188 | } |
| 189 | |
| 190 | char PPCLowerMASSVEntries::ID = 0; |
| 191 | |
| 192 | char &llvm::PPCLowerMASSVEntriesID = PPCLowerMASSVEntries::ID; |
| 193 | |
| 194 | INITIALIZE_PASS(PPCLowerMASSVEntries, DEBUG_TYPE, "Lower MASSV entries" , false, |
| 195 | false) |
| 196 | |
| 197 | ModulePass *llvm::createPPCLowerMASSVEntriesPass() { |
| 198 | return new PPCLowerMASSVEntries(); |
| 199 | } |
| 200 | |