blob: 1ce17aa63bdbfc8ea9be486bb26b2aabb53a22f2 [file] [log] [blame]
Nick Lewyckyea08c702014-02-26 03:10:45 +00001//===-- InstrinsicInst.cpp - Intrinsic Instruction Wrappers ---------------===//
Jim Laskey0cf8ed62006-03-23 18:05:12 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Jim Laskey0cf8ed62006-03-23 18:05:12 +00006//
7//===----------------------------------------------------------------------===//
Jim Laskey864e4442006-03-24 10:00:56 +00008//
9// This file implements methods that make it really easy to deal with intrinsic
Devang Patelbe94f232010-01-05 01:10:40 +000010// functions.
Jim Laskey864e4442006-03-24 10:00:56 +000011//
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.
Wei Dinga131d3f2017-08-24 04:18:24 +000016//
Jim Laskey864e4442006-03-24 10:00:56 +000017// 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
Wei Dinga131d3f2017-08-24 04:18:24 +000019// cast instruction needs to be stripped away.
Jim Laskey864e4442006-03-24 10:00:56 +000020//
21//===----------------------------------------------------------------------===//
Jim Laskey0cf8ed62006-03-23 18:05:12 +000022
Chandler Carruth9fb823b2013-01-02 11:36:10 +000023#include "llvm/IR/IntrinsicInst.h"
Nikita Popov79dffc62019-04-16 18:55:16 +000024#include "llvm/IR/Operator.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000025#include "llvm/ADT/StringSwitch.h"
Chandler Carruth9fb823b2013-01-02 11:36:10 +000026#include "llvm/IR/Constants.h"
Bjorn Pettersson428caf92018-06-15 13:48:55 +000027#include "llvm/IR/DebugInfoMetadata.h"
Chandler Carruth9fb823b2013-01-02 11:36:10 +000028#include "llvm/IR/GlobalVariable.h"
29#include "llvm/IR/Metadata.h"
Xinliang David Lia754c472016-09-20 19:07:22 +000030#include "llvm/IR/Module.h"
Simon Moll733b3192020-03-17 14:52:06 +010031#include "llvm/IR/PatternMatch.h"
32
Reid Klecknerc2752da2016-01-26 22:33:19 +000033#include "llvm/Support/raw_ostream.h"
Jim Laskey0cf8ed62006-03-23 18:05:12 +000034using namespace llvm;
35
36//===----------------------------------------------------------------------===//
Hsiangkai Wangef72e482018-08-06 03:59:47 +000037/// DbgVariableIntrinsic - This is the common base class for debug info
38/// intrinsics for variables.
Jim Laskey0cf8ed62006-03-23 18:05:12 +000039///
40
Hsiangkai Wangef72e482018-08-06 03:59:47 +000041Value *DbgVariableIntrinsic::getVariableLocation(bool AllowNullOp) const {
Duncan P. N. Exon Smith40b44e12016-03-29 18:56:03 +000042 Value *Op = getArgOperand(0);
43 if (AllowNullOp && !Op)
44 return nullptr;
45
Duncan P. N. Exon Smith5bf8fef2014-12-09 18:38:53 +000046 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.
Hsiangkai Wangef72e482018-08-06 03:59:47 +000051 assert(!cast<MDNode>(MD)->getNumOperands() && "Expected an empty MDNode");
Duncan P. N. Exon Smith5bf8fef2014-12-09 18:38:53 +000052 return nullptr;
53}
54
Hsiangkai Wangef72e482018-08-06 03:59:47 +000055Optional<uint64_t> DbgVariableIntrinsic::getFragmentSizeInBits() const {
Bjorn Pettersson428caf92018-06-15 13:48:55 +000056 if (auto Fragment = getExpression()->getFragmentInfo())
57 return Fragment->SizeInBits;
58 return getVariable()->getSizeInBits();
59}
60
Reid Klecknerc2752da2016-01-26 22:33:19 +000061int 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.
Reid Klecknerc2752da2016-01-26 22:33:19 +000072 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) {
Simon Pilgrimcc972982019-09-24 12:30:07 +000077 size_t CmpStart = CmpEnd;
Reid Klecknerc2752da2016-01-26 22:33:19 +000078 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}
Xinliang David Lia754c472016-09-20 19:07:22 +000097
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}
Andrew Kaylora0a11642017-01-26 23:27:59 +0000106
Serge Pavlovea8678d2019-08-29 19:29:11 +0700107Optional<fp::RoundingMode> ConstrainedFPIntrinsic::getRoundingMode() const {
Andrew Kaylorf4660012017-05-25 21:31:00 +0000108 unsigned NumOperands = getNumArgOperands();
Wei Dinga131d3f2017-08-24 04:18:24 +0000109 Metadata *MD =
Simon Pilgrim06cdcb52019-09-24 11:40:45 +0000110 cast<MetadataAsValue>(getArgOperand(NumOperands - 2))->getMetadata();
Andrew Kaylora0a11642017-01-26 23:27:59 +0000111 if (!MD || !isa<MDString>(MD))
Kevin P. Neal472e5dd2019-07-08 16:18:18 +0000112 return None;
113 return StrToRoundingMode(cast<MDString>(MD)->getString());
114}
Andrew Kaylora0a11642017-01-26 23:27:59 +0000115
Serge Pavlovea8678d2019-08-29 19:29:11 +0700116Optional<fp::ExceptionBehavior>
Andrew Kaylora0a11642017-01-26 23:27:59 +0000117ConstrainedFPIntrinsic::getExceptionBehavior() const {
Andrew Kaylorf4660012017-05-25 21:31:00 +0000118 unsigned NumOperands = getNumArgOperands();
Wei Dinga131d3f2017-08-24 04:18:24 +0000119 Metadata *MD =
Simon Pilgrim06cdcb52019-09-24 11:40:45 +0000120 cast<MetadataAsValue>(getArgOperand(NumOperands - 1))->getMetadata();
Andrew Kaylora0a11642017-01-26 23:27:59 +0000121 if (!MD || !isa<MDString>(MD))
Kevin P. Neal472e5dd2019-07-08 16:18:18 +0000122 return None;
123 return StrToExceptionBehavior(cast<MDString>(MD)->getString());
124}
125
Ulrich Weigand9db13b52019-12-06 11:30:04 +0100126FCmpInst::Predicate
127ConstrainedFPCmpIntrinsic::getPredicate() const {
128 Metadata *MD =
129 cast<MetadataAsValue>(getArgOperand(2))->getMetadata();
130 if (!MD || !isa<MDString>(MD))
131 return FCmpInst::BAD_FCMP_PREDICATE;
132 return StringSwitch<FCmpInst::Predicate>(cast<MDString>(MD)->getString())
133 .Case("oeq", FCmpInst::FCMP_OEQ)
134 .Case("ogt", FCmpInst::FCMP_OGT)
135 .Case("oge", FCmpInst::FCMP_OGE)
136 .Case("olt", FCmpInst::FCMP_OLT)
137 .Case("ole", FCmpInst::FCMP_OLE)
138 .Case("one", FCmpInst::FCMP_ONE)
139 .Case("ord", FCmpInst::FCMP_ORD)
140 .Case("uno", FCmpInst::FCMP_UNO)
141 .Case("ueq", FCmpInst::FCMP_UEQ)
142 .Case("ugt", FCmpInst::FCMP_UGT)
143 .Case("uge", FCmpInst::FCMP_UGE)
144 .Case("ult", FCmpInst::FCMP_ULT)
145 .Case("ule", FCmpInst::FCMP_ULE)
146 .Case("une", FCmpInst::FCMP_UNE)
147 .Default(FCmpInst::BAD_FCMP_PREDICATE);
148}
149
Andrew Kaylorf4660012017-05-25 21:31:00 +0000150bool ConstrainedFPIntrinsic::isUnaryOp() const {
151 switch (getIntrinsicID()) {
Wei Dinga131d3f2017-08-24 04:18:24 +0000152 default:
Andrew Kaylorf4660012017-05-25 21:31:00 +0000153 return false;
Wang, Pengfei17b8f962020-01-17 10:32:30 +0800154#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \
Serge Pavlov0c50c0b2019-11-05 20:42:16 +0700155 case Intrinsic::INTRINSIC: \
156 return NARG == 1;
157#include "llvm/IR/ConstrainedOps.def"
Andrew Kaylorf4660012017-05-25 21:31:00 +0000158 }
159}
Wei Dinga131d3f2017-08-24 04:18:24 +0000160
161bool ConstrainedFPIntrinsic::isTernaryOp() const {
162 switch (getIntrinsicID()) {
163 default:
164 return false;
Wang, Pengfei17b8f962020-01-17 10:32:30 +0800165#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \
Serge Pavlov0c50c0b2019-11-05 20:42:16 +0700166 case Intrinsic::INTRINSIC: \
167 return NARG == 3;
168#include "llvm/IR/ConstrainedOps.def"
169 }
170}
171
172bool ConstrainedFPIntrinsic::classof(const IntrinsicInst *I) {
173 switch (I->getIntrinsicID()) {
Wang, Pengfei17b8f962020-01-17 10:32:30 +0800174#define INSTRUCTION(NAME, NARGS, ROUND_MODE, INTRINSIC) \
Serge Pavlov0c50c0b2019-11-05 20:42:16 +0700175 case Intrinsic::INTRINSIC:
176#include "llvm/IR/ConstrainedOps.def"
177 return true;
178 default:
179 return false;
Wei Dinga131d3f2017-08-24 04:18:24 +0000180 }
181}
182
Simon Moll733b3192020-03-17 14:52:06 +0100183ElementCount VPIntrinsic::getStaticVectorLength() const {
184 auto GetVectorLengthOfType = [](const Type *T) -> ElementCount {
185 auto VT = cast<VectorType>(T);
186 auto ElemCount = VT->getElementCount();
187 return ElemCount;
188 };
189
190 auto VPMask = getMaskParam();
191 return GetVectorLengthOfType(VPMask->getType());
192}
193
194Value *VPIntrinsic::getMaskParam() const {
195 auto maskPos = GetMaskParamPos(getIntrinsicID());
196 if (maskPos)
197 return getArgOperand(maskPos.getValue());
198 return nullptr;
199}
200
201Value *VPIntrinsic::getVectorLengthParam() const {
202 auto vlenPos = GetVectorLengthParamPos(getIntrinsicID());
203 if (vlenPos)
204 return getArgOperand(vlenPos.getValue());
205 return nullptr;
206}
207
208Optional<int> VPIntrinsic::GetMaskParamPos(Intrinsic::ID IntrinsicID) {
209 switch (IntrinsicID) {
210 default:
211 return None;
212
213#define REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS) \
214 case Intrinsic::VPID: \
215 return MASKPOS;
216#include "llvm/IR/VPIntrinsics.def"
217 }
218}
219
220Optional<int> VPIntrinsic::GetVectorLengthParamPos(Intrinsic::ID IntrinsicID) {
221 switch (IntrinsicID) {
222 default:
223 return None;
224
225#define REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS) \
226 case Intrinsic::VPID: \
227 return VLENPOS;
228#include "llvm/IR/VPIntrinsics.def"
229 }
230}
231
232bool VPIntrinsic::IsVPIntrinsic(Intrinsic::ID ID) {
233 switch (ID) {
234 default:
235 return false;
236
237#define REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS) \
238 case Intrinsic::VPID: \
239 break;
240#include "llvm/IR/VPIntrinsics.def"
241 }
242 return true;
243}
244
245// Equivalent non-predicated opcode
246unsigned VPIntrinsic::GetFunctionalOpcodeForVP(Intrinsic::ID ID) {
247 switch (ID) {
248 default:
249 return Instruction::Call;
250
251#define HANDLE_VP_TO_OC(VPID, OC) \
252 case Intrinsic::VPID: \
253 return Instruction::OC;
254#include "llvm/IR/VPIntrinsics.def"
255 }
256}
257
258Intrinsic::ID VPIntrinsic::GetForOpcode(unsigned OC) {
259 switch (OC) {
260 default:
261 return Intrinsic::not_intrinsic;
262
263#define HANDLE_VP_TO_OC(VPID, OC) \
264 case Instruction::OC: \
265 return Intrinsic::VPID;
266#include "llvm/IR/VPIntrinsics.def"
267 }
268}
269
270bool VPIntrinsic::canIgnoreVectorLengthParam() const {
271 using namespace PatternMatch;
272
273 ElementCount EC = getStaticVectorLength();
274
275 // No vlen param - no lanes masked-off by it.
276 auto *VLParam = getVectorLengthParam();
277 if (!VLParam)
278 return true;
279
280 // Note that the VP intrinsic causes undefined behavior if the Explicit Vector
281 // Length parameter is strictly greater-than the number of vector elements of
282 // the operation. This function returns true when this is detected statically
283 // in the IR.
284
285 // Check whether "W == vscale * EC.Min"
286 if (EC.Scalable) {
287 // Undig the DL
288 auto ParMod = this->getModule();
289 if (!ParMod)
290 return false;
291 const auto &DL = ParMod->getDataLayout();
292
293 // Compare vscale patterns
294 uint64_t ParamFactor;
295 if (EC.Min > 1 &&
296 match(VLParam, m_c_BinOp(m_ConstantInt(ParamFactor), m_VScale(DL)))) {
297 return ParamFactor >= EC.Min;
298 }
299 if (match(VLParam, m_VScale(DL))) {
300 return ParamFactor;
301 }
302 return false;
303 }
304
305 // standard SIMD operation
306 auto VLConst = dyn_cast<ConstantInt>(VLParam);
307 if (!VLConst)
308 return false;
309
310 uint64_t VLNum = VLConst->getZExtValue();
311 if (VLNum >= EC.Min)
312 return true;
313
314 return false;
315}
316
Nikita Popov2fb0a822019-05-28 18:08:06 +0000317Instruction::BinaryOps BinaryOpIntrinsic::getBinaryOp() const {
Nikita Popov79dffc62019-04-16 18:55:16 +0000318 switch (getIntrinsicID()) {
319 case Intrinsic::uadd_with_overflow:
320 case Intrinsic::sadd_with_overflow:
Nikita Popov2fb0a822019-05-28 18:08:06 +0000321 case Intrinsic::uadd_sat:
322 case Intrinsic::sadd_sat:
Nikita Popov79dffc62019-04-16 18:55:16 +0000323 return Instruction::Add;
324 case Intrinsic::usub_with_overflow:
325 case Intrinsic::ssub_with_overflow:
Nikita Popov2fb0a822019-05-28 18:08:06 +0000326 case Intrinsic::usub_sat:
327 case Intrinsic::ssub_sat:
Nikita Popov79dffc62019-04-16 18:55:16 +0000328 return Instruction::Sub;
329 case Intrinsic::umul_with_overflow:
330 case Intrinsic::smul_with_overflow:
331 return Instruction::Mul;
332 default:
333 llvm_unreachable("Invalid intrinsic");
334 }
335}
336
Nikita Popov2fb0a822019-05-28 18:08:06 +0000337bool BinaryOpIntrinsic::isSigned() const {
Nikita Popov79dffc62019-04-16 18:55:16 +0000338 switch (getIntrinsicID()) {
339 case Intrinsic::sadd_with_overflow:
340 case Intrinsic::ssub_with_overflow:
341 case Intrinsic::smul_with_overflow:
Nikita Popov2fb0a822019-05-28 18:08:06 +0000342 case Intrinsic::sadd_sat:
343 case Intrinsic::ssub_sat:
Nikita Popov79dffc62019-04-16 18:55:16 +0000344 return true;
345 default:
346 return false;
347 }
348}
349
Nikita Popov2fb0a822019-05-28 18:08:06 +0000350unsigned BinaryOpIntrinsic::getNoWrapKind() const {
Nikita Popov79dffc62019-04-16 18:55:16 +0000351 if (isSigned())
352 return OverflowingBinaryOperator::NoSignedWrap;
353 else
354 return OverflowingBinaryOperator::NoUnsignedWrap;
355}