PPCLowerMASSVEntries.cpp revision 360784
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
26using namespace llvm;
27
28namespace {
29
30// Length of the suffix "massv", which is specific to IBM MASSV library entries.
31const unsigned MASSVSuffixLength = 5;
32
33static StringRef MASSVFuncs[] = {
34#define TLI_DEFINE_MASSV_VECFUNCS_NAMES
35#include "llvm/Analysis/VecFuncs.def"
36};
37
38class PPCLowerMASSVEntries : public ModulePass {
39public:
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
52private:
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.
65bool 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.
75StringRef 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.
90std::string
91PPCLowerMASSVEntries::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.
102bool 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
118bool 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
155char PPCLowerMASSVEntries::ID = 0;
156
157char &llvm::PPCLowerMASSVEntriesID = PPCLowerMASSVEntries::ID;
158
159INITIALIZE_PASS(PPCLowerMASSVEntries, DEBUG_TYPE, "Lower MASSV entries", false,
160                false)
161
162ModulePass *llvm::createPPCLowerMASSVEntriesPass() {
163  return new PPCLowerMASSVEntries();
164}
165