Home | History | Annotate | Download | only in Utils
      1 //===- llvm/Transforms/Utils/VectorUtils.h - Vector utilities -*- C++ -*-=====//
      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 // This file defines some vectorizer utilities.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #ifndef LLVM_TRANSFORMS_UTILS_VECTORUTILS_H
     15 #define LLVM_TRANSFORMS_UTILS_VECTORUTILS_H
     16 
     17 #include "llvm/IR/Intrinsics.h"
     18 #include "llvm/IR/IntrinsicInst.h"
     19 #include "llvm/Target/TargetLibraryInfo.h"
     20 
     21 namespace llvm {
     22 
     23 /// \brief Identify if the intrinsic is trivially vectorizable.
     24 ///
     25 /// This method returns true if the intrinsic's argument types are all
     26 /// scalars for the scalar form of the intrinsic and all vectors for
     27 /// the vector form of the intrinsic.
     28 static inline bool isTriviallyVectorizable(Intrinsic::ID ID) {
     29   switch (ID) {
     30   case Intrinsic::sqrt:
     31   case Intrinsic::sin:
     32   case Intrinsic::cos:
     33   case Intrinsic::exp:
     34   case Intrinsic::exp2:
     35   case Intrinsic::log:
     36   case Intrinsic::log10:
     37   case Intrinsic::log2:
     38   case Intrinsic::fabs:
     39   case Intrinsic::copysign:
     40   case Intrinsic::floor:
     41   case Intrinsic::ceil:
     42   case Intrinsic::trunc:
     43   case Intrinsic::rint:
     44   case Intrinsic::nearbyint:
     45   case Intrinsic::round:
     46   case Intrinsic::bswap:
     47   case Intrinsic::ctpop:
     48   case Intrinsic::pow:
     49   case Intrinsic::fma:
     50   case Intrinsic::fmuladd:
     51   case Intrinsic::ctlz:
     52   case Intrinsic::cttz:
     53   case Intrinsic::powi:
     54     return true;
     55   default:
     56     return false;
     57   }
     58 }
     59 
     60 static bool hasVectorInstrinsicScalarOpd(Intrinsic::ID ID,
     61                                          unsigned ScalarOpdIdx) {
     62   switch (ID) {
     63     case Intrinsic::ctlz:
     64     case Intrinsic::cttz:
     65     case Intrinsic::powi:
     66       return (ScalarOpdIdx == 1);
     67     default:
     68       return false;
     69   }
     70 }
     71 
     72 static Intrinsic::ID checkUnaryFloatSignature(const CallInst &I,
     73                                               Intrinsic::ID ValidIntrinsicID) {
     74   if (I.getNumArgOperands() != 1 ||
     75       !I.getArgOperand(0)->getType()->isFloatingPointTy() ||
     76       I.getType() != I.getArgOperand(0)->getType() ||
     77       !I.onlyReadsMemory())
     78     return Intrinsic::not_intrinsic;
     79 
     80   return ValidIntrinsicID;
     81 }
     82 
     83 static Intrinsic::ID checkBinaryFloatSignature(const CallInst &I,
     84                                                Intrinsic::ID ValidIntrinsicID) {
     85   if (I.getNumArgOperands() != 2 ||
     86       !I.getArgOperand(0)->getType()->isFloatingPointTy() ||
     87       !I.getArgOperand(1)->getType()->isFloatingPointTy() ||
     88       I.getType() != I.getArgOperand(0)->getType() ||
     89       I.getType() != I.getArgOperand(1)->getType() ||
     90       !I.onlyReadsMemory())
     91     return Intrinsic::not_intrinsic;
     92 
     93   return ValidIntrinsicID;
     94 }
     95 
     96 static Intrinsic::ID
     97 getIntrinsicIDForCall(CallInst *CI, const TargetLibraryInfo *TLI) {
     98   // If we have an intrinsic call, check if it is trivially vectorizable.
     99   if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(CI)) {
    100     Intrinsic::ID ID = II->getIntrinsicID();
    101     if (isTriviallyVectorizable(ID) || ID == Intrinsic::lifetime_start ||
    102         ID == Intrinsic::lifetime_end)
    103       return ID;
    104     else
    105       return Intrinsic::not_intrinsic;
    106   }
    107 
    108   if (!TLI)
    109     return Intrinsic::not_intrinsic;
    110 
    111   LibFunc::Func Func;
    112   Function *F = CI->getCalledFunction();
    113   // We're going to make assumptions on the semantics of the functions, check
    114   // that the target knows that it's available in this environment and it does
    115   // not have local linkage.
    116   if (!F || F->hasLocalLinkage() || !TLI->getLibFunc(F->getName(), Func))
    117     return Intrinsic::not_intrinsic;
    118 
    119   // Otherwise check if we have a call to a function that can be turned into a
    120   // vector intrinsic.
    121   switch (Func) {
    122   default:
    123     break;
    124   case LibFunc::sin:
    125   case LibFunc::sinf:
    126   case LibFunc::sinl:
    127     return checkUnaryFloatSignature(*CI, Intrinsic::sin);
    128   case LibFunc::cos:
    129   case LibFunc::cosf:
    130   case LibFunc::cosl:
    131     return checkUnaryFloatSignature(*CI, Intrinsic::cos);
    132   case LibFunc::exp:
    133   case LibFunc::expf:
    134   case LibFunc::expl:
    135     return checkUnaryFloatSignature(*CI, Intrinsic::exp);
    136   case LibFunc::exp2:
    137   case LibFunc::exp2f:
    138   case LibFunc::exp2l:
    139     return checkUnaryFloatSignature(*CI, Intrinsic::exp2);
    140   case LibFunc::log:
    141   case LibFunc::logf:
    142   case LibFunc::logl:
    143     return checkUnaryFloatSignature(*CI, Intrinsic::log);
    144   case LibFunc::log10:
    145   case LibFunc::log10f:
    146   case LibFunc::log10l:
    147     return checkUnaryFloatSignature(*CI, Intrinsic::log10);
    148   case LibFunc::log2:
    149   case LibFunc::log2f:
    150   case LibFunc::log2l:
    151     return checkUnaryFloatSignature(*CI, Intrinsic::log2);
    152   case LibFunc::fabs:
    153   case LibFunc::fabsf:
    154   case LibFunc::fabsl:
    155     return checkUnaryFloatSignature(*CI, Intrinsic::fabs);
    156   case LibFunc::copysign:
    157   case LibFunc::copysignf:
    158   case LibFunc::copysignl:
    159     return checkBinaryFloatSignature(*CI, Intrinsic::copysign);
    160   case LibFunc::floor:
    161   case LibFunc::floorf:
    162   case LibFunc::floorl:
    163     return checkUnaryFloatSignature(*CI, Intrinsic::floor);
    164   case LibFunc::ceil:
    165   case LibFunc::ceilf:
    166   case LibFunc::ceill:
    167     return checkUnaryFloatSignature(*CI, Intrinsic::ceil);
    168   case LibFunc::trunc:
    169   case LibFunc::truncf:
    170   case LibFunc::truncl:
    171     return checkUnaryFloatSignature(*CI, Intrinsic::trunc);
    172   case LibFunc::rint:
    173   case LibFunc::rintf:
    174   case LibFunc::rintl:
    175     return checkUnaryFloatSignature(*CI, Intrinsic::rint);
    176   case LibFunc::nearbyint:
    177   case LibFunc::nearbyintf:
    178   case LibFunc::nearbyintl:
    179     return checkUnaryFloatSignature(*CI, Intrinsic::nearbyint);
    180   case LibFunc::round:
    181   case LibFunc::roundf:
    182   case LibFunc::roundl:
    183     return checkUnaryFloatSignature(*CI, Intrinsic::round);
    184   case LibFunc::pow:
    185   case LibFunc::powf:
    186   case LibFunc::powl:
    187     return checkBinaryFloatSignature(*CI, Intrinsic::pow);
    188   }
    189 
    190   return Intrinsic::not_intrinsic;
    191 }
    192 
    193 } // llvm namespace
    194 
    195 #endif
    196