xref: /llvm-project/llvm/lib/IR/IntrinsicInst.cpp (revision 8820de68ddf02fe3c73def49ec32bbeca54c2754)
1 //===-- IntrinsicInst.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/Metadata.h"
28 #include "llvm/IR/Module.h"
29 #include "llvm/IR/Operator.h"
30 #include "llvm/IR/PatternMatch.h"
31 #include "llvm/IR/Statepoint.h"
32 #include <optional>
33 
34 using namespace llvm;
35 
36 bool IntrinsicInst::mayLowerToFunctionCall(Intrinsic::ID IID) {
37   switch (IID) {
38   case Intrinsic::objc_autorelease:
39   case Intrinsic::objc_autoreleasePoolPop:
40   case Intrinsic::objc_autoreleasePoolPush:
41   case Intrinsic::objc_autoreleaseReturnValue:
42   case Intrinsic::objc_copyWeak:
43   case Intrinsic::objc_destroyWeak:
44   case Intrinsic::objc_initWeak:
45   case Intrinsic::objc_loadWeak:
46   case Intrinsic::objc_loadWeakRetained:
47   case Intrinsic::objc_moveWeak:
48   case Intrinsic::objc_release:
49   case Intrinsic::objc_retain:
50   case Intrinsic::objc_retainAutorelease:
51   case Intrinsic::objc_retainAutoreleaseReturnValue:
52   case Intrinsic::objc_retainAutoreleasedReturnValue:
53   case Intrinsic::objc_retainBlock:
54   case Intrinsic::objc_storeStrong:
55   case Intrinsic::objc_storeWeak:
56   case Intrinsic::objc_unsafeClaimAutoreleasedReturnValue:
57   case Intrinsic::objc_retainedObject:
58   case Intrinsic::objc_unretainedObject:
59   case Intrinsic::objc_unretainedPointer:
60   case Intrinsic::objc_retain_autorelease:
61   case Intrinsic::objc_sync_enter:
62   case Intrinsic::objc_sync_exit:
63     return true;
64   default:
65     return false;
66   }
67 }
68 
69 //===----------------------------------------------------------------------===//
70 /// DbgVariableIntrinsic - This is the common base class for debug info
71 /// intrinsics for variables.
72 ///
73 
74 iterator_range<location_op_iterator> RawLocationWrapper::location_ops() const {
75   Metadata *MD = getRawLocation();
76   assert(MD && "First operand of DbgVariableIntrinsic should be non-null.");
77   // If operand is ValueAsMetadata, return a range over just that operand.
78   if (auto *VAM = dyn_cast<ValueAsMetadata>(MD)) {
79     return {location_op_iterator(VAM), location_op_iterator(VAM + 1)};
80   }
81   // If operand is DIArgList, return a range over its args.
82   if (auto *AL = dyn_cast<DIArgList>(MD))
83     return {location_op_iterator(AL->args_begin()),
84             location_op_iterator(AL->args_end())};
85   // Operand must be an empty metadata tuple, so return empty iterator.
86   return {location_op_iterator(static_cast<ValueAsMetadata *>(nullptr)),
87           location_op_iterator(static_cast<ValueAsMetadata *>(nullptr))};
88 }
89 
90 iterator_range<location_op_iterator>
91 DbgVariableIntrinsic::location_ops() const {
92   return getWrappedLocation().location_ops();
93 }
94 
95 Value *DbgVariableIntrinsic::getVariableLocationOp(unsigned OpIdx) const {
96   return getWrappedLocation().getVariableLocationOp(OpIdx);
97 }
98 
99 Value *RawLocationWrapper::getVariableLocationOp(unsigned OpIdx) const {
100   Metadata *MD = getRawLocation();
101   assert(MD && "First operand of DbgVariableIntrinsic should be non-null.");
102   if (auto *AL = dyn_cast<DIArgList>(MD))
103     return AL->getArgs()[OpIdx]->getValue();
104   if (isa<MDNode>(MD))
105     return nullptr;
106   assert(
107       isa<ValueAsMetadata>(MD) &&
108       "Attempted to get location operand from DbgVariableIntrinsic with none.");
109   auto *V = cast<ValueAsMetadata>(MD);
110   assert(OpIdx == 0 && "Operand Index must be 0 for a debug intrinsic with a "
111                        "single location operand.");
112   return V->getValue();
113 }
114 
115 static ValueAsMetadata *getAsMetadata(Value *V) {
116   return isa<MetadataAsValue>(V) ? dyn_cast<ValueAsMetadata>(
117                                        cast<MetadataAsValue>(V)->getMetadata())
118                                  : ValueAsMetadata::get(V);
119 }
120 
121 void DbgVariableIntrinsic::replaceVariableLocationOp(Value *OldValue,
122                                                      Value *NewValue,
123                                                      bool AllowEmpty) {
124   // If OldValue is used as the address part of a dbg.assign intrinsic replace
125   // it with NewValue and return true.
126   auto ReplaceDbgAssignAddress = [this, OldValue, NewValue]() -> bool {
127     auto *DAI = dyn_cast<DbgAssignIntrinsic>(this);
128     if (!DAI || OldValue != DAI->getAddress())
129       return false;
130     DAI->setAddress(NewValue);
131     return true;
132   };
133   bool DbgAssignAddrReplaced = ReplaceDbgAssignAddress();
134   (void)DbgAssignAddrReplaced;
135 
136   assert(NewValue && "Values must be non-null");
137   auto Locations = location_ops();
138   auto OldIt = find(Locations, OldValue);
139   if (OldIt == Locations.end()) {
140     if (AllowEmpty || DbgAssignAddrReplaced)
141       return;
142     assert(DbgAssignAddrReplaced &&
143            "OldValue must be dbg.assign addr if unused in DIArgList");
144     return;
145   }
146 
147   assert(OldIt != Locations.end() && "OldValue must be a current location");
148   if (!hasArgList()) {
149     Value *NewOperand = isa<MetadataAsValue>(NewValue)
150                             ? NewValue
151                             : MetadataAsValue::get(
152                                   getContext(), ValueAsMetadata::get(NewValue));
153     return setArgOperand(0, NewOperand);
154   }
155   SmallVector<ValueAsMetadata *, 4> MDs;
156   ValueAsMetadata *NewOperand = getAsMetadata(NewValue);
157   for (auto *VMD : Locations)
158     MDs.push_back(VMD == *OldIt ? NewOperand : getAsMetadata(VMD));
159   setArgOperand(
160       0, MetadataAsValue::get(getContext(), DIArgList::get(getContext(), MDs)));
161 }
162 void DbgVariableIntrinsic::replaceVariableLocationOp(unsigned OpIdx,
163                                                      Value *NewValue) {
164   assert(OpIdx < getNumVariableLocationOps() && "Invalid Operand Index");
165   if (!hasArgList()) {
166     Value *NewOperand = isa<MetadataAsValue>(NewValue)
167                             ? NewValue
168                             : MetadataAsValue::get(
169                                   getContext(), ValueAsMetadata::get(NewValue));
170     return setArgOperand(0, NewOperand);
171   }
172   SmallVector<ValueAsMetadata *, 4> MDs;
173   ValueAsMetadata *NewOperand = getAsMetadata(NewValue);
174   for (unsigned Idx = 0; Idx < getNumVariableLocationOps(); ++Idx)
175     MDs.push_back(Idx == OpIdx ? NewOperand
176                                : getAsMetadata(getVariableLocationOp(Idx)));
177   setArgOperand(
178       0, MetadataAsValue::get(getContext(), DIArgList::get(getContext(), MDs)));
179 }
180 
181 void DbgVariableIntrinsic::addVariableLocationOps(ArrayRef<Value *> NewValues,
182                                                   DIExpression *NewExpr) {
183   assert(NewExpr->hasAllLocationOps(getNumVariableLocationOps() +
184                                     NewValues.size()) &&
185          "NewExpr for debug variable intrinsic does not reference every "
186          "location operand.");
187   assert(!is_contained(NewValues, nullptr) && "New values must be non-null");
188   setArgOperand(2, MetadataAsValue::get(getContext(), NewExpr));
189   SmallVector<ValueAsMetadata *, 4> MDs;
190   for (auto *VMD : location_ops())
191     MDs.push_back(getAsMetadata(VMD));
192   for (auto *VMD : NewValues)
193     MDs.push_back(getAsMetadata(VMD));
194   setArgOperand(
195       0, MetadataAsValue::get(getContext(), DIArgList::get(getContext(), MDs)));
196 }
197 
198 std::optional<uint64_t> DbgVariableIntrinsic::getFragmentSizeInBits() const {
199   if (auto Fragment = getExpression()->getFragmentInfo())
200     return Fragment->SizeInBits;
201   return getVariable()->getSizeInBits();
202 }
203 
204 Value *DbgAssignIntrinsic::getAddress() const {
205   auto *MD = getRawAddress();
206   if (auto *V = dyn_cast<ValueAsMetadata>(MD))
207     return V->getValue();
208 
209   // When the value goes to null, it gets replaced by an empty MDNode.
210   assert(!cast<MDNode>(MD)->getNumOperands() && "Expected an empty MDNode");
211   return nullptr;
212 }
213 
214 void DbgAssignIntrinsic::setAssignId(DIAssignID *New) {
215   setOperand(OpAssignID, MetadataAsValue::get(getContext(), New));
216 }
217 
218 void DbgAssignIntrinsic::setAddress(Value *V) {
219   setOperand(OpAddress,
220              MetadataAsValue::get(getContext(), ValueAsMetadata::get(V)));
221 }
222 
223 void DbgAssignIntrinsic::setKillAddress() {
224   if (isKillAddress())
225     return;
226   setAddress(PoisonValue::get(getAddress()->getType()));
227 }
228 
229 bool DbgAssignIntrinsic::isKillAddress() const {
230   Value *Addr = getAddress();
231   return !Addr || isa<UndefValue>(Addr);
232 }
233 
234 void DbgAssignIntrinsic::setValue(Value *V) {
235   setOperand(OpValue,
236              MetadataAsValue::get(getContext(), ValueAsMetadata::get(V)));
237 }
238 
239 ConstantInt *InstrProfCntrInstBase::getNumCounters() const {
240   if (InstrProfValueProfileInst::classof(this))
241     llvm_unreachable("InstrProfValueProfileInst does not have counters!");
242   return cast<ConstantInt>(const_cast<Value *>(getArgOperand(2)));
243 }
244 
245 ConstantInt *InstrProfCntrInstBase::getIndex() const {
246   if (InstrProfValueProfileInst::classof(this))
247     llvm_unreachable("Please use InstrProfValueProfileInst::getIndex()");
248   return cast<ConstantInt>(const_cast<Value *>(getArgOperand(3)));
249 }
250 
251 void InstrProfCntrInstBase::setIndex(uint32_t Idx) {
252   assert(isa<InstrProfCntrInstBase>(this));
253   setArgOperand(3, ConstantInt::get(Type::getInt32Ty(getContext()), Idx));
254 }
255 
256 Value *InstrProfIncrementInst::getStep() const {
257   if (InstrProfIncrementInstStep::classof(this)) {
258     return const_cast<Value *>(getArgOperand(4));
259   }
260   const Module *M = getModule();
261   LLVMContext &Context = M->getContext();
262   return ConstantInt::get(Type::getInt64Ty(Context), 1);
263 }
264 
265 Value *InstrProfCallsite::getCallee() const {
266   if (isa<InstrProfCallsite>(this))
267     return getArgOperand(4);
268   return nullptr;
269 }
270 
271 void InstrProfCallsite::setCallee(Value *Callee) {
272   assert(isa<InstrProfCallsite>(this));
273   setArgOperand(4, Callee);
274 }
275 
276 std::optional<RoundingMode> ConstrainedFPIntrinsic::getRoundingMode() const {
277   unsigned NumOperands = arg_size();
278   Metadata *MD = nullptr;
279   auto *MAV = dyn_cast<MetadataAsValue>(getArgOperand(NumOperands - 2));
280   if (MAV)
281     MD = MAV->getMetadata();
282   if (!MD || !isa<MDString>(MD))
283     return std::nullopt;
284   return convertStrToRoundingMode(cast<MDString>(MD)->getString());
285 }
286 
287 std::optional<fp::ExceptionBehavior>
288 ConstrainedFPIntrinsic::getExceptionBehavior() const {
289   unsigned NumOperands = arg_size();
290   Metadata *MD = nullptr;
291   auto *MAV = dyn_cast<MetadataAsValue>(getArgOperand(NumOperands - 1));
292   if (MAV)
293     MD = MAV->getMetadata();
294   if (!MD || !isa<MDString>(MD))
295     return std::nullopt;
296   return convertStrToExceptionBehavior(cast<MDString>(MD)->getString());
297 }
298 
299 bool ConstrainedFPIntrinsic::isDefaultFPEnvironment() const {
300   std::optional<fp::ExceptionBehavior> Except = getExceptionBehavior();
301   if (Except) {
302     if (*Except != fp::ebIgnore)
303       return false;
304   }
305 
306   std::optional<RoundingMode> Rounding = getRoundingMode();
307   if (Rounding) {
308     if (*Rounding != RoundingMode::NearestTiesToEven)
309       return false;
310   }
311 
312   return true;
313 }
314 
315 static FCmpInst::Predicate getFPPredicateFromMD(const Value *Op) {
316   Metadata *MD = cast<MetadataAsValue>(Op)->getMetadata();
317   if (!MD || !isa<MDString>(MD))
318     return FCmpInst::BAD_FCMP_PREDICATE;
319   return StringSwitch<FCmpInst::Predicate>(cast<MDString>(MD)->getString())
320       .Case("oeq", FCmpInst::FCMP_OEQ)
321       .Case("ogt", FCmpInst::FCMP_OGT)
322       .Case("oge", FCmpInst::FCMP_OGE)
323       .Case("olt", FCmpInst::FCMP_OLT)
324       .Case("ole", FCmpInst::FCMP_OLE)
325       .Case("one", FCmpInst::FCMP_ONE)
326       .Case("ord", FCmpInst::FCMP_ORD)
327       .Case("uno", FCmpInst::FCMP_UNO)
328       .Case("ueq", FCmpInst::FCMP_UEQ)
329       .Case("ugt", FCmpInst::FCMP_UGT)
330       .Case("uge", FCmpInst::FCMP_UGE)
331       .Case("ult", FCmpInst::FCMP_ULT)
332       .Case("ule", FCmpInst::FCMP_ULE)
333       .Case("une", FCmpInst::FCMP_UNE)
334       .Default(FCmpInst::BAD_FCMP_PREDICATE);
335 }
336 
337 FCmpInst::Predicate ConstrainedFPCmpIntrinsic::getPredicate() const {
338   return getFPPredicateFromMD(getArgOperand(2));
339 }
340 
341 unsigned ConstrainedFPIntrinsic::getNonMetadataArgCount() const {
342   // All constrained fp intrinsics have "fpexcept" metadata.
343   unsigned NumArgs = arg_size() - 1;
344 
345   // Some intrinsics have "round" metadata.
346   if (Intrinsic::hasConstrainedFPRoundingModeOperand(getIntrinsicID()))
347     NumArgs -= 1;
348 
349   // Compare intrinsics take their predicate as metadata.
350   if (isa<ConstrainedFPCmpIntrinsic>(this))
351     NumArgs -= 1;
352 
353   return NumArgs;
354 }
355 
356 bool ConstrainedFPIntrinsic::classof(const IntrinsicInst *I) {
357   return Intrinsic::isConstrainedFPIntrinsic(I->getIntrinsicID());
358 }
359 
360 ElementCount VPIntrinsic::getStaticVectorLength() const {
361   auto GetVectorLengthOfType = [](const Type *T) -> ElementCount {
362     const auto *VT = cast<VectorType>(T);
363     auto ElemCount = VT->getElementCount();
364     return ElemCount;
365   };
366 
367   Value *VPMask = getMaskParam();
368   if (!VPMask) {
369     assert((getIntrinsicID() == Intrinsic::vp_merge ||
370             getIntrinsicID() == Intrinsic::vp_select) &&
371            "Unexpected VP intrinsic without mask operand");
372     return GetVectorLengthOfType(getType());
373   }
374   return GetVectorLengthOfType(VPMask->getType());
375 }
376 
377 Value *VPIntrinsic::getMaskParam() const {
378   if (auto MaskPos = getMaskParamPos(getIntrinsicID()))
379     return getArgOperand(*MaskPos);
380   return nullptr;
381 }
382 
383 void VPIntrinsic::setMaskParam(Value *NewMask) {
384   auto MaskPos = getMaskParamPos(getIntrinsicID());
385   setArgOperand(*MaskPos, NewMask);
386 }
387 
388 Value *VPIntrinsic::getVectorLengthParam() const {
389   if (auto EVLPos = getVectorLengthParamPos(getIntrinsicID()))
390     return getArgOperand(*EVLPos);
391   return nullptr;
392 }
393 
394 void VPIntrinsic::setVectorLengthParam(Value *NewEVL) {
395   auto EVLPos = getVectorLengthParamPos(getIntrinsicID());
396   setArgOperand(*EVLPos, NewEVL);
397 }
398 
399 std::optional<unsigned>
400 VPIntrinsic::getMaskParamPos(Intrinsic::ID IntrinsicID) {
401   switch (IntrinsicID) {
402   default:
403     return std::nullopt;
404 
405 #define BEGIN_REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS)                    \
406   case Intrinsic::VPID:                                                        \
407     return MASKPOS;
408 #include "llvm/IR/VPIntrinsics.def"
409   }
410 }
411 
412 std::optional<unsigned>
413 VPIntrinsic::getVectorLengthParamPos(Intrinsic::ID IntrinsicID) {
414   switch (IntrinsicID) {
415   default:
416     return std::nullopt;
417 
418 #define BEGIN_REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS)                    \
419   case Intrinsic::VPID:                                                        \
420     return VLENPOS;
421 #include "llvm/IR/VPIntrinsics.def"
422   }
423 }
424 
425 /// \return the alignment of the pointer used by this load/store/gather or
426 /// scatter.
427 MaybeAlign VPIntrinsic::getPointerAlignment() const {
428   std::optional<unsigned> PtrParamOpt =
429       getMemoryPointerParamPos(getIntrinsicID());
430   assert(PtrParamOpt && "no pointer argument!");
431   return getParamAlign(*PtrParamOpt);
432 }
433 
434 /// \return The pointer operand of this load,store, gather or scatter.
435 Value *VPIntrinsic::getMemoryPointerParam() const {
436   if (auto PtrParamOpt = getMemoryPointerParamPos(getIntrinsicID()))
437     return getArgOperand(*PtrParamOpt);
438   return nullptr;
439 }
440 
441 std::optional<unsigned>
442 VPIntrinsic::getMemoryPointerParamPos(Intrinsic::ID VPID) {
443   switch (VPID) {
444   default:
445     return std::nullopt;
446   case Intrinsic::vp_store:
447   case Intrinsic::vp_scatter:
448   case Intrinsic::experimental_vp_strided_store:
449     return 1;
450   case Intrinsic::vp_load:
451   case Intrinsic::vp_gather:
452   case Intrinsic::experimental_vp_strided_load:
453     return 0;
454   }
455 }
456 
457 /// \return The data (payload) operand of this store or scatter.
458 Value *VPIntrinsic::getMemoryDataParam() const {
459   auto DataParamOpt = getMemoryDataParamPos(getIntrinsicID());
460   if (!DataParamOpt)
461     return nullptr;
462   return getArgOperand(*DataParamOpt);
463 }
464 
465 std::optional<unsigned> VPIntrinsic::getMemoryDataParamPos(Intrinsic::ID VPID) {
466   switch (VPID) {
467   default:
468     return std::nullopt;
469   case Intrinsic::vp_store:
470   case Intrinsic::vp_scatter:
471   case Intrinsic::experimental_vp_strided_store:
472     return 0;
473   }
474 }
475 
476 constexpr bool isVPIntrinsic(Intrinsic::ID ID) {
477   switch (ID) {
478   default:
479     break;
480 #define BEGIN_REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS)                    \
481   case Intrinsic::VPID:                                                        \
482     return true;
483 #include "llvm/IR/VPIntrinsics.def"
484   }
485   return false;
486 }
487 
488 bool VPIntrinsic::isVPIntrinsic(Intrinsic::ID ID) {
489   return ::isVPIntrinsic(ID);
490 }
491 
492 // Equivalent non-predicated opcode
493 constexpr static std::optional<unsigned>
494 getFunctionalOpcodeForVP(Intrinsic::ID ID) {
495   switch (ID) {
496   default:
497     break;
498 #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
499 #define VP_PROPERTY_FUNCTIONAL_OPC(OPC) return Instruction::OPC;
500 #define END_REGISTER_VP_INTRINSIC(VPID) break;
501 #include "llvm/IR/VPIntrinsics.def"
502   }
503   return std::nullopt;
504 }
505 
506 std::optional<unsigned>
507 VPIntrinsic::getFunctionalOpcodeForVP(Intrinsic::ID ID) {
508   return ::getFunctionalOpcodeForVP(ID);
509 }
510 
511 // Equivalent non-predicated intrinsic ID
512 constexpr static std::optional<Intrinsic::ID>
513 getFunctionalIntrinsicIDForVP(Intrinsic::ID ID) {
514   switch (ID) {
515   default:
516     break;
517 #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
518 #define VP_PROPERTY_FUNCTIONAL_INTRINSIC(INTRIN) return Intrinsic::INTRIN;
519 #define END_REGISTER_VP_INTRINSIC(VPID) break;
520 #include "llvm/IR/VPIntrinsics.def"
521   }
522   return std::nullopt;
523 }
524 
525 std::optional<Intrinsic::ID>
526 VPIntrinsic::getFunctionalIntrinsicIDForVP(Intrinsic::ID ID) {
527   return ::getFunctionalIntrinsicIDForVP(ID);
528 }
529 
530 constexpr static bool doesVPHaveNoFunctionalEquivalent(Intrinsic::ID ID) {
531   switch (ID) {
532   default:
533     break;
534 #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
535 #define VP_PROPERTY_NO_FUNCTIONAL return true;
536 #define END_REGISTER_VP_INTRINSIC(VPID) break;
537 #include "llvm/IR/VPIntrinsics.def"
538   }
539   return false;
540 }
541 
542 // All VP intrinsics should have an equivalent non-VP opcode or intrinsic
543 // defined, or be marked that they don't have one.
544 #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...)                                 \
545   static_assert(doesVPHaveNoFunctionalEquivalent(Intrinsic::VPID) ||           \
546                 getFunctionalOpcodeForVP(Intrinsic::VPID) ||                   \
547                 getFunctionalIntrinsicIDForVP(Intrinsic::VPID));
548 #include "llvm/IR/VPIntrinsics.def"
549 
550 // Equivalent non-predicated constrained intrinsic
551 std::optional<Intrinsic::ID>
552 VPIntrinsic::getConstrainedIntrinsicIDForVP(Intrinsic::ID ID) {
553   switch (ID) {
554   default:
555     break;
556 #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
557 #define VP_PROPERTY_CONSTRAINEDFP(CID) return Intrinsic::CID;
558 #define END_REGISTER_VP_INTRINSIC(VPID) break;
559 #include "llvm/IR/VPIntrinsics.def"
560   }
561   return std::nullopt;
562 }
563 
564 Intrinsic::ID VPIntrinsic::getForOpcode(unsigned IROPC) {
565   switch (IROPC) {
566   default:
567     break;
568 
569 #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) break;
570 #define VP_PROPERTY_FUNCTIONAL_OPC(OPC) case Instruction::OPC:
571 #define END_REGISTER_VP_INTRINSIC(VPID) return Intrinsic::VPID;
572 #include "llvm/IR/VPIntrinsics.def"
573   }
574   return Intrinsic::not_intrinsic;
575 }
576 
577 constexpr static Intrinsic::ID getForIntrinsic(Intrinsic::ID Id) {
578   if (::isVPIntrinsic(Id))
579     return Id;
580 
581   switch (Id) {
582   default:
583     break;
584 #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) break;
585 #define VP_PROPERTY_FUNCTIONAL_INTRINSIC(INTRIN) case Intrinsic::INTRIN:
586 #define END_REGISTER_VP_INTRINSIC(VPID) return Intrinsic::VPID;
587 #include "llvm/IR/VPIntrinsics.def"
588   }
589   return Intrinsic::not_intrinsic;
590 }
591 
592 Intrinsic::ID VPIntrinsic::getForIntrinsic(Intrinsic::ID Id) {
593   return ::getForIntrinsic(Id);
594 }
595 
596 bool VPIntrinsic::canIgnoreVectorLengthParam() const {
597   using namespace PatternMatch;
598 
599   ElementCount EC = getStaticVectorLength();
600 
601   // No vlen param - no lanes masked-off by it.
602   auto *VLParam = getVectorLengthParam();
603   if (!VLParam)
604     return true;
605 
606   // Note that the VP intrinsic causes undefined behavior if the Explicit Vector
607   // Length parameter is strictly greater-than the number of vector elements of
608   // the operation. This function returns true when this is detected statically
609   // in the IR.
610 
611   // Check whether "W == vscale * EC.getKnownMinValue()"
612   if (EC.isScalable()) {
613     // Compare vscale patterns
614     uint64_t VScaleFactor;
615     if (match(VLParam, m_Mul(m_VScale(), m_ConstantInt(VScaleFactor))))
616       return VScaleFactor >= EC.getKnownMinValue();
617     return (EC.getKnownMinValue() == 1) && match(VLParam, m_VScale());
618   }
619 
620   // standard SIMD operation
621   const auto *VLConst = dyn_cast<ConstantInt>(VLParam);
622   if (!VLConst)
623     return false;
624 
625   uint64_t VLNum = VLConst->getZExtValue();
626   if (VLNum >= EC.getKnownMinValue())
627     return true;
628 
629   return false;
630 }
631 
632 Function *VPIntrinsic::getOrInsertDeclarationForParams(
633     Module *M, Intrinsic::ID VPID, Type *ReturnType, ArrayRef<Value *> Params) {
634   assert(isVPIntrinsic(VPID) && "not a VP intrinsic");
635   Function *VPFunc;
636   switch (VPID) {
637   default: {
638     Type *OverloadTy = Params[0]->getType();
639     if (VPReductionIntrinsic::isVPReduction(VPID))
640       OverloadTy =
641           Params[*VPReductionIntrinsic::getVectorParamPos(VPID)]->getType();
642 
643     VPFunc = Intrinsic::getOrInsertDeclaration(M, VPID, OverloadTy);
644     break;
645   }
646   case Intrinsic::vp_trunc:
647   case Intrinsic::vp_sext:
648   case Intrinsic::vp_zext:
649   case Intrinsic::vp_fptoui:
650   case Intrinsic::vp_fptosi:
651   case Intrinsic::vp_uitofp:
652   case Intrinsic::vp_sitofp:
653   case Intrinsic::vp_fptrunc:
654   case Intrinsic::vp_fpext:
655   case Intrinsic::vp_ptrtoint:
656   case Intrinsic::vp_inttoptr:
657   case Intrinsic::vp_lrint:
658   case Intrinsic::vp_llrint:
659   case Intrinsic::vp_cttz_elts:
660     VPFunc = Intrinsic::getOrInsertDeclaration(
661         M, VPID, {ReturnType, Params[0]->getType()});
662     break;
663   case Intrinsic::vp_is_fpclass:
664     VPFunc = Intrinsic::getOrInsertDeclaration(M, VPID, {Params[0]->getType()});
665     break;
666   case Intrinsic::vp_merge:
667   case Intrinsic::vp_select:
668     VPFunc = Intrinsic::getOrInsertDeclaration(M, VPID, {Params[1]->getType()});
669     break;
670   case Intrinsic::vp_load:
671     VPFunc = Intrinsic::getOrInsertDeclaration(
672         M, VPID, {ReturnType, Params[0]->getType()});
673     break;
674   case Intrinsic::experimental_vp_strided_load:
675     VPFunc = Intrinsic::getOrInsertDeclaration(
676         M, VPID, {ReturnType, Params[0]->getType(), Params[1]->getType()});
677     break;
678   case Intrinsic::vp_gather:
679     VPFunc = Intrinsic::getOrInsertDeclaration(
680         M, VPID, {ReturnType, Params[0]->getType()});
681     break;
682   case Intrinsic::vp_store:
683     VPFunc = Intrinsic::getOrInsertDeclaration(
684         M, VPID, {Params[0]->getType(), Params[1]->getType()});
685     break;
686   case Intrinsic::experimental_vp_strided_store:
687     VPFunc = Intrinsic::getOrInsertDeclaration(
688         M, VPID,
689         {Params[0]->getType(), Params[1]->getType(), Params[2]->getType()});
690     break;
691   case Intrinsic::vp_scatter:
692     VPFunc = Intrinsic::getOrInsertDeclaration(
693         M, VPID, {Params[0]->getType(), Params[1]->getType()});
694     break;
695   case Intrinsic::experimental_vp_splat:
696     VPFunc = Intrinsic::getOrInsertDeclaration(M, VPID, ReturnType);
697     break;
698   }
699   assert(VPFunc && "Could not declare VP intrinsic");
700   return VPFunc;
701 }
702 
703 bool VPReductionIntrinsic::isVPReduction(Intrinsic::ID ID) {
704   switch (ID) {
705   case Intrinsic::vp_reduce_add:
706   case Intrinsic::vp_reduce_mul:
707   case Intrinsic::vp_reduce_and:
708   case Intrinsic::vp_reduce_or:
709   case Intrinsic::vp_reduce_xor:
710   case Intrinsic::vp_reduce_smax:
711   case Intrinsic::vp_reduce_smin:
712   case Intrinsic::vp_reduce_umax:
713   case Intrinsic::vp_reduce_umin:
714   case Intrinsic::vp_reduce_fmax:
715   case Intrinsic::vp_reduce_fmin:
716   case Intrinsic::vp_reduce_fmaximum:
717   case Intrinsic::vp_reduce_fminimum:
718   case Intrinsic::vp_reduce_fadd:
719   case Intrinsic::vp_reduce_fmul:
720     return true;
721   default:
722     return false;
723   }
724 }
725 
726 bool VPCastIntrinsic::isVPCast(Intrinsic::ID ID) {
727   // All of the vp.casts correspond to instructions
728   if (std::optional<unsigned> Opc = getFunctionalOpcodeForVP(ID))
729     return Instruction::isCast(*Opc);
730   return false;
731 }
732 
733 bool VPCmpIntrinsic::isVPCmp(Intrinsic::ID ID) {
734   switch (ID) {
735   default:
736     return false;
737   case Intrinsic::vp_fcmp:
738   case Intrinsic::vp_icmp:
739     return true;
740   }
741 }
742 
743 bool VPBinOpIntrinsic::isVPBinOp(Intrinsic::ID ID) {
744   switch (ID) {
745   default:
746     break;
747 #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
748 #define VP_PROPERTY_BINARYOP return true;
749 #define END_REGISTER_VP_INTRINSIC(VPID) break;
750 #include "llvm/IR/VPIntrinsics.def"
751   }
752   return false;
753 }
754 
755 static ICmpInst::Predicate getIntPredicateFromMD(const Value *Op) {
756   Metadata *MD = cast<MetadataAsValue>(Op)->getMetadata();
757   if (!MD || !isa<MDString>(MD))
758     return ICmpInst::BAD_ICMP_PREDICATE;
759   return StringSwitch<ICmpInst::Predicate>(cast<MDString>(MD)->getString())
760       .Case("eq", ICmpInst::ICMP_EQ)
761       .Case("ne", ICmpInst::ICMP_NE)
762       .Case("ugt", ICmpInst::ICMP_UGT)
763       .Case("uge", ICmpInst::ICMP_UGE)
764       .Case("ult", ICmpInst::ICMP_ULT)
765       .Case("ule", ICmpInst::ICMP_ULE)
766       .Case("sgt", ICmpInst::ICMP_SGT)
767       .Case("sge", ICmpInst::ICMP_SGE)
768       .Case("slt", ICmpInst::ICMP_SLT)
769       .Case("sle", ICmpInst::ICMP_SLE)
770       .Default(ICmpInst::BAD_ICMP_PREDICATE);
771 }
772 
773 CmpInst::Predicate VPCmpIntrinsic::getPredicate() const {
774   assert(isVPCmp(getIntrinsicID()));
775   return getIntrinsicID() == Intrinsic::vp_fcmp
776              ? getFPPredicateFromMD(getArgOperand(2))
777              : getIntPredicateFromMD(getArgOperand(2));
778 }
779 
780 unsigned VPReductionIntrinsic::getVectorParamPos() const {
781   return *VPReductionIntrinsic::getVectorParamPos(getIntrinsicID());
782 }
783 
784 unsigned VPReductionIntrinsic::getStartParamPos() const {
785   return *VPReductionIntrinsic::getStartParamPos(getIntrinsicID());
786 }
787 
788 std::optional<unsigned>
789 VPReductionIntrinsic::getVectorParamPos(Intrinsic::ID ID) {
790   if (isVPReduction(ID))
791     return 1;
792   return std::nullopt;
793 }
794 
795 std::optional<unsigned>
796 VPReductionIntrinsic::getStartParamPos(Intrinsic::ID ID) {
797   if (isVPReduction(ID))
798     return 0;
799   return std::nullopt;
800 }
801 
802 Instruction::BinaryOps BinaryOpIntrinsic::getBinaryOp() const {
803   switch (getIntrinsicID()) {
804   case Intrinsic::uadd_with_overflow:
805   case Intrinsic::sadd_with_overflow:
806   case Intrinsic::uadd_sat:
807   case Intrinsic::sadd_sat:
808     return Instruction::Add;
809   case Intrinsic::usub_with_overflow:
810   case Intrinsic::ssub_with_overflow:
811   case Intrinsic::usub_sat:
812   case Intrinsic::ssub_sat:
813     return Instruction::Sub;
814   case Intrinsic::umul_with_overflow:
815   case Intrinsic::smul_with_overflow:
816     return Instruction::Mul;
817   default:
818     llvm_unreachable("Invalid intrinsic");
819   }
820 }
821 
822 bool BinaryOpIntrinsic::isSigned() const {
823   switch (getIntrinsicID()) {
824   case Intrinsic::sadd_with_overflow:
825   case Intrinsic::ssub_with_overflow:
826   case Intrinsic::smul_with_overflow:
827   case Intrinsic::sadd_sat:
828   case Intrinsic::ssub_sat:
829     return true;
830   default:
831     return false;
832   }
833 }
834 
835 unsigned BinaryOpIntrinsic::getNoWrapKind() const {
836   if (isSigned())
837     return OverflowingBinaryOperator::NoSignedWrap;
838   else
839     return OverflowingBinaryOperator::NoUnsignedWrap;
840 }
841 
842 const Value *GCProjectionInst::getStatepoint() const {
843   const Value *Token = getArgOperand(0);
844   if (isa<UndefValue>(Token))
845     return Token;
846 
847   // Treat none token as if it was undef here
848   if (isa<ConstantTokenNone>(Token))
849     return UndefValue::get(Token->getType());
850 
851   // This takes care both of relocates for call statepoints and relocates
852   // on normal path of invoke statepoint.
853   if (!isa<LandingPadInst>(Token))
854     return cast<GCStatepointInst>(Token);
855 
856   // This relocate is on exceptional path of an invoke statepoint
857   const BasicBlock *InvokeBB =
858     cast<Instruction>(Token)->getParent()->getUniquePredecessor();
859 
860   assert(InvokeBB && "safepoints should have unique landingpads");
861   assert(InvokeBB->getTerminator() &&
862          "safepoint block should be well formed");
863 
864   return cast<GCStatepointInst>(InvokeBB->getTerminator());
865 }
866 
867 Value *GCRelocateInst::getBasePtr() const {
868   auto Statepoint = getStatepoint();
869   if (isa<UndefValue>(Statepoint))
870     return UndefValue::get(Statepoint->getType());
871 
872   auto *GCInst = cast<GCStatepointInst>(Statepoint);
873   if (auto Opt = GCInst->getOperandBundle(LLVMContext::OB_gc_live))
874     return *(Opt->Inputs.begin() + getBasePtrIndex());
875   return *(GCInst->arg_begin() + getBasePtrIndex());
876 }
877 
878 Value *GCRelocateInst::getDerivedPtr() const {
879   auto *Statepoint = getStatepoint();
880   if (isa<UndefValue>(Statepoint))
881     return UndefValue::get(Statepoint->getType());
882 
883   auto *GCInst = cast<GCStatepointInst>(Statepoint);
884   if (auto Opt = GCInst->getOperandBundle(LLVMContext::OB_gc_live))
885     return *(Opt->Inputs.begin() + getDerivedPtrIndex());
886   return *(GCInst->arg_begin() + getDerivedPtrIndex());
887 }
888