Skip to content

Commit 256d253

Browse files
committed
[PowerPC] Scalar IBM MASS library conversion pass
This patch introduces the conversions from math function calls to MASS library calls. To resolves calls generated with these conversions, one need to link libxlopt.a library. This patch is tested on PowerPC Linux and AIX. Differential: https://reviews.llvm.org/D101759 Reviewer: bmahjour
1 parent 99ae458 commit 256d253

21 files changed

+4184
-1
lines changed
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
//===-- ScalarFuncs.def - Library information ----------*- C++ -*----------===//
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 .def file creates mapping from standard IEEE math functions
10+
// their corresponding entries in the IBM MASS (scalar) library.
11+
// LLVM intrinsic math functions will be handled in PPCISelLowing to
12+
// allow existing optimizations like pow(x,0.5) --> sqrt(x).
13+
14+
#if defined(TLI_DEFINE_SCALAR_MASS_FUNCS)
15+
#define TLI_DEFINE_SCALAR_MASS_FUNC(SCAL, MASSENTRY) {SCAL, MASSENTRY},
16+
#endif
17+
18+
TLI_DEFINE_SCALAR_MASS_FUNC("acosf", "__xl_acosf")
19+
TLI_DEFINE_SCALAR_MASS_FUNC("__acosf_finite", "__xl_acosf")
20+
TLI_DEFINE_SCALAR_MASS_FUNC("acos", "__xl_acos")
21+
TLI_DEFINE_SCALAR_MASS_FUNC("__acos_finite", "__xl_acos")
22+
23+
TLI_DEFINE_SCALAR_MASS_FUNC("acoshf", "__xl_acoshf")
24+
TLI_DEFINE_SCALAR_MASS_FUNC("__acoshf_finite", "__xl_acoshf")
25+
TLI_DEFINE_SCALAR_MASS_FUNC("acosh", "__xl_acosh")
26+
TLI_DEFINE_SCALAR_MASS_FUNC("__acosh_finite", "__xl_acosh")
27+
28+
TLI_DEFINE_SCALAR_MASS_FUNC("asinf", "__xl_asinf")
29+
TLI_DEFINE_SCALAR_MASS_FUNC("__asinf_finite", "__xl_asinf")
30+
TLI_DEFINE_SCALAR_MASS_FUNC("asin", "__xl_asin")
31+
TLI_DEFINE_SCALAR_MASS_FUNC("__asin_finite", "__xl_asin")
32+
33+
TLI_DEFINE_SCALAR_MASS_FUNC("asinhf", "__xl_asinhf")
34+
TLI_DEFINE_SCALAR_MASS_FUNC("asinh", "__xl_asinh")
35+
36+
TLI_DEFINE_SCALAR_MASS_FUNC("atanf", "__xl_atanf")
37+
TLI_DEFINE_SCALAR_MASS_FUNC("atan", "__xl_atan")
38+
39+
TLI_DEFINE_SCALAR_MASS_FUNC("atan2f", "__xl_atan2f")
40+
TLI_DEFINE_SCALAR_MASS_FUNC("__atan2f_finite", "__xl_atan2f")
41+
TLI_DEFINE_SCALAR_MASS_FUNC("atan2", "__xl_atan2")
42+
TLI_DEFINE_SCALAR_MASS_FUNC("__atan2_finite", "__xl_atan2")
43+
44+
TLI_DEFINE_SCALAR_MASS_FUNC("atanhf", "__xl_atanhf")
45+
TLI_DEFINE_SCALAR_MASS_FUNC("__atanhf_finite", "__xl_atanhf")
46+
TLI_DEFINE_SCALAR_MASS_FUNC("atanh", "__xl_atanh")
47+
TLI_DEFINE_SCALAR_MASS_FUNC("__atanh_finite", "__xl_atanh")
48+
49+
TLI_DEFINE_SCALAR_MASS_FUNC("cbrtf", "__xl_cbrtf")
50+
TLI_DEFINE_SCALAR_MASS_FUNC("cbrt", "__xl_cbrt")
51+
52+
TLI_DEFINE_SCALAR_MASS_FUNC("cosf", "__xl_cosf")
53+
TLI_DEFINE_SCALAR_MASS_FUNC("cos", "__xl_cos")
54+
55+
TLI_DEFINE_SCALAR_MASS_FUNC("coshf", "__xl_coshf")
56+
TLI_DEFINE_SCALAR_MASS_FUNC("__coshf_finite", "__xl_coshf")
57+
TLI_DEFINE_SCALAR_MASS_FUNC("cosh", "__xl_cosh")
58+
TLI_DEFINE_SCALAR_MASS_FUNC("__cosh_finite", "__xl_cosh")
59+
60+
TLI_DEFINE_SCALAR_MASS_FUNC("erff", "__xl_erff")
61+
TLI_DEFINE_SCALAR_MASS_FUNC("erf", "__xl_erf")
62+
63+
TLI_DEFINE_SCALAR_MASS_FUNC("erfcf", "__xl_erfcf")
64+
TLI_DEFINE_SCALAR_MASS_FUNC("erfc", "__xl_erfc")
65+
66+
TLI_DEFINE_SCALAR_MASS_FUNC("expf", "__xl_expf")
67+
TLI_DEFINE_SCALAR_MASS_FUNC("__expf_finite", "__xl_expf")
68+
TLI_DEFINE_SCALAR_MASS_FUNC("exp", "__xl_exp")
69+
TLI_DEFINE_SCALAR_MASS_FUNC("__exp_finite", "__xl_exp")
70+
71+
TLI_DEFINE_SCALAR_MASS_FUNC("expm1f", "__xl_expm1f")
72+
TLI_DEFINE_SCALAR_MASS_FUNC("expm1", "__xl_expm1")
73+
74+
TLI_DEFINE_SCALAR_MASS_FUNC("hypotf", "__xl_hypotf")
75+
TLI_DEFINE_SCALAR_MASS_FUNC("hypot", "__xl_hypot")
76+
77+
TLI_DEFINE_SCALAR_MASS_FUNC("lgammaf", "__xl_lgammaf")
78+
TLI_DEFINE_SCALAR_MASS_FUNC("lgamma", "__xl_lgamma")
79+
80+
TLI_DEFINE_SCALAR_MASS_FUNC("logf", "__xl_logf")
81+
TLI_DEFINE_SCALAR_MASS_FUNC("__logf_finite", "__xl_logf")
82+
TLI_DEFINE_SCALAR_MASS_FUNC("log", "__xl_log")
83+
TLI_DEFINE_SCALAR_MASS_FUNC("__log_finite", "__xl_log")
84+
85+
TLI_DEFINE_SCALAR_MASS_FUNC("log10f", "__xl_log10f")
86+
TLI_DEFINE_SCALAR_MASS_FUNC("__log10f_finite", "__xl_log10f")
87+
TLI_DEFINE_SCALAR_MASS_FUNC("log10", "__xl_log10")
88+
TLI_DEFINE_SCALAR_MASS_FUNC("__log10_finite", "__xl_log10")
89+
90+
TLI_DEFINE_SCALAR_MASS_FUNC("log1pf", "__xl_log1pf")
91+
TLI_DEFINE_SCALAR_MASS_FUNC("log1p", "__xl_log1p")
92+
93+
TLI_DEFINE_SCALAR_MASS_FUNC("powf", "__xl_powf")
94+
TLI_DEFINE_SCALAR_MASS_FUNC("__powf_finite", "__xl_powf")
95+
TLI_DEFINE_SCALAR_MASS_FUNC("pow", "__xl_pow")
96+
TLI_DEFINE_SCALAR_MASS_FUNC("__pow_finite", "__xl_pow")
97+
98+
TLI_DEFINE_SCALAR_MASS_FUNC("rsqrt", "__xl_rsqrt")
99+
100+
TLI_DEFINE_SCALAR_MASS_FUNC("sinf", "__xl_sinf")
101+
TLI_DEFINE_SCALAR_MASS_FUNC("sin", "__xl_sin")
102+
103+
TLI_DEFINE_SCALAR_MASS_FUNC("sinhf", "__xl_sinhf")
104+
TLI_DEFINE_SCALAR_MASS_FUNC("__sinhf_finite", "__xl_sinhf")
105+
TLI_DEFINE_SCALAR_MASS_FUNC("sinh", "__xl_sinh")
106+
TLI_DEFINE_SCALAR_MASS_FUNC("__sinh_finite", "__xl_sinh")
107+
108+
TLI_DEFINE_SCALAR_MASS_FUNC("sqrt", "__xl_sqrt")
109+
110+
TLI_DEFINE_SCALAR_MASS_FUNC("tanf", "__xl_tanf")
111+
TLI_DEFINE_SCALAR_MASS_FUNC("tan", "__xl_tan")
112+
113+
TLI_DEFINE_SCALAR_MASS_FUNC("tanhf", "__xl_tanhf")
114+
TLI_DEFINE_SCALAR_MASS_FUNC("tanh", "__xl_tanh")
115+
116+
#undef TLI_DEFINE_SCALAR_MASS_FUNCS
117+
#undef TLI_DEFINE_SCALAR_MASS_FUNC

