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
34using namespace llvm;
35
36bool 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_claimAutoreleasedReturnValue:
43 case Intrinsic::objc_copyWeak:
44 case Intrinsic::objc_destroyWeak:
45 case Intrinsic::objc_initWeak:
46 case Intrinsic::objc_loadWeak:
47 case Intrinsic::objc_loadWeakRetained:
48 case Intrinsic::objc_moveWeak:
49 case Intrinsic::objc_release:
50 case Intrinsic::objc_retain:
51 case Intrinsic::objc_retainAutorelease:
52 case Intrinsic::objc_retainAutoreleaseReturnValue:
53 case Intrinsic::objc_retainAutoreleasedReturnValue:
54 case Intrinsic::objc_retainBlock:
55 case Intrinsic::objc_storeStrong:
56 case Intrinsic::objc_storeWeak:
57 case Intrinsic::objc_unsafeClaimAutoreleasedReturnValue:
58 case Intrinsic::objc_retainedObject:
59 case Intrinsic::objc_unretainedObject:
60 case Intrinsic::objc_unretainedPointer:
61 case Intrinsic::objc_retain_autorelease:
62 case Intrinsic::objc_sync_enter:
63 case Intrinsic::objc_sync_exit:
64 return true;
65 default:
66 return false;
67 }
68}
69
70//===----------------------------------------------------------------------===//
71/// DbgVariableIntrinsic - This is the common base class for debug info
72/// intrinsics for variables.
73///
74
75iterator_range<location_op_iterator> RawLocationWrapper::location_ops() const {
76 Metadata *MD = getRawLocation();
77 assert(MD && "First operand of DbgVariableIntrinsic should be non-null.");
78 // If operand is ValueAsMetadata, return a range over just that operand.
79 if (auto *VAM = dyn_cast<ValueAsMetadata>(Val: MD)) {
80 return {location_op_iterator(VAM), location_op_iterator(VAM + 1)};
81 }
82 // If operand is DIArgList, return a range over its args.
83 if (auto *AL = dyn_cast<DIArgList>(Val: MD))
84 return {location_op_iterator(AL->args_begin()),
85 location_op_iterator(AL->args_end())};
86 // Operand must be an empty metadata tuple, so return empty iterator.
87 return {location_op_iterator(static_cast<ValueAsMetadata *>(nullptr)),
88 location_op_iterator(static_cast<ValueAsMetadata *>(nullptr))};
89}
90
91Value *DbgVariableIntrinsic::getVariableLocationOp(unsigned OpIdx) const {
92 return getWrappedLocation().getVariableLocationOp(OpIdx);
93}
94
95Value *RawLocationWrapper::getVariableLocationOp(unsigned OpIdx) const {
96 Metadata *MD = getRawLocation();
97 assert(MD && "First operand of DbgVariableIntrinsic should be non-null.");
98 if (auto *AL = dyn_cast<DIArgList>(Val: MD))
99 return AL->getArgs()[OpIdx]->getValue();
100 if (isa<MDNode>(Val: MD))
101 return nullptr;
102 assert(
103 isa<ValueAsMetadata>(MD) &&
104 "Attempted to get location operand from DbgVariableIntrinsic with none.");
105 auto *V = cast<ValueAsMetadata>(Val: MD);
106 assert(OpIdx == 0 && "Operand Index must be 0 for a debug intrinsic with a "
107 "single location operand.");
108 return V->getValue();
109}
110
111ConstantInt *InstrProfCntrInstBase::getNumCounters() const {
112 if (InstrProfValueProfileInst::classof(I: this))
113 llvm_unreachable("InstrProfValueProfileInst does not have counters!");
114 return cast<ConstantInt>(Val: getArgOperand(i: 2));
115}
116
117ConstantInt *InstrProfCntrInstBase::getIndex() const {
118 if (InstrProfValueProfileInst::classof(I: this))
119 llvm_unreachable("Please use InstrProfValueProfileInst::getIndex()");
120 return cast<ConstantInt>(Val: getArgOperand(i: 3));
121}
122
123void InstrProfCntrInstBase::setIndex(uint32_t Idx) {
124 assert(isa<InstrProfCntrInstBase>(this));
125 setArgOperand(i: 3, v: ConstantInt::get(Ty: Type::getInt32Ty(C&: getContext()), V: Idx));
126}
127
128Value *InstrProfIncrementInst::getStep() const {
129 if (InstrProfIncrementInstStep::classof(I: this)) {
130 return getArgOperand(i: 4);
131 }
132 const Module *M = getModule();
133 LLVMContext &Context = M->getContext();
134 return ConstantInt::get(Ty: Type::getInt64Ty(C&: Context), V: 1);
135}
136
137Value *InstrProfCallsite::getCallee() const { return getArgOperand(i: 4); }
138
139void InstrProfCallsite::setCallee(Value *Callee) {
140 assert(isa<InstrProfCallsite>(this));
141 setArgOperand(i: 4, v: Callee);
142}
143
144std::optional<RoundingMode> ConstrainedFPIntrinsic::getRoundingMode() const {
145 unsigned NumOperands = arg_size();
146 Metadata *MD = nullptr;
147 auto *MAV = dyn_cast<MetadataAsValue>(Val: getArgOperand(i: NumOperands - 2));
148 if (MAV)
149 MD = MAV->getMetadata();
150 if (!MD || !isa<MDString>(Val: MD))
151 return std::nullopt;
152 return convertStrToRoundingMode(cast<MDString>(Val: MD)->getString());
153}
154
155std::optional<fp::ExceptionBehavior>
156ConstrainedFPIntrinsic::getExceptionBehavior() const {
157 unsigned NumOperands = arg_size();
158 Metadata *MD = nullptr;
159 auto *MAV = dyn_cast<MetadataAsValue>(Val: getArgOperand(i: NumOperands - 1));
160 if (MAV)
161 MD = MAV->getMetadata();
162 if (!MD || !isa<MDString>(Val: MD))
163 return std::nullopt;
164 return convertStrToExceptionBehavior(cast<MDString>(Val: MD)->getString());
165}
166
167bool ConstrainedFPIntrinsic::isDefaultFPEnvironment() const {
168 std::optional<fp::ExceptionBehavior> Except = getExceptionBehavior();
169 if (Except) {
170 if (*Except != fp::ebIgnore)
171 return false;
172 }
173
174 std::optional<RoundingMode> Rounding = getRoundingMode();
175 if (Rounding) {
176 if (*Rounding != RoundingMode::NearestTiesToEven)
177 return false;
178 }
179
180 return true;
181}
182
183static FCmpInst::Predicate getFPPredicateFromMD(const Value *Op) {
184 Metadata *MD = cast<MetadataAsValue>(Val: Op)->getMetadata();
185 if (!MD || !isa<MDString>(Val: MD))
186 return FCmpInst::BAD_FCMP_PREDICATE;
187 return StringSwitch<FCmpInst::Predicate>(cast<MDString>(Val: MD)->getString())
188 .Case(S: "oeq", Value: FCmpInst::FCMP_OEQ)
189 .Case(S: "ogt", Value: FCmpInst::FCMP_OGT)
190 .Case(S: "oge", Value: FCmpInst::FCMP_OGE)
191 .Case(S: "olt", Value: FCmpInst::FCMP_OLT)
192 .Case(S: "ole", Value: FCmpInst::FCMP_OLE)
193 .Case(S: "one", Value: FCmpInst::FCMP_ONE)
194 .Case(S: "ord", Value: FCmpInst::FCMP_ORD)
195 .Case(S: "uno", Value: FCmpInst::FCMP_UNO)
196 .Case(S: "ueq", Value: FCmpInst::FCMP_UEQ)
197 .Case(S: "ugt", Value: FCmpInst::FCMP_UGT)
198 .Case(S: "uge", Value: FCmpInst::FCMP_UGE)
199 .Case(S: "ult", Value: FCmpInst::FCMP_ULT)
200 .Case(S: "ule", Value: FCmpInst::FCMP_ULE)
201 .Case(S: "une", Value: FCmpInst::FCMP_UNE)
202 .Default(Value: FCmpInst::BAD_FCMP_PREDICATE);
203}
204
205FCmpInst::Predicate ConstrainedFPCmpIntrinsic::getPredicate() const {
206 return getFPPredicateFromMD(Op: getArgOperand(i: 2));
207}
208
209unsigned ConstrainedFPIntrinsic::getNonMetadataArgCount() const {
210 // All constrained fp intrinsics have "fpexcept" metadata.
211 unsigned NumArgs = arg_size() - 1;
212
213 // Some intrinsics have "round" metadata.
214 if (Intrinsic::hasConstrainedFPRoundingModeOperand(QID: getIntrinsicID()))
215 NumArgs -= 1;
216
217 // Compare intrinsics take their predicate as metadata.
218 if (isa<ConstrainedFPCmpIntrinsic>(Val: this))
219 NumArgs -= 1;
220
221 return NumArgs;
222}
223
224bool ConstrainedFPIntrinsic::classof(const IntrinsicInst *I) {
225 return Intrinsic::isConstrainedFPIntrinsic(QID: I->getIntrinsicID());
226}
227
228ElementCount VPIntrinsic::getStaticVectorLength() const {
229 auto GetVectorLengthOfType = [](const Type *T) -> ElementCount {
230 const auto *VT = cast<VectorType>(Val: T);
231 auto ElemCount = VT->getElementCount();
232 return ElemCount;
233 };
234
235 Value *VPMask = getMaskParam();
236 if (!VPMask) {
237 assert((getIntrinsicID() == Intrinsic::vp_merge) &&
238 "Unexpected VP intrinsic without mask operand");
239 return GetVectorLengthOfType(getType());
240 }
241 return GetVectorLengthOfType(VPMask->getType());
242}
243
244Value *VPIntrinsic::getMaskParam() const {
245 if (auto MaskPos = getMaskParamPos(IntrinsicID: getIntrinsicID()))
246 return getArgOperand(i: *MaskPos);
247 return nullptr;
248}
249
250void VPIntrinsic::setMaskParam(Value *NewMask) {
251 auto MaskPos = getMaskParamPos(IntrinsicID: getIntrinsicID());
252 setArgOperand(i: *MaskPos, v: NewMask);
253}
254
255Value *VPIntrinsic::getVectorLengthParam() const {
256 if (auto EVLPos = getVectorLengthParamPos(IntrinsicID: getIntrinsicID()))
257 return getArgOperand(i: *EVLPos);
258 return nullptr;
259}
260
261void VPIntrinsic::setVectorLengthParam(Value *NewEVL) {
262 auto EVLPos = getVectorLengthParamPos(IntrinsicID: getIntrinsicID());
263 setArgOperand(i: *EVLPos, v: NewEVL);
264}
265
266std::optional<unsigned>
267VPIntrinsic::getMaskParamPos(Intrinsic::ID IntrinsicID) {
268 switch (IntrinsicID) {
269 default:
270 return std::nullopt;
271
272#define BEGIN_REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS) \
273 case Intrinsic::VPID: \
274 return MASKPOS;
275#include "llvm/IR/VPIntrinsics.def"
276 }
277}
278
279std::optional<unsigned>
280VPIntrinsic::getVectorLengthParamPos(Intrinsic::ID IntrinsicID) {
281 switch (IntrinsicID) {
282 default:
283 return std::nullopt;
284
285#define BEGIN_REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS) \
286 case Intrinsic::VPID: \
287 return VLENPOS;
288#include "llvm/IR/VPIntrinsics.def"
289 }
290}
291
292/// \return the alignment of the pointer used by this load/store/gather or
293/// scatter.
294MaybeAlign VPIntrinsic::getPointerAlignment() const {
295 std::optional<unsigned> PtrParamOpt =
296 getMemoryPointerParamPos(getIntrinsicID());
297 assert(PtrParamOpt && "no pointer argument!");
298 return getParamAlign(ArgNo: *PtrParamOpt);
299}
300
301/// \return The pointer operand of this load,store, gather or scatter.
302Value *VPIntrinsic::getMemoryPointerParam() const {
303 if (auto PtrParamOpt = getMemoryPointerParamPos(getIntrinsicID()))
304 return getArgOperand(i: *PtrParamOpt);
305 return nullptr;
306}
307
308std::optional<unsigned>
309VPIntrinsic::getMemoryPointerParamPos(Intrinsic::ID VPID) {
310 switch (VPID) {
311 default:
312 return std::nullopt;
313 case Intrinsic::vp_store:
314 case Intrinsic::vp_scatter:
315 case Intrinsic::experimental_vp_strided_store:
316 return 1;
317 case Intrinsic::vp_load:
318 case Intrinsic::vp_load_ff:
319 case Intrinsic::vp_gather:
320 case Intrinsic::experimental_vp_strided_load:
321 return 0;
322 }
323}
324
325/// \return The data (payload) operand of this store or scatter.
326Value *VPIntrinsic::getMemoryDataParam() const {
327 auto DataParamOpt = getMemoryDataParamPos(getIntrinsicID());
328 if (!DataParamOpt)
329 return nullptr;
330 return getArgOperand(i: *DataParamOpt);
331}
332
333std::optional<unsigned> VPIntrinsic::getMemoryDataParamPos(Intrinsic::ID VPID) {
334 switch (VPID) {
335 default:
336 return std::nullopt;
337 case Intrinsic::vp_store:
338 case Intrinsic::vp_scatter:
339 case Intrinsic::experimental_vp_strided_store:
340 return 0;
341 }
342}
343
344constexpr bool isVPIntrinsic(Intrinsic::ID ID) {
345 switch (ID) {
346 default:
347 break;
348#define BEGIN_REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS) \
349 case Intrinsic::VPID: \
350 return true;
351#include "llvm/IR/VPIntrinsics.def"
352 }
353 return false;
354}
355
356bool VPIntrinsic::isVPIntrinsic(Intrinsic::ID ID) {
357 return ::isVPIntrinsic(ID);
358}
359
360// Equivalent non-predicated opcode
361constexpr static std::optional<unsigned>
362getFunctionalOpcodeForVP(Intrinsic::ID ID) {
363 switch (ID) {
364 default:
365 break;
366#define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
367#define VP_PROPERTY_FUNCTIONAL_OPC(OPC) return Instruction::OPC;
368#define END_REGISTER_VP_INTRINSIC(VPID) break;
369#include "llvm/IR/VPIntrinsics.def"
370 }
371 return std::nullopt;
372}
373
374std::optional<unsigned>
375VPIntrinsic::getFunctionalOpcodeForVP(Intrinsic::ID ID) {
376 return ::getFunctionalOpcodeForVP(ID);
377}
378
379// Equivalent non-predicated intrinsic ID
380constexpr static std::optional<Intrinsic::ID>
381getFunctionalIntrinsicIDForVP(Intrinsic::ID ID) {
382 switch (ID) {
383 default:
384 break;
385#define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
386#define VP_PROPERTY_FUNCTIONAL_INTRINSIC(INTRIN) return Intrinsic::INTRIN;
387#define END_REGISTER_VP_INTRINSIC(VPID) break;
388#include "llvm/IR/VPIntrinsics.def"
389 }
390 return std::nullopt;
391}
392
393std::optional<Intrinsic::ID>
394VPIntrinsic::getFunctionalIntrinsicIDForVP(Intrinsic::ID ID) {
395 return ::getFunctionalIntrinsicIDForVP(ID);
396}
397
398constexpr static bool doesVPHaveNoFunctionalEquivalent(Intrinsic::ID ID) {
399 switch (ID) {
400 default:
401 break;
402#define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
403#define VP_PROPERTY_NO_FUNCTIONAL return true;
404#define END_REGISTER_VP_INTRINSIC(VPID) break;
405#include "llvm/IR/VPIntrinsics.def"
406 }
407 return false;
408}
409
410// All VP intrinsics should have an equivalent non-VP opcode or intrinsic
411// defined, or be marked that they don't have one.
412#define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) \
413 static_assert(doesVPHaveNoFunctionalEquivalent(Intrinsic::VPID) || \
414 getFunctionalOpcodeForVP(Intrinsic::VPID) || \
415 getFunctionalIntrinsicIDForVP(Intrinsic::VPID));
416#include "llvm/IR/VPIntrinsics.def"
417
418bool VPIntrinsic::canIgnoreVectorLengthParam() const {
419 using namespace PatternMatch;
420
421 ElementCount EC = getStaticVectorLength();
422
423 // No vlen param - no lanes masked-off by it.
424 auto *VLParam = getVectorLengthParam();
425 if (!VLParam)
426 return true;
427
428 // Note that the VP intrinsic causes undefined behavior if the Explicit Vector
429 // Length parameter is strictly greater-than the number of vector elements of
430 // the operation. This function returns true when this is detected statically
431 // in the IR.
432
433 // Check whether "W == vscale * EC.getKnownMinValue()"
434 if (EC.isScalable()) {
435 // Compare vscale patterns
436 uint64_t VScaleFactor;
437 if (match(V: VLParam, P: m_Mul(L: m_VScale(), R: m_ConstantInt(V&: VScaleFactor))))
438 return VScaleFactor >= EC.getKnownMinValue();
439 return (EC.getKnownMinValue() == 1) && match(V: VLParam, P: m_VScale());
440 }
441
442 // standard SIMD operation
443 const auto *VLConst = dyn_cast<ConstantInt>(Val: VLParam);
444 if (!VLConst)
445 return false;
446
447 uint64_t VLNum = VLConst->getZExtValue();
448 if (VLNum >= EC.getKnownMinValue())
449 return true;
450
451 return false;
452}
453
454Function *VPIntrinsic::getOrInsertDeclarationForParams(
455 Module *M, Intrinsic::ID VPID, Type *ReturnType, ArrayRef<Value *> Params) {
456 assert(isVPIntrinsic(VPID) && "not a VP intrinsic");
457 Function *VPFunc;
458 switch (VPID) {
459 default: {
460 Type *OverloadTy = Params[0]->getType();
461 if (VPReductionIntrinsic::isVPReduction(ID: VPID))
462 OverloadTy =
463 Params[*VPReductionIntrinsic::getVectorParamPos(ID: VPID)]->getType();
464
465 VPFunc = Intrinsic::getOrInsertDeclaration(M, id: VPID, OverloadTys: OverloadTy);
466 break;
467 }
468 case Intrinsic::vp_cttz_elts:
469 VPFunc = Intrinsic::getOrInsertDeclaration(
470 M, id: VPID, OverloadTys: {ReturnType, Params[0]->getType()});
471 break;
472 case Intrinsic::vp_merge:
473 VPFunc = Intrinsic::getOrInsertDeclaration(M, id: VPID, OverloadTys: {Params[1]->getType()});
474 break;
475 case Intrinsic::vp_load:
476 VPFunc = Intrinsic::getOrInsertDeclaration(
477 M, id: VPID, OverloadTys: {ReturnType, Params[0]->getType()});
478 break;
479 case Intrinsic::vp_load_ff:
480 VPFunc = Intrinsic::getOrInsertDeclaration(
481 M, id: VPID, OverloadTys: {ReturnType->getStructElementType(N: 0), Params[0]->getType()});
482 break;
483 case Intrinsic::experimental_vp_strided_load:
484 VPFunc = Intrinsic::getOrInsertDeclaration(
485 M, id: VPID, OverloadTys: {ReturnType, Params[0]->getType(), Params[1]->getType()});
486 break;
487 case Intrinsic::vp_gather:
488 VPFunc = Intrinsic::getOrInsertDeclaration(
489 M, id: VPID, OverloadTys: {ReturnType, Params[0]->getType()});
490 break;
491 case Intrinsic::vp_store:
492 VPFunc = Intrinsic::getOrInsertDeclaration(
493 M, id: VPID, OverloadTys: {Params[0]->getType(), Params[1]->getType()});
494 break;
495 case Intrinsic::experimental_vp_strided_store:
496 VPFunc = Intrinsic::getOrInsertDeclaration(
497 M, id: VPID,
498 OverloadTys: {Params[0]->getType(), Params[1]->getType(), Params[2]->getType()});
499 break;
500 case Intrinsic::vp_scatter:
501 VPFunc = Intrinsic::getOrInsertDeclaration(
502 M, id: VPID, OverloadTys: {Params[0]->getType(), Params[1]->getType()});
503 break;
504 }
505 assert(VPFunc && "Could not declare VP intrinsic");
506 return VPFunc;
507}
508
509bool VPReductionIntrinsic::isVPReduction(Intrinsic::ID ID) {
510 switch (ID) {
511 case Intrinsic::vp_reduce_add:
512 case Intrinsic::vp_reduce_mul:
513 case Intrinsic::vp_reduce_and:
514 case Intrinsic::vp_reduce_or:
515 case Intrinsic::vp_reduce_xor:
516 case Intrinsic::vp_reduce_smax:
517 case Intrinsic::vp_reduce_smin:
518 case Intrinsic::vp_reduce_umax:
519 case Intrinsic::vp_reduce_umin:
520 case Intrinsic::vp_reduce_fmax:
521 case Intrinsic::vp_reduce_fmin:
522 case Intrinsic::vp_reduce_fmaximum:
523 case Intrinsic::vp_reduce_fminimum:
524 case Intrinsic::vp_reduce_fadd:
525 case Intrinsic::vp_reduce_fmul:
526 return true;
527 default:
528 return false;
529 }
530}
531
532unsigned VPReductionIntrinsic::getVectorParamPos() const {
533 return *VPReductionIntrinsic::getVectorParamPos(ID: getIntrinsicID());
534}
535
536unsigned VPReductionIntrinsic::getStartParamPos() const {
537 return *VPReductionIntrinsic::getStartParamPos(ID: getIntrinsicID());
538}
539
540std::optional<unsigned>
541VPReductionIntrinsic::getVectorParamPos(Intrinsic::ID ID) {
542 if (isVPReduction(ID))
543 return 1;
544 return std::nullopt;
545}
546
547std::optional<unsigned>
548VPReductionIntrinsic::getStartParamPos(Intrinsic::ID ID) {
549 if (isVPReduction(ID))
550 return 0;
551 return std::nullopt;
552}
553
554Instruction::BinaryOps BinaryOpIntrinsic::getBinaryOp() const {
555 switch (getIntrinsicID()) {
556 case Intrinsic::uadd_with_overflow:
557 case Intrinsic::sadd_with_overflow:
558 case Intrinsic::uadd_sat:
559 case Intrinsic::sadd_sat:
560 return Instruction::Add;
561 case Intrinsic::usub_with_overflow:
562 case Intrinsic::ssub_with_overflow:
563 case Intrinsic::usub_sat:
564 case Intrinsic::ssub_sat:
565 return Instruction::Sub;
566 case Intrinsic::umul_with_overflow:
567 case Intrinsic::smul_with_overflow:
568 return Instruction::Mul;
569 default:
570 llvm_unreachable("Invalid intrinsic");
571 }
572}
573
574bool BinaryOpIntrinsic::isSigned() const {
575 switch (getIntrinsicID()) {
576 case Intrinsic::sadd_with_overflow:
577 case Intrinsic::ssub_with_overflow:
578 case Intrinsic::smul_with_overflow:
579 case Intrinsic::sadd_sat:
580 case Intrinsic::ssub_sat:
581 return true;
582 default:
583 return false;
584 }
585}
586
587unsigned BinaryOpIntrinsic::getNoWrapKind() const {
588 if (isSigned())
589 return OverflowingBinaryOperator::NoSignedWrap;
590 else
591 return OverflowingBinaryOperator::NoUnsignedWrap;
592}
593
594const Value *GCProjectionInst::getStatepoint() const {
595 const Value *Token = getArgOperand(i: 0);
596 if (isa<UndefValue>(Val: Token))
597 return Token;
598
599 // Treat none token as if it was undef here
600 if (isa<ConstantTokenNone>(Val: Token))
601 return UndefValue::get(T: Token->getType());
602
603 // This takes care both of relocates for call statepoints and relocates
604 // on normal path of invoke statepoint.
605 if (!isa<LandingPadInst>(Val: Token))
606 return cast<GCStatepointInst>(Val: Token);
607
608 // This relocate is on exceptional path of an invoke statepoint
609 const BasicBlock *InvokeBB =
610 cast<Instruction>(Val: Token)->getParent()->getUniquePredecessor();
611
612 assert(InvokeBB && "safepoints should have unique landingpads");
613
614 return cast<GCStatepointInst>(Val: InvokeBB->getTerminator());
615}
616
617Value *GCRelocateInst::getBasePtr() const {
618 auto Statepoint = getStatepoint();
619 if (isa<UndefValue>(Val: Statepoint))
620 return UndefValue::get(T: Statepoint->getType());
621 // Handle too few (bundle) arguments to avoid crashes when printing invalid
622 // IR, e.g. in the verifier.
623 auto *GCInst = cast<GCStatepointInst>(Val: Statepoint);
624 if (auto Opt = GCInst->getOperandBundle(ID: LLVMContext::OB_gc_live)) {
625 if (getBasePtrIndex() > Opt->Inputs.size())
626 return nullptr;
627 return *(Opt->Inputs.begin() + getBasePtrIndex());
628 }
629 if (getBasePtrIndex() > GCInst->arg_size())
630 return nullptr;
631 return *(GCInst->arg_begin() + getBasePtrIndex());
632}
633
634Value *GCRelocateInst::getDerivedPtr() const {
635 auto *Statepoint = getStatepoint();
636 if (isa<UndefValue>(Val: Statepoint))
637 return UndefValue::get(T: Statepoint->getType());
638
639 // Handle too few (bundle) arguments to avoid crashes when printing invalid
640 // IR, e.g. in the verifier.
641 auto *GCInst = cast<GCStatepointInst>(Val: Statepoint);
642 if (auto Opt = GCInst->getOperandBundle(ID: LLVMContext::OB_gc_live)) {
643 if (getDerivedPtrIndex() > Opt->Inputs.size())
644 return nullptr;
645 return *(Opt->Inputs.begin() + getDerivedPtrIndex());
646 }
647 if (getDerivedPtrIndex() > GCInst->arg_size())
648 return nullptr;
649 return *(GCInst->arg_begin() + getDerivedPtrIndex());
650}
651
652ConvergenceControlInst *ConvergenceControlInst::CreateAnchor(BasicBlock &BB) {
653 Module *M = BB.getModule();
654 Function *Fn = Intrinsic::getOrInsertDeclaration(
655 M, id: llvm::Intrinsic::experimental_convergence_anchor);
656 auto *Call = CallInst::Create(Func: Fn, NameStr: "", InsertBefore: BB.getFirstInsertionPt());
657 return cast<ConvergenceControlInst>(Val: Call);
658}
659
660ConvergenceControlInst *ConvergenceControlInst::CreateEntry(BasicBlock &BB) {
661 Module *M = BB.getModule();
662 Function *Fn = Intrinsic::getOrInsertDeclaration(
663 M, id: llvm::Intrinsic::experimental_convergence_entry);
664 auto *Call = CallInst::Create(Func: Fn, NameStr: "", InsertBefore: BB.getFirstInsertionPt());
665 return cast<ConvergenceControlInst>(Val: Call);
666}
667
668ConvergenceControlInst *
669ConvergenceControlInst::CreateLoop(BasicBlock &BB,
670 ConvergenceControlInst *ParentToken) {
671 Module *M = BB.getModule();
672 Function *Fn = Intrinsic::getOrInsertDeclaration(
673 M, id: llvm::Intrinsic::experimental_convergence_loop);
674 llvm::Value *BundleArgs[] = {ParentToken};
675 llvm::OperandBundleDef OB("convergencectrl", BundleArgs);
676 auto *Call = CallInst::Create(Func: Fn, Args: {}, Bundles: {OB}, NameStr: "", InsertBefore: BB.getFirstInsertionPt());
677 return cast<ConvergenceControlInst>(Val: Call);
678}
679