diff options
Diffstat (limited to 'include/llvm/IR/IntrinsicInst.h')
-rw-r--r-- | include/llvm/IR/IntrinsicInst.h | 533 |
1 files changed, 289 insertions, 244 deletions
diff --git a/include/llvm/IR/IntrinsicInst.h b/include/llvm/IR/IntrinsicInst.h index f55d17ec72c8a..2ca0a24cbae13 100644 --- a/include/llvm/IR/IntrinsicInst.h +++ b/include/llvm/IR/IntrinsicInst.h @@ -71,11 +71,35 @@ namespace llvm { /// variable's value or its address. Value *getVariableLocation(bool AllowNullOp = true) const; - // Methods for support type inquiry through isa, cast, and dyn_cast: + /// Does this describe the address of a local variable. True for dbg.addr + /// and dbg.declare, but not dbg.value, which describes its value. + bool isAddressOfVariable() const { + return getIntrinsicID() != Intrinsic::dbg_value; + } + + DILocalVariable *getVariable() const { + return cast<DILocalVariable>(getRawVariable()); + } + + DIExpression *getExpression() const { + return cast<DIExpression>(getRawExpression()); + } + + Metadata *getRawVariable() const { + return cast<MetadataAsValue>(getArgOperand(1))->getMetadata(); + } + + Metadata *getRawExpression() const { + return cast<MetadataAsValue>(getArgOperand(2))->getMetadata(); + } + + /// \name Casting methods + /// @{ static bool classof(const IntrinsicInst *I) { switch (I->getIntrinsicID()) { case Intrinsic::dbg_declare: case Intrinsic::dbg_value: + case Intrinsic::dbg_addr: return true; default: return false; } @@ -83,6 +107,7 @@ namespace llvm { static bool classof(const Value *V) { return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); } + /// @} }; /// This represents the llvm.dbg.declare instruction. @@ -90,25 +115,26 @@ namespace llvm { public: Value *getAddress() const { return getVariableLocation(); } - DILocalVariable *getVariable() const { - return cast<DILocalVariable>(getRawVariable()); - } - - DIExpression *getExpression() const { - return cast<DIExpression>(getRawExpression()); + /// \name Casting methods + /// @{ + static bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::dbg_declare; } - - Metadata *getRawVariable() const { - return cast<MetadataAsValue>(getArgOperand(1))->getMetadata(); + static bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); } + /// @} + }; - Metadata *getRawExpression() const { - return cast<MetadataAsValue>(getArgOperand(2))->getMetadata(); - } + /// This represents the llvm.dbg.addr instruction. + class DbgAddrIntrinsic : public DbgInfoIntrinsic { + public: + Value *getAddress() const { return getVariableLocation(); } - // Methods for support type inquiry through isa, cast, and dyn_cast: + /// \name Casting methods + /// @{ static bool classof(const IntrinsicInst *I) { - return I->getIntrinsicID() == Intrinsic::dbg_declare; + return I->getIntrinsicID() == Intrinsic::dbg_addr; } static bool classof(const Value *V) { return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); @@ -122,34 +148,15 @@ namespace llvm { return getVariableLocation(/* AllowNullOp = */ false); } - uint64_t getOffset() const { - return cast<ConstantInt>( - const_cast<Value*>(getArgOperand(1)))->getZExtValue(); - } - - DILocalVariable *getVariable() const { - return cast<DILocalVariable>(getRawVariable()); - } - - DIExpression *getExpression() const { - return cast<DIExpression>(getRawExpression()); - } - - Metadata *getRawVariable() const { - return cast<MetadataAsValue>(getArgOperand(2))->getMetadata(); - } - - Metadata *getRawExpression() const { - return cast<MetadataAsValue>(getArgOperand(3))->getMetadata(); - } - - // Methods for support type inquiry through isa, cast, and dyn_cast: + /// \name Casting methods + /// @{ static bool classof(const IntrinsicInst *I) { return I->getIntrinsicID() == Intrinsic::dbg_value; } static bool classof(const Value *V) { return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); } + /// @} }; /// This is the common base class for constrained floating point intrinsics. @@ -172,6 +179,7 @@ namespace llvm { }; bool isUnaryOp() const; + bool isTernaryOp() const; RoundingMode getRoundingMode() const; ExceptionBehavior getExceptionBehavior() const; @@ -183,6 +191,7 @@ namespace llvm { case Intrinsic::experimental_constrained_fmul: case Intrinsic::experimental_constrained_fdiv: case Intrinsic::experimental_constrained_frem: + case Intrinsic::experimental_constrained_fma: case Intrinsic::experimental_constrained_sqrt: case Intrinsic::experimental_constrained_pow: case Intrinsic::experimental_constrained_powi: @@ -204,12 +213,13 @@ namespace llvm { } }; - /// This class represents atomic memcpy intrinsic - /// TODO: Integrate this class into MemIntrinsic hierarchy; for now this is - /// C&P of all methods from that hierarchy - class ElementUnorderedAtomicMemCpyInst : public IntrinsicInst { + /// Common base class for all memory intrinsics. Simply provides + /// common methods. + /// Written as CRTP to avoid a common base class amongst the + /// three atomicity hierarchies. + template <typename Derived> class MemIntrinsicBase : public IntrinsicInst { private: - enum { ARG_DEST = 0, ARG_SOURCE = 1, ARG_LENGTH = 2, ARG_ELEMENTSIZE = 3 }; + enum { ARG_DEST = 0, ARG_LENGTH = 2 }; public: Value *getRawDest() const { @@ -218,51 +228,21 @@ namespace llvm { const Use &getRawDestUse() const { return getArgOperandUse(ARG_DEST); } Use &getRawDestUse() { return getArgOperandUse(ARG_DEST); } - /// Return the arguments to the instruction. - Value *getRawSource() const { - return const_cast<Value *>(getArgOperand(ARG_SOURCE)); - } - const Use &getRawSourceUse() const { return getArgOperandUse(ARG_SOURCE); } - Use &getRawSourceUse() { return getArgOperandUse(ARG_SOURCE); } - Value *getLength() const { return const_cast<Value *>(getArgOperand(ARG_LENGTH)); } const Use &getLengthUse() const { return getArgOperandUse(ARG_LENGTH); } Use &getLengthUse() { return getArgOperandUse(ARG_LENGTH); } - bool isVolatile() const { return false; } - - Value *getRawElementSizeInBytes() const { - return const_cast<Value *>(getArgOperand(ARG_ELEMENTSIZE)); - } - - ConstantInt *getElementSizeInBytesCst() const { - return cast<ConstantInt>(getRawElementSizeInBytes()); - } - - uint32_t getElementSizeInBytes() const { - return getElementSizeInBytesCst()->getZExtValue(); - } - /// This is just like getRawDest, but it strips off any cast - /// instructions that feed it, giving the original input. The returned - /// value is guaranteed to be a pointer. + /// instructions (including addrspacecast) that feed it, giving the + /// original input. The returned value is guaranteed to be a pointer. Value *getDest() const { return getRawDest()->stripPointerCasts(); } - /// This is just like getRawSource, but it strips off any cast - /// instructions that feed it, giving the original input. The returned - /// value is guaranteed to be a pointer. - Value *getSource() const { return getRawSource()->stripPointerCasts(); } - unsigned getDestAddressSpace() const { return cast<PointerType>(getRawDest()->getType())->getAddressSpace(); } - unsigned getSourceAddressSpace() const { - return cast<PointerType>(getRawSource()->getType())->getAddressSpace(); - } - /// Set the specified arguments of the instruction. void setDest(Value *Ptr) { assert(getRawDest()->getType() == Ptr->getType() && @@ -270,58 +250,20 @@ namespace llvm { setArgOperand(ARG_DEST, Ptr); } - void setSource(Value *Ptr) { - assert(getRawSource()->getType() == Ptr->getType() && - "setSource called with pointer of wrong type!"); - setArgOperand(ARG_SOURCE, Ptr); - } - void setLength(Value *L) { assert(getLength()->getType() == L->getType() && "setLength called with value of wrong type!"); setArgOperand(ARG_LENGTH, L); } - - void setElementSizeInBytes(Constant *V) { - assert(V->getType() == Type::getInt8Ty(getContext()) && - "setElementSizeInBytes called with value of wrong type!"); - setArgOperand(ARG_ELEMENTSIZE, V); - } - - static bool classof(const IntrinsicInst *I) { - return I->getIntrinsicID() == Intrinsic::memcpy_element_unordered_atomic; - } - static bool classof(const Value *V) { - return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); - } }; - class ElementUnorderedAtomicMemMoveInst : public IntrinsicInst { + // The common base class for the atomic memset/memmove/memcpy intrinsics + // i.e. llvm.element.unordered.atomic.memset/memcpy/memmove + class AtomicMemIntrinsic : public MemIntrinsicBase<AtomicMemIntrinsic> { private: - enum { ARG_DEST = 0, ARG_SOURCE = 1, ARG_LENGTH = 2, ARG_ELEMENTSIZE = 3 }; + enum { ARG_ELEMENTSIZE = 3 }; public: - Value *getRawDest() const { - return const_cast<Value *>(getArgOperand(ARG_DEST)); - } - const Use &getRawDestUse() const { return getArgOperandUse(ARG_DEST); } - Use &getRawDestUse() { return getArgOperandUse(ARG_DEST); } - - /// Return the arguments to the instruction. - Value *getRawSource() const { - return const_cast<Value *>(getArgOperand(ARG_SOURCE)); - } - const Use &getRawSourceUse() const { return getArgOperandUse(ARG_SOURCE); } - Use &getRawSourceUse() { return getArgOperandUse(ARG_SOURCE); } - - Value *getLength() const { - return const_cast<Value *>(getArgOperand(ARG_LENGTH)); - } - const Use &getLengthUse() const { return getArgOperandUse(ARG_LENGTH); } - Use &getLengthUse() { return getArgOperandUse(ARG_LENGTH); } - - bool isVolatile() const { return false; } - Value *getRawElementSizeInBytes() const { return const_cast<Value *>(getArgOperand(ARG_ELEMENTSIZE)); } @@ -334,150 +276,129 @@ namespace llvm { return getElementSizeInBytesCst()->getZExtValue(); } - /// This is just like getRawDest, but it strips off any cast - /// instructions that feed it, giving the original input. The returned - /// value is guaranteed to be a pointer. - Value *getDest() const { return getRawDest()->stripPointerCasts(); } - - /// This is just like getRawSource, but it strips off any cast - /// instructions that feed it, giving the original input. The returned - /// value is guaranteed to be a pointer. - Value *getSource() const { return getRawSource()->stripPointerCasts(); } - - unsigned getDestAddressSpace() const { - return cast<PointerType>(getRawDest()->getType())->getAddressSpace(); - } - - unsigned getSourceAddressSpace() const { - return cast<PointerType>(getRawSource()->getType())->getAddressSpace(); - } - - /// Set the specified arguments of the instruction. - void setDest(Value *Ptr) { - assert(getRawDest()->getType() == Ptr->getType() && - "setDest called with pointer of wrong type!"); - setArgOperand(ARG_DEST, Ptr); - } - - void setSource(Value *Ptr) { - assert(getRawSource()->getType() == Ptr->getType() && - "setSource called with pointer of wrong type!"); - setArgOperand(ARG_SOURCE, Ptr); - } - - void setLength(Value *L) { - assert(getLength()->getType() == L->getType() && - "setLength called with value of wrong type!"); - setArgOperand(ARG_LENGTH, L); - } - void setElementSizeInBytes(Constant *V) { assert(V->getType() == Type::getInt8Ty(getContext()) && "setElementSizeInBytes called with value of wrong type!"); setArgOperand(ARG_ELEMENTSIZE, V); } - static inline bool classof(const IntrinsicInst *I) { - return I->getIntrinsicID() == Intrinsic::memmove_element_unordered_atomic; + static bool classof(const IntrinsicInst *I) { + switch (I->getIntrinsicID()) { + case Intrinsic::memcpy_element_unordered_atomic: + case Intrinsic::memmove_element_unordered_atomic: + case Intrinsic::memset_element_unordered_atomic: + return true; + default: + return false; + } } - static inline bool classof(const Value *V) { + static bool classof(const Value *V) { return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); } }; /// This class represents atomic memset intrinsic - /// TODO: Integrate this class into MemIntrinsic hierarchy; for now this is - /// C&P of all methods from that hierarchy - class ElementUnorderedAtomicMemSetInst : public IntrinsicInst { + // i.e. llvm.element.unordered.atomic.memset + class AtomicMemSetInst : public AtomicMemIntrinsic { private: - enum { ARG_DEST = 0, ARG_VALUE = 1, ARG_LENGTH = 2, ARG_ELEMENTSIZE = 3 }; + enum { ARG_VALUE = 1 }; public: - Value *getRawDest() const { - return const_cast<Value *>(getArgOperand(ARG_DEST)); + Value *getValue() const { + return const_cast<Value *>(getArgOperand(ARG_VALUE)); } - const Use &getRawDestUse() const { return getArgOperandUse(ARG_DEST); } - Use &getRawDestUse() { return getArgOperandUse(ARG_DEST); } - - Value *getValue() const { return const_cast<Value*>(getArgOperand(ARG_VALUE)); } const Use &getValueUse() const { return getArgOperandUse(ARG_VALUE); } Use &getValueUse() { return getArgOperandUse(ARG_VALUE); } - Value *getLength() const { - return const_cast<Value *>(getArgOperand(ARG_LENGTH)); + void setValue(Value *Val) { + assert(getValue()->getType() == Val->getType() && + "setValue called with value of wrong type!"); + setArgOperand(ARG_VALUE, Val); } - const Use &getLengthUse() const { return getArgOperandUse(ARG_LENGTH); } - Use &getLengthUse() { return getArgOperandUse(ARG_LENGTH); } - - bool isVolatile() const { return false; } - Value *getRawElementSizeInBytes() const { - return const_cast<Value *>(getArgOperand(ARG_ELEMENTSIZE)); + static bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::memset_element_unordered_atomic; } - - ConstantInt *getElementSizeInBytesCst() const { - return cast<ConstantInt>(getRawElementSizeInBytes()); + static bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); } + }; - uint32_t getElementSizeInBytes() const { - return getElementSizeInBytesCst()->getZExtValue(); + // This class wraps the atomic memcpy/memmove intrinsics + // i.e. llvm.element.unordered.atomic.memcpy/memmove + class AtomicMemTransferInst : public AtomicMemIntrinsic { + private: + enum { ARG_SOURCE = 1 }; + + public: + /// Return the arguments to the instruction. + Value *getRawSource() const { + return const_cast<Value *>(getArgOperand(ARG_SOURCE)); } + const Use &getRawSourceUse() const { return getArgOperandUse(ARG_SOURCE); } + Use &getRawSourceUse() { return getArgOperandUse(ARG_SOURCE); } - /// This is just like getRawDest, but it strips off any cast + /// This is just like getRawSource, but it strips off any cast /// instructions that feed it, giving the original input. The returned /// value is guaranteed to be a pointer. - Value *getDest() const { return getRawDest()->stripPointerCasts(); } + Value *getSource() const { return getRawSource()->stripPointerCasts(); } - unsigned getDestAddressSpace() const { - return cast<PointerType>(getRawDest()->getType())->getAddressSpace(); + unsigned getSourceAddressSpace() const { + return cast<PointerType>(getRawSource()->getType())->getAddressSpace(); } - /// Set the specified arguments of the instruction. - void setDest(Value *Ptr) { - assert(getRawDest()->getType() == Ptr->getType() && - "setDest called with pointer of wrong type!"); - setArgOperand(ARG_DEST, Ptr); + void setSource(Value *Ptr) { + assert(getRawSource()->getType() == Ptr->getType() && + "setSource called with pointer of wrong type!"); + setArgOperand(ARG_SOURCE, Ptr); } - void setValue(Value *Val) { - assert(getValue()->getType() == Val->getType() && - "setValue called with value of wrong type!"); - setArgOperand(ARG_VALUE, Val); + static bool classof(const IntrinsicInst *I) { + switch (I->getIntrinsicID()) { + case Intrinsic::memcpy_element_unordered_atomic: + case Intrinsic::memmove_element_unordered_atomic: + return true; + default: + return false; + } } - - void setLength(Value *L) { - assert(getLength()->getType() == L->getType() && - "setLength called with value of wrong type!"); - setArgOperand(ARG_LENGTH, L); + static bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); } + }; - void setElementSizeInBytes(Constant *V) { - assert(V->getType() == Type::getInt8Ty(getContext()) && - "setElementSizeInBytes called with value of wrong type!"); - setArgOperand(ARG_ELEMENTSIZE, V); + /// This class represents the atomic memcpy intrinsic + /// i.e. llvm.element.unordered.atomic.memcpy + class AtomicMemCpyInst : public AtomicMemTransferInst { + public: + static bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::memcpy_element_unordered_atomic; + } + static bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); } + }; - static inline bool classof(const IntrinsicInst *I) { - return I->getIntrinsicID() == Intrinsic::memset_element_unordered_atomic; + /// This class represents the atomic memmove intrinsic + /// i.e. llvm.element.unordered.atomic.memmove + class AtomicMemMoveInst : public AtomicMemTransferInst { + public: + static bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::memmove_element_unordered_atomic; } - static inline bool classof(const Value *V) { + static bool classof(const Value *V) { return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); } }; /// This is the common base class for memset/memcpy/memmove. - class MemIntrinsic : public IntrinsicInst { - public: - Value *getRawDest() const { return const_cast<Value*>(getArgOperand(0)); } - const Use &getRawDestUse() const { return getArgOperandUse(0); } - Use &getRawDestUse() { return getArgOperandUse(0); } - - Value *getLength() const { return const_cast<Value*>(getArgOperand(2)); } - const Use &getLengthUse() const { return getArgOperandUse(2); } - Use &getLengthUse() { return getArgOperandUse(2); } + class MemIntrinsic : public MemIntrinsicBase<MemIntrinsic> { + private: + enum { ARG_ALIGN = 3, ARG_VOLATILE = 4 }; + public: ConstantInt *getAlignmentCst() const { - return cast<ConstantInt>(const_cast<Value*>(getArgOperand(3))); + return cast<ConstantInt>(const_cast<Value *>(getArgOperand(ARG_ALIGN))); } unsigned getAlignment() const { @@ -485,45 +406,20 @@ namespace llvm { } ConstantInt *getVolatileCst() const { - return cast<ConstantInt>(const_cast<Value*>(getArgOperand(4))); + return cast<ConstantInt>( + const_cast<Value *>(getArgOperand(ARG_VOLATILE))); } bool isVolatile() const { return !getVolatileCst()->isZero(); } - unsigned getDestAddressSpace() const { - return cast<PointerType>(getRawDest()->getType())->getAddressSpace(); - } - - /// This is just like getRawDest, but it strips off any cast - /// instructions that feed it, giving the original input. The returned - /// value is guaranteed to be a pointer. - Value *getDest() const { return getRawDest()->stripPointerCasts(); } - - /// Set the specified arguments of the instruction. - void setDest(Value *Ptr) { - assert(getRawDest()->getType() == Ptr->getType() && - "setDest called with pointer of wrong type!"); - setArgOperand(0, Ptr); - } - - void setLength(Value *L) { - assert(getLength()->getType() == L->getType() && - "setLength called with value of wrong type!"); - setArgOperand(2, L); - } - - void setAlignment(Constant* A) { - setArgOperand(3, A); - } + void setAlignment(Constant *A) { setArgOperand(ARG_ALIGN, A); } - void setVolatile(Constant* V) { - setArgOperand(4, V); - } + void setVolatile(Constant *V) { setArgOperand(ARG_VOLATILE, V); } Type *getAlignmentType() const { - return getArgOperand(3)->getType(); + return getArgOperand(ARG_ALIGN)->getType(); } // Methods for support type inquiry through isa, cast, and dyn_cast: @@ -621,6 +517,155 @@ namespace llvm { } }; + // The common base class for any memset/memmove/memcpy intrinsics; + // whether they be atomic or non-atomic. + // i.e. llvm.element.unordered.atomic.memset/memcpy/memmove + // and llvm.memset/memcpy/memmove + class AnyMemIntrinsic : public MemIntrinsicBase<AnyMemIntrinsic> { + public: + bool isVolatile() const { + // Only the non-atomic intrinsics can be volatile + if (auto *MI = dyn_cast<MemIntrinsic>(this)) + return MI->isVolatile(); + return false; + } + + static bool classof(const IntrinsicInst *I) { + switch (I->getIntrinsicID()) { + case Intrinsic::memcpy: + case Intrinsic::memmove: + case Intrinsic::memset: + case Intrinsic::memcpy_element_unordered_atomic: + case Intrinsic::memmove_element_unordered_atomic: + case Intrinsic::memset_element_unordered_atomic: + return true; + default: + return false; + } + } + static bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + }; + + /// This class represents any memset intrinsic + // i.e. llvm.element.unordered.atomic.memset + // and llvm.memset + class AnyMemSetInst : public AnyMemIntrinsic { + private: + enum { ARG_VALUE = 1 }; + + public: + Value *getValue() const { + return const_cast<Value *>(getArgOperand(ARG_VALUE)); + } + const Use &getValueUse() const { return getArgOperandUse(ARG_VALUE); } + Use &getValueUse() { return getArgOperandUse(ARG_VALUE); } + + void setValue(Value *Val) { + assert(getValue()->getType() == Val->getType() && + "setValue called with value of wrong type!"); + setArgOperand(ARG_VALUE, Val); + } + + static bool classof(const IntrinsicInst *I) { + switch (I->getIntrinsicID()) { + case Intrinsic::memset: + case Intrinsic::memset_element_unordered_atomic: + return true; + default: + return false; + } + } + static bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + }; + + // This class wraps any memcpy/memmove intrinsics + // i.e. llvm.element.unordered.atomic.memcpy/memmove + // and llvm.memcpy/memmove + class AnyMemTransferInst : public AnyMemIntrinsic { + private: + enum { ARG_SOURCE = 1 }; + + public: + /// Return the arguments to the instruction. + Value *getRawSource() const { + return const_cast<Value *>(getArgOperand(ARG_SOURCE)); + } + const Use &getRawSourceUse() const { return getArgOperandUse(ARG_SOURCE); } + Use &getRawSourceUse() { return getArgOperandUse(ARG_SOURCE); } + + /// This is just like getRawSource, but it strips off any cast + /// instructions that feed it, giving the original input. The returned + /// value is guaranteed to be a pointer. + Value *getSource() const { return getRawSource()->stripPointerCasts(); } + + unsigned getSourceAddressSpace() const { + return cast<PointerType>(getRawSource()->getType())->getAddressSpace(); + } + + void setSource(Value *Ptr) { + assert(getRawSource()->getType() == Ptr->getType() && + "setSource called with pointer of wrong type!"); + setArgOperand(ARG_SOURCE, Ptr); + } + + static bool classof(const IntrinsicInst *I) { + switch (I->getIntrinsicID()) { + case Intrinsic::memcpy: + case Intrinsic::memmove: + case Intrinsic::memcpy_element_unordered_atomic: + case Intrinsic::memmove_element_unordered_atomic: + return true; + default: + return false; + } + } + static bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + }; + + /// This class represents any memcpy intrinsic + /// i.e. llvm.element.unordered.atomic.memcpy + /// and llvm.memcpy + class AnyMemCpyInst : public AnyMemTransferInst { + public: + static bool classof(const IntrinsicInst *I) { + switch (I->getIntrinsicID()) { + case Intrinsic::memcpy: + case Intrinsic::memcpy_element_unordered_atomic: + return true; + default: + return false; + } + } + static bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + }; + + /// This class represents any memmove intrinsic + /// i.e. llvm.element.unordered.atomic.memmove + /// and llvm.memmove + class AnyMemMoveInst : public AnyMemTransferInst { + public: + static bool classof(const IntrinsicInst *I) { + switch (I->getIntrinsicID()) { + case Intrinsic::memmove: + case Intrinsic::memmove_element_unordered_atomic: + return true; + default: + return false; + } + } + static bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + }; + /// This represents the llvm.va_start intrinsic. class VAStartInst : public IntrinsicInst { public: |