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