xref: /freebsd-src/contrib/llvm-project/llvm/lib/IR/IntrinsicInst.cpp (revision 52418fc2be8efa5172b90a3a9e617017173612c4)
1fe6060f1SDimitry Andric //===-- IntrinsicInst.cpp - Intrinsic Instruction Wrappers ---------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements methods that make it really easy to deal with intrinsic
100b57cec5SDimitry Andric // functions.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric // All intrinsic function calls are instances of the call instruction, so these
130b57cec5SDimitry Andric // are all subclasses of the CallInst class.  Note that none of these classes
140b57cec5SDimitry Andric // has state or virtual methods, which is an important part of this gross/neat
150b57cec5SDimitry Andric // hack working.
160b57cec5SDimitry Andric //
170b57cec5SDimitry Andric // In some cases, arguments to intrinsics need to be generic and are defined as
180b57cec5SDimitry Andric // type pointer to empty struct { }*.  To access the real item of interest the
190b57cec5SDimitry Andric // cast instruction needs to be stripped away.
200b57cec5SDimitry Andric //
210b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
240b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
250b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
260b57cec5SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
270b57cec5SDimitry Andric #include "llvm/IR/Metadata.h"
280b57cec5SDimitry Andric #include "llvm/IR/Module.h"
295ffd83dbSDimitry Andric #include "llvm/IR/Operator.h"
305ffd83dbSDimitry Andric #include "llvm/IR/PatternMatch.h"
31fe6060f1SDimitry Andric #include "llvm/IR/Statepoint.h"
32bdd1243dSDimitry Andric #include <optional>
335ffd83dbSDimitry Andric 
340b57cec5SDimitry Andric using namespace llvm;
350b57cec5SDimitry Andric 
36972a253aSDimitry Andric bool IntrinsicInst::mayLowerToFunctionCall(Intrinsic::ID IID) {
37972a253aSDimitry Andric   switch (IID) {
38972a253aSDimitry Andric   case Intrinsic::objc_autorelease:
39972a253aSDimitry Andric   case Intrinsic::objc_autoreleasePoolPop:
40972a253aSDimitry Andric   case Intrinsic::objc_autoreleasePoolPush:
41972a253aSDimitry Andric   case Intrinsic::objc_autoreleaseReturnValue:
42972a253aSDimitry Andric   case Intrinsic::objc_copyWeak:
43972a253aSDimitry Andric   case Intrinsic::objc_destroyWeak:
44972a253aSDimitry Andric   case Intrinsic::objc_initWeak:
45972a253aSDimitry Andric   case Intrinsic::objc_loadWeak:
46972a253aSDimitry Andric   case Intrinsic::objc_loadWeakRetained:
47972a253aSDimitry Andric   case Intrinsic::objc_moveWeak:
48972a253aSDimitry Andric   case Intrinsic::objc_release:
49972a253aSDimitry Andric   case Intrinsic::objc_retain:
50972a253aSDimitry Andric   case Intrinsic::objc_retainAutorelease:
51972a253aSDimitry Andric   case Intrinsic::objc_retainAutoreleaseReturnValue:
52972a253aSDimitry Andric   case Intrinsic::objc_retainAutoreleasedReturnValue:
53972a253aSDimitry Andric   case Intrinsic::objc_retainBlock:
54972a253aSDimitry Andric   case Intrinsic::objc_storeStrong:
55972a253aSDimitry Andric   case Intrinsic::objc_storeWeak:
56972a253aSDimitry Andric   case Intrinsic::objc_unsafeClaimAutoreleasedReturnValue:
57972a253aSDimitry Andric   case Intrinsic::objc_retainedObject:
58972a253aSDimitry Andric   case Intrinsic::objc_unretainedObject:
59972a253aSDimitry Andric   case Intrinsic::objc_unretainedPointer:
60972a253aSDimitry Andric   case Intrinsic::objc_retain_autorelease:
61972a253aSDimitry Andric   case Intrinsic::objc_sync_enter:
62972a253aSDimitry Andric   case Intrinsic::objc_sync_exit:
63972a253aSDimitry Andric     return true;
64972a253aSDimitry Andric   default:
65972a253aSDimitry Andric     return false;
66972a253aSDimitry Andric   }
67972a253aSDimitry Andric }
68972a253aSDimitry Andric 
690b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
700b57cec5SDimitry Andric /// DbgVariableIntrinsic - This is the common base class for debug info
710b57cec5SDimitry Andric /// intrinsics for variables.
720b57cec5SDimitry Andric ///
730b57cec5SDimitry Andric 
7406c3fb27SDimitry Andric iterator_range<location_op_iterator> RawLocationWrapper::location_ops() const {
7506c3fb27SDimitry Andric   Metadata *MD = getRawLocation();
76fe6060f1SDimitry Andric   assert(MD && "First operand of DbgVariableIntrinsic should be non-null.");
77fe6060f1SDimitry Andric   // If operand is ValueAsMetadata, return a range over just that operand.
78fe6060f1SDimitry Andric   if (auto *VAM = dyn_cast<ValueAsMetadata>(MD)) {
79fe6060f1SDimitry Andric     return {location_op_iterator(VAM), location_op_iterator(VAM + 1)};
80fe6060f1SDimitry Andric   }
81fe6060f1SDimitry Andric   // If operand is DIArgList, return a range over its args.
82fe6060f1SDimitry Andric   if (auto *AL = dyn_cast<DIArgList>(MD))
83fe6060f1SDimitry Andric     return {location_op_iterator(AL->args_begin()),
84fe6060f1SDimitry Andric             location_op_iterator(AL->args_end())};
85fe6060f1SDimitry Andric   // Operand must be an empty metadata tuple, so return empty iterator.
86fe6060f1SDimitry Andric   return {location_op_iterator(static_cast<ValueAsMetadata *>(nullptr)),
87fe6060f1SDimitry Andric           location_op_iterator(static_cast<ValueAsMetadata *>(nullptr))};
88fe6060f1SDimitry Andric }
89fe6060f1SDimitry Andric 
9006c3fb27SDimitry Andric iterator_range<location_op_iterator>
9106c3fb27SDimitry Andric DbgVariableIntrinsic::location_ops() const {
9206c3fb27SDimitry Andric   return getWrappedLocation().location_ops();
9306c3fb27SDimitry Andric }
9406c3fb27SDimitry Andric 
95fe6060f1SDimitry Andric Value *DbgVariableIntrinsic::getVariableLocationOp(unsigned OpIdx) const {
9606c3fb27SDimitry Andric   return getWrappedLocation().getVariableLocationOp(OpIdx);
9706c3fb27SDimitry Andric }
9806c3fb27SDimitry Andric 
9906c3fb27SDimitry Andric Value *RawLocationWrapper::getVariableLocationOp(unsigned OpIdx) const {
10006c3fb27SDimitry Andric   Metadata *MD = getRawLocation();
101fe6060f1SDimitry Andric   assert(MD && "First operand of DbgVariableIntrinsic should be non-null.");
102fe6060f1SDimitry Andric   if (auto *AL = dyn_cast<DIArgList>(MD))
103fe6060f1SDimitry Andric     return AL->getArgs()[OpIdx]->getValue();
104fe6060f1SDimitry Andric   if (isa<MDNode>(MD))
105fe6060f1SDimitry Andric     return nullptr;
106fe6060f1SDimitry Andric   assert(
107fe6060f1SDimitry Andric       isa<ValueAsMetadata>(MD) &&
108fe6060f1SDimitry Andric       "Attempted to get location operand from DbgVariableIntrinsic with none.");
109fe6060f1SDimitry Andric   auto *V = cast<ValueAsMetadata>(MD);
110fe6060f1SDimitry Andric   assert(OpIdx == 0 && "Operand Index must be 0 for a debug intrinsic with a "
111fe6060f1SDimitry Andric                        "single location operand.");
1120b57cec5SDimitry Andric   return V->getValue();
113fe6060f1SDimitry Andric }
1140b57cec5SDimitry Andric 
115fe6060f1SDimitry Andric static ValueAsMetadata *getAsMetadata(Value *V) {
116fe6060f1SDimitry Andric   return isa<MetadataAsValue>(V) ? dyn_cast<ValueAsMetadata>(
117fe6060f1SDimitry Andric                                        cast<MetadataAsValue>(V)->getMetadata())
118fe6060f1SDimitry Andric                                  : ValueAsMetadata::get(V);
119fe6060f1SDimitry Andric }
120fe6060f1SDimitry Andric 
121fe6060f1SDimitry Andric void DbgVariableIntrinsic::replaceVariableLocationOp(Value *OldValue,
1220fca6ea1SDimitry Andric                                                      Value *NewValue,
1230fca6ea1SDimitry Andric                                                      bool AllowEmpty) {
124bdd1243dSDimitry Andric   // If OldValue is used as the address part of a dbg.assign intrinsic replace
125bdd1243dSDimitry Andric   // it with NewValue and return true.
126bdd1243dSDimitry Andric   auto ReplaceDbgAssignAddress = [this, OldValue, NewValue]() -> bool {
127bdd1243dSDimitry Andric     auto *DAI = dyn_cast<DbgAssignIntrinsic>(this);
128bdd1243dSDimitry Andric     if (!DAI || OldValue != DAI->getAddress())
129bdd1243dSDimitry Andric       return false;
130bdd1243dSDimitry Andric     DAI->setAddress(NewValue);
131bdd1243dSDimitry Andric     return true;
132bdd1243dSDimitry Andric   };
133bdd1243dSDimitry Andric   bool DbgAssignAddrReplaced = ReplaceDbgAssignAddress();
134bdd1243dSDimitry Andric   (void)DbgAssignAddrReplaced;
135bdd1243dSDimitry Andric 
136fe6060f1SDimitry Andric   assert(NewValue && "Values must be non-null");
137fe6060f1SDimitry Andric   auto Locations = location_ops();
138fe6060f1SDimitry Andric   auto OldIt = find(Locations, OldValue);
13906c3fb27SDimitry Andric   if (OldIt == Locations.end()) {
1400fca6ea1SDimitry Andric     if (AllowEmpty || DbgAssignAddrReplaced)
1410fca6ea1SDimitry Andric       return;
14206c3fb27SDimitry Andric     assert(DbgAssignAddrReplaced &&
14306c3fb27SDimitry Andric            "OldValue must be dbg.assign addr if unused in DIArgList");
144bdd1243dSDimitry Andric     return;
14506c3fb27SDimitry Andric   }
14606c3fb27SDimitry Andric 
14706c3fb27SDimitry Andric   assert(OldIt != Locations.end() && "OldValue must be a current location");
14806c3fb27SDimitry Andric   if (!hasArgList()) {
149fe6060f1SDimitry Andric     Value *NewOperand = isa<MetadataAsValue>(NewValue)
150fe6060f1SDimitry Andric                             ? NewValue
151fe6060f1SDimitry Andric                             : MetadataAsValue::get(
152fe6060f1SDimitry Andric                                   getContext(), ValueAsMetadata::get(NewValue));
153fe6060f1SDimitry Andric     return setArgOperand(0, NewOperand);
154fe6060f1SDimitry Andric   }
155fe6060f1SDimitry Andric   SmallVector<ValueAsMetadata *, 4> MDs;
156fe6060f1SDimitry Andric   ValueAsMetadata *NewOperand = getAsMetadata(NewValue);
157fe6060f1SDimitry Andric   for (auto *VMD : Locations)
158fe6060f1SDimitry Andric     MDs.push_back(VMD == *OldIt ? NewOperand : getAsMetadata(VMD));
159fe6060f1SDimitry Andric   setArgOperand(
160fe6060f1SDimitry Andric       0, MetadataAsValue::get(getContext(), DIArgList::get(getContext(), MDs)));
161fe6060f1SDimitry Andric }
162fe6060f1SDimitry Andric void DbgVariableIntrinsic::replaceVariableLocationOp(unsigned OpIdx,
163fe6060f1SDimitry Andric                                                      Value *NewValue) {
164fe6060f1SDimitry Andric   assert(OpIdx < getNumVariableLocationOps() && "Invalid Operand Index");
165fe6060f1SDimitry Andric   if (!hasArgList()) {
166fe6060f1SDimitry Andric     Value *NewOperand = isa<MetadataAsValue>(NewValue)
167fe6060f1SDimitry Andric                             ? NewValue
168fe6060f1SDimitry Andric                             : MetadataAsValue::get(
169fe6060f1SDimitry Andric                                   getContext(), ValueAsMetadata::get(NewValue));
170fe6060f1SDimitry Andric     return setArgOperand(0, NewOperand);
171fe6060f1SDimitry Andric   }
172fe6060f1SDimitry Andric   SmallVector<ValueAsMetadata *, 4> MDs;
173fe6060f1SDimitry Andric   ValueAsMetadata *NewOperand = getAsMetadata(NewValue);
174fe6060f1SDimitry Andric   for (unsigned Idx = 0; Idx < getNumVariableLocationOps(); ++Idx)
175fe6060f1SDimitry Andric     MDs.push_back(Idx == OpIdx ? NewOperand
176fe6060f1SDimitry Andric                                : getAsMetadata(getVariableLocationOp(Idx)));
177fe6060f1SDimitry Andric   setArgOperand(
178fe6060f1SDimitry Andric       0, MetadataAsValue::get(getContext(), DIArgList::get(getContext(), MDs)));
179fe6060f1SDimitry Andric }
180fe6060f1SDimitry Andric 
181fe6060f1SDimitry Andric void DbgVariableIntrinsic::addVariableLocationOps(ArrayRef<Value *> NewValues,
182fe6060f1SDimitry Andric                                                   DIExpression *NewExpr) {
183fe6060f1SDimitry Andric   assert(NewExpr->hasAllLocationOps(getNumVariableLocationOps() +
184fe6060f1SDimitry Andric                                     NewValues.size()) &&
185fe6060f1SDimitry Andric          "NewExpr for debug variable intrinsic does not reference every "
186fe6060f1SDimitry Andric          "location operand.");
187fe6060f1SDimitry Andric   assert(!is_contained(NewValues, nullptr) && "New values must be non-null");
188fe6060f1SDimitry Andric   setArgOperand(2, MetadataAsValue::get(getContext(), NewExpr));
189fe6060f1SDimitry Andric   SmallVector<ValueAsMetadata *, 4> MDs;
190fe6060f1SDimitry Andric   for (auto *VMD : location_ops())
191fe6060f1SDimitry Andric     MDs.push_back(getAsMetadata(VMD));
192fe6060f1SDimitry Andric   for (auto *VMD : NewValues)
193fe6060f1SDimitry Andric     MDs.push_back(getAsMetadata(VMD));
194fe6060f1SDimitry Andric   setArgOperand(
195fe6060f1SDimitry Andric       0, MetadataAsValue::get(getContext(), DIArgList::get(getContext(), MDs)));
1960b57cec5SDimitry Andric }
1970b57cec5SDimitry Andric 
198bdd1243dSDimitry Andric std::optional<uint64_t> DbgVariableIntrinsic::getFragmentSizeInBits() const {
1990b57cec5SDimitry Andric   if (auto Fragment = getExpression()->getFragmentInfo())
2000b57cec5SDimitry Andric     return Fragment->SizeInBits;
2010b57cec5SDimitry Andric   return getVariable()->getSizeInBits();
2020b57cec5SDimitry Andric }
2030b57cec5SDimitry Andric 
204bdd1243dSDimitry Andric Value *DbgAssignIntrinsic::getAddress() const {
205bdd1243dSDimitry Andric   auto *MD = getRawAddress();
206bdd1243dSDimitry Andric   if (auto *V = dyn_cast<ValueAsMetadata>(MD))
207bdd1243dSDimitry Andric     return V->getValue();
208bdd1243dSDimitry Andric 
209bdd1243dSDimitry Andric   // When the value goes to null, it gets replaced by an empty MDNode.
210bdd1243dSDimitry Andric   assert(!cast<MDNode>(MD)->getNumOperands() && "Expected an empty MDNode");
211bdd1243dSDimitry Andric   return nullptr;
212bdd1243dSDimitry Andric }
213bdd1243dSDimitry Andric 
214bdd1243dSDimitry Andric void DbgAssignIntrinsic::setAssignId(DIAssignID *New) {
215bdd1243dSDimitry Andric   setOperand(OpAssignID, MetadataAsValue::get(getContext(), New));
216bdd1243dSDimitry Andric }
217bdd1243dSDimitry Andric 
218bdd1243dSDimitry Andric void DbgAssignIntrinsic::setAddress(Value *V) {
219bdd1243dSDimitry Andric   setOperand(OpAddress,
220bdd1243dSDimitry Andric              MetadataAsValue::get(getContext(), ValueAsMetadata::get(V)));
221bdd1243dSDimitry Andric }
222bdd1243dSDimitry Andric 
223bdd1243dSDimitry Andric void DbgAssignIntrinsic::setKillAddress() {
224bdd1243dSDimitry Andric   if (isKillAddress())
225bdd1243dSDimitry Andric     return;
226bdd1243dSDimitry Andric   setAddress(UndefValue::get(getAddress()->getType()));
227bdd1243dSDimitry Andric }
228bdd1243dSDimitry Andric 
229bdd1243dSDimitry Andric bool DbgAssignIntrinsic::isKillAddress() const {
230bdd1243dSDimitry Andric   Value *Addr = getAddress();
231bdd1243dSDimitry Andric   return !Addr || isa<UndefValue>(Addr);
232bdd1243dSDimitry Andric }
233bdd1243dSDimitry Andric 
234bdd1243dSDimitry Andric void DbgAssignIntrinsic::setValue(Value *V) {
235bdd1243dSDimitry Andric   setOperand(OpValue,
236bdd1243dSDimitry Andric              MetadataAsValue::get(getContext(), ValueAsMetadata::get(V)));
237bdd1243dSDimitry Andric }
238bdd1243dSDimitry Andric 
2390b57cec5SDimitry Andric int llvm::Intrinsic::lookupLLVMIntrinsicByName(ArrayRef<const char *> NameTable,
2400b57cec5SDimitry Andric                                                StringRef Name) {
2415f757f3fSDimitry Andric   assert(Name.starts_with("llvm.") && "Unexpected intrinsic prefix");
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric   // Do successive binary searches of the dotted name components. For
2440b57cec5SDimitry Andric   // "llvm.gc.experimental.statepoint.p1i8.p1i32", we will find the range of
2450b57cec5SDimitry Andric   // intrinsics starting with "llvm.gc", then "llvm.gc.experimental", then
2460b57cec5SDimitry Andric   // "llvm.gc.experimental.statepoint", and then we will stop as the range is
2470b57cec5SDimitry Andric   // size 1. During the search, we can skip the prefix that we already know is
2480b57cec5SDimitry Andric   // identical. By using strncmp we consider names with differing suffixes to
2490b57cec5SDimitry Andric   // be part of the equal range.
2500b57cec5SDimitry Andric   size_t CmpEnd = 4; // Skip the "llvm" component.
2510b57cec5SDimitry Andric   const char *const *Low = NameTable.begin();
2520b57cec5SDimitry Andric   const char *const *High = NameTable.end();
2530b57cec5SDimitry Andric   const char *const *LastLow = Low;
2540b57cec5SDimitry Andric   while (CmpEnd < Name.size() && High - Low > 0) {
2558bcb0991SDimitry Andric     size_t CmpStart = CmpEnd;
2560b57cec5SDimitry Andric     CmpEnd = Name.find('.', CmpStart + 1);
2570b57cec5SDimitry Andric     CmpEnd = CmpEnd == StringRef::npos ? Name.size() : CmpEnd;
2580b57cec5SDimitry Andric     auto Cmp = [CmpStart, CmpEnd](const char *LHS, const char *RHS) {
2590b57cec5SDimitry Andric       return strncmp(LHS + CmpStart, RHS + CmpStart, CmpEnd - CmpStart) < 0;
2600b57cec5SDimitry Andric     };
2610b57cec5SDimitry Andric     LastLow = Low;
2620b57cec5SDimitry Andric     std::tie(Low, High) = std::equal_range(Low, High, Name.data(), Cmp);
2630b57cec5SDimitry Andric   }
2640b57cec5SDimitry Andric   if (High - Low > 0)
2650b57cec5SDimitry Andric     LastLow = Low;
2660b57cec5SDimitry Andric 
2670b57cec5SDimitry Andric   if (LastLow == NameTable.end())
2680b57cec5SDimitry Andric     return -1;
2690b57cec5SDimitry Andric   StringRef NameFound = *LastLow;
2700b57cec5SDimitry Andric   if (Name == NameFound ||
2715f757f3fSDimitry Andric       (Name.starts_with(NameFound) && Name[NameFound.size()] == '.'))
2720b57cec5SDimitry Andric     return LastLow - NameTable.begin();
2730b57cec5SDimitry Andric   return -1;
2740b57cec5SDimitry Andric }
2750b57cec5SDimitry Andric 
2765f757f3fSDimitry Andric ConstantInt *InstrProfCntrInstBase::getNumCounters() const {
27704eeddc0SDimitry Andric   if (InstrProfValueProfileInst::classof(this))
27804eeddc0SDimitry Andric     llvm_unreachable("InstrProfValueProfileInst does not have counters!");
27904eeddc0SDimitry Andric   return cast<ConstantInt>(const_cast<Value *>(getArgOperand(2)));
28004eeddc0SDimitry Andric }
28104eeddc0SDimitry Andric 
2825f757f3fSDimitry Andric ConstantInt *InstrProfCntrInstBase::getIndex() const {
28304eeddc0SDimitry Andric   if (InstrProfValueProfileInst::classof(this))
28404eeddc0SDimitry Andric     llvm_unreachable("Please use InstrProfValueProfileInst::getIndex()");
28504eeddc0SDimitry Andric   return cast<ConstantInt>(const_cast<Value *>(getArgOperand(3)));
28604eeddc0SDimitry Andric }
28704eeddc0SDimitry Andric 
2880b57cec5SDimitry Andric Value *InstrProfIncrementInst::getStep() const {
2890b57cec5SDimitry Andric   if (InstrProfIncrementInstStep::classof(this)) {
2900b57cec5SDimitry Andric     return const_cast<Value *>(getArgOperand(4));
2910b57cec5SDimitry Andric   }
2920b57cec5SDimitry Andric   const Module *M = getModule();
2930b57cec5SDimitry Andric   LLVMContext &Context = M->getContext();
2940b57cec5SDimitry Andric   return ConstantInt::get(Type::getInt64Ty(Context), 1);
2950b57cec5SDimitry Andric }
2960b57cec5SDimitry Andric 
2970fca6ea1SDimitry Andric Value *InstrProfCallsite::getCallee() const {
2980fca6ea1SDimitry Andric   if (isa<InstrProfCallsite>(this))
2990fca6ea1SDimitry Andric     return getArgOperand(4);
3000fca6ea1SDimitry Andric   return nullptr;
3010fca6ea1SDimitry Andric }
3020fca6ea1SDimitry Andric 
303bdd1243dSDimitry Andric std::optional<RoundingMode> ConstrainedFPIntrinsic::getRoundingMode() const {
304349cc55cSDimitry Andric   unsigned NumOperands = arg_size();
305fe6060f1SDimitry Andric   Metadata *MD = nullptr;
306fe6060f1SDimitry Andric   auto *MAV = dyn_cast<MetadataAsValue>(getArgOperand(NumOperands - 2));
307fe6060f1SDimitry Andric   if (MAV)
308fe6060f1SDimitry Andric     MD = MAV->getMetadata();
3090b57cec5SDimitry Andric   if (!MD || !isa<MDString>(MD))
310bdd1243dSDimitry Andric     return std::nullopt;
311349cc55cSDimitry Andric   return convertStrToRoundingMode(cast<MDString>(MD)->getString());
3120b57cec5SDimitry Andric }
3130b57cec5SDimitry Andric 
314bdd1243dSDimitry Andric std::optional<fp::ExceptionBehavior>
3150b57cec5SDimitry Andric ConstrainedFPIntrinsic::getExceptionBehavior() const {
316349cc55cSDimitry Andric   unsigned NumOperands = arg_size();
317fe6060f1SDimitry Andric   Metadata *MD = nullptr;
318fe6060f1SDimitry Andric   auto *MAV = dyn_cast<MetadataAsValue>(getArgOperand(NumOperands - 1));
319fe6060f1SDimitry Andric   if (MAV)
320fe6060f1SDimitry Andric     MD = MAV->getMetadata();
3210b57cec5SDimitry Andric   if (!MD || !isa<MDString>(MD))
322bdd1243dSDimitry Andric     return std::nullopt;
323349cc55cSDimitry Andric   return convertStrToExceptionBehavior(cast<MDString>(MD)->getString());
3240b57cec5SDimitry Andric }
3250b57cec5SDimitry Andric 
326fe6060f1SDimitry Andric bool ConstrainedFPIntrinsic::isDefaultFPEnvironment() const {
327bdd1243dSDimitry Andric   std::optional<fp::ExceptionBehavior> Except = getExceptionBehavior();
328fe6060f1SDimitry Andric   if (Except) {
329bdd1243dSDimitry Andric     if (*Except != fp::ebIgnore)
330fe6060f1SDimitry Andric       return false;
331fe6060f1SDimitry Andric   }
332fe6060f1SDimitry Andric 
333bdd1243dSDimitry Andric   std::optional<RoundingMode> Rounding = getRoundingMode();
334fe6060f1SDimitry Andric   if (Rounding) {
335bdd1243dSDimitry Andric     if (*Rounding != RoundingMode::NearestTiesToEven)
336fe6060f1SDimitry Andric       return false;
337fe6060f1SDimitry Andric   }
338fe6060f1SDimitry Andric 
339fe6060f1SDimitry Andric   return true;
340fe6060f1SDimitry Andric }
341fe6060f1SDimitry Andric 
34281ad6265SDimitry Andric static FCmpInst::Predicate getFPPredicateFromMD(const Value *Op) {
34381ad6265SDimitry Andric   Metadata *MD = cast<MetadataAsValue>(Op)->getMetadata();
344480093f4SDimitry Andric   if (!MD || !isa<MDString>(MD))
345480093f4SDimitry Andric     return FCmpInst::BAD_FCMP_PREDICATE;
346480093f4SDimitry Andric   return StringSwitch<FCmpInst::Predicate>(cast<MDString>(MD)->getString())
347480093f4SDimitry Andric       .Case("oeq", FCmpInst::FCMP_OEQ)
348480093f4SDimitry Andric       .Case("ogt", FCmpInst::FCMP_OGT)
349480093f4SDimitry Andric       .Case("oge", FCmpInst::FCMP_OGE)
350480093f4SDimitry Andric       .Case("olt", FCmpInst::FCMP_OLT)
351480093f4SDimitry Andric       .Case("ole", FCmpInst::FCMP_OLE)
352480093f4SDimitry Andric       .Case("one", FCmpInst::FCMP_ONE)
353480093f4SDimitry Andric       .Case("ord", FCmpInst::FCMP_ORD)
354480093f4SDimitry Andric       .Case("uno", FCmpInst::FCMP_UNO)
355480093f4SDimitry Andric       .Case("ueq", FCmpInst::FCMP_UEQ)
356480093f4SDimitry Andric       .Case("ugt", FCmpInst::FCMP_UGT)
357480093f4SDimitry Andric       .Case("uge", FCmpInst::FCMP_UGE)
358480093f4SDimitry Andric       .Case("ult", FCmpInst::FCMP_ULT)
359480093f4SDimitry Andric       .Case("ule", FCmpInst::FCMP_ULE)
360480093f4SDimitry Andric       .Case("une", FCmpInst::FCMP_UNE)
361480093f4SDimitry Andric       .Default(FCmpInst::BAD_FCMP_PREDICATE);
3620b57cec5SDimitry Andric }
3630b57cec5SDimitry Andric 
36481ad6265SDimitry Andric FCmpInst::Predicate ConstrainedFPCmpIntrinsic::getPredicate() const {
36581ad6265SDimitry Andric   return getFPPredicateFromMD(getArgOperand(2));
36681ad6265SDimitry Andric }
36781ad6265SDimitry Andric 
3680fca6ea1SDimitry Andric unsigned ConstrainedFPIntrinsic::getNonMetadataArgCount() const {
3690fca6ea1SDimitry Andric   // All constrained fp intrinsics have "fpexcept" metadata.
3700fca6ea1SDimitry Andric   unsigned NumArgs = arg_size() - 1;
3710b57cec5SDimitry Andric 
3720fca6ea1SDimitry Andric   // Some intrinsics have "round" metadata.
3730fca6ea1SDimitry Andric   if (Intrinsic::hasConstrainedFPRoundingModeOperand(getIntrinsicID()))
3740fca6ea1SDimitry Andric     NumArgs -= 1;
3750fca6ea1SDimitry Andric 
3760fca6ea1SDimitry Andric   // Compare intrinsics take their predicate as metadata.
3770fca6ea1SDimitry Andric   if (isa<ConstrainedFPCmpIntrinsic>(this))
3780fca6ea1SDimitry Andric     NumArgs -= 1;
3790fca6ea1SDimitry Andric 
3800fca6ea1SDimitry Andric   return NumArgs;
381480093f4SDimitry Andric }
382480093f4SDimitry Andric 
383480093f4SDimitry Andric bool ConstrainedFPIntrinsic::classof(const IntrinsicInst *I) {
3840fca6ea1SDimitry Andric   return Intrinsic::isConstrainedFPIntrinsic(I->getIntrinsicID());
3850b57cec5SDimitry Andric }
3860b57cec5SDimitry Andric 
3875ffd83dbSDimitry Andric ElementCount VPIntrinsic::getStaticVectorLength() const {
3885ffd83dbSDimitry Andric   auto GetVectorLengthOfType = [](const Type *T) -> ElementCount {
389fe6060f1SDimitry Andric     const auto *VT = cast<VectorType>(T);
3905ffd83dbSDimitry Andric     auto ElemCount = VT->getElementCount();
3915ffd83dbSDimitry Andric     return ElemCount;
3925ffd83dbSDimitry Andric   };
3935ffd83dbSDimitry Andric 
394fe6060f1SDimitry Andric   Value *VPMask = getMaskParam();
39581ad6265SDimitry Andric   if (!VPMask) {
39681ad6265SDimitry Andric     assert((getIntrinsicID() == Intrinsic::vp_merge ||
39781ad6265SDimitry Andric             getIntrinsicID() == Intrinsic::vp_select) &&
39881ad6265SDimitry Andric            "Unexpected VP intrinsic without mask operand");
39981ad6265SDimitry Andric     return GetVectorLengthOfType(getType());
40081ad6265SDimitry Andric   }
4015ffd83dbSDimitry Andric   return GetVectorLengthOfType(VPMask->getType());
4025ffd83dbSDimitry Andric }
4035ffd83dbSDimitry Andric 
4045ffd83dbSDimitry Andric Value *VPIntrinsic::getMaskParam() const {
405fe6060f1SDimitry Andric   if (auto MaskPos = getMaskParamPos(getIntrinsicID()))
40681ad6265SDimitry Andric     return getArgOperand(*MaskPos);
4075ffd83dbSDimitry Andric   return nullptr;
4085ffd83dbSDimitry Andric }
4095ffd83dbSDimitry Andric 
410fe6060f1SDimitry Andric void VPIntrinsic::setMaskParam(Value *NewMask) {
411fe6060f1SDimitry Andric   auto MaskPos = getMaskParamPos(getIntrinsicID());
412fe6060f1SDimitry Andric   setArgOperand(*MaskPos, NewMask);
413fe6060f1SDimitry Andric }
414fe6060f1SDimitry Andric 
4155ffd83dbSDimitry Andric Value *VPIntrinsic::getVectorLengthParam() const {
416fe6060f1SDimitry Andric   if (auto EVLPos = getVectorLengthParamPos(getIntrinsicID()))
41781ad6265SDimitry Andric     return getArgOperand(*EVLPos);
4185ffd83dbSDimitry Andric   return nullptr;
4195ffd83dbSDimitry Andric }
4205ffd83dbSDimitry Andric 
421fe6060f1SDimitry Andric void VPIntrinsic::setVectorLengthParam(Value *NewEVL) {
422fe6060f1SDimitry Andric   auto EVLPos = getVectorLengthParamPos(getIntrinsicID());
423fe6060f1SDimitry Andric   setArgOperand(*EVLPos, NewEVL);
424fe6060f1SDimitry Andric }
425fe6060f1SDimitry Andric 
426bdd1243dSDimitry Andric std::optional<unsigned>
427bdd1243dSDimitry Andric VPIntrinsic::getMaskParamPos(Intrinsic::ID IntrinsicID) {
4285ffd83dbSDimitry Andric   switch (IntrinsicID) {
4295ffd83dbSDimitry Andric   default:
430bdd1243dSDimitry Andric     return std::nullopt;
4315ffd83dbSDimitry Andric 
432e8d8bef9SDimitry Andric #define BEGIN_REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS)                    \
4335ffd83dbSDimitry Andric   case Intrinsic::VPID:                                                        \
4345ffd83dbSDimitry Andric     return MASKPOS;
4355ffd83dbSDimitry Andric #include "llvm/IR/VPIntrinsics.def"
4365ffd83dbSDimitry Andric   }
4375ffd83dbSDimitry Andric }
4385ffd83dbSDimitry Andric 
439bdd1243dSDimitry Andric std::optional<unsigned>
440fe6060f1SDimitry Andric VPIntrinsic::getVectorLengthParamPos(Intrinsic::ID IntrinsicID) {
4415ffd83dbSDimitry Andric   switch (IntrinsicID) {
4425ffd83dbSDimitry Andric   default:
443bdd1243dSDimitry Andric     return std::nullopt;
4445ffd83dbSDimitry Andric 
445e8d8bef9SDimitry Andric #define BEGIN_REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS)                    \
4465ffd83dbSDimitry Andric   case Intrinsic::VPID:                                                        \
4475ffd83dbSDimitry Andric     return VLENPOS;
4485ffd83dbSDimitry Andric #include "llvm/IR/VPIntrinsics.def"
4495ffd83dbSDimitry Andric   }
4505ffd83dbSDimitry Andric }
4515ffd83dbSDimitry Andric 
452fe6060f1SDimitry Andric /// \return the alignment of the pointer used by this load/store/gather or
453fe6060f1SDimitry Andric /// scatter.
454fe6060f1SDimitry Andric MaybeAlign VPIntrinsic::getPointerAlignment() const {
455bdd1243dSDimitry Andric   std::optional<unsigned> PtrParamOpt =
456bdd1243dSDimitry Andric       getMemoryPointerParamPos(getIntrinsicID());
45781ad6265SDimitry Andric   assert(PtrParamOpt && "no pointer argument!");
458bdd1243dSDimitry Andric   return getParamAlign(*PtrParamOpt);
459fe6060f1SDimitry Andric }
460fe6060f1SDimitry Andric 
461fe6060f1SDimitry Andric /// \return The pointer operand of this load,store, gather or scatter.
462fe6060f1SDimitry Andric Value *VPIntrinsic::getMemoryPointerParam() const {
463fe6060f1SDimitry Andric   if (auto PtrParamOpt = getMemoryPointerParamPos(getIntrinsicID()))
464bdd1243dSDimitry Andric     return getArgOperand(*PtrParamOpt);
465fe6060f1SDimitry Andric   return nullptr;
466fe6060f1SDimitry Andric }
467fe6060f1SDimitry Andric 
468bdd1243dSDimitry Andric std::optional<unsigned>
469bdd1243dSDimitry Andric VPIntrinsic::getMemoryPointerParamPos(Intrinsic::ID VPID) {
470fe6060f1SDimitry Andric   switch (VPID) {
471fe6060f1SDimitry Andric   default:
4724824e7fdSDimitry Andric     break;
4734824e7fdSDimitry Andric #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
4744824e7fdSDimitry Andric #define VP_PROPERTY_MEMOP(POINTERPOS, ...) return POINTERPOS;
4754824e7fdSDimitry Andric #define END_REGISTER_VP_INTRINSIC(VPID) break;
476fe6060f1SDimitry Andric #include "llvm/IR/VPIntrinsics.def"
477fe6060f1SDimitry Andric   }
478bdd1243dSDimitry Andric   return std::nullopt;
479fe6060f1SDimitry Andric }
480fe6060f1SDimitry Andric 
481fe6060f1SDimitry Andric /// \return The data (payload) operand of this store or scatter.
482fe6060f1SDimitry Andric Value *VPIntrinsic::getMemoryDataParam() const {
483fe6060f1SDimitry Andric   auto DataParamOpt = getMemoryDataParamPos(getIntrinsicID());
48481ad6265SDimitry Andric   if (!DataParamOpt)
485fe6060f1SDimitry Andric     return nullptr;
486bdd1243dSDimitry Andric   return getArgOperand(*DataParamOpt);
487fe6060f1SDimitry Andric }
488fe6060f1SDimitry Andric 
489bdd1243dSDimitry Andric std::optional<unsigned> VPIntrinsic::getMemoryDataParamPos(Intrinsic::ID VPID) {
490fe6060f1SDimitry Andric   switch (VPID) {
491fe6060f1SDimitry Andric   default:
4924824e7fdSDimitry Andric     break;
4934824e7fdSDimitry Andric #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
4944824e7fdSDimitry Andric #define VP_PROPERTY_MEMOP(POINTERPOS, DATAPOS) return DATAPOS;
4954824e7fdSDimitry Andric #define END_REGISTER_VP_INTRINSIC(VPID) break;
496fe6060f1SDimitry Andric #include "llvm/IR/VPIntrinsics.def"
497fe6060f1SDimitry Andric   }
498bdd1243dSDimitry Andric   return std::nullopt;
499fe6060f1SDimitry Andric }
500fe6060f1SDimitry Andric 
5015f757f3fSDimitry Andric constexpr bool isVPIntrinsic(Intrinsic::ID ID) {
5025ffd83dbSDimitry Andric   switch (ID) {
5035ffd83dbSDimitry Andric   default:
5044824e7fdSDimitry Andric     break;
505e8d8bef9SDimitry Andric #define BEGIN_REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS)                    \
5065ffd83dbSDimitry Andric   case Intrinsic::VPID:                                                        \
5074824e7fdSDimitry Andric     return true;
5085ffd83dbSDimitry Andric #include "llvm/IR/VPIntrinsics.def"
5095ffd83dbSDimitry Andric   }
5104824e7fdSDimitry Andric   return false;
5115ffd83dbSDimitry Andric }
5125ffd83dbSDimitry Andric 
5135f757f3fSDimitry Andric bool VPIntrinsic::isVPIntrinsic(Intrinsic::ID ID) {
5145f757f3fSDimitry Andric   return ::isVPIntrinsic(ID);
5155f757f3fSDimitry Andric }
5165f757f3fSDimitry Andric 
5175ffd83dbSDimitry Andric // Equivalent non-predicated opcode
5185f757f3fSDimitry Andric constexpr static std::optional<unsigned>
5195f757f3fSDimitry Andric getFunctionalOpcodeForVP(Intrinsic::ID ID) {
5205ffd83dbSDimitry Andric   switch (ID) {
5215ffd83dbSDimitry Andric   default:
522e8d8bef9SDimitry Andric     break;
523e8d8bef9SDimitry Andric #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
5244824e7fdSDimitry Andric #define VP_PROPERTY_FUNCTIONAL_OPC(OPC) return Instruction::OPC;
5254824e7fdSDimitry Andric #define END_REGISTER_VP_INTRINSIC(VPID) break;
5265ffd83dbSDimitry Andric #include "llvm/IR/VPIntrinsics.def"
5275ffd83dbSDimitry Andric   }
528bdd1243dSDimitry Andric   return std::nullopt;
5295ffd83dbSDimitry Andric }
5305ffd83dbSDimitry Andric 
53106c3fb27SDimitry Andric std::optional<unsigned>
5325f757f3fSDimitry Andric VPIntrinsic::getFunctionalOpcodeForVP(Intrinsic::ID ID) {
5335f757f3fSDimitry Andric   return ::getFunctionalOpcodeForVP(ID);
5345f757f3fSDimitry Andric }
5355f757f3fSDimitry Andric 
5365f757f3fSDimitry Andric // Equivalent non-predicated intrinsic ID
5375f757f3fSDimitry Andric constexpr static std::optional<Intrinsic::ID>
5385f757f3fSDimitry Andric getFunctionalIntrinsicIDForVP(Intrinsic::ID ID) {
5395f757f3fSDimitry Andric   switch (ID) {
5405f757f3fSDimitry Andric   default:
5415f757f3fSDimitry Andric     break;
5425f757f3fSDimitry Andric #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
5435f757f3fSDimitry Andric #define VP_PROPERTY_FUNCTIONAL_INTRINSIC(INTRIN) return Intrinsic::INTRIN;
5445f757f3fSDimitry Andric #define END_REGISTER_VP_INTRINSIC(VPID) break;
5455f757f3fSDimitry Andric #include "llvm/IR/VPIntrinsics.def"
5465f757f3fSDimitry Andric   }
5475f757f3fSDimitry Andric   return std::nullopt;
5485f757f3fSDimitry Andric }
5495f757f3fSDimitry Andric 
5505f757f3fSDimitry Andric std::optional<Intrinsic::ID>
5515f757f3fSDimitry Andric VPIntrinsic::getFunctionalIntrinsicIDForVP(Intrinsic::ID ID) {
5525f757f3fSDimitry Andric   return ::getFunctionalIntrinsicIDForVP(ID);
5535f757f3fSDimitry Andric }
5545f757f3fSDimitry Andric 
5555f757f3fSDimitry Andric constexpr static bool doesVPHaveNoFunctionalEquivalent(Intrinsic::ID ID) {
5565f757f3fSDimitry Andric   switch (ID) {
5575f757f3fSDimitry Andric   default:
5585f757f3fSDimitry Andric     break;
5595f757f3fSDimitry Andric #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
5605f757f3fSDimitry Andric #define VP_PROPERTY_NO_FUNCTIONAL return true;
5615f757f3fSDimitry Andric #define END_REGISTER_VP_INTRINSIC(VPID) break;
5625f757f3fSDimitry Andric #include "llvm/IR/VPIntrinsics.def"
5635f757f3fSDimitry Andric   }
5645f757f3fSDimitry Andric   return false;
5655f757f3fSDimitry Andric }
5665f757f3fSDimitry Andric 
5675f757f3fSDimitry Andric // All VP intrinsics should have an equivalent non-VP opcode or intrinsic
5685f757f3fSDimitry Andric // defined, or be marked that they don't have one.
5695f757f3fSDimitry Andric #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...)                                 \
5705f757f3fSDimitry Andric   static_assert(doesVPHaveNoFunctionalEquivalent(Intrinsic::VPID) ||           \
5715f757f3fSDimitry Andric                 getFunctionalOpcodeForVP(Intrinsic::VPID) ||                   \
5725f757f3fSDimitry Andric                 getFunctionalIntrinsicIDForVP(Intrinsic::VPID));
5735f757f3fSDimitry Andric #include "llvm/IR/VPIntrinsics.def"
5745f757f3fSDimitry Andric 
5755f757f3fSDimitry Andric // Equivalent non-predicated constrained intrinsic
5765f757f3fSDimitry Andric std::optional<Intrinsic::ID>
57706c3fb27SDimitry Andric VPIntrinsic::getConstrainedIntrinsicIDForVP(Intrinsic::ID ID) {
57806c3fb27SDimitry Andric   switch (ID) {
57906c3fb27SDimitry Andric   default:
58006c3fb27SDimitry Andric     break;
58106c3fb27SDimitry Andric #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
58206c3fb27SDimitry Andric #define VP_PROPERTY_CONSTRAINEDFP(HASRND, HASEXCEPT, CID) return Intrinsic::CID;
58306c3fb27SDimitry Andric #define END_REGISTER_VP_INTRINSIC(VPID) break;
58406c3fb27SDimitry Andric #include "llvm/IR/VPIntrinsics.def"
58506c3fb27SDimitry Andric   }
58606c3fb27SDimitry Andric   return std::nullopt;
58706c3fb27SDimitry Andric }
58806c3fb27SDimitry Andric 
589fe6060f1SDimitry Andric Intrinsic::ID VPIntrinsic::getForOpcode(unsigned IROPC) {
590e8d8bef9SDimitry Andric   switch (IROPC) {
5915ffd83dbSDimitry Andric   default:
5924824e7fdSDimitry Andric     break;
5935ffd83dbSDimitry Andric 
5944824e7fdSDimitry Andric #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) break;
5954824e7fdSDimitry Andric #define VP_PROPERTY_FUNCTIONAL_OPC(OPC) case Instruction::OPC:
596e8d8bef9SDimitry Andric #define END_REGISTER_VP_INTRINSIC(VPID) return Intrinsic::VPID;
5975ffd83dbSDimitry Andric #include "llvm/IR/VPIntrinsics.def"
5985ffd83dbSDimitry Andric   }
5994824e7fdSDimitry Andric   return Intrinsic::not_intrinsic;
6005ffd83dbSDimitry Andric }
6015ffd83dbSDimitry Andric 
602*52418fc2SDimitry Andric constexpr static Intrinsic::ID getForIntrinsic(Intrinsic::ID Id) {
603*52418fc2SDimitry Andric   if (::isVPIntrinsic(Id))
604*52418fc2SDimitry Andric     return Id;
605*52418fc2SDimitry Andric 
606*52418fc2SDimitry Andric   switch (Id) {
607*52418fc2SDimitry Andric   default:
608*52418fc2SDimitry Andric     break;
609*52418fc2SDimitry Andric #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) break;
610*52418fc2SDimitry Andric #define VP_PROPERTY_FUNCTIONAL_INTRINSIC(INTRIN) case Intrinsic::INTRIN:
611*52418fc2SDimitry Andric #define END_REGISTER_VP_INTRINSIC(VPID) return Intrinsic::VPID;
612*52418fc2SDimitry Andric #include "llvm/IR/VPIntrinsics.def"
613*52418fc2SDimitry Andric   }
614*52418fc2SDimitry Andric   return Intrinsic::not_intrinsic;
615*52418fc2SDimitry Andric }
616*52418fc2SDimitry Andric 
617*52418fc2SDimitry Andric Intrinsic::ID VPIntrinsic::getForIntrinsic(Intrinsic::ID Id) {
618*52418fc2SDimitry Andric   return ::getForIntrinsic(Id);
619*52418fc2SDimitry Andric }
620*52418fc2SDimitry Andric 
6215ffd83dbSDimitry Andric bool VPIntrinsic::canIgnoreVectorLengthParam() const {
6225ffd83dbSDimitry Andric   using namespace PatternMatch;
6235ffd83dbSDimitry Andric 
6245ffd83dbSDimitry Andric   ElementCount EC = getStaticVectorLength();
6255ffd83dbSDimitry Andric 
6265ffd83dbSDimitry Andric   // No vlen param - no lanes masked-off by it.
6275ffd83dbSDimitry Andric   auto *VLParam = getVectorLengthParam();
6285ffd83dbSDimitry Andric   if (!VLParam)
6295ffd83dbSDimitry Andric     return true;
6305ffd83dbSDimitry Andric 
6315ffd83dbSDimitry Andric   // Note that the VP intrinsic causes undefined behavior if the Explicit Vector
6325ffd83dbSDimitry Andric   // Length parameter is strictly greater-than the number of vector elements of
6335ffd83dbSDimitry Andric   // the operation. This function returns true when this is detected statically
6345ffd83dbSDimitry Andric   // in the IR.
6355ffd83dbSDimitry Andric 
636e8d8bef9SDimitry Andric   // Check whether "W == vscale * EC.getKnownMinValue()"
637e8d8bef9SDimitry Andric   if (EC.isScalable()) {
6385ffd83dbSDimitry Andric     // Compare vscale patterns
6395ffd83dbSDimitry Andric     uint64_t VScaleFactor;
6400fca6ea1SDimitry Andric     if (match(VLParam, m_Mul(m_VScale(), m_ConstantInt(VScaleFactor))))
641e8d8bef9SDimitry Andric       return VScaleFactor >= EC.getKnownMinValue();
64206c3fb27SDimitry Andric     return (EC.getKnownMinValue() == 1) && match(VLParam, m_VScale());
6435ffd83dbSDimitry Andric   }
6445ffd83dbSDimitry Andric 
6455ffd83dbSDimitry Andric   // standard SIMD operation
646fe6060f1SDimitry Andric   const auto *VLConst = dyn_cast<ConstantInt>(VLParam);
6475ffd83dbSDimitry Andric   if (!VLConst)
6485ffd83dbSDimitry Andric     return false;
6495ffd83dbSDimitry Andric 
6505ffd83dbSDimitry Andric   uint64_t VLNum = VLConst->getZExtValue();
651e8d8bef9SDimitry Andric   if (VLNum >= EC.getKnownMinValue())
6525ffd83dbSDimitry Andric     return true;
6535ffd83dbSDimitry Andric 
6545ffd83dbSDimitry Andric   return false;
6555ffd83dbSDimitry Andric }
6565ffd83dbSDimitry Andric 
657fe6060f1SDimitry Andric Function *VPIntrinsic::getDeclarationForParams(Module *M, Intrinsic::ID VPID,
6580eae32dcSDimitry Andric                                                Type *ReturnType,
659fe6060f1SDimitry Andric                                                ArrayRef<Value *> Params) {
660fe6060f1SDimitry Andric   assert(isVPIntrinsic(VPID) && "not a VP intrinsic");
661fe6060f1SDimitry Andric   Function *VPFunc;
662fe6060f1SDimitry Andric   switch (VPID) {
663349cc55cSDimitry Andric   default: {
664349cc55cSDimitry Andric     Type *OverloadTy = Params[0]->getType();
665349cc55cSDimitry Andric     if (VPReductionIntrinsic::isVPReduction(VPID))
666349cc55cSDimitry Andric       OverloadTy =
667349cc55cSDimitry Andric           Params[*VPReductionIntrinsic::getVectorParamPos(VPID)]->getType();
668349cc55cSDimitry Andric 
669349cc55cSDimitry Andric     VPFunc = Intrinsic::getDeclaration(M, VPID, OverloadTy);
670349cc55cSDimitry Andric     break;
671349cc55cSDimitry Andric   }
67281ad6265SDimitry Andric   case Intrinsic::vp_trunc:
67381ad6265SDimitry Andric   case Intrinsic::vp_sext:
67481ad6265SDimitry Andric   case Intrinsic::vp_zext:
67581ad6265SDimitry Andric   case Intrinsic::vp_fptoui:
67681ad6265SDimitry Andric   case Intrinsic::vp_fptosi:
67781ad6265SDimitry Andric   case Intrinsic::vp_uitofp:
67881ad6265SDimitry Andric   case Intrinsic::vp_sitofp:
67981ad6265SDimitry Andric   case Intrinsic::vp_fptrunc:
68081ad6265SDimitry Andric   case Intrinsic::vp_fpext:
68181ad6265SDimitry Andric   case Intrinsic::vp_ptrtoint:
68281ad6265SDimitry Andric   case Intrinsic::vp_inttoptr:
6830fca6ea1SDimitry Andric   case Intrinsic::vp_lrint:
6840fca6ea1SDimitry Andric   case Intrinsic::vp_llrint:
6850fca6ea1SDimitry Andric   case Intrinsic::vp_cttz_elts:
68681ad6265SDimitry Andric     VPFunc =
68781ad6265SDimitry Andric         Intrinsic::getDeclaration(M, VPID, {ReturnType, Params[0]->getType()});
68881ad6265SDimitry Andric     break;
6895f757f3fSDimitry Andric   case Intrinsic::vp_is_fpclass:
6905f757f3fSDimitry Andric     VPFunc = Intrinsic::getDeclaration(M, VPID, {Params[0]->getType()});
6915f757f3fSDimitry Andric     break;
69204eeddc0SDimitry Andric   case Intrinsic::vp_merge:
693349cc55cSDimitry Andric   case Intrinsic::vp_select:
694349cc55cSDimitry Andric     VPFunc = Intrinsic::getDeclaration(M, VPID, {Params[1]->getType()});
695fe6060f1SDimitry Andric     break;
696fe6060f1SDimitry Andric   case Intrinsic::vp_load:
697fe6060f1SDimitry Andric     VPFunc = Intrinsic::getDeclaration(
6980eae32dcSDimitry Andric         M, VPID, {ReturnType, Params[0]->getType()});
699fe6060f1SDimitry Andric     break;
70081ad6265SDimitry Andric   case Intrinsic::experimental_vp_strided_load:
70181ad6265SDimitry Andric     VPFunc = Intrinsic::getDeclaration(
70281ad6265SDimitry Andric         M, VPID, {ReturnType, Params[0]->getType(), Params[1]->getType()});
70381ad6265SDimitry Andric     break;
704fe6060f1SDimitry Andric   case Intrinsic::vp_gather:
705fe6060f1SDimitry Andric     VPFunc = Intrinsic::getDeclaration(
7060eae32dcSDimitry Andric         M, VPID, {ReturnType, Params[0]->getType()});
707fe6060f1SDimitry Andric     break;
708fe6060f1SDimitry Andric   case Intrinsic::vp_store:
709fe6060f1SDimitry Andric     VPFunc = Intrinsic::getDeclaration(
7100eae32dcSDimitry Andric         M, VPID, {Params[0]->getType(), Params[1]->getType()});
711fe6060f1SDimitry Andric     break;
71281ad6265SDimitry Andric   case Intrinsic::experimental_vp_strided_store:
71381ad6265SDimitry Andric     VPFunc = Intrinsic::getDeclaration(
71481ad6265SDimitry Andric         M, VPID,
71581ad6265SDimitry Andric         {Params[0]->getType(), Params[1]->getType(), Params[2]->getType()});
71681ad6265SDimitry Andric     break;
717fe6060f1SDimitry Andric   case Intrinsic::vp_scatter:
718fe6060f1SDimitry Andric     VPFunc = Intrinsic::getDeclaration(
719fe6060f1SDimitry Andric         M, VPID, {Params[0]->getType(), Params[1]->getType()});
720fe6060f1SDimitry Andric     break;
7210fca6ea1SDimitry Andric   case Intrinsic::experimental_vp_splat:
7220fca6ea1SDimitry Andric     VPFunc = Intrinsic::getDeclaration(M, VPID, ReturnType);
7230fca6ea1SDimitry Andric     break;
724fe6060f1SDimitry Andric   }
725fe6060f1SDimitry Andric   assert(VPFunc && "Could not declare VP intrinsic");
726fe6060f1SDimitry Andric   return VPFunc;
727fe6060f1SDimitry Andric }
728fe6060f1SDimitry Andric 
729349cc55cSDimitry Andric bool VPReductionIntrinsic::isVPReduction(Intrinsic::ID ID) {
730349cc55cSDimitry Andric   switch (ID) {
731349cc55cSDimitry Andric   default:
732349cc55cSDimitry Andric     break;
7334824e7fdSDimitry Andric #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
7344824e7fdSDimitry Andric #define VP_PROPERTY_REDUCTION(STARTPOS, ...) return true;
7354824e7fdSDimitry Andric #define END_REGISTER_VP_INTRINSIC(VPID) break;
736349cc55cSDimitry Andric #include "llvm/IR/VPIntrinsics.def"
737349cc55cSDimitry Andric   }
7384824e7fdSDimitry Andric   return false;
739349cc55cSDimitry Andric }
740349cc55cSDimitry Andric 
74181ad6265SDimitry Andric bool VPCastIntrinsic::isVPCast(Intrinsic::ID ID) {
74281ad6265SDimitry Andric   switch (ID) {
74381ad6265SDimitry Andric   default:
74481ad6265SDimitry Andric     break;
74581ad6265SDimitry Andric #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
74681ad6265SDimitry Andric #define VP_PROPERTY_CASTOP return true;
74781ad6265SDimitry Andric #define END_REGISTER_VP_INTRINSIC(VPID) break;
74881ad6265SDimitry Andric #include "llvm/IR/VPIntrinsics.def"
74981ad6265SDimitry Andric   }
75081ad6265SDimitry Andric   return false;
75181ad6265SDimitry Andric }
75281ad6265SDimitry Andric 
75381ad6265SDimitry Andric bool VPCmpIntrinsic::isVPCmp(Intrinsic::ID ID) {
75481ad6265SDimitry Andric   switch (ID) {
75581ad6265SDimitry Andric   default:
75681ad6265SDimitry Andric     break;
75781ad6265SDimitry Andric #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
75881ad6265SDimitry Andric #define VP_PROPERTY_CMP(CCPOS, ...) return true;
75981ad6265SDimitry Andric #define END_REGISTER_VP_INTRINSIC(VPID) break;
76081ad6265SDimitry Andric #include "llvm/IR/VPIntrinsics.def"
76181ad6265SDimitry Andric   }
76281ad6265SDimitry Andric   return false;
76381ad6265SDimitry Andric }
76481ad6265SDimitry Andric 
7655f757f3fSDimitry Andric bool VPBinOpIntrinsic::isVPBinOp(Intrinsic::ID ID) {
7665f757f3fSDimitry Andric   switch (ID) {
7675f757f3fSDimitry Andric   default:
7685f757f3fSDimitry Andric     break;
7695f757f3fSDimitry Andric #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
7705f757f3fSDimitry Andric #define VP_PROPERTY_BINARYOP return true;
7715f757f3fSDimitry Andric #define END_REGISTER_VP_INTRINSIC(VPID) break;
7725f757f3fSDimitry Andric #include "llvm/IR/VPIntrinsics.def"
7735f757f3fSDimitry Andric   }
7745f757f3fSDimitry Andric   return false;
7755f757f3fSDimitry Andric }
7765f757f3fSDimitry Andric 
77781ad6265SDimitry Andric static ICmpInst::Predicate getIntPredicateFromMD(const Value *Op) {
77881ad6265SDimitry Andric   Metadata *MD = cast<MetadataAsValue>(Op)->getMetadata();
77981ad6265SDimitry Andric   if (!MD || !isa<MDString>(MD))
78081ad6265SDimitry Andric     return ICmpInst::BAD_ICMP_PREDICATE;
78181ad6265SDimitry Andric   return StringSwitch<ICmpInst::Predicate>(cast<MDString>(MD)->getString())
78281ad6265SDimitry Andric       .Case("eq", ICmpInst::ICMP_EQ)
78381ad6265SDimitry Andric       .Case("ne", ICmpInst::ICMP_NE)
78481ad6265SDimitry Andric       .Case("ugt", ICmpInst::ICMP_UGT)
78581ad6265SDimitry Andric       .Case("uge", ICmpInst::ICMP_UGE)
78681ad6265SDimitry Andric       .Case("ult", ICmpInst::ICMP_ULT)
78781ad6265SDimitry Andric       .Case("ule", ICmpInst::ICMP_ULE)
78881ad6265SDimitry Andric       .Case("sgt", ICmpInst::ICMP_SGT)
78981ad6265SDimitry Andric       .Case("sge", ICmpInst::ICMP_SGE)
79081ad6265SDimitry Andric       .Case("slt", ICmpInst::ICMP_SLT)
79181ad6265SDimitry Andric       .Case("sle", ICmpInst::ICMP_SLE)
79281ad6265SDimitry Andric       .Default(ICmpInst::BAD_ICMP_PREDICATE);
79381ad6265SDimitry Andric }
79481ad6265SDimitry Andric 
79581ad6265SDimitry Andric CmpInst::Predicate VPCmpIntrinsic::getPredicate() const {
79681ad6265SDimitry Andric   bool IsFP = true;
797bdd1243dSDimitry Andric   std::optional<unsigned> CCArgIdx;
79881ad6265SDimitry Andric   switch (getIntrinsicID()) {
79981ad6265SDimitry Andric   default:
80081ad6265SDimitry Andric     break;
80181ad6265SDimitry Andric #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
80281ad6265SDimitry Andric #define VP_PROPERTY_CMP(CCPOS, ISFP)                                           \
80381ad6265SDimitry Andric   CCArgIdx = CCPOS;                                                            \
80481ad6265SDimitry Andric   IsFP = ISFP;                                                                 \
80581ad6265SDimitry Andric   break;
80681ad6265SDimitry Andric #define END_REGISTER_VP_INTRINSIC(VPID) break;
80781ad6265SDimitry Andric #include "llvm/IR/VPIntrinsics.def"
80881ad6265SDimitry Andric   }
80981ad6265SDimitry Andric   assert(CCArgIdx && "Unexpected vector-predicated comparison");
81081ad6265SDimitry Andric   return IsFP ? getFPPredicateFromMD(getArgOperand(*CCArgIdx))
81181ad6265SDimitry Andric               : getIntPredicateFromMD(getArgOperand(*CCArgIdx));
81281ad6265SDimitry Andric }
81381ad6265SDimitry Andric 
814349cc55cSDimitry Andric unsigned VPReductionIntrinsic::getVectorParamPos() const {
815349cc55cSDimitry Andric   return *VPReductionIntrinsic::getVectorParamPos(getIntrinsicID());
816349cc55cSDimitry Andric }
817349cc55cSDimitry Andric 
818349cc55cSDimitry Andric unsigned VPReductionIntrinsic::getStartParamPos() const {
819349cc55cSDimitry Andric   return *VPReductionIntrinsic::getStartParamPos(getIntrinsicID());
820349cc55cSDimitry Andric }
821349cc55cSDimitry Andric 
822bdd1243dSDimitry Andric std::optional<unsigned>
823bdd1243dSDimitry Andric VPReductionIntrinsic::getVectorParamPos(Intrinsic::ID ID) {
824349cc55cSDimitry Andric   switch (ID) {
8254824e7fdSDimitry Andric #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
8264824e7fdSDimitry Andric #define VP_PROPERTY_REDUCTION(STARTPOS, VECTORPOS) return VECTORPOS;
8274824e7fdSDimitry Andric #define END_REGISTER_VP_INTRINSIC(VPID) break;
828349cc55cSDimitry Andric #include "llvm/IR/VPIntrinsics.def"
829349cc55cSDimitry Andric   default:
8304824e7fdSDimitry Andric     break;
831349cc55cSDimitry Andric   }
832bdd1243dSDimitry Andric   return std::nullopt;
833349cc55cSDimitry Andric }
834349cc55cSDimitry Andric 
835bdd1243dSDimitry Andric std::optional<unsigned>
836bdd1243dSDimitry Andric VPReductionIntrinsic::getStartParamPos(Intrinsic::ID ID) {
837349cc55cSDimitry Andric   switch (ID) {
8384824e7fdSDimitry Andric #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
8394824e7fdSDimitry Andric #define VP_PROPERTY_REDUCTION(STARTPOS, VECTORPOS) return STARTPOS;
8404824e7fdSDimitry Andric #define END_REGISTER_VP_INTRINSIC(VPID) break;
841349cc55cSDimitry Andric #include "llvm/IR/VPIntrinsics.def"
842349cc55cSDimitry Andric   default:
8434824e7fdSDimitry Andric     break;
844349cc55cSDimitry Andric   }
845bdd1243dSDimitry Andric   return std::nullopt;
846349cc55cSDimitry Andric }
847349cc55cSDimitry Andric 
8480b57cec5SDimitry Andric Instruction::BinaryOps BinaryOpIntrinsic::getBinaryOp() const {
8490b57cec5SDimitry Andric   switch (getIntrinsicID()) {
8500b57cec5SDimitry Andric   case Intrinsic::uadd_with_overflow:
8510b57cec5SDimitry Andric   case Intrinsic::sadd_with_overflow:
8520b57cec5SDimitry Andric   case Intrinsic::uadd_sat:
8530b57cec5SDimitry Andric   case Intrinsic::sadd_sat:
8540b57cec5SDimitry Andric     return Instruction::Add;
8550b57cec5SDimitry Andric   case Intrinsic::usub_with_overflow:
8560b57cec5SDimitry Andric   case Intrinsic::ssub_with_overflow:
8570b57cec5SDimitry Andric   case Intrinsic::usub_sat:
8580b57cec5SDimitry Andric   case Intrinsic::ssub_sat:
8590b57cec5SDimitry Andric     return Instruction::Sub;
8600b57cec5SDimitry Andric   case Intrinsic::umul_with_overflow:
8610b57cec5SDimitry Andric   case Intrinsic::smul_with_overflow:
8620b57cec5SDimitry Andric     return Instruction::Mul;
8630b57cec5SDimitry Andric   default:
8640b57cec5SDimitry Andric     llvm_unreachable("Invalid intrinsic");
8650b57cec5SDimitry Andric   }
8660b57cec5SDimitry Andric }
8670b57cec5SDimitry Andric 
8680b57cec5SDimitry Andric bool BinaryOpIntrinsic::isSigned() const {
8690b57cec5SDimitry Andric   switch (getIntrinsicID()) {
8700b57cec5SDimitry Andric   case Intrinsic::sadd_with_overflow:
8710b57cec5SDimitry Andric   case Intrinsic::ssub_with_overflow:
8720b57cec5SDimitry Andric   case Intrinsic::smul_with_overflow:
8730b57cec5SDimitry Andric   case Intrinsic::sadd_sat:
8740b57cec5SDimitry Andric   case Intrinsic::ssub_sat:
8750b57cec5SDimitry Andric     return true;
8760b57cec5SDimitry Andric   default:
8770b57cec5SDimitry Andric     return false;
8780b57cec5SDimitry Andric   }
8790b57cec5SDimitry Andric }
8800b57cec5SDimitry Andric 
8810b57cec5SDimitry Andric unsigned BinaryOpIntrinsic::getNoWrapKind() const {
8820b57cec5SDimitry Andric   if (isSigned())
8830b57cec5SDimitry Andric     return OverflowingBinaryOperator::NoSignedWrap;
8840b57cec5SDimitry Andric   else
8850b57cec5SDimitry Andric     return OverflowingBinaryOperator::NoUnsignedWrap;
8860b57cec5SDimitry Andric }
887fe6060f1SDimitry Andric 
888fcaf7f86SDimitry Andric const Value *GCProjectionInst::getStatepoint() const {
889fe6060f1SDimitry Andric   const Value *Token = getArgOperand(0);
890fcaf7f86SDimitry Andric   if (isa<UndefValue>(Token))
891fcaf7f86SDimitry Andric     return Token;
892fe6060f1SDimitry Andric 
8935f757f3fSDimitry Andric   // Treat none token as if it was undef here
8945f757f3fSDimitry Andric   if (isa<ConstantTokenNone>(Token))
8955f757f3fSDimitry Andric     return UndefValue::get(Token->getType());
8965f757f3fSDimitry Andric 
897fe6060f1SDimitry Andric   // This takes care both of relocates for call statepoints and relocates
898fe6060f1SDimitry Andric   // on normal path of invoke statepoint.
899fe6060f1SDimitry Andric   if (!isa<LandingPadInst>(Token))
900fe6060f1SDimitry Andric     return cast<GCStatepointInst>(Token);
901fe6060f1SDimitry Andric 
902fe6060f1SDimitry Andric   // This relocate is on exceptional path of an invoke statepoint
903fe6060f1SDimitry Andric   const BasicBlock *InvokeBB =
904fe6060f1SDimitry Andric     cast<Instruction>(Token)->getParent()->getUniquePredecessor();
905fe6060f1SDimitry Andric 
906fe6060f1SDimitry Andric   assert(InvokeBB && "safepoints should have unique landingpads");
907fe6060f1SDimitry Andric   assert(InvokeBB->getTerminator() &&
908fe6060f1SDimitry Andric          "safepoint block should be well formed");
909fe6060f1SDimitry Andric 
910fe6060f1SDimitry Andric   return cast<GCStatepointInst>(InvokeBB->getTerminator());
911fe6060f1SDimitry Andric }
912fe6060f1SDimitry Andric 
913fe6060f1SDimitry Andric Value *GCRelocateInst::getBasePtr() const {
914fcaf7f86SDimitry Andric   auto Statepoint = getStatepoint();
915fcaf7f86SDimitry Andric   if (isa<UndefValue>(Statepoint))
916fcaf7f86SDimitry Andric     return UndefValue::get(Statepoint->getType());
917fcaf7f86SDimitry Andric 
918fcaf7f86SDimitry Andric   auto *GCInst = cast<GCStatepointInst>(Statepoint);
919fcaf7f86SDimitry Andric   if (auto Opt = GCInst->getOperandBundle(LLVMContext::OB_gc_live))
920fe6060f1SDimitry Andric     return *(Opt->Inputs.begin() + getBasePtrIndex());
921fcaf7f86SDimitry Andric   return *(GCInst->arg_begin() + getBasePtrIndex());
922fe6060f1SDimitry Andric }
923fe6060f1SDimitry Andric 
924fe6060f1SDimitry Andric Value *GCRelocateInst::getDerivedPtr() const {
925fcaf7f86SDimitry Andric   auto *Statepoint = getStatepoint();
926fcaf7f86SDimitry Andric   if (isa<UndefValue>(Statepoint))
927fcaf7f86SDimitry Andric     return UndefValue::get(Statepoint->getType());
928fcaf7f86SDimitry Andric 
929fcaf7f86SDimitry Andric   auto *GCInst = cast<GCStatepointInst>(Statepoint);
930fcaf7f86SDimitry Andric   if (auto Opt = GCInst->getOperandBundle(LLVMContext::OB_gc_live))
931fe6060f1SDimitry Andric     return *(Opt->Inputs.begin() + getDerivedPtrIndex());
932fcaf7f86SDimitry Andric   return *(GCInst->arg_begin() + getDerivedPtrIndex());
933fe6060f1SDimitry Andric }
934