1 | //===-- PPCGenScalarMASSEntries.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 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. |
14 | // |
15 | //===----------------------------------------------------------------------===// |
16 | |
17 | #include "PPC.h" |
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" |
24 | |
25 | #define DEBUG_TYPE "ppc-gen-scalar-mass" |
26 | |
27 | using namespace llvm; |
28 | |
29 | namespace { |
30 | |
31 | class PPCGenScalarMASSEntries : public ModulePass { |
32 | public: |
33 | static char ID; |
34 | |
35 | PPCGenScalarMASSEntries() : ModulePass(ID) { |
36 | ScalarMASSFuncs = { |
37 | #define TLI_DEFINE_SCALAR_MASS_FUNCS |
38 | #include "llvm/Analysis/ScalarFuncs.def" |
39 | }; |
40 | } |
41 | |
42 | bool runOnModule(Module &M) override; |
43 | |
44 | StringRef getPassName() const override { |
45 | return "PPC Generate Scalar MASS Entries" ; |
46 | } |
47 | |
48 | void getAnalysisUsage(AnalysisUsage &AU) const override { |
49 | AU.addRequired<TargetTransformInfoWrapperPass>(); |
50 | } |
51 | |
52 | private: |
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; |
58 | }; |
59 | |
60 | } // namespace |
61 | |
62 | // Returns true if 'afn' flag exists on the call instruction with the math |
63 | // function |
64 | bool PPCGenScalarMASSEntries::isCandidateSafeToLower(const CallInst &CI) const { |
65 | // skip functions with no scalar or vector FP type (like cosisin) |
66 | if (!isa<FPMathOperator>(Val: CI)) |
67 | return false; |
68 | |
69 | return CI.hasApproxFunc(); |
70 | } |
71 | |
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>(Val: CI)) |
77 | return false; |
78 | |
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(); |
82 | } |
83 | |
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, |
88 | CallInst &CI, |
89 | Function &Func) const { |
90 | if (CI.use_empty()) |
91 | return false; |
92 | |
93 | Module *M = Func.getParent(); |
94 | assert(M && "Expecting a valid Module" ); |
95 | |
96 | std::string MASSEntryStr = MASSEntry.str(); |
97 | if (isFiniteCallSafe(CI)) |
98 | MASSEntryStr += "_finite" ; |
99 | |
100 | FunctionCallee FCache = M->getOrInsertFunction( |
101 | Name: MASSEntryStr, T: Func.getFunctionType(), AttributeList: Func.getAttributes()); |
102 | |
103 | CI.setCalledFunction(FCache); |
104 | |
105 | return true; |
106 | } |
107 | |
108 | bool PPCGenScalarMASSEntries::runOnModule(Module &M) { |
109 | bool Changed = false; |
110 | |
111 | auto *TPC = getAnalysisIfAvailable<TargetPassConfig>(); |
112 | if (!TPC || skipModule(M)) |
113 | return false; |
114 | |
115 | for (Function &Func : M) { |
116 | if (!Func.isDeclaration()) |
117 | continue; |
118 | |
119 | auto Iter = ScalarMASSFuncs.find(x: Func.getName()); |
120 | if (Iter == ScalarMASSFuncs.end()) |
121 | continue; |
122 | |
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(Elt: User); |
129 | |
130 | for (auto *User : TheUsers) |
131 | if (auto *CI = dyn_cast_or_null<CallInst>(Val: User)) { |
132 | if (isCandidateSafeToLower(CI: *CI)) |
133 | Changed |= createScalarMASSCall(MASSEntry: Iter->second, CI&: *CI, Func); |
134 | } |
135 | } |
136 | |
137 | return Changed; |
138 | } |
139 | |
140 | char PPCGenScalarMASSEntries::ID = 0; |
141 | |
142 | char &llvm::PPCGenScalarMASSEntriesID = PPCGenScalarMASSEntries::ID; |
143 | |
144 | INITIALIZE_PASS(PPCGenScalarMASSEntries, DEBUG_TYPE, |
145 | "Generate Scalar MASS entries" , false, false) |
146 | |
147 | ModulePass *llvm::createPPCGenScalarMASSEntriesPass() { |
148 | return new PPCGenScalarMASSEntries(); |
149 | } |
150 | |