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/IR/PatternMatch.h"
32 
33 #include "llvm/Support/raw_ostream.h"
34 using namespace llvm;
35 
36 //===----------------------------------------------------------------------===//
37 /// DbgVariableIntrinsic - This is the common base class for debug info
38 /// intrinsics for variables.
39 ///
40 
41 Value *DbgVariableIntrinsic::getVariableLocation(bool AllowNullOp) const {
42   Value *Op = getArgOperand(0);
43   if (AllowNullOp && !Op)
44     return nullptr;
45 
46   auto *MD = cast<MetadataAsValue>(Op)->getMetadata();
47   if (auto *V = dyn_cast<ValueAsMetadata>(MD))
48     return V->getValue();
49 
50   // When the value goes to null, it gets replaced by an empty MDNode.
51   assert(!cast<MDNode>(MD)->getNumOperands() && "Expected an empty MDNode");
52   return nullptr;
53 }
54 
55 Optional<uint64_t> DbgVariableIntrinsic::getFragmentSizeInBits() const {
56   if (auto Fragment = getExpression()->getFragmentInfo())
57     return Fragment->SizeInBits;
58   return getVariable()->getSizeInBits();
59 }
60 
61 int llvm::Intrinsic::lookupLLVMIntrinsicByName(ArrayRef<const char *> NameTable,
62                                                StringRef Name) {
63   assert(Name.startswith("llvm."));
64 
65   // Do successive binary searches of the dotted name components. For
66   // "llvm.gc.experimental.statepoint.p1i8.p1i32", we will find the range of
67   // intrinsics starting with "llvm.gc", then "llvm.gc.experimental", then
68   // "llvm.gc.experimental.statepoint", and then we will stop as the range is
69   // size 1. During the search, we can skip the prefix that we already know is
70   // identical. By using strncmp we consider names with differing suffixes to
71   // be part of the equal range.
72   size_t CmpEnd = 4; // Skip the "llvm" component.
73   const char *const *Low = NameTable.begin();
74   const char *const *High = NameTable.end();
75   const char *const *LastLow = Low;
76   while (CmpEnd < Name.size() && High - Low > 0) {
77     size_t CmpStart = CmpEnd;
78     CmpEnd = Name.find('.', CmpStart + 1);
79     CmpEnd = CmpEnd == StringRef::npos ? Name.size() : CmpEnd;
80     auto Cmp = [CmpStart, CmpEnd](const char *LHS, const char *RHS) {
81       return strncmp(LHS + CmpStart, RHS + CmpStart, CmpEnd - CmpStart) < 0;
82     };
83     LastLow = Low;
84     std::tie(Low, High) = std::equal_range(Low, High, Name.data(), Cmp);
85   }
86   if (High - Low > 0)
87     LastLow = Low;
88 
89   if (LastLow == NameTable.end())
90     return -1;
91   StringRef NameFound = *LastLow;
92   if (Name == NameFound ||
93       (Name.startswith(NameFound) && Name[NameFound.size()] == '.'))
94     return LastLow - NameTable.begin();
95   return -1;
96 }
97 
98 Value *InstrProfIncrementInst::getStep() const {
99   if (InstrProfIncrementInstStep::classof(this)) {
100     return const_cast<Value *>(getArgOperand(4));
101   }
102   const Module *M = getModule();
103   LLVMContext &Context = M->getContext();
104   return ConstantInt::get(Type::getInt64Ty(Context), 1);
105 }
106 
107 Optional<fp::RoundingMode> ConstrainedFPIntrinsic::getRoundingMode() const {
108   unsigned NumOperands = getNumArgOperands();
109   Metadata *MD =
110       cast<MetadataAsValue>(getArgOperand(NumOperands - 2))->getMetadata();
111   if (!MD || !isa<MDString>(MD))
112     return None;
113   return StrToRoundingMode(cast<MDString>(MD)->getString());
114 }
115 
116 Optional<fp::ExceptionBehavior>
117 ConstrainedFPIntrinsic::getExceptionBehavior() const {
118   unsigned NumOperands = getNumArgOperands();
119   Metadata *MD =
120       cast<MetadataAsValue>(getArgOperand(NumOperands - 1))->getMetadata();
121   if (!MD || !isa<MDString>(MD))
122     return None;
123   return StrToExceptionBehavior(cast<MDString>(MD)->getString());
124 }
125 
126 FCmpInst::Predicate
127 ConstrainedFPCmpIntrinsic::getPredicate() const {
128   Metadata *MD =
129       cast<MetadataAsValue>(getArgOperand(2))->getMetadata();
130   if (!MD || !isa<MDString>(MD))
131     return FCmpInst::BAD_FCMP_PREDICATE;
132   return StringSwitch<FCmpInst::Predicate>(cast<MDString>(MD)->getString())
133            .Case("oeq", FCmpInst::FCMP_OEQ)
134            .Case("ogt", FCmpInst::FCMP_OGT)
135            .Case("oge", FCmpInst::FCMP_OGE)
136            .Case("olt", FCmpInst::FCMP_OLT)
137            .Case("ole", FCmpInst::FCMP_OLE)
138            .Case("one", FCmpInst::FCMP_ONE)
139            .Case("ord", FCmpInst::FCMP_ORD)
140            .Case("uno", FCmpInst::FCMP_UNO)
141            .Case("ueq", FCmpInst::FCMP_UEQ)
142            .Case("ugt", FCmpInst::FCMP_UGT)
143            .Case("uge", FCmpInst::FCMP_UGE)
144            .Case("ult", FCmpInst::FCMP_ULT)
145            .Case("ule", FCmpInst::FCMP_ULE)
146            .Case("une", FCmpInst::FCMP_UNE)
147            .Default(FCmpInst::BAD_FCMP_PREDICATE);
148 }
149 
150 bool ConstrainedFPIntrinsic::isUnaryOp() const {
151   switch (getIntrinsicID()) {
152     default:
153       return false;
154 #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC)                         \
155     case Intrinsic::INTRINSIC:                                                 \
156       return NARG == 1;
157 #include "llvm/IR/ConstrainedOps.def"
158   }
159 }
160 
161 bool ConstrainedFPIntrinsic::isTernaryOp() const {
162   switch (getIntrinsicID()) {
163     default:
164       return false;
165 #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC)                         \
166     case Intrinsic::INTRINSIC:                                                 \
167       return NARG == 3;
168 #include "llvm/IR/ConstrainedOps.def"
169   }
170 }
171 
172 bool ConstrainedFPIntrinsic::classof(const IntrinsicInst *I) {
173   switch (I->getIntrinsicID()) {
174 #define INSTRUCTION(NAME, NARGS, ROUND_MODE, INTRINSIC)                        \
175   case Intrinsic::INTRINSIC:
176 #include "llvm/IR/ConstrainedOps.def"
177     return true;
178   default:
179     return false;
180   }
181 }
182 
183 ElementCount VPIntrinsic::getStaticVectorLength() const {
184   auto GetVectorLengthOfType = [](const Type *T) -> ElementCount {
185     auto VT = cast<VectorType>(T);
186     auto ElemCount = VT->getElementCount();
187     return ElemCount;
188   };
189 
190   auto VPMask = getMaskParam();
191   return GetVectorLengthOfType(VPMask->getType());
192 }
193 
194 Value *VPIntrinsic::getMaskParam() const {
195   auto maskPos = GetMaskParamPos(getIntrinsicID());
196   if (maskPos)
197     return getArgOperand(maskPos.getValue());
198   return nullptr;
199 }
200 
201 Value *VPIntrinsic::getVectorLengthParam() const {
202   auto vlenPos = GetVectorLengthParamPos(getIntrinsicID());
203   if (vlenPos)
204     return getArgOperand(vlenPos.getValue());
205   return nullptr;
206 }
207 
208 Optional<int> VPIntrinsic::GetMaskParamPos(Intrinsic::ID IntrinsicID) {
209   switch (IntrinsicID) {
210   default:
211     return None;
212 
213 #define REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS)                          \
214   case Intrinsic::VPID:                                                        \
215     return MASKPOS;
216 #include "llvm/IR/VPIntrinsics.def"
217   }
218 }
219 
220 Optional<int> VPIntrinsic::GetVectorLengthParamPos(Intrinsic::ID IntrinsicID) {
221   switch (IntrinsicID) {
222   default:
223     return None;
224 
225 #define REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS)                          \
226   case Intrinsic::VPID:                                                        \
227     return VLENPOS;
228 #include "llvm/IR/VPIntrinsics.def"
229   }
230 }
231 
232 bool VPIntrinsic::IsVPIntrinsic(Intrinsic::ID ID) {
233   switch (ID) {
234   default:
235     return false;
236 
237 #define REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS)                          \
238   case Intrinsic::VPID:                                                        \
239     break;
240 #include "llvm/IR/VPIntrinsics.def"
241   }
242   return true;
243 }
244 
245 // Equivalent non-predicated opcode
246 unsigned VPIntrinsic::GetFunctionalOpcodeForVP(Intrinsic::ID ID) {
247   switch (ID) {
248   default:
249     return Instruction::Call;
250 
251 #define HANDLE_VP_TO_OC(VPID, OC)                                              \
252   case Intrinsic::VPID:                                                        \
253     return Instruction::OC;
254 #include "llvm/IR/VPIntrinsics.def"
255   }
256 }
257 
258 Intrinsic::ID VPIntrinsic::GetForOpcode(unsigned OC) {
259   switch (OC) {
260   default:
261     return Intrinsic::not_intrinsic;
262 
263 #define HANDLE_VP_TO_OC(VPID, OC)                                              \
264   case Instruction::OC:                                                        \
265     return Intrinsic::VPID;
266 #include "llvm/IR/VPIntrinsics.def"
267   }
268 }
269 
270 bool VPIntrinsic::canIgnoreVectorLengthParam() const {
271   using namespace PatternMatch;
272 
273   ElementCount EC = getStaticVectorLength();
274 
275   // No vlen param - no lanes masked-off by it.
276   auto *VLParam = getVectorLengthParam();
277   if (!VLParam)
278     return true;
279 
280   // Note that the VP intrinsic causes undefined behavior if the Explicit Vector
281   // Length parameter is strictly greater-than the number of vector elements of
282   // the operation. This function returns true when this is detected statically
283   // in the IR.
284 
285   // Check whether "W == vscale * EC.Min"
286   if (EC.Scalable) {
287     // Undig the DL
288     auto ParMod = this->getModule();
289     if (!ParMod)
290       return false;
291     const auto &DL = ParMod->getDataLayout();
292 
293     // Compare vscale patterns
294     uint64_t ParamFactor;
295     if (EC.Min > 1 &&
296         match(VLParam, m_c_BinOp(m_ConstantInt(ParamFactor), m_VScale(DL)))) {
297       return ParamFactor >= EC.Min;
298     }
299     if (match(VLParam, m_VScale(DL))) {
300       return ParamFactor;
301     }
302     return false;
303   }
304 
305   // standard SIMD operation
306   auto VLConst = dyn_cast<ConstantInt>(VLParam);
307   if (!VLConst)
308     return false;
309 
310   uint64_t VLNum = VLConst->getZExtValue();
311   if (VLNum >= EC.Min)
312     return true;
313 
314   return false;
315 }
316 
317 Instruction::BinaryOps BinaryOpIntrinsic::getBinaryOp() const {
318   switch (getIntrinsicID()) {
319     case Intrinsic::uadd_with_overflow:
320     case Intrinsic::sadd_with_overflow:
321     case Intrinsic::uadd_sat:
322     case Intrinsic::sadd_sat:
323       return Instruction::Add;
324     case Intrinsic::usub_with_overflow:
325     case Intrinsic::ssub_with_overflow:
326     case Intrinsic::usub_sat:
327     case Intrinsic::ssub_sat:
328       return Instruction::Sub;
329     case Intrinsic::umul_with_overflow:
330     case Intrinsic::smul_with_overflow:
331       return Instruction::Mul;
332     default:
333       llvm_unreachable("Invalid intrinsic");
334   }
335 }
336 
337 bool BinaryOpIntrinsic::isSigned() const {
338   switch (getIntrinsicID()) {
339     case Intrinsic::sadd_with_overflow:
340     case Intrinsic::ssub_with_overflow:
341     case Intrinsic::smul_with_overflow:
342     case Intrinsic::sadd_sat:
343     case Intrinsic::ssub_sat:
344       return true;
345     default:
346       return false;
347   }
348 }
349 
350 unsigned BinaryOpIntrinsic::getNoWrapKind() const {
351   if (isSigned())
352     return OverflowingBinaryOperator::NoSignedWrap;
353   else
354     return OverflowingBinaryOperator::NoUnsignedWrap;
355 }
356