blob: 7a042326f67f65a5b9bb524c8f1e6a948d9266f5 [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"
Reid Klecknerc2752da2016-01-26 22:33:19 +000031#include "llvm/Support/raw_ostream.h"
Jim Laskey0cf8ed62006-03-23 18:05:12 +000032using namespace llvm;
33
34//===----------------------------------------------------------------------===//
Hsiangkai Wangef72e482018-08-06 03:59:47 +000035/// DbgVariableIntrinsic - This is the common base class for debug info
36/// intrinsics for variables.
Jim Laskey0cf8ed62006-03-23 18:05:12 +000037///
38
Hsiangkai Wangef72e482018-08-06 03:59:47 +000039Value *DbgVariableIntrinsic::getVariableLocation(bool AllowNullOp) const {
Duncan P. N. Exon Smith40b44e12016-03-29 18:56:03 +000040 Value *Op = getArgOperand(0);
41 if (AllowNullOp && !Op)
42 return nullptr;
43
Duncan P. N. Exon Smith5bf8fef2014-12-09 18:38:53 +000044 auto *MD = cast<MetadataAsValue>(Op)->getMetadata();
45 if (auto *V = dyn_cast<ValueAsMetadata>(MD))
46 return V->getValue();
47
48 // When the value goes to null, it gets replaced by an empty MDNode.
Hsiangkai Wangef72e482018-08-06 03:59:47 +000049 assert(!cast<MDNode>(MD)->getNumOperands() && "Expected an empty MDNode");
Duncan P. N. Exon Smith5bf8fef2014-12-09 18:38:53 +000050 return nullptr;
51}
52
Hsiangkai Wangef72e482018-08-06 03:59:47 +000053Optional<uint64_t> DbgVariableIntrinsic::getFragmentSizeInBits() const {
Bjorn Pettersson428caf92018-06-15 13:48:55 +000054 if (auto Fragment = getExpression()->getFragmentInfo())
55 return Fragment->SizeInBits;
56 return getVariable()->getSizeInBits();
57}
58
Reid Klecknerc2752da2016-01-26 22:33:19 +000059int llvm::Intrinsic::lookupLLVMIntrinsicByName(ArrayRef<const char *> NameTable,
60 StringRef Name) {
61 assert(Name.startswith("llvm."));
62
63 // Do successive binary searches of the dotted name components. For
64 // "llvm.gc.experimental.statepoint.p1i8.p1i32", we will find the range of
65 // intrinsics starting with "llvm.gc", then "llvm.gc.experimental", then
66 // "llvm.gc.experimental.statepoint", and then we will stop as the range is
67 // size 1. During the search, we can skip the prefix that we already know is
68 // identical. By using strncmp we consider names with differing suffixes to
69 // be part of the equal range.
70 size_t CmpStart = 0;
71 size_t CmpEnd = 4; // Skip the "llvm" component.
72 const char *const *Low = NameTable.begin();
73 const char *const *High = NameTable.end();
74 const char *const *LastLow = Low;
75 while (CmpEnd < Name.size() && High - Low > 0) {
76 CmpStart = CmpEnd;
77 CmpEnd = Name.find('.', CmpStart + 1);
78 CmpEnd = CmpEnd == StringRef::npos ? Name.size() : CmpEnd;
79 auto Cmp = [CmpStart, CmpEnd](const char *LHS, const char *RHS) {
80 return strncmp(LHS + CmpStart, RHS + CmpStart, CmpEnd - CmpStart) < 0;
81 };
82 LastLow = Low;
83 std::tie(Low, High) = std::equal_range(Low, High, Name.data(), Cmp);
84 }
85 if (High - Low > 0)
86 LastLow = Low;
87
88 if (LastLow == NameTable.end())
89 return -1;
90 StringRef NameFound = *LastLow;
91 if (Name == NameFound ||
92 (Name.startswith(NameFound) && Name[NameFound.size()] == '.'))
93 return LastLow - NameTable.begin();
94 return -1;
95}
Xinliang David Lia754c472016-09-20 19:07:22 +000096
97Value *InstrProfIncrementInst::getStep() const {
98 if (InstrProfIncrementInstStep::classof(this)) {
99 return const_cast<Value *>(getArgOperand(4));
100 }
101 const Module *M = getModule();
102 LLVMContext &Context = M->getContext();
103 return ConstantInt::get(Type::getInt64Ty(Context), 1);
104}
Andrew Kaylora0a11642017-01-26 23:27:59 +0000105
Kevin P. Neal472e5dd2019-07-08 16:18:18 +0000106Optional<ConstrainedFPIntrinsic::RoundingMode>
Andrew Kaylora0a11642017-01-26 23:27:59 +0000107ConstrainedFPIntrinsic::getRoundingMode() const {
Andrew Kaylorf4660012017-05-25 21:31:00 +0000108 unsigned NumOperands = getNumArgOperands();
Wei Dinga131d3f2017-08-24 04:18:24 +0000109 Metadata *MD =
Andrew Kaylorf4660012017-05-25 21:31:00 +0000110 dyn_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
Kevin P. Neal472e5dd2019-07-08 16:18:18 +0000116Optional<ConstrainedFPIntrinsic::RoundingMode>
117ConstrainedFPIntrinsic::StrToRoundingMode(StringRef RoundingArg) {
Andrew Kaylora0a11642017-01-26 23:27:59 +0000118 // For dynamic rounding mode, we use round to nearest but we will set the
119 // 'exact' SDNodeFlag so that the value will not be rounded.
Kevin P. Neal472e5dd2019-07-08 16:18:18 +0000120 return StringSwitch<Optional<RoundingMode>>(RoundingArg)
Andrew Kaylora0a11642017-01-26 23:27:59 +0000121 .Case("round.dynamic", rmDynamic)
122 .Case("round.tonearest", rmToNearest)
123 .Case("round.downward", rmDownward)
124 .Case("round.upward", rmUpward)
125 .Case("round.towardzero", rmTowardZero)
Kevin P. Neal472e5dd2019-07-08 16:18:18 +0000126 .Default(None);
Andrew Kaylora0a11642017-01-26 23:27:59 +0000127}
128
Kevin P. Neal472e5dd2019-07-08 16:18:18 +0000129Optional<StringRef>
130ConstrainedFPIntrinsic::RoundingModeToStr(RoundingMode UseRounding) {
131 Optional<StringRef> RoundingStr = None;
132 switch (UseRounding) {
133 case ConstrainedFPIntrinsic::rmDynamic:
134 RoundingStr = "round.dynamic";
135 break;
136 case ConstrainedFPIntrinsic::rmToNearest:
137 RoundingStr = "round.tonearest";
138 break;
139 case ConstrainedFPIntrinsic::rmDownward:
140 RoundingStr = "round.downward";
141 break;
142 case ConstrainedFPIntrinsic::rmUpward:
143 RoundingStr = "round.upward";
144 break;
145 case ConstrainedFPIntrinsic::rmTowardZero:
146 RoundingStr = "round.tozero";
147 break;
148 }
149 return RoundingStr;
150}
151
152Optional<ConstrainedFPIntrinsic::ExceptionBehavior>
Andrew Kaylora0a11642017-01-26 23:27:59 +0000153ConstrainedFPIntrinsic::getExceptionBehavior() const {
Andrew Kaylorf4660012017-05-25 21:31:00 +0000154 unsigned NumOperands = getNumArgOperands();
Wei Dinga131d3f2017-08-24 04:18:24 +0000155 Metadata *MD =
Andrew Kaylorf4660012017-05-25 21:31:00 +0000156 dyn_cast<MetadataAsValue>(getArgOperand(NumOperands - 1))->getMetadata();
Andrew Kaylora0a11642017-01-26 23:27:59 +0000157 if (!MD || !isa<MDString>(MD))
Kevin P. Neal472e5dd2019-07-08 16:18:18 +0000158 return None;
159 return StrToExceptionBehavior(cast<MDString>(MD)->getString());
160}
161
162Optional<ConstrainedFPIntrinsic::ExceptionBehavior>
163ConstrainedFPIntrinsic::StrToExceptionBehavior(StringRef ExceptionArg) {
164 return StringSwitch<Optional<ExceptionBehavior>>(ExceptionArg)
Andrew Kaylora0a11642017-01-26 23:27:59 +0000165 .Case("fpexcept.ignore", ebIgnore)
166 .Case("fpexcept.maytrap", ebMayTrap)
167 .Case("fpexcept.strict", ebStrict)
Kevin P. Neal472e5dd2019-07-08 16:18:18 +0000168 .Default(None);
169}
170
171Optional<StringRef>
172ConstrainedFPIntrinsic::ExceptionBehaviorToStr(ExceptionBehavior UseExcept) {
173 Optional<StringRef> ExceptStr = None;
174 switch (UseExcept) {
175 case ConstrainedFPIntrinsic::ebStrict:
176 ExceptStr = "fpexcept.strict";
177 break;
178 case ConstrainedFPIntrinsic::ebIgnore:
179 ExceptStr = "fpexcept.ignore";
180 break;
181 case ConstrainedFPIntrinsic::ebMayTrap:
182 ExceptStr = "fpexcept.maytrap";
183 break;
184 }
185 return ExceptStr;
Andrew Kaylora0a11642017-01-26 23:27:59 +0000186}
Andrew Kaylorf4660012017-05-25 21:31:00 +0000187
188bool ConstrainedFPIntrinsic::isUnaryOp() const {
189 switch (getIntrinsicID()) {
Wei Dinga131d3f2017-08-24 04:18:24 +0000190 default:
Andrew Kaylorf4660012017-05-25 21:31:00 +0000191 return false;
Kevin P. Neal59877492019-05-13 13:23:30 +0000192 case Intrinsic::experimental_constrained_fptrunc:
193 case Intrinsic::experimental_constrained_fpext:
Andrew Kaylorf4660012017-05-25 21:31:00 +0000194 case Intrinsic::experimental_constrained_sqrt:
195 case Intrinsic::experimental_constrained_sin:
196 case Intrinsic::experimental_constrained_cos:
197 case Intrinsic::experimental_constrained_exp:
198 case Intrinsic::experimental_constrained_exp2:
199 case Intrinsic::experimental_constrained_log:
200 case Intrinsic::experimental_constrained_log10:
201 case Intrinsic::experimental_constrained_log2:
202 case Intrinsic::experimental_constrained_rint:
203 case Intrinsic::experimental_constrained_nearbyint:
Cameron McInally9757d5d2018-11-05 15:59:49 +0000204 case Intrinsic::experimental_constrained_ceil:
205 case Intrinsic::experimental_constrained_floor:
206 case Intrinsic::experimental_constrained_round:
207 case Intrinsic::experimental_constrained_trunc:
Andrew Kaylorf4660012017-05-25 21:31:00 +0000208 return true;
209 }
210}
Wei Dinga131d3f2017-08-24 04:18:24 +0000211
212bool ConstrainedFPIntrinsic::isTernaryOp() const {
213 switch (getIntrinsicID()) {
214 default:
215 return false;
216 case Intrinsic::experimental_constrained_fma:
217 return true;
218 }
219}
220
Nikita Popov2fb0a822019-05-28 18:08:06 +0000221Instruction::BinaryOps BinaryOpIntrinsic::getBinaryOp() const {
Nikita Popov79dffc62019-04-16 18:55:16 +0000222 switch (getIntrinsicID()) {
223 case Intrinsic::uadd_with_overflow:
224 case Intrinsic::sadd_with_overflow:
Nikita Popov2fb0a822019-05-28 18:08:06 +0000225 case Intrinsic::uadd_sat:
226 case Intrinsic::sadd_sat:
Nikita Popov79dffc62019-04-16 18:55:16 +0000227 return Instruction::Add;
228 case Intrinsic::usub_with_overflow:
229 case Intrinsic::ssub_with_overflow:
Nikita Popov2fb0a822019-05-28 18:08:06 +0000230 case Intrinsic::usub_sat:
231 case Intrinsic::ssub_sat:
Nikita Popov79dffc62019-04-16 18:55:16 +0000232 return Instruction::Sub;
233 case Intrinsic::umul_with_overflow:
234 case Intrinsic::smul_with_overflow:
235 return Instruction::Mul;
236 default:
237 llvm_unreachable("Invalid intrinsic");
238 }
239}
240
Nikita Popov2fb0a822019-05-28 18:08:06 +0000241bool BinaryOpIntrinsic::isSigned() const {
Nikita Popov79dffc62019-04-16 18:55:16 +0000242 switch (getIntrinsicID()) {
243 case Intrinsic::sadd_with_overflow:
244 case Intrinsic::ssub_with_overflow:
245 case Intrinsic::smul_with_overflow:
Nikita Popov2fb0a822019-05-28 18:08:06 +0000246 case Intrinsic::sadd_sat:
247 case Intrinsic::ssub_sat:
Nikita Popov79dffc62019-04-16 18:55:16 +0000248 return true;
249 default:
250 return false;
251 }
252}
253
Nikita Popov2fb0a822019-05-28 18:08:06 +0000254unsigned BinaryOpIntrinsic::getNoWrapKind() const {
Nikita Popov79dffc62019-04-16 18:55:16 +0000255 if (isSigned())
256 return OverflowingBinaryOperator::NoSignedWrap;
257 else
258 return OverflowingBinaryOperator::NoUnsignedWrap;
259}