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

Generated by: LCOV version 1.13