Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCGenScalarMASSEntries.cpp
35266 views
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>(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>(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
MASSEntryStr, Func.getFunctionType(), 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(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(User);
129
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);
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
151