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.
11 //
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.
16 //
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.
20 //
21 //===----------------------------------------------------------------------===//
22
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;
33
34 //===----------------------------------------------------------------------===//
35 /// DbgVariableIntrinsic - This is the common base class for debug info
36 /// intrinsics for variables.
37 ///
38
getVariableLocation(bool AllowNullOp) const39 Value *DbgVariableIntrinsic::getVariableLocation(bool AllowNullOp) const {
40 Value *Op = getArgOperand(0);
41 if (AllowNullOp && !Op)
42 return nullptr;
43
44 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.
49 assert(!cast<MDNode>(MD)->getNumOperands() && "Expected an empty MDNode");
50 return nullptr;
51 }
52
getFragmentSizeInBits() const53 Optional<uint64_t> DbgVariableIntrinsic::getFragmentSizeInBits() const {
54 if (auto Fragment = getExpression()->getFragmentInfo())
55 return Fragment->SizeInBits;
56 return getVariable()->getSizeInBits();
57 }
58
lookupLLVMIntrinsicByName(ArrayRef<const char * > NameTable,StringRef Name)59 int 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 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;
80 };
81 LastLow = Low;
82 std::tie(Low, High) = std::equal_range(Low, High, Name.data(), Cmp);
83 }
84 if (High - Low > 0)
85 LastLow = Low;
86
87 if (LastLow == NameTable.end())
88 return -1;
89 StringRef NameFound = *LastLow;
90 if (Name == NameFound ||
91 (Name.startswith(NameFound) && Name[NameFound.size()] == '.'))
92 return LastLow - NameTable.begin();
93 return -1;
94 }
95
getStep() const96 Value *InstrProfIncrementInst::getStep() const {
97 if (InstrProfIncrementInstStep::classof(this)) {
98 return const_cast<Value *>(getArgOperand(4));
99 }
100 const Module *M = getModule();
101 LLVMContext &Context = M->getContext();
102 return ConstantInt::get(Type::getInt64Ty(Context), 1);
103 }
104
getRoundingMode() const105 Optional<fp::RoundingMode> ConstrainedFPIntrinsic::getRoundingMode() const {
106 unsigned NumOperands = getNumArgOperands();
107 Metadata *MD =
108 cast<MetadataAsValue>(getArgOperand(NumOperands - 2))->getMetadata();
109 if (!MD || !isa<MDString>(MD))
110 return None;
111 return StrToRoundingMode(cast<MDString>(MD)->getString());
112 }
113
114 Optional<fp::ExceptionBehavior>
getExceptionBehavior() const115 ConstrainedFPIntrinsic::getExceptionBehavior() const {
116 unsigned NumOperands = getNumArgOperands();
117 Metadata *MD =
118 cast<MetadataAsValue>(getArgOperand(NumOperands - 1))->getMetadata();
119 if (!MD || !isa<MDString>(MD))
120 return None;
121 return StrToExceptionBehavior(cast<MDString>(MD)->getString());
122 }
123
124 FCmpInst::Predicate
getPredicate() const125 ConstrainedFPCmpIntrinsic::getPredicate() const {
126 Metadata *MD =
127 cast<MetadataAsValue>(getArgOperand(2))->getMetadata();
128 if (!MD || !isa<MDString>(MD))
129 return FCmpInst::BAD_FCMP_PREDICATE;
130 return StringSwitch<FCmpInst::Predicate>(cast<MDString>(MD)->getString())
131 .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);
146 }
147
isUnaryOp() const148 bool ConstrainedFPIntrinsic::isUnaryOp() const {
149 switch (getIntrinsicID()) {
150 default:
151 return false;
152 #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
153 case Intrinsic::INTRINSIC: \
154 return NARG == 1;
155 #include "llvm/IR/ConstrainedOps.def"
156 }
157 }
158
isTernaryOp() const159 bool ConstrainedFPIntrinsic::isTernaryOp() const {
160 switch (getIntrinsicID()) {
161 default:
162 return false;
163 #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
164 case Intrinsic::INTRINSIC: \
165 return NARG == 3;
166 #include "llvm/IR/ConstrainedOps.def"
167 }
168 }
169
classof(const IntrinsicInst * I)170 bool ConstrainedFPIntrinsic::classof(const IntrinsicInst *I) {
171 switch (I->getIntrinsicID()) {
172 #define INSTRUCTION(NAME, NARGS, ROUND_MODE, INTRINSIC, DAGN) \
173 case Intrinsic::INTRINSIC:
174 #include "llvm/IR/ConstrainedOps.def"
175 return true;
176 default:
177 return false;
178 }
179 }
180
getBinaryOp() const181 Instruction::BinaryOps BinaryOpIntrinsic::getBinaryOp() const {
182 switch (getIntrinsicID()) {
183 case Intrinsic::uadd_with_overflow:
184 case Intrinsic::sadd_with_overflow:
185 case Intrinsic::uadd_sat:
186 case Intrinsic::sadd_sat:
187 return Instruction::Add;
188 case Intrinsic::usub_with_overflow:
189 case Intrinsic::ssub_with_overflow:
190 case Intrinsic::usub_sat:
191 case Intrinsic::ssub_sat:
192 return Instruction::Sub;
193 case Intrinsic::umul_with_overflow:
194 case Intrinsic::smul_with_overflow:
195 return Instruction::Mul;
196 default:
197 llvm_unreachable("Invalid intrinsic");
198 }
199 }
200
isSigned() const201 bool BinaryOpIntrinsic::isSigned() const {
202 switch (getIntrinsicID()) {
203 case Intrinsic::sadd_with_overflow:
204 case Intrinsic::ssub_with_overflow:
205 case Intrinsic::smul_with_overflow:
206 case Intrinsic::sadd_sat:
207 case Intrinsic::ssub_sat:
208 return true;
209 default:
210 return false;
211 }
212 }
213
getNoWrapKind() const214 unsigned BinaryOpIntrinsic::getNoWrapKind() const {
215 if (isSigned())
216 return OverflowingBinaryOperator::NoSignedWrap;
217 else
218 return OverflowingBinaryOperator::NoUnsignedWrap;
219 }
220