1//===-- InstrinsicInst.cpp - Intrinsic Instruction Wrappers ---------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements methods that make it really easy to deal with intrinsic
10// functions.
11//
12// All intrinsic function calls are instances of the call instruction, so these
13// are all subclasses of the CallInst class.  Note that none of these classes
14// has state or virtual methods, which is an important part of this gross/neat
15// hack working.
16//
17// In some cases, arguments to intrinsics need to be generic and are defined as
18// type pointer to empty struct { }*.  To access the real item of interest the
19// cast instruction needs to be stripped away.
20//
21//===----------------------------------------------------------------------===//
22
23#include "llvm/IR/IntrinsicInst.h"
24#include "llvm/ADT/StringSwitch.h"
25#include "llvm/IR/Constants.h"
26#include "llvm/IR/DebugInfoMetadata.h"
27#include "llvm/IR/GlobalVariable.h"
28#include "llvm/IR/Metadata.h"
29#include "llvm/IR/Module.h"
30#include "llvm/IR/Operator.h"
31#include "llvm/IR/PatternMatch.h"
32
33#include "llvm/Support/raw_ostream.h"
34using namespace llvm;
35
36//===----------------------------------------------------------------------===//
37/// DbgVariableIntrinsic - This is the common base class for debug info
38/// intrinsics for variables.
39///
40
41Value *DbgVariableIntrinsic::getVariableLocation(bool AllowNullOp) const {
42  Value *Op = getArgOperand(0);
43  if (AllowNullOp && !Op)
44    return nullptr;
45
46  auto *MD = cast<MetadataAsValue>(Op)->getMetadata();
47  if (auto *V = dyn_cast<ValueAsMetadata>(MD))
48    return V->getValue();
49
50  // When the value goes to null, it gets replaced by an empty MDNode.
51  assert(!cast<MDNode>(MD)->getNumOperands() && "Expected an empty MDNode");
52  return nullptr;
53}
54
55Optional<uint64_t> DbgVariableIntrinsic::getFragmentSizeInBits() const {
56  if (auto Fragment = getExpression()->getFragmentInfo())
57    return Fragment->SizeInBits;
58  return getVariable()->getSizeInBits();
59}
60
61int llvm::Intrinsic::lookupLLVMIntrinsicByName(ArrayRef<const char *> NameTable,
62                                               StringRef Name) {
63  assert(Name.startswith("llvm."));
64
65  // Do successive binary searches of the dotted name components. For
66  // "llvm.gc.experimental.statepoint.p1i8.p1i32", we will find the range of
67  // intrinsics starting with "llvm.gc", then "llvm.gc.experimental", then
68  // "llvm.gc.experimental.statepoint", and then we will stop as the range is
69  // size 1. During the search, we can skip the prefix that we already know is
70  // identical. By using strncmp we consider names with differing suffixes to
71  // be part of the equal range.
72  size_t CmpEnd = 4; // Skip the "llvm" component.
73  const char *const *Low = NameTable.begin();
74  const char *const *High = NameTable.end();
75  const char *const *LastLow = Low;
76  while (CmpEnd < Name.size() && High - Low > 0) {
77    size_t CmpStart = CmpEnd;
78    CmpEnd = Name.find('.', CmpStart + 1);
79    CmpEnd = CmpEnd == StringRef::npos ? Name.size() : CmpEnd;
80    auto Cmp = [CmpStart, CmpEnd](const char *LHS, const char *RHS) {
81      return strncmp(LHS + CmpStart, RHS + CmpStart, CmpEnd - CmpStart) < 0;
82    };
83    LastLow = Low;
84    std::tie(Low, High) = std::equal_range(Low, High, Name.data(), Cmp);
85  }
86  if (High - Low > 0)
87    LastLow = Low;
88
89  if (LastLow == NameTable.end())
90    return -1;
91  StringRef NameFound = *LastLow;
92  if (Name == NameFound ||
93      (Name.startswith(NameFound) && Name[NameFound.size()] == '.'))
94    return LastLow - NameTable.begin();
95  return -1;
96}
97
98Value *InstrProfIncrementInst::getStep() const {
99  if (InstrProfIncrementInstStep::classof(this)) {
100    return const_cast<Value *>(getArgOperand(4));
101  }
102  const Module *M = getModule();
103  LLVMContext &Context = M->getContext();
104  return ConstantInt::get(Type::getInt64Ty(Context), 1);
105}
106
107Optional<RoundingMode> ConstrainedFPIntrinsic::getRoundingMode() const {
108  unsigned NumOperands = getNumArgOperands();
109  Metadata *MD =
110      cast<MetadataAsValue>(getArgOperand(NumOperands - 2))->getMetadata();
111  if (!MD || !isa<MDString>(MD))
112    return None;
113  return StrToRoundingMode(cast<MDString>(MD)->getString());
114}
115
116Optional<fp::ExceptionBehavior>
117ConstrainedFPIntrinsic::getExceptionBehavior() const {
118  unsigned NumOperands = getNumArgOperands();
119  Metadata *MD =
120      cast<MetadataAsValue>(getArgOperand(NumOperands - 1))->getMetadata();
121  if (!MD || !isa<MDString>(MD))
122    return None;
123  return StrToExceptionBehavior(cast<MDString>(MD)->getString());
124}
125
126FCmpInst::Predicate ConstrainedFPCmpIntrinsic::getPredicate() const {
127  Metadata *MD = cast<MetadataAsValue>(getArgOperand(2))->getMetadata();
128  if (!MD || !isa<MDString>(MD))
129    return FCmpInst::BAD_FCMP_PREDICATE;
130  return StringSwitch<FCmpInst::Predicate>(cast<MDString>(MD)->getString())
131      .Case("oeq", FCmpInst::FCMP_OEQ)
132      .Case("ogt", FCmpInst::FCMP_OGT)
133      .Case("oge", FCmpInst::FCMP_OGE)
134      .Case("olt", FCmpInst::FCMP_OLT)
135      .Case("ole", FCmpInst::FCMP_OLE)
136      .Case("one", FCmpInst::FCMP_ONE)
137      .Case("ord", FCmpInst::FCMP_ORD)
138      .Case("uno", FCmpInst::FCMP_UNO)
139      .Case("ueq", FCmpInst::FCMP_UEQ)
140      .Case("ugt", FCmpInst::FCMP_UGT)
141      .Case("uge", FCmpInst::FCMP_UGE)
142      .Case("ult", FCmpInst::FCMP_ULT)
143      .Case("ule", FCmpInst::FCMP_ULE)
144      .Case("une", FCmpInst::FCMP_UNE)
145      .Default(FCmpInst::BAD_FCMP_PREDICATE);
146}
147
148bool ConstrainedFPIntrinsic::isUnaryOp() const {
149  switch (getIntrinsicID()) {
150  default:
151    return false;
152#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC)                         \
153  case Intrinsic::INTRINSIC:                                                   \
154    return NARG == 1;
155#include "llvm/IR/ConstrainedOps.def"
156  }
157}
158
159bool ConstrainedFPIntrinsic::isTernaryOp() const {
160  switch (getIntrinsicID()) {
161  default:
162    return false;
163#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC)                         \
164  case Intrinsic::INTRINSIC:                                                   \
165    return NARG == 3;
166#include "llvm/IR/ConstrainedOps.def"
167  }
168}
169
170bool ConstrainedFPIntrinsic::classof(const IntrinsicInst *I) {
171  switch (I->getIntrinsicID()) {
172#define INSTRUCTION(NAME, NARGS, ROUND_MODE, INTRINSIC)                        \
173  case Intrinsic::INTRINSIC:
174#include "llvm/IR/ConstrainedOps.def"
175    return true;
176  default:
177    return false;
178  }
179}
180
181ElementCount VPIntrinsic::getStaticVectorLength() const {
182  auto GetVectorLengthOfType = [](const Type *T) -> ElementCount {
183    auto VT = cast<VectorType>(T);
184    auto ElemCount = VT->getElementCount();
185    return ElemCount;
186  };
187
188  auto VPMask = getMaskParam();
189  return GetVectorLengthOfType(VPMask->getType());
190}
191
192Value *VPIntrinsic::getMaskParam() const {
193  auto maskPos = GetMaskParamPos(getIntrinsicID());
194  if (maskPos)
195    return getArgOperand(maskPos.getValue());
196  return nullptr;
197}
198
199Value *VPIntrinsic::getVectorLengthParam() const {
200  auto vlenPos = GetVectorLengthParamPos(getIntrinsicID());
201  if (vlenPos)
202    return getArgOperand(vlenPos.getValue());
203  return nullptr;
204}
205
206Optional<int> VPIntrinsic::GetMaskParamPos(Intrinsic::ID IntrinsicID) {
207  switch (IntrinsicID) {
208  default:
209    return None;
210
211#define REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS)                          \
212  case Intrinsic::VPID:                                                        \
213    return MASKPOS;
214#include "llvm/IR/VPIntrinsics.def"
215  }
216}
217
218Optional<int> VPIntrinsic::GetVectorLengthParamPos(Intrinsic::ID IntrinsicID) {
219  switch (IntrinsicID) {
220  default:
221    return None;
222
223#define REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS)                          \
224  case Intrinsic::VPID:                                                        \
225    return VLENPOS;
226#include "llvm/IR/VPIntrinsics.def"
227  }
228}
229
230bool VPIntrinsic::IsVPIntrinsic(Intrinsic::ID ID) {
231  switch (ID) {
232  default:
233    return false;
234
235#define REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS)                          \
236  case Intrinsic::VPID:                                                        \
237    break;
238#include "llvm/IR/VPIntrinsics.def"
239  }
240  return true;
241}
242
243// Equivalent non-predicated opcode
244unsigned VPIntrinsic::GetFunctionalOpcodeForVP(Intrinsic::ID ID) {
245  switch (ID) {
246  default:
247    return Instruction::Call;
248
249#define HANDLE_VP_TO_OC(VPID, OC)                                              \
250  case Intrinsic::VPID:                                                        \
251    return Instruction::OC;
252#include "llvm/IR/VPIntrinsics.def"
253  }
254}
255
256Intrinsic::ID VPIntrinsic::GetForOpcode(unsigned OC) {
257  switch (OC) {
258  default:
259    return Intrinsic::not_intrinsic;
260
261#define HANDLE_VP_TO_OC(VPID, OC)                                              \
262  case Instruction::OC:                                                        \
263    return Intrinsic::VPID;
264#include "llvm/IR/VPIntrinsics.def"
265  }
266}
267
268bool VPIntrinsic::canIgnoreVectorLengthParam() const {
269  using namespace PatternMatch;
270
271  ElementCount EC = getStaticVectorLength();
272
273  // No vlen param - no lanes masked-off by it.
274  auto *VLParam = getVectorLengthParam();
275  if (!VLParam)
276    return true;
277
278  // Note that the VP intrinsic causes undefined behavior if the Explicit Vector
279  // Length parameter is strictly greater-than the number of vector elements of
280  // the operation. This function returns true when this is detected statically
281  // in the IR.
282
283  // Check whether "W == vscale * EC.Min"
284  if (EC.Scalable) {
285    // Undig the DL
286    auto ParMod = this->getModule();
287    if (!ParMod)
288      return false;
289    const auto &DL = ParMod->getDataLayout();
290
291    // Compare vscale patterns
292    uint64_t VScaleFactor;
293    if (match(VLParam, m_c_Mul(m_ConstantInt(VScaleFactor), m_VScale(DL))))
294      return VScaleFactor >= EC.Min;
295    return (EC.Min == 1) && match(VLParam, m_VScale(DL));
296  }
297
298  // standard SIMD operation
299  auto VLConst = dyn_cast<ConstantInt>(VLParam);
300  if (!VLConst)
301    return false;
302
303  uint64_t VLNum = VLConst->getZExtValue();
304  if (VLNum >= EC.Min)
305    return true;
306
307  return false;
308}
309
310Instruction::BinaryOps BinaryOpIntrinsic::getBinaryOp() const {
311  switch (getIntrinsicID()) {
312  case Intrinsic::uadd_with_overflow:
313  case Intrinsic::sadd_with_overflow:
314  case Intrinsic::uadd_sat:
315  case Intrinsic::sadd_sat:
316    return Instruction::Add;
317  case Intrinsic::usub_with_overflow:
318  case Intrinsic::ssub_with_overflow:
319  case Intrinsic::usub_sat:
320  case Intrinsic::ssub_sat:
321    return Instruction::Sub;
322  case Intrinsic::umul_with_overflow:
323  case Intrinsic::smul_with_overflow:
324    return Instruction::Mul;
325  default:
326    llvm_unreachable("Invalid intrinsic");
327  }
328}
329
330bool BinaryOpIntrinsic::isSigned() const {
331  switch (getIntrinsicID()) {
332  case Intrinsic::sadd_with_overflow:
333  case Intrinsic::ssub_with_overflow:
334  case Intrinsic::smul_with_overflow:
335  case Intrinsic::sadd_sat:
336  case Intrinsic::ssub_sat:
337    return true;
338  default:
339    return false;
340  }
341}
342
343unsigned BinaryOpIntrinsic::getNoWrapKind() const {
344  if (isSigned())
345    return OverflowingBinaryOperator::NoSignedWrap;
346  else
347    return OverflowingBinaryOperator::NoUnsignedWrap;
348}
349