• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/ADT/StringSwitch.h"
25 #include "llvm/IR/Constants.h"
26 #include "llvm/IR/DebugInfoMetadata.h"
27 #include "llvm/IR/GlobalVariable.h"
28 #include "llvm/IR/Metadata.h"
29 #include "llvm/IR/Module.h"
30 #include "llvm/IR/Operator.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 
getVariableLocation(bool AllowNullOp) const41 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 
getFragmentSizeInBits() const55 Optional<uint64_t> DbgVariableIntrinsic::getFragmentSizeInBits() const {
56   if (auto Fragment = getExpression()->getFragmentInfo())
57     return Fragment->SizeInBits;
58   return getVariable()->getSizeInBits();
59 }
60 
lookupLLVMIntrinsicByName(ArrayRef<const char * > NameTable,StringRef Name)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 
getStep() const98 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 
getRoundingMode() const107 Optional<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>
getExceptionBehavior() const117 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 
getPredicate() const126 FCmpInst::Predicate ConstrainedFPCmpIntrinsic::getPredicate() const {
127   Metadata *MD = 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)                         \
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)                         \
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)                        \
173   case Intrinsic::INTRINSIC:
174 #include "llvm/IR/ConstrainedOps.def"
175     return true;
176   default:
177     return false;
178   }
179 }
180 
getStaticVectorLength() const181 ElementCount VPIntrinsic::getStaticVectorLength() const {
182   auto GetVectorLengthOfType = [](const Type *T) -> ElementCount {
183     auto VT = cast<VectorType>(T);
184     auto ElemCount = VT->getElementCount();
185     return ElemCount;
186   };
187 
188   auto VPMask = getMaskParam();
189   return GetVectorLengthOfType(VPMask->getType());
190 }
191 
getMaskParam() const192 Value *VPIntrinsic::getMaskParam() const {
193   auto maskPos = GetMaskParamPos(getIntrinsicID());
194   if (maskPos)
195     return getArgOperand(maskPos.getValue());
196   return nullptr;
197 }
198 
getVectorLengthParam() const199 Value *VPIntrinsic::getVectorLengthParam() const {
200   auto vlenPos = GetVectorLengthParamPos(getIntrinsicID());
201   if (vlenPos)
202     return getArgOperand(vlenPos.getValue());
203   return nullptr;
204 }
205 
GetMaskParamPos(Intrinsic::ID IntrinsicID)206 Optional<int> VPIntrinsic::GetMaskParamPos(Intrinsic::ID IntrinsicID) {
207   switch (IntrinsicID) {
208   default:
209     return None;
210 
211 #define BEGIN_REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS)                    \
212   case Intrinsic::VPID:                                                        \
213     return MASKPOS;
214 #include "llvm/IR/VPIntrinsics.def"
215   }
216 }
217 
GetVectorLengthParamPos(Intrinsic::ID IntrinsicID)218 Optional<int> VPIntrinsic::GetVectorLengthParamPos(Intrinsic::ID IntrinsicID) {
219   switch (IntrinsicID) {
220   default:
221     return None;
222 
223 #define BEGIN_REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS)                    \
224   case Intrinsic::VPID:                                                        \
225     return VLENPOS;
226 #include "llvm/IR/VPIntrinsics.def"
227   }
228 }
229 
IsVPIntrinsic(Intrinsic::ID ID)230 bool VPIntrinsic::IsVPIntrinsic(Intrinsic::ID ID) {
231   switch (ID) {
232   default:
233     return false;
234 
235 #define BEGIN_REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS)                    \
236   case Intrinsic::VPID:                                                        \
237     break;
238 #include "llvm/IR/VPIntrinsics.def"
239   }
240   return true;
241 }
242 
243 // Equivalent non-predicated opcode
GetFunctionalOpcodeForVP(Intrinsic::ID ID)244 unsigned VPIntrinsic::GetFunctionalOpcodeForVP(Intrinsic::ID ID) {
245   unsigned FunctionalOC = Instruction::Call;
246   switch (ID) {
247   default:
248     break;
249 #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
250 #define HANDLE_VP_TO_OPC(OPC) FunctionalOC = Instruction::OPC;
251 #define END_REGISTER_VP_INTRINSIC(...) break;
252 #include "llvm/IR/VPIntrinsics.def"
253   }
254 
255   return FunctionalOC;
256 }
257 
GetForOpcode(unsigned IROPC)258 Intrinsic::ID VPIntrinsic::GetForOpcode(unsigned IROPC) {
259   switch (IROPC) {
260   default:
261     return Intrinsic::not_intrinsic;
262 
263 #define HANDLE_VP_TO_OPC(OPC) case Instruction::OPC:
264 #define END_REGISTER_VP_INTRINSIC(VPID) return Intrinsic::VPID;
265 #include "llvm/IR/VPIntrinsics.def"
266   }
267 }
268 
canIgnoreVectorLengthParam() const269 bool VPIntrinsic::canIgnoreVectorLengthParam() const {
270   using namespace PatternMatch;
271 
272   ElementCount EC = getStaticVectorLength();
273 
274   // No vlen param - no lanes masked-off by it.
275   auto *VLParam = getVectorLengthParam();
276   if (!VLParam)
277     return true;
278 
279   // Note that the VP intrinsic causes undefined behavior if the Explicit Vector
280   // Length parameter is strictly greater-than the number of vector elements of
281   // the operation. This function returns true when this is detected statically
282   // in the IR.
283 
284   // Check whether "W == vscale * EC.getKnownMinValue()"
285   if (EC.isScalable()) {
286     // Undig the DL
287     auto ParMod = this->getModule();
288     if (!ParMod)
289       return false;
290     const auto &DL = ParMod->getDataLayout();
291 
292     // Compare vscale patterns
293     uint64_t VScaleFactor;
294     if (match(VLParam, m_c_Mul(m_ConstantInt(VScaleFactor), m_VScale(DL))))
295       return VScaleFactor >= EC.getKnownMinValue();
296     return (EC.getKnownMinValue() == 1) && match(VLParam, m_VScale(DL));
297   }
298 
299   // standard SIMD operation
300   auto VLConst = dyn_cast<ConstantInt>(VLParam);
301   if (!VLConst)
302     return false;
303 
304   uint64_t VLNum = VLConst->getZExtValue();
305   if (VLNum >= EC.getKnownMinValue())
306     return true;
307 
308   return false;
309 }
310 
getBinaryOp() const311 Instruction::BinaryOps BinaryOpIntrinsic::getBinaryOp() const {
312   switch (getIntrinsicID()) {
313   case Intrinsic::uadd_with_overflow:
314   case Intrinsic::sadd_with_overflow:
315   case Intrinsic::uadd_sat:
316   case Intrinsic::sadd_sat:
317     return Instruction::Add;
318   case Intrinsic::usub_with_overflow:
319   case Intrinsic::ssub_with_overflow:
320   case Intrinsic::usub_sat:
321   case Intrinsic::ssub_sat:
322     return Instruction::Sub;
323   case Intrinsic::umul_with_overflow:
324   case Intrinsic::smul_with_overflow:
325     return Instruction::Mul;
326   default:
327     llvm_unreachable("Invalid intrinsic");
328   }
329 }
330 
isSigned() const331 bool BinaryOpIntrinsic::isSigned() const {
332   switch (getIntrinsicID()) {
333   case Intrinsic::sadd_with_overflow:
334   case Intrinsic::ssub_with_overflow:
335   case Intrinsic::smul_with_overflow:
336   case Intrinsic::sadd_sat:
337   case Intrinsic::ssub_sat:
338     return true;
339   default:
340     return false;
341   }
342 }
343 
getNoWrapKind() const344 unsigned BinaryOpIntrinsic::getNoWrapKind() const {
345   if (isSigned())
346     return OverflowingBinaryOperator::NoSignedWrap;
347   else
348     return OverflowingBinaryOperator::NoUnsignedWrap;
349 }
350