blob: b6b036d0bbca2adc2c3f83d1cf78f9c1fb7a4572 [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"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000024#include "llvm/ADT/StringSwitch.h"
Chandler Carruth9fb823b2013-01-02 11:36:10 +000025#include "llvm/IR/Constants.h"
Bjorn Pettersson428caf92018-06-15 13:48:55 +000026#include "llvm/IR/DebugInfoMetadata.h"
Chandler Carruth9fb823b2013-01-02 11:36:10 +000027#include "llvm/IR/GlobalVariable.h"
28#include "llvm/IR/Metadata.h"
Xinliang David Lia754c472016-09-20 19:07:22 +000029#include "llvm/IR/Module.h"
Simon Moll2eeb6ca2020-04-15 12:05:07 +020030#include "llvm/IR/Operator.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 Pavlovc7ff5b32020-03-26 14:51:09 +0700107Optional<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
Simon Moll2eeb6ca2020-04-15 12:05:07 +0200126FCmpInst::Predicate ConstrainedFPCmpIntrinsic::getPredicate() const {
127 Metadata *MD = cast<MetadataAsValue>(getArgOperand(2))->getMetadata();
Ulrich Weigand9db13b52019-12-06 11:30:04 +0100128 if (!MD || !isa<MDString>(MD))
129 return FCmpInst::BAD_FCMP_PREDICATE;
130 return StringSwitch<FCmpInst::Predicate>(cast<MDString>(MD)->getString())
Simon Moll2eeb6ca2020-04-15 12:05:07 +0200131 .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);
Ulrich Weigand9db13b52019-12-06 11:30:04 +0100146}
147
Andrew Kaylorf4660012017-05-25 21:31:00 +0000148bool ConstrainedFPIntrinsic::isUnaryOp() const {
149 switch (getIntrinsicID()) {
Simon Moll2eeb6ca2020-04-15 12:05:07 +0200150 default:
151 return false;
Wang, Pengfei17b8f962020-01-17 10:32:30 +0800152#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \
Simon Moll2eeb6ca2020-04-15 12:05:07 +0200153 case Intrinsic::INTRINSIC: \
154 return NARG == 1;
Serge Pavlov0c50c0b2019-11-05 20:42:16 +0700155#include "llvm/IR/ConstrainedOps.def"
Andrew Kaylorf4660012017-05-25 21:31:00 +0000156 }
157}
Wei Dinga131d3f2017-08-24 04:18:24 +0000158
159bool ConstrainedFPIntrinsic::isTernaryOp() const {
160 switch (getIntrinsicID()) {
Simon Moll2eeb6ca2020-04-15 12:05:07 +0200161 default:
162 return false;
Wang, Pengfei17b8f962020-01-17 10:32:30 +0800163#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \
Simon Moll2eeb6ca2020-04-15 12:05:07 +0200164 case Intrinsic::INTRINSIC: \
165 return NARG == 3;
Serge Pavlov0c50c0b2019-11-05 20:42:16 +0700166#include "llvm/IR/ConstrainedOps.def"
167 }
168}
169
170bool ConstrainedFPIntrinsic::classof(const IntrinsicInst *I) {
171 switch (I->getIntrinsicID()) {
Wang, Pengfei17b8f962020-01-17 10:32:30 +0800172#define INSTRUCTION(NAME, NARGS, ROUND_MODE, INTRINSIC) \
Serge Pavlov0c50c0b2019-11-05 20:42:16 +0700173 case Intrinsic::INTRINSIC:
174#include "llvm/IR/ConstrainedOps.def"
175 return true;
176 default:
177 return false;
Wei Dinga131d3f2017-08-24 04:18:24 +0000178 }
179}
180
Simon Moll733b3192020-03-17 14:52:06 +0100181ElementCount 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
David Sherwoodf4257c52020-08-14 12:15:59 +0100283 // Check whether "W == vscale * EC.getKnownMinValue()"
284 if (EC.isScalable()) {
Simon Moll733b3192020-03-17 14:52:06 +0100285 // 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
Simon Molla0dfdda2020-06-04 11:09:48 +0200292 uint64_t VScaleFactor;
293 if (match(VLParam, m_c_Mul(m_ConstantInt(VScaleFactor), m_VScale(DL))))
David Sherwoodf4257c52020-08-14 12:15:59 +0100294 return VScaleFactor >= EC.getKnownMinValue();
295 return (EC.getKnownMinValue() == 1) && match(VLParam, m_VScale(DL));
Simon Moll733b3192020-03-17 14:52:06 +0100296 }
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();
David Sherwoodf4257c52020-08-14 12:15:59 +0100304 if (VLNum >= EC.getKnownMinValue())
Simon Moll733b3192020-03-17 14:52:06 +0100305 return true;
306
307 return false;
308}
309
Nikita Popov2fb0a822019-05-28 18:08:06 +0000310Instruction::BinaryOps BinaryOpIntrinsic::getBinaryOp() const {
Nikita Popov79dffc62019-04-16 18:55:16 +0000311 switch (getIntrinsicID()) {
Simon Moll2eeb6ca2020-04-15 12:05:07 +0200312 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");
Nikita Popov79dffc62019-04-16 18:55:16 +0000327 }
328}
329
Nikita Popov2fb0a822019-05-28 18:08:06 +0000330bool BinaryOpIntrinsic::isSigned() const {
Nikita Popov79dffc62019-04-16 18:55:16 +0000331 switch (getIntrinsicID()) {
Simon Moll2eeb6ca2020-04-15 12:05:07 +0200332 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;
Nikita Popov79dffc62019-04-16 18:55:16 +0000340 }
341}
342
Nikita Popov2fb0a822019-05-28 18:08:06 +0000343unsigned BinaryOpIntrinsic::getNoWrapKind() const {
Nikita Popov79dffc62019-04-16 18:55:16 +0000344 if (isSigned())
345 return OverflowingBinaryOperator::NoSignedWrap;
346 else
347 return OverflowingBinaryOperator::NoUnsignedWrap;
348}