LCOV - code coverage report
Current view: top level - lib/Target/AMDGPU - AMDGPULibCalls.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 378 602 62.8 %
Date: 2018-10-20 13:21:21 Functions: 37 40 92.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- AMDGPULibCalls.cpp -------------------------------------------------===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : //
      10             : /// \file
      11             : /// This file does AMD library function optimizations.
      12             : //
      13             : //===----------------------------------------------------------------------===//
      14             : 
      15             : #define DEBUG_TYPE "amdgpu-simplifylib"
      16             : 
      17             : #include "AMDGPU.h"
      18             : #include "AMDGPULibFunc.h"
      19             : #include "llvm/Analysis/AliasAnalysis.h"
      20             : #include "llvm/Analysis/Loads.h"
      21             : #include "llvm/ADT/StringSet.h"
      22             : #include "llvm/ADT/StringRef.h"
      23             : #include "llvm/IR/Constants.h"
      24             : #include "llvm/IR/DerivedTypes.h"
      25             : #include "llvm/IR/Instructions.h"
      26             : #include "llvm/IR/IRBuilder.h"
      27             : #include "llvm/IR/Function.h"
      28             : #include "llvm/IR/LLVMContext.h"
      29             : #include "llvm/IR/Module.h"
      30             : #include "llvm/IR/ValueSymbolTable.h"
      31             : #include "llvm/Support/Debug.h"
      32             : #include "llvm/Support/raw_ostream.h"
      33             : #include "llvm/Target/TargetOptions.h"
      34             : #include <vector>
      35             : #include <cmath>
      36             : 
      37             : using namespace llvm;
      38             : 
      39             : static cl::opt<bool> EnablePreLink("amdgpu-prelink",
      40             :   cl::desc("Enable pre-link mode optimizations"),
      41             :   cl::init(false),
      42             :   cl::Hidden);
      43             : 
      44             : static cl::list<std::string> UseNative("amdgpu-use-native",
      45             :   cl::desc("Comma separated list of functions to replace with native, or all"),
      46             :   cl::CommaSeparated, cl::ValueOptional,
      47             :   cl::Hidden);
      48             : 
      49             : #define MATH_PI     3.14159265358979323846264338327950288419716939937511
      50             : #define MATH_E      2.71828182845904523536028747135266249775724709369996
      51             : #define MATH_SQRT2  1.41421356237309504880168872420969807856967187537695
      52             : 
      53             : #define MATH_LOG2E     1.4426950408889634073599246810018921374266459541529859
      54             : #define MATH_LOG10E    0.4342944819032518276511289189166050822943970058036665
      55             : // Value of log2(10)
      56             : #define MATH_LOG2_10   3.3219280948873623478703194294893901758648313930245806
      57             : // Value of 1 / log2(10)
      58             : #define MATH_RLOG2_10  0.3010299956639811952137388947244930267681898814621085
      59             : // Value of 1 / M_LOG2E_F = 1 / log2(e)
      60             : #define MATH_RLOG2_E   0.6931471805599453094172321214581765680755001343602552
      61             : 
      62             : namespace llvm {
      63             : 
      64         203 : class AMDGPULibCalls {
      65             : private:
      66             : 
      67             :   typedef llvm::AMDGPULibFunc FuncInfo;
      68             : 
      69             :   // -fuse-native.
      70             :   bool AllNative = false;
      71             : 
      72             :   bool useNativeFunc(const StringRef F) const;
      73             : 
      74             :   // Return a pointer (pointer expr) to the function if function defintion with
      75             :   // "FuncName" exists. It may create a new function prototype in pre-link mode.
      76             :   Constant *getFunction(Module *M, const FuncInfo& fInfo);
      77             : 
      78             :   // Replace a normal function with its native version.
      79             :   bool replaceWithNative(CallInst *CI, const FuncInfo &FInfo);
      80             : 
      81             :   bool parseFunctionName(const StringRef& FMangledName,
      82             :                          FuncInfo *FInfo=nullptr /*out*/);
      83             : 
      84             :   bool TDOFold(CallInst *CI, const FuncInfo &FInfo);
      85             : 
      86             :   /* Specialized optimizations */
      87             : 
      88             :   // recip (half or native)
      89             :   bool fold_recip(CallInst *CI, IRBuilder<> &B, const FuncInfo &FInfo);
      90             : 
      91             :   // divide (half or native)
      92             :   bool fold_divide(CallInst *CI, IRBuilder<> &B, const FuncInfo &FInfo);
      93             : 
      94             :   // pow/powr/pown
      95             :   bool fold_pow(CallInst *CI, IRBuilder<> &B, const FuncInfo &FInfo);
      96             : 
      97             :   // rootn
      98             :   bool fold_rootn(CallInst *CI, IRBuilder<> &B, const FuncInfo &FInfo);
      99             : 
     100             :   // fma/mad
     101             :   bool fold_fma_mad(CallInst *CI, IRBuilder<> &B, const FuncInfo &FInfo);
     102             : 
     103             :   // -fuse-native for sincos
     104             :   bool sincosUseNative(CallInst *aCI, const FuncInfo &FInfo);
     105             : 
     106             :   // evaluate calls if calls' arguments are constants.
     107             :   bool evaluateScalarMathFunc(FuncInfo &FInfo, double& Res0,
     108             :     double& Res1, Constant *copr0, Constant *copr1, Constant *copr2);
     109             :   bool evaluateCall(CallInst *aCI, FuncInfo &FInfo);
     110             : 
     111             :   // exp
     112             :   bool fold_exp(CallInst *CI, IRBuilder<> &B, const FuncInfo &FInfo);
     113             : 
     114             :   // exp2
     115             :   bool fold_exp2(CallInst *CI, IRBuilder<> &B, const FuncInfo &FInfo);
     116             : 
     117             :   // exp10
     118             :   bool fold_exp10(CallInst *CI, IRBuilder<> &B, const FuncInfo &FInfo);
     119             : 
     120             :   // log
     121             :   bool fold_log(CallInst *CI, IRBuilder<> &B, const FuncInfo &FInfo);
     122             : 
     123             :   // log2
     124             :   bool fold_log2(CallInst *CI, IRBuilder<> &B, const FuncInfo &FInfo);
     125             : 
     126             :   // log10
     127             :   bool fold_log10(CallInst *CI, IRBuilder<> &B, const FuncInfo &FInfo);
     128             : 
     129             :   // sqrt
     130             :   bool fold_sqrt(CallInst *CI, IRBuilder<> &B, const FuncInfo &FInfo);
     131             : 
     132             :   // sin/cos
     133             :   bool fold_sincos(CallInst * CI, IRBuilder<> &B, AliasAnalysis * AA);
     134             : 
     135             :   // __read_pipe/__write_pipe
     136             :   bool fold_read_write_pipe(CallInst *CI, IRBuilder<> &B, FuncInfo &FInfo);
     137             : 
     138             :   // Get insertion point at entry.
     139             :   BasicBlock::iterator getEntryIns(CallInst * UI);
     140             :   // Insert an Alloc instruction.
     141             :   AllocaInst* insertAlloca(CallInst * UI, IRBuilder<> &B, const char *prefix);
     142             :   // Get a scalar native builtin signle argument FP function
     143             :   Constant* getNativeFunction(Module* M, const FuncInfo &FInfo);
     144             : 
     145             : protected:
     146             :   CallInst *CI;
     147             : 
     148             :   bool isUnsafeMath(const CallInst *CI) const;
     149             : 
     150           0 :   void replaceCall(Value *With) {
     151          51 :     CI->replaceAllUsesWith(With);
     152          92 :     CI->eraseFromParent();
     153           0 :   }
     154             : 
     155             : public:
     156             :   bool fold(CallInst *CI, AliasAnalysis *AA = nullptr);
     157             : 
     158             :   void initNativeFuncs();
     159             : 
     160             :   // Replace a normal math function call with that native version
     161             :   bool useNative(CallInst *CI);
     162             : };
     163             : 
     164             : } // end llvm namespace
     165             : 
     166             : namespace {
     167             : 
     168             :   class AMDGPUSimplifyLibCalls : public FunctionPass {
     169             : 
     170             :   AMDGPULibCalls Simplifier;
     171             : 
     172             :   const TargetOptions Options;
     173             : 
     174             :   public:
     175             :     static char ID; // Pass identification
     176             : 
     177          73 :     AMDGPUSimplifyLibCalls(const TargetOptions &Opt = TargetOptions())
     178         146 :       : FunctionPass(ID), Options(Opt) {
     179          73 :       initializeAMDGPUSimplifyLibCallsPass(*PassRegistry::getPassRegistry());
     180          73 :     }
     181             : 
     182          73 :     void getAnalysisUsage(AnalysisUsage &AU) const override {
     183             :       AU.addRequired<AAResultsWrapperPass>();
     184          73 :     }
     185             : 
     186             :     bool runOnFunction(Function &M) override;
     187             :   };
     188             : 
     189             :   class AMDGPUUseNativeCalls : public FunctionPass {
     190             : 
     191             :   AMDGPULibCalls Simplifier;
     192             : 
     193             :   public:
     194             :     static char ID; // Pass identification
     195             : 
     196         130 :     AMDGPUUseNativeCalls() : FunctionPass(ID) {
     197         130 :       initializeAMDGPUUseNativeCallsPass(*PassRegistry::getPassRegistry());
     198         130 :       Simplifier.initNativeFuncs();
     199         130 :     }
     200             : 
     201             :     bool runOnFunction(Function &F) override;
     202             :   };
     203             : 
     204             : } // end anonymous namespace.
     205             : 
     206             : char AMDGPUSimplifyLibCalls::ID = 0;
     207             : char AMDGPUUseNativeCalls::ID = 0;
     208             : 
     209       85105 : INITIALIZE_PASS_BEGIN(AMDGPUSimplifyLibCalls, "amdgpu-simplifylib",
     210             :                       "Simplify well-known AMD library calls", false, false)
     211       85105 : INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
     212      199097 : INITIALIZE_PASS_END(AMDGPUSimplifyLibCalls, "amdgpu-simplifylib",
     213             :                     "Simplify well-known AMD library calls", false, false)
     214             : 
     215      199154 : INITIALIZE_PASS(AMDGPUUseNativeCalls, "amdgpu-usenative",
     216             :                 "Replace builtin math calls with that native versions.",
     217             :                 false, false)
     218             : 
     219             : template <typename IRB>
     220          31 : static CallInst *CreateCallEx(IRB &B, Value *Callee, Value *Arg,
     221             :                               const Twine &Name = "") {
     222          31 :   CallInst *R = B.CreateCall(Callee, Arg, Name);
     223             :   if (Function* F = dyn_cast<Function>(Callee))
     224             :     R->setCallingConv(F->getCallingConv());
     225          31 :   return R;
     226             : }
     227             : 
     228             : template <typename IRB>
     229           6 : static CallInst *CreateCallEx2(IRB &B, Value *Callee, Value *Arg1, Value *Arg2,
     230             :                                const Twine &Name = "") {
     231           6 :   CallInst *R = B.CreateCall(Callee, {Arg1, Arg2}, Name);
     232             :   if (Function* F = dyn_cast<Function>(Callee))
     233             :     R->setCallingConv(F->getCallingConv());
     234           6 :   return R;
     235             : }
     236             : 
     237             : //  Data structures for table-driven optimizations.
     238             : //  FuncTbl works for both f32 and f64 functions with 1 input argument
     239             : 
     240             : struct TableEntry {
     241             :   double   result;
     242             :   double   input;
     243             : };
     244             : 
     245             : /* a list of {result, input} */
     246             : static const TableEntry tbl_acos[] = {
     247             :   {MATH_PI/2.0, 0.0},
     248             :   {MATH_PI/2.0, -0.0},
     249             :   {0.0, 1.0},
     250             :   {MATH_PI, -1.0}
     251             : };
     252             : static const TableEntry tbl_acosh[] = {
     253             :   {0.0, 1.0}
     254             : };
     255             : static const TableEntry tbl_acospi[] = {
     256             :   {0.5, 0.0},
     257             :   {0.5, -0.0},
     258             :   {0.0, 1.0},
     259             :   {1.0, -1.0}
     260             : };
     261             : static const TableEntry tbl_asin[] = {
     262             :   {0.0, 0.0},
     263             :   {-0.0, -0.0},
     264             :   {MATH_PI/2.0, 1.0},
     265             :   {-MATH_PI/2.0, -1.0}
     266             : };
     267             : static const TableEntry tbl_asinh[] = {
     268             :   {0.0, 0.0},
     269             :   {-0.0, -0.0}
     270             : };
     271             : static const TableEntry tbl_asinpi[] = {
     272             :   {0.0, 0.0},
     273             :   {-0.0, -0.0},
     274             :   {0.5, 1.0},
     275             :   {-0.5, -1.0}
     276             : };
     277             : static const TableEntry tbl_atan[] = {
     278             :   {0.0, 0.0},
     279             :   {-0.0, -0.0},
     280             :   {MATH_PI/4.0, 1.0},
     281             :   {-MATH_PI/4.0, -1.0}
     282             : };
     283             : static const TableEntry tbl_atanh[] = {
     284             :   {0.0, 0.0},
     285             :   {-0.0, -0.0}
     286             : };
     287             : static const TableEntry tbl_atanpi[] = {
     288             :   {0.0, 0.0},
     289             :   {-0.0, -0.0},
     290             :   {0.25, 1.0},
     291             :   {-0.25, -1.0}
     292             : };
     293             : static const TableEntry tbl_cbrt[] = {
     294             :   {0.0, 0.0},
     295             :   {-0.0, -0.0},
     296             :   {1.0, 1.0},
     297             :   {-1.0, -1.0},
     298             : };
     299             : static const TableEntry tbl_cos[] = {
     300             :   {1.0, 0.0},
     301             :   {1.0, -0.0}
     302             : };
     303             : static const TableEntry tbl_cosh[] = {
     304             :   {1.0, 0.0},
     305             :   {1.0, -0.0}
     306             : };
     307             : static const TableEntry tbl_cospi[] = {
     308             :   {1.0, 0.0},
     309             :   {1.0, -0.0}
     310             : };
     311             : static const TableEntry tbl_erfc[] = {
     312             :   {1.0, 0.0},
     313             :   {1.0, -0.0}
     314             : };
     315             : static const TableEntry tbl_erf[] = {
     316             :   {0.0, 0.0},
     317             :   {-0.0, -0.0}
     318             : };
     319             : static const TableEntry tbl_exp[] = {
     320             :   {1.0, 0.0},
     321             :   {1.0, -0.0},
     322             :   {MATH_E, 1.0}
     323             : };
     324             : static const TableEntry tbl_exp2[] = {
     325             :   {1.0, 0.0},
     326             :   {1.0, -0.0},
     327             :   {2.0, 1.0}
     328             : };
     329             : static const TableEntry tbl_exp10[] = {
     330             :   {1.0, 0.0},
     331             :   {1.0, -0.0},
     332             :   {10.0, 1.0}
     333             : };
     334             : static const TableEntry tbl_expm1[] = {
     335             :   {0.0, 0.0},
     336             :   {-0.0, -0.0}
     337             : };
     338             : static const TableEntry tbl_log[] = {
     339             :   {0.0, 1.0},
     340             :   {1.0, MATH_E}
     341             : };
     342             : static const TableEntry tbl_log2[] = {
     343             :   {0.0, 1.0},
     344             :   {1.0, 2.0}
     345             : };
     346             : static const TableEntry tbl_log10[] = {
     347             :   {0.0, 1.0},
     348             :   {1.0, 10.0}
     349             : };
     350             : static const TableEntry tbl_rsqrt[] = {
     351             :   {1.0, 1.0},
     352             :   {1.0/MATH_SQRT2, 2.0}
     353             : };
     354             : static const TableEntry tbl_sin[] = {
     355             :   {0.0, 0.0},
     356             :   {-0.0, -0.0}
     357             : };
     358             : static const TableEntry tbl_sinh[] = {
     359             :   {0.0, 0.0},
     360             :   {-0.0, -0.0}
     361             : };
     362             : static const TableEntry tbl_sinpi[] = {
     363             :   {0.0, 0.0},
     364             :   {-0.0, -0.0}
     365             : };
     366             : static const TableEntry tbl_sqrt[] = {
     367             :   {0.0, 0.0},
     368             :   {1.0, 1.0},
     369             :   {MATH_SQRT2, 2.0}
     370             : };
     371             : static const TableEntry tbl_tan[] = {
     372             :   {0.0, 0.0},
     373             :   {-0.0, -0.0}
     374             : };
     375             : static const TableEntry tbl_tanh[] = {
     376             :   {0.0, 0.0},
     377             :   {-0.0, -0.0}
     378             : };
     379             : static const TableEntry tbl_tanpi[] = {
     380             :   {0.0, 0.0},
     381             :   {-0.0, -0.0}
     382             : };
     383             : static const TableEntry tbl_tgamma[] = {
     384             :   {1.0, 1.0},
     385             :   {1.0, 2.0},
     386             :   {2.0, 3.0},
     387             :   {6.0, 4.0}
     388             : };
     389             : 
     390          53 : static bool HasNative(AMDGPULibFunc::EFuncId id) {
     391          53 :   switch(id) {
     392             :   case AMDGPULibFunc::EI_DIVIDE:
     393             :   case AMDGPULibFunc::EI_COS:
     394             :   case AMDGPULibFunc::EI_EXP:
     395             :   case AMDGPULibFunc::EI_EXP2:
     396             :   case AMDGPULibFunc::EI_EXP10:
     397             :   case AMDGPULibFunc::EI_LOG:
     398             :   case AMDGPULibFunc::EI_LOG2:
     399             :   case AMDGPULibFunc::EI_LOG10:
     400             :   case AMDGPULibFunc::EI_POWR:
     401             :   case AMDGPULibFunc::EI_RECIP:
     402             :   case AMDGPULibFunc::EI_RSQRT:
     403             :   case AMDGPULibFunc::EI_SIN:
     404             :   case AMDGPULibFunc::EI_SINCOS:
     405             :   case AMDGPULibFunc::EI_SQRT:
     406             :   case AMDGPULibFunc::EI_TAN:
     407             :     return true;
     408          26 :   default:;
     409             :   }
     410          26 :   return false;
     411             : }
     412             : 
     413             : struct TableRef {
     414             :   size_t size;
     415             :   const TableEntry *table; // variable size: from 0 to (size - 1)
     416             : 
     417             :   TableRef() : size(0), table(nullptr) {}
     418             : 
     419             :   template <size_t N>
     420             :   TableRef(const TableEntry (&tbl)[N]) : size(N), table(&tbl[0]) {}
     421             : };
     422             : 
     423         210 : static TableRef getOptTable(AMDGPULibFunc::EFuncId id) {
     424         210 :   switch(id) {
     425           0 :   case AMDGPULibFunc::EI_ACOS:    return TableRef(tbl_acos);
     426           0 :   case AMDGPULibFunc::EI_ACOSH:   return TableRef(tbl_acosh);
     427           0 :   case AMDGPULibFunc::EI_ACOSPI:  return TableRef(tbl_acospi);
     428           0 :   case AMDGPULibFunc::EI_ASIN:    return TableRef(tbl_asin);
     429           0 :   case AMDGPULibFunc::EI_ASINH:   return TableRef(tbl_asinh);
     430           0 :   case AMDGPULibFunc::EI_ASINPI:  return TableRef(tbl_asinpi);
     431           0 :   case AMDGPULibFunc::EI_ATAN:    return TableRef(tbl_atan);
     432           0 :   case AMDGPULibFunc::EI_ATANH:   return TableRef(tbl_atanh);
     433           0 :   case AMDGPULibFunc::EI_ATANPI:  return TableRef(tbl_atanpi);
     434           0 :   case AMDGPULibFunc::EI_CBRT:    return TableRef(tbl_cbrt);
     435             :   case AMDGPULibFunc::EI_NCOS:
     436          19 :   case AMDGPULibFunc::EI_COS:     return TableRef(tbl_cos);
     437           0 :   case AMDGPULibFunc::EI_COSH:    return TableRef(tbl_cosh);
     438           0 :   case AMDGPULibFunc::EI_COSPI:   return TableRef(tbl_cospi);
     439           0 :   case AMDGPULibFunc::EI_ERFC:    return TableRef(tbl_erfc);
     440           0 :   case AMDGPULibFunc::EI_ERF:     return TableRef(tbl_erf);
     441           3 :   case AMDGPULibFunc::EI_EXP:     return TableRef(tbl_exp);
     442             :   case AMDGPULibFunc::EI_NEXP2:
     443           3 :   case AMDGPULibFunc::EI_EXP2:    return TableRef(tbl_exp2);
     444           3 :   case AMDGPULibFunc::EI_EXP10:   return TableRef(tbl_exp10);
     445           0 :   case AMDGPULibFunc::EI_EXPM1:   return TableRef(tbl_expm1);
     446           3 :   case AMDGPULibFunc::EI_LOG:     return TableRef(tbl_log);
     447             :   case AMDGPULibFunc::EI_NLOG2:
     448           3 :   case AMDGPULibFunc::EI_LOG2:    return TableRef(tbl_log2);
     449           3 :   case AMDGPULibFunc::EI_LOG10:   return TableRef(tbl_log10);
     450             :   case AMDGPULibFunc::EI_NRSQRT:
     451           3 :   case AMDGPULibFunc::EI_RSQRT:   return TableRef(tbl_rsqrt);
     452             :   case AMDGPULibFunc::EI_NSIN:
     453          21 :   case AMDGPULibFunc::EI_SIN:     return TableRef(tbl_sin);
     454           0 :   case AMDGPULibFunc::EI_SINH:    return TableRef(tbl_sinh);
     455           0 :   case AMDGPULibFunc::EI_SINPI:   return TableRef(tbl_sinpi);
     456             :   case AMDGPULibFunc::EI_NSQRT:
     457           6 :   case AMDGPULibFunc::EI_SQRT:    return TableRef(tbl_sqrt);
     458           3 :   case AMDGPULibFunc::EI_TAN:     return TableRef(tbl_tan);
     459           0 :   case AMDGPULibFunc::EI_TANH:    return TableRef(tbl_tanh);
     460           0 :   case AMDGPULibFunc::EI_TANPI:   return TableRef(tbl_tanpi);
     461           0 :   case AMDGPULibFunc::EI_TGAMMA:  return TableRef(tbl_tgamma);
     462             :   default:;
     463             :   }
     464         140 :   return TableRef();
     465             : }
     466             : 
     467             : static inline int getVecSize(const AMDGPULibFunc& FInfo) {
     468         200 :   return FInfo.getLeads()[0].VectorSize;
     469             : }
     470             : 
     471             : static inline AMDGPULibFunc::EType getArgType(const AMDGPULibFunc& FInfo) {
     472         117 :   return (AMDGPULibFunc::EType)FInfo.getLeads()[0].ArgType;
     473             : }
     474             : 
     475          81 : Constant *AMDGPULibCalls::getFunction(Module *M, const FuncInfo& fInfo) {
     476             :   // If we are doing PreLinkOpt, the function is external. So it is safe to
     477             :   // use getOrInsertFunction() at this stage.
     478             : 
     479          63 :   return EnablePreLink ? AMDGPULibFunc::getOrInsertFunction(M, fInfo)
     480          81 :                        : AMDGPULibFunc::getFunction(M, fInfo);
     481             : }
     482             : 
     483         877 : bool AMDGPULibCalls::parseFunctionName(const StringRef& FMangledName,
     484             :                                     FuncInfo *FInfo) {
     485         877 :   return AMDGPULibFunc::parse(FMangledName, *FInfo);
     486             : }
     487             : 
     488         290 : bool AMDGPULibCalls::isUnsafeMath(const CallInst *CI) const {
     489         251 :   if (auto Op = dyn_cast<FPMathOperator>(CI))
     490             :     if (Op->isFast())
     491             :       return true;
     492          43 :   const Function *F = CI->getParent()->getParent();
     493          43 :   Attribute Attr = F->getFnAttribute("unsafe-fp-math");
     494          43 :   return Attr.getValueAsString() == "true";
     495             : }
     496             : 
     497         132 : bool AMDGPULibCalls::useNativeFunc(const StringRef F) const {
     498         262 :   return AllNative ||
     499         130 :          std::find(UseNative.begin(), UseNative.end(), F) != UseNative.end();
     500             : }
     501             : 
     502         130 : void AMDGPULibCalls::initNativeFuncs() {
     503         130 :   AllNative = useNativeFunc("all") ||
     504         130 :               (UseNative.getNumOccurrences() && UseNative.size() == 1 &&
     505             :                UseNative.begin()->empty());
     506         130 : }
     507             : 
     508           1 : bool AMDGPULibCalls::sincosUseNative(CallInst *aCI, const FuncInfo &FInfo) {
     509           1 :   bool native_sin = useNativeFunc("sin");
     510           1 :   bool native_cos = useNativeFunc("cos");
     511             : 
     512           1 :   if (native_sin && native_cos) {
     513           1 :     Module *M = aCI->getModule();
     514           1 :     Value *opr0 = aCI->getArgOperand(0);
     515             : 
     516             :     AMDGPULibFunc nf;
     517           1 :     nf.getLeads()[0].ArgType = FInfo.getLeads()[0].ArgType;
     518           1 :     nf.getLeads()[0].VectorSize = FInfo.getLeads()[0].VectorSize;
     519             : 
     520             :     nf.setPrefix(AMDGPULibFunc::NATIVE);
     521             :     nf.setId(AMDGPULibFunc::EI_SIN);
     522           1 :     Constant *sinExpr = getFunction(M, nf);
     523             : 
     524             :     nf.setPrefix(AMDGPULibFunc::NATIVE);
     525             :     nf.setId(AMDGPULibFunc::EI_COS);
     526           1 :     Constant *cosExpr = getFunction(M, nf);
     527           1 :     if (sinExpr && cosExpr) {
     528           1 :       Value *sinval = CallInst::Create(sinExpr, opr0, "splitsin", aCI);
     529           1 :       Value *cosval = CallInst::Create(cosExpr, opr0, "splitcos", aCI);
     530           1 :       new StoreInst(cosval, aCI->getArgOperand(1), aCI);
     531             : 
     532             :       DEBUG_WITH_TYPE("usenative", dbgs() << "<useNative> replace " << *aCI
     533             :                                           << " with native version of sin/cos");
     534             : 
     535             :       replaceCall(sinval);
     536             :       return true;
     537             :     }
     538             :   }
     539             :   return false;
     540             : }
     541             : 
     542          73 : bool AMDGPULibCalls::useNative(CallInst *aCI) {
     543          73 :   CI = aCI;
     544             :   Function *Callee = aCI->getCalledFunction();
     545             : 
     546             :   FuncInfo FInfo;
     547         142 :   if (!parseFunctionName(Callee->getName(), &FInfo) || !FInfo.isMangled() ||
     548          52 :       FInfo.getPrefix() != AMDGPULibFunc::NOPFX ||
     549         124 :       getArgType(FInfo) == AMDGPULibFunc::F64 || !HasNative(FInfo.getId()) ||
     550          73 :       !(AllNative || useNativeFunc(FInfo.getName()))) {
     551             :     return false;
     552             :   }
     553             : 
     554          25 :   if (FInfo.getId() == AMDGPULibFunc::EI_SINCOS)
     555           1 :     return sincosUseNative(aCI, FInfo);
     556             : 
     557             :   FInfo.setPrefix(AMDGPULibFunc::NATIVE);
     558          24 :   Constant *F = getFunction(aCI->getModule(), FInfo);
     559          24 :   if (!F)
     560             :     return false;
     561             : 
     562             :   aCI->setCalledFunction(F);
     563             :   DEBUG_WITH_TYPE("usenative", dbgs() << "<useNative> replace " << *aCI
     564             :                                       << " with native version");
     565          24 :   return true;
     566             : }
     567             : 
     568             : // Clang emits call of __read_pipe_2 or __read_pipe_4 for OpenCL read_pipe
     569             : // builtin, with appended type size and alignment arguments, where 2 or 4
     570             : // indicates the original number of arguments. The library has optimized version
     571             : // of __read_pipe_2/__read_pipe_4 when the type size and alignment has the same
     572             : // power of 2 value. This function transforms __read_pipe_2 to __read_pipe_2_N
     573             : // for such cases where N is the size in bytes of the type (N = 1, 2, 4, 8, ...,
     574             : // 128). The same for __read_pipe_4, write_pipe_2, and write_pipe_4.
     575          39 : bool AMDGPULibCalls::fold_read_write_pipe(CallInst *CI, IRBuilder<> &B,
     576             :                                           FuncInfo &FInfo) {
     577             :   auto *Callee = CI->getCalledFunction();
     578          39 :   if (!Callee->isDeclaration())
     579             :     return false;
     580             : 
     581             :   assert(Callee->hasName() && "Invalid read_pipe/write_pipe function");
     582          39 :   auto *M = Callee->getParent();
     583          39 :   auto &Ctx = M->getContext();
     584          39 :   std::string Name = Callee->getName();
     585          39 :   auto NumArg = CI->getNumArgOperands();
     586          39 :   if (NumArg != 4 && NumArg != 6)
     587             :     return false;
     588          39 :   auto *PacketSize = CI->getArgOperand(NumArg - 2);
     589          39 :   auto *PacketAlign = CI->getArgOperand(NumArg - 1);
     590          39 :   if (!isa<ConstantInt>(PacketSize) || !isa<ConstantInt>(PacketAlign))
     591             :     return false;
     592          39 :   unsigned Size = cast<ConstantInt>(PacketSize)->getZExtValue();
     593          39 :   unsigned Align = cast<ConstantInt>(PacketAlign)->getZExtValue();
     594          39 :   if (Size != Align || !isPowerOf2_32(Size))
     595             :     return false;
     596             : 
     597             :   Type *PtrElemTy;
     598          36 :   if (Size <= 8)
     599          24 :     PtrElemTy = Type::getIntNTy(Ctx, Size * 8);
     600             :   else
     601          12 :     PtrElemTy = VectorType::get(Type::getInt64Ty(Ctx), Size / 8);
     602          36 :   unsigned PtrArgLoc = CI->getNumArgOperands() - 3;
     603             :   auto PtrArg = CI->getArgOperand(PtrArgLoc);
     604          36 :   unsigned PtrArgAS = PtrArg->getType()->getPointerAddressSpace();
     605          36 :   auto *PtrTy = llvm::PointerType::get(PtrElemTy, PtrArgAS);
     606             : 
     607             :   SmallVector<llvm::Type *, 6> ArgTys;
     608          84 :   for (unsigned I = 0; I != PtrArgLoc; ++I)
     609          48 :     ArgTys.push_back(CI->getArgOperand(I)->getType());
     610          36 :   ArgTys.push_back(PtrTy);
     611             : 
     612          72 :   Name = Name + "_" + std::to_string(Size);
     613          36 :   auto *FTy = FunctionType::get(Callee->getReturnType(),
     614             :                                 ArrayRef<Type *>(ArgTys), false);
     615          36 :   AMDGPULibFunc NewLibFunc(Name, FTy);
     616          36 :   auto *F = AMDGPULibFunc::getOrInsertFunction(M, NewLibFunc);
     617          36 :   if (!F)
     618             :     return false;
     619             : 
     620          36 :   auto *BCast = B.CreatePointerCast(PtrArg, PtrTy);
     621             :   SmallVector<Value *, 6> Args;
     622          84 :   for (unsigned I = 0; I != PtrArgLoc; ++I)
     623          48 :     Args.push_back(CI->getArgOperand(I));
     624          36 :   Args.push_back(BCast);
     625             : 
     626          36 :   auto *NCI = B.CreateCall(F, Args);
     627             :   NCI->setAttributes(CI->getAttributes());
     628          36 :   CI->replaceAllUsesWith(NCI);
     629          36 :   CI->dropAllReferences();
     630          36 :   CI->eraseFromParent();
     631             : 
     632             :   return true;
     633             : }
     634             : 
     635             : // This function returns false if no change; return true otherwise.
     636         804 : bool AMDGPULibCalls::fold(CallInst *CI, AliasAnalysis *AA) {
     637         804 :   this->CI = CI;
     638             :   Function *Callee = CI->getCalledFunction();
     639             : 
     640             :   // Ignore indirect calls.
     641             :   if (Callee == 0) return false;
     642             : 
     643             :   FuncInfo FInfo;
     644         804 :   if (!parseFunctionName(Callee->getName(), &FInfo))
     645             :     return false;
     646             : 
     647             :   // Further check the number of arguments to see if they match.
     648         420 :   if (CI->getNumArgOperands() != FInfo.getNumArgs())
     649             :     return false;
     650             : 
     651         210 :   BasicBlock *BB = CI->getParent();
     652         210 :   LLVMContext &Context = CI->getParent()->getContext();
     653             :   IRBuilder<> B(Context);
     654             : 
     655             :   // Set the builder to the instruction after the call.
     656         210 :   B.SetInsertPoint(BB, CI->getIterator());
     657             : 
     658             :   // Copy fast flags from the original call.
     659             :   if (const FPMathOperator *FPOp = dyn_cast<const FPMathOperator>(CI))
     660             :     B.setFastMathFlags(FPOp->getFastMathFlags());
     661             : 
     662         210 :   if (TDOFold(CI, FInfo))
     663             :     return true;
     664             : 
     665             :   // Under unsafe-math, evaluate calls if possible.
     666             :   // According to Brian Sumner, we can do this for all f32 function calls
     667             :   // using host's double function calls.
     668         210 :   if (isUnsafeMath(CI) && evaluateCall(CI, FInfo))
     669             :     return true;
     670             : 
     671             :   // Specilized optimizations for each function call
     672         204 :   switch (FInfo.getId()) {
     673             :   case AMDGPULibFunc::EI_RECIP:
     674             :     // skip vector function
     675             :     assert ((FInfo.getPrefix() == AMDGPULibFunc::NATIVE ||
     676             :              FInfo.getPrefix() == AMDGPULibFunc::HALF) &&
     677             :             "recip must be an either native or half function");
     678           0 :     return (getVecSize(FInfo) != 1) ? false : fold_recip(CI, B, FInfo);
     679             : 
     680             :   case AMDGPULibFunc::EI_DIVIDE:
     681             :     // skip vector function
     682             :     assert ((FInfo.getPrefix() == AMDGPULibFunc::NATIVE ||
     683             :              FInfo.getPrefix() == AMDGPULibFunc::HALF) &&
     684             :             "divide must be an either native or half function");
     685           6 :     return (getVecSize(FInfo) != 1) ? false : fold_divide(CI, B, FInfo);
     686             : 
     687          51 :   case AMDGPULibFunc::EI_POW:
     688             :   case AMDGPULibFunc::EI_POWR:
     689             :   case AMDGPULibFunc::EI_POWN:
     690          51 :     return fold_pow(CI, B, FInfo);
     691             : 
     692             :   case AMDGPULibFunc::EI_ROOTN:
     693             :     // skip vector function
     694          15 :     return (getVecSize(FInfo) != 1) ? false : fold_rootn(CI, B, FInfo);
     695             : 
     696             :   case AMDGPULibFunc::EI_FMA:
     697             :   case AMDGPULibFunc::EI_MAD:
     698             :   case AMDGPULibFunc::EI_NFMA:
     699             :     // skip vector function
     700          21 :     return (getVecSize(FInfo) != 1) ? false : fold_fma_mad(CI, B, FInfo);
     701             : 
     702           6 :   case AMDGPULibFunc::EI_SQRT:
     703           6 :     return isUnsafeMath(CI) && fold_sqrt(CI, B, FInfo);
     704             :   case AMDGPULibFunc::EI_COS:
     705             :   case AMDGPULibFunc::EI_SIN:
     706           0 :     if ((getArgType(FInfo) == AMDGPULibFunc::F32 ||
     707             :          getArgType(FInfo) == AMDGPULibFunc::F64)
     708          40 :         && (FInfo.getPrefix() == AMDGPULibFunc::NOPFX))
     709          26 :       return fold_sincos(CI, B, AA);
     710             : 
     711             :     break;
     712          39 :   case AMDGPULibFunc::EI_READ_PIPE_2:
     713             :   case AMDGPULibFunc::EI_READ_PIPE_4:
     714             :   case AMDGPULibFunc::EI_WRITE_PIPE_2:
     715             :   case AMDGPULibFunc::EI_WRITE_PIPE_4:
     716          39 :     return fold_read_write_pipe(CI, B, FInfo);
     717             : 
     718             :   default:
     719             :     break;
     720             :   }
     721             : 
     722             :   return false;
     723             : }
     724             : 
     725         210 : bool AMDGPULibCalls::TDOFold(CallInst *CI, const FuncInfo &FInfo) {
     726             :   // Table-Driven optimization
     727         210 :   const TableRef tr = getOptTable(FInfo.getId());
     728         210 :   if (tr.size==0)
     729             :     return false;
     730             : 
     731          70 :   int const sz = (int)tr.size;
     732          70 :   const TableEntry * const ftbl = tr.table;
     733          70 :   Value *opr0 = CI->getArgOperand(0);
     734             : 
     735          70 :   if (getVecSize(FInfo) > 1) {
     736             :     if (ConstantDataVector *CV = dyn_cast<ConstantDataVector>(opr0)) {
     737             :       SmallVector<double, 0> DVal;
     738           0 :       for (int eltNo = 0; eltNo < getVecSize(FInfo); ++eltNo) {
     739           0 :         ConstantFP *eltval = dyn_cast<ConstantFP>(
     740             :                                CV->getElementAsConstant((unsigned)eltNo));
     741             :         assert(eltval && "Non-FP arguments in math function!");
     742             :         bool found = false;
     743           0 :         for (int i=0; i < sz; ++i) {
     744           0 :           if (eltval->isExactlyValue(ftbl[i].input)) {
     745           0 :             DVal.push_back(ftbl[i].result);
     746             :             found = true;
     747             :             break;
     748             :           }
     749             :         }
     750             :         if (!found) {
     751             :           // This vector constants not handled yet.
     752             :           return false;
     753             :         }
     754             :       }
     755           0 :       LLVMContext &context = CI->getParent()->getParent()->getContext();
     756             :       Constant *nval;
     757           0 :       if (getArgType(FInfo) == AMDGPULibFunc::F32) {
     758             :         SmallVector<float, 0> FVal;
     759           0 :         for (unsigned i = 0; i < DVal.size(); ++i) {
     760           0 :           FVal.push_back((float)DVal[i]);
     761             :         }
     762             :         ArrayRef<float> tmp(FVal);
     763           0 :         nval = ConstantDataVector::get(context, tmp);
     764             :       } else { // F64
     765             :         ArrayRef<double> tmp(DVal);
     766           0 :         nval = ConstantDataVector::get(context, tmp);
     767             :       }
     768             :       LLVM_DEBUG(errs() << "AMDIC: " << *CI << " ---> " << *nval << "\n");
     769             :       replaceCall(nval);
     770           0 :       return true;
     771             :     }
     772             :   } else {
     773             :     // Scalar version
     774             :     if (ConstantFP *CF = dyn_cast<ConstantFP>(opr0)) {
     775           0 :       for (int i = 0; i < sz; ++i) {
     776           0 :         if (CF->isExactlyValue(ftbl[i].input)) {
     777           0 :           Value *nval = ConstantFP::get(CF->getType(), ftbl[i].result);
     778             :           LLVM_DEBUG(errs() << "AMDIC: " << *CI << " ---> " << *nval << "\n");
     779             :           replaceCall(nval);
     780           0 :           return true;
     781             :         }
     782             :       }
     783             :     }
     784             :   }
     785             : 
     786             :   return false;
     787             : }
     788             : 
     789           0 : bool AMDGPULibCalls::replaceWithNative(CallInst *CI, const FuncInfo &FInfo) {
     790           0 :   Module *M = CI->getModule();
     791           0 :   if (getArgType(FInfo) != AMDGPULibFunc::F32 ||
     792           0 :       FInfo.getPrefix() != AMDGPULibFunc::NOPFX ||
     793           0 :       !HasNative(FInfo.getId()))
     794             :     return false;
     795             : 
     796           0 :   AMDGPULibFunc nf = FInfo;
     797             :   nf.setPrefix(AMDGPULibFunc::NATIVE);
     798           0 :   if (Constant *FPExpr = getFunction(M, nf)) {
     799             :     LLVM_DEBUG(dbgs() << "AMDIC: " << *CI << " ---> ");
     800             : 
     801             :     CI->setCalledFunction(FPExpr);
     802             : 
     803             :     LLVM_DEBUG(dbgs() << *CI << '\n');
     804             : 
     805           0 :     return true;
     806             :   }
     807             :   return false;
     808             : }
     809             : 
     810             : //  [native_]half_recip(c) ==> 1.0/c
     811           0 : bool AMDGPULibCalls::fold_recip(CallInst *CI, IRBuilder<> &B,
     812             :                                 const FuncInfo &FInfo) {
     813           0 :   Value *opr0 = CI->getArgOperand(0);
     814             :   if (ConstantFP *CF = dyn_cast<ConstantFP>(opr0)) {
     815             :     // Just create a normal div. Later, InstCombine will be able
     816             :     // to compute the divide into a constant (avoid check float infinity
     817             :     // or subnormal at this point).
     818           0 :     Value *nval = B.CreateFDiv(ConstantFP::get(CF->getType(), 1.0),
     819             :                                opr0,
     820             :                                "recip2div");
     821             :     LLVM_DEBUG(errs() << "AMDIC: " << *CI << " ---> " << *nval << "\n");
     822             :     replaceCall(nval);
     823           0 :     return true;
     824             :   }
     825             :   return false;
     826             : }
     827             : 
     828             : //  [native_]half_divide(x, c) ==> x/c
     829           6 : bool AMDGPULibCalls::fold_divide(CallInst *CI, IRBuilder<> &B,
     830             :                                  const FuncInfo &FInfo) {
     831           6 :   Value *opr0 = CI->getArgOperand(0);
     832             :   Value *opr1 = CI->getArgOperand(1);
     833             :   ConstantFP *CF0 = dyn_cast<ConstantFP>(opr0);
     834             :   ConstantFP *CF1 = dyn_cast<ConstantFP>(opr1);
     835             : 
     836           6 :   if ((CF0 && CF1) ||  // both are constants
     837           6 :       (CF1 && (getArgType(FInfo) == AMDGPULibFunc::F32)))
     838             :       // CF1 is constant && f32 divide
     839             :   {
     840           6 :     Value *nval1 = B.CreateFDiv(ConstantFP::get(opr1->getType(), 1.0),
     841             :                                 opr1, "__div2recip");
     842           6 :     Value *nval  = B.CreateFMul(opr0, nval1, "__div2mul");
     843             :     replaceCall(nval);
     844           6 :     return true;
     845             :   }
     846             :   return false;
     847             : }
     848             : 
     849             : namespace llvm {
     850             : static double log2(double V) {
     851             : #if _XOPEN_SOURCE >= 600 || _ISOC99_SOURCE || _POSIX_C_SOURCE >= 200112L
     852           0 :   return ::log2(V);
     853             : #else
     854             :   return log(V) / 0.693147180559945309417;
     855             : #endif
     856             : }
     857             : }
     858             : 
     859          51 : bool AMDGPULibCalls::fold_pow(CallInst *CI, IRBuilder<> &B,
     860             :                               const FuncInfo &FInfo) {
     861             :   assert((FInfo.getId() == AMDGPULibFunc::EI_POW ||
     862             :           FInfo.getId() == AMDGPULibFunc::EI_POWR ||
     863             :           FInfo.getId() == AMDGPULibFunc::EI_POWN) &&
     864             :          "fold_pow: encounter a wrong function call");
     865             : 
     866             :   Value *opr0, *opr1;
     867             :   ConstantFP *CF;
     868             :   ConstantInt *CINT;
     869             :   ConstantAggregateZero *CZero;
     870             :   Type *eltType;
     871             : 
     872          51 :   opr0 = CI->getArgOperand(0);
     873             :   opr1 = CI->getArgOperand(1);
     874             :   CZero = dyn_cast<ConstantAggregateZero>(opr1);
     875          51 :   if (getVecSize(FInfo) == 1) {
     876          51 :     eltType = opr0->getType();
     877             :     CF = dyn_cast<ConstantFP>(opr1);
     878             :     CINT = dyn_cast<ConstantInt>(opr1);
     879             :   } else {
     880           0 :     VectorType *VTy = dyn_cast<VectorType>(opr0->getType());
     881             :     assert(VTy && "Oprand of vector function should be of vectortype");
     882           0 :     eltType = VTy->getElementType();
     883             :     ConstantDataVector *CDV = dyn_cast<ConstantDataVector>(opr1);
     884             : 
     885             :     // Now, only Handle vector const whose elements have the same value.
     886           0 :     CF = CDV ? dyn_cast_or_null<ConstantFP>(CDV->getSplatValue()) : nullptr;
     887           0 :     CINT = CDV ? dyn_cast_or_null<ConstantInt>(CDV->getSplatValue()) : nullptr;
     888             :   }
     889             : 
     890             :   // No unsafe math , no constant argument, do nothing
     891          51 :   if (!isUnsafeMath(CI) && !CF && !CINT && !CZero)
     892             :     return false;
     893             : 
     894             :   // 0x1111111 means that we don't do anything for this call.
     895          54 :   int ci_opr1 = (CINT ? (int)CINT->getSExtValue() : 0x1111111);
     896             : 
     897          90 :   if ((CF && CF->isZero()) || (CINT && ci_opr1 == 0) || CZero) {
     898             :     //  pow/powr/pown(x, 0) == 1
     899             :     LLVM_DEBUG(errs() << "AMDIC: " << *CI << " ---> 1\n");
     900           6 :     Constant *cnval = ConstantFP::get(eltType, 1.0);
     901           6 :     if (getVecSize(FInfo) > 1) {
     902           0 :       cnval = ConstantDataVector::getSplat(getVecSize(FInfo), cnval);
     903             :     }
     904             :     replaceCall(cnval);
     905           6 :     return true;
     906             :   }
     907          45 :   if ((CF && CF->isExactlyValue(1.0)) || (CINT && ci_opr1 == 1)) {
     908             :     // pow/powr/pown(x, 1.0) = x
     909             :     LLVM_DEBUG(errs() << "AMDIC: " << *CI << " ---> " << *opr0 << "\n");
     910             :     replaceCall(opr0);
     911           6 :     return true;
     912             :   }
     913          39 :   if ((CF && CF->isExactlyValue(2.0)) || (CINT && ci_opr1 == 2)) {
     914             :     // pow/powr/pown(x, 2.0) = x*x
     915             :     LLVM_DEBUG(errs() << "AMDIC: " << *CI << " ---> " << *opr0 << " * " << *opr0
     916             :                       << "\n");
     917           6 :     Value *nval = B.CreateFMul(opr0, opr0, "__pow2");
     918             :     replaceCall(nval);
     919           6 :     return true;
     920             :   }
     921          33 :   if ((CF && CF->isExactlyValue(-1.0)) || (CINT && ci_opr1 == -1)) {
     922             :     // pow/powr/pown(x, -1.0) = 1.0/x
     923             :     LLVM_DEBUG(errs() << "AMDIC: " << *CI << " ---> 1 / " << *opr0 << "\n");
     924           6 :     Constant *cnval = ConstantFP::get(eltType, 1.0);
     925           6 :     if (getVecSize(FInfo) > 1) {
     926           0 :       cnval = ConstantDataVector::getSplat(getVecSize(FInfo), cnval);
     927             :     }
     928           6 :     Value *nval = B.CreateFDiv(cnval, opr0, "__powrecip");
     929             :     replaceCall(nval);
     930           6 :     return true;
     931             :   }
     932             : 
     933          27 :   Module *M = CI->getModule();
     934          27 :   if (CF && (CF->isExactlyValue(0.5) || CF->isExactlyValue(-0.5))) {
     935             :     // pow[r](x, [-]0.5) = sqrt(x)
     936           6 :     bool issqrt = CF->isExactlyValue(0.5);
     937           6 :     if (Constant *FPExpr = getFunction(M,
     938          15 :         AMDGPULibFunc(issqrt ? AMDGPULibFunc::EI_SQRT
     939             :                              : AMDGPULibFunc::EI_RSQRT, FInfo))) {
     940             :       LLVM_DEBUG(errs() << "AMDIC: " << *CI << " ---> "
     941             :                         << FInfo.getName().c_str() << "(" << *opr0 << ")\n");
     942           8 :       Value *nval = CreateCallEx(B,FPExpr, opr0, issqrt ? "__pow2sqrt"
     943             :                                                         : "__pow2rsqrt");
     944             :       replaceCall(nval);
     945           4 :       return true;
     946             :     }
     947             :   }
     948             : 
     949          23 :   if (!isUnsafeMath(CI))
     950             :     return false;
     951             : 
     952             :   // Unsafe Math optimization
     953             : 
     954             :   // Remember that ci_opr1 is set if opr1 is integral
     955          23 :   if (CF) {
     956             :     double dval = (getArgType(FInfo) == AMDGPULibFunc::F32)
     957          11 :                     ? (double)CF->getValueAPF().convertToFloat()
     958           0 :                     : CF->getValueAPF().convertToDouble();
     959          11 :     int ival = (int)dval;
     960          11 :     if ((double)ival == dval) {
     961             :       ci_opr1 = ival;
     962             :     } else
     963             :       ci_opr1 = 0x11111111;
     964             :   }
     965             : 
     966             :   // pow/powr/pown(x, c) = [1/](x*x*..x); where
     967             :   //   trunc(c) == c && the number of x == c && |c| <= 12
     968          23 :   unsigned abs_opr1 = (ci_opr1 < 0) ? -ci_opr1 : ci_opr1;
     969          23 :   if (abs_opr1 <= 12) {
     970             :     Constant *cnval;
     971             :     Value *nval;
     972           9 :     if (abs_opr1 == 0) {
     973           0 :       cnval = ConstantFP::get(eltType, 1.0);
     974           0 :       if (getVecSize(FInfo) > 1) {
     975           0 :         cnval = ConstantDataVector::getSplat(getVecSize(FInfo), cnval);
     976             :       }
     977             :       nval = cnval;
     978             :     } else {
     979             :       Value *valx2 = nullptr;
     980             :       nval = nullptr;
     981          45 :       while (abs_opr1 > 0) {
     982          36 :         valx2 = valx2 ? B.CreateFMul(valx2, valx2, "__powx2") : opr0;
     983          36 :         if (abs_opr1 & 1) {
     984          27 :           nval = nval ? B.CreateFMul(nval, valx2, "__powprod") : valx2;
     985             :         }
     986          36 :         abs_opr1 >>= 1;
     987             :       }
     988             :     }
     989             : 
     990           9 :     if (ci_opr1 < 0) {
     991           0 :       cnval = ConstantFP::get(eltType, 1.0);
     992           0 :       if (getVecSize(FInfo) > 1) {
     993           0 :         cnval = ConstantDataVector::getSplat(getVecSize(FInfo), cnval);
     994             :       }
     995           0 :       nval = B.CreateFDiv(cnval, nval, "__1powprod");
     996             :     }
     997             :     LLVM_DEBUG(errs() << "AMDIC: " << *CI << " ---> "
     998             :                       << ((ci_opr1 < 0) ? "1/prod(" : "prod(") << *opr0
     999             :                       << ")\n");
    1000             :     replaceCall(nval);
    1001           9 :     return true;
    1002             :   }
    1003             : 
    1004             :   // powr ---> exp2(y * log2(x))
    1005             :   // pown/pow ---> powr(fabs(x), y) | (x & ((int)y << 31))
    1006          14 :   Constant *ExpExpr = getFunction(M, AMDGPULibFunc(AMDGPULibFunc::EI_EXP2,
    1007             :                                                    FInfo));
    1008          14 :   if (!ExpExpr)
    1009             :     return false;
    1010             : 
    1011             :   bool needlog = false;
    1012             :   bool needabs = false;
    1013             :   bool needcopysign = false;
    1014             :   Constant *cnval = nullptr;
    1015           8 :   if (getVecSize(FInfo) == 1) {
    1016             :     CF = dyn_cast<ConstantFP>(opr0);
    1017             : 
    1018             :     if (CF) {
    1019             :       double V = (getArgType(FInfo) == AMDGPULibFunc::F32)
    1020           0 :                    ? (double)CF->getValueAPF().convertToFloat()
    1021           0 :                    : CF->getValueAPF().convertToDouble();
    1022             : 
    1023             :       V = log2(std::abs(V));
    1024           0 :       cnval = ConstantFP::get(eltType, V);
    1025           0 :       needcopysign = (FInfo.getId() != AMDGPULibFunc::EI_POWR) &&
    1026             :                      CF->isNegative();
    1027             :     } else {
    1028             :       needlog = true;
    1029           8 :       needcopysign = needabs = FInfo.getId() != AMDGPULibFunc::EI_POWR &&
    1030             :                                (!CF || CF->isNegative());
    1031             :     }
    1032             :   } else {
    1033             :     ConstantDataVector *CDV = dyn_cast<ConstantDataVector>(opr0);
    1034             : 
    1035             :     if (!CDV) {
    1036             :       needlog = true;
    1037           0 :       needcopysign = needabs = FInfo.getId() != AMDGPULibFunc::EI_POWR;
    1038             :     } else {
    1039             :       assert ((int)CDV->getNumElements() == getVecSize(FInfo) &&
    1040             :               "Wrong vector size detected");
    1041             : 
    1042             :       SmallVector<double, 0> DVal;
    1043           0 :       for (int i=0; i < getVecSize(FInfo); ++i) {
    1044             :         double V = (getArgType(FInfo) == AMDGPULibFunc::F32)
    1045           0 :                      ? (double)CDV->getElementAsFloat(i)
    1046           0 :                      : CDV->getElementAsDouble(i);
    1047           0 :         if (V < 0.0) needcopysign = true;
    1048           0 :         V = log2(std::abs(V));
    1049           0 :         DVal.push_back(V);
    1050             :       }
    1051           0 :       if (getArgType(FInfo) == AMDGPULibFunc::F32) {
    1052             :         SmallVector<float, 0> FVal;
    1053           0 :         for (unsigned i=0; i < DVal.size(); ++i) {
    1054           0 :           FVal.push_back((float)DVal[i]);
    1055             :         }
    1056             :         ArrayRef<float> tmp(FVal);
    1057           0 :         cnval = ConstantDataVector::get(M->getContext(), tmp);
    1058             :       } else {
    1059             :         ArrayRef<double> tmp(DVal);
    1060           0 :         cnval = ConstantDataVector::get(M->getContext(), tmp);
    1061             :       }
    1062             :     }
    1063             :   }
    1064             : 
    1065           8 :   if (needcopysign && (FInfo.getId() == AMDGPULibFunc::EI_POW)) {
    1066             :     // We cannot handle corner cases for a general pow() function, give up
    1067             :     // unless y is a constant integral value. Then proceed as if it were pown.
    1068           2 :     if (getVecSize(FInfo) == 1) {
    1069             :       if (const ConstantFP *CF = dyn_cast<ConstantFP>(opr1)) {
    1070             :         double y = (getArgType(FInfo) == AMDGPULibFunc::F32)
    1071           2 :                    ? (double)CF->getValueAPF().convertToFloat()
    1072           0 :                    : CF->getValueAPF().convertToDouble();
    1073           2 :         if (y != (double)(int64_t)y)
    1074             :           return false;
    1075             :       } else
    1076             :         return false;
    1077             :     } else {
    1078             :       if (const ConstantDataVector *CDV = dyn_cast<ConstantDataVector>(opr1)) {
    1079           0 :         for (int i=0; i < getVecSize(FInfo); ++i) {
    1080             :           double y = (getArgType(FInfo) == AMDGPULibFunc::F32)
    1081           0 :                      ? (double)CDV->getElementAsFloat(i)
    1082           0 :                      : CDV->getElementAsDouble(i);
    1083           0 :           if (y != (double)(int64_t)y)
    1084             :             return false;
    1085             :         }
    1086             :       } else
    1087             :         return false;
    1088             :     }
    1089             :   }
    1090             : 
    1091             :   Value *nval;
    1092           8 :   if (needabs) {
    1093           4 :     Constant *AbsExpr = getFunction(M, AMDGPULibFunc(AMDGPULibFunc::EI_FABS,
    1094             :                                                      FInfo));
    1095           4 :     if (!AbsExpr)
    1096             :       return false;
    1097           4 :     nval = CreateCallEx(B, AbsExpr, opr0, "__fabs");
    1098             :   } else {
    1099           4 :     nval = cnval ? cnval : opr0;
    1100             :   }
    1101           8 :   if (needlog) {
    1102           8 :     Constant *LogExpr = getFunction(M, AMDGPULibFunc(AMDGPULibFunc::EI_LOG2,
    1103             :                                                      FInfo));
    1104           8 :     if (!LogExpr)
    1105             :       return false;
    1106           8 :     nval = CreateCallEx(B,LogExpr, nval, "__log2");
    1107             :   }
    1108             : 
    1109           8 :   if (FInfo.getId() == AMDGPULibFunc::EI_POWN) {
    1110             :     // convert int(32) to fp(f32 or f64)
    1111           2 :     opr1 = B.CreateSIToFP(opr1, nval->getType(), "pownI2F");
    1112             :   }
    1113           8 :   nval = B.CreateFMul(opr1, nval, "__ylogx");
    1114           8 :   nval = CreateCallEx(B,ExpExpr, nval, "__exp2");
    1115             : 
    1116           8 :   if (needcopysign) {
    1117             :     Value *opr_n;
    1118           4 :     Type* rTy = opr0->getType();
    1119           4 :     Type* nTyS = eltType->isDoubleTy() ? B.getInt64Ty() : B.getInt32Ty();
    1120             :     Type *nTy = nTyS;
    1121             :     if (const VectorType *vTy = dyn_cast<VectorType>(rTy))
    1122           0 :       nTy = VectorType::get(nTyS, vTy->getNumElements());
    1123           4 :     unsigned size = nTy->getScalarSizeInBits();
    1124             :     opr_n = CI->getArgOperand(1);
    1125           8 :     if (opr_n->getType()->isIntegerTy())
    1126           2 :       opr_n = B.CreateZExtOrBitCast(opr_n, nTy, "__ytou");
    1127             :     else
    1128           2 :       opr_n = B.CreateFPToSI(opr1, nTy, "__ytou");
    1129             : 
    1130           4 :     Value *sign = B.CreateShl(opr_n, size-1, "__yeven");
    1131           4 :     sign = B.CreateAnd(B.CreateBitCast(opr0, nTy), sign, "__pow_sign");
    1132           4 :     nval = B.CreateOr(B.CreateBitCast(nval, nTy), sign);
    1133           4 :     nval = B.CreateBitCast(nval, opr0->getType());
    1134             :   }
    1135             : 
    1136             :   LLVM_DEBUG(errs() << "AMDIC: " << *CI << " ---> "
    1137             :                     << "exp2(" << *opr1 << " * log2(" << *opr0 << "))\n");
    1138             :   replaceCall(nval);
    1139             : 
    1140           8 :   return true;
    1141             : }
    1142             : 
    1143          15 : bool AMDGPULibCalls::fold_rootn(CallInst *CI, IRBuilder<> &B,
    1144             :                                 const FuncInfo &FInfo) {
    1145          15 :   Value *opr0 = CI->getArgOperand(0);
    1146             :   Value *opr1 = CI->getArgOperand(1);
    1147             : 
    1148             :   ConstantInt *CINT = dyn_cast<ConstantInt>(opr1);
    1149             :   if (!CINT) {
    1150             :     return false;
    1151             :   }
    1152          15 :   int ci_opr1 = (int)CINT->getSExtValue();
    1153          15 :   if (ci_opr1 == 1) {  // rootn(x, 1) = x
    1154             :     LLVM_DEBUG(errs() << "AMDIC: " << *CI << " ---> " << *opr0 << "\n");
    1155             :     replaceCall(opr0);
    1156           3 :     return true;
    1157             :   }
    1158          12 :   if (ci_opr1 == 2) {  // rootn(x, 2) = sqrt(x)
    1159             :     std::vector<const Type*> ParamsTys;
    1160           3 :     ParamsTys.push_back(opr0->getType());
    1161           3 :     Module *M = CI->getModule();
    1162           6 :     if (Constant *FPExpr = getFunction(M, AMDGPULibFunc(AMDGPULibFunc::EI_SQRT,
    1163             :                                                         FInfo))) {
    1164             :       LLVM_DEBUG(errs() << "AMDIC: " << *CI << " ---> sqrt(" << *opr0 << ")\n");
    1165           2 :       Value *nval = CreateCallEx(B,FPExpr, opr0, "__rootn2sqrt");
    1166             :       replaceCall(nval);
    1167             :       return true;
    1168             :     }
    1169           9 :   } else if (ci_opr1 == 3) { // rootn(x, 3) = cbrt(x)
    1170           3 :     Module *M = CI->getModule();
    1171           6 :     if (Constant *FPExpr = getFunction(M, AMDGPULibFunc(AMDGPULibFunc::EI_CBRT,
    1172             :                                                         FInfo))) {
    1173             :       LLVM_DEBUG(errs() << "AMDIC: " << *CI << " ---> cbrt(" << *opr0 << ")\n");
    1174           2 :       Value *nval = CreateCallEx(B,FPExpr, opr0, "__rootn2cbrt");
    1175             :       replaceCall(nval);
    1176           2 :       return true;
    1177             :     }
    1178           6 :   } else if (ci_opr1 == -1) { // rootn(x, -1) = 1.0/x
    1179             :     LLVM_DEBUG(errs() << "AMDIC: " << *CI << " ---> 1.0 / " << *opr0 << "\n");
    1180           3 :     Value *nval = B.CreateFDiv(ConstantFP::get(opr0->getType(), 1.0),
    1181             :                                opr0,
    1182             :                                "__rootn2div");
    1183             :     replaceCall(nval);
    1184           3 :     return true;
    1185           3 :   } else if (ci_opr1 == -2) {  // rootn(x, -2) = rsqrt(x)
    1186             :     std::vector<const Type*> ParamsTys;
    1187           3 :     ParamsTys.push_back(opr0->getType());
    1188           3 :     Module *M = CI->getModule();
    1189           6 :     if (Constant *FPExpr = getFunction(M, AMDGPULibFunc(AMDGPULibFunc::EI_RSQRT,
    1190             :                                                         FInfo))) {
    1191             :       LLVM_DEBUG(errs() << "AMDIC: " << *CI << " ---> rsqrt(" << *opr0
    1192             :                         << ")\n");
    1193           2 :       Value *nval = CreateCallEx(B,FPExpr, opr0, "__rootn2rsqrt");
    1194             :       replaceCall(nval);
    1195             :       return true;
    1196             :     }
    1197             :   }
    1198             :   return false;
    1199             : }
    1200             : 
    1201          21 : bool AMDGPULibCalls::fold_fma_mad(CallInst *CI, IRBuilder<> &B,
    1202             :                                   const FuncInfo &FInfo) {
    1203          21 :   Value *opr0 = CI->getArgOperand(0);
    1204             :   Value *opr1 = CI->getArgOperand(1);
    1205             :   Value *opr2 = CI->getArgOperand(2);
    1206             : 
    1207             :   ConstantFP *CF0 = dyn_cast<ConstantFP>(opr0);
    1208             :   ConstantFP *CF1 = dyn_cast<ConstantFP>(opr1);
    1209          39 :   if ((CF0 && CF0->isZero()) || (CF1 && CF1->isZero())) {
    1210             :     // fma/mad(a, b, c) = c if a=0 || b=0
    1211             :     LLVM_DEBUG(errs() << "AMDIC: " << *CI << " ---> " << *opr2 << "\n");
    1212             :     replaceCall(opr2);
    1213          12 :     return true;
    1214             :   }
    1215           9 :   if (CF0 && CF0->isExactlyValue(1.0f)) {
    1216             :     // fma/mad(a, b, c) = b+c if a=1
    1217             :     LLVM_DEBUG(errs() << "AMDIC: " << *CI << " ---> " << *opr1 << " + " << *opr2
    1218             :                       << "\n");
    1219           3 :     Value *nval = B.CreateFAdd(opr1, opr2, "fmaadd");
    1220             :     replaceCall(nval);
    1221           3 :     return true;
    1222             :   }
    1223           6 :   if (CF1 && CF1->isExactlyValue(1.0f)) {
    1224             :     // fma/mad(a, b, c) = a+c if b=1
    1225             :     LLVM_DEBUG(errs() << "AMDIC: " << *CI << " ---> " << *opr0 << " + " << *opr2
    1226             :                       << "\n");
    1227           3 :     Value *nval = B.CreateFAdd(opr0, opr2, "fmaadd");
    1228             :     replaceCall(nval);
    1229           3 :     return true;
    1230             :   }
    1231             :   if (ConstantFP *CF = dyn_cast<ConstantFP>(opr2)) {
    1232           3 :     if (CF->isZero()) {
    1233             :       // fma/mad(a, b, c) = a*b if c=0
    1234             :       LLVM_DEBUG(errs() << "AMDIC: " << *CI << " ---> " << *opr0 << " * "
    1235             :                         << *opr1 << "\n");
    1236           3 :       Value *nval = B.CreateFMul(opr0, opr1, "fmamul");
    1237             :       replaceCall(nval);
    1238           3 :       return true;
    1239             :     }
    1240             :   }
    1241             : 
    1242             :   return false;
    1243             : }
    1244             : 
    1245             : // Get a scalar native builtin signle argument FP function
    1246           2 : Constant* AMDGPULibCalls::getNativeFunction(Module* M, const FuncInfo& FInfo) {
    1247           2 :   if (getArgType(FInfo) == AMDGPULibFunc::F64 || !HasNative(FInfo.getId()))
    1248             :     return nullptr;
    1249           2 :   FuncInfo nf = FInfo;
    1250             :   nf.setPrefix(AMDGPULibFunc::NATIVE);
    1251           2 :   return getFunction(M, nf);
    1252             : }
    1253             : 
    1254             : // fold sqrt -> native_sqrt (x)
    1255           6 : bool AMDGPULibCalls::fold_sqrt(CallInst *CI, IRBuilder<> &B,
    1256             :                                const FuncInfo &FInfo) {
    1257           9 :   if (getArgType(FInfo) == AMDGPULibFunc::F32 && (getVecSize(FInfo) == 1) &&
    1258             :       (FInfo.getPrefix() != AMDGPULibFunc::NATIVE)) {
    1259           2 :     if (Constant *FPExpr = getNativeFunction(
    1260           4 :         CI->getModule(), AMDGPULibFunc(AMDGPULibFunc::EI_SQRT, FInfo))) {
    1261           1 :       Value *opr0 = CI->getArgOperand(0);
    1262             :       LLVM_DEBUG(errs() << "AMDIC: " << *CI << " ---> "
    1263             :                         << "sqrt(" << *opr0 << ")\n");
    1264           1 :       Value *nval = CreateCallEx(B,FPExpr, opr0, "__sqrt");
    1265             :       replaceCall(nval);
    1266           1 :       return true;
    1267             :     }
    1268             :   }
    1269             :   return false;
    1270             : }
    1271             : 
    1272             : // fold sin, cos -> sincos.
    1273          26 : bool AMDGPULibCalls::fold_sincos(CallInst *CI, IRBuilder<> &B,
    1274             :                                  AliasAnalysis *AA) {
    1275             :   AMDGPULibFunc fInfo;
    1276          26 :   if (!AMDGPULibFunc::parse(CI->getCalledFunction()->getName(), fInfo))
    1277             :     return false;
    1278             : 
    1279             :   assert(fInfo.getId() == AMDGPULibFunc::EI_SIN ||
    1280             :          fInfo.getId() == AMDGPULibFunc::EI_COS);
    1281             :   bool const isSin = fInfo.getId() == AMDGPULibFunc::EI_SIN;
    1282             : 
    1283          26 :   Value *CArgVal = CI->getArgOperand(0);
    1284          26 :   BasicBlock * const CBB = CI->getParent();
    1285             : 
    1286             :   int const MaxScan = 30;
    1287             : 
    1288             :   { // fold in load value.
    1289             :     LoadInst *LI = dyn_cast<LoadInst>(CArgVal);
    1290          20 :     if (LI && LI->getParent() == CBB) {
    1291          20 :       BasicBlock::iterator BBI = LI->getIterator();
    1292          20 :       Value *AvailableVal = FindAvailableLoadedValue(LI, CBB, BBI, MaxScan, AA);
    1293          20 :       if (AvailableVal) {
    1294           0 :         CArgVal->replaceAllUsesWith(AvailableVal);
    1295           0 :         if (CArgVal->getNumUses() == 0)
    1296           0 :           LI->eraseFromParent();
    1297             :         CArgVal = CI->getArgOperand(0);
    1298             :       }
    1299             :     }
    1300             :   }
    1301             : 
    1302          26 :   Module *M = CI->getModule();
    1303          26 :   fInfo.setId(isSin ? AMDGPULibFunc::EI_COS : AMDGPULibFunc::EI_SIN);
    1304             :   std::string const PairName = fInfo.mangle();
    1305             : 
    1306             :   CallInst *UI = nullptr;
    1307          64 :   for (User* U : CArgVal->users()) {
    1308             :     CallInst *XI = dyn_cast_or_null<CallInst>(U);
    1309          50 :     if (!XI || XI == CI || XI->getParent() != CBB)
    1310             :       continue;
    1311             : 
    1312             :     Function *UCallee = XI->getCalledFunction();
    1313          24 :     if (!UCallee || !UCallee->getName().equals(PairName))
    1314           0 :       continue;
    1315             : 
    1316          24 :     BasicBlock::iterator BBI = CI->getIterator();
    1317          48 :     if (BBI == CI->getParent()->begin())
    1318             :       break;
    1319             :     --BBI;
    1320          42 :     for (int I = MaxScan; I > 0 && BBI != CBB->begin(); --BBI, --I) {
    1321          30 :       if (cast<Instruction>(BBI) == XI) {
    1322             :         UI = XI;
    1323             :         break;
    1324             :       }
    1325             :     }
    1326          24 :     if (UI) break;
    1327             :   }
    1328             : 
    1329          26 :   if (!UI) return false;
    1330             : 
    1331             :   // Merge the sin and cos.
    1332             : 
    1333             :   // for OpenCL 2.0 we have only generic implementation of sincos
    1334             :   // function.
    1335          12 :   AMDGPULibFunc nf(AMDGPULibFunc::EI_SINCOS, fInfo);
    1336          12 :   nf.getLeads()[0].PtrKind = AMDGPULibFunc::getEPtrKindFromAddrSpace(AMDGPUAS::FLAT_ADDRESS);
    1337          12 :   Function *Fsincos = dyn_cast_or_null<Function>(getFunction(M, nf));
    1338             :   if (!Fsincos) return false;
    1339             : 
    1340             :   BasicBlock::iterator ItOld = B.GetInsertPoint();
    1341           6 :   AllocaInst *Alloc = insertAlloca(UI, B, "__sincos_");
    1342           6 :   B.SetInsertPoint(UI);
    1343             : 
    1344             :   Value *P = Alloc;
    1345           6 :   Type *PTy = Fsincos->getFunctionType()->getParamType(1);
    1346             :   // The allocaInst allocates the memory in private address space. This need
    1347             :   // to be bitcasted to point to the address space of cos pointer type.
    1348             :   // In OpenCL 2.0 this is generic, while in 1.2 that is private.
    1349           6 :   if (PTy->getPointerAddressSpace() != AMDGPUAS::PRIVATE_ADDRESS)
    1350           6 :     P = B.CreateAddrSpaceCast(Alloc, PTy);
    1351           6 :   CallInst *Call = CreateCallEx2(B, Fsincos, UI->getArgOperand(0), P);
    1352             : 
    1353             :   LLVM_DEBUG(errs() << "AMDIC: fold_sincos (" << *CI << ", " << *UI << ") with "
    1354             :                     << *Call << "\n");
    1355             : 
    1356           6 :   if (!isSin) { // CI->cos, UI->sin
    1357           6 :     B.SetInsertPoint(&*ItOld);
    1358           6 :     UI->replaceAllUsesWith(&*Call);
    1359           6 :     Instruction *Reload = B.CreateLoad(Alloc);
    1360           6 :     CI->replaceAllUsesWith(Reload);
    1361           6 :     UI->eraseFromParent();
    1362           6 :     CI->eraseFromParent();
    1363             :   } else { // CI->sin, UI->cos
    1364           0 :     Instruction *Reload = B.CreateLoad(Alloc);
    1365           0 :     UI->replaceAllUsesWith(Reload);
    1366           0 :     CI->replaceAllUsesWith(Call);
    1367           0 :     UI->eraseFromParent();
    1368           0 :     CI->eraseFromParent();
    1369             :   }
    1370             :   return true;
    1371             : }
    1372             : 
    1373             : // Get insertion point at entry.
    1374           6 : BasicBlock::iterator AMDGPULibCalls::getEntryIns(CallInst * UI) {
    1375           6 :   Function * Func = UI->getParent()->getParent();
    1376             :   BasicBlock * BB = &Func->getEntryBlock();
    1377             :   assert(BB && "Entry block not found!");
    1378             :   BasicBlock::iterator ItNew = BB->begin();
    1379           6 :   return ItNew;
    1380             : }
    1381             : 
    1382             : // Insert a AllocsInst at the beginning of function entry block.
    1383           6 : AllocaInst* AMDGPULibCalls::insertAlloca(CallInst *UI, IRBuilder<> &B,
    1384             :                                          const char *prefix) {
    1385           6 :   BasicBlock::iterator ItNew = getEntryIns(UI);
    1386             :   Function *UCallee = UI->getCalledFunction();
    1387             :   Type *RetType = UCallee->getReturnType();
    1388          12 :   B.SetInsertPoint(&*ItNew);
    1389           6 :   AllocaInst *Alloc = B.CreateAlloca(RetType, 0,
    1390          12 :     std::string(prefix) + UI->getName());
    1391          12 :   Alloc->setAlignment(UCallee->getParent()->getDataLayout()
    1392           6 :                        .getTypeAllocSize(RetType));
    1393           6 :   return Alloc;
    1394             : }
    1395             : 
    1396           6 : bool AMDGPULibCalls::evaluateScalarMathFunc(FuncInfo &FInfo,
    1397             :                                             double& Res0, double& Res1,
    1398             :                                             Constant *copr0, Constant *copr1,
    1399             :                                             Constant *copr2) {
    1400             :   // By default, opr0/opr1/opr3 holds values of float/double type.
    1401             :   // If they are not float/double, each function has to its
    1402             :   // operand separately.
    1403             :   double opr0=0.0, opr1=0.0, opr2=0.0;
    1404             :   ConstantFP *fpopr0 = dyn_cast_or_null<ConstantFP>(copr0);
    1405             :   ConstantFP *fpopr1 = dyn_cast_or_null<ConstantFP>(copr1);
    1406             :   ConstantFP *fpopr2 = dyn_cast_or_null<ConstantFP>(copr2);
    1407           6 :   if (fpopr0) {
    1408             :     opr0 = (getArgType(FInfo) == AMDGPULibFunc::F64)
    1409          12 :              ? fpopr0->getValueAPF().convertToDouble()
    1410           6 :              : (double)fpopr0->getValueAPF().convertToFloat();
    1411             :   }
    1412             : 
    1413           6 :   if (fpopr1) {
    1414             :     opr1 = (getArgType(FInfo) == AMDGPULibFunc::F64)
    1415           0 :              ? fpopr1->getValueAPF().convertToDouble()
    1416           0 :              : (double)fpopr1->getValueAPF().convertToFloat();
    1417             :   }
    1418             : 
    1419           6 :   if (fpopr2) {
    1420             :     opr2 = (getArgType(FInfo) == AMDGPULibFunc::F64)
    1421           0 :              ? fpopr2->getValueAPF().convertToDouble()
    1422           0 :              : (double)fpopr2->getValueAPF().convertToFloat();
    1423             :   }
    1424             : 
    1425           6 :   switch (FInfo.getId()) {
    1426             :   default : return false;
    1427             : 
    1428           0 :   case AMDGPULibFunc::EI_ACOS:
    1429           0 :     Res0 = acos(opr0);
    1430           0 :     return true;
    1431             : 
    1432           0 :   case AMDGPULibFunc::EI_ACOSH:
    1433             :     // acosh(x) == log(x + sqrt(x*x - 1))
    1434           0 :     Res0 = log(opr0 + sqrt(opr0*opr0 - 1.0));
    1435           0 :     return true;
    1436             : 
    1437           0 :   case AMDGPULibFunc::EI_ACOSPI:
    1438           0 :     Res0 = acos(opr0) / MATH_PI;
    1439           0 :     return true;
    1440             : 
    1441           0 :   case AMDGPULibFunc::EI_ASIN:
    1442           0 :     Res0 = asin(opr0);
    1443           0 :     return true;
    1444             : 
    1445           0 :   case AMDGPULibFunc::EI_ASINH:
    1446             :     // asinh(x) == log(x + sqrt(x*x + 1))
    1447           0 :     Res0 = log(opr0 + sqrt(opr0*opr0 + 1.0));
    1448           0 :     return true;
    1449             : 
    1450           0 :   case AMDGPULibFunc::EI_ASINPI:
    1451           0 :     Res0 = asin(opr0) / MATH_PI;
    1452           0 :     return true;
    1453             : 
    1454           0 :   case AMDGPULibFunc::EI_ATAN:
    1455           0 :     Res0 = atan(opr0);
    1456           0 :     return true;
    1457             : 
    1458           0 :   case AMDGPULibFunc::EI_ATANH:
    1459             :     // atanh(x) == (log(x+1) - log(x-1))/2;
    1460           0 :     Res0 = (log(opr0 + 1.0) - log(opr0 - 1.0))/2.0;
    1461           0 :     return true;
    1462             : 
    1463           0 :   case AMDGPULibFunc::EI_ATANPI:
    1464           0 :     Res0 = atan(opr0) / MATH_PI;
    1465           0 :     return true;
    1466             : 
    1467           0 :   case AMDGPULibFunc::EI_CBRT:
    1468           0 :     Res0 = (opr0 < 0.0) ? -pow(-opr0, 1.0/3.0) : pow(opr0, 1.0/3.0);
    1469           0 :     return true;
    1470             : 
    1471           0 :   case AMDGPULibFunc::EI_COS:
    1472           0 :     Res0 = cos(opr0);
    1473           0 :     return true;
    1474             : 
    1475           0 :   case AMDGPULibFunc::EI_COSH:
    1476           0 :     Res0 = cosh(opr0);
    1477           0 :     return true;
    1478             : 
    1479           0 :   case AMDGPULibFunc::EI_COSPI:
    1480           0 :     Res0 = cos(MATH_PI * opr0);
    1481           0 :     return true;
    1482             : 
    1483           0 :   case AMDGPULibFunc::EI_EXP:
    1484           0 :     Res0 = exp(opr0);
    1485           0 :     return true;
    1486             : 
    1487           0 :   case AMDGPULibFunc::EI_EXP2:
    1488           0 :     Res0 = pow(2.0, opr0);
    1489           0 :     return true;
    1490             : 
    1491           0 :   case AMDGPULibFunc::EI_EXP10:
    1492           0 :     Res0 = pow(10.0, opr0);
    1493           0 :     return true;
    1494             : 
    1495           0 :   case AMDGPULibFunc::EI_EXPM1:
    1496           0 :     Res0 = exp(opr0) - 1.0;
    1497           0 :     return true;
    1498             : 
    1499           0 :   case AMDGPULibFunc::EI_LOG:
    1500           0 :     Res0 = log(opr0);
    1501           0 :     return true;
    1502             : 
    1503           0 :   case AMDGPULibFunc::EI_LOG2:
    1504           0 :     Res0 = log(opr0) / log(2.0);
    1505           0 :     return true;
    1506             : 
    1507           0 :   case AMDGPULibFunc::EI_LOG10:
    1508           0 :     Res0 = log(opr0) / log(10.0);
    1509           0 :     return true;
    1510             : 
    1511           0 :   case AMDGPULibFunc::EI_RSQRT:
    1512           0 :     Res0 = 1.0 / sqrt(opr0);
    1513           0 :     return true;
    1514             : 
    1515           0 :   case AMDGPULibFunc::EI_SIN:
    1516           0 :     Res0 = sin(opr0);
    1517           0 :     return true;
    1518             : 
    1519           0 :   case AMDGPULibFunc::EI_SINH:
    1520           0 :     Res0 = sinh(opr0);
    1521           0 :     return true;
    1522             : 
    1523           0 :   case AMDGPULibFunc::EI_SINPI:
    1524           0 :     Res0 = sin(MATH_PI * opr0);
    1525           0 :     return true;
    1526             : 
    1527           0 :   case AMDGPULibFunc::EI_SQRT:
    1528           0 :     Res0 = sqrt(opr0);
    1529           0 :     return true;
    1530             : 
    1531           0 :   case AMDGPULibFunc::EI_TAN:
    1532           0 :     Res0 = tan(opr0);
    1533           0 :     return true;
    1534             : 
    1535           0 :   case AMDGPULibFunc::EI_TANH:
    1536           0 :     Res0 = tanh(opr0);
    1537           0 :     return true;
    1538             : 
    1539           0 :   case AMDGPULibFunc::EI_TANPI:
    1540           0 :     Res0 = tan(MATH_PI * opr0);
    1541           0 :     return true;
    1542             : 
    1543           6 :   case AMDGPULibFunc::EI_RECIP:
    1544           6 :     Res0 = 1.0 / opr0;
    1545           6 :     return true;
    1546             : 
    1547             :   // two-arg functions
    1548           0 :   case AMDGPULibFunc::EI_DIVIDE:
    1549           0 :     Res0 = opr0 / opr1;
    1550           0 :     return true;
    1551             : 
    1552           0 :   case AMDGPULibFunc::EI_POW:
    1553             :   case AMDGPULibFunc::EI_POWR:
    1554           0 :     Res0 = pow(opr0, opr1);
    1555           0 :     return true;
    1556             : 
    1557             :   case AMDGPULibFunc::EI_POWN: {
    1558             :     if (ConstantInt *iopr1 = dyn_cast_or_null<ConstantInt>(copr1)) {
    1559           0 :       double val = (double)iopr1->getSExtValue();
    1560           0 :       Res0 = pow(opr0, val);
    1561           0 :       return true;
    1562             :     }
    1563             :     return false;
    1564             :   }
    1565             : 
    1566             :   case AMDGPULibFunc::EI_ROOTN: {
    1567             :     if (ConstantInt *iopr1 = dyn_cast_or_null<ConstantInt>(copr1)) {
    1568           0 :       double val = (double)iopr1->getSExtValue();
    1569           0 :       Res0 = pow(opr0, 1.0 / val);
    1570           0 :       return true;
    1571             :     }
    1572             :     return false;
    1573             :   }
    1574             : 
    1575             :   // with ptr arg
    1576           0 :   case AMDGPULibFunc::EI_SINCOS:
    1577           0 :     Res0 = sin(opr0);
    1578           0 :     Res1 = cos(opr0);
    1579           0 :     return true;
    1580             : 
    1581             :   // three-arg functions
    1582           0 :   case AMDGPULibFunc::EI_FMA:
    1583             :   case AMDGPULibFunc::EI_MAD:
    1584           0 :     Res0 = opr0 * opr1 + opr2;
    1585           0 :     return true;
    1586             :   }
    1587             : 
    1588             :   return false;
    1589             : }
    1590             : 
    1591         167 : bool AMDGPULibCalls::evaluateCall(CallInst *aCI, FuncInfo &FInfo) {
    1592         167 :   int numArgs = (int)aCI->getNumArgOperands();
    1593         167 :   if (numArgs > 3)
    1594             :     return false;
    1595             : 
    1596             :   Constant *copr0 = nullptr;
    1597             :   Constant *copr1 = nullptr;
    1598             :   Constant *copr2 = nullptr;
    1599         167 :   if (numArgs > 0) {
    1600             :     if ((copr0 = dyn_cast<Constant>(aCI->getArgOperand(0))) == nullptr)
    1601             :       return false;
    1602             :   }
    1603             : 
    1604          15 :   if (numArgs > 1) {
    1605             :     if ((copr1 = dyn_cast<Constant>(aCI->getArgOperand(1))) == nullptr) {
    1606           9 :       if (FInfo.getId() != AMDGPULibFunc::EI_SINCOS)
    1607             :         return false;
    1608             :     }
    1609             :   }
    1610             : 
    1611           6 :   if (numArgs > 2) {
    1612             :     if ((copr2 = dyn_cast<Constant>(aCI->getArgOperand(2))) == nullptr)
    1613             :       return false;
    1614             :   }
    1615             : 
    1616             :   // At this point, all arguments to aCI are constants.
    1617             : 
    1618             :   // max vector size is 16, and sincos will generate two results.
    1619             :   double DVal0[16], DVal1[16];
    1620             :   bool hasTwoResults = (FInfo.getId() == AMDGPULibFunc::EI_SINCOS);
    1621           6 :   if (getVecSize(FInfo) == 1) {
    1622           6 :     if (!evaluateScalarMathFunc(FInfo, DVal0[0],
    1623             :                                 DVal1[0], copr0, copr1, copr2)) {
    1624             :       return false;
    1625             :     }
    1626             :   } else {
    1627             :     ConstantDataVector *CDV0 = dyn_cast_or_null<ConstantDataVector>(copr0);
    1628             :     ConstantDataVector *CDV1 = dyn_cast_or_null<ConstantDataVector>(copr1);
    1629             :     ConstantDataVector *CDV2 = dyn_cast_or_null<ConstantDataVector>(copr2);
    1630           0 :     for (int i=0; i < getVecSize(FInfo); ++i) {
    1631           0 :       Constant *celt0 = CDV0 ? CDV0->getElementAsConstant(i) : nullptr;
    1632           0 :       Constant *celt1 = CDV1 ? CDV1->getElementAsConstant(i) : nullptr;
    1633           0 :       Constant *celt2 = CDV2 ? CDV2->getElementAsConstant(i) : nullptr;
    1634           0 :       if (!evaluateScalarMathFunc(FInfo, DVal0[i],
    1635           0 :                                   DVal1[i], celt0, celt1, celt2)) {
    1636             :         return false;
    1637             :       }
    1638             :     }
    1639             :   }
    1640             : 
    1641           6 :   LLVMContext &context = CI->getParent()->getParent()->getContext();
    1642             :   Constant *nval0, *nval1;
    1643           6 :   if (getVecSize(FInfo) == 1) {
    1644           6 :     nval0 = ConstantFP::get(CI->getType(), DVal0[0]);
    1645           6 :     if (hasTwoResults)
    1646           0 :       nval1 = ConstantFP::get(CI->getType(), DVal1[0]);
    1647             :   } else {
    1648           0 :     if (getArgType(FInfo) == AMDGPULibFunc::F32) {
    1649             :       SmallVector <float, 0> FVal0, FVal1;
    1650           0 :       for (int i=0; i < getVecSize(FInfo); ++i)
    1651           0 :         FVal0.push_back((float)DVal0[i]);
    1652             :       ArrayRef<float> tmp0(FVal0);
    1653           0 :       nval0 = ConstantDataVector::get(context, tmp0);
    1654           0 :       if (hasTwoResults) {
    1655           0 :         for (int i=0; i < getVecSize(FInfo); ++i)
    1656           0 :           FVal1.push_back((float)DVal1[i]);
    1657             :         ArrayRef<float> tmp1(FVal1);
    1658           0 :         nval1 = ConstantDataVector::get(context, tmp1);
    1659             :       }
    1660             :     } else {
    1661             :       ArrayRef<double> tmp0(DVal0);
    1662           0 :       nval0 = ConstantDataVector::get(context, tmp0);
    1663           0 :       if (hasTwoResults) {
    1664             :         ArrayRef<double> tmp1(DVal1);
    1665           0 :         nval1 = ConstantDataVector::get(context, tmp1);
    1666             :       }
    1667             :     }
    1668             :   }
    1669             : 
    1670           6 :   if (hasTwoResults) {
    1671             :     // sincos
    1672             :     assert(FInfo.getId() == AMDGPULibFunc::EI_SINCOS &&
    1673             :            "math function with ptr arg not supported yet");
    1674           0 :     new StoreInst(nval1, aCI->getArgOperand(1), aCI);
    1675             :   }
    1676             : 
    1677             :   replaceCall(nval0);
    1678           6 :   return true;
    1679             : }
    1680             : 
    1681             : // Public interface to the Simplify LibCalls pass.
    1682          73 : FunctionPass *llvm::createAMDGPUSimplifyLibCallsPass(const TargetOptions &Opt) {
    1683          73 :   return new AMDGPUSimplifyLibCalls(Opt);
    1684             : }
    1685             : 
    1686         130 : FunctionPass *llvm::createAMDGPUUseNativeCallsPass() {
    1687         130 :   return new AMDGPUUseNativeCalls();
    1688             : }
    1689             : 
    1690         553 : static bool setFastFlags(Function &F, const TargetOptions &Options) {
    1691             :   AttrBuilder B;
    1692             : 
    1693         553 :   if (Options.UnsafeFPMath || Options.NoInfsFPMath)
    1694           4 :     B.addAttribute("no-infs-fp-math", "true");
    1695         553 :   if (Options.UnsafeFPMath || Options.NoNaNsFPMath)
    1696           4 :     B.addAttribute("no-nans-fp-math", "true");
    1697         553 :   if (Options.UnsafeFPMath) {
    1698           2 :     B.addAttribute("less-precise-fpmad", "true");
    1699           2 :     B.addAttribute("unsafe-fp-math", "true");
    1700             :   }
    1701             : 
    1702         553 :   if (!B.hasAttributes())
    1703             :     return false;
    1704             : 
    1705           6 :   F.addAttributes(AttributeList::FunctionIndex, B);
    1706             : 
    1707           6 :   return true;
    1708             : }
    1709             : 
    1710         659 : bool AMDGPUSimplifyLibCalls::runOnFunction(Function &F) {
    1711         659 :   if (skipFunction(F))
    1712             :     return false;
    1713             : 
    1714             :   bool Changed = false;
    1715         659 :   auto AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
    1716             : 
    1717             :   LLVM_DEBUG(dbgs() << "AMDIC: process function ";
    1718             :              F.printAsOperand(dbgs(), false, F.getParent()); dbgs() << '\n';);
    1719             : 
    1720         659 :   if (!EnablePreLink)
    1721         553 :     Changed |= setFastFlags(F, Options);
    1722             : 
    1723        1495 :   for (auto &BB : F) {
    1724        5994 :     for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ) {
    1725             :       // Ignore non-calls.
    1726             :       CallInst *CI = dyn_cast<CallInst>(I);
    1727             :       ++I;
    1728        5158 :       if (!CI) continue;
    1729             : 
    1730             :       // Ignore indirect calls.
    1731             :       Function *Callee = CI->getCalledFunction();
    1732             :       if (Callee == 0) continue;
    1733             : 
    1734             :       LLVM_DEBUG(dbgs() << "AMDIC: try folding " << *CI << "\n";
    1735             :                  dbgs().flush());
    1736         804 :       if(Simplifier.fold(CI, AA))
    1737             :         Changed = true;
    1738             :     }
    1739             :   }
    1740             :   return Changed;
    1741             : }
    1742             : 
    1743        1182 : bool AMDGPUUseNativeCalls::runOnFunction(Function &F) {
    1744        1182 :   if (skipFunction(F) || UseNative.empty())
    1745             :     return false;
    1746             : 
    1747             :   bool Changed = false;
    1748         106 :   for (auto &BB : F) {
    1749         336 :     for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ) {
    1750             :       // Ignore non-calls.
    1751             :       CallInst *CI = dyn_cast<CallInst>(I);
    1752             :       ++I;
    1753         283 :       if (!CI) continue;
    1754             : 
    1755             :       // Ignore indirect calls.
    1756             :       Function *Callee = CI->getCalledFunction();
    1757             :       if (Callee == 0) continue;
    1758             : 
    1759          73 :       if(Simplifier.useNative(CI))
    1760             :         Changed = true;
    1761             :     }
    1762             :   }
    1763             :   return Changed;
    1764             : }

Generated by: LCOV version 1.13