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
21namespace 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.
28static 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
60static 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
72static 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
83static 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
96static Intrinsic::ID
97getIntrinsicIDForCall(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