Path: blob/main/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCGenScalarMASSEntries.cpp
35266 views
//===-- PPCGenScalarMASSEntries.cpp ---------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This transformation converts standard math functions into their9// corresponding MASS (scalar) entries for PowerPC targets.10// Following are examples of such conversion:11// tanh ---> __xl_tanh_finite12// Such lowering is legal under the fast-math option.13//14//===----------------------------------------------------------------------===//1516#include "PPC.h"17#include "PPCSubtarget.h"18#include "PPCTargetMachine.h"19#include "llvm/Analysis/TargetTransformInfo.h"20#include "llvm/CodeGen/TargetPassConfig.h"21#include "llvm/IR/Instructions.h"22#include "llvm/IR/Module.h"2324#define DEBUG_TYPE "ppc-gen-scalar-mass"2526using namespace llvm;2728namespace {2930class PPCGenScalarMASSEntries : public ModulePass {31public:32static char ID;3334PPCGenScalarMASSEntries() : ModulePass(ID) {35ScalarMASSFuncs = {36#define TLI_DEFINE_SCALAR_MASS_FUNCS37#include "llvm/Analysis/ScalarFuncs.def"38};39}4041bool runOnModule(Module &M) override;4243StringRef getPassName() const override {44return "PPC Generate Scalar MASS Entries";45}4647void getAnalysisUsage(AnalysisUsage &AU) const override {48AU.addRequired<TargetTransformInfoWrapperPass>();49}5051private:52std::map<StringRef, StringRef> ScalarMASSFuncs;53bool isCandidateSafeToLower(const CallInst &CI) const;54bool isFiniteCallSafe(const CallInst &CI) const;55bool createScalarMASSCall(StringRef MASSEntry, CallInst &CI,56Function &Func) const;57};5859} // namespace6061// Returns true if 'afn' flag exists on the call instruction with the math62// function63bool PPCGenScalarMASSEntries::isCandidateSafeToLower(const CallInst &CI) const {64// skip functions with no scalar or vector FP type (like cosisin)65if (!isa<FPMathOperator>(CI))66return false;6768return CI.hasApproxFunc();69}7071// Returns true if 'nnan', 'ninf' and 'nsz' flags exist on the call instruction72// with the math function73bool PPCGenScalarMASSEntries::isFiniteCallSafe(const CallInst &CI) const {74// skip functions with no scalar or vector FP type (like cosisin)75if (!isa<FPMathOperator>(CI))76return false;7778// FIXME: no-errno and trapping-math need to be set for MASS converstion79// but they don't have IR representation.80return CI.hasNoNaNs() && CI.hasNoInfs() && CI.hasNoSignedZeros();81}8283/// Lowers scalar math functions to scalar MASS functions.84/// e.g.: tanh --> __xl_tanh_finite or __xl_tanh85/// Both function prototype and its callsite is updated during lowering.86bool PPCGenScalarMASSEntries::createScalarMASSCall(StringRef MASSEntry,87CallInst &CI,88Function &Func) const {89if (CI.use_empty())90return false;9192Module *M = Func.getParent();93assert(M && "Expecting a valid Module");9495std::string MASSEntryStr = MASSEntry.str();96if (isFiniteCallSafe(CI))97MASSEntryStr += "_finite";9899FunctionCallee FCache = M->getOrInsertFunction(100MASSEntryStr, Func.getFunctionType(), Func.getAttributes());101102CI.setCalledFunction(FCache);103104return true;105}106107bool PPCGenScalarMASSEntries::runOnModule(Module &M) {108bool Changed = false;109110auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();111if (!TPC || skipModule(M))112return false;113114for (Function &Func : M) {115if (!Func.isDeclaration())116continue;117118auto Iter = ScalarMASSFuncs.find(Func.getName());119if (Iter == ScalarMASSFuncs.end())120continue;121122// The call to createScalarMASSCall() invalidates the iterator over users123// upon replacing the users. Precomputing the current list of users allows124// us to replace all the call sites.125SmallVector<User *, 4> TheUsers;126for (auto *User : Func.users())127TheUsers.push_back(User);128129for (auto *User : TheUsers)130if (auto *CI = dyn_cast_or_null<CallInst>(User)) {131if (isCandidateSafeToLower(*CI))132Changed |= createScalarMASSCall(Iter->second, *CI, Func);133}134}135136return Changed;137}138139char PPCGenScalarMASSEntries::ID = 0;140141char &llvm::PPCGenScalarMASSEntriesID = PPCGenScalarMASSEntries::ID;142143INITIALIZE_PASS(PPCGenScalarMASSEntries, DEBUG_TYPE,144"Generate Scalar MASS entries", false, false)145146ModulePass *llvm::createPPCGenScalarMASSEntriesPass() {147return new PPCGenScalarMASSEntries();148}149150151