1 //===-- PPCLowerMASSVEntries.cpp ------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements lowering of MASSV (SIMD) entries for specific PowerPC
11 // Following is an example of a conversion specific to Power9 subtarget:
12 // __sind2_massv ---> __sind2_P9
14 //===----------------------------------------------------------------------===//
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"
25 #define DEBUG_TYPE "ppc-lower-massv-entries"
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
38 class PPCLowerMASSVEntries
: public ModulePass
{
42 PPCLowerMASSVEntries() : ModulePass(ID
) {}
44 bool runOnModule(Module
&M
) override
;
46 StringRef
getPassName() const override
{ return "PPC Lower MASS Entries"; }
48 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
49 AU
.addRequired
<TargetTransformInfoWrapperPass
>();
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
);
64 /// Checks if the specified function name represents an entry in the MASSV
66 bool PPCLowerMASSVEntries::isMASSVFunc(StringRef Name
) {
67 return llvm::is_contained(MASSVFuncs
, Name
);
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.
79 // TODO: add _P10 enties to Linux MASS lib and remove the check for AIX
80 if (Subtarget
->isAIXABI() && Subtarget
->hasP10Vector())
82 if (Subtarget
->hasP9Vector())
84 if (Subtarget
->hasP8Vector())
86 if (Subtarget
->isAIXABI())
90 "Mininum subtarget for -vector-library=MASSV option is Power8 on Linux "
91 "and Power7 on AIX when vectorization is not disabled.");
94 /// Creates PowerPC subtarget-specific name corresponding to the specified
95 /// generic MASSV function, and the PowerPC subtarget.
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
;
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
,
109 if (Func
.getName() != "__powf4" && Func
.getName() != "__powd2")
112 if (Constant
*Exp
= dyn_cast
<Constant
>(CI
->getArgOperand(1)))
113 if (ConstantFP
*CFP
= dyn_cast_or_null
<ConstantFP
>(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())
119 if (!CFP
->isExactlyValue(0.75) && !CFP
->isExactlyValue(0.25))
122 if (CFP
->isExactlyValue(0.25) && !CI
->hasNoSignedZeros())
125 CI
->setCalledFunction(
126 Intrinsic::getOrInsertDeclaration(&M
, Intrinsic::pow
, CI
->getType()));
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
,
138 const PPCSubtarget
*Subtarget
) {
142 // Handling pow(x, 0.25), pow(x, 0.75), powf(x, 0.25), powf(x, 0.75)
143 if (handlePowSpecialCases(CI
, Func
, M
))
146 std::string MASSVEntryName
= createMASSVFuncName(Func
, Subtarget
);
147 FunctionCallee FCache
= M
.getOrInsertFunction(
148 MASSVEntryName
, Func
.getFunctionType(), Func
.getAttributes());
150 CI
->setCalledFunction(FCache
);
155 bool PPCLowerMASSVEntries::runOnModule(Module
&M
) {
156 bool Changed
= false;
158 auto *TPC
= getAnalysisIfAvailable
<TargetPassConfig
>();
162 auto &TM
= TPC
->getTM
<PPCTargetMachine
>();
163 const PPCSubtarget
*Subtarget
;
165 for (Function
&Func
: M
) {
166 if (!Func
.isDeclaration())
169 if (!isMASSVFunc(Func
.getName()))
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());
177 for (auto *User
: MASSVUsers
) {
178 auto *CI
= dyn_cast
<CallInst
>(User
);
182 Subtarget
= &TM
.getSubtarget
<PPCSubtarget
>(*CI
->getParent()->getParent());
183 Changed
|= lowerMASSVCall(CI
, Func
, M
, Subtarget
);
190 char PPCLowerMASSVEntries::ID
= 0;
192 char &llvm::PPCLowerMASSVEntriesID
= PPCLowerMASSVEntries::ID
;
194 INITIALIZE_PASS(PPCLowerMASSVEntries
, DEBUG_TYPE
, "Lower MASSV entries", false,
197 ModulePass
*llvm::createPPCLowerMASSVEntriesPass() {
198 return new PPCLowerMASSVEntries();