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. 550b57cec5SDimitry Andric Intrinsic::ID getIntrinsicID() const { 560b57cec5SDimitry Andric return getCalledFunction()->getIntrinsicID(); 570b57cec5SDimitry Andric } 580b57cec5SDimitry Andric 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. 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. 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: 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 } 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. 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 /// @{ 156bdd1243dSDimitry Andric static bool classof(const IntrinsicInst *I) { 157bdd1243dSDimitry Andric return isLifetimeIntrinsic(I->getIntrinsicID()); 158bdd1243dSDimitry Andric } 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. 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 /// @{ 1830b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) { 1845ffd83dbSDimitry Andric return isDbgInfoIntrinsic(I->getIntrinsicID()); 1850b57cec5SDimitry Andric } 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: 201fe6060f1SDimitry Andric location_op_iterator(ValueAsMetadata *SingleIter) : I(SingleIter) {} 202fe6060f1SDimitry Andric location_op_iterator(ValueAsMetadata **MultiIter) : I(MultiIter) {} 203fe6060f1SDimitry Andric 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; 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 } 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; 26006c3fb27SDimitry Andric unsigned getNumVariableLocationOps() const { 26106c3fb27SDimitry Andric if (hasArgList()) 26206c3fb27SDimitry Andric return cast<DIArgList>(getRawLocation())->getArgs().size(); 26306c3fb27SDimitry Andric return 1; 26406c3fb27SDimitry Andric } 26506c3fb27SDimitry Andric bool hasArgList() const { return isa<DIArgList>(getRawLocation()); } 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 324fe6060f1SDimitry Andric void setVariable(DILocalVariable *NewVar) { 325fe6060f1SDimitry Andric setArgOperand(1, MetadataAsValue::get(NewVar->getContext(), NewVar)); 326fe6060f1SDimitry Andric } 327fe6060f1SDimitry Andric 328fe6060f1SDimitry Andric void setExpression(DIExpression *NewExpr) { 329fe6060f1SDimitry Andric setArgOperand(2, MetadataAsValue::get(NewExpr->getContext(), NewExpr)); 330fe6060f1SDimitry Andric } 331fe6060f1SDimitry Andric 332fe6060f1SDimitry Andric unsigned getNumVariableLocationOps() const { 33306c3fb27SDimitry Andric return getWrappedLocation().getNumVariableLocationOps(); 334fe6060f1SDimitry Andric } 335fe6060f1SDimitry Andric 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. 3410b57cec5SDimitry Andric bool isAddressOfVariable() const { 34206c3fb27SDimitry Andric return getIntrinsicID() == Intrinsic::dbg_declare; 3430b57cec5SDimitry Andric } 3440b57cec5SDimitry Andric 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 357bdd1243dSDimitry Andric bool isKillLocation() const { 35806c3fb27SDimitry Andric return getWrappedLocation().isKillLocation(getExpression()); 359fe6060f1SDimitry Andric } 360fe6060f1SDimitry Andric 3610b57cec5SDimitry Andric DILocalVariable *getVariable() const { 3620b57cec5SDimitry Andric return cast<DILocalVariable>(getRawVariable()); 3630b57cec5SDimitry Andric } 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric DIExpression *getExpression() const { 3660b57cec5SDimitry Andric return cast<DIExpression>(getRawExpression()); 3670b57cec5SDimitry Andric } 3680b57cec5SDimitry Andric 369fe6060f1SDimitry Andric Metadata *getRawLocation() const { 370fe6060f1SDimitry Andric return cast<MetadataAsValue>(getArgOperand(0))->getMetadata(); 371fe6060f1SDimitry Andric } 372fe6060f1SDimitry Andric 37306c3fb27SDimitry Andric RawLocationWrapper getWrappedLocation() const { 37406c3fb27SDimitry Andric return RawLocationWrapper(getRawLocation()); 37506c3fb27SDimitry Andric } 37606c3fb27SDimitry Andric 3770b57cec5SDimitry Andric Metadata *getRawVariable() const { 3780b57cec5SDimitry Andric return cast<MetadataAsValue>(getArgOperand(1))->getMetadata(); 3790b57cec5SDimitry Andric } 3800b57cec5SDimitry Andric 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. 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. 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. 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 /// @{ 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 } 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: 431fe6060f1SDimitry Andric void setArgOperand(unsigned i, Value *v) { 432fe6060f1SDimitry Andric DbgInfoIntrinsic::setArgOperand(i, v); 433fe6060f1SDimitry Andric } 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: 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 /// @{ 4480b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) { 4490b57cec5SDimitry Andric return I->getIntrinsicID() == Intrinsic::dbg_declare; 4500b57cec5SDimitry Andric } 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 } 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 /// @{ 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 } 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; 494bdd1243dSDimitry Andric Metadata *getRawAddress() const { 495bdd1243dSDimitry Andric return cast<MetadataAsValue>(getArgOperand(OpAddress))->getMetadata(); 496bdd1243dSDimitry Andric } 497bdd1243dSDimitry Andric Metadata *getRawAssignID() const { 498bdd1243dSDimitry Andric return cast<MetadataAsValue>(getArgOperand(OpAssignID))->getMetadata(); 499bdd1243dSDimitry Andric } 500bdd1243dSDimitry Andric DIAssignID *getAssignID() const { return cast<DIAssignID>(getRawAssignID()); } 501bdd1243dSDimitry Andric Metadata *getRawAddressExpression() const { 502bdd1243dSDimitry Andric return cast<MetadataAsValue>(getArgOperand(OpAddressExpr))->getMetadata(); 503bdd1243dSDimitry Andric } 504bdd1243dSDimitry Andric DIExpression *getAddressExpression() const { 505bdd1243dSDimitry Andric return cast<DIExpression>(getRawAddressExpression()); 506bdd1243dSDimitry Andric } 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 /// @{ 523bdd1243dSDimitry Andric static bool classof(const IntrinsicInst *I) { 524bdd1243dSDimitry Andric return I->getIntrinsicID() == Intrinsic::dbg_assign; 5250b57cec5SDimitry Andric } 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: 5355ffd83dbSDimitry Andric DILabel *getLabel() const { return cast<DILabel>(getRawLabel()); } 5360fca6ea1SDimitry Andric void setLabel(DILabel *NewLabel) { 5370fca6ea1SDimitry Andric setArgOperand(0, MetadataAsValue::get(getContext(), NewLabel)); 5380fca6ea1SDimitry Andric } 5390b57cec5SDimitry Andric 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 /// @{ 5460b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) { 5470b57cec5SDimitry Andric return I->getIntrinsicID() == Intrinsic::dbg_label; 5480b57cec5SDimitry Andric } 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: 6085ffd83dbSDimitry Andric static bool classof(const IntrinsicInst *I) { 609fe6060f1SDimitry Andric return isVPIntrinsic(I->getIntrinsicID()); 6105ffd83dbSDimitry Andric } 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 616bdd1243dSDimitry Andric std::optional<unsigned> getFunctionalOpcode() const { 617fe6060f1SDimitry Andric return getFunctionalOpcodeForVP(getIntrinsicID()); 6185ffd83dbSDimitry Andric } 6195ffd83dbSDimitry Andric 6205f757f3fSDimitry Andric // Equivalent non-predicated intrinsic ID 6215f757f3fSDimitry Andric std::optional<unsigned> getFunctionalIntrinsicID() const { 6225f757f3fSDimitry Andric return getFunctionalIntrinsicIDForVP(getIntrinsicID()); 6235f757f3fSDimitry Andric } 6245f757f3fSDimitry Andric 62506c3fb27SDimitry Andric // Equivalent non-predicated constrained ID 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 /// @{ 655349cc55cSDimitry Andric static bool classof(const IntrinsicInst *I) { 656349cc55cSDimitry Andric return VPReductionIntrinsic::isVPReduction(I->getIntrinsicID()); 657349cc55cSDimitry Andric } 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 /// @{ 67081ad6265SDimitry Andric static bool classof(const IntrinsicInst *I) { 67181ad6265SDimitry Andric return VPCastIntrinsic::isVPCast(I->getIntrinsicID()); 67281ad6265SDimitry Andric } 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 /// @{ 68781ad6265SDimitry Andric static bool classof(const IntrinsicInst *I) { 68881ad6265SDimitry Andric return VPCmpIntrinsic::isVPCmp(I->getIntrinsicID()); 68981ad6265SDimitry Andric } 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 /// @{ 7025f757f3fSDimitry Andric static bool classof(const IntrinsicInst *I) { 7035f757f3fSDimitry Andric return VPBinOpIntrinsic::isVPBinOp(I->getIntrinsicID()); 7045f757f3fSDimitry Andric } 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); 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; 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: 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 } 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: 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 } 764fe6060f1SDimitry Andric static bool classof(const Value *V) { 765fe6060f1SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 766fe6060f1SDimitry Andric } 767fe6060f1SDimitry Andric 768fe6060f1SDimitry Andric Value *getLHS() const { return const_cast<Value *>(getArgOperand(0)); } 769fe6060f1SDimitry Andric Value *getRHS() const { return const_cast<Value *>(getArgOperand(1)); } 770fe6060f1SDimitry Andric 771fe6060f1SDimitry Andric /// Returns the comparison predicate underlying the intrinsic. 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. 78804eeddc0SDimitry Andric ICmpInst::Predicate getPredicate() const { 78904eeddc0SDimitry Andric return getPredicate(getIntrinsicID()); 79004eeddc0SDimitry Andric } 79104eeddc0SDimitry Andric 792fe6060f1SDimitry Andric /// Whether the intrinsic is signed or unsigned. 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. 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. 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. 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. 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. 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: 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 } 8530fca6ea1SDimitry Andric static bool classof(const Value *V) { 8540fca6ea1SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 8550fca6ea1SDimitry Andric } 8560fca6ea1SDimitry Andric 8570fca6ea1SDimitry Andric Value *getLHS() const { return const_cast<Value *>(getArgOperand(0)); } 8580fca6ea1SDimitry Andric Value *getRHS() const { return const_cast<Value *>(getArgOperand(1)); } 8590fca6ea1SDimitry Andric 8600fca6ea1SDimitry Andric static bool isSigned(Intrinsic::ID ID) { return ID == Intrinsic::scmp; } 8610fca6ea1SDimitry Andric bool isSigned() const { return isSigned(getIntrinsicID()); } 8620fca6ea1SDimitry Andric 8630fca6ea1SDimitry Andric static CmpInst::Predicate getGTPredicate(Intrinsic::ID ID) { 8640fca6ea1SDimitry Andric return isSigned(ID) ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT; 8650fca6ea1SDimitry Andric } 8660fca6ea1SDimitry Andric CmpInst::Predicate getGTPredicate() const { 8670fca6ea1SDimitry Andric return getGTPredicate(getIntrinsicID()); 8680fca6ea1SDimitry Andric } 8690fca6ea1SDimitry Andric 8700fca6ea1SDimitry Andric static CmpInst::Predicate getLTPredicate(Intrinsic::ID ID) { 8710fca6ea1SDimitry Andric return isSigned(ID) ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT; 8720fca6ea1SDimitry Andric } 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: 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 } 8990b57cec5SDimitry Andric static bool classof(const Value *V) { 9000b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 9010b57cec5SDimitry Andric } 9020b57cec5SDimitry Andric 9030b57cec5SDimitry Andric Value *getLHS() const { return const_cast<Value *>(getArgOperand(0)); } 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: 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 } 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: 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 } 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: 9650b57cec5SDimitry Andric Value *getRawDest() const { 9660b57cec5SDimitry Andric return const_cast<Value *>(getArgOperand(ARG_DEST)); 9670b57cec5SDimitry Andric } 9680b57cec5SDimitry Andric const Use &getRawDestUse() const { return getArgOperandUse(ARG_DEST); } 9690b57cec5SDimitry Andric Use &getRawDestUse() { return getArgOperandUse(ARG_DEST); } 9700b57cec5SDimitry Andric 9710b57cec5SDimitry Andric Value *getLength() const { 9720b57cec5SDimitry Andric return const_cast<Value *>(getArgOperand(ARG_LENGTH)); 9730b57cec5SDimitry Andric } 9740b57cec5SDimitry Andric const Use &getLengthUse() const { return getArgOperandUse(ARG_LENGTH); } 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. 9800b57cec5SDimitry Andric Value *getDest() const { return getRawDest()->stripPointerCasts(); } 9810b57cec5SDimitry Andric 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") 9895ffd83dbSDimitry Andric unsigned getDestAlignment() const { 9905ffd83dbSDimitry Andric if (auto MA = getParamAlign(ARG_DEST)) 9915ffd83dbSDimitry Andric return MA->value(); 9925ffd83dbSDimitry Andric return 0; 9935ffd83dbSDimitry Andric } 994480093f4SDimitry Andric MaybeAlign getDestAlign() const { return getParamAlign(ARG_DEST); } 9950b57cec5SDimitry Andric 9960b57cec5SDimitry Andric /// Set the specified arguments of the instruction. 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 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 } 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 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. 10300b57cec5SDimitry Andric Value *getRawSource() const { 10310b57cec5SDimitry Andric return const_cast<Value *>(BaseCL::getArgOperand(ARG_SOURCE)); 10320b57cec5SDimitry Andric } 10330b57cec5SDimitry Andric const Use &getRawSourceUse() const { 10340b57cec5SDimitry Andric return BaseCL::getArgOperandUse(ARG_SOURCE); 10350b57cec5SDimitry Andric } 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. 10410b57cec5SDimitry Andric Value *getSource() const { return getRawSource()->stripPointerCasts(); } 10420b57cec5SDimitry Andric 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") 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 1056480093f4SDimitry Andric MaybeAlign getSourceAlign() const { 1057480093f4SDimitry Andric return BaseCL::getParamAlign(ARG_SOURCE); 1058480093f4SDimitry Andric } 1059480093f4SDimitry Andric 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 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 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: 10870b57cec5SDimitry Andric Value *getValue() const { 10880b57cec5SDimitry Andric return const_cast<Value *>(BaseCL::getArgOperand(ARG_VALUE)); 10890b57cec5SDimitry Andric } 10905ffd83dbSDimitry Andric const Use &getValueUse() const { return BaseCL::getArgOperandUse(ARG_VALUE); } 10910b57cec5SDimitry Andric Use &getValueUse() { return BaseCL::getArgOperandUse(ARG_VALUE); } 10920b57cec5SDimitry Andric 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: 11070b57cec5SDimitry Andric Value *getRawElementSizeInBytes() const { 11080b57cec5SDimitry Andric return const_cast<Value *>(getArgOperand(ARG_ELEMENTSIZE)); 11090b57cec5SDimitry Andric } 11100b57cec5SDimitry Andric 11110b57cec5SDimitry Andric ConstantInt *getElementSizeInBytesCst() const { 11120b57cec5SDimitry Andric return cast<ConstantInt>(getRawElementSizeInBytes()); 11130b57cec5SDimitry Andric } 11140b57cec5SDimitry Andric 11150b57cec5SDimitry Andric uint32_t getElementSizeInBytes() const { 11160b57cec5SDimitry Andric return getElementSizeInBytesCst()->getZExtValue(); 11170b57cec5SDimitry Andric } 11180b57cec5SDimitry Andric 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 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 } 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: 11440b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) { 11450b57cec5SDimitry Andric return I->getIntrinsicID() == Intrinsic::memset_element_unordered_atomic; 11460b57cec5SDimitry Andric } 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: 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 } 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: 11740b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) { 11750b57cec5SDimitry Andric return I->getIntrinsicID() == Intrinsic::memcpy_element_unordered_atomic; 11760b57cec5SDimitry Andric } 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: 11860b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) { 11870b57cec5SDimitry Andric return I->getIntrinsicID() == Intrinsic::memmove_element_unordered_atomic; 11880b57cec5SDimitry Andric } 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: 12000b57cec5SDimitry Andric ConstantInt *getVolatileCst() const { 12015ffd83dbSDimitry Andric return cast<ConstantInt>(const_cast<Value *>(getArgOperand(ARG_VOLATILE))); 12020b57cec5SDimitry Andric } 12030b57cec5SDimitry Andric 12045ffd83dbSDimitry Andric bool isVolatile() const { return !getVolatileCst()->isZero(); } 12050b57cec5SDimitry Andric 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: 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 } 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: 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 } 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: 124881ad6265SDimitry Andric static bool classof(const IntrinsicInst *I) { 124981ad6265SDimitry Andric return I->getIntrinsicID() == Intrinsic::memset_inline; 12500b57cec5SDimitry Andric } 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: 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 } 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: 12790b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) { 1280fe6060f1SDimitry Andric return I->getIntrinsicID() == Intrinsic::memcpy || 1281fe6060f1SDimitry Andric I->getIntrinsicID() == Intrinsic::memcpy_inline; 12820b57cec5SDimitry Andric } 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: 12920b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) { 12930b57cec5SDimitry Andric return I->getIntrinsicID() == Intrinsic::memmove; 12940b57cec5SDimitry Andric } 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: 13045ffd83dbSDimitry Andric static bool classof(const IntrinsicInst *I) { 13055ffd83dbSDimitry Andric return I->getIntrinsicID() == Intrinsic::memcpy_inline; 13065ffd83dbSDimitry Andric } 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: 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 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 } 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: 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 } 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: 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 } 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: 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 } 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: 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 } 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: 14290b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) { 14300b57cec5SDimitry Andric return I->getIntrinsicID() == Intrinsic::vastart; 14310b57cec5SDimitry Andric } 14320b57cec5SDimitry Andric static bool classof(const Value *V) { 14330b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 14340b57cec5SDimitry Andric } 14350b57cec5SDimitry Andric 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: 14420b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) { 14430b57cec5SDimitry Andric return I->getIntrinsicID() == Intrinsic::vaend; 14440b57cec5SDimitry Andric } 14450b57cec5SDimitry Andric static bool classof(const Value *V) { 14460b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 14470b57cec5SDimitry Andric } 14480b57cec5SDimitry Andric 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: 14550b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) { 14560b57cec5SDimitry Andric return I->getIntrinsicID() == Intrinsic::vacopy; 14570b57cec5SDimitry Andric } 14580b57cec5SDimitry Andric static bool classof(const Value *V) { 14590b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 14600b57cec5SDimitry Andric } 14610b57cec5SDimitry Andric 14620b57cec5SDimitry Andric Value *getDest() const { return const_cast<Value *>(getArgOperand(0)); } 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: 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 } 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: 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. 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. 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: 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: 15251fd87a68SDimitry Andric static bool classof(const IntrinsicInst *I) { 15261fd87a68SDimitry Andric return I->getIntrinsicID() == Intrinsic::instrprof_cover; 15271fd87a68SDimitry Andric } 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: 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 } 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: 15490b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) { 15500b57cec5SDimitry Andric return I->getIntrinsicID() == Intrinsic::instrprof_increment_step; 15510b57cec5SDimitry Andric } 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: 15630fca6ea1SDimitry Andric static bool classof(const IntrinsicInst *I) { 15640fca6ea1SDimitry Andric return I->getIntrinsicID() == Intrinsic::instrprof_callsite; 15650fca6ea1SDimitry Andric } 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: 157506c3fb27SDimitry Andric static bool classof(const IntrinsicInst *I) { 157606c3fb27SDimitry Andric return I->getIntrinsicID() == Intrinsic::instrprof_timestamp; 157706c3fb27SDimitry Andric } 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: 15860b57cec5SDimitry Andric static bool classof(const IntrinsicInst *I) { 15870b57cec5SDimitry Andric return I->getIntrinsicID() == Intrinsic::instrprof_value_profile; 15880b57cec5SDimitry Andric } 15890b57cec5SDimitry Andric static bool classof(const Value *V) { 15900b57cec5SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 15910b57cec5SDimitry Andric } 15920b57cec5SDimitry Andric 15930b57cec5SDimitry Andric Value *getTargetValue() const { 15940b57cec5SDimitry Andric return cast<Value>(const_cast<Value *>(getArgOperand(2))); 15950b57cec5SDimitry Andric } 15960b57cec5SDimitry Andric 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. 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: 16105f757f3fSDimitry Andric static bool classof(const IntrinsicInst *I) { 16110fca6ea1SDimitry Andric return InstrProfInstBase::isMCDCBitmapBase(*I); 16125f757f3fSDimitry Andric } 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. 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. 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: 16335f757f3fSDimitry Andric static bool classof(const IntrinsicInst *I) { 16345f757f3fSDimitry Andric return I->getIntrinsicID() == Intrinsic::instrprof_mcdc_parameters; 16355f757f3fSDimitry Andric } 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: 16445f757f3fSDimitry Andric static bool classof(const IntrinsicInst *I) { 16455f757f3fSDimitry Andric return I->getIntrinsicID() == Intrinsic::instrprof_mcdc_tvbitmap_update; 16465f757f3fSDimitry Andric } 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. 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. 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: 1666e8d8bef9SDimitry Andric static bool classof(const IntrinsicInst *I) { 1667e8d8bef9SDimitry Andric return I->getIntrinsicID() == Intrinsic::pseudoprobe; 1668e8d8bef9SDimitry Andric } 1669e8d8bef9SDimitry Andric 1670e8d8bef9SDimitry Andric static bool classof(const Value *V) { 1671e8d8bef9SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 1672e8d8bef9SDimitry Andric } 1673e8d8bef9SDimitry Andric 1674e8d8bef9SDimitry Andric ConstantInt *getFuncGuid() const { 1675e8d8bef9SDimitry Andric return cast<ConstantInt>(const_cast<Value *>(getArgOperand(0))); 1676e8d8bef9SDimitry Andric } 1677e8d8bef9SDimitry Andric 1678d409305fSDimitry Andric ConstantInt *getIndex() const { 1679d409305fSDimitry Andric return cast<ConstantInt>(const_cast<Value *>(getArgOperand(1))); 1680d409305fSDimitry Andric } 1681d409305fSDimitry Andric 1682e8d8bef9SDimitry Andric ConstantInt *getAttributes() const { 1683e8d8bef9SDimitry Andric return cast<ConstantInt>(const_cast<Value *>(getArgOperand(2))); 1684e8d8bef9SDimitry Andric } 1685e8d8bef9SDimitry Andric 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: 1693e8d8bef9SDimitry Andric static bool classof(const IntrinsicInst *I) { 1694e8d8bef9SDimitry Andric return I->getIntrinsicID() == Intrinsic::experimental_noalias_scope_decl; 1695e8d8bef9SDimitry Andric } 1696e8d8bef9SDimitry Andric 1697e8d8bef9SDimitry Andric static bool classof(const Value *V) { 1698e8d8bef9SDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 1699e8d8bef9SDimitry Andric } 1700e8d8bef9SDimitry Andric 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 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: 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 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. 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: 1741fe6060f1SDimitry Andric static bool classof(const IntrinsicInst *I) { 1742fe6060f1SDimitry Andric return I->getIntrinsicID() == Intrinsic::experimental_gc_relocate; 1743fe6060f1SDimitry Andric } 1744fe6060f1SDimitry Andric 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. 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. 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: 1769fe6060f1SDimitry Andric static bool classof(const IntrinsicInst *I) { 1770fe6060f1SDimitry Andric return I->getIntrinsicID() == Intrinsic::experimental_gc_result; 1771fe6060f1SDimitry Andric } 1772fe6060f1SDimitry Andric 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: 1782fe6060f1SDimitry Andric static bool classof(const IntrinsicInst *I) { 1783fe6060f1SDimitry Andric return I->getIntrinsicID() == Intrinsic::assume; 1784fe6060f1SDimitry Andric } 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. 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: 1805cb14a3feSDimitry Andric static bool classof(const IntrinsicInst *I) { 1806cb14a3feSDimitry Andric return isConvergenceControlIntrinsic(I->getIntrinsicID()); 1807cb14a3feSDimitry Andric } 1808cb14a3feSDimitry Andric 1809cb14a3feSDimitry Andric static bool classof(const Value *V) { 1810cb14a3feSDimitry Andric return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 1811cb14a3feSDimitry Andric } 18120fca6ea1SDimitry Andric 18130fca6ea1SDimitry Andric bool isAnchor() { 18140fca6ea1SDimitry Andric return getIntrinsicID() == Intrinsic::experimental_convergence_anchor; 18150fca6ea1SDimitry Andric } 18160fca6ea1SDimitry Andric bool isEntry() { 18170fca6ea1SDimitry Andric return getIntrinsicID() == Intrinsic::experimental_convergence_entry; 18180fca6ea1SDimitry Andric } 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