1 //===-- PPCGenScalarMASSEntries.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 transformation converts standard math functions into their
10 // corresponding MASS (scalar) entries for PowerPC targets.
11 // Following are examples of such conversion:
12 // tanh ---> __xl_tanh_finite
13 // Such lowering is legal under the fast-math option.
15 //===----------------------------------------------------------------------===//
18 #include "PPCSubtarget.h"
19 #include "PPCTargetMachine.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-gen-scalar-mass"
31 class PPCGenScalarMASSEntries
: public ModulePass
{
35 PPCGenScalarMASSEntries() : ModulePass(ID
) {
37 #define TLI_DEFINE_SCALAR_MASS_FUNCS
38 #include "llvm/Analysis/ScalarFuncs.def"
42 bool runOnModule(Module
&M
) override
;
44 StringRef
getPassName() const override
{
45 return "PPC Generate Scalar MASS Entries";
48 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
49 AU
.addRequired
<TargetTransformInfoWrapperPass
>();
53 std::map
<StringRef
, StringRef
> ScalarMASSFuncs
;
54 bool isCandidateSafeToLower(const CallInst
&CI
) const;
55 bool isFiniteCallSafe(const CallInst
&CI
) const;
56 bool createScalarMASSCall(StringRef MASSEntry
, CallInst
&CI
,
57 Function
&Func
) const;
62 // Returns true if 'afn' flag exists on the call instruction with the math
64 bool PPCGenScalarMASSEntries::isCandidateSafeToLower(const CallInst
&CI
) const {
65 // skip functions with no scalar or vector FP type (like cosisin)
66 if (!isa
<FPMathOperator
>(CI
))
69 return CI
.hasApproxFunc();
72 // Returns true if 'nnan', 'ninf' and 'nsz' flags exist on the call instruction
73 // with the math function
74 bool PPCGenScalarMASSEntries::isFiniteCallSafe(const CallInst
&CI
) const {
75 // skip functions with no scalar or vector FP type (like cosisin)
76 if (!isa
<FPMathOperator
>(CI
))
79 // FIXME: no-errno and trapping-math need to be set for MASS converstion
80 // but they don't have IR representation.
81 return CI
.hasNoNaNs() && CI
.hasNoInfs() && CI
.hasNoSignedZeros();
84 /// Lowers scalar math functions to scalar MASS functions.
85 /// e.g.: tanh --> __xl_tanh_finite or __xl_tanh
86 /// Both function prototype and its callsite is updated during lowering.
87 bool PPCGenScalarMASSEntries::createScalarMASSCall(StringRef MASSEntry
,
89 Function
&Func
) const {
93 Module
*M
= Func
.getParent();
94 assert(M
&& "Expecting a valid Module");
96 std::string MASSEntryStr
= MASSEntry
.str();
97 if (isFiniteCallSafe(CI
))
98 MASSEntryStr
+= "_finite";
100 FunctionCallee FCache
= M
->getOrInsertFunction(
101 MASSEntryStr
, Func
.getFunctionType(), Func
.getAttributes());
103 CI
.setCalledFunction(FCache
);
108 bool PPCGenScalarMASSEntries::runOnModule(Module
&M
) {
109 bool Changed
= false;
111 auto *TPC
= getAnalysisIfAvailable
<TargetPassConfig
>();
112 if (!TPC
|| skipModule(M
))
115 for (Function
&Func
: M
) {
116 if (!Func
.isDeclaration())
119 auto Iter
= ScalarMASSFuncs
.find(Func
.getName());
120 if (Iter
== ScalarMASSFuncs
.end())
123 // The call to createScalarMASSCall() invalidates the iterator over users
124 // upon replacing the users. Precomputing the current list of users allows
125 // us to replace all the call sites.
126 SmallVector
<User
*, 4> TheUsers
;
127 for (auto *User
: Func
.users())
128 TheUsers
.push_back(User
);
130 for (auto *User
: TheUsers
)
131 if (auto *CI
= dyn_cast_or_null
<CallInst
>(User
)) {
132 if (isCandidateSafeToLower(*CI
))
133 Changed
|= createScalarMASSCall(Iter
->second
, *CI
, Func
);
140 char PPCGenScalarMASSEntries::ID
= 0;
142 char &llvm::PPCGenScalarMASSEntriesID
= PPCGenScalarMASSEntries::ID
;
144 INITIALIZE_PASS(PPCGenScalarMASSEntries
, DEBUG_TYPE
,
145 "Generate Scalar MASS entries", false, false)
147 ModulePass
*llvm::createPPCGenScalarMASSEntriesPass() {
148 return new PPCGenScalarMASSEntries();