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