llvm/include/llvm/CodeGen/CommandFlags.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ bool getEnableNoNaNsFPMath();
6262

6363
bool getEnableNoSignedZerosFPMath();
6464

65+
bool getEnableApproxFuncFPMath();
66+
6567
bool getEnableNoTrappingFPMath();
6668

6769
DenormalMode::DenormalModeKind getDenormalFPMath();

llvm/include/llvm/IR/Attributes.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ def MustProgress : EnumAttr<"mustprogress", [FnAttr]>;
294294
def LessPreciseFPMAD : StrBoolAttr<"less-precise-fpmad">;
295295
def NoInfsFPMath : StrBoolAttr<"no-infs-fp-math">;
296296
def NoNansFPMath : StrBoolAttr<"no-nans-fp-math">;
297+
def ApproxFuncFPMath : StrBoolAttr<"approx-func-fp-math">;
297298
def NoSignedZerosFPMath : StrBoolAttr<"no-signed-zeros-fp-math">;
298299
def UnsafeFPMath : StrBoolAttr<"unsafe-fp-math">;
299300
def NoJumpTables : StrBoolAttr<"no-jump-tables">;
@@ -333,6 +334,7 @@ class MergeRule<string F> {
333334
def : MergeRule<"setAND<LessPreciseFPMADAttr>">;
334335
def : MergeRule<"setAND<NoInfsFPMathAttr>">;
335336
def : MergeRule<"setAND<NoNansFPMathAttr>">;
337+
def : MergeRule<"setAND<ApproxFuncFPMathAttr>">;
336338
def : MergeRule<"setAND<NoSignedZerosFPMathAttr>">;
337339
def : MergeRule<"setAND<UnsafeFPMathAttr>">;
338340
def : MergeRule<"setOR<NoImplicitFloatAttr>">;

llvm/lib/CodeGen/CommandFlags.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ CGOPT(bool, EnableUnsafeFPMath)
5858
CGOPT(bool, EnableNoInfsFPMath)
5959
CGOPT(bool, EnableNoNaNsFPMath)
6060
CGOPT(bool, EnableNoSignedZerosFPMath)
61+
CGOPT(bool, EnableApproxFuncFPMath)
6162
CGOPT(bool, EnableNoTrappingFPMath)
6263
CGOPT(bool, EnableAIXExtendedAltivecABI)
6364
CGOPT(DenormalMode::DenormalModeKind, DenormalFPMath)
@@ -218,6 +219,12 @@ codegen::RegisterCodeGenFlags::RegisterCodeGenFlags() {
218219
cl::init(false));
219220
CGBINDOPT(EnableNoSignedZerosFPMath);
220221

222+
static cl::opt<bool> EnableApproxFuncFPMath(
223+
"enable-approx-func-fp-math",
224+
cl::desc("Enable FP math optimizations that assume approx func"),
225+
cl::init(false));
226+
CGBINDOPT(EnableApproxFuncFPMath);
227+
221228
static cl::opt<bool> EnableNoTrappingFPMath(
222229
"enable-no-trapping-fp-math",
223230
cl::desc("Enable setting the FP exceptions build "
@@ -493,6 +500,7 @@ codegen::InitTargetOptionsFromCodeGenFlags(const Triple &TheTriple) {
493500
Options.NoInfsFPMath = getEnableNoInfsFPMath();
494501
Options.NoNaNsFPMath = getEnableNoNaNsFPMath();
495502
Options.NoSignedZerosFPMath = getEnableNoSignedZerosFPMath();
503+
Options.ApproxFuncFPMath = getEnableApproxFuncFPMath();
496504
Options.NoTrappingFPMath = getEnableNoTrappingFPMath();
497505

498506
DenormalMode::DenormalModeKind DenormKind = getDenormalFPMath();
@@ -643,6 +651,7 @@ void codegen::setFunctionAttributes(StringRef CPU, StringRef Features,
643651
HANDLE_BOOL_ATTR(EnableNoInfsFPMathView, "no-infs-fp-math");
644652
HANDLE_BOOL_ATTR(EnableNoNaNsFPMathView, "no-nans-fp-math");
645653
HANDLE_BOOL_ATTR(EnableNoSignedZerosFPMathView, "no-signed-zeros-fp-math");
654+
HANDLE_BOOL_ATTR(EnableApproxFuncFPMathView, "approx-func-fp-math");
646655

647656
if (DenormalFPMathView->getNumOccurrences() > 0 &&
648657
!F.hasFnAttribute("denormal-fp-math")) {

llvm/lib/Target/PowerPC/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ add_llvm_target(PowerPCCodeGen
5555
PPCExpandISEL.cpp
5656
PPCPreEmitPeephole.cpp
5757
PPCLowerMASSVEntries.cpp
58+
PPCGenScalarMASSEntries.cpp
5859
GISel/PPCCallLowering.cpp
5960
GISel/PPCRegisterBankInfo.cpp
6061
GISel/PPCLegalizerInfo.cpp

llvm/lib/Target/PowerPC/PPC.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ FunctionPass *createPPCCTRLoops();
8484
void initializePPCLowerMASSVEntriesPass(PassRegistry &);
8585
extern char &PPCLowerMASSVEntriesID;
8686

87+
ModulePass *createPPCGenScalarMASSEntriesPass();
88+
void initializePPCGenScalarMASSEntriesPass(PassRegistry &);
89+
extern char &PPCGenScalarMASSEntriesID;
90+
8791
InstructionSelector *
8892
createPPCInstructionSelector(const PPCTargetMachine &, const PPCSubtarget &,
8993
const PPCRegisterBankInfo &);
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
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+
return CI.hasApproxFunc();
66+
}
67+
68+
// Returns true if 'nnan', 'ninf' and 'nsz' flags exist on the call instruction
69+
// with the math function
70+
bool PPCGenScalarMASSEntries::isFiniteCallSafe(const CallInst &CI) const {
71+
// FIXME: no-errno and trapping-math need to be set for MASS converstion
72+
// but they don't have IR representation.
73+
return CI.hasNoNaNs() && CI.hasNoInfs() && CI.hasNoSignedZeros();
74+
}
75+
76+
/// Lowers scalar math functions to scalar MASS functions.
77+
/// e.g.: tanh --> __xl_tanh_finite or __xl_tanh
78+
/// Both function prototype and its callsite is updated during lowering.
79+
bool PPCGenScalarMASSEntries::createScalarMASSCall(StringRef MASSEntry,
80+
CallInst &CI,
81+
Function &Func) const {
82+
if (CI.use_empty())
83+
return false;
84+
85+
Module *M = Func.getParent();
86+
assert(M && "Expecting a valid Module");
87+
88+
std::string MASSEntryStr = MASSEntry.str();
89+
if (isFiniteCallSafe(CI))
90+
MASSEntryStr += "_finite";
91+
92+
FunctionCallee FCache = M->getOrInsertFunction(
93+
MASSEntryStr, Func.getFunctionType(), Func.getAttributes());
94+
95+
CI.setCalledFunction(FCache);
96+
97+
return true;
98+
}
99+
100+
bool PPCGenScalarMASSEntries::runOnModule(Module &M) {
101+
bool Changed = false;
102+
103+
auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
104+
if (!TPC || skipModule(M))
105+
return false;
106+
107+
for (Function &Func : M) {
108+
if (!Func.isDeclaration())
109+
continue;
110+
111+
auto Iter = ScalarMASSFuncs.find(Func.getName());
112+
if (Iter == ScalarMASSFuncs.end())
113+
continue;
114+
115+
// The call to createScalarMASSCall() invalidates the iterator over users
116+
// upon replacing the users. Precomputing the current list of users allows
117+
// us to replace all the call sites.
118+
SmallVector<User *, 4> TheUsers;
119+
for (auto *User : Func.users())
120+
TheUsers.push_back(User);
121+
122+
for (auto *User : TheUsers)
123+
if (auto *CI = dyn_cast_or_null<CallInst>(User)) {
124+
if (isCandidateSafeToLower(*CI))
125+
Changed |= createScalarMASSCall(Iter->second, *CI, Func);
126+
}
127+
}
128+
129+
return Changed;
130+
}
131+
132+
char PPCGenScalarMASSEntries::ID = 0;
133+
134+
char &llvm::PPCGenScalarMASSEntriesID = PPCGenScalarMASSEntries::ID;
135+
136+
INITIALIZE_PASS(PPCGenScalarMASSEntries, DEBUG_TYPE,
137+
"Generate Scalar MASS entries", false, false)
138+
139+
ModulePass *llvm::createPPCGenScalarMASSEntriesPass() {
140+
return new PPCGenScalarMASSEntries();
141+
}

0 commit comments

Comments
 (0)