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.
70 size_t CmpEnd
= 4; // Skip the "llvm" component.
71 const char *const *Low
= NameTable
.begin();
72 const char *const *High
= NameTable
.end();
73 const char *const *LastLow
= Low
;
74 while (CmpEnd
< Name
.size() && High
- Low
> 0) {
75 size_t CmpStart
= CmpEnd
;
76 CmpEnd
= Name
.find('.', CmpStart
+ 1);
77 CmpEnd
= CmpEnd
== StringRef::npos
? Name
.size() : CmpEnd
;
78 auto Cmp
= [CmpStart
, CmpEnd
](const char *LHS
, const char *RHS
) {
79 return strncmp(LHS
+ CmpStart
, RHS
+ CmpStart
, CmpEnd
- CmpStart
) < 0;
82 std::tie(Low
, High
) = std::equal_range(Low
, High
, Name
.data(), Cmp
);
87 if (LastLow
== NameTable
.end())
89 StringRef NameFound
= *LastLow
;
90 if (Name
== NameFound
||
91 (Name
.startswith(NameFound
) && Name
[NameFound
.size()] == '.'))
92 return LastLow
- NameTable
.begin();
96 Value
*InstrProfIncrementInst::getStep() const {
97 if (InstrProfIncrementInstStep::classof(this)) {
98 return const_cast<Value
*>(getArgOperand(4));
100 const Module
*M
= getModule();
101 LLVMContext
&Context
= M
->getContext();
102 return ConstantInt::get(Type::getInt64Ty(Context
), 1);
105 Optional
<ConstrainedFPIntrinsic::RoundingMode
>
106 ConstrainedFPIntrinsic::getRoundingMode() const {
107 unsigned NumOperands
= getNumArgOperands();
109 cast
<MetadataAsValue
>(getArgOperand(NumOperands
- 2))->getMetadata();
110 if (!MD
|| !isa
<MDString
>(MD
))
112 return StrToRoundingMode(cast
<MDString
>(MD
)->getString());
115 Optional
<ConstrainedFPIntrinsic::RoundingMode
>
116 ConstrainedFPIntrinsic::StrToRoundingMode(StringRef RoundingArg
) {
117 // For dynamic rounding mode, we use round to nearest but we will set the
118 // 'exact' SDNodeFlag so that the value will not be rounded.
119 return StringSwitch
<Optional
<RoundingMode
>>(RoundingArg
)
120 .Case("round.dynamic", rmDynamic
)
121 .Case("round.tonearest", rmToNearest
)
122 .Case("round.downward", rmDownward
)
123 .Case("round.upward", rmUpward
)
124 .Case("round.towardzero", rmTowardZero
)
129 ConstrainedFPIntrinsic::RoundingModeToStr(RoundingMode UseRounding
) {
130 Optional
<StringRef
> RoundingStr
= None
;
131 switch (UseRounding
) {
132 case ConstrainedFPIntrinsic::rmDynamic
:
133 RoundingStr
= "round.dynamic";
135 case ConstrainedFPIntrinsic::rmToNearest
:
136 RoundingStr
= "round.tonearest";
138 case ConstrainedFPIntrinsic::rmDownward
:
139 RoundingStr
= "round.downward";
141 case ConstrainedFPIntrinsic::rmUpward
:
142 RoundingStr
= "round.upward";
144 case ConstrainedFPIntrinsic::rmTowardZero
:
145 RoundingStr
= "round.towardzero";
151 Optional
<ConstrainedFPIntrinsic::ExceptionBehavior
>
152 ConstrainedFPIntrinsic::getExceptionBehavior() const {
153 unsigned NumOperands
= getNumArgOperands();
155 cast
<MetadataAsValue
>(getArgOperand(NumOperands
- 1))->getMetadata();
156 if (!MD
|| !isa
<MDString
>(MD
))
158 return StrToExceptionBehavior(cast
<MDString
>(MD
)->getString());
161 Optional
<ConstrainedFPIntrinsic::ExceptionBehavior
>
162 ConstrainedFPIntrinsic::StrToExceptionBehavior(StringRef ExceptionArg
) {
163 return StringSwitch
<Optional
<ExceptionBehavior
>>(ExceptionArg
)
164 .Case("fpexcept.ignore", ebIgnore
)
165 .Case("fpexcept.maytrap", ebMayTrap
)
166 .Case("fpexcept.strict", ebStrict
)
171 ConstrainedFPIntrinsic::ExceptionBehaviorToStr(ExceptionBehavior UseExcept
) {
172 Optional
<StringRef
> ExceptStr
= None
;
174 case ConstrainedFPIntrinsic::ebStrict
:
175 ExceptStr
= "fpexcept.strict";
177 case ConstrainedFPIntrinsic::ebIgnore
:
178 ExceptStr
= "fpexcept.ignore";
180 case ConstrainedFPIntrinsic::ebMayTrap
:
181 ExceptStr
= "fpexcept.maytrap";
187 bool ConstrainedFPIntrinsic::isUnaryOp() const {
188 switch (getIntrinsicID()) {
191 case Intrinsic::experimental_constrained_fptosi
:
192 case Intrinsic::experimental_constrained_fptoui
:
193 case Intrinsic::experimental_constrained_fptrunc
:
194 case Intrinsic::experimental_constrained_fpext
:
195 case Intrinsic::experimental_constrained_sqrt
:
196 case Intrinsic::experimental_constrained_sin
:
197 case Intrinsic::experimental_constrained_cos
:
198 case Intrinsic::experimental_constrained_exp
:
199 case Intrinsic::experimental_constrained_exp2
:
200 case Intrinsic::experimental_constrained_log
:
201 case Intrinsic::experimental_constrained_log10
:
202 case Intrinsic::experimental_constrained_log2
:
203 case Intrinsic::experimental_constrained_lrint
:
204 case Intrinsic::experimental_constrained_llrint
:
205 case Intrinsic::experimental_constrained_rint
:
206 case Intrinsic::experimental_constrained_nearbyint
:
207 case Intrinsic::experimental_constrained_ceil
:
208 case Intrinsic::experimental_constrained_floor
:
209 case Intrinsic::experimental_constrained_lround
:
210 case Intrinsic::experimental_constrained_llround
:
211 case Intrinsic::experimental_constrained_round
:
212 case Intrinsic::experimental_constrained_trunc
:
217 bool ConstrainedFPIntrinsic::isTernaryOp() const {
218 switch (getIntrinsicID()) {
221 case Intrinsic::experimental_constrained_fma
:
226 Instruction::BinaryOps
BinaryOpIntrinsic::getBinaryOp() const {
227 switch (getIntrinsicID()) {
228 case Intrinsic::uadd_with_overflow
:
229 case Intrinsic::sadd_with_overflow
:
230 case Intrinsic::uadd_sat
:
231 case Intrinsic::sadd_sat
:
232 return Instruction::Add
;
233 case Intrinsic::usub_with_overflow
:
234 case Intrinsic::ssub_with_overflow
:
235 case Intrinsic::usub_sat
:
236 case Intrinsic::ssub_sat
:
237 return Instruction::Sub
;
238 case Intrinsic::umul_with_overflow
:
239 case Intrinsic::smul_with_overflow
:
240 return Instruction::Mul
;
242 llvm_unreachable("Invalid intrinsic");
246 bool BinaryOpIntrinsic::isSigned() const {
247 switch (getIntrinsicID()) {
248 case Intrinsic::sadd_with_overflow
:
249 case Intrinsic::ssub_with_overflow
:
250 case Intrinsic::smul_with_overflow
:
251 case Intrinsic::sadd_sat
:
252 case Intrinsic::ssub_sat
:
259 unsigned BinaryOpIntrinsic::getNoWrapKind() const {
261 return OverflowingBinaryOperator::NoSignedWrap
;
263 return OverflowingBinaryOperator::NoUnsignedWrap
;