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