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