1 //===-- InstrinsicInst.cpp - Intrinsic Instruction Wrappers ---------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements methods that make it really easy to deal with intrinsic
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
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.
21 //===----------------------------------------------------------------------===//
23 #include "llvm/IR/IntrinsicInst.h"
24 #include "llvm/IR/Operator.h"
25 #include "llvm/ADT/StringSwitch.h"
26 #include "llvm/IR/Constants.h"
27 #include "llvm/IR/DebugInfoMetadata.h"
28 #include "llvm/IR/GlobalVariable.h"
29 #include "llvm/IR/Metadata.h"
30 #include "llvm/IR/Module.h"
31 #include "llvm/Support/raw_ostream.h"
34 //===----------------------------------------------------------------------===//
35 /// DbgVariableIntrinsic - This is the common base class for debug info
36 /// intrinsics for variables.
39 Value
*DbgVariableIntrinsic::getVariableLocation(bool AllowNullOp
) const {
40 Value
*Op
= getArgOperand(0);
41 if (AllowNullOp
&& !Op
)
44 auto *MD
= cast
<MetadataAsValue
>(Op
)->getMetadata();
45 if (auto *V
= dyn_cast
<ValueAsMetadata
>(MD
))
48 // When the value goes to null, it gets replaced by an empty MDNode.
49 assert(!cast
<MDNode
>(MD
)->getNumOperands() && "Expected an empty MDNode");
53 Optional
<uint64_t> DbgVariableIntrinsic::getFragmentSizeInBits() const {
54 if (auto Fragment
= getExpression()->getFragmentInfo())
55 return Fragment
->SizeInBits
;
56 return getVariable()->getSizeInBits();
59 int llvm::Intrinsic::lookupLLVMIntrinsicByName(ArrayRef
<const char *> NameTable
,
61 assert(Name
.startswith("llvm."));
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.
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) {
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;
83 std::tie(Low
, High
) = std::equal_range(Low
, High
, Name
.data(), Cmp
);
88 if (LastLow
== NameTable
.end())
90 StringRef NameFound
= *LastLow
;
91 if (Name
== NameFound
||
92 (Name
.startswith(NameFound
) && Name
[NameFound
.size()] == '.'))
93 return LastLow
- NameTable
.begin();
97 Value
*InstrProfIncrementInst::getStep() const {
98 if (InstrProfIncrementInstStep::classof(this)) {
99 return const_cast<Value
*>(getArgOperand(4));
101 const Module
*M
= getModule();
102 LLVMContext
&Context
= M
->getContext();
103 return ConstantInt::get(Type::getInt64Ty(Context
), 1);
106 Optional
<ConstrainedFPIntrinsic::RoundingMode
>
107 ConstrainedFPIntrinsic::getRoundingMode() const {
108 unsigned NumOperands
= getNumArgOperands();
110 dyn_cast
<MetadataAsValue
>(getArgOperand(NumOperands
- 2))->getMetadata();
111 if (!MD
|| !isa
<MDString
>(MD
))
113 return StrToRoundingMode(cast
<MDString
>(MD
)->getString());
116 Optional
<ConstrainedFPIntrinsic::RoundingMode
>
117 ConstrainedFPIntrinsic::StrToRoundingMode(StringRef RoundingArg
) {
118 // 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.
120 return StringSwitch
<Optional
<RoundingMode
>>(RoundingArg
)
121 .Case("round.dynamic", rmDynamic
)
122 .Case("round.tonearest", rmToNearest
)
123 .Case("round.downward", rmDownward
)
124 .Case("round.upward", rmUpward
)
125 .Case("round.towardzero", rmTowardZero
)
130 ConstrainedFPIntrinsic::RoundingModeToStr(RoundingMode UseRounding
) {
131 Optional
<StringRef
> RoundingStr
= None
;
132 switch (UseRounding
) {
133 case ConstrainedFPIntrinsic::rmDynamic
:
134 RoundingStr
= "round.dynamic";
136 case ConstrainedFPIntrinsic::rmToNearest
:
137 RoundingStr
= "round.tonearest";
139 case ConstrainedFPIntrinsic::rmDownward
:
140 RoundingStr
= "round.downward";
142 case ConstrainedFPIntrinsic::rmUpward
:
143 RoundingStr
= "round.upward";
145 case ConstrainedFPIntrinsic::rmTowardZero
:
146 RoundingStr
= "round.tozero";
152 Optional
<ConstrainedFPIntrinsic::ExceptionBehavior
>
153 ConstrainedFPIntrinsic::getExceptionBehavior() const {
154 unsigned NumOperands
= getNumArgOperands();
156 dyn_cast
<MetadataAsValue
>(getArgOperand(NumOperands
- 1))->getMetadata();
157 if (!MD
|| !isa
<MDString
>(MD
))
159 return StrToExceptionBehavior(cast
<MDString
>(MD
)->getString());
162 Optional
<ConstrainedFPIntrinsic::ExceptionBehavior
>
163 ConstrainedFPIntrinsic::StrToExceptionBehavior(StringRef ExceptionArg
) {
164 return StringSwitch
<Optional
<ExceptionBehavior
>>(ExceptionArg
)
165 .Case("fpexcept.ignore", ebIgnore
)
166 .Case("fpexcept.maytrap", ebMayTrap
)
167 .Case("fpexcept.strict", ebStrict
)
172 ConstrainedFPIntrinsic::ExceptionBehaviorToStr(ExceptionBehavior UseExcept
) {
173 Optional
<StringRef
> ExceptStr
= None
;
175 case ConstrainedFPIntrinsic::ebStrict
:
176 ExceptStr
= "fpexcept.strict";
178 case ConstrainedFPIntrinsic::ebIgnore
:
179 ExceptStr
= "fpexcept.ignore";
181 case ConstrainedFPIntrinsic::ebMayTrap
:
182 ExceptStr
= "fpexcept.maytrap";
188 bool ConstrainedFPIntrinsic::isUnaryOp() const {
189 switch (getIntrinsicID()) {
192 case Intrinsic::experimental_constrained_fptrunc
:
193 case Intrinsic::experimental_constrained_fpext
:
194 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
:
204 case Intrinsic::experimental_constrained_ceil
:
205 case Intrinsic::experimental_constrained_floor
:
206 case Intrinsic::experimental_constrained_round
:
207 case Intrinsic::experimental_constrained_trunc
:
212 bool ConstrainedFPIntrinsic::isTernaryOp() const {
213 switch (getIntrinsicID()) {
216 case Intrinsic::experimental_constrained_fma
:
221 Instruction::BinaryOps
BinaryOpIntrinsic::getBinaryOp() const {
222 switch (getIntrinsicID()) {
223 case Intrinsic::uadd_with_overflow
:
224 case Intrinsic::sadd_with_overflow
:
225 case Intrinsic::uadd_sat
:
226 case Intrinsic::sadd_sat
:
227 return Instruction::Add
;
228 case Intrinsic::usub_with_overflow
:
229 case Intrinsic::ssub_with_overflow
:
230 case Intrinsic::usub_sat
:
231 case Intrinsic::ssub_sat
:
232 return Instruction::Sub
;
233 case Intrinsic::umul_with_overflow
:
234 case Intrinsic::smul_with_overflow
:
235 return Instruction::Mul
;
237 llvm_unreachable("Invalid intrinsic");
241 bool BinaryOpIntrinsic::isSigned() const {
242 switch (getIntrinsicID()) {
243 case Intrinsic::sadd_with_overflow
:
244 case Intrinsic::ssub_with_overflow
:
245 case Intrinsic::smul_with_overflow
:
246 case Intrinsic::sadd_sat
:
247 case Intrinsic::ssub_sat
:
254 unsigned BinaryOpIntrinsic::getNoWrapKind() const {
256 return OverflowingBinaryOperator::NoSignedWrap
;
258 return OverflowingBinaryOperator::NoUnsignedWrap
;