brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.5 KiB · be96d4d Raw
147 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// This transformation converts standard math functions into their10// corresponding MASS (scalar) entries for PowerPC targets.11// Following are examples of such conversion:12//     tanh ---> __xl_tanh_finite13// Such lowering is legal under the fast-math option.14//15//===----------------------------------------------------------------------===//16 17#include "PPC.h"18#include "PPCSubtarget.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"23 24#define DEBUG_TYPE "ppc-gen-scalar-mass"25 26using namespace llvm;27 28namespace {29 30class PPCGenScalarMASSEntries : public ModulePass {31public:32  static char ID;33 34  PPCGenScalarMASSEntries() : ModulePass(ID) {35    ScalarMASSFuncs = {36#define TLI_DEFINE_SCALAR_MASS_FUNCS37#include "llvm/Analysis/ScalarFuncs.def"38    };39  }40 41  bool runOnModule(Module &M) override;42 43  StringRef getPassName() const override {44    return "PPC Generate Scalar MASS Entries";45  }46 47  void getAnalysisUsage(AnalysisUsage &AU) const override {48    AU.addRequired<TargetTransformInfoWrapperPass>();49  }50 51private:52  std::map<StringRef, StringRef> ScalarMASSFuncs;53  bool isCandidateSafeToLower(const CallInst &CI) const;54  bool isFiniteCallSafe(const CallInst &CI) const;55  bool createScalarMASSCall(StringRef MASSEntry, CallInst &CI,56                            Function &Func) const;57};58 59} // namespace60 61// 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)65  if (!isa<FPMathOperator>(CI))66    return false;67 68  return CI.hasApproxFunc();69}70 71// 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)75  if (!isa<FPMathOperator>(CI))76    return false;77 78  // FIXME: no-errno and trapping-math need to be set for MASS converstion79  // but they don't have IR representation.80  return CI.hasNoNaNs() && CI.hasNoInfs() && CI.hasNoSignedZeros();81}82 83/// 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,87                                                   CallInst &CI,88                                                   Function &Func) const {89  if (CI.use_empty())90    return false;91 92  Module *M = Func.getParent();93  assert(M && "Expecting a valid Module");94 95  std::string MASSEntryStr = MASSEntry.str();96  if (isFiniteCallSafe(CI))97    MASSEntryStr += "_finite";98 99  FunctionCallee FCache = M->getOrInsertFunction(100      MASSEntryStr, Func.getFunctionType(), Func.getAttributes());101 102  CI.setCalledFunction(FCache);103 104  return true;105}106 107bool PPCGenScalarMASSEntries::runOnModule(Module &M) {108  bool Changed = false;109 110  auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();111  if (!TPC || skipModule(M))112    return false;113 114  for (Function &Func : M) {115    if (!Func.isDeclaration())116      continue;117 118    auto Iter = ScalarMASSFuncs.find(Func.getName());119    if (Iter == ScalarMASSFuncs.end())120      continue;121 122    // 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.125    SmallVector<User *, 4> TheUsers(Func.users());126 127    for (auto *User : TheUsers)128      if (auto *CI = dyn_cast_or_null<CallInst>(User)) {129        if (isCandidateSafeToLower(*CI))130          Changed |= createScalarMASSCall(Iter->second, *CI, Func);131      }132  }133 134  return Changed;135}136 137char PPCGenScalarMASSEntries::ID = 0;138 139char &llvm::PPCGenScalarMASSEntriesID = PPCGenScalarMASSEntries::ID;140 141INITIALIZE_PASS(PPCGenScalarMASSEntries, DEBUG_TYPE,142                "Generate Scalar MASS entries", false, false)143 144ModulePass *llvm::createPPCGenScalarMASSEntriesPass() {145  return new PPCGenScalarMASSEntries();146}147