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