• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
isTriviallyVectorizable(Intrinsic::ID ID)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 
hasVectorInstrinsicScalarOpd(Intrinsic::ID ID,unsigned ScalarOpdIdx)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 
checkUnaryFloatSignature(const CallInst & I,Intrinsic::ID ValidIntrinsicID)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 
checkBinaryFloatSignature(const CallInst & I,Intrinsic::ID ValidIntrinsicID)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
getIntrinsicIDForCall(CallInst * CI,const TargetLibraryInfo * TLI)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