xref: /openbsd/gnu/llvm/llvm/lib/IR/IntrinsicInst.cpp (revision d415bd75)
173471bf0Spatrick //===-- IntrinsicInst.cpp - Intrinsic Instruction Wrappers ---------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This file implements methods that make it really easy to deal with intrinsic
1009467b48Spatrick // functions.
1109467b48Spatrick //
1209467b48Spatrick // All intrinsic function calls are instances of the call instruction, so these
1309467b48Spatrick // are all subclasses of the CallInst class.  Note that none of these classes
1409467b48Spatrick // has state or virtual methods, which is an important part of this gross/neat
1509467b48Spatrick // hack working.
1609467b48Spatrick //
1709467b48Spatrick // In some cases, arguments to intrinsics need to be generic and are defined as
1809467b48Spatrick // type pointer to empty struct { }*.  To access the real item of interest the
1909467b48Spatrick // cast instruction needs to be stripped away.
2009467b48Spatrick //
2109467b48Spatrick //===----------------------------------------------------------------------===//
2209467b48Spatrick 
2309467b48Spatrick #include "llvm/IR/IntrinsicInst.h"
2409467b48Spatrick #include "llvm/ADT/StringSwitch.h"
2509467b48Spatrick #include "llvm/IR/Constants.h"
2609467b48Spatrick #include "llvm/IR/DebugInfoMetadata.h"
2709467b48Spatrick #include "llvm/IR/Metadata.h"
2809467b48Spatrick #include "llvm/IR/Module.h"
29097a140dSpatrick #include "llvm/IR/Operator.h"
30097a140dSpatrick #include "llvm/IR/PatternMatch.h"
3173471bf0Spatrick #include "llvm/IR/Statepoint.h"
32*d415bd75Srobert #include <optional>
33097a140dSpatrick 
3409467b48Spatrick using namespace llvm;
3509467b48Spatrick 
mayLowerToFunctionCall(Intrinsic::ID IID)36*d415bd75Srobert bool IntrinsicInst::mayLowerToFunctionCall(Intrinsic::ID IID) {
37*d415bd75Srobert   switch (IID) {
38*d415bd75Srobert   case Intrinsic::objc_autorelease:
39*d415bd75Srobert   case Intrinsic::objc_autoreleasePoolPop:
40*d415bd75Srobert   case Intrinsic::objc_autoreleasePoolPush:
41*d415bd75Srobert   case Intrinsic::objc_autoreleaseReturnValue:
42*d415bd75Srobert   case Intrinsic::objc_copyWeak:
43*d415bd75Srobert   case Intrinsic::objc_destroyWeak:
44*d415bd75Srobert   case Intrinsic::objc_initWeak:
45*d415bd75Srobert   case Intrinsic::objc_loadWeak:
46*d415bd75Srobert   case Intrinsic::objc_loadWeakRetained:
47*d415bd75Srobert   case Intrinsic::objc_moveWeak:
48*d415bd75Srobert   case Intrinsic::objc_release:
49*d415bd75Srobert   case Intrinsic::objc_retain:
50*d415bd75Srobert   case Intrinsic::objc_retainAutorelease:
51*d415bd75Srobert   case Intrinsic::objc_retainAutoreleaseReturnValue:
52*d415bd75Srobert   case Intrinsic::objc_retainAutoreleasedReturnValue:
53*d415bd75Srobert   case Intrinsic::objc_retainBlock:
54*d415bd75Srobert   case Intrinsic::objc_storeStrong:
55*d415bd75Srobert   case Intrinsic::objc_storeWeak:
56*d415bd75Srobert   case Intrinsic::objc_unsafeClaimAutoreleasedReturnValue:
57*d415bd75Srobert   case Intrinsic::objc_retainedObject:
58*d415bd75Srobert   case Intrinsic::objc_unretainedObject:
59*d415bd75Srobert   case Intrinsic::objc_unretainedPointer:
60*d415bd75Srobert   case Intrinsic::objc_retain_autorelease:
61*d415bd75Srobert   case Intrinsic::objc_sync_enter:
62*d415bd75Srobert   case Intrinsic::objc_sync_exit:
63*d415bd75Srobert     return true;
64*d415bd75Srobert   default:
65*d415bd75Srobert     return false;
66*d415bd75Srobert   }
67*d415bd75Srobert }
68*d415bd75Srobert 
6909467b48Spatrick //===----------------------------------------------------------------------===//
7009467b48Spatrick /// DbgVariableIntrinsic - This is the common base class for debug info
7109467b48Spatrick /// intrinsics for variables.
7209467b48Spatrick ///
7309467b48Spatrick 
7473471bf0Spatrick iterator_range<DbgVariableIntrinsic::location_op_iterator>
location_ops() const7573471bf0Spatrick DbgVariableIntrinsic::location_ops() const {
7673471bf0Spatrick   auto *MD = getRawLocation();
7773471bf0Spatrick   assert(MD && "First operand of DbgVariableIntrinsic should be non-null.");
7809467b48Spatrick 
7973471bf0Spatrick   // If operand is ValueAsMetadata, return a range over just that operand.
8073471bf0Spatrick   if (auto *VAM = dyn_cast<ValueAsMetadata>(MD)) {
8173471bf0Spatrick     return {location_op_iterator(VAM), location_op_iterator(VAM + 1)};
8273471bf0Spatrick   }
8373471bf0Spatrick   // If operand is DIArgList, return a range over its args.
8473471bf0Spatrick   if (auto *AL = dyn_cast<DIArgList>(MD))
8573471bf0Spatrick     return {location_op_iterator(AL->args_begin()),
8673471bf0Spatrick             location_op_iterator(AL->args_end())};
8773471bf0Spatrick   // Operand must be an empty metadata tuple, so return empty iterator.
8873471bf0Spatrick   return {location_op_iterator(static_cast<ValueAsMetadata *>(nullptr)),
8973471bf0Spatrick           location_op_iterator(static_cast<ValueAsMetadata *>(nullptr))};
9073471bf0Spatrick }
9173471bf0Spatrick 
getVariableLocationOp(unsigned OpIdx) const9273471bf0Spatrick Value *DbgVariableIntrinsic::getVariableLocationOp(unsigned OpIdx) const {
9373471bf0Spatrick   auto *MD = getRawLocation();
9473471bf0Spatrick   assert(MD && "First operand of DbgVariableIntrinsic should be non-null.");
9573471bf0Spatrick   if (auto *AL = dyn_cast<DIArgList>(MD))
9673471bf0Spatrick     return AL->getArgs()[OpIdx]->getValue();
9773471bf0Spatrick   if (isa<MDNode>(MD))
9873471bf0Spatrick     return nullptr;
9973471bf0Spatrick   assert(
10073471bf0Spatrick       isa<ValueAsMetadata>(MD) &&
10173471bf0Spatrick       "Attempted to get location operand from DbgVariableIntrinsic with none.");
10273471bf0Spatrick   auto *V = cast<ValueAsMetadata>(MD);
10373471bf0Spatrick   assert(OpIdx == 0 && "Operand Index must be 0 for a debug intrinsic with a "
10473471bf0Spatrick                        "single location operand.");
10509467b48Spatrick   return V->getValue();
10673471bf0Spatrick }
10709467b48Spatrick 
getAsMetadata(Value * V)10873471bf0Spatrick static ValueAsMetadata *getAsMetadata(Value *V) {
10973471bf0Spatrick   return isa<MetadataAsValue>(V) ? dyn_cast<ValueAsMetadata>(
11073471bf0Spatrick                                        cast<MetadataAsValue>(V)->getMetadata())
11173471bf0Spatrick                                  : ValueAsMetadata::get(V);
11273471bf0Spatrick }
11373471bf0Spatrick 
replaceVariableLocationOp(Value * OldValue,Value * NewValue)11473471bf0Spatrick void DbgVariableIntrinsic::replaceVariableLocationOp(Value *OldValue,
11573471bf0Spatrick                                                      Value *NewValue) {
116*d415bd75Srobert   // If OldValue is used as the address part of a dbg.assign intrinsic replace
117*d415bd75Srobert   // it with NewValue and return true.
118*d415bd75Srobert   auto ReplaceDbgAssignAddress = [this, OldValue, NewValue]() -> bool {
119*d415bd75Srobert     auto *DAI = dyn_cast<DbgAssignIntrinsic>(this);
120*d415bd75Srobert     if (!DAI || OldValue != DAI->getAddress())
121*d415bd75Srobert       return false;
122*d415bd75Srobert     DAI->setAddress(NewValue);
123*d415bd75Srobert     return true;
124*d415bd75Srobert   };
125*d415bd75Srobert   bool DbgAssignAddrReplaced = ReplaceDbgAssignAddress();
126*d415bd75Srobert   (void)DbgAssignAddrReplaced;
127*d415bd75Srobert 
12873471bf0Spatrick   assert(NewValue && "Values must be non-null");
12973471bf0Spatrick   auto Locations = location_ops();
13073471bf0Spatrick   auto OldIt = find(Locations, OldValue);
131*d415bd75Srobert   assert((OldIt != Locations.end() || DbgAssignAddrReplaced) &&
132*d415bd75Srobert          "OldValue must be a current location");
13373471bf0Spatrick   if (!hasArgList()) {
134*d415bd75Srobert     // Additional check necessary to avoid unconditionally replacing this
135*d415bd75Srobert     // operand when a dbg.assign address is replaced (DbgAssignAddrReplaced is
136*d415bd75Srobert     // true).
137*d415bd75Srobert     if (OldValue != getVariableLocationOp(0))
138*d415bd75Srobert       return;
13973471bf0Spatrick     Value *NewOperand = isa<MetadataAsValue>(NewValue)
14073471bf0Spatrick                             ? NewValue
14173471bf0Spatrick                             : MetadataAsValue::get(
14273471bf0Spatrick                                   getContext(), ValueAsMetadata::get(NewValue));
14373471bf0Spatrick     return setArgOperand(0, NewOperand);
14473471bf0Spatrick   }
14573471bf0Spatrick   SmallVector<ValueAsMetadata *, 4> MDs;
14673471bf0Spatrick   ValueAsMetadata *NewOperand = getAsMetadata(NewValue);
14773471bf0Spatrick   for (auto *VMD : Locations)
14873471bf0Spatrick     MDs.push_back(VMD == *OldIt ? NewOperand : getAsMetadata(VMD));
14973471bf0Spatrick   setArgOperand(
15073471bf0Spatrick       0, MetadataAsValue::get(getContext(), DIArgList::get(getContext(), MDs)));
15173471bf0Spatrick }
replaceVariableLocationOp(unsigned OpIdx,Value * NewValue)15273471bf0Spatrick void DbgVariableIntrinsic::replaceVariableLocationOp(unsigned OpIdx,
15373471bf0Spatrick                                                      Value *NewValue) {
15473471bf0Spatrick   assert(OpIdx < getNumVariableLocationOps() && "Invalid Operand Index");
15573471bf0Spatrick   if (!hasArgList()) {
15673471bf0Spatrick     Value *NewOperand = isa<MetadataAsValue>(NewValue)
15773471bf0Spatrick                             ? NewValue
15873471bf0Spatrick                             : MetadataAsValue::get(
15973471bf0Spatrick                                   getContext(), ValueAsMetadata::get(NewValue));
16073471bf0Spatrick     return setArgOperand(0, NewOperand);
16173471bf0Spatrick   }
16273471bf0Spatrick   SmallVector<ValueAsMetadata *, 4> MDs;
16373471bf0Spatrick   ValueAsMetadata *NewOperand = getAsMetadata(NewValue);
16473471bf0Spatrick   for (unsigned Idx = 0; Idx < getNumVariableLocationOps(); ++Idx)
16573471bf0Spatrick     MDs.push_back(Idx == OpIdx ? NewOperand
16673471bf0Spatrick                                : getAsMetadata(getVariableLocationOp(Idx)));
16773471bf0Spatrick   setArgOperand(
16873471bf0Spatrick       0, MetadataAsValue::get(getContext(), DIArgList::get(getContext(), MDs)));
16973471bf0Spatrick }
17073471bf0Spatrick 
addVariableLocationOps(ArrayRef<Value * > NewValues,DIExpression * NewExpr)17173471bf0Spatrick void DbgVariableIntrinsic::addVariableLocationOps(ArrayRef<Value *> NewValues,
17273471bf0Spatrick                                                   DIExpression *NewExpr) {
17373471bf0Spatrick   assert(NewExpr->hasAllLocationOps(getNumVariableLocationOps() +
17473471bf0Spatrick                                     NewValues.size()) &&
17573471bf0Spatrick          "NewExpr for debug variable intrinsic does not reference every "
17673471bf0Spatrick          "location operand.");
17773471bf0Spatrick   assert(!is_contained(NewValues, nullptr) && "New values must be non-null");
17873471bf0Spatrick   setArgOperand(2, MetadataAsValue::get(getContext(), NewExpr));
17973471bf0Spatrick   SmallVector<ValueAsMetadata *, 4> MDs;
18073471bf0Spatrick   for (auto *VMD : location_ops())
18173471bf0Spatrick     MDs.push_back(getAsMetadata(VMD));
18273471bf0Spatrick   for (auto *VMD : NewValues)
18373471bf0Spatrick     MDs.push_back(getAsMetadata(VMD));
18473471bf0Spatrick   setArgOperand(
18573471bf0Spatrick       0, MetadataAsValue::get(getContext(), DIArgList::get(getContext(), MDs)));
18609467b48Spatrick }
18709467b48Spatrick 
getFragmentSizeInBits() const188*d415bd75Srobert std::optional<uint64_t> DbgVariableIntrinsic::getFragmentSizeInBits() const {
18909467b48Spatrick   if (auto Fragment = getExpression()->getFragmentInfo())
19009467b48Spatrick     return Fragment->SizeInBits;
19109467b48Spatrick   return getVariable()->getSizeInBits();
19209467b48Spatrick }
19309467b48Spatrick 
getAddress() const194*d415bd75Srobert Value *DbgAssignIntrinsic::getAddress() const {
195*d415bd75Srobert   auto *MD = getRawAddress();
196*d415bd75Srobert   if (auto *V = dyn_cast<ValueAsMetadata>(MD))
197*d415bd75Srobert     return V->getValue();
198*d415bd75Srobert 
199*d415bd75Srobert   // When the value goes to null, it gets replaced by an empty MDNode.
200*d415bd75Srobert   assert(!cast<MDNode>(MD)->getNumOperands() && "Expected an empty MDNode");
201*d415bd75Srobert   return nullptr;
202*d415bd75Srobert }
203*d415bd75Srobert 
setAssignId(DIAssignID * New)204*d415bd75Srobert void DbgAssignIntrinsic::setAssignId(DIAssignID *New) {
205*d415bd75Srobert   setOperand(OpAssignID, MetadataAsValue::get(getContext(), New));
206*d415bd75Srobert }
207*d415bd75Srobert 
setAddress(Value * V)208*d415bd75Srobert void DbgAssignIntrinsic::setAddress(Value *V) {
209*d415bd75Srobert   assert(V->getType()->isPointerTy() &&
210*d415bd75Srobert          "Destination Component must be a pointer type");
211*d415bd75Srobert   setOperand(OpAddress,
212*d415bd75Srobert              MetadataAsValue::get(getContext(), ValueAsMetadata::get(V)));
213*d415bd75Srobert }
214*d415bd75Srobert 
setKillAddress()215*d415bd75Srobert void DbgAssignIntrinsic::setKillAddress() {
216*d415bd75Srobert   if (isKillAddress())
217*d415bd75Srobert     return;
218*d415bd75Srobert   setAddress(UndefValue::get(getAddress()->getType()));
219*d415bd75Srobert }
220*d415bd75Srobert 
isKillAddress() const221*d415bd75Srobert bool DbgAssignIntrinsic::isKillAddress() const {
222*d415bd75Srobert   Value *Addr = getAddress();
223*d415bd75Srobert   return !Addr || isa<UndefValue>(Addr);
224*d415bd75Srobert }
225*d415bd75Srobert 
setValue(Value * V)226*d415bd75Srobert void DbgAssignIntrinsic::setValue(Value *V) {
227*d415bd75Srobert   setOperand(OpValue,
228*d415bd75Srobert              MetadataAsValue::get(getContext(), ValueAsMetadata::get(V)));
229*d415bd75Srobert }
230*d415bd75Srobert 
lookupLLVMIntrinsicByName(ArrayRef<const char * > NameTable,StringRef Name)23109467b48Spatrick int llvm::Intrinsic::lookupLLVMIntrinsicByName(ArrayRef<const char *> NameTable,
23209467b48Spatrick                                                StringRef Name) {
23309467b48Spatrick   assert(Name.startswith("llvm."));
23409467b48Spatrick 
23509467b48Spatrick   // Do successive binary searches of the dotted name components. For
23609467b48Spatrick   // "llvm.gc.experimental.statepoint.p1i8.p1i32", we will find the range of
23709467b48Spatrick   // intrinsics starting with "llvm.gc", then "llvm.gc.experimental", then
23809467b48Spatrick   // "llvm.gc.experimental.statepoint", and then we will stop as the range is
23909467b48Spatrick   // size 1. During the search, we can skip the prefix that we already know is
24009467b48Spatrick   // identical. By using strncmp we consider names with differing suffixes to
24109467b48Spatrick   // be part of the equal range.
24209467b48Spatrick   size_t CmpEnd = 4; // Skip the "llvm" component.
24309467b48Spatrick   const char *const *Low = NameTable.begin();
24409467b48Spatrick   const char *const *High = NameTable.end();
24509467b48Spatrick   const char *const *LastLow = Low;
24609467b48Spatrick   while (CmpEnd < Name.size() && High - Low > 0) {
24709467b48Spatrick     size_t CmpStart = CmpEnd;
24809467b48Spatrick     CmpEnd = Name.find('.', CmpStart + 1);
24909467b48Spatrick     CmpEnd = CmpEnd == StringRef::npos ? Name.size() : CmpEnd;
25009467b48Spatrick     auto Cmp = [CmpStart, CmpEnd](const char *LHS, const char *RHS) {
25109467b48Spatrick       return strncmp(LHS + CmpStart, RHS + CmpStart, CmpEnd - CmpStart) < 0;
25209467b48Spatrick     };
25309467b48Spatrick     LastLow = Low;
25409467b48Spatrick     std::tie(Low, High) = std::equal_range(Low, High, Name.data(), Cmp);
25509467b48Spatrick   }
25609467b48Spatrick   if (High - Low > 0)
25709467b48Spatrick     LastLow = Low;
25809467b48Spatrick 
25909467b48Spatrick   if (LastLow == NameTable.end())
26009467b48Spatrick     return -1;
26109467b48Spatrick   StringRef NameFound = *LastLow;
26209467b48Spatrick   if (Name == NameFound ||
26309467b48Spatrick       (Name.startswith(NameFound) && Name[NameFound.size()] == '.'))
26409467b48Spatrick     return LastLow - NameTable.begin();
26509467b48Spatrick   return -1;
26609467b48Spatrick }
26709467b48Spatrick 
getNumCounters() const268*d415bd75Srobert ConstantInt *InstrProfInstBase::getNumCounters() const {
269*d415bd75Srobert   if (InstrProfValueProfileInst::classof(this))
270*d415bd75Srobert     llvm_unreachable("InstrProfValueProfileInst does not have counters!");
271*d415bd75Srobert   return cast<ConstantInt>(const_cast<Value *>(getArgOperand(2)));
272*d415bd75Srobert }
273*d415bd75Srobert 
getIndex() const274*d415bd75Srobert ConstantInt *InstrProfInstBase::getIndex() const {
275*d415bd75Srobert   if (InstrProfValueProfileInst::classof(this))
276*d415bd75Srobert     llvm_unreachable("Please use InstrProfValueProfileInst::getIndex()");
277*d415bd75Srobert   return cast<ConstantInt>(const_cast<Value *>(getArgOperand(3)));
278*d415bd75Srobert }
279*d415bd75Srobert 
getStep() const28009467b48Spatrick Value *InstrProfIncrementInst::getStep() const {
28109467b48Spatrick   if (InstrProfIncrementInstStep::classof(this)) {
28209467b48Spatrick     return const_cast<Value *>(getArgOperand(4));
28309467b48Spatrick   }
28409467b48Spatrick   const Module *M = getModule();
28509467b48Spatrick   LLVMContext &Context = M->getContext();
28609467b48Spatrick   return ConstantInt::get(Type::getInt64Ty(Context), 1);
28709467b48Spatrick }
28809467b48Spatrick 
getRoundingMode() const289*d415bd75Srobert std::optional<RoundingMode> ConstrainedFPIntrinsic::getRoundingMode() const {
290*d415bd75Srobert   unsigned NumOperands = arg_size();
29173471bf0Spatrick   Metadata *MD = nullptr;
29273471bf0Spatrick   auto *MAV = dyn_cast<MetadataAsValue>(getArgOperand(NumOperands - 2));
29373471bf0Spatrick   if (MAV)
29473471bf0Spatrick     MD = MAV->getMetadata();
29509467b48Spatrick   if (!MD || !isa<MDString>(MD))
296*d415bd75Srobert     return std::nullopt;
297*d415bd75Srobert   return convertStrToRoundingMode(cast<MDString>(MD)->getString());
29809467b48Spatrick }
29909467b48Spatrick 
300*d415bd75Srobert std::optional<fp::ExceptionBehavior>
getExceptionBehavior() const30109467b48Spatrick ConstrainedFPIntrinsic::getExceptionBehavior() const {
302*d415bd75Srobert   unsigned NumOperands = arg_size();
30373471bf0Spatrick   Metadata *MD = nullptr;
30473471bf0Spatrick   auto *MAV = dyn_cast<MetadataAsValue>(getArgOperand(NumOperands - 1));
30573471bf0Spatrick   if (MAV)
30673471bf0Spatrick     MD = MAV->getMetadata();
30709467b48Spatrick   if (!MD || !isa<MDString>(MD))
308*d415bd75Srobert     return std::nullopt;
309*d415bd75Srobert   return convertStrToExceptionBehavior(cast<MDString>(MD)->getString());
31009467b48Spatrick }
31109467b48Spatrick 
isDefaultFPEnvironment() const31273471bf0Spatrick bool ConstrainedFPIntrinsic::isDefaultFPEnvironment() const {
313*d415bd75Srobert   std::optional<fp::ExceptionBehavior> Except = getExceptionBehavior();
31473471bf0Spatrick   if (Except) {
315*d415bd75Srobert     if (*Except != fp::ebIgnore)
31673471bf0Spatrick       return false;
31773471bf0Spatrick   }
31873471bf0Spatrick 
319*d415bd75Srobert   std::optional<RoundingMode> Rounding = getRoundingMode();
32073471bf0Spatrick   if (Rounding) {
321*d415bd75Srobert     if (*Rounding != RoundingMode::NearestTiesToEven)
32273471bf0Spatrick       return false;
32373471bf0Spatrick   }
32473471bf0Spatrick 
32573471bf0Spatrick   return true;
32673471bf0Spatrick }
32773471bf0Spatrick 
getFPPredicateFromMD(const Value * Op)328*d415bd75Srobert static FCmpInst::Predicate getFPPredicateFromMD(const Value *Op) {
329*d415bd75Srobert   Metadata *MD = cast<MetadataAsValue>(Op)->getMetadata();
33009467b48Spatrick   if (!MD || !isa<MDString>(MD))
33109467b48Spatrick     return FCmpInst::BAD_FCMP_PREDICATE;
33209467b48Spatrick   return StringSwitch<FCmpInst::Predicate>(cast<MDString>(MD)->getString())
33309467b48Spatrick       .Case("oeq", FCmpInst::FCMP_OEQ)
33409467b48Spatrick       .Case("ogt", FCmpInst::FCMP_OGT)
33509467b48Spatrick       .Case("oge", FCmpInst::FCMP_OGE)
33609467b48Spatrick       .Case("olt", FCmpInst::FCMP_OLT)
33709467b48Spatrick       .Case("ole", FCmpInst::FCMP_OLE)
33809467b48Spatrick       .Case("one", FCmpInst::FCMP_ONE)
33909467b48Spatrick       .Case("ord", FCmpInst::FCMP_ORD)
34009467b48Spatrick       .Case("uno", FCmpInst::FCMP_UNO)
34109467b48Spatrick       .Case("ueq", FCmpInst::FCMP_UEQ)
34209467b48Spatrick       .Case("ugt", FCmpInst::FCMP_UGT)
34309467b48Spatrick       .Case("uge", FCmpInst::FCMP_UGE)
34409467b48Spatrick       .Case("ult", FCmpInst::FCMP_ULT)
34509467b48Spatrick       .Case("ule", FCmpInst::FCMP_ULE)
34609467b48Spatrick       .Case("une", FCmpInst::FCMP_UNE)
34709467b48Spatrick       .Default(FCmpInst::BAD_FCMP_PREDICATE);
34809467b48Spatrick }
34909467b48Spatrick 
getPredicate() const350*d415bd75Srobert FCmpInst::Predicate ConstrainedFPCmpIntrinsic::getPredicate() const {
351*d415bd75Srobert   return getFPPredicateFromMD(getArgOperand(2));
352*d415bd75Srobert }
353*d415bd75Srobert 
isUnaryOp() const35409467b48Spatrick bool ConstrainedFPIntrinsic::isUnaryOp() const {
35509467b48Spatrick   switch (getIntrinsicID()) {
35609467b48Spatrick   default:
35709467b48Spatrick     return false;
358097a140dSpatrick #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC)                         \
35909467b48Spatrick   case Intrinsic::INTRINSIC:                                                   \
36009467b48Spatrick     return NARG == 1;
36109467b48Spatrick #include "llvm/IR/ConstrainedOps.def"
36209467b48Spatrick   }
36309467b48Spatrick }
36409467b48Spatrick 
isTernaryOp() const36509467b48Spatrick bool ConstrainedFPIntrinsic::isTernaryOp() const {
36609467b48Spatrick   switch (getIntrinsicID()) {
36709467b48Spatrick   default:
36809467b48Spatrick     return false;
369097a140dSpatrick #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC)                         \
37009467b48Spatrick   case Intrinsic::INTRINSIC:                                                   \
37109467b48Spatrick     return NARG == 3;
37209467b48Spatrick #include "llvm/IR/ConstrainedOps.def"
37309467b48Spatrick   }
37409467b48Spatrick }
37509467b48Spatrick 
classof(const IntrinsicInst * I)37609467b48Spatrick bool ConstrainedFPIntrinsic::classof(const IntrinsicInst *I) {
37709467b48Spatrick   switch (I->getIntrinsicID()) {
378097a140dSpatrick #define INSTRUCTION(NAME, NARGS, ROUND_MODE, INTRINSIC)                        \
37909467b48Spatrick   case Intrinsic::INTRINSIC:
38009467b48Spatrick #include "llvm/IR/ConstrainedOps.def"
38109467b48Spatrick     return true;
38209467b48Spatrick   default:
38309467b48Spatrick     return false;
38409467b48Spatrick   }
38509467b48Spatrick }
38609467b48Spatrick 
getStaticVectorLength() const387097a140dSpatrick ElementCount VPIntrinsic::getStaticVectorLength() const {
388097a140dSpatrick   auto GetVectorLengthOfType = [](const Type *T) -> ElementCount {
38973471bf0Spatrick     const auto *VT = cast<VectorType>(T);
390097a140dSpatrick     auto ElemCount = VT->getElementCount();
391097a140dSpatrick     return ElemCount;
392097a140dSpatrick   };
393097a140dSpatrick 
39473471bf0Spatrick   Value *VPMask = getMaskParam();
395*d415bd75Srobert   if (!VPMask) {
396*d415bd75Srobert     assert((getIntrinsicID() == Intrinsic::vp_merge ||
397*d415bd75Srobert             getIntrinsicID() == Intrinsic::vp_select) &&
398*d415bd75Srobert            "Unexpected VP intrinsic without mask operand");
399*d415bd75Srobert     return GetVectorLengthOfType(getType());
400*d415bd75Srobert   }
401097a140dSpatrick   return GetVectorLengthOfType(VPMask->getType());
402097a140dSpatrick }
403097a140dSpatrick 
getMaskParam() const404097a140dSpatrick Value *VPIntrinsic::getMaskParam() const {
40573471bf0Spatrick   if (auto MaskPos = getMaskParamPos(getIntrinsicID()))
406*d415bd75Srobert     return getArgOperand(*MaskPos);
407097a140dSpatrick   return nullptr;
408097a140dSpatrick }
409097a140dSpatrick 
setMaskParam(Value * NewMask)41073471bf0Spatrick void VPIntrinsic::setMaskParam(Value *NewMask) {
41173471bf0Spatrick   auto MaskPos = getMaskParamPos(getIntrinsicID());
41273471bf0Spatrick   setArgOperand(*MaskPos, NewMask);
41373471bf0Spatrick }
41473471bf0Spatrick 
getVectorLengthParam() const415097a140dSpatrick Value *VPIntrinsic::getVectorLengthParam() const {
41673471bf0Spatrick   if (auto EVLPos = getVectorLengthParamPos(getIntrinsicID()))
417*d415bd75Srobert     return getArgOperand(*EVLPos);
418097a140dSpatrick   return nullptr;
419097a140dSpatrick }
420097a140dSpatrick 
setVectorLengthParam(Value * NewEVL)42173471bf0Spatrick void VPIntrinsic::setVectorLengthParam(Value *NewEVL) {
42273471bf0Spatrick   auto EVLPos = getVectorLengthParamPos(getIntrinsicID());
42373471bf0Spatrick   setArgOperand(*EVLPos, NewEVL);
42473471bf0Spatrick }
42573471bf0Spatrick 
426*d415bd75Srobert std::optional<unsigned>
getMaskParamPos(Intrinsic::ID IntrinsicID)427*d415bd75Srobert VPIntrinsic::getMaskParamPos(Intrinsic::ID IntrinsicID) {
428097a140dSpatrick   switch (IntrinsicID) {
429097a140dSpatrick   default:
430*d415bd75Srobert     return std::nullopt;
431097a140dSpatrick 
43273471bf0Spatrick #define BEGIN_REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS)                    \
433097a140dSpatrick   case Intrinsic::VPID:                                                        \
434097a140dSpatrick     return MASKPOS;
435097a140dSpatrick #include "llvm/IR/VPIntrinsics.def"
436097a140dSpatrick   }
437097a140dSpatrick }
438097a140dSpatrick 
439*d415bd75Srobert std::optional<unsigned>
getVectorLengthParamPos(Intrinsic::ID IntrinsicID)44073471bf0Spatrick VPIntrinsic::getVectorLengthParamPos(Intrinsic::ID IntrinsicID) {
441097a140dSpatrick   switch (IntrinsicID) {
442097a140dSpatrick   default:
443*d415bd75Srobert     return std::nullopt;
444097a140dSpatrick 
44573471bf0Spatrick #define BEGIN_REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS)                    \
446097a140dSpatrick   case Intrinsic::VPID:                                                        \
447097a140dSpatrick     return VLENPOS;
448097a140dSpatrick #include "llvm/IR/VPIntrinsics.def"
449097a140dSpatrick   }
450097a140dSpatrick }
451097a140dSpatrick 
45273471bf0Spatrick /// \return the alignment of the pointer used by this load/store/gather or
45373471bf0Spatrick /// scatter.
getPointerAlignment() const45473471bf0Spatrick MaybeAlign VPIntrinsic::getPointerAlignment() const {
455*d415bd75Srobert   std::optional<unsigned> PtrParamOpt =
456*d415bd75Srobert       getMemoryPointerParamPos(getIntrinsicID());
457*d415bd75Srobert   assert(PtrParamOpt && "no pointer argument!");
458*d415bd75Srobert   return getParamAlign(*PtrParamOpt);
45973471bf0Spatrick }
46073471bf0Spatrick 
46173471bf0Spatrick /// \return The pointer operand of this load,store, gather or scatter.
getMemoryPointerParam() const46273471bf0Spatrick Value *VPIntrinsic::getMemoryPointerParam() const {
46373471bf0Spatrick   if (auto PtrParamOpt = getMemoryPointerParamPos(getIntrinsicID()))
464*d415bd75Srobert     return getArgOperand(*PtrParamOpt);
46573471bf0Spatrick   return nullptr;
46673471bf0Spatrick }
46773471bf0Spatrick 
468*d415bd75Srobert std::optional<unsigned>
getMemoryPointerParamPos(Intrinsic::ID VPID)469*d415bd75Srobert VPIntrinsic::getMemoryPointerParamPos(Intrinsic::ID VPID) {
47073471bf0Spatrick   switch (VPID) {
47173471bf0Spatrick   default:
472*d415bd75Srobert     break;
473*d415bd75Srobert #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
474*d415bd75Srobert #define VP_PROPERTY_MEMOP(POINTERPOS, ...) return POINTERPOS;
475*d415bd75Srobert #define END_REGISTER_VP_INTRINSIC(VPID) break;
47673471bf0Spatrick #include "llvm/IR/VPIntrinsics.def"
47773471bf0Spatrick   }
478*d415bd75Srobert   return std::nullopt;
47973471bf0Spatrick }
48073471bf0Spatrick 
48173471bf0Spatrick /// \return The data (payload) operand of this store or scatter.
getMemoryDataParam() const48273471bf0Spatrick Value *VPIntrinsic::getMemoryDataParam() const {
48373471bf0Spatrick   auto DataParamOpt = getMemoryDataParamPos(getIntrinsicID());
484*d415bd75Srobert   if (!DataParamOpt)
48573471bf0Spatrick     return nullptr;
486*d415bd75Srobert   return getArgOperand(*DataParamOpt);
48773471bf0Spatrick }
48873471bf0Spatrick 
getMemoryDataParamPos(Intrinsic::ID VPID)489*d415bd75Srobert std::optional<unsigned> VPIntrinsic::getMemoryDataParamPos(Intrinsic::ID VPID) {
49073471bf0Spatrick   switch (VPID) {
49173471bf0Spatrick   default:
492*d415bd75Srobert     break;
493*d415bd75Srobert #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
494*d415bd75Srobert #define VP_PROPERTY_MEMOP(POINTERPOS, DATAPOS) return DATAPOS;
495*d415bd75Srobert #define END_REGISTER_VP_INTRINSIC(VPID) break;
49673471bf0Spatrick #include "llvm/IR/VPIntrinsics.def"
49773471bf0Spatrick   }
498*d415bd75Srobert   return std::nullopt;
49973471bf0Spatrick }
50073471bf0Spatrick 
isVPIntrinsic(Intrinsic::ID ID)50173471bf0Spatrick bool VPIntrinsic::isVPIntrinsic(Intrinsic::ID ID) {
502097a140dSpatrick   switch (ID) {
503097a140dSpatrick   default:
504*d415bd75Srobert     break;
50573471bf0Spatrick #define BEGIN_REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS)                    \
506097a140dSpatrick   case Intrinsic::VPID:                                                        \
507*d415bd75Srobert     return true;
508097a140dSpatrick #include "llvm/IR/VPIntrinsics.def"
509097a140dSpatrick   }
510*d415bd75Srobert   return false;
511097a140dSpatrick }
512097a140dSpatrick 
513097a140dSpatrick // Equivalent non-predicated opcode
514*d415bd75Srobert std::optional<unsigned>
getFunctionalOpcodeForVP(Intrinsic::ID ID)515*d415bd75Srobert VPIntrinsic::getFunctionalOpcodeForVP(Intrinsic::ID ID) {
516097a140dSpatrick   switch (ID) {
517097a140dSpatrick   default:
51873471bf0Spatrick     break;
51973471bf0Spatrick #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
520*d415bd75Srobert #define VP_PROPERTY_FUNCTIONAL_OPC(OPC) return Instruction::OPC;
521*d415bd75Srobert #define END_REGISTER_VP_INTRINSIC(VPID) break;
522097a140dSpatrick #include "llvm/IR/VPIntrinsics.def"
523097a140dSpatrick   }
524*d415bd75Srobert   return std::nullopt;
525097a140dSpatrick }
526097a140dSpatrick 
getForOpcode(unsigned IROPC)52773471bf0Spatrick Intrinsic::ID VPIntrinsic::getForOpcode(unsigned IROPC) {
52873471bf0Spatrick   switch (IROPC) {
529097a140dSpatrick   default:
530*d415bd75Srobert     break;
531097a140dSpatrick 
532*d415bd75Srobert #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) break;
533*d415bd75Srobert #define VP_PROPERTY_FUNCTIONAL_OPC(OPC) case Instruction::OPC:
53473471bf0Spatrick #define END_REGISTER_VP_INTRINSIC(VPID) return Intrinsic::VPID;
535097a140dSpatrick #include "llvm/IR/VPIntrinsics.def"
536097a140dSpatrick   }
537*d415bd75Srobert   return Intrinsic::not_intrinsic;
538097a140dSpatrick }
539097a140dSpatrick 
canIgnoreVectorLengthParam() const540097a140dSpatrick bool VPIntrinsic::canIgnoreVectorLengthParam() const {
541097a140dSpatrick   using namespace PatternMatch;
542097a140dSpatrick 
543097a140dSpatrick   ElementCount EC = getStaticVectorLength();
544097a140dSpatrick 
545097a140dSpatrick   // No vlen param - no lanes masked-off by it.
546097a140dSpatrick   auto *VLParam = getVectorLengthParam();
547097a140dSpatrick   if (!VLParam)
548097a140dSpatrick     return true;
549097a140dSpatrick 
550097a140dSpatrick   // Note that the VP intrinsic causes undefined behavior if the Explicit Vector
551097a140dSpatrick   // Length parameter is strictly greater-than the number of vector elements of
552097a140dSpatrick   // the operation. This function returns true when this is detected statically
553097a140dSpatrick   // in the IR.
554097a140dSpatrick 
55573471bf0Spatrick   // Check whether "W == vscale * EC.getKnownMinValue()"
55673471bf0Spatrick   if (EC.isScalable()) {
557097a140dSpatrick     // Undig the DL
55873471bf0Spatrick     const auto *ParMod = this->getModule();
559097a140dSpatrick     if (!ParMod)
560097a140dSpatrick       return false;
561097a140dSpatrick     const auto &DL = ParMod->getDataLayout();
562097a140dSpatrick 
563097a140dSpatrick     // Compare vscale patterns
564097a140dSpatrick     uint64_t VScaleFactor;
565097a140dSpatrick     if (match(VLParam, m_c_Mul(m_ConstantInt(VScaleFactor), m_VScale(DL))))
56673471bf0Spatrick       return VScaleFactor >= EC.getKnownMinValue();
56773471bf0Spatrick     return (EC.getKnownMinValue() == 1) && match(VLParam, m_VScale(DL));
568097a140dSpatrick   }
569097a140dSpatrick 
570097a140dSpatrick   // standard SIMD operation
57173471bf0Spatrick   const auto *VLConst = dyn_cast<ConstantInt>(VLParam);
572097a140dSpatrick   if (!VLConst)
573097a140dSpatrick     return false;
574097a140dSpatrick 
575097a140dSpatrick   uint64_t VLNum = VLConst->getZExtValue();
57673471bf0Spatrick   if (VLNum >= EC.getKnownMinValue())
577097a140dSpatrick     return true;
578097a140dSpatrick 
579097a140dSpatrick   return false;
580097a140dSpatrick }
581097a140dSpatrick 
getDeclarationForParams(Module * M,Intrinsic::ID VPID,Type * ReturnType,ArrayRef<Value * > Params)58273471bf0Spatrick Function *VPIntrinsic::getDeclarationForParams(Module *M, Intrinsic::ID VPID,
583*d415bd75Srobert                                                Type *ReturnType,
58473471bf0Spatrick                                                ArrayRef<Value *> Params) {
58573471bf0Spatrick   assert(isVPIntrinsic(VPID) && "not a VP intrinsic");
58673471bf0Spatrick   Function *VPFunc;
58773471bf0Spatrick   switch (VPID) {
588*d415bd75Srobert   default: {
589*d415bd75Srobert     Type *OverloadTy = Params[0]->getType();
590*d415bd75Srobert     if (VPReductionIntrinsic::isVPReduction(VPID))
591*d415bd75Srobert       OverloadTy =
592*d415bd75Srobert           Params[*VPReductionIntrinsic::getVectorParamPos(VPID)]->getType();
593*d415bd75Srobert 
594*d415bd75Srobert     VPFunc = Intrinsic::getDeclaration(M, VPID, OverloadTy);
595*d415bd75Srobert     break;
596*d415bd75Srobert   }
597*d415bd75Srobert   case Intrinsic::vp_trunc:
598*d415bd75Srobert   case Intrinsic::vp_sext:
599*d415bd75Srobert   case Intrinsic::vp_zext:
600*d415bd75Srobert   case Intrinsic::vp_fptoui:
601*d415bd75Srobert   case Intrinsic::vp_fptosi:
602*d415bd75Srobert   case Intrinsic::vp_uitofp:
603*d415bd75Srobert   case Intrinsic::vp_sitofp:
604*d415bd75Srobert   case Intrinsic::vp_fptrunc:
605*d415bd75Srobert   case Intrinsic::vp_fpext:
606*d415bd75Srobert   case Intrinsic::vp_ptrtoint:
607*d415bd75Srobert   case Intrinsic::vp_inttoptr:
608*d415bd75Srobert     VPFunc =
609*d415bd75Srobert         Intrinsic::getDeclaration(M, VPID, {ReturnType, Params[0]->getType()});
610*d415bd75Srobert     break;
611*d415bd75Srobert   case Intrinsic::vp_merge:
612*d415bd75Srobert   case Intrinsic::vp_select:
613*d415bd75Srobert     VPFunc = Intrinsic::getDeclaration(M, VPID, {Params[1]->getType()});
61473471bf0Spatrick     break;
61573471bf0Spatrick   case Intrinsic::vp_load:
61673471bf0Spatrick     VPFunc = Intrinsic::getDeclaration(
617*d415bd75Srobert         M, VPID, {ReturnType, Params[0]->getType()});
618*d415bd75Srobert     break;
619*d415bd75Srobert   case Intrinsic::experimental_vp_strided_load:
620*d415bd75Srobert     VPFunc = Intrinsic::getDeclaration(
621*d415bd75Srobert         M, VPID, {ReturnType, Params[0]->getType(), Params[1]->getType()});
62273471bf0Spatrick     break;
62373471bf0Spatrick   case Intrinsic::vp_gather:
62473471bf0Spatrick     VPFunc = Intrinsic::getDeclaration(
625*d415bd75Srobert         M, VPID, {ReturnType, Params[0]->getType()});
62673471bf0Spatrick     break;
62773471bf0Spatrick   case Intrinsic::vp_store:
62873471bf0Spatrick     VPFunc = Intrinsic::getDeclaration(
629*d415bd75Srobert         M, VPID, {Params[0]->getType(), Params[1]->getType()});
630*d415bd75Srobert     break;
631*d415bd75Srobert   case Intrinsic::experimental_vp_strided_store:
632*d415bd75Srobert     VPFunc = Intrinsic::getDeclaration(
63373471bf0Spatrick         M, VPID,
634*d415bd75Srobert         {Params[0]->getType(), Params[1]->getType(), Params[2]->getType()});
63573471bf0Spatrick     break;
63673471bf0Spatrick   case Intrinsic::vp_scatter:
63773471bf0Spatrick     VPFunc = Intrinsic::getDeclaration(
63873471bf0Spatrick         M, VPID, {Params[0]->getType(), Params[1]->getType()});
63973471bf0Spatrick     break;
64073471bf0Spatrick   }
64173471bf0Spatrick   assert(VPFunc && "Could not declare VP intrinsic");
64273471bf0Spatrick   return VPFunc;
64373471bf0Spatrick }
64473471bf0Spatrick 
isVPReduction(Intrinsic::ID ID)645*d415bd75Srobert bool VPReductionIntrinsic::isVPReduction(Intrinsic::ID ID) {
646*d415bd75Srobert   switch (ID) {
647*d415bd75Srobert   default:
648*d415bd75Srobert     break;
649*d415bd75Srobert #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
650*d415bd75Srobert #define VP_PROPERTY_REDUCTION(STARTPOS, ...) return true;
651*d415bd75Srobert #define END_REGISTER_VP_INTRINSIC(VPID) break;
652*d415bd75Srobert #include "llvm/IR/VPIntrinsics.def"
653*d415bd75Srobert   }
654*d415bd75Srobert   return false;
655*d415bd75Srobert }
656*d415bd75Srobert 
isVPCast(Intrinsic::ID ID)657*d415bd75Srobert bool VPCastIntrinsic::isVPCast(Intrinsic::ID ID) {
658*d415bd75Srobert   switch (ID) {
659*d415bd75Srobert   default:
660*d415bd75Srobert     break;
661*d415bd75Srobert #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
662*d415bd75Srobert #define VP_PROPERTY_CASTOP return true;
663*d415bd75Srobert #define END_REGISTER_VP_INTRINSIC(VPID) break;
664*d415bd75Srobert #include "llvm/IR/VPIntrinsics.def"
665*d415bd75Srobert   }
666*d415bd75Srobert   return false;
667*d415bd75Srobert }
668*d415bd75Srobert 
isVPCmp(Intrinsic::ID ID)669*d415bd75Srobert bool VPCmpIntrinsic::isVPCmp(Intrinsic::ID ID) {
670*d415bd75Srobert   switch (ID) {
671*d415bd75Srobert   default:
672*d415bd75Srobert     break;
673*d415bd75Srobert #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
674*d415bd75Srobert #define VP_PROPERTY_CMP(CCPOS, ...) return true;
675*d415bd75Srobert #define END_REGISTER_VP_INTRINSIC(VPID) break;
676*d415bd75Srobert #include "llvm/IR/VPIntrinsics.def"
677*d415bd75Srobert   }
678*d415bd75Srobert   return false;
679*d415bd75Srobert }
680*d415bd75Srobert 
getIntPredicateFromMD(const Value * Op)681*d415bd75Srobert static ICmpInst::Predicate getIntPredicateFromMD(const Value *Op) {
682*d415bd75Srobert   Metadata *MD = cast<MetadataAsValue>(Op)->getMetadata();
683*d415bd75Srobert   if (!MD || !isa<MDString>(MD))
684*d415bd75Srobert     return ICmpInst::BAD_ICMP_PREDICATE;
685*d415bd75Srobert   return StringSwitch<ICmpInst::Predicate>(cast<MDString>(MD)->getString())
686*d415bd75Srobert       .Case("eq", ICmpInst::ICMP_EQ)
687*d415bd75Srobert       .Case("ne", ICmpInst::ICMP_NE)
688*d415bd75Srobert       .Case("ugt", ICmpInst::ICMP_UGT)
689*d415bd75Srobert       .Case("uge", ICmpInst::ICMP_UGE)
690*d415bd75Srobert       .Case("ult", ICmpInst::ICMP_ULT)
691*d415bd75Srobert       .Case("ule", ICmpInst::ICMP_ULE)
692*d415bd75Srobert       .Case("sgt", ICmpInst::ICMP_SGT)
693*d415bd75Srobert       .Case("sge", ICmpInst::ICMP_SGE)
694*d415bd75Srobert       .Case("slt", ICmpInst::ICMP_SLT)
695*d415bd75Srobert       .Case("sle", ICmpInst::ICMP_SLE)
696*d415bd75Srobert       .Default(ICmpInst::BAD_ICMP_PREDICATE);
697*d415bd75Srobert }
698*d415bd75Srobert 
getPredicate() const699*d415bd75Srobert CmpInst::Predicate VPCmpIntrinsic::getPredicate() const {
700*d415bd75Srobert   bool IsFP = true;
701*d415bd75Srobert   std::optional<unsigned> CCArgIdx;
702*d415bd75Srobert   switch (getIntrinsicID()) {
703*d415bd75Srobert   default:
704*d415bd75Srobert     break;
705*d415bd75Srobert #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
706*d415bd75Srobert #define VP_PROPERTY_CMP(CCPOS, ISFP)                                           \
707*d415bd75Srobert   CCArgIdx = CCPOS;                                                            \
708*d415bd75Srobert   IsFP = ISFP;                                                                 \
709*d415bd75Srobert   break;
710*d415bd75Srobert #define END_REGISTER_VP_INTRINSIC(VPID) break;
711*d415bd75Srobert #include "llvm/IR/VPIntrinsics.def"
712*d415bd75Srobert   }
713*d415bd75Srobert   assert(CCArgIdx && "Unexpected vector-predicated comparison");
714*d415bd75Srobert   return IsFP ? getFPPredicateFromMD(getArgOperand(*CCArgIdx))
715*d415bd75Srobert               : getIntPredicateFromMD(getArgOperand(*CCArgIdx));
716*d415bd75Srobert }
717*d415bd75Srobert 
getVectorParamPos() const718*d415bd75Srobert unsigned VPReductionIntrinsic::getVectorParamPos() const {
719*d415bd75Srobert   return *VPReductionIntrinsic::getVectorParamPos(getIntrinsicID());
720*d415bd75Srobert }
721*d415bd75Srobert 
getStartParamPos() const722*d415bd75Srobert unsigned VPReductionIntrinsic::getStartParamPos() const {
723*d415bd75Srobert   return *VPReductionIntrinsic::getStartParamPos(getIntrinsicID());
724*d415bd75Srobert }
725*d415bd75Srobert 
726*d415bd75Srobert std::optional<unsigned>
getVectorParamPos(Intrinsic::ID ID)727*d415bd75Srobert VPReductionIntrinsic::getVectorParamPos(Intrinsic::ID ID) {
728*d415bd75Srobert   switch (ID) {
729*d415bd75Srobert #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
730*d415bd75Srobert #define VP_PROPERTY_REDUCTION(STARTPOS, VECTORPOS) return VECTORPOS;
731*d415bd75Srobert #define END_REGISTER_VP_INTRINSIC(VPID) break;
732*d415bd75Srobert #include "llvm/IR/VPIntrinsics.def"
733*d415bd75Srobert   default:
734*d415bd75Srobert     break;
735*d415bd75Srobert   }
736*d415bd75Srobert   return std::nullopt;
737*d415bd75Srobert }
738*d415bd75Srobert 
739*d415bd75Srobert std::optional<unsigned>
getStartParamPos(Intrinsic::ID ID)740*d415bd75Srobert VPReductionIntrinsic::getStartParamPos(Intrinsic::ID ID) {
741*d415bd75Srobert   switch (ID) {
742*d415bd75Srobert #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
743*d415bd75Srobert #define VP_PROPERTY_REDUCTION(STARTPOS, VECTORPOS) return STARTPOS;
744*d415bd75Srobert #define END_REGISTER_VP_INTRINSIC(VPID) break;
745*d415bd75Srobert #include "llvm/IR/VPIntrinsics.def"
746*d415bd75Srobert   default:
747*d415bd75Srobert     break;
748*d415bd75Srobert   }
749*d415bd75Srobert   return std::nullopt;
750*d415bd75Srobert }
751*d415bd75Srobert 
getBinaryOp() const75209467b48Spatrick Instruction::BinaryOps BinaryOpIntrinsic::getBinaryOp() const {
75309467b48Spatrick   switch (getIntrinsicID()) {
75409467b48Spatrick   case Intrinsic::uadd_with_overflow:
75509467b48Spatrick   case Intrinsic::sadd_with_overflow:
75609467b48Spatrick   case Intrinsic::uadd_sat:
75709467b48Spatrick   case Intrinsic::sadd_sat:
75809467b48Spatrick     return Instruction::Add;
75909467b48Spatrick   case Intrinsic::usub_with_overflow:
76009467b48Spatrick   case Intrinsic::ssub_with_overflow:
76109467b48Spatrick   case Intrinsic::usub_sat:
76209467b48Spatrick   case Intrinsic::ssub_sat:
76309467b48Spatrick     return Instruction::Sub;
76409467b48Spatrick   case Intrinsic::umul_with_overflow:
76509467b48Spatrick   case Intrinsic::smul_with_overflow:
76609467b48Spatrick     return Instruction::Mul;
76709467b48Spatrick   default:
76809467b48Spatrick     llvm_unreachable("Invalid intrinsic");
76909467b48Spatrick   }
77009467b48Spatrick }
77109467b48Spatrick 
isSigned() const77209467b48Spatrick bool BinaryOpIntrinsic::isSigned() const {
77309467b48Spatrick   switch (getIntrinsicID()) {
77409467b48Spatrick   case Intrinsic::sadd_with_overflow:
77509467b48Spatrick   case Intrinsic::ssub_with_overflow:
77609467b48Spatrick   case Intrinsic::smul_with_overflow:
77709467b48Spatrick   case Intrinsic::sadd_sat:
77809467b48Spatrick   case Intrinsic::ssub_sat:
77909467b48Spatrick     return true;
78009467b48Spatrick   default:
78109467b48Spatrick     return false;
78209467b48Spatrick   }
78309467b48Spatrick }
78409467b48Spatrick 
getNoWrapKind() const78509467b48Spatrick unsigned BinaryOpIntrinsic::getNoWrapKind() const {
78609467b48Spatrick   if (isSigned())
78709467b48Spatrick     return OverflowingBinaryOperator::NoSignedWrap;
78809467b48Spatrick   else
78909467b48Spatrick     return OverflowingBinaryOperator::NoUnsignedWrap;
79009467b48Spatrick }
79173471bf0Spatrick 
getStatepoint() const792*d415bd75Srobert const Value *GCProjectionInst::getStatepoint() const {
79373471bf0Spatrick   const Value *Token = getArgOperand(0);
794*d415bd75Srobert   if (isa<UndefValue>(Token))
795*d415bd75Srobert     return Token;
79673471bf0Spatrick 
79773471bf0Spatrick   // This takes care both of relocates for call statepoints and relocates
79873471bf0Spatrick   // on normal path of invoke statepoint.
79973471bf0Spatrick   if (!isa<LandingPadInst>(Token))
80073471bf0Spatrick     return cast<GCStatepointInst>(Token);
80173471bf0Spatrick 
80273471bf0Spatrick   // This relocate is on exceptional path of an invoke statepoint
80373471bf0Spatrick   const BasicBlock *InvokeBB =
80473471bf0Spatrick     cast<Instruction>(Token)->getParent()->getUniquePredecessor();
80573471bf0Spatrick 
80673471bf0Spatrick   assert(InvokeBB && "safepoints should have unique landingpads");
80773471bf0Spatrick   assert(InvokeBB->getTerminator() &&
80873471bf0Spatrick          "safepoint block should be well formed");
80973471bf0Spatrick 
81073471bf0Spatrick   return cast<GCStatepointInst>(InvokeBB->getTerminator());
81173471bf0Spatrick }
81273471bf0Spatrick 
getBasePtr() const81373471bf0Spatrick Value *GCRelocateInst::getBasePtr() const {
814*d415bd75Srobert   auto Statepoint = getStatepoint();
815*d415bd75Srobert   if (isa<UndefValue>(Statepoint))
816*d415bd75Srobert     return UndefValue::get(Statepoint->getType());
817*d415bd75Srobert 
818*d415bd75Srobert   auto *GCInst = cast<GCStatepointInst>(Statepoint);
819*d415bd75Srobert   if (auto Opt = GCInst->getOperandBundle(LLVMContext::OB_gc_live))
82073471bf0Spatrick     return *(Opt->Inputs.begin() + getBasePtrIndex());
821*d415bd75Srobert   return *(GCInst->arg_begin() + getBasePtrIndex());
82273471bf0Spatrick }
82373471bf0Spatrick 
getDerivedPtr() const82473471bf0Spatrick Value *GCRelocateInst::getDerivedPtr() const {
825*d415bd75Srobert   auto *Statepoint = getStatepoint();
826*d415bd75Srobert   if (isa<UndefValue>(Statepoint))
827*d415bd75Srobert     return UndefValue::get(Statepoint->getType());
828*d415bd75Srobert 
829*d415bd75Srobert   auto *GCInst = cast<GCStatepointInst>(Statepoint);
830*d415bd75Srobert   if (auto Opt = GCInst->getOperandBundle(LLVMContext::OB_gc_live))
83173471bf0Spatrick     return *(Opt->Inputs.begin() + getDerivedPtrIndex());
832*d415bd75Srobert   return *(GCInst->arg_begin() + getDerivedPtrIndex());
83373471bf0Spatrick }
834