[llvm-objcopy] - Reimplement strip-dwo-groups.test to stop using the precompiled...
[llvm-complete.git] / lib / IR / IntrinsicInst.cpp
blob7a042326f67f65a5b9bb524c8f1e6a948d9266f5
1 //===-- InstrinsicInst.cpp - Intrinsic Instruction Wrappers ---------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements methods that make it really easy to deal with intrinsic
10 // functions.
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.
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"
32 using namespace llvm;
34 //===----------------------------------------------------------------------===//
35 /// DbgVariableIntrinsic - This is the common base class for debug info
36 /// intrinsics for variables.
37 ///
39 Value *DbgVariableIntrinsic::getVariableLocation(bool AllowNullOp) const {
40 Value *Op = getArgOperand(0);
41 if (AllowNullOp && !Op)
42 return nullptr;
44 auto *MD = cast<MetadataAsValue>(Op)->getMetadata();
45 if (auto *V = dyn_cast<ValueAsMetadata>(MD))
46 return V->getValue();
48 // When the value goes to null, it gets replaced by an empty MDNode.
49 assert(!cast<MDNode>(MD)->getNumOperands() && "Expected an empty MDNode");
50 return nullptr;
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,
60 StringRef Name) {
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 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;
82 LastLow = Low;
83 std::tie(Low, High) = std::equal_range(Low, High, Name.data(), Cmp);
85 if (High - Low > 0)
86 LastLow = Low;
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;
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();
109 Metadata *MD =
110 dyn_cast<MetadataAsValue>(getArgOperand(NumOperands - 2))->getMetadata();
111 if (!MD || !isa<MDString>(MD))
112 return None;
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)
126 .Default(None);
129 Optional<StringRef>
130 ConstrainedFPIntrinsic::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;
149 return RoundingStr;
152 Optional<ConstrainedFPIntrinsic::ExceptionBehavior>
153 ConstrainedFPIntrinsic::getExceptionBehavior() const {
154 unsigned NumOperands = getNumArgOperands();
155 Metadata *MD =
156 dyn_cast<MetadataAsValue>(getArgOperand(NumOperands - 1))->getMetadata();
157 if (!MD || !isa<MDString>(MD))
158 return None;
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)
168 .Default(None);
171 Optional<StringRef>
172 ConstrainedFPIntrinsic::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;
185 return ExceptStr;
188 bool ConstrainedFPIntrinsic::isUnaryOp() const {
189 switch (getIntrinsicID()) {
190 default:
191 return false;
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:
208 return true;
212 bool ConstrainedFPIntrinsic::isTernaryOp() const {
213 switch (getIntrinsicID()) {
214 default:
215 return false;
216 case Intrinsic::experimental_constrained_fma:
217 return true;
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;
236 default:
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:
248 return true;
249 default:
250 return false;
254 unsigned BinaryOpIntrinsic::getNoWrapKind() const {
255 if (isSigned())
256 return OverflowingBinaryOperator::NoSignedWrap;
257 else
258 return OverflowingBinaryOperator::NoUnsignedWrap;