10b57cec5SDimitry Andric //===-- llvm/IntrinsicInst.h - Intrinsic Instruction Wrappers ---*- C++ -*-===//
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 defines classes that make it really easy to deal with intrinsic
100b57cec5SDimitry Andric // functions with the isa/dyncast family of functions. In particular, this
110b57cec5SDimitry Andric // allows you to do things like:
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric // if (MemCpyInst *MCI = dyn_cast<MemCpyInst>(Inst))
140b57cec5SDimitry Andric // ... MCI->getDest() ... MCI->getSource() ...
150b57cec5SDimitry Andric //
160b57cec5SDimitry Andric // All intrinsic function calls are instances of the call instruction, so these
170b57cec5SDimitry Andric // are all subclasses of the CallInst class. Note that none of these classes
180b57cec5SDimitry Andric // has state or virtual methods, which is an important part of this gross/neat
190b57cec5SDimitry Andric // hack working.
200b57cec5SDimitry Andric //
210b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
220b57cec5SDimitry Andric
230b57cec5SDimitry Andric #ifndef LLVM_IR_INTRINSICINST_H
240b57cec5SDimitry Andric #define LLVM_IR_INTRINSICINST_H
250b57cec5SDimitry Andric
260b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
27fe6060f1SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
280b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h"
29480093f4SDimitry Andric #include "llvm/IR/FPEnv.h"
300b57cec5SDimitry Andric #include "llvm/IR/Function.h"
310b57cec5SDimitry Andric #include "llvm/IR/GlobalVariable.h"
320b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
330b57cec5SDimitry Andric #include "llvm/IR/Intrinsics.h"
340b57cec5SDimitry Andric #include "llvm/IR/Value.h"
350b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
360fca6ea1SDimitry Andric #include "llvm/Support/MathExtras.h"
370b57cec5SDimitry Andric #include <cassert>
380b57cec5SDimitry Andric #include <cstdint>
39bdd1243dSDimitry Andric #include <optional>
400b57cec5SDimitry Andric
410b57cec5SDimitry Andric namespace llvm {
420b57cec5SDimitry Andric
4381ad6265SDimitry Andric class Metadata;
4481ad6265SDimitry Andric
450b57cec5SDimitry Andric /// A wrapper class for inspecting calls to intrinsic functions.
460b57cec5SDimitry Andric /// This allows the standard isa/dyncast/cast functionality to work with calls
470b57cec5SDimitry Andric /// to intrinsic functions.
480b57cec5SDimitry Andric class IntrinsicInst : public CallInst {
490b57cec5SDimitry Andric public:
500b57cec5SDimitry Andric IntrinsicInst() = delete;
510b57cec5SDimitry Andric IntrinsicInst(const IntrinsicInst &) = delete;
520b57cec5SDimitry Andric IntrinsicInst &operator=(const IntrinsicInst &) = delete;
530b57cec5SDimitry Andric
540b57cec5SDimitry Andric /// Return the intrinsic ID of this intrinsic.
getIntrinsicID()550b57cec5SDimitry Andric Intrinsic::ID getIntrinsicID() const {
560b57cec5SDimitry Andric return getCalledFunction()->getIntrinsicID();
570b57cec5SDimitry Andric }
580b57cec5SDimitry Andric
isAssociative()595f757f3fSDimitry Andric bool isAssociative() const {
605f757f3fSDimitry Andric switch (getIntrinsicID()) {
615f757f3fSDimitry Andric case Intrinsic::smax:
625f757f3fSDimitry Andric case Intrinsic::smin:
635f757f3fSDimitry Andric case Intrinsic::umax:
645f757f3fSDimitry Andric case Intrinsic::umin:
655f757f3fSDimitry Andric return true;
665f757f3fSDimitry Andric default:
675f757f3fSDimitry Andric return false;
685f757f3fSDimitry Andric }
695f757f3fSDimitry Andric }
705f757f3fSDimitry Andric
71e8d8bef9SDimitry Andric /// Return true if swapping the first two arguments to the intrinsic produces
72e8d8bef9SDimitry Andric /// the same result.
isCommutative()73e8d8bef9SDimitry Andric bool isCommutative() const {
74e8d8bef9SDimitry Andric switch (getIntrinsicID()) {
75e8d8bef9SDimitry Andric case Intrinsic::maxnum:
76e8d8bef9SDimitry Andric case Intrinsic::minnum:
77e8d8bef9SDimitry Andric case Intrinsic::maximum:
78e8d8bef9SDimitry Andric case Intrinsic::minimum:
79e8d8bef9SDimitry Andric case Intrinsic::smax:
80e8d8bef9SDimitry Andric case Intrinsic::smin:
81e8d8bef9SDimitry Andric case Intrinsic::umax:
82e8d8bef9SDimitry Andric case Intrinsic::umin:
83e8d8bef9SDimitry Andric case Intrinsic::sadd_sat:
84e8d8bef9SDimitry Andric case Intrinsic::uadd_sat:
85e8d8bef9SDimitry Andric case Intrinsic::sadd_with_overflow:
86e8d8bef9SDimitry Andric case Intrinsic::uadd_with_overflow:
87e8d8bef9SDimitry Andric case Intrinsic::smul_with_overflow:
88e8d8bef9SDimitry Andric case Intrinsic::umul_with_overflow:
89e8d8bef9SDimitry Andric case Intrinsic::smul_fix:
90e8d8bef9SDimitry Andric case Intrinsic::umul_fix:
91e8d8bef9SDimitry Andric case Intrinsic::smul_fix_sat:
92e8d8bef9SDimitry Andric case Intrinsic::umul_fix_sat:
93e8d8bef9SDimitry Andric case Intrinsic::fma:
94e8d8bef9SDimitry Andric case Intrinsic::fmuladd:
95e8d8bef9SDimitry Andric return true;
96e8d8bef9SDimitry Andric default:
97e8d8bef9SDimitry Andric return false;
98e8d8bef9SDimitry Andric }
99e8d8bef9SDimitry Andric }
100e8d8bef9SDimitry Andric
101972a253aSDimitry Andric /// Checks if the intrinsic is an annotation.
isAssumeLikeIntrinsic()102fe6060f1SDimitry Andric bool isAssumeLikeIntrinsic() const {
103fe6060f1SDimitry Andric switch (getIntrinsicID()) {
104fe6060f1SDimitry Andric default: break;
105fe6060f1SDimitry Andric case Intrinsic::assume:
106fe6060f1SDimitry Andric case Intrinsic::sideeffect:
107fe6060f1SDimitry Andric case Intrinsic::pseudoprobe:
108bdd1243dSDimitry Andric case Intrinsic::dbg_assign:
109fe6060f1SDimitry Andric case Intrinsic::dbg_declare:
110fe6060f1SDimitry Andric case Intrinsic::dbg_value:
111fe6060f1SDimitry Andric case Intrinsic::dbg_label:
112fe6060f1SDimitry Andric case Intrinsic::invariant_start:
113fe6060f1SDimitry Andric case Intrinsic::invariant_end:
114fe6060f1SDimitry Andric case Intrinsic::lifetime_start:
115fe6060f1SDimitry Andric case Intrinsic::lifetime_end:
116fe6060f1SDimitry Andric case Intrinsic::experimental_noalias_scope_decl:
117fe6060f1SDimitry Andric case Intrinsic::objectsize:
118fe6060f1SDimitry Andric case Intrinsic::ptr_annotation:
119fe6060f1SDimitry Andric case Intrinsic::var_annotation:
120fe6060f1SDimitry Andric return true;
121fe6060f1SDimitry Andric }
122fe6060f1SDimitry Andric return false;
123fe6060f1SDimitry Andric }
124fe6060f1SDimitry Andric
125972a253aSDimitry Andric /// Check if the intrinsic might lower into a regular function call in the
126972a253aSDimitry Andric /// course of IR transformations
127972a253aSDimitry Andric static bool mayLowerToFunctionCall(Intrinsic::ID IID);
128972a253aSDimitry Andric
129972a253aSDimitry Andric /// Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const CallInst * I)1300b57cec5SDimitry Andric static bool classof(const CallInst *I) {
1310b57cec5SDimitry Andric if (const Function *CF = I->getCalledFunction())
1320b57cec5SDimitry Andric return CF->isIntrinsic();
1330b57cec5SDimitry Andric return false;
1340b57cec5SDimitry Andric }
classof(const Value * V)1350b57cec5SDimitry Andric static bool classof(const Value *V) {
1360b57cec5SDimitry Andric return isa<CallInst>(V) && classof(cast<CallInst>(V));
1370b57cec5SDimitry Andric }
1380b57cec5SDimitry Andric };
1390b57cec5SDimitry Andric
140bdd1243dSDimitry Andric /// Check if \p ID corresponds to a lifetime intrinsic.
isLifetimeIntrinsic(Intrinsic::ID ID)141bdd1243dSDimitry Andric static inline bool isLifetimeIntrinsic(Intrinsic::ID ID) {
142bdd1243dSDimitry Andric switch (ID) {
143bdd1243dSDimitry Andric case Intrinsic::lifetime_start:
144bdd1243dSDimitry Andric case Intrinsic::lifetime_end:
145bdd1243dSDimitry Andric return true;
146bdd1243dSDimitry Andric default:
147bdd1243dSDimitry Andric return false;
148bdd1243dSDimitry Andric }
149bdd1243dSDimitry Andric }
150bdd1243dSDimitry Andric
151bdd1243dSDimitry Andric /// This is the common base class for lifetime intrinsics.
152bdd1243dSDimitry Andric class LifetimeIntrinsic : public IntrinsicInst {
153bdd1243dSDimitry Andric public:
154bdd1243dSDimitry Andric /// \name Casting methods
155bdd1243dSDimitry Andric /// @{
classof(const IntrinsicInst * I)156bdd1243dSDimitry Andric static bool classof(const IntrinsicInst *I) {
157bdd1243dSDimitry Andric return isLifetimeIntrinsic(I->getIntrinsicID());
158bdd1243dSDimitry Andric }
classof(const Value * V)159bdd1243dSDimitry Andric static bool classof(const Value *V) {
160bdd1243dSDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
161bdd1243dSDimitry Andric }
162bdd1243dSDimitry Andric /// @}
163bdd1243dSDimitry Andric };
164bdd1243dSDimitry Andric
1655ffd83dbSDimitry Andric /// Check if \p ID corresponds to a debug info intrinsic.
isDbgInfoIntrinsic(Intrinsic::ID ID)1665ffd83dbSDimitry Andric static inline bool isDbgInfoIntrinsic(Intrinsic::ID ID) {
1675ffd83dbSDimitry Andric switch (ID) {
1685ffd83dbSDimitry Andric case Intrinsic::dbg_declare:
1695ffd83dbSDimitry Andric case Intrinsic::dbg_value:
1705ffd83dbSDimitry Andric case Intrinsic::dbg_label:
171bdd1243dSDimitry Andric case Intrinsic::dbg_assign:
1725ffd83dbSDimitry Andric return true;
1735ffd83dbSDimitry Andric default:
1745ffd83dbSDimitry Andric return false;
1755ffd83dbSDimitry Andric }
1765ffd83dbSDimitry Andric }
1775ffd83dbSDimitry Andric
1780b57cec5SDimitry Andric /// This is the common base class for debug info intrinsics.
1790b57cec5SDimitry Andric class DbgInfoIntrinsic : public IntrinsicInst {
1800b57cec5SDimitry Andric public:
1810b57cec5SDimitry Andric /// \name Casting methods
1820b57cec5SDimitry Andric /// @{
classof(const IntrinsicInst * I)1830b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) {
1845ffd83dbSDimitry Andric return isDbgInfoIntrinsic(I->getIntrinsicID());
1850b57cec5SDimitry Andric }
classof(const Value * V)1860b57cec5SDimitry Andric static bool classof(const Value *V) {
1870b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
1880b57cec5SDimitry Andric }
1890b57cec5SDimitry Andric /// @}
1900b57cec5SDimitry Andric };
1910b57cec5SDimitry Andric
192fe6060f1SDimitry Andric // Iterator for ValueAsMetadata that internally uses direct pointer iteration
193fe6060f1SDimitry Andric // over either a ValueAsMetadata* or a ValueAsMetadata**, dereferencing to the
194fe6060f1SDimitry Andric // ValueAsMetadata .
195fe6060f1SDimitry Andric class location_op_iterator
196fe6060f1SDimitry Andric : public iterator_facade_base<location_op_iterator,
197fe6060f1SDimitry Andric std::bidirectional_iterator_tag, Value *> {
198fe6060f1SDimitry Andric PointerUnion<ValueAsMetadata *, ValueAsMetadata **> I;
199fe6060f1SDimitry Andric
200fe6060f1SDimitry Andric public:
location_op_iterator(ValueAsMetadata * SingleIter)201fe6060f1SDimitry Andric location_op_iterator(ValueAsMetadata *SingleIter) : I(SingleIter) {}
location_op_iterator(ValueAsMetadata ** MultiIter)202fe6060f1SDimitry Andric location_op_iterator(ValueAsMetadata **MultiIter) : I(MultiIter) {}
203fe6060f1SDimitry Andric
location_op_iterator(const location_op_iterator & R)204fe6060f1SDimitry Andric location_op_iterator(const location_op_iterator &R) : I(R.I) {}
205fe6060f1SDimitry Andric location_op_iterator &operator=(const location_op_iterator &R) {
206fe6060f1SDimitry Andric I = R.I;
207fe6060f1SDimitry Andric return *this;
208fe6060f1SDimitry Andric }
20906c3fb27SDimitry Andric bool operator==(const location_op_iterator &RHS) const { return I == RHS.I; }
210fe6060f1SDimitry Andric const Value *operator*() const {
21106c3fb27SDimitry Andric ValueAsMetadata *VAM = isa<ValueAsMetadata *>(I)
21206c3fb27SDimitry Andric ? cast<ValueAsMetadata *>(I)
21306c3fb27SDimitry Andric : *cast<ValueAsMetadata **>(I);
214fe6060f1SDimitry Andric return VAM->getValue();
215fe6060f1SDimitry Andric };
216fe6060f1SDimitry Andric Value *operator*() {
21706c3fb27SDimitry Andric ValueAsMetadata *VAM = isa<ValueAsMetadata *>(I)
21806c3fb27SDimitry Andric ? cast<ValueAsMetadata *>(I)
21906c3fb27SDimitry Andric : *cast<ValueAsMetadata **>(I);
220fe6060f1SDimitry Andric return VAM->getValue();
221fe6060f1SDimitry Andric }
222fe6060f1SDimitry Andric location_op_iterator &operator++() {
22306c3fb27SDimitry Andric if (isa<ValueAsMetadata *>(I))
22406c3fb27SDimitry Andric I = cast<ValueAsMetadata *>(I) + 1;
225fe6060f1SDimitry Andric else
22606c3fb27SDimitry Andric I = cast<ValueAsMetadata **>(I) + 1;
227fe6060f1SDimitry Andric return *this;
228fe6060f1SDimitry Andric }
229fe6060f1SDimitry Andric location_op_iterator &operator--() {
23006c3fb27SDimitry Andric if (isa<ValueAsMetadata *>(I))
23106c3fb27SDimitry Andric I = cast<ValueAsMetadata *>(I) - 1;
232fe6060f1SDimitry Andric else
23306c3fb27SDimitry Andric I = cast<ValueAsMetadata **>(I) - 1;
234fe6060f1SDimitry Andric return *this;
235fe6060f1SDimitry Andric }
236fe6060f1SDimitry Andric };
237fe6060f1SDimitry Andric
23806c3fb27SDimitry Andric /// Lightweight class that wraps the location operand metadata of a debug
23906c3fb27SDimitry Andric /// intrinsic. The raw location may be a ValueAsMetadata, an empty MDTuple,
24006c3fb27SDimitry Andric /// or a DIArgList.
24106c3fb27SDimitry Andric class RawLocationWrapper {
24206c3fb27SDimitry Andric Metadata *RawLocation = nullptr;
24306c3fb27SDimitry Andric
24406c3fb27SDimitry Andric public:
24506c3fb27SDimitry Andric RawLocationWrapper() = default;
RawLocationWrapper(Metadata * RawLocation)24606c3fb27SDimitry Andric explicit RawLocationWrapper(Metadata *RawLocation)
24706c3fb27SDimitry Andric : RawLocation(RawLocation) {
24806c3fb27SDimitry Andric // Allow ValueAsMetadata, empty MDTuple, DIArgList.
24906c3fb27SDimitry Andric assert(RawLocation && "unexpected null RawLocation");
25006c3fb27SDimitry Andric assert(isa<ValueAsMetadata>(RawLocation) || isa<DIArgList>(RawLocation) ||
25106c3fb27SDimitry Andric (isa<MDNode>(RawLocation) &&
25206c3fb27SDimitry Andric !cast<MDNode>(RawLocation)->getNumOperands()));
25306c3fb27SDimitry Andric }
getRawLocation()25406c3fb27SDimitry Andric Metadata *getRawLocation() const { return RawLocation; }
25506c3fb27SDimitry Andric /// Get the locations corresponding to the variable referenced by the debug
25606c3fb27SDimitry Andric /// info intrinsic. Depending on the intrinsic, this could be the
25706c3fb27SDimitry Andric /// variable's value or its address.
25806c3fb27SDimitry Andric iterator_range<location_op_iterator> location_ops() const;
25906c3fb27SDimitry Andric Value *getVariableLocationOp(unsigned OpIdx) const;
getNumVariableLocationOps()26006c3fb27SDimitry Andric unsigned getNumVariableLocationOps() const {
26106c3fb27SDimitry Andric if (hasArgList())
26206c3fb27SDimitry Andric return cast<DIArgList>(getRawLocation())->getArgs().size();
26306c3fb27SDimitry Andric return 1;
26406c3fb27SDimitry Andric }
hasArgList()26506c3fb27SDimitry Andric bool hasArgList() const { return isa<DIArgList>(getRawLocation()); }
isKillLocation(const DIExpression * Expression)26606c3fb27SDimitry Andric bool isKillLocation(const DIExpression *Expression) const {
26706c3fb27SDimitry Andric // Check for "kill" sentinel values.
26806c3fb27SDimitry Andric // Non-variadic: empty metadata.
26906c3fb27SDimitry Andric if (!hasArgList() && isa<MDNode>(getRawLocation()))
27006c3fb27SDimitry Andric return true;
27106c3fb27SDimitry Andric // Variadic: empty DIArgList with empty expression.
27206c3fb27SDimitry Andric if (getNumVariableLocationOps() == 0 && !Expression->isComplex())
27306c3fb27SDimitry Andric return true;
27406c3fb27SDimitry Andric // Variadic and non-variadic: Interpret expressions using undef or poison
27506c3fb27SDimitry Andric // values as kills.
27606c3fb27SDimitry Andric return any_of(location_ops(), [](Value *V) { return isa<UndefValue>(V); });
27706c3fb27SDimitry Andric }
27806c3fb27SDimitry Andric
27906c3fb27SDimitry Andric friend bool operator==(const RawLocationWrapper &A,
28006c3fb27SDimitry Andric const RawLocationWrapper &B) {
28106c3fb27SDimitry Andric return A.RawLocation == B.RawLocation;
28206c3fb27SDimitry Andric }
28306c3fb27SDimitry Andric friend bool operator!=(const RawLocationWrapper &A,
28406c3fb27SDimitry Andric const RawLocationWrapper &B) {
28506c3fb27SDimitry Andric return !(A == B);
28606c3fb27SDimitry Andric }
28706c3fb27SDimitry Andric friend bool operator>(const RawLocationWrapper &A,
28806c3fb27SDimitry Andric const RawLocationWrapper &B) {
28906c3fb27SDimitry Andric return A.RawLocation > B.RawLocation;
29006c3fb27SDimitry Andric }
29106c3fb27SDimitry Andric friend bool operator>=(const RawLocationWrapper &A,
29206c3fb27SDimitry Andric const RawLocationWrapper &B) {
29306c3fb27SDimitry Andric return A.RawLocation >= B.RawLocation;
29406c3fb27SDimitry Andric }
29506c3fb27SDimitry Andric friend bool operator<(const RawLocationWrapper &A,
29606c3fb27SDimitry Andric const RawLocationWrapper &B) {
29706c3fb27SDimitry Andric return A.RawLocation < B.RawLocation;
29806c3fb27SDimitry Andric }
29906c3fb27SDimitry Andric friend bool operator<=(const RawLocationWrapper &A,
30006c3fb27SDimitry Andric const RawLocationWrapper &B) {
30106c3fb27SDimitry Andric return A.RawLocation <= B.RawLocation;
30206c3fb27SDimitry Andric }
30306c3fb27SDimitry Andric };
30406c3fb27SDimitry Andric
30506c3fb27SDimitry Andric /// This is the common base class for debug info intrinsics for variables.
30606c3fb27SDimitry Andric class DbgVariableIntrinsic : public DbgInfoIntrinsic {
30706c3fb27SDimitry Andric public:
308fe6060f1SDimitry Andric /// Get the locations corresponding to the variable referenced by the debug
3090b57cec5SDimitry Andric /// info intrinsic. Depending on the intrinsic, this could be the
3100b57cec5SDimitry Andric /// variable's value or its address.
311fe6060f1SDimitry Andric iterator_range<location_op_iterator> location_ops() const;
312fe6060f1SDimitry Andric
313fe6060f1SDimitry Andric Value *getVariableLocationOp(unsigned OpIdx) const;
314fe6060f1SDimitry Andric
3150fca6ea1SDimitry Andric void replaceVariableLocationOp(Value *OldValue, Value *NewValue,
3160fca6ea1SDimitry Andric bool AllowEmpty = false);
317fe6060f1SDimitry Andric void replaceVariableLocationOp(unsigned OpIdx, Value *NewValue);
318fe6060f1SDimitry Andric /// Adding a new location operand will always result in this intrinsic using
319fe6060f1SDimitry Andric /// an ArgList, and must always be accompanied by a new expression that uses
320fe6060f1SDimitry Andric /// the new operand.
321fe6060f1SDimitry Andric void addVariableLocationOps(ArrayRef<Value *> NewValues,
322fe6060f1SDimitry Andric DIExpression *NewExpr);
323fe6060f1SDimitry Andric
setVariable(DILocalVariable * NewVar)324fe6060f1SDimitry Andric void setVariable(DILocalVariable *NewVar) {
325fe6060f1SDimitry Andric setArgOperand(1, MetadataAsValue::get(NewVar->getContext(), NewVar));
326fe6060f1SDimitry Andric }
327fe6060f1SDimitry Andric
setExpression(DIExpression * NewExpr)328fe6060f1SDimitry Andric void setExpression(DIExpression *NewExpr) {
329fe6060f1SDimitry Andric setArgOperand(2, MetadataAsValue::get(NewExpr->getContext(), NewExpr));
330fe6060f1SDimitry Andric }
331fe6060f1SDimitry Andric
getNumVariableLocationOps()332fe6060f1SDimitry Andric unsigned getNumVariableLocationOps() const {
33306c3fb27SDimitry Andric return getWrappedLocation().getNumVariableLocationOps();
334fe6060f1SDimitry Andric }
335fe6060f1SDimitry Andric
hasArgList()33606c3fb27SDimitry Andric bool hasArgList() const { return getWrappedLocation().hasArgList(); }
3370b57cec5SDimitry Andric
33806c3fb27SDimitry Andric /// Does this describe the address of a local variable. True for dbg.declare,
33906c3fb27SDimitry Andric /// but not dbg.value, which describes its value, or dbg.assign, which
34006c3fb27SDimitry Andric /// describes a combination of the variable's value and address.
isAddressOfVariable()3410b57cec5SDimitry Andric bool isAddressOfVariable() const {
34206c3fb27SDimitry Andric return getIntrinsicID() == Intrinsic::dbg_declare;
3430b57cec5SDimitry Andric }
3440b57cec5SDimitry Andric
setKillLocation()345bdd1243dSDimitry Andric void setKillLocation() {
346fe6060f1SDimitry Andric // TODO: When/if we remove duplicate values from DIArgLists, we don't need
347fe6060f1SDimitry Andric // this set anymore.
348fe6060f1SDimitry Andric SmallPtrSet<Value *, 4> RemovedValues;
349fe6060f1SDimitry Andric for (Value *OldValue : location_ops()) {
350fe6060f1SDimitry Andric if (!RemovedValues.insert(OldValue).second)
351fe6060f1SDimitry Andric continue;
352bdd1243dSDimitry Andric Value *Poison = PoisonValue::get(OldValue->getType());
353bdd1243dSDimitry Andric replaceVariableLocationOp(OldValue, Poison);
354fe6060f1SDimitry Andric }
355fe6060f1SDimitry Andric }
356fe6060f1SDimitry Andric
isKillLocation()357bdd1243dSDimitry Andric bool isKillLocation() const {
35806c3fb27SDimitry Andric return getWrappedLocation().isKillLocation(getExpression());
359fe6060f1SDimitry Andric }
360fe6060f1SDimitry Andric
getVariable()3610b57cec5SDimitry Andric DILocalVariable *getVariable() const {
3620b57cec5SDimitry Andric return cast<DILocalVariable>(getRawVariable());
3630b57cec5SDimitry Andric }
3640b57cec5SDimitry Andric
getExpression()3650b57cec5SDimitry Andric DIExpression *getExpression() const {
3660b57cec5SDimitry Andric return cast<DIExpression>(getRawExpression());
3670b57cec5SDimitry Andric }
3680b57cec5SDimitry Andric
getRawLocation()369fe6060f1SDimitry Andric Metadata *getRawLocation() const {
370fe6060f1SDimitry Andric return cast<MetadataAsValue>(getArgOperand(0))->getMetadata();
371fe6060f1SDimitry Andric }
372fe6060f1SDimitry Andric
getWrappedLocation()37306c3fb27SDimitry Andric RawLocationWrapper getWrappedLocation() const {
37406c3fb27SDimitry Andric return RawLocationWrapper(getRawLocation());
37506c3fb27SDimitry Andric }
37606c3fb27SDimitry Andric
getRawVariable()3770b57cec5SDimitry Andric Metadata *getRawVariable() const {
3780b57cec5SDimitry Andric return cast<MetadataAsValue>(getArgOperand(1))->getMetadata();
3790b57cec5SDimitry Andric }
3800b57cec5SDimitry Andric
getRawExpression()3810b57cec5SDimitry Andric Metadata *getRawExpression() const {
3820b57cec5SDimitry Andric return cast<MetadataAsValue>(getArgOperand(2))->getMetadata();
3830b57cec5SDimitry Andric }
3840b57cec5SDimitry Andric
385fe6060f1SDimitry Andric /// Use of this should generally be avoided; instead,
386fe6060f1SDimitry Andric /// replaceVariableLocationOp and addVariableLocationOps should be used where
387fe6060f1SDimitry Andric /// possible to avoid creating invalid state.
setRawLocation(Metadata * Location)388fe6060f1SDimitry Andric void setRawLocation(Metadata *Location) {
389fe6060f1SDimitry Andric return setArgOperand(0, MetadataAsValue::get(getContext(), Location));
390fe6060f1SDimitry Andric }
391fe6060f1SDimitry Andric
3920b57cec5SDimitry Andric /// Get the size (in bits) of the variable, or fragment of the variable that
3930b57cec5SDimitry Andric /// is described.
394bdd1243dSDimitry Andric std::optional<uint64_t> getFragmentSizeInBits() const;
395bdd1243dSDimitry Andric
396bdd1243dSDimitry Andric /// Get the FragmentInfo for the variable.
getFragment()397bdd1243dSDimitry Andric std::optional<DIExpression::FragmentInfo> getFragment() const {
398bdd1243dSDimitry Andric return getExpression()->getFragmentInfo();
399bdd1243dSDimitry Andric }
4000b57cec5SDimitry Andric
40106c3fb27SDimitry Andric /// Get the FragmentInfo for the variable if it exists, otherwise return a
40206c3fb27SDimitry Andric /// FragmentInfo that covers the entire variable if the variable size is
40306c3fb27SDimitry Andric /// known, otherwise return a zero-sized fragment.
getFragmentOrEntireVariable()40406c3fb27SDimitry Andric DIExpression::FragmentInfo getFragmentOrEntireVariable() const {
40506c3fb27SDimitry Andric DIExpression::FragmentInfo VariableSlice(0, 0);
40606c3fb27SDimitry Andric // Get the fragment or variable size, or zero.
40706c3fb27SDimitry Andric if (auto Sz = getFragmentSizeInBits())
40806c3fb27SDimitry Andric VariableSlice.SizeInBits = *Sz;
40906c3fb27SDimitry Andric if (auto Frag = getExpression()->getFragmentInfo())
41006c3fb27SDimitry Andric VariableSlice.OffsetInBits = Frag->OffsetInBits;
41106c3fb27SDimitry Andric return VariableSlice;
41206c3fb27SDimitry Andric }
41306c3fb27SDimitry Andric
4140b57cec5SDimitry Andric /// \name Casting methods
4150b57cec5SDimitry Andric /// @{
classof(const IntrinsicInst * I)4160b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) {
4170b57cec5SDimitry Andric switch (I->getIntrinsicID()) {
4180b57cec5SDimitry Andric case Intrinsic::dbg_declare:
4190b57cec5SDimitry Andric case Intrinsic::dbg_value:
420bdd1243dSDimitry Andric case Intrinsic::dbg_assign:
4210b57cec5SDimitry Andric return true;
4225ffd83dbSDimitry Andric default:
4235ffd83dbSDimitry Andric return false;
4240b57cec5SDimitry Andric }
4250b57cec5SDimitry Andric }
classof(const Value * V)4260b57cec5SDimitry Andric static bool classof(const Value *V) {
4270b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
4280b57cec5SDimitry Andric }
4290b57cec5SDimitry Andric /// @}
430bdd1243dSDimitry Andric protected:
setArgOperand(unsigned i,Value * v)431fe6060f1SDimitry Andric void setArgOperand(unsigned i, Value *v) {
432fe6060f1SDimitry Andric DbgInfoIntrinsic::setArgOperand(i, v);
433fe6060f1SDimitry Andric }
setOperand(unsigned i,Value * v)434fe6060f1SDimitry Andric void setOperand(unsigned i, Value *v) { DbgInfoIntrinsic::setOperand(i, v); }
4350b57cec5SDimitry Andric };
4360b57cec5SDimitry Andric
4370b57cec5SDimitry Andric /// This represents the llvm.dbg.declare instruction.
4380b57cec5SDimitry Andric class DbgDeclareInst : public DbgVariableIntrinsic {
4390b57cec5SDimitry Andric public:
getAddress()440fe6060f1SDimitry Andric Value *getAddress() const {
441fe6060f1SDimitry Andric assert(getNumVariableLocationOps() == 1 &&
442fe6060f1SDimitry Andric "dbg.declare must have exactly 1 location operand.");
443fe6060f1SDimitry Andric return getVariableLocationOp(0);
444fe6060f1SDimitry Andric }
4450b57cec5SDimitry Andric
4460b57cec5SDimitry Andric /// \name Casting methods
4470b57cec5SDimitry Andric /// @{
classof(const IntrinsicInst * I)4480b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) {
4490b57cec5SDimitry Andric return I->getIntrinsicID() == Intrinsic::dbg_declare;
4500b57cec5SDimitry Andric }
classof(const Value * V)4510b57cec5SDimitry Andric static bool classof(const Value *V) {
4520b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
4530b57cec5SDimitry Andric }
4540b57cec5SDimitry Andric /// @}
4550b57cec5SDimitry Andric };
4560b57cec5SDimitry Andric
4570b57cec5SDimitry Andric /// This represents the llvm.dbg.value instruction.
4580b57cec5SDimitry Andric class DbgValueInst : public DbgVariableIntrinsic {
4590b57cec5SDimitry Andric public:
460fe6060f1SDimitry Andric // The default argument should only be used in ISel, and the default option
461fe6060f1SDimitry Andric // should be removed once ISel support for multiple location ops is complete.
462fe6060f1SDimitry Andric Value *getValue(unsigned OpIdx = 0) const {
463fe6060f1SDimitry Andric return getVariableLocationOp(OpIdx);
464fe6060f1SDimitry Andric }
getValues()465fe6060f1SDimitry Andric iterator_range<location_op_iterator> getValues() const {
466fe6060f1SDimitry Andric return location_ops();
4670b57cec5SDimitry Andric }
4680b57cec5SDimitry Andric
4690b57cec5SDimitry Andric /// \name Casting methods
4700b57cec5SDimitry Andric /// @{
classof(const IntrinsicInst * I)4710b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) {
472bdd1243dSDimitry Andric return I->getIntrinsicID() == Intrinsic::dbg_value ||
473bdd1243dSDimitry Andric I->getIntrinsicID() == Intrinsic::dbg_assign;
474bdd1243dSDimitry Andric }
classof(const Value * V)475bdd1243dSDimitry Andric static bool classof(const Value *V) {
476bdd1243dSDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
477bdd1243dSDimitry Andric }
478bdd1243dSDimitry Andric /// @}
479bdd1243dSDimitry Andric };
480bdd1243dSDimitry Andric
481bdd1243dSDimitry Andric /// This represents the llvm.dbg.assign instruction.
482bdd1243dSDimitry Andric class DbgAssignIntrinsic : public DbgValueInst {
483bdd1243dSDimitry Andric enum Operands {
484bdd1243dSDimitry Andric OpValue,
485bdd1243dSDimitry Andric OpVar,
486bdd1243dSDimitry Andric OpExpr,
487bdd1243dSDimitry Andric OpAssignID,
488bdd1243dSDimitry Andric OpAddress,
489bdd1243dSDimitry Andric OpAddressExpr,
490bdd1243dSDimitry Andric };
491bdd1243dSDimitry Andric
492bdd1243dSDimitry Andric public:
493bdd1243dSDimitry Andric Value *getAddress() const;
getRawAddress()494bdd1243dSDimitry Andric Metadata *getRawAddress() const {
495bdd1243dSDimitry Andric return cast<MetadataAsValue>(getArgOperand(OpAddress))->getMetadata();
496bdd1243dSDimitry Andric }
getRawAssignID()497bdd1243dSDimitry Andric Metadata *getRawAssignID() const {
498bdd1243dSDimitry Andric return cast<MetadataAsValue>(getArgOperand(OpAssignID))->getMetadata();
499bdd1243dSDimitry Andric }
getAssignID()500bdd1243dSDimitry Andric DIAssignID *getAssignID() const { return cast<DIAssignID>(getRawAssignID()); }
getRawAddressExpression()501bdd1243dSDimitry Andric Metadata *getRawAddressExpression() const {
502bdd1243dSDimitry Andric return cast<MetadataAsValue>(getArgOperand(OpAddressExpr))->getMetadata();
503bdd1243dSDimitry Andric }
getAddressExpression()504bdd1243dSDimitry Andric DIExpression *getAddressExpression() const {
505bdd1243dSDimitry Andric return cast<DIExpression>(getRawAddressExpression());
506bdd1243dSDimitry Andric }
setAddressExpression(DIExpression * NewExpr)507bdd1243dSDimitry Andric void setAddressExpression(DIExpression *NewExpr) {
508bdd1243dSDimitry Andric setArgOperand(OpAddressExpr,
509bdd1243dSDimitry Andric MetadataAsValue::get(NewExpr->getContext(), NewExpr));
510bdd1243dSDimitry Andric }
511bdd1243dSDimitry Andric void setAssignId(DIAssignID *New);
512bdd1243dSDimitry Andric void setAddress(Value *V);
513bdd1243dSDimitry Andric /// Kill the address component.
514bdd1243dSDimitry Andric void setKillAddress();
515bdd1243dSDimitry Andric /// Check whether this kills the address component. This doesn't take into
516bdd1243dSDimitry Andric /// account the position of the intrinsic, therefore a returned value of false
517bdd1243dSDimitry Andric /// does not guarentee the address is a valid location for the variable at the
518bdd1243dSDimitry Andric /// intrinsic's position in IR.
519bdd1243dSDimitry Andric bool isKillAddress() const;
520bdd1243dSDimitry Andric void setValue(Value *V);
521bdd1243dSDimitry Andric /// \name Casting methods
522bdd1243dSDimitry Andric /// @{
classof(const IntrinsicInst * I)523bdd1243dSDimitry Andric static bool classof(const IntrinsicInst *I) {
524bdd1243dSDimitry Andric return I->getIntrinsicID() == Intrinsic::dbg_assign;
5250b57cec5SDimitry Andric }
classof(const Value * V)5260b57cec5SDimitry Andric static bool classof(const Value *V) {
5270b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
5280b57cec5SDimitry Andric }
5290b57cec5SDimitry Andric /// @}
5300b57cec5SDimitry Andric };
5310b57cec5SDimitry Andric
5320b57cec5SDimitry Andric /// This represents the llvm.dbg.label instruction.
5330b57cec5SDimitry Andric class DbgLabelInst : public DbgInfoIntrinsic {
5340b57cec5SDimitry Andric public:
getLabel()5355ffd83dbSDimitry Andric DILabel *getLabel() const { return cast<DILabel>(getRawLabel()); }
setLabel(DILabel * NewLabel)5360fca6ea1SDimitry Andric void setLabel(DILabel *NewLabel) {
5370fca6ea1SDimitry Andric setArgOperand(0, MetadataAsValue::get(getContext(), NewLabel));
5380fca6ea1SDimitry Andric }
5390b57cec5SDimitry Andric
getRawLabel()5400b57cec5SDimitry Andric Metadata *getRawLabel() const {
5410b57cec5SDimitry Andric return cast<MetadataAsValue>(getArgOperand(0))->getMetadata();
5420b57cec5SDimitry Andric }
5430b57cec5SDimitry Andric
5440b57cec5SDimitry Andric /// Methods for support type inquiry through isa, cast, and dyn_cast:
5450b57cec5SDimitry Andric /// @{
classof(const IntrinsicInst * I)5460b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) {
5470b57cec5SDimitry Andric return I->getIntrinsicID() == Intrinsic::dbg_label;
5480b57cec5SDimitry Andric }
classof(const Value * V)5490b57cec5SDimitry Andric static bool classof(const Value *V) {
5500b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
5510b57cec5SDimitry Andric }
5520b57cec5SDimitry Andric /// @}
5530b57cec5SDimitry Andric };
5540b57cec5SDimitry Andric
5555ffd83dbSDimitry Andric /// This is the common base class for vector predication intrinsics.
5565ffd83dbSDimitry Andric class VPIntrinsic : public IntrinsicInst {
5575ffd83dbSDimitry Andric public:
558fe6060f1SDimitry Andric /// \brief Declares a llvm.vp.* intrinsic in \p M that matches the parameters
5590eae32dcSDimitry Andric /// \p Params. Additionally, the load and gather intrinsics require
5600eae32dcSDimitry Andric /// \p ReturnType to be specified.
561fe6060f1SDimitry Andric static Function *getDeclarationForParams(Module *M, Intrinsic::ID,
5620eae32dcSDimitry Andric Type *ReturnType,
563fe6060f1SDimitry Andric ArrayRef<Value *> Params);
564fe6060f1SDimitry Andric
565bdd1243dSDimitry Andric static std::optional<unsigned> getMaskParamPos(Intrinsic::ID IntrinsicID);
566bdd1243dSDimitry Andric static std::optional<unsigned> getVectorLengthParamPos(
567bdd1243dSDimitry Andric Intrinsic::ID IntrinsicID);
5685ffd83dbSDimitry Andric
5695ffd83dbSDimitry Andric /// The llvm.vp.* intrinsics for this instruction Opcode
570fe6060f1SDimitry Andric static Intrinsic::ID getForOpcode(unsigned OC);
5715ffd83dbSDimitry Andric
572*52418fc2SDimitry Andric /// The llvm.vp.* intrinsics for this intrinsic ID \p Id. Return \p Id if it
573*52418fc2SDimitry Andric /// is already a VP intrinsic.
574*52418fc2SDimitry Andric static Intrinsic::ID getForIntrinsic(Intrinsic::ID Id);
575*52418fc2SDimitry Andric
5765ffd83dbSDimitry Andric // Whether \p ID is a VP intrinsic ID.
577fe6060f1SDimitry Andric static bool isVPIntrinsic(Intrinsic::ID);
5785ffd83dbSDimitry Andric
579fe6060f1SDimitry Andric /// \return The mask parameter or nullptr.
5805ffd83dbSDimitry Andric Value *getMaskParam() const;
581fe6060f1SDimitry Andric void setMaskParam(Value *);
5825ffd83dbSDimitry Andric
583fe6060f1SDimitry Andric /// \return The vector length parameter or nullptr.
5845ffd83dbSDimitry Andric Value *getVectorLengthParam() const;
585fe6060f1SDimitry Andric void setVectorLengthParam(Value *);
5865ffd83dbSDimitry Andric
587fe6060f1SDimitry Andric /// \return Whether the vector length param can be ignored.
5885ffd83dbSDimitry Andric bool canIgnoreVectorLengthParam() const;
5895ffd83dbSDimitry Andric
590fe6060f1SDimitry Andric /// \return The static element count (vector number of elements) the vector
5915ffd83dbSDimitry Andric /// length parameter applies to.
5925ffd83dbSDimitry Andric ElementCount getStaticVectorLength() const;
5935ffd83dbSDimitry Andric
594fe6060f1SDimitry Andric /// \return The alignment of the pointer used by this load/store/gather or
595fe6060f1SDimitry Andric /// scatter.
596fe6060f1SDimitry Andric MaybeAlign getPointerAlignment() const;
597fe6060f1SDimitry Andric // MaybeAlign setPointerAlignment(Align NewAlign); // TODO
598fe6060f1SDimitry Andric
599fe6060f1SDimitry Andric /// \return The pointer operand of this load,store, gather or scatter.
600fe6060f1SDimitry Andric Value *getMemoryPointerParam() const;
601bdd1243dSDimitry Andric static std::optional<unsigned> getMemoryPointerParamPos(Intrinsic::ID);
602fe6060f1SDimitry Andric
603fe6060f1SDimitry Andric /// \return The data (payload) operand of this store or scatter.
604fe6060f1SDimitry Andric Value *getMemoryDataParam() const;
605bdd1243dSDimitry Andric static std::optional<unsigned> getMemoryDataParamPos(Intrinsic::ID);
606fe6060f1SDimitry Andric
6075ffd83dbSDimitry Andric // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)6085ffd83dbSDimitry Andric static bool classof(const IntrinsicInst *I) {
609fe6060f1SDimitry Andric return isVPIntrinsic(I->getIntrinsicID());
6105ffd83dbSDimitry Andric }
classof(const Value * V)6115ffd83dbSDimitry Andric static bool classof(const Value *V) {
6125ffd83dbSDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
6135ffd83dbSDimitry Andric }
6145ffd83dbSDimitry Andric
6155ffd83dbSDimitry Andric // Equivalent non-predicated opcode
getFunctionalOpcode()616bdd1243dSDimitry Andric std::optional<unsigned> getFunctionalOpcode() const {
617fe6060f1SDimitry Andric return getFunctionalOpcodeForVP(getIntrinsicID());
6185ffd83dbSDimitry Andric }
6195ffd83dbSDimitry Andric
6205f757f3fSDimitry Andric // Equivalent non-predicated intrinsic ID
getFunctionalIntrinsicID()6215f757f3fSDimitry Andric std::optional<unsigned> getFunctionalIntrinsicID() const {
6225f757f3fSDimitry Andric return getFunctionalIntrinsicIDForVP(getIntrinsicID());
6235f757f3fSDimitry Andric }
6245f757f3fSDimitry Andric
62506c3fb27SDimitry Andric // Equivalent non-predicated constrained ID
getConstrainedIntrinsicID()62606c3fb27SDimitry Andric std::optional<unsigned> getConstrainedIntrinsicID() const {
62706c3fb27SDimitry Andric return getConstrainedIntrinsicIDForVP(getIntrinsicID());
62806c3fb27SDimitry Andric }
62906c3fb27SDimitry Andric
6305ffd83dbSDimitry Andric // Equivalent non-predicated opcode
631bdd1243dSDimitry Andric static std::optional<unsigned> getFunctionalOpcodeForVP(Intrinsic::ID ID);
63206c3fb27SDimitry Andric
6335f757f3fSDimitry Andric // Equivalent non-predicated intrinsic ID
6345f757f3fSDimitry Andric static std::optional<Intrinsic::ID>
6355f757f3fSDimitry Andric getFunctionalIntrinsicIDForVP(Intrinsic::ID ID);
6365f757f3fSDimitry Andric
63706c3fb27SDimitry Andric // Equivalent non-predicated constrained ID
6385f757f3fSDimitry Andric static std::optional<Intrinsic::ID>
63906c3fb27SDimitry Andric getConstrainedIntrinsicIDForVP(Intrinsic::ID ID);
6405ffd83dbSDimitry Andric };
6415ffd83dbSDimitry Andric
642349cc55cSDimitry Andric /// This represents vector predication reduction intrinsics.
643349cc55cSDimitry Andric class VPReductionIntrinsic : public VPIntrinsic {
644349cc55cSDimitry Andric public:
645349cc55cSDimitry Andric static bool isVPReduction(Intrinsic::ID ID);
646349cc55cSDimitry Andric
647349cc55cSDimitry Andric unsigned getStartParamPos() const;
648349cc55cSDimitry Andric unsigned getVectorParamPos() const;
649349cc55cSDimitry Andric
650bdd1243dSDimitry Andric static std::optional<unsigned> getStartParamPos(Intrinsic::ID ID);
651bdd1243dSDimitry Andric static std::optional<unsigned> getVectorParamPos(Intrinsic::ID ID);
652349cc55cSDimitry Andric
653349cc55cSDimitry Andric /// Methods for support type inquiry through isa, cast, and dyn_cast:
654349cc55cSDimitry Andric /// @{
classof(const IntrinsicInst * I)655349cc55cSDimitry Andric static bool classof(const IntrinsicInst *I) {
656349cc55cSDimitry Andric return VPReductionIntrinsic::isVPReduction(I->getIntrinsicID());
657349cc55cSDimitry Andric }
classof(const Value * V)658349cc55cSDimitry Andric static bool classof(const Value *V) {
659349cc55cSDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
660349cc55cSDimitry Andric }
661349cc55cSDimitry Andric /// @}
662349cc55cSDimitry Andric };
663349cc55cSDimitry Andric
66481ad6265SDimitry Andric class VPCastIntrinsic : public VPIntrinsic {
66581ad6265SDimitry Andric public:
66681ad6265SDimitry Andric static bool isVPCast(Intrinsic::ID ID);
66781ad6265SDimitry Andric
66881ad6265SDimitry Andric /// Methods for support type inquiry through isa, cast, and dyn_cast:
66981ad6265SDimitry Andric /// @{
classof(const IntrinsicInst * I)67081ad6265SDimitry Andric static bool classof(const IntrinsicInst *I) {
67181ad6265SDimitry Andric return VPCastIntrinsic::isVPCast(I->getIntrinsicID());
67281ad6265SDimitry Andric }
classof(const Value * V)67381ad6265SDimitry Andric static bool classof(const Value *V) {
67481ad6265SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
67581ad6265SDimitry Andric }
67681ad6265SDimitry Andric /// @}
67781ad6265SDimitry Andric };
67881ad6265SDimitry Andric
67981ad6265SDimitry Andric class VPCmpIntrinsic : public VPIntrinsic {
68081ad6265SDimitry Andric public:
68181ad6265SDimitry Andric static bool isVPCmp(Intrinsic::ID ID);
68281ad6265SDimitry Andric
68381ad6265SDimitry Andric CmpInst::Predicate getPredicate() const;
68481ad6265SDimitry Andric
68581ad6265SDimitry Andric /// Methods for support type inquiry through isa, cast, and dyn_cast:
68681ad6265SDimitry Andric /// @{
classof(const IntrinsicInst * I)68781ad6265SDimitry Andric static bool classof(const IntrinsicInst *I) {
68881ad6265SDimitry Andric return VPCmpIntrinsic::isVPCmp(I->getIntrinsicID());
68981ad6265SDimitry Andric }
classof(const Value * V)69081ad6265SDimitry Andric static bool classof(const Value *V) {
69181ad6265SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
69281ad6265SDimitry Andric }
69381ad6265SDimitry Andric /// @}
69481ad6265SDimitry Andric };
69581ad6265SDimitry Andric
6965f757f3fSDimitry Andric class VPBinOpIntrinsic : public VPIntrinsic {
6975f757f3fSDimitry Andric public:
6985f757f3fSDimitry Andric static bool isVPBinOp(Intrinsic::ID ID);
6995f757f3fSDimitry Andric
7005f757f3fSDimitry Andric /// Methods for support type inquiry through isa, cast, and dyn_cast:
7015f757f3fSDimitry Andric /// @{
classof(const IntrinsicInst * I)7025f757f3fSDimitry Andric static bool classof(const IntrinsicInst *I) {
7035f757f3fSDimitry Andric return VPBinOpIntrinsic::isVPBinOp(I->getIntrinsicID());
7045f757f3fSDimitry Andric }
classof(const Value * V)7055f757f3fSDimitry Andric static bool classof(const Value *V) {
7065f757f3fSDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
7075f757f3fSDimitry Andric }
7085f757f3fSDimitry Andric /// @}
7095f757f3fSDimitry Andric };
7105f757f3fSDimitry Andric
7115f757f3fSDimitry Andric
7120b57cec5SDimitry Andric /// This is the common base class for constrained floating point intrinsics.
7130b57cec5SDimitry Andric class ConstrainedFPIntrinsic : public IntrinsicInst {
7140b57cec5SDimitry Andric public:
7150fca6ea1SDimitry Andric unsigned getNonMetadataArgCount() const;
716bdd1243dSDimitry Andric std::optional<RoundingMode> getRoundingMode() const;
717bdd1243dSDimitry Andric std::optional<fp::ExceptionBehavior> getExceptionBehavior() const;
718fe6060f1SDimitry Andric bool isDefaultFPEnvironment() const;
7190b57cec5SDimitry Andric
720480093f4SDimitry Andric // Methods for support type inquiry through isa, cast, and dyn_cast:
721480093f4SDimitry Andric static bool classof(const IntrinsicInst *I);
classof(const Value * V)722480093f4SDimitry Andric static bool classof(const Value *V) {
723480093f4SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
724480093f4SDimitry Andric }
725480093f4SDimitry Andric };
7260b57cec5SDimitry Andric
727480093f4SDimitry Andric /// Constrained floating point compare intrinsics.
728480093f4SDimitry Andric class ConstrainedFPCmpIntrinsic : public ConstrainedFPIntrinsic {
729480093f4SDimitry Andric public:
730480093f4SDimitry Andric FCmpInst::Predicate getPredicate() const;
isSignaling()73181ad6265SDimitry Andric bool isSignaling() const {
73281ad6265SDimitry Andric return getIntrinsicID() == Intrinsic::experimental_constrained_fcmps;
73381ad6265SDimitry Andric }
7340b57cec5SDimitry Andric
7350b57cec5SDimitry Andric // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)7360b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) {
7370b57cec5SDimitry Andric switch (I->getIntrinsicID()) {
738480093f4SDimitry Andric case Intrinsic::experimental_constrained_fcmp:
739480093f4SDimitry Andric case Intrinsic::experimental_constrained_fcmps:
7400b57cec5SDimitry Andric return true;
7415ffd83dbSDimitry Andric default:
7425ffd83dbSDimitry Andric return false;
7430b57cec5SDimitry Andric }
7440b57cec5SDimitry Andric }
classof(const Value * V)7450b57cec5SDimitry Andric static bool classof(const Value *V) {
7460b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
7470b57cec5SDimitry Andric }
7480b57cec5SDimitry Andric };
7490b57cec5SDimitry Andric
750fe6060f1SDimitry Andric /// This class represents min/max intrinsics.
751fe6060f1SDimitry Andric class MinMaxIntrinsic : public IntrinsicInst {
752fe6060f1SDimitry Andric public:
classof(const IntrinsicInst * I)753fe6060f1SDimitry Andric static bool classof(const IntrinsicInst *I) {
754fe6060f1SDimitry Andric switch (I->getIntrinsicID()) {
755fe6060f1SDimitry Andric case Intrinsic::umin:
756fe6060f1SDimitry Andric case Intrinsic::umax:
757fe6060f1SDimitry Andric case Intrinsic::smin:
758fe6060f1SDimitry Andric case Intrinsic::smax:
759fe6060f1SDimitry Andric return true;
760fe6060f1SDimitry Andric default:
761fe6060f1SDimitry Andric return false;
762fe6060f1SDimitry Andric }
763fe6060f1SDimitry Andric }
classof(const Value * V)764fe6060f1SDimitry Andric static bool classof(const Value *V) {
765fe6060f1SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
766fe6060f1SDimitry Andric }
767fe6060f1SDimitry Andric
getLHS()768fe6060f1SDimitry Andric Value *getLHS() const { return const_cast<Value *>(getArgOperand(0)); }
getRHS()769fe6060f1SDimitry Andric Value *getRHS() const { return const_cast<Value *>(getArgOperand(1)); }
770fe6060f1SDimitry Andric
771fe6060f1SDimitry Andric /// Returns the comparison predicate underlying the intrinsic.
getPredicate(Intrinsic::ID ID)77204eeddc0SDimitry Andric static ICmpInst::Predicate getPredicate(Intrinsic::ID ID) {
77304eeddc0SDimitry Andric switch (ID) {
774fe6060f1SDimitry Andric case Intrinsic::umin:
775fe6060f1SDimitry Andric return ICmpInst::Predicate::ICMP_ULT;
776fe6060f1SDimitry Andric case Intrinsic::umax:
777fe6060f1SDimitry Andric return ICmpInst::Predicate::ICMP_UGT;
778fe6060f1SDimitry Andric case Intrinsic::smin:
779fe6060f1SDimitry Andric return ICmpInst::Predicate::ICMP_SLT;
780fe6060f1SDimitry Andric case Intrinsic::smax:
781fe6060f1SDimitry Andric return ICmpInst::Predicate::ICMP_SGT;
782fe6060f1SDimitry Andric default:
783fe6060f1SDimitry Andric llvm_unreachable("Invalid intrinsic");
784fe6060f1SDimitry Andric }
785fe6060f1SDimitry Andric }
786fe6060f1SDimitry Andric
78704eeddc0SDimitry Andric /// Returns the comparison predicate underlying the intrinsic.
getPredicate()78804eeddc0SDimitry Andric ICmpInst::Predicate getPredicate() const {
78904eeddc0SDimitry Andric return getPredicate(getIntrinsicID());
79004eeddc0SDimitry Andric }
79104eeddc0SDimitry Andric
792fe6060f1SDimitry Andric /// Whether the intrinsic is signed or unsigned.
isSigned(Intrinsic::ID ID)79304eeddc0SDimitry Andric static bool isSigned(Intrinsic::ID ID) {
79404eeddc0SDimitry Andric return ICmpInst::isSigned(getPredicate(ID));
79504eeddc0SDimitry Andric };
79604eeddc0SDimitry Andric
79704eeddc0SDimitry Andric /// Whether the intrinsic is signed or unsigned.
isSigned()79804eeddc0SDimitry Andric bool isSigned() const { return isSigned(getIntrinsicID()); };
79904eeddc0SDimitry Andric
80004eeddc0SDimitry Andric /// Min/max intrinsics are monotonic, they operate on a fixed-bitwidth values,
80104eeddc0SDimitry Andric /// so there is a certain threshold value, upon reaching which,
80204eeddc0SDimitry Andric /// their value can no longer change. Return said threshold.
getSaturationPoint(Intrinsic::ID ID,unsigned numBits)80304eeddc0SDimitry Andric static APInt getSaturationPoint(Intrinsic::ID ID, unsigned numBits) {
80404eeddc0SDimitry Andric switch (ID) {
80504eeddc0SDimitry Andric case Intrinsic::umin:
80604eeddc0SDimitry Andric return APInt::getMinValue(numBits);
80704eeddc0SDimitry Andric case Intrinsic::umax:
80804eeddc0SDimitry Andric return APInt::getMaxValue(numBits);
80904eeddc0SDimitry Andric case Intrinsic::smin:
81004eeddc0SDimitry Andric return APInt::getSignedMinValue(numBits);
81104eeddc0SDimitry Andric case Intrinsic::smax:
81204eeddc0SDimitry Andric return APInt::getSignedMaxValue(numBits);
81304eeddc0SDimitry Andric default:
81404eeddc0SDimitry Andric llvm_unreachable("Invalid intrinsic");
81504eeddc0SDimitry Andric }
81604eeddc0SDimitry Andric }
81704eeddc0SDimitry Andric
81804eeddc0SDimitry Andric /// Min/max intrinsics are monotonic, they operate on a fixed-bitwidth values,
81904eeddc0SDimitry Andric /// so there is a certain threshold value, upon reaching which,
82004eeddc0SDimitry Andric /// their value can no longer change. Return said threshold.
getSaturationPoint(unsigned numBits)82104eeddc0SDimitry Andric APInt getSaturationPoint(unsigned numBits) const {
82204eeddc0SDimitry Andric return getSaturationPoint(getIntrinsicID(), numBits);
82304eeddc0SDimitry Andric }
82404eeddc0SDimitry Andric
82504eeddc0SDimitry Andric /// Min/max intrinsics are monotonic, they operate on a fixed-bitwidth values,
82604eeddc0SDimitry Andric /// so there is a certain threshold value, upon reaching which,
82704eeddc0SDimitry Andric /// their value can no longer change. Return said threshold.
getSaturationPoint(Intrinsic::ID ID,Type * Ty)82804eeddc0SDimitry Andric static Constant *getSaturationPoint(Intrinsic::ID ID, Type *Ty) {
82904eeddc0SDimitry Andric return Constant::getIntegerValue(
83004eeddc0SDimitry Andric Ty, getSaturationPoint(ID, Ty->getScalarSizeInBits()));
83104eeddc0SDimitry Andric }
83204eeddc0SDimitry Andric
83304eeddc0SDimitry Andric /// Min/max intrinsics are monotonic, they operate on a fixed-bitwidth values,
83404eeddc0SDimitry Andric /// so there is a certain threshold value, upon reaching which,
83504eeddc0SDimitry Andric /// their value can no longer change. Return said threshold.
getSaturationPoint(Type * Ty)83604eeddc0SDimitry Andric Constant *getSaturationPoint(Type *Ty) const {
83704eeddc0SDimitry Andric return getSaturationPoint(getIntrinsicID(), Ty);
83804eeddc0SDimitry Andric }
839fe6060f1SDimitry Andric };
840fe6060f1SDimitry Andric
8410fca6ea1SDimitry Andric /// This class represents a ucmp/scmp intrinsic
8420fca6ea1SDimitry Andric class CmpIntrinsic : public IntrinsicInst {
8430fca6ea1SDimitry Andric public:
classof(const IntrinsicInst * I)8440fca6ea1SDimitry Andric static bool classof(const IntrinsicInst *I) {
8450fca6ea1SDimitry Andric switch (I->getIntrinsicID()) {
8460fca6ea1SDimitry Andric case Intrinsic::scmp:
8470fca6ea1SDimitry Andric case Intrinsic::ucmp:
8480fca6ea1SDimitry Andric return true;
8490fca6ea1SDimitry Andric default:
8500fca6ea1SDimitry Andric return false;
8510fca6ea1SDimitry Andric }
8520fca6ea1SDimitry Andric }
classof(const Value * V)8530fca6ea1SDimitry Andric static bool classof(const Value *V) {
8540fca6ea1SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
8550fca6ea1SDimitry Andric }
8560fca6ea1SDimitry Andric
getLHS()8570fca6ea1SDimitry Andric Value *getLHS() const { return const_cast<Value *>(getArgOperand(0)); }
getRHS()8580fca6ea1SDimitry Andric Value *getRHS() const { return const_cast<Value *>(getArgOperand(1)); }
8590fca6ea1SDimitry Andric
isSigned(Intrinsic::ID ID)8600fca6ea1SDimitry Andric static bool isSigned(Intrinsic::ID ID) { return ID == Intrinsic::scmp; }
isSigned()8610fca6ea1SDimitry Andric bool isSigned() const { return isSigned(getIntrinsicID()); }
8620fca6ea1SDimitry Andric
getGTPredicate(Intrinsic::ID ID)8630fca6ea1SDimitry Andric static CmpInst::Predicate getGTPredicate(Intrinsic::ID ID) {
8640fca6ea1SDimitry Andric return isSigned(ID) ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT;
8650fca6ea1SDimitry Andric }
getGTPredicate()8660fca6ea1SDimitry Andric CmpInst::Predicate getGTPredicate() const {
8670fca6ea1SDimitry Andric return getGTPredicate(getIntrinsicID());
8680fca6ea1SDimitry Andric }
8690fca6ea1SDimitry Andric
getLTPredicate(Intrinsic::ID ID)8700fca6ea1SDimitry Andric static CmpInst::Predicate getLTPredicate(Intrinsic::ID ID) {
8710fca6ea1SDimitry Andric return isSigned(ID) ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT;
8720fca6ea1SDimitry Andric }
getLTPredicate()8730fca6ea1SDimitry Andric CmpInst::Predicate getLTPredicate() const {
8740fca6ea1SDimitry Andric return getLTPredicate(getIntrinsicID());
8750fca6ea1SDimitry Andric }
8760fca6ea1SDimitry Andric };
8770fca6ea1SDimitry Andric
8780b57cec5SDimitry Andric /// This class represents an intrinsic that is based on a binary operation.
8790b57cec5SDimitry Andric /// This includes op.with.overflow and saturating add/sub intrinsics.
8800b57cec5SDimitry Andric class BinaryOpIntrinsic : public IntrinsicInst {
8810b57cec5SDimitry Andric public:
classof(const IntrinsicInst * I)8820b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) {
8830b57cec5SDimitry Andric switch (I->getIntrinsicID()) {
8840b57cec5SDimitry Andric case Intrinsic::uadd_with_overflow:
8850b57cec5SDimitry Andric case Intrinsic::sadd_with_overflow:
8860b57cec5SDimitry Andric case Intrinsic::usub_with_overflow:
8870b57cec5SDimitry Andric case Intrinsic::ssub_with_overflow:
8880b57cec5SDimitry Andric case Intrinsic::umul_with_overflow:
8890b57cec5SDimitry Andric case Intrinsic::smul_with_overflow:
8900b57cec5SDimitry Andric case Intrinsic::uadd_sat:
8910b57cec5SDimitry Andric case Intrinsic::sadd_sat:
8920b57cec5SDimitry Andric case Intrinsic::usub_sat:
8930b57cec5SDimitry Andric case Intrinsic::ssub_sat:
8940b57cec5SDimitry Andric return true;
8950b57cec5SDimitry Andric default:
8960b57cec5SDimitry Andric return false;
8970b57cec5SDimitry Andric }
8980b57cec5SDimitry Andric }
classof(const Value * V)8990b57cec5SDimitry Andric static bool classof(const Value *V) {
9000b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
9010b57cec5SDimitry Andric }
9020b57cec5SDimitry Andric
getLHS()9030b57cec5SDimitry Andric Value *getLHS() const { return const_cast<Value *>(getArgOperand(0)); }
getRHS()9040b57cec5SDimitry Andric Value *getRHS() const { return const_cast<Value *>(getArgOperand(1)); }
9050b57cec5SDimitry Andric
9060b57cec5SDimitry Andric /// Returns the binary operation underlying the intrinsic.
9070b57cec5SDimitry Andric Instruction::BinaryOps getBinaryOp() const;
9080b57cec5SDimitry Andric
9090b57cec5SDimitry Andric /// Whether the intrinsic is signed or unsigned.
9100b57cec5SDimitry Andric bool isSigned() const;
9110b57cec5SDimitry Andric
9120b57cec5SDimitry Andric /// Returns one of OBO::NoSignedWrap or OBO::NoUnsignedWrap.
9130b57cec5SDimitry Andric unsigned getNoWrapKind() const;
9140b57cec5SDimitry Andric };
9150b57cec5SDimitry Andric
9160b57cec5SDimitry Andric /// Represents an op.with.overflow intrinsic.
9170b57cec5SDimitry Andric class WithOverflowInst : public BinaryOpIntrinsic {
9180b57cec5SDimitry Andric public:
classof(const IntrinsicInst * I)9190b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) {
9200b57cec5SDimitry Andric switch (I->getIntrinsicID()) {
9210b57cec5SDimitry Andric case Intrinsic::uadd_with_overflow:
9220b57cec5SDimitry Andric case Intrinsic::sadd_with_overflow:
9230b57cec5SDimitry Andric case Intrinsic::usub_with_overflow:
9240b57cec5SDimitry Andric case Intrinsic::ssub_with_overflow:
9250b57cec5SDimitry Andric case Intrinsic::umul_with_overflow:
9260b57cec5SDimitry Andric case Intrinsic::smul_with_overflow:
9270b57cec5SDimitry Andric return true;
9280b57cec5SDimitry Andric default:
9290b57cec5SDimitry Andric return false;
9300b57cec5SDimitry Andric }
9310b57cec5SDimitry Andric }
classof(const Value * V)9320b57cec5SDimitry Andric static bool classof(const Value *V) {
9330b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
9340b57cec5SDimitry Andric }
9350b57cec5SDimitry Andric };
9360b57cec5SDimitry Andric
9370b57cec5SDimitry Andric /// Represents a saturating add/sub intrinsic.
9380b57cec5SDimitry Andric class SaturatingInst : public BinaryOpIntrinsic {
9390b57cec5SDimitry Andric public:
classof(const IntrinsicInst * I)9400b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) {
9410b57cec5SDimitry Andric switch (I->getIntrinsicID()) {
9420b57cec5SDimitry Andric case Intrinsic::uadd_sat:
9430b57cec5SDimitry Andric case Intrinsic::sadd_sat:
9440b57cec5SDimitry Andric case Intrinsic::usub_sat:
9450b57cec5SDimitry Andric case Intrinsic::ssub_sat:
9460b57cec5SDimitry Andric return true;
9470b57cec5SDimitry Andric default:
9480b57cec5SDimitry Andric return false;
9490b57cec5SDimitry Andric }
9500b57cec5SDimitry Andric }
classof(const Value * V)9510b57cec5SDimitry Andric static bool classof(const Value *V) {
9520b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
9530b57cec5SDimitry Andric }
9540b57cec5SDimitry Andric };
9550b57cec5SDimitry Andric
9560b57cec5SDimitry Andric /// Common base class for all memory intrinsics. Simply provides
9570b57cec5SDimitry Andric /// common methods.
9580b57cec5SDimitry Andric /// Written as CRTP to avoid a common base class amongst the
9590b57cec5SDimitry Andric /// three atomicity hierarchies.
9600b57cec5SDimitry Andric template <typename Derived> class MemIntrinsicBase : public IntrinsicInst {
9610b57cec5SDimitry Andric private:
9620b57cec5SDimitry Andric enum { ARG_DEST = 0, ARG_LENGTH = 2 };
9630b57cec5SDimitry Andric
9640b57cec5SDimitry Andric public:
getRawDest()9650b57cec5SDimitry Andric Value *getRawDest() const {
9660b57cec5SDimitry Andric return const_cast<Value *>(getArgOperand(ARG_DEST));
9670b57cec5SDimitry Andric }
getRawDestUse()9680b57cec5SDimitry Andric const Use &getRawDestUse() const { return getArgOperandUse(ARG_DEST); }
getRawDestUse()9690b57cec5SDimitry Andric Use &getRawDestUse() { return getArgOperandUse(ARG_DEST); }
9700b57cec5SDimitry Andric
getLength()9710b57cec5SDimitry Andric Value *getLength() const {
9720b57cec5SDimitry Andric return const_cast<Value *>(getArgOperand(ARG_LENGTH));
9730b57cec5SDimitry Andric }
getLengthUse()9740b57cec5SDimitry Andric const Use &getLengthUse() const { return getArgOperandUse(ARG_LENGTH); }
getLengthUse()9750b57cec5SDimitry Andric Use &getLengthUse() { return getArgOperandUse(ARG_LENGTH); }
9760b57cec5SDimitry Andric
9770b57cec5SDimitry Andric /// This is just like getRawDest, but it strips off any cast
9780b57cec5SDimitry Andric /// instructions (including addrspacecast) that feed it, giving the
9790b57cec5SDimitry Andric /// original input. The returned value is guaranteed to be a pointer.
getDest()9800b57cec5SDimitry Andric Value *getDest() const { return getRawDest()->stripPointerCasts(); }
9810b57cec5SDimitry Andric
getDestAddressSpace()9820b57cec5SDimitry Andric unsigned getDestAddressSpace() const {
9830b57cec5SDimitry Andric return cast<PointerType>(getRawDest()->getType())->getAddressSpace();
9840b57cec5SDimitry Andric }
9850b57cec5SDimitry Andric
986480093f4SDimitry Andric /// FIXME: Remove this function once transition to Align is over.
987480093f4SDimitry Andric /// Use getDestAlign() instead.
988bdd1243dSDimitry Andric LLVM_DEPRECATED("Use getDestAlign() instead", "getDestAlign")
getDestAlignment()9895ffd83dbSDimitry Andric unsigned getDestAlignment() const {
9905ffd83dbSDimitry Andric if (auto MA = getParamAlign(ARG_DEST))
9915ffd83dbSDimitry Andric return MA->value();
9925ffd83dbSDimitry Andric return 0;
9935ffd83dbSDimitry Andric }
getDestAlign()994480093f4SDimitry Andric MaybeAlign getDestAlign() const { return getParamAlign(ARG_DEST); }
9950b57cec5SDimitry Andric
9960b57cec5SDimitry Andric /// Set the specified arguments of the instruction.
setDest(Value * Ptr)9970b57cec5SDimitry Andric void setDest(Value *Ptr) {
9980b57cec5SDimitry Andric assert(getRawDest()->getType() == Ptr->getType() &&
9990b57cec5SDimitry Andric "setDest called with pointer of wrong type!");
10000b57cec5SDimitry Andric setArgOperand(ARG_DEST, Ptr);
10010b57cec5SDimitry Andric }
10020b57cec5SDimitry Andric
setDestAlignment(MaybeAlign Alignment)1003480093f4SDimitry Andric void setDestAlignment(MaybeAlign Alignment) {
10040b57cec5SDimitry Andric removeParamAttr(ARG_DEST, Attribute::Alignment);
1005480093f4SDimitry Andric if (Alignment)
1006480093f4SDimitry Andric addParamAttr(ARG_DEST,
1007480093f4SDimitry Andric Attribute::getWithAlignment(getContext(), *Alignment));
1008480093f4SDimitry Andric }
setDestAlignment(Align Alignment)1009480093f4SDimitry Andric void setDestAlignment(Align Alignment) {
1010480093f4SDimitry Andric removeParamAttr(ARG_DEST, Attribute::Alignment);
1011480093f4SDimitry Andric addParamAttr(ARG_DEST,
1012480093f4SDimitry Andric Attribute::getWithAlignment(getContext(), Alignment));
10130b57cec5SDimitry Andric }
10140b57cec5SDimitry Andric
setLength(Value * L)10150b57cec5SDimitry Andric void setLength(Value *L) {
10160b57cec5SDimitry Andric assert(getLength()->getType() == L->getType() &&
10170b57cec5SDimitry Andric "setLength called with value of wrong type!");
10180b57cec5SDimitry Andric setArgOperand(ARG_LENGTH, L);
10190b57cec5SDimitry Andric }
10200b57cec5SDimitry Andric };
10210b57cec5SDimitry Andric
10220b57cec5SDimitry Andric /// Common base class for all memory transfer intrinsics. Simply provides
10230b57cec5SDimitry Andric /// common methods.
10240b57cec5SDimitry Andric template <class BaseCL> class MemTransferBase : public BaseCL {
10250b57cec5SDimitry Andric private:
10260b57cec5SDimitry Andric enum { ARG_SOURCE = 1 };
10270b57cec5SDimitry Andric
10280b57cec5SDimitry Andric public:
10290b57cec5SDimitry Andric /// Return the arguments to the instruction.
getRawSource()10300b57cec5SDimitry Andric Value *getRawSource() const {
10310b57cec5SDimitry Andric return const_cast<Value *>(BaseCL::getArgOperand(ARG_SOURCE));
10320b57cec5SDimitry Andric }
getRawSourceUse()10330b57cec5SDimitry Andric const Use &getRawSourceUse() const {
10340b57cec5SDimitry Andric return BaseCL::getArgOperandUse(ARG_SOURCE);
10350b57cec5SDimitry Andric }
getRawSourceUse()10360b57cec5SDimitry Andric Use &getRawSourceUse() { return BaseCL::getArgOperandUse(ARG_SOURCE); }
10370b57cec5SDimitry Andric
10380b57cec5SDimitry Andric /// This is just like getRawSource, but it strips off any cast
10390b57cec5SDimitry Andric /// instructions that feed it, giving the original input. The returned
10400b57cec5SDimitry Andric /// value is guaranteed to be a pointer.
getSource()10410b57cec5SDimitry Andric Value *getSource() const { return getRawSource()->stripPointerCasts(); }
10420b57cec5SDimitry Andric
getSourceAddressSpace()10430b57cec5SDimitry Andric unsigned getSourceAddressSpace() const {
10440b57cec5SDimitry Andric return cast<PointerType>(getRawSource()->getType())->getAddressSpace();
10450b57cec5SDimitry Andric }
10460b57cec5SDimitry Andric
1047480093f4SDimitry Andric /// FIXME: Remove this function once transition to Align is over.
1048480093f4SDimitry Andric /// Use getSourceAlign() instead.
1049bdd1243dSDimitry Andric LLVM_DEPRECATED("Use getSourceAlign() instead", "getSourceAlign")
getSourceAlignment()10500b57cec5SDimitry Andric unsigned getSourceAlignment() const {
10515ffd83dbSDimitry Andric if (auto MA = BaseCL::getParamAlign(ARG_SOURCE))
10525ffd83dbSDimitry Andric return MA->value();
10535ffd83dbSDimitry Andric return 0;
10540b57cec5SDimitry Andric }
10550b57cec5SDimitry Andric
getSourceAlign()1056480093f4SDimitry Andric MaybeAlign getSourceAlign() const {
1057480093f4SDimitry Andric return BaseCL::getParamAlign(ARG_SOURCE);
1058480093f4SDimitry Andric }
1059480093f4SDimitry Andric
setSource(Value * Ptr)10600b57cec5SDimitry Andric void setSource(Value *Ptr) {
10610b57cec5SDimitry Andric assert(getRawSource()->getType() == Ptr->getType() &&
10620b57cec5SDimitry Andric "setSource called with pointer of wrong type!");
10630b57cec5SDimitry Andric BaseCL::setArgOperand(ARG_SOURCE, Ptr);
10640b57cec5SDimitry Andric }
10650b57cec5SDimitry Andric
setSourceAlignment(MaybeAlign Alignment)1066480093f4SDimitry Andric void setSourceAlignment(MaybeAlign Alignment) {
10670b57cec5SDimitry Andric BaseCL::removeParamAttr(ARG_SOURCE, Attribute::Alignment);
1068480093f4SDimitry Andric if (Alignment)
1069480093f4SDimitry Andric BaseCL::addParamAttr(ARG_SOURCE, Attribute::getWithAlignment(
1070480093f4SDimitry Andric BaseCL::getContext(), *Alignment));
1071480093f4SDimitry Andric }
1072bdd1243dSDimitry Andric
setSourceAlignment(Align Alignment)1073480093f4SDimitry Andric void setSourceAlignment(Align Alignment) {
1074480093f4SDimitry Andric BaseCL::removeParamAttr(ARG_SOURCE, Attribute::Alignment);
1075480093f4SDimitry Andric BaseCL::addParamAttr(ARG_SOURCE, Attribute::getWithAlignment(
1076480093f4SDimitry Andric BaseCL::getContext(), Alignment));
10770b57cec5SDimitry Andric }
10780b57cec5SDimitry Andric };
10790b57cec5SDimitry Andric
10800b57cec5SDimitry Andric /// Common base class for all memset intrinsics. Simply provides
10810b57cec5SDimitry Andric /// common methods.
10820b57cec5SDimitry Andric template <class BaseCL> class MemSetBase : public BaseCL {
10830b57cec5SDimitry Andric private:
10840b57cec5SDimitry Andric enum { ARG_VALUE = 1 };
10850b57cec5SDimitry Andric
10860b57cec5SDimitry Andric public:
getValue()10870b57cec5SDimitry Andric Value *getValue() const {
10880b57cec5SDimitry Andric return const_cast<Value *>(BaseCL::getArgOperand(ARG_VALUE));
10890b57cec5SDimitry Andric }
getValueUse()10905ffd83dbSDimitry Andric const Use &getValueUse() const { return BaseCL::getArgOperandUse(ARG_VALUE); }
getValueUse()10910b57cec5SDimitry Andric Use &getValueUse() { return BaseCL::getArgOperandUse(ARG_VALUE); }
10920b57cec5SDimitry Andric
setValue(Value * Val)10930b57cec5SDimitry Andric void setValue(Value *Val) {
10940b57cec5SDimitry Andric assert(getValue()->getType() == Val->getType() &&
10950b57cec5SDimitry Andric "setValue called with value of wrong type!");
10960b57cec5SDimitry Andric BaseCL::setArgOperand(ARG_VALUE, Val);
10970b57cec5SDimitry Andric }
10980b57cec5SDimitry Andric };
10990b57cec5SDimitry Andric
11000b57cec5SDimitry Andric // The common base class for the atomic memset/memmove/memcpy intrinsics
11010b57cec5SDimitry Andric // i.e. llvm.element.unordered.atomic.memset/memcpy/memmove
11020b57cec5SDimitry Andric class AtomicMemIntrinsic : public MemIntrinsicBase<AtomicMemIntrinsic> {
11030b57cec5SDimitry Andric private:
11040b57cec5SDimitry Andric enum { ARG_ELEMENTSIZE = 3 };
11050b57cec5SDimitry Andric
11060b57cec5SDimitry Andric public:
getRawElementSizeInBytes()11070b57cec5SDimitry Andric Value *getRawElementSizeInBytes() const {
11080b57cec5SDimitry Andric return const_cast<Value *>(getArgOperand(ARG_ELEMENTSIZE));
11090b57cec5SDimitry Andric }
11100b57cec5SDimitry Andric
getElementSizeInBytesCst()11110b57cec5SDimitry Andric ConstantInt *getElementSizeInBytesCst() const {
11120b57cec5SDimitry Andric return cast<ConstantInt>(getRawElementSizeInBytes());
11130b57cec5SDimitry Andric }
11140b57cec5SDimitry Andric
getElementSizeInBytes()11150b57cec5SDimitry Andric uint32_t getElementSizeInBytes() const {
11160b57cec5SDimitry Andric return getElementSizeInBytesCst()->getZExtValue();
11170b57cec5SDimitry Andric }
11180b57cec5SDimitry Andric
setElementSizeInBytes(Constant * V)11190b57cec5SDimitry Andric void setElementSizeInBytes(Constant *V) {
11200b57cec5SDimitry Andric assert(V->getType() == Type::getInt8Ty(getContext()) &&
11210b57cec5SDimitry Andric "setElementSizeInBytes called with value of wrong type!");
11220b57cec5SDimitry Andric setArgOperand(ARG_ELEMENTSIZE, V);
11230b57cec5SDimitry Andric }
11240b57cec5SDimitry Andric
classof(const IntrinsicInst * I)11250b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) {
11260b57cec5SDimitry Andric switch (I->getIntrinsicID()) {
11270b57cec5SDimitry Andric case Intrinsic::memcpy_element_unordered_atomic:
11280b57cec5SDimitry Andric case Intrinsic::memmove_element_unordered_atomic:
11290b57cec5SDimitry Andric case Intrinsic::memset_element_unordered_atomic:
11300b57cec5SDimitry Andric return true;
11310b57cec5SDimitry Andric default:
11320b57cec5SDimitry Andric return false;
11330b57cec5SDimitry Andric }
11340b57cec5SDimitry Andric }
classof(const Value * V)11350b57cec5SDimitry Andric static bool classof(const Value *V) {
11360b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
11370b57cec5SDimitry Andric }
11380b57cec5SDimitry Andric };
11390b57cec5SDimitry Andric
11400b57cec5SDimitry Andric /// This class represents atomic memset intrinsic
11410b57cec5SDimitry Andric // i.e. llvm.element.unordered.atomic.memset
11420b57cec5SDimitry Andric class AtomicMemSetInst : public MemSetBase<AtomicMemIntrinsic> {
11430b57cec5SDimitry Andric public:
classof(const IntrinsicInst * I)11440b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) {
11450b57cec5SDimitry Andric return I->getIntrinsicID() == Intrinsic::memset_element_unordered_atomic;
11460b57cec5SDimitry Andric }
classof(const Value * V)11470b57cec5SDimitry Andric static bool classof(const Value *V) {
11480b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
11490b57cec5SDimitry Andric }
11500b57cec5SDimitry Andric };
11510b57cec5SDimitry Andric
11520b57cec5SDimitry Andric // This class wraps the atomic memcpy/memmove intrinsics
11530b57cec5SDimitry Andric // i.e. llvm.element.unordered.atomic.memcpy/memmove
11540b57cec5SDimitry Andric class AtomicMemTransferInst : public MemTransferBase<AtomicMemIntrinsic> {
11550b57cec5SDimitry Andric public:
classof(const IntrinsicInst * I)11560b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) {
11570b57cec5SDimitry Andric switch (I->getIntrinsicID()) {
11580b57cec5SDimitry Andric case Intrinsic::memcpy_element_unordered_atomic:
11590b57cec5SDimitry Andric case Intrinsic::memmove_element_unordered_atomic:
11600b57cec5SDimitry Andric return true;
11610b57cec5SDimitry Andric default:
11620b57cec5SDimitry Andric return false;
11630b57cec5SDimitry Andric }
11640b57cec5SDimitry Andric }
classof(const Value * V)11650b57cec5SDimitry Andric static bool classof(const Value *V) {
11660b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
11670b57cec5SDimitry Andric }
11680b57cec5SDimitry Andric };
11690b57cec5SDimitry Andric
11700b57cec5SDimitry Andric /// This class represents the atomic memcpy intrinsic
11710b57cec5SDimitry Andric /// i.e. llvm.element.unordered.atomic.memcpy
11720b57cec5SDimitry Andric class AtomicMemCpyInst : public AtomicMemTransferInst {
11730b57cec5SDimitry Andric public:
classof(const IntrinsicInst * I)11740b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) {
11750b57cec5SDimitry Andric return I->getIntrinsicID() == Intrinsic::memcpy_element_unordered_atomic;
11760b57cec5SDimitry Andric }
classof(const Value * V)11770b57cec5SDimitry Andric static bool classof(const Value *V) {
11780b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
11790b57cec5SDimitry Andric }
11800b57cec5SDimitry Andric };
11810b57cec5SDimitry Andric
11820b57cec5SDimitry Andric /// This class represents the atomic memmove intrinsic
11830b57cec5SDimitry Andric /// i.e. llvm.element.unordered.atomic.memmove
11840b57cec5SDimitry Andric class AtomicMemMoveInst : public AtomicMemTransferInst {
11850b57cec5SDimitry Andric public:
classof(const IntrinsicInst * I)11860b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) {
11870b57cec5SDimitry Andric return I->getIntrinsicID() == Intrinsic::memmove_element_unordered_atomic;
11880b57cec5SDimitry Andric }
classof(const Value * V)11890b57cec5SDimitry Andric static bool classof(const Value *V) {
11900b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
11910b57cec5SDimitry Andric }
11920b57cec5SDimitry Andric };
11930b57cec5SDimitry Andric
11940b57cec5SDimitry Andric /// This is the common base class for memset/memcpy/memmove.
11950b57cec5SDimitry Andric class MemIntrinsic : public MemIntrinsicBase<MemIntrinsic> {
11960b57cec5SDimitry Andric private:
11970b57cec5SDimitry Andric enum { ARG_VOLATILE = 3 };
11980b57cec5SDimitry Andric
11990b57cec5SDimitry Andric public:
getVolatileCst()12000b57cec5SDimitry Andric ConstantInt *getVolatileCst() const {
12015ffd83dbSDimitry Andric return cast<ConstantInt>(const_cast<Value *>(getArgOperand(ARG_VOLATILE)));
12020b57cec5SDimitry Andric }
12030b57cec5SDimitry Andric
isVolatile()12045ffd83dbSDimitry Andric bool isVolatile() const { return !getVolatileCst()->isZero(); }
12050b57cec5SDimitry Andric
setVolatile(Constant * V)12060b57cec5SDimitry Andric void setVolatile(Constant *V) { setArgOperand(ARG_VOLATILE, V); }
12070b57cec5SDimitry Andric
12080b57cec5SDimitry Andric // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)12090b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) {
12100b57cec5SDimitry Andric switch (I->getIntrinsicID()) {
12110b57cec5SDimitry Andric case Intrinsic::memcpy:
12120b57cec5SDimitry Andric case Intrinsic::memmove:
12130b57cec5SDimitry Andric case Intrinsic::memset:
121481ad6265SDimitry Andric case Intrinsic::memset_inline:
12155ffd83dbSDimitry Andric case Intrinsic::memcpy_inline:
12160b57cec5SDimitry Andric return true;
12175ffd83dbSDimitry Andric default:
12185ffd83dbSDimitry Andric return false;
12190b57cec5SDimitry Andric }
12200b57cec5SDimitry Andric }
classof(const Value * V)12210b57cec5SDimitry Andric static bool classof(const Value *V) {
12220b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
12230b57cec5SDimitry Andric }
12240b57cec5SDimitry Andric };
12250b57cec5SDimitry Andric
122681ad6265SDimitry Andric /// This class wraps the llvm.memset and llvm.memset.inline intrinsics.
12270b57cec5SDimitry Andric class MemSetInst : public MemSetBase<MemIntrinsic> {
12280b57cec5SDimitry Andric public:
12290b57cec5SDimitry Andric // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)12300b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) {
123181ad6265SDimitry Andric switch (I->getIntrinsicID()) {
123281ad6265SDimitry Andric case Intrinsic::memset:
123381ad6265SDimitry Andric case Intrinsic::memset_inline:
123481ad6265SDimitry Andric return true;
123581ad6265SDimitry Andric default:
123681ad6265SDimitry Andric return false;
123781ad6265SDimitry Andric }
123881ad6265SDimitry Andric }
classof(const Value * V)123981ad6265SDimitry Andric static bool classof(const Value *V) {
124081ad6265SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
124181ad6265SDimitry Andric }
124281ad6265SDimitry Andric };
124381ad6265SDimitry Andric
124481ad6265SDimitry Andric /// This class wraps the llvm.memset.inline intrinsic.
124581ad6265SDimitry Andric class MemSetInlineInst : public MemSetInst {
124681ad6265SDimitry Andric public:
124781ad6265SDimitry Andric // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)124881ad6265SDimitry Andric static bool classof(const IntrinsicInst *I) {
124981ad6265SDimitry Andric return I->getIntrinsicID() == Intrinsic::memset_inline;
12500b57cec5SDimitry Andric }
classof(const Value * V)12510b57cec5SDimitry Andric static bool classof(const Value *V) {
12520b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
12530b57cec5SDimitry Andric }
12540b57cec5SDimitry Andric };
12550b57cec5SDimitry Andric
12560b57cec5SDimitry Andric /// This class wraps the llvm.memcpy/memmove intrinsics.
12570b57cec5SDimitry Andric class MemTransferInst : public MemTransferBase<MemIntrinsic> {
12580b57cec5SDimitry Andric public:
12590b57cec5SDimitry Andric // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)12600b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) {
12615ffd83dbSDimitry Andric switch (I->getIntrinsicID()) {
12625ffd83dbSDimitry Andric case Intrinsic::memcpy:
12635ffd83dbSDimitry Andric case Intrinsic::memmove:
12645ffd83dbSDimitry Andric case Intrinsic::memcpy_inline:
12655ffd83dbSDimitry Andric return true;
12665ffd83dbSDimitry Andric default:
12675ffd83dbSDimitry Andric return false;
12685ffd83dbSDimitry Andric }
12690b57cec5SDimitry Andric }
classof(const Value * V)12700b57cec5SDimitry Andric static bool classof(const Value *V) {
12710b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
12720b57cec5SDimitry Andric }
12730b57cec5SDimitry Andric };
12740b57cec5SDimitry Andric
12750b57cec5SDimitry Andric /// This class wraps the llvm.memcpy intrinsic.
12760b57cec5SDimitry Andric class MemCpyInst : public MemTransferInst {
12770b57cec5SDimitry Andric public:
12780b57cec5SDimitry Andric // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)12790b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) {
1280fe6060f1SDimitry Andric return I->getIntrinsicID() == Intrinsic::memcpy ||
1281fe6060f1SDimitry Andric I->getIntrinsicID() == Intrinsic::memcpy_inline;
12820b57cec5SDimitry Andric }
classof(const Value * V)12830b57cec5SDimitry Andric static bool classof(const Value *V) {
12840b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
12850b57cec5SDimitry Andric }
12860b57cec5SDimitry Andric };
12870b57cec5SDimitry Andric
12880b57cec5SDimitry Andric /// This class wraps the llvm.memmove intrinsic.
12890b57cec5SDimitry Andric class MemMoveInst : public MemTransferInst {
12900b57cec5SDimitry Andric public:
12910b57cec5SDimitry Andric // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)12920b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) {
12930b57cec5SDimitry Andric return I->getIntrinsicID() == Intrinsic::memmove;
12940b57cec5SDimitry Andric }
classof(const Value * V)12950b57cec5SDimitry Andric static bool classof(const Value *V) {
12960b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
12970b57cec5SDimitry Andric }
12980b57cec5SDimitry Andric };
12990b57cec5SDimitry Andric
13005ffd83dbSDimitry Andric /// This class wraps the llvm.memcpy.inline intrinsic.
1301fe6060f1SDimitry Andric class MemCpyInlineInst : public MemCpyInst {
13025ffd83dbSDimitry Andric public:
13035ffd83dbSDimitry Andric // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)13045ffd83dbSDimitry Andric static bool classof(const IntrinsicInst *I) {
13055ffd83dbSDimitry Andric return I->getIntrinsicID() == Intrinsic::memcpy_inline;
13065ffd83dbSDimitry Andric }
classof(const Value * V)13075ffd83dbSDimitry Andric static bool classof(const Value *V) {
13085ffd83dbSDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
13095ffd83dbSDimitry Andric }
13105ffd83dbSDimitry Andric };
13115ffd83dbSDimitry Andric
13120b57cec5SDimitry Andric // The common base class for any memset/memmove/memcpy intrinsics;
13130b57cec5SDimitry Andric // whether they be atomic or non-atomic.
13140b57cec5SDimitry Andric // i.e. llvm.element.unordered.atomic.memset/memcpy/memmove
13150b57cec5SDimitry Andric // and llvm.memset/memcpy/memmove
13160b57cec5SDimitry Andric class AnyMemIntrinsic : public MemIntrinsicBase<AnyMemIntrinsic> {
13170b57cec5SDimitry Andric public:
isVolatile()13180b57cec5SDimitry Andric bool isVolatile() const {
13190b57cec5SDimitry Andric // Only the non-atomic intrinsics can be volatile
13200b57cec5SDimitry Andric if (auto *MI = dyn_cast<MemIntrinsic>(this))
13210b57cec5SDimitry Andric return MI->isVolatile();
13220b57cec5SDimitry Andric return false;
13230b57cec5SDimitry Andric }
13240b57cec5SDimitry Andric
classof(const IntrinsicInst * I)13250b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) {
13260b57cec5SDimitry Andric switch (I->getIntrinsicID()) {
13270b57cec5SDimitry Andric case Intrinsic::memcpy:
13285ffd83dbSDimitry Andric case Intrinsic::memcpy_inline:
13290b57cec5SDimitry Andric case Intrinsic::memmove:
13300b57cec5SDimitry Andric case Intrinsic::memset:
133181ad6265SDimitry Andric case Intrinsic::memset_inline:
13320b57cec5SDimitry Andric case Intrinsic::memcpy_element_unordered_atomic:
13330b57cec5SDimitry Andric case Intrinsic::memmove_element_unordered_atomic:
13340b57cec5SDimitry Andric case Intrinsic::memset_element_unordered_atomic:
13350b57cec5SDimitry Andric return true;
13360b57cec5SDimitry Andric default:
13370b57cec5SDimitry Andric return false;
13380b57cec5SDimitry Andric }
13390b57cec5SDimitry Andric }
classof(const Value * V)13400b57cec5SDimitry Andric static bool classof(const Value *V) {
13410b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
13420b57cec5SDimitry Andric }
13430b57cec5SDimitry Andric };
13440b57cec5SDimitry Andric
13450b57cec5SDimitry Andric /// This class represents any memset intrinsic
13460b57cec5SDimitry Andric // i.e. llvm.element.unordered.atomic.memset
13470b57cec5SDimitry Andric // and llvm.memset
13480b57cec5SDimitry Andric class AnyMemSetInst : public MemSetBase<AnyMemIntrinsic> {
13490b57cec5SDimitry Andric public:
classof(const IntrinsicInst * I)13500b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) {
13510b57cec5SDimitry Andric switch (I->getIntrinsicID()) {
13520b57cec5SDimitry Andric case Intrinsic::memset:
135381ad6265SDimitry Andric case Intrinsic::memset_inline:
13540b57cec5SDimitry Andric case Intrinsic::memset_element_unordered_atomic:
13550b57cec5SDimitry Andric return true;
13560b57cec5SDimitry Andric default:
13570b57cec5SDimitry Andric return false;
13580b57cec5SDimitry Andric }
13590b57cec5SDimitry Andric }
classof(const Value * V)13600b57cec5SDimitry Andric static bool classof(const Value *V) {
13610b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
13620b57cec5SDimitry Andric }
13630b57cec5SDimitry Andric };
13640b57cec5SDimitry Andric
13650b57cec5SDimitry Andric // This class wraps any memcpy/memmove intrinsics
13660b57cec5SDimitry Andric // i.e. llvm.element.unordered.atomic.memcpy/memmove
13670b57cec5SDimitry Andric // and llvm.memcpy/memmove
13680b57cec5SDimitry Andric class AnyMemTransferInst : public MemTransferBase<AnyMemIntrinsic> {
13690b57cec5SDimitry Andric public:
classof(const IntrinsicInst * I)13700b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) {
13710b57cec5SDimitry Andric switch (I->getIntrinsicID()) {
13720b57cec5SDimitry Andric case Intrinsic::memcpy:
13735ffd83dbSDimitry Andric case Intrinsic::memcpy_inline:
13740b57cec5SDimitry Andric case Intrinsic::memmove:
13750b57cec5SDimitry Andric case Intrinsic::memcpy_element_unordered_atomic:
13760b57cec5SDimitry Andric case Intrinsic::memmove_element_unordered_atomic:
13770b57cec5SDimitry Andric return true;
13780b57cec5SDimitry Andric default:
13790b57cec5SDimitry Andric return false;
13800b57cec5SDimitry Andric }
13810b57cec5SDimitry Andric }
classof(const Value * V)13820b57cec5SDimitry Andric static bool classof(const Value *V) {
13830b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
13840b57cec5SDimitry Andric }
13850b57cec5SDimitry Andric };
13860b57cec5SDimitry Andric
13870b57cec5SDimitry Andric /// This class represents any memcpy intrinsic
13880b57cec5SDimitry Andric /// i.e. llvm.element.unordered.atomic.memcpy
13890b57cec5SDimitry Andric /// and llvm.memcpy
13900b57cec5SDimitry Andric class AnyMemCpyInst : public AnyMemTransferInst {
13910b57cec5SDimitry Andric public:
classof(const IntrinsicInst * I)13920b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) {
13930b57cec5SDimitry Andric switch (I->getIntrinsicID()) {
13940b57cec5SDimitry Andric case Intrinsic::memcpy:
13955ffd83dbSDimitry Andric case Intrinsic::memcpy_inline:
13960b57cec5SDimitry Andric case Intrinsic::memcpy_element_unordered_atomic:
13970b57cec5SDimitry Andric return true;
13980b57cec5SDimitry Andric default:
13990b57cec5SDimitry Andric return false;
14000b57cec5SDimitry Andric }
14010b57cec5SDimitry Andric }
classof(const Value * V)14020b57cec5SDimitry Andric static bool classof(const Value *V) {
14030b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
14040b57cec5SDimitry Andric }
14050b57cec5SDimitry Andric };
14060b57cec5SDimitry Andric
14070b57cec5SDimitry Andric /// This class represents any memmove intrinsic
14080b57cec5SDimitry Andric /// i.e. llvm.element.unordered.atomic.memmove
14090b57cec5SDimitry Andric /// and llvm.memmove
14100b57cec5SDimitry Andric class AnyMemMoveInst : public AnyMemTransferInst {
14110b57cec5SDimitry Andric public:
classof(const IntrinsicInst * I)14120b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) {
14130b57cec5SDimitry Andric switch (I->getIntrinsicID()) {
14140b57cec5SDimitry Andric case Intrinsic::memmove:
14150b57cec5SDimitry Andric case Intrinsic::memmove_element_unordered_atomic:
14160b57cec5SDimitry Andric return true;
14170b57cec5SDimitry Andric default:
14180b57cec5SDimitry Andric return false;
14190b57cec5SDimitry Andric }
14200b57cec5SDimitry Andric }
classof(const Value * V)14210b57cec5SDimitry Andric static bool classof(const Value *V) {
14220b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
14230b57cec5SDimitry Andric }
14240b57cec5SDimitry Andric };
14250b57cec5SDimitry Andric
14260b57cec5SDimitry Andric /// This represents the llvm.va_start intrinsic.
14270b57cec5SDimitry Andric class VAStartInst : public IntrinsicInst {
14280b57cec5SDimitry Andric public:
classof(const IntrinsicInst * I)14290b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) {
14300b57cec5SDimitry Andric return I->getIntrinsicID() == Intrinsic::vastart;
14310b57cec5SDimitry Andric }
classof(const Value * V)14320b57cec5SDimitry Andric static bool classof(const Value *V) {
14330b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
14340b57cec5SDimitry Andric }
14350b57cec5SDimitry Andric
getArgList()14360b57cec5SDimitry Andric Value *getArgList() const { return const_cast<Value *>(getArgOperand(0)); }
14370b57cec5SDimitry Andric };
14380b57cec5SDimitry Andric
14390b57cec5SDimitry Andric /// This represents the llvm.va_end intrinsic.
14400b57cec5SDimitry Andric class VAEndInst : public IntrinsicInst {
14410b57cec5SDimitry Andric public:
classof(const IntrinsicInst * I)14420b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) {
14430b57cec5SDimitry Andric return I->getIntrinsicID() == Intrinsic::vaend;
14440b57cec5SDimitry Andric }
classof(const Value * V)14450b57cec5SDimitry Andric static bool classof(const Value *V) {
14460b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
14470b57cec5SDimitry Andric }
14480b57cec5SDimitry Andric
getArgList()14490b57cec5SDimitry Andric Value *getArgList() const { return const_cast<Value *>(getArgOperand(0)); }
14500b57cec5SDimitry Andric };
14510b57cec5SDimitry Andric
14520b57cec5SDimitry Andric /// This represents the llvm.va_copy intrinsic.
14530b57cec5SDimitry Andric class VACopyInst : public IntrinsicInst {
14540b57cec5SDimitry Andric public:
classof(const IntrinsicInst * I)14550b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) {
14560b57cec5SDimitry Andric return I->getIntrinsicID() == Intrinsic::vacopy;
14570b57cec5SDimitry Andric }
classof(const Value * V)14580b57cec5SDimitry Andric static bool classof(const Value *V) {
14590b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
14600b57cec5SDimitry Andric }
14610b57cec5SDimitry Andric
getDest()14620b57cec5SDimitry Andric Value *getDest() const { return const_cast<Value *>(getArgOperand(0)); }
getSrc()14630b57cec5SDimitry Andric Value *getSrc() const { return const_cast<Value *>(getArgOperand(1)); }
14640b57cec5SDimitry Andric };
14650b57cec5SDimitry Andric
146604eeddc0SDimitry Andric /// A base class for all instrprof intrinsics.
146704eeddc0SDimitry Andric class InstrProfInstBase : public IntrinsicInst {
14680fca6ea1SDimitry Andric protected:
isCounterBase(const IntrinsicInst & I)14690fca6ea1SDimitry Andric static bool isCounterBase(const IntrinsicInst &I) {
14700fca6ea1SDimitry Andric switch (I.getIntrinsicID()) {
14710fca6ea1SDimitry Andric case Intrinsic::instrprof_cover:
14720fca6ea1SDimitry Andric case Intrinsic::instrprof_increment:
14730fca6ea1SDimitry Andric case Intrinsic::instrprof_increment_step:
14740fca6ea1SDimitry Andric case Intrinsic::instrprof_callsite:
14750fca6ea1SDimitry Andric case Intrinsic::instrprof_timestamp:
14760fca6ea1SDimitry Andric case Intrinsic::instrprof_value_profile:
14770fca6ea1SDimitry Andric return true;
14780fca6ea1SDimitry Andric }
14790fca6ea1SDimitry Andric return false;
14800fca6ea1SDimitry Andric }
isMCDCBitmapBase(const IntrinsicInst & I)14810fca6ea1SDimitry Andric static bool isMCDCBitmapBase(const IntrinsicInst &I) {
14820fca6ea1SDimitry Andric switch (I.getIntrinsicID()) {
14830fca6ea1SDimitry Andric case Intrinsic::instrprof_mcdc_parameters:
14840fca6ea1SDimitry Andric case Intrinsic::instrprof_mcdc_tvbitmap_update:
14850fca6ea1SDimitry Andric return true;
14860fca6ea1SDimitry Andric }
14870fca6ea1SDimitry Andric return false;
14880fca6ea1SDimitry Andric }
14890fca6ea1SDimitry Andric
149004eeddc0SDimitry Andric public:
classof(const Value * V)14910fca6ea1SDimitry Andric static bool classof(const Value *V) {
14920fca6ea1SDimitry Andric if (const auto *Instr = dyn_cast<IntrinsicInst>(V))
14930fca6ea1SDimitry Andric return isCounterBase(*Instr) || isMCDCBitmapBase(*Instr);
14940fca6ea1SDimitry Andric return false;
14950fca6ea1SDimitry Andric }
149604eeddc0SDimitry Andric // The name of the instrumented function.
getName()149704eeddc0SDimitry Andric GlobalVariable *getName() const {
149804eeddc0SDimitry Andric return cast<GlobalVariable>(
149904eeddc0SDimitry Andric const_cast<Value *>(getArgOperand(0))->stripPointerCasts());
150004eeddc0SDimitry Andric }
150104eeddc0SDimitry Andric // The hash of the CFG for the instrumented function.
getHash()150204eeddc0SDimitry Andric ConstantInt *getHash() const {
150304eeddc0SDimitry Andric return cast<ConstantInt>(const_cast<Value *>(getArgOperand(1)));
150404eeddc0SDimitry Andric }
15055f757f3fSDimitry Andric };
15065f757f3fSDimitry Andric
15075f757f3fSDimitry Andric /// A base class for all instrprof counter intrinsics.
15085f757f3fSDimitry Andric class InstrProfCntrInstBase : public InstrProfInstBase {
15095f757f3fSDimitry Andric public:
classof(const Value * V)15100fca6ea1SDimitry Andric static bool classof(const Value *V) {
15110fca6ea1SDimitry Andric if (const auto *Instr = dyn_cast<IntrinsicInst>(V))
15120fca6ea1SDimitry Andric return InstrProfInstBase::isCounterBase(*Instr);
15130fca6ea1SDimitry Andric return false;
15140fca6ea1SDimitry Andric }
15150fca6ea1SDimitry Andric
151604eeddc0SDimitry Andric // The number of counters for the instrumented function.
151704eeddc0SDimitry Andric ConstantInt *getNumCounters() const;
151804eeddc0SDimitry Andric // The index of the counter that this instruction acts on.
151904eeddc0SDimitry Andric ConstantInt *getIndex() const;
152004eeddc0SDimitry Andric };
152104eeddc0SDimitry Andric
15221fd87a68SDimitry Andric /// This represents the llvm.instrprof.cover intrinsic.
15235f757f3fSDimitry Andric class InstrProfCoverInst : public InstrProfCntrInstBase {
15241fd87a68SDimitry Andric public:
classof(const IntrinsicInst * I)15251fd87a68SDimitry Andric static bool classof(const IntrinsicInst *I) {
15261fd87a68SDimitry Andric return I->getIntrinsicID() == Intrinsic::instrprof_cover;
15271fd87a68SDimitry Andric }
classof(const Value * V)15281fd87a68SDimitry Andric static bool classof(const Value *V) {
15291fd87a68SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
15301fd87a68SDimitry Andric }
15311fd87a68SDimitry Andric };
15321fd87a68SDimitry Andric
153304eeddc0SDimitry Andric /// This represents the llvm.instrprof.increment intrinsic.
15345f757f3fSDimitry Andric class InstrProfIncrementInst : public InstrProfCntrInstBase {
15350b57cec5SDimitry Andric public:
classof(const IntrinsicInst * I)15360b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) {
1537bdd1243dSDimitry Andric return I->getIntrinsicID() == Intrinsic::instrprof_increment ||
1538bdd1243dSDimitry Andric I->getIntrinsicID() == Intrinsic::instrprof_increment_step;
15390b57cec5SDimitry Andric }
classof(const Value * V)15400b57cec5SDimitry Andric static bool classof(const Value *V) {
15410b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
15420b57cec5SDimitry Andric }
15430b57cec5SDimitry Andric Value *getStep() const;
15440b57cec5SDimitry Andric };
15450b57cec5SDimitry Andric
154604eeddc0SDimitry Andric /// This represents the llvm.instrprof.increment.step intrinsic.
15470b57cec5SDimitry Andric class InstrProfIncrementInstStep : public InstrProfIncrementInst {
15480b57cec5SDimitry Andric public:
classof(const IntrinsicInst * I)15490b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) {
15500b57cec5SDimitry Andric return I->getIntrinsicID() == Intrinsic::instrprof_increment_step;
15510b57cec5SDimitry Andric }
classof(const Value * V)15520b57cec5SDimitry Andric static bool classof(const Value *V) {
15530b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
15540b57cec5SDimitry Andric }
15550b57cec5SDimitry Andric };
15560b57cec5SDimitry Andric
15570fca6ea1SDimitry Andric /// This represents the llvm.instrprof.callsite intrinsic.
15580fca6ea1SDimitry Andric /// It is structurally like the increment or step counters, hence the
15590fca6ea1SDimitry Andric /// inheritance relationship, albeit somewhat tenuous (it's not 'counting' per
15600fca6ea1SDimitry Andric /// se)
15610fca6ea1SDimitry Andric class InstrProfCallsite : public InstrProfCntrInstBase {
15620fca6ea1SDimitry Andric public:
classof(const IntrinsicInst * I)15630fca6ea1SDimitry Andric static bool classof(const IntrinsicInst *I) {
15640fca6ea1SDimitry Andric return I->getIntrinsicID() == Intrinsic::instrprof_callsite;
15650fca6ea1SDimitry Andric }
classof(const Value * V)15660fca6ea1SDimitry Andric static bool classof(const Value *V) {
15670fca6ea1SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
15680fca6ea1SDimitry Andric }
15690fca6ea1SDimitry Andric Value *getCallee() const;
15700fca6ea1SDimitry Andric };
15710fca6ea1SDimitry Andric
157206c3fb27SDimitry Andric /// This represents the llvm.instrprof.timestamp intrinsic.
15735f757f3fSDimitry Andric class InstrProfTimestampInst : public InstrProfCntrInstBase {
157406c3fb27SDimitry Andric public:
classof(const IntrinsicInst * I)157506c3fb27SDimitry Andric static bool classof(const IntrinsicInst *I) {
157606c3fb27SDimitry Andric return I->getIntrinsicID() == Intrinsic::instrprof_timestamp;
157706c3fb27SDimitry Andric }
classof(const Value * V)157806c3fb27SDimitry Andric static bool classof(const Value *V) {
157906c3fb27SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
158006c3fb27SDimitry Andric }
158106c3fb27SDimitry Andric };
158206c3fb27SDimitry Andric
158304eeddc0SDimitry Andric /// This represents the llvm.instrprof.value.profile intrinsic.
15845f757f3fSDimitry Andric class InstrProfValueProfileInst : public InstrProfCntrInstBase {
15850b57cec5SDimitry Andric public:
classof(const IntrinsicInst * I)15860b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) {
15870b57cec5SDimitry Andric return I->getIntrinsicID() == Intrinsic::instrprof_value_profile;
15880b57cec5SDimitry Andric }
classof(const Value * V)15890b57cec5SDimitry Andric static bool classof(const Value *V) {
15900b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
15910b57cec5SDimitry Andric }
15920b57cec5SDimitry Andric
getTargetValue()15930b57cec5SDimitry Andric Value *getTargetValue() const {
15940b57cec5SDimitry Andric return cast<Value>(const_cast<Value *>(getArgOperand(2)));
15950b57cec5SDimitry Andric }
15960b57cec5SDimitry Andric
getValueKind()15970b57cec5SDimitry Andric ConstantInt *getValueKind() const {
15980b57cec5SDimitry Andric return cast<ConstantInt>(const_cast<Value *>(getArgOperand(3)));
15990b57cec5SDimitry Andric }
16000b57cec5SDimitry Andric
16010b57cec5SDimitry Andric // Returns the value site index.
getIndex()16020b57cec5SDimitry Andric ConstantInt *getIndex() const {
16030b57cec5SDimitry Andric return cast<ConstantInt>(const_cast<Value *>(getArgOperand(4)));
16040b57cec5SDimitry Andric }
16050b57cec5SDimitry Andric };
16060b57cec5SDimitry Andric
16075f757f3fSDimitry Andric /// A base class for instrprof mcdc intrinsics that require global bitmap bytes.
16085f757f3fSDimitry Andric class InstrProfMCDCBitmapInstBase : public InstrProfInstBase {
16095f757f3fSDimitry Andric public:
classof(const IntrinsicInst * I)16105f757f3fSDimitry Andric static bool classof(const IntrinsicInst *I) {
16110fca6ea1SDimitry Andric return InstrProfInstBase::isMCDCBitmapBase(*I);
16125f757f3fSDimitry Andric }
classof(const Value * V)16135f757f3fSDimitry Andric static bool classof(const Value *V) {
16145f757f3fSDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
16155f757f3fSDimitry Andric }
16165f757f3fSDimitry Andric
16170fca6ea1SDimitry Andric /// \return The number of bits used for the MCDC bitmaps for the instrumented
16180fca6ea1SDimitry Andric /// function.
getNumBitmapBits()16190fca6ea1SDimitry Andric ConstantInt *getNumBitmapBits() const {
16200fca6ea1SDimitry Andric return cast<ConstantInt>(const_cast<Value *>(getArgOperand(2)));
16210fca6ea1SDimitry Andric }
16220fca6ea1SDimitry Andric
16235f757f3fSDimitry Andric /// \return The number of bytes used for the MCDC bitmaps for the instrumented
16245f757f3fSDimitry Andric /// function.
getNumBitmapBytes()16250fca6ea1SDimitry Andric auto getNumBitmapBytes() const {
16260fca6ea1SDimitry Andric return alignTo(getNumBitmapBits()->getZExtValue(), CHAR_BIT) / CHAR_BIT;
16275f757f3fSDimitry Andric }
16285f757f3fSDimitry Andric };
16295f757f3fSDimitry Andric
16305f757f3fSDimitry Andric /// This represents the llvm.instrprof.mcdc.parameters intrinsic.
16315f757f3fSDimitry Andric class InstrProfMCDCBitmapParameters : public InstrProfMCDCBitmapInstBase {
16325f757f3fSDimitry Andric public:
classof(const IntrinsicInst * I)16335f757f3fSDimitry Andric static bool classof(const IntrinsicInst *I) {
16345f757f3fSDimitry Andric return I->getIntrinsicID() == Intrinsic::instrprof_mcdc_parameters;
16355f757f3fSDimitry Andric }
classof(const Value * V)16365f757f3fSDimitry Andric static bool classof(const Value *V) {
16375f757f3fSDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
16385f757f3fSDimitry Andric }
16395f757f3fSDimitry Andric };
16405f757f3fSDimitry Andric
16415f757f3fSDimitry Andric /// This represents the llvm.instrprof.mcdc.tvbitmap.update intrinsic.
16425f757f3fSDimitry Andric class InstrProfMCDCTVBitmapUpdate : public InstrProfMCDCBitmapInstBase {
16435f757f3fSDimitry Andric public:
classof(const IntrinsicInst * I)16445f757f3fSDimitry Andric static bool classof(const IntrinsicInst *I) {
16455f757f3fSDimitry Andric return I->getIntrinsicID() == Intrinsic::instrprof_mcdc_tvbitmap_update;
16465f757f3fSDimitry Andric }
classof(const Value * V)16475f757f3fSDimitry Andric static bool classof(const Value *V) {
16485f757f3fSDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
16495f757f3fSDimitry Andric }
16505f757f3fSDimitry Andric
16515f757f3fSDimitry Andric /// \return The index of the TestVector Bitmap upon which this intrinsic
16525f757f3fSDimitry Andric /// acts.
getBitmapIndex()16535f757f3fSDimitry Andric ConstantInt *getBitmapIndex() const {
16540fca6ea1SDimitry Andric return cast<ConstantInt>(const_cast<Value *>(getArgOperand(2)));
16555f757f3fSDimitry Andric }
16565f757f3fSDimitry Andric
16575f757f3fSDimitry Andric /// \return The address of the corresponding condition bitmap containing
16585f757f3fSDimitry Andric /// the index of the TestVector to update within the TestVector Bitmap.
getMCDCCondBitmapAddr()16595f757f3fSDimitry Andric Value *getMCDCCondBitmapAddr() const {
16605f757f3fSDimitry Andric return cast<Value>(const_cast<Value *>(getArgOperand(3)));
16615f757f3fSDimitry Andric }
16625f757f3fSDimitry Andric };
16635f757f3fSDimitry Andric
1664e8d8bef9SDimitry Andric class PseudoProbeInst : public IntrinsicInst {
1665e8d8bef9SDimitry Andric public:
classof(const IntrinsicInst * I)1666e8d8bef9SDimitry Andric static bool classof(const IntrinsicInst *I) {
1667e8d8bef9SDimitry Andric return I->getIntrinsicID() == Intrinsic::pseudoprobe;
1668e8d8bef9SDimitry Andric }
1669e8d8bef9SDimitry Andric
classof(const Value * V)1670e8d8bef9SDimitry Andric static bool classof(const Value *V) {
1671e8d8bef9SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
1672e8d8bef9SDimitry Andric }
1673e8d8bef9SDimitry Andric
getFuncGuid()1674e8d8bef9SDimitry Andric ConstantInt *getFuncGuid() const {
1675e8d8bef9SDimitry Andric return cast<ConstantInt>(const_cast<Value *>(getArgOperand(0)));
1676e8d8bef9SDimitry Andric }
1677e8d8bef9SDimitry Andric
getIndex()1678d409305fSDimitry Andric ConstantInt *getIndex() const {
1679d409305fSDimitry Andric return cast<ConstantInt>(const_cast<Value *>(getArgOperand(1)));
1680d409305fSDimitry Andric }
1681d409305fSDimitry Andric
getAttributes()1682e8d8bef9SDimitry Andric ConstantInt *getAttributes() const {
1683e8d8bef9SDimitry Andric return cast<ConstantInt>(const_cast<Value *>(getArgOperand(2)));
1684e8d8bef9SDimitry Andric }
1685e8d8bef9SDimitry Andric
getFactor()1686d409305fSDimitry Andric ConstantInt *getFactor() const {
1687d409305fSDimitry Andric return cast<ConstantInt>(const_cast<Value *>(getArgOperand(3)));
1688e8d8bef9SDimitry Andric }
1689e8d8bef9SDimitry Andric };
1690e8d8bef9SDimitry Andric
1691e8d8bef9SDimitry Andric class NoAliasScopeDeclInst : public IntrinsicInst {
1692e8d8bef9SDimitry Andric public:
classof(const IntrinsicInst * I)1693e8d8bef9SDimitry Andric static bool classof(const IntrinsicInst *I) {
1694e8d8bef9SDimitry Andric return I->getIntrinsicID() == Intrinsic::experimental_noalias_scope_decl;
1695e8d8bef9SDimitry Andric }
1696e8d8bef9SDimitry Andric
classof(const Value * V)1697e8d8bef9SDimitry Andric static bool classof(const Value *V) {
1698e8d8bef9SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
1699e8d8bef9SDimitry Andric }
1700e8d8bef9SDimitry Andric
getScopeList()1701e8d8bef9SDimitry Andric MDNode *getScopeList() const {
1702e8d8bef9SDimitry Andric auto *MV =
1703e8d8bef9SDimitry Andric cast<MetadataAsValue>(getOperand(Intrinsic::NoAliasScopeDeclScopeArg));
1704e8d8bef9SDimitry Andric return cast<MDNode>(MV->getMetadata());
1705e8d8bef9SDimitry Andric }
1706e8d8bef9SDimitry Andric
setScopeList(MDNode * ScopeList)1707e8d8bef9SDimitry Andric void setScopeList(MDNode *ScopeList) {
1708e8d8bef9SDimitry Andric setOperand(Intrinsic::NoAliasScopeDeclScopeArg,
1709e8d8bef9SDimitry Andric MetadataAsValue::get(getContext(), ScopeList));
1710e8d8bef9SDimitry Andric }
1711e8d8bef9SDimitry Andric };
1712e8d8bef9SDimitry Andric
1713fe6060f1SDimitry Andric /// Common base class for representing values projected from a statepoint.
1714fe6060f1SDimitry Andric /// Currently, the only projections available are gc.result and gc.relocate.
1715fe6060f1SDimitry Andric class GCProjectionInst : public IntrinsicInst {
1716fe6060f1SDimitry Andric public:
classof(const IntrinsicInst * I)1717fe6060f1SDimitry Andric static bool classof(const IntrinsicInst *I) {
1718fe6060f1SDimitry Andric return I->getIntrinsicID() == Intrinsic::experimental_gc_relocate ||
1719fe6060f1SDimitry Andric I->getIntrinsicID() == Intrinsic::experimental_gc_result;
1720fe6060f1SDimitry Andric }
1721fe6060f1SDimitry Andric
classof(const Value * V)1722fe6060f1SDimitry Andric static bool classof(const Value *V) {
1723fe6060f1SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
1724fe6060f1SDimitry Andric }
1725fe6060f1SDimitry Andric
1726fe6060f1SDimitry Andric /// Return true if this relocate is tied to the invoke statepoint.
1727fe6060f1SDimitry Andric /// This includes relocates which are on the unwinding path.
isTiedToInvoke()1728fe6060f1SDimitry Andric bool isTiedToInvoke() const {
1729fe6060f1SDimitry Andric const Value *Token = getArgOperand(0);
1730fe6060f1SDimitry Andric
1731fe6060f1SDimitry Andric return isa<LandingPadInst>(Token) || isa<InvokeInst>(Token);
1732fe6060f1SDimitry Andric }
1733fe6060f1SDimitry Andric
1734fe6060f1SDimitry Andric /// The statepoint with which this gc.relocate is associated.
1735fcaf7f86SDimitry Andric const Value *getStatepoint() const;
1736fe6060f1SDimitry Andric };
1737fe6060f1SDimitry Andric
1738fe6060f1SDimitry Andric /// Represents calls to the gc.relocate intrinsic.
1739fe6060f1SDimitry Andric class GCRelocateInst : public GCProjectionInst {
1740fe6060f1SDimitry Andric public:
classof(const IntrinsicInst * I)1741fe6060f1SDimitry Andric static bool classof(const IntrinsicInst *I) {
1742fe6060f1SDimitry Andric return I->getIntrinsicID() == Intrinsic::experimental_gc_relocate;
1743fe6060f1SDimitry Andric }
1744fe6060f1SDimitry Andric
classof(const Value * V)1745fe6060f1SDimitry Andric static bool classof(const Value *V) {
1746fe6060f1SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
1747fe6060f1SDimitry Andric }
1748fe6060f1SDimitry Andric
1749fe6060f1SDimitry Andric /// The index into the associate statepoint's argument list
1750fe6060f1SDimitry Andric /// which contains the base pointer of the pointer whose
1751fe6060f1SDimitry Andric /// relocation this gc.relocate describes.
getBasePtrIndex()1752fe6060f1SDimitry Andric unsigned getBasePtrIndex() const {
1753fe6060f1SDimitry Andric return cast<ConstantInt>(getArgOperand(1))->getZExtValue();
1754fe6060f1SDimitry Andric }
1755fe6060f1SDimitry Andric
1756fe6060f1SDimitry Andric /// The index into the associate statepoint's argument list which
1757fe6060f1SDimitry Andric /// contains the pointer whose relocation this gc.relocate describes.
getDerivedPtrIndex()1758fe6060f1SDimitry Andric unsigned getDerivedPtrIndex() const {
1759fe6060f1SDimitry Andric return cast<ConstantInt>(getArgOperand(2))->getZExtValue();
1760fe6060f1SDimitry Andric }
1761fe6060f1SDimitry Andric
1762fe6060f1SDimitry Andric Value *getBasePtr() const;
1763fe6060f1SDimitry Andric Value *getDerivedPtr() const;
1764fe6060f1SDimitry Andric };
1765fe6060f1SDimitry Andric
1766fe6060f1SDimitry Andric /// Represents calls to the gc.result intrinsic.
1767fe6060f1SDimitry Andric class GCResultInst : public GCProjectionInst {
1768fe6060f1SDimitry Andric public:
classof(const IntrinsicInst * I)1769fe6060f1SDimitry Andric static bool classof(const IntrinsicInst *I) {
1770fe6060f1SDimitry Andric return I->getIntrinsicID() == Intrinsic::experimental_gc_result;
1771fe6060f1SDimitry Andric }
1772fe6060f1SDimitry Andric
classof(const Value * V)1773fe6060f1SDimitry Andric static bool classof(const Value *V) {
1774fe6060f1SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
1775fe6060f1SDimitry Andric }
1776fe6060f1SDimitry Andric };
1777fe6060f1SDimitry Andric
1778fe6060f1SDimitry Andric
1779fe6060f1SDimitry Andric /// This represents the llvm.assume intrinsic.
178006c3fb27SDimitry Andric class AssumeInst : public IntrinsicInst {
1781fe6060f1SDimitry Andric public:
classof(const IntrinsicInst * I)1782fe6060f1SDimitry Andric static bool classof(const IntrinsicInst *I) {
1783fe6060f1SDimitry Andric return I->getIntrinsicID() == Intrinsic::assume;
1784fe6060f1SDimitry Andric }
classof(const Value * V)1785fe6060f1SDimitry Andric static bool classof(const Value *V) {
1786fe6060f1SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
1787fe6060f1SDimitry Andric }
1788fe6060f1SDimitry Andric };
1789fe6060f1SDimitry Andric
1790cb14a3feSDimitry Andric /// Check if \p ID corresponds to a convergence control intrinsic.
isConvergenceControlIntrinsic(unsigned IntrinsicID)1791cb14a3feSDimitry Andric static inline bool isConvergenceControlIntrinsic(unsigned IntrinsicID) {
1792cb14a3feSDimitry Andric switch (IntrinsicID) {
1793cb14a3feSDimitry Andric default:
1794cb14a3feSDimitry Andric return false;
1795cb14a3feSDimitry Andric case Intrinsic::experimental_convergence_anchor:
1796cb14a3feSDimitry Andric case Intrinsic::experimental_convergence_entry:
1797cb14a3feSDimitry Andric case Intrinsic::experimental_convergence_loop:
1798cb14a3feSDimitry Andric return true;
1799cb14a3feSDimitry Andric }
1800cb14a3feSDimitry Andric }
1801cb14a3feSDimitry Andric
1802cb14a3feSDimitry Andric /// Represents calls to the llvm.experimintal.convergence.* intrinsics.
1803cb14a3feSDimitry Andric class ConvergenceControlInst : public IntrinsicInst {
1804cb14a3feSDimitry Andric public:
classof(const IntrinsicInst * I)1805cb14a3feSDimitry Andric static bool classof(const IntrinsicInst *I) {
1806cb14a3feSDimitry Andric return isConvergenceControlIntrinsic(I->getIntrinsicID());
1807cb14a3feSDimitry Andric }
1808cb14a3feSDimitry Andric
classof(const Value * V)1809cb14a3feSDimitry Andric static bool classof(const Value *V) {
1810cb14a3feSDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
1811cb14a3feSDimitry Andric }
18120fca6ea1SDimitry Andric
isAnchor()18130fca6ea1SDimitry Andric bool isAnchor() {
18140fca6ea1SDimitry Andric return getIntrinsicID() == Intrinsic::experimental_convergence_anchor;
18150fca6ea1SDimitry Andric }
isEntry()18160fca6ea1SDimitry Andric bool isEntry() {
18170fca6ea1SDimitry Andric return getIntrinsicID() == Intrinsic::experimental_convergence_entry;
18180fca6ea1SDimitry Andric }
isLoop()18190fca6ea1SDimitry Andric bool isLoop() {
18200fca6ea1SDimitry Andric return getIntrinsicID() == Intrinsic::experimental_convergence_loop;
18210fca6ea1SDimitry Andric }
1822cb14a3feSDimitry Andric };
1823cb14a3feSDimitry Andric
18240b57cec5SDimitry Andric } // end namespace llvm
18250b57cec5SDimitry Andric
18260b57cec5SDimitry Andric #endif // LLVM_IR_INTRINSICINST_H
1827