diff options
Diffstat (limited to 'include/llvm/IR')
44 files changed, 25859 insertions, 0 deletions
diff --git a/include/llvm/IR/Argument.h b/include/llvm/IR/Argument.h new file mode 100644 index 0000000..ef4e4fc --- /dev/null +++ b/include/llvm/IR/Argument.h @@ -0,0 +1,96 @@ +//===-- llvm/Argument.h - Definition of the Argument class ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the Argument class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_ARGUMENT_H +#define LLVM_IR_ARGUMENT_H + +#include "llvm/ADT/Twine.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/IR/Attributes.h" +#include "llvm/IR/Value.h" + +namespace llvm { + +template<typename ValueSubClass, typename ItemParentClass> + class SymbolTableListTraits; + +/// \brief LLVM Argument representation +/// +/// This class represents an incoming formal argument to a Function. A formal +/// argument, since it is ``formal'', does not contain an actual value but +/// instead represents the type, argument number, and attributes of an argument +/// for a specific function. When used in the body of said function, the +/// argument of course represents the value of the actual argument that the +/// function was called with. +class Argument : public Value, public ilist_node<Argument> { + virtual void anchor(); + Function *Parent; + + friend class SymbolTableListTraits<Argument, Function>; + void setParent(Function *parent); + +public: + /// \brief Constructor. + /// + /// If \p F is specified, the argument is inserted at the end of the argument + /// list for \p F. + explicit Argument(Type *Ty, const Twine &Name = "", Function *F = 0); + + inline const Function *getParent() const { return Parent; } + inline Function *getParent() { return Parent; } + + /// \brief Return the index of this formal argument in its containing + /// function. + /// + /// For example in "void foo(int a, float b)" a is 0 and b is 1. + unsigned getArgNo() const; + + /// \brief Return true if this argument has the byval attribute on it in its + /// containing function. + bool hasByValAttr() const; + + /// \brief If this is a byval argument, return its alignment. + unsigned getParamAlignment() const; + + /// \brief Return true if this argument has the nest attribute on it in its + /// containing function. + bool hasNestAttr() const; + + /// \brief Return true if this argument has the noalias attribute on it in its + /// containing function. + bool hasNoAliasAttr() const; + + /// \brief Return true if this argument has the nocapture attribute on it in + /// its containing function. + bool hasNoCaptureAttr() const; + + /// \brief Return true if this argument has the sret attribute on it in its + /// containing function. + bool hasStructRetAttr() const; + + /// \brief Add a Attribute to an argument. + void addAttr(AttributeSet AS); + + /// \brief Remove a Attribute from an argument. + void removeAttr(AttributeSet AS); + + /// \brief Method for support type inquiry through isa, cast, and + /// dyn_cast. + static inline bool classof(const Value *V) { + return V->getValueID() == ArgumentVal; + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h new file mode 100644 index 0000000..074b387 --- /dev/null +++ b/include/llvm/IR/Attributes.h @@ -0,0 +1,499 @@ +//===-- llvm/Attributes.h - Container for Attributes ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This file contains the simple types necessary to represent the +/// attributes associated with functions and their calls. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_ATTRIBUTES_H +#define LLVM_IR_ATTRIBUTES_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/PointerLikeTypeTraits.h" +#include <bitset> +#include <cassert> +#include <map> +#include <string> + +namespace llvm { + +class AttrBuilder; +class AttributeImpl; +class AttributeSetImpl; +class AttributeSetNode; +class Constant; +template<typename T> struct DenseMapInfo; +class LLVMContext; +class Type; + +//===----------------------------------------------------------------------===// +/// \class +/// \brief Functions, function parameters, and return types can have attributes +/// to indicate how they should be treated by optimizations and code +/// generation. This class represents one of those attributes. It's light-weight +/// and should be passed around by-value. +class Attribute { +public: + /// This enumeration lists the attributes that can be associated with + /// parameters, function results, or the function itself. + /// + /// Note: The `uwtable' attribute is about the ABI or the user mandating an + /// entry in the unwind table. The `nounwind' attribute is about an exception + /// passing by the function. + /// + /// In a theoretical system that uses tables for profiling and SjLj for + /// exceptions, they would be fully independent. In a normal system that uses + /// tables for both, the semantics are: + /// + /// nil = Needs an entry because an exception might pass by. + /// nounwind = No need for an entry + /// uwtable = Needs an entry because the ABI says so and because + /// an exception might pass by. + /// uwtable + nounwind = Needs an entry because the ABI says so. + + enum AttrKind { + // IR-Level Attributes + None, ///< No attributes have been set + Alignment, ///< Alignment of parameter (5 bits) + ///< stored as log2 of alignment with +1 bias + ///< 0 means unaligned (different from align(1)) + AlwaysInline, ///< inline=always + ByVal, ///< Pass structure by value + InlineHint, ///< Source said inlining was desirable + InReg, ///< Force argument to be passed in register + MinSize, ///< Function must be optimized for size first + Naked, ///< Naked function + Nest, ///< Nested function static chain + NoAlias, ///< Considered to not alias after call + NoBuiltin, ///< Callee isn't recognized as a builtin + NoCapture, ///< Function creates no aliases of pointer + NoDuplicate, ///< Call cannot be duplicated + NoImplicitFloat, ///< Disable implicit floating point insts + NoInline, ///< inline=never + NonLazyBind, ///< Function is called early and/or + ///< often, so lazy binding isn't worthwhile + NoRedZone, ///< Disable redzone + NoReturn, ///< Mark the function as not returning + NoUnwind, ///< Function doesn't unwind stack + OptimizeForSize, ///< opt_size + ReadNone, ///< Function does not access memory + ReadOnly, ///< Function only reads from memory + ReturnsTwice, ///< Function can return twice + SExt, ///< Sign extended before/after call + StackAlignment, ///< Alignment of stack for function (3 bits) + ///< stored as log2 of alignment with +1 bias 0 + ///< means unaligned (different from + ///< alignstack=(1)) + StackProtect, ///< Stack protection. + StackProtectReq, ///< Stack protection required. + StackProtectStrong, ///< Strong Stack protection. + StructRet, ///< Hidden pointer to structure to return + SanitizeAddress, ///< AddressSanitizer is on. + SanitizeThread, ///< ThreadSanitizer is on. + SanitizeMemory, ///< MemorySanitizer is on. + UWTable, ///< Function must be in a unwind table + ZExt, ///< Zero extended before/after call + + EndAttrKinds ///< Sentinal value useful for loops + }; +private: + AttributeImpl *pImpl; + Attribute(AttributeImpl *A) : pImpl(A) {} +public: + Attribute() : pImpl(0) {} + + //===--------------------------------------------------------------------===// + // Attribute Construction + //===--------------------------------------------------------------------===// + + /// \brief Return a uniquified Attribute object. + static Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val = 0); + static Attribute get(LLVMContext &Context, StringRef Kind, + StringRef Val = StringRef()); + + /// \brief Return a uniquified Attribute object that has the specific + /// alignment set. + static Attribute getWithAlignment(LLVMContext &Context, uint64_t Align); + static Attribute getWithStackAlignment(LLVMContext &Context, uint64_t Align); + + //===--------------------------------------------------------------------===// + // Attribute Accessors + //===--------------------------------------------------------------------===// + + /// \brief Return true if the attribute is an Attribute::AttrKind type. + bool isEnumAttribute() const; + + /// \brief Return true if the attribute is an alignment attribute. + bool isAlignAttribute() const; + + /// \brief Return true if the attribute is a string (target-dependent) + /// attribute. + bool isStringAttribute() const; + + /// \brief Return true if the attribute is present. + bool hasAttribute(AttrKind Val) const; + + /// \brief Return true if the target-dependent attribute is present. + bool hasAttribute(StringRef Val) const; + + /// \brief Return the attribute's kind as an enum (Attribute::AttrKind). This + /// requires the attribute to be an enum or alignment attribute. + Attribute::AttrKind getKindAsEnum() const; + + /// \brief Return the attribute's value as an integer. This requires that the + /// attribute be an alignment attribute. + uint64_t getValueAsInt() const; + + /// \brief Return the attribute's kind as a string. This requires the + /// attribute to be a string attribute. + StringRef getKindAsString() const; + + /// \brief Return the attribute's value as a string. This requires the + /// attribute to be a string attribute. + StringRef getValueAsString() const; + + /// \brief Returns the alignment field of an attribute as a byte alignment + /// value. + unsigned getAlignment() const; + + /// \brief Returns the stack alignment field of an attribute as a byte + /// alignment value. + unsigned getStackAlignment() const; + + /// \brief The Attribute is converted to a string of equivalent mnemonic. This + /// is, presumably, for writing out the mnemonics for the assembly writer. + std::string getAsString(bool InAttrGrp = false) const; + + /// \brief Equality and non-equality operators. + bool operator==(Attribute A) const { return pImpl == A.pImpl; } + bool operator!=(Attribute A) const { return pImpl != A.pImpl; } + + /// \brief Less-than operator. Useful for sorting the attributes list. + bool operator<(Attribute A) const; + + void Profile(FoldingSetNodeID &ID) const { + ID.AddPointer(pImpl); + } +}; + +//===----------------------------------------------------------------------===// +/// \class +/// \brief This class holds the attributes for a function, its return value, and +/// its parameters. You access the attributes for each of them via an index into +/// the AttributeSet object. The function attributes are at index +/// `AttributeSet::FunctionIndex', the return value is at index +/// `AttributeSet::ReturnIndex', and the attributes for the parameters start at +/// index `1'. +class AttributeSet { +public: + enum AttrIndex { + ReturnIndex = 0U, + FunctionIndex = ~0U + }; +private: + friend class AttrBuilder; + friend class AttributeSetImpl; + template <typename Ty> friend struct DenseMapInfo; + + /// \brief The attributes that we are managing. This can be null to represent + /// the empty attributes list. + AttributeSetImpl *pImpl; + + /// \brief The attributes for the specified index are returned. + AttributeSetNode *getAttributes(unsigned Idx) const; + + /// \brief Create an AttributeSet with the specified parameters in it. + static AttributeSet get(LLVMContext &C, + ArrayRef<std::pair<unsigned, Attribute> > Attrs); + static AttributeSet get(LLVMContext &C, + ArrayRef<std::pair<unsigned, + AttributeSetNode*> > Attrs); + + static AttributeSet getImpl(LLVMContext &C, + ArrayRef<std::pair<unsigned, + AttributeSetNode*> > Attrs); + + + explicit AttributeSet(AttributeSetImpl *LI) : pImpl(LI) {} +public: + AttributeSet() : pImpl(0) {} + + //===--------------------------------------------------------------------===// + // AttributeSet Construction and Mutation + //===--------------------------------------------------------------------===// + + /// \brief Return an AttributeSet with the specified parameters in it. + static AttributeSet get(LLVMContext &C, ArrayRef<AttributeSet> Attrs); + static AttributeSet get(LLVMContext &C, unsigned Idx, + ArrayRef<Attribute::AttrKind> Kind); + static AttributeSet get(LLVMContext &C, unsigned Idx, AttrBuilder &B); + + /// \brief Add an attribute to the attribute set at the given index. Since + /// attribute sets are immutable, this returns a new set. + AttributeSet addAttribute(LLVMContext &C, unsigned Idx, + Attribute::AttrKind Attr) const; + + /// \brief Add an attribute to the attribute set at the given index. Since + /// attribute sets are immutable, this returns a new set. + AttributeSet addAttribute(LLVMContext &C, unsigned Idx, + StringRef Kind) const; + + /// \brief Add attributes to the attribute set at the given index. Since + /// attribute sets are immutable, this returns a new set. + AttributeSet addAttributes(LLVMContext &C, unsigned Idx, + AttributeSet Attrs) const; + + /// \brief Remove the specified attribute at the specified index from this + /// attribute list. Since attribute lists are immutable, this returns the new + /// list. + AttributeSet removeAttribute(LLVMContext &C, unsigned Idx, + Attribute::AttrKind Attr) const; + + /// \brief Remove the specified attributes at the specified index from this + /// attribute list. Since attribute lists are immutable, this returns the new + /// list. + AttributeSet removeAttributes(LLVMContext &C, unsigned Idx, + AttributeSet Attrs) const; + + //===--------------------------------------------------------------------===// + // AttributeSet Accessors + //===--------------------------------------------------------------------===// + + /// \brief Retrieve the LLVM context. + LLVMContext &getContext() const; + + /// \brief The attributes for the specified index are returned. + AttributeSet getParamAttributes(unsigned Idx) const; + + /// \brief The attributes for the ret value are returned. + AttributeSet getRetAttributes() const; + + /// \brief The function attributes are returned. + AttributeSet getFnAttributes() const; + + /// \brief Return true if the attribute exists at the given index. + bool hasAttribute(unsigned Index, Attribute::AttrKind Kind) const; + + /// \brief Return true if the attribute exists at the given index. + bool hasAttribute(unsigned Index, StringRef Kind) const; + + /// \brief Return true if attribute exists at the given index. + bool hasAttributes(unsigned Index) const; + + /// \brief Return true if the specified attribute is set for at least one + /// parameter or for the return value. + bool hasAttrSomewhere(Attribute::AttrKind Attr) const; + + /// \brief Return the attribute object that exists at the given index. + Attribute getAttribute(unsigned Index, Attribute::AttrKind Kind) const; + + /// \brief Return the attribute object that exists at the given index. + Attribute getAttribute(unsigned Index, StringRef Kind) const; + + /// \brief Return the alignment for the specified function parameter. + unsigned getParamAlignment(unsigned Idx) const; + + /// \brief Get the stack alignment. + unsigned getStackAlignment(unsigned Index) const; + + /// \brief Return the attributes at the index as a string. + std::string getAsString(unsigned Index, bool InAttrGrp = false) const; + + typedef ArrayRef<Attribute>::iterator iterator; + + iterator begin(unsigned Idx) const; + iterator end(unsigned Idx) const; + + /// operator==/!= - Provide equality predicates. + bool operator==(const AttributeSet &RHS) const { + return pImpl == RHS.pImpl; + } + bool operator!=(const AttributeSet &RHS) const { + return pImpl != RHS.pImpl; + } + + //===--------------------------------------------------------------------===// + // AttributeSet Introspection + //===--------------------------------------------------------------------===// + + // FIXME: Remove this. + uint64_t Raw(unsigned Index) const; + + /// \brief Return a raw pointer that uniquely identifies this attribute list. + void *getRawPointer() const { + return pImpl; + } + + /// \brief Return true if there are no attributes. + bool isEmpty() const { + return getNumSlots() == 0; + } + + /// \brief Return the number of slots used in this attribute list. This is + /// the number of arguments that have an attribute set on them (including the + /// function itself). + unsigned getNumSlots() const; + + /// \brief Return the index for the given slot. + uint64_t getSlotIndex(unsigned Slot) const; + + /// \brief Return the attributes at the given slot. + AttributeSet getSlotAttributes(unsigned Slot) const; + + void dump() const; +}; + +//===----------------------------------------------------------------------===// +/// \class +/// \brief Provide DenseMapInfo for AttributeSet. +template<> struct DenseMapInfo<AttributeSet> { + static inline AttributeSet getEmptyKey() { + uintptr_t Val = static_cast<uintptr_t>(-1); + Val <<= PointerLikeTypeTraits<void*>::NumLowBitsAvailable; + return AttributeSet(reinterpret_cast<AttributeSetImpl*>(Val)); + } + static inline AttributeSet getTombstoneKey() { + uintptr_t Val = static_cast<uintptr_t>(-2); + Val <<= PointerLikeTypeTraits<void*>::NumLowBitsAvailable; + return AttributeSet(reinterpret_cast<AttributeSetImpl*>(Val)); + } + static unsigned getHashValue(AttributeSet AS) { + return (unsigned((uintptr_t)AS.pImpl) >> 4) ^ + (unsigned((uintptr_t)AS.pImpl) >> 9); + } + static bool isEqual(AttributeSet LHS, AttributeSet RHS) { return LHS == RHS; } +}; + +//===----------------------------------------------------------------------===// +/// \class +/// \brief This class is used in conjunction with the Attribute::get method to +/// create an Attribute object. The object itself is uniquified. The Builder's +/// value, however, is not. So this can be used as a quick way to test for +/// equality, presence of attributes, etc. +class AttrBuilder { + std::bitset<Attribute::EndAttrKinds> Attrs; + std::map<std::string, std::string> TargetDepAttrs; + uint64_t Alignment; + uint64_t StackAlignment; +public: + AttrBuilder() : Attrs(0), Alignment(0), StackAlignment(0) {} + explicit AttrBuilder(uint64_t Val) + : Attrs(0), Alignment(0), StackAlignment(0) { + addRawValue(Val); + } + AttrBuilder(const Attribute &A) : Attrs(0), Alignment(0), StackAlignment(0) { + addAttribute(A); + } + AttrBuilder(AttributeSet AS, unsigned Idx); + AttrBuilder(const AttrBuilder &B) + : Attrs(B.Attrs), + TargetDepAttrs(B.TargetDepAttrs.begin(), B.TargetDepAttrs.end()), + Alignment(B.Alignment), StackAlignment(B.StackAlignment) {} + + void clear(); + + /// \brief Add an attribute to the builder. + AttrBuilder &addAttribute(Attribute::AttrKind Val); + + /// \brief Add the Attribute object to the builder. + AttrBuilder &addAttribute(Attribute A); + + /// \brief Add the target-dependent attribute to the builder. + AttrBuilder &addAttribute(StringRef A, StringRef V = StringRef()); + + /// \brief Remove an attribute from the builder. + AttrBuilder &removeAttribute(Attribute::AttrKind Val); + + /// \brief Remove the attributes from the builder. + AttrBuilder &removeAttributes(AttributeSet A, uint64_t Index); + + /// \brief Remove the target-dependent attribute to the builder. + AttrBuilder &removeAttribute(StringRef A); + + /// \brief Add the attributes from the builder. + AttrBuilder &merge(const AttrBuilder &B); + + /// \brief Return true if the builder has the specified attribute. + bool contains(Attribute::AttrKind A) const { + assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!"); + return Attrs[A]; + } + + /// \brief Return true if the builder has the specified target-dependent + /// attribute. + bool contains(StringRef A) const; + + /// \brief Return true if the builder has IR-level attributes. + bool hasAttributes() const; + + /// \brief Return true if the builder has any attribute that's in the + /// specified attribute. + bool hasAttributes(AttributeSet A, uint64_t Index) const; + + /// \brief Return true if the builder has an alignment attribute. + bool hasAlignmentAttr() const; + + /// \brief Retrieve the alignment attribute, if it exists. + uint64_t getAlignment() const { return Alignment; } + + /// \brief Retrieve the stack alignment attribute, if it exists. + uint64_t getStackAlignment() const { return StackAlignment; } + + /// \brief This turns an int alignment (which must be a power of 2) into the + /// form used internally in Attribute. + AttrBuilder &addAlignmentAttr(unsigned Align); + + /// \brief This turns an int stack alignment (which must be a power of 2) into + /// the form used internally in Attribute. + AttrBuilder &addStackAlignmentAttr(unsigned Align); + + /// \brief Return true if the builder contains no target-independent + /// attributes. + bool empty() const { return Attrs.none(); } + + // Iterators for target-dependent attributes. + typedef std::pair<std::string, std::string> td_type; + typedef std::map<std::string, std::string>::iterator td_iterator; + typedef std::map<std::string, std::string>::const_iterator td_const_iterator; + + td_iterator td_begin() { return TargetDepAttrs.begin(); } + td_iterator td_end() { return TargetDepAttrs.end(); } + + td_const_iterator td_begin() const { return TargetDepAttrs.begin(); } + td_const_iterator td_end() const { return TargetDepAttrs.end(); } + + bool td_empty() const { return TargetDepAttrs.empty(); } + + /// \brief Remove attributes that are used on functions only. + void removeFunctionOnlyAttrs(); + + bool operator==(const AttrBuilder &B); + bool operator!=(const AttrBuilder &B) { + return !(*this == B); + } + + // FIXME: Remove this in 4.0. + + /// \brief Add the raw value to the internal representation. + AttrBuilder &addRawValue(uint64_t Val); +}; + +namespace AttributeFuncs { + +/// \brief Which attributes cannot be applied to a type. +AttributeSet typeIncompatible(Type *Ty, uint64_t Index); + +} // end AttributeFuncs namespace + +} // end llvm namespace + +#endif diff --git a/include/llvm/IR/BasicBlock.h b/include/llvm/IR/BasicBlock.h new file mode 100644 index 0000000..ea5695a --- /dev/null +++ b/include/llvm/IR/BasicBlock.h @@ -0,0 +1,303 @@ +//===-- llvm/BasicBlock.h - Represent a basic block in the VM ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the BasicBlock class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_BASICBLOCK_H +#define LLVM_IR_BASICBLOCK_H + +#include "llvm/ADT/Twine.h" +#include "llvm/ADT/ilist.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/SymbolTableListTraits.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class LandingPadInst; +class TerminatorInst; +class LLVMContext; +class BlockAddress; + +template<> struct ilist_traits<Instruction> + : public SymbolTableListTraits<Instruction, BasicBlock> { + + /// \brief Return a node that marks the end of a list. + /// + /// The sentinel is relative to this instance, so we use a non-static + /// method. + Instruction *createSentinel() const { + // Since i(p)lists always publicly derive from their corresponding traits, + // placing a data member in this class will augment the i(p)list. But since + // the NodeTy is expected to be publicly derive from ilist_node<NodeTy>, + // there is a legal viable downcast from it to NodeTy. We use this trick to + // superimpose an i(p)list with a "ghostly" NodeTy, which becomes the + // sentinel. Dereferencing the sentinel is forbidden (save the + // ilist_node<NodeTy>), so no one will ever notice the superposition. + return static_cast<Instruction*>(&Sentinel); + } + static void destroySentinel(Instruction*) {} + + Instruction *provideInitialHead() const { return createSentinel(); } + Instruction *ensureHead(Instruction*) const { return createSentinel(); } + static void noteHead(Instruction*, Instruction*) {} +private: + mutable ilist_half_node<Instruction> Sentinel; +}; + +/// \brief LLVM Basic Block Representation +/// +/// This represents a single basic block in LLVM. A basic block is simply a +/// container of instructions that execute sequentially. Basic blocks are Values +/// because they are referenced by instructions such as branches and switch +/// tables. The type of a BasicBlock is "Type::LabelTy" because the basic block +/// represents a label to which a branch can jump. +/// +/// A well formed basic block is formed of a list of non-terminating +/// instructions followed by a single TerminatorInst instruction. +/// TerminatorInst's may not occur in the middle of basic blocks, and must +/// terminate the blocks. The BasicBlock class allows malformed basic blocks to +/// occur because it may be useful in the intermediate stage of constructing or +/// modifying a program. However, the verifier will ensure that basic blocks +/// are "well formed". +class BasicBlock : public Value, // Basic blocks are data objects also + public ilist_node<BasicBlock> { + friend class BlockAddress; +public: + typedef iplist<Instruction> InstListType; +private: + InstListType InstList; + Function *Parent; + + void setParent(Function *parent); + friend class SymbolTableListTraits<BasicBlock, Function>; + + BasicBlock(const BasicBlock &) LLVM_DELETED_FUNCTION; + void operator=(const BasicBlock &) LLVM_DELETED_FUNCTION; + + /// \brief Constructor. + /// + /// If the function parameter is specified, the basic block is automatically + /// inserted at either the end of the function (if InsertBefore is null), or + /// before the specified basic block. + explicit BasicBlock(LLVMContext &C, const Twine &Name = "", + Function *Parent = 0, BasicBlock *InsertBefore = 0); +public: + /// \brief Get the context in which this basic block lives. + LLVMContext &getContext() const; + + /// Instruction iterators... + typedef InstListType::iterator iterator; + typedef InstListType::const_iterator const_iterator; + typedef InstListType::reverse_iterator reverse_iterator; + typedef InstListType::const_reverse_iterator const_reverse_iterator; + + /// \brief Creates a new BasicBlock. + /// + /// If the Parent parameter is specified, the basic block is automatically + /// inserted at either the end of the function (if InsertBefore is 0), or + /// before the specified basic block. + static BasicBlock *Create(LLVMContext &Context, const Twine &Name = "", + Function *Parent = 0,BasicBlock *InsertBefore = 0) { + return new BasicBlock(Context, Name, Parent, InsertBefore); + } + ~BasicBlock(); + + /// \brief Return the enclosing method, or null if none. + const Function *getParent() const { return Parent; } + Function *getParent() { return Parent; } + + /// \brief Returns the terminator instruction if the block is well formed or + /// null if the block is not well formed. + TerminatorInst *getTerminator(); + const TerminatorInst *getTerminator() const; + + /// \brief Returns a pointer to the first instruction in this block that is + /// not a PHINode instruction. + /// + /// When adding instructions to the beginning of the basic block, they should + /// be added before the returned value, not before the first instruction, + /// which might be PHI. Returns 0 is there's no non-PHI instruction. + Instruction* getFirstNonPHI(); + const Instruction* getFirstNonPHI() const { + return const_cast<BasicBlock*>(this)->getFirstNonPHI(); + } + + /// \brief Returns a pointer to the first instruction in this block that is not + /// a PHINode or a debug intrinsic. + Instruction* getFirstNonPHIOrDbg(); + const Instruction* getFirstNonPHIOrDbg() const { + return const_cast<BasicBlock*>(this)->getFirstNonPHIOrDbg(); + } + + /// \brief Returns a pointer to the first instruction in this block that is not + /// a PHINode, a debug intrinsic, or a lifetime intrinsic. + Instruction* getFirstNonPHIOrDbgOrLifetime(); + const Instruction* getFirstNonPHIOrDbgOrLifetime() const { + return const_cast<BasicBlock*>(this)->getFirstNonPHIOrDbgOrLifetime(); + } + + /// \brief Returns an iterator to the first instruction in this block that is + /// suitable for inserting a non-PHI instruction. + /// + /// In particular, it skips all PHIs and LandingPad instructions. + iterator getFirstInsertionPt(); + const_iterator getFirstInsertionPt() const { + return const_cast<BasicBlock*>(this)->getFirstInsertionPt(); + } + + /// \brief Unlink 'this' from the containing function, but do not delete it. + void removeFromParent(); + + /// \brief Unlink 'this' from the containing function and delete it. + void eraseFromParent(); + + /// \brief Unlink this basic block from its current function and insert it + /// into the function that \p MovePos lives in, right before \p MovePos. + void moveBefore(BasicBlock *MovePos); + + /// \brief Unlink this basic block from its current function and insert it + /// right after \p MovePos in the function \p MovePos lives in. + void moveAfter(BasicBlock *MovePos); + + + /// \brief Return this block if it has a single predecessor block. Otherwise + /// return a null pointer. + BasicBlock *getSinglePredecessor(); + const BasicBlock *getSinglePredecessor() const { + return const_cast<BasicBlock*>(this)->getSinglePredecessor(); + } + + /// \brief Return this block if it has a unique predecessor block. Otherwise return a null pointer. + /// + /// Note that unique predecessor doesn't mean single edge, there can be + /// multiple edges from the unique predecessor to this block (for example a + /// switch statement with multiple cases having the same destination). + BasicBlock *getUniquePredecessor(); + const BasicBlock *getUniquePredecessor() const { + return const_cast<BasicBlock*>(this)->getUniquePredecessor(); + } + + //===--------------------------------------------------------------------===// + /// Instruction iterator methods + /// + inline iterator begin() { return InstList.begin(); } + inline const_iterator begin() const { return InstList.begin(); } + inline iterator end () { return InstList.end(); } + inline const_iterator end () const { return InstList.end(); } + + inline reverse_iterator rbegin() { return InstList.rbegin(); } + inline const_reverse_iterator rbegin() const { return InstList.rbegin(); } + inline reverse_iterator rend () { return InstList.rend(); } + inline const_reverse_iterator rend () const { return InstList.rend(); } + + inline size_t size() const { return InstList.size(); } + inline bool empty() const { return InstList.empty(); } + inline const Instruction &front() const { return InstList.front(); } + inline Instruction &front() { return InstList.front(); } + inline const Instruction &back() const { return InstList.back(); } + inline Instruction &back() { return InstList.back(); } + + /// \brief Return the underlying instruction list container. + /// + /// Currently you need to access the underlying instruction list container + /// directly if you want to modify it. + const InstListType &getInstList() const { return InstList; } + InstListType &getInstList() { return InstList; } + + /// \brief Returns a pointer to a member of the instruction list. + static iplist<Instruction> BasicBlock::*getSublistAccess(Instruction*) { + return &BasicBlock::InstList; + } + + /// \brief Returns a pointer to the symbol table if one exists. + ValueSymbolTable *getValueSymbolTable(); + + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast. + static inline bool classof(const Value *V) { + return V->getValueID() == Value::BasicBlockVal; + } + + /// \brief Cause all subinstructions to "let go" of all the references that + /// said subinstructions are maintaining. + /// + /// This allows one to 'delete' a whole class at a time, even though there may + /// be circular references... first all references are dropped, and all use + /// counts go to zero. Then everything is delete'd for real. Note that no + /// operations are valid on an object that has "dropped all references", + /// except operator delete. + void dropAllReferences(); + + /// \brief Notify the BasicBlock that the predecessor \p Pred is no longer + /// able to reach it. + /// + /// This is actually not used to update the Predecessor list, but is actually + /// used to update the PHI nodes that reside in the block. Note that this + /// should be called while the predecessor still refers to this block. + void removePredecessor(BasicBlock *Pred, bool DontDeleteUselessPHIs = false); + + /// \brief Split the basic block into two basic blocks at the specified + /// instruction. + /// + /// Note that all instructions BEFORE the specified iterator stay as part of + /// the original basic block, an unconditional branch is added to the original + /// BB, and the rest of the instructions in the BB are moved to the new BB, + /// including the old terminator. The newly formed BasicBlock is returned. + /// This function invalidates the specified iterator. + /// + /// Note that this only works on well formed basic blocks (must have a + /// terminator), and 'I' must not be the end of instruction list (which would + /// cause a degenerate basic block to be formed, having a terminator inside of + /// the basic block). + /// + /// Also note that this doesn't preserve any passes. To split blocks while + /// keeping loop information consistent, use the SplitBlock utility function. + BasicBlock *splitBasicBlock(iterator I, const Twine &BBName = ""); + + /// \brief Returns true if there are any uses of this basic block other than + /// direct branches, switches, etc. to it. + bool hasAddressTaken() const { return getSubclassDataFromValue() != 0; } + + /// \brief Update all phi nodes in this basic block's successors to refer to + /// basic block \p New instead of to it. + void replaceSuccessorsPhiUsesWith(BasicBlock *New); + + /// \brief Return true if this basic block is a landing pad. + /// + /// Being a ``landing pad'' means that the basic block is the destination of + /// the 'unwind' edge of an invoke instruction. + bool isLandingPad() const; + + /// \brief Return the landingpad instruction associated with the landing pad. + LandingPadInst *getLandingPadInst(); + const LandingPadInst *getLandingPadInst() const; + +private: + /// \brief Increment the internal refcount of the number of BlockAddresses + /// referencing this BasicBlock by \p Amt. + /// + /// This is almost always 0, sometimes one possibly, but almost never 2, and + /// inconceivably 3 or more. + void AdjustBlockAddressRefCount(int Amt) { + setValueSubclassData(getSubclassDataFromValue()+Amt); + assert((int)(signed char)getSubclassDataFromValue() >= 0 && + "Refcount wrap-around"); + } + /// \brief Shadow Value::setValueSubclassData with a private forwarding method + /// so that any future subclasses cannot accidentally use it. + void setValueSubclassData(unsigned short D) { + Value::setValueSubclassData(D); + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/IR/CMakeLists.txt b/include/llvm/IR/CMakeLists.txt new file mode 100644 index 0000000..2d52a89 --- /dev/null +++ b/include/llvm/IR/CMakeLists.txt @@ -0,0 +1,7 @@ +set(LLVM_TARGET_DEFINITIONS Intrinsics.td) + +tablegen(LLVM Intrinsics.gen -gen-intrinsic) + +add_custom_target(intrinsics_gen ALL + DEPENDS ${llvm_builded_incs_dir}/IR/Intrinsics.gen) +set_target_properties(intrinsics_gen PROPERTIES FOLDER "Tablegenning") diff --git a/include/llvm/IR/CallingConv.h b/include/llvm/IR/CallingConv.h new file mode 100644 index 0000000..6f3ab20 --- /dev/null +++ b/include/llvm/IR/CallingConv.h @@ -0,0 +1,129 @@ +//===-- llvm/CallingConv.h - LLVM Calling Conventions -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines LLVM's set of calling conventions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_CALLINGCONV_H +#define LLVM_IR_CALLINGCONV_H + +namespace llvm { + +/// CallingConv Namespace - This namespace contains an enum with a value for +/// the well-known calling conventions. +/// +namespace CallingConv { + /// A set of enums which specify the assigned numeric values for known llvm + /// calling conventions. + /// @brief LLVM Calling Convention Representation + enum ID { + /// C - The default llvm calling convention, compatible with C. This + /// convention is the only calling convention that supports varargs calls. + /// As with typical C calling conventions, the callee/caller have to + /// tolerate certain amounts of prototype mismatch. + C = 0, + + // Generic LLVM calling conventions. None of these calling conventions + // support varargs calls, and all assume that the caller and callee + // prototype exactly match. + + /// Fast - This calling convention attempts to make calls as fast as + /// possible (e.g. by passing things in registers). + Fast = 8, + + // Cold - This calling convention attempts to make code in the caller as + // efficient as possible under the assumption that the call is not commonly + // executed. As such, these calls often preserve all registers so that the + // call does not break any live ranges in the caller side. + Cold = 9, + + // GHC - Calling convention used by the Glasgow Haskell Compiler (GHC). + GHC = 10, + + // HiPE - Calling convention used by the High-Performance Erlang Compiler + // (HiPE). + HiPE = 11, + + // Target - This is the start of the target-specific calling conventions, + // e.g. fastcall and thiscall on X86. + FirstTargetCC = 64, + + /// X86_StdCall - stdcall is the calling conventions mostly used by the + /// Win32 API. It is basically the same as the C convention with the + /// difference in that the callee is responsible for popping the arguments + /// from the stack. + X86_StdCall = 64, + + /// X86_FastCall - 'fast' analog of X86_StdCall. Passes first two arguments + /// in ECX:EDX registers, others - via stack. Callee is responsible for + /// stack cleaning. + X86_FastCall = 65, + + /// ARM_APCS - ARM Procedure Calling Standard calling convention (obsolete, + /// but still used on some targets). + ARM_APCS = 66, + + /// ARM_AAPCS - ARM Architecture Procedure Calling Standard calling + /// convention (aka EABI). Soft float variant. + ARM_AAPCS = 67, + + /// ARM_AAPCS_VFP - Same as ARM_AAPCS, but uses hard floating point ABI. + ARM_AAPCS_VFP = 68, + + /// MSP430_INTR - Calling convention used for MSP430 interrupt routines. + MSP430_INTR = 69, + + /// X86_ThisCall - Similar to X86_StdCall. Passes first argument in ECX, + /// others via stack. Callee is responsible for stack cleaning. MSVC uses + /// this by default for methods in its ABI. + X86_ThisCall = 70, + + /// PTX_Kernel - Call to a PTX kernel. + /// Passes all arguments in parameter space. + PTX_Kernel = 71, + + /// PTX_Device - Call to a PTX device function. + /// Passes all arguments in register or parameter space. + PTX_Device = 72, + + /// MBLAZE_INTR - Calling convention used for MBlaze interrupt routines. + MBLAZE_INTR = 73, + + /// MBLAZE_INTR - Calling convention used for MBlaze interrupt support + /// routines (i.e. GCC's save_volatiles attribute). + MBLAZE_SVOL = 74, + + /// SPIR_FUNC - Calling convention for SPIR non-kernel device functions. + /// No lowering or expansion of arguments. + /// Structures are passed as a pointer to a struct with the byval attribute. + /// Functions can only call SPIR_FUNC and SPIR_KERNEL functions. + /// Functions can only have zero or one return values. + /// Variable arguments are not allowed, except for printf. + /// How arguments/return values are lowered are not specified. + /// Functions are only visible to the devices. + SPIR_FUNC = 75, + + /// SPIR_KERNEL - Calling convention for SPIR kernel functions. + /// Inherits the restrictions of SPIR_FUNC, except + /// Cannot have non-void return values. + /// Cannot have variable arguments. + /// Can also be called by the host. + /// Is externally visible. + SPIR_KERNEL = 76, + + /// Intel_OCL_BI - Calling conventions for Intel OpenCL built-ins + Intel_OCL_BI = 77 + + }; +} // End CallingConv namespace + +} // End llvm namespace + +#endif diff --git a/include/llvm/IR/Constant.h b/include/llvm/IR/Constant.h new file mode 100644 index 0000000..26bad1d --- /dev/null +++ b/include/llvm/IR/Constant.h @@ -0,0 +1,170 @@ +//===-- llvm/Constant.h - Constant class definition -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the Constant class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_CONSTANT_H +#define LLVM_IR_CONSTANT_H + +#include "llvm/IR/User.h" + +namespace llvm { + class APInt; + + template<typename T> class SmallVectorImpl; + +/// This is an important base class in LLVM. It provides the common facilities +/// of all constant values in an LLVM program. A constant is a value that is +/// immutable at runtime. Functions are constants because their address is +/// immutable. Same with global variables. +/// +/// All constants share the capabilities provided in this class. All constants +/// can have a null value. They can have an operand list. Constants can be +/// simple (integer and floating point values), complex (arrays and structures), +/// or expression based (computations yielding a constant value composed of +/// only certain operators and other constant values). +/// +/// Note that Constants are immutable (once created they never change) +/// and are fully shared by structural equivalence. This means that two +/// structurally equivalent constants will always have the same address. +/// Constants are created on demand as needed and never deleted: thus clients +/// don't have to worry about the lifetime of the objects. +/// @brief LLVM Constant Representation +class Constant : public User { + void operator=(const Constant &) LLVM_DELETED_FUNCTION; + Constant(const Constant &) LLVM_DELETED_FUNCTION; + virtual void anchor(); + +protected: + Constant(Type *ty, ValueTy vty, Use *Ops, unsigned NumOps) + : User(ty, vty, Ops, NumOps) {} + + void destroyConstantImpl(); +public: + /// isNullValue - Return true if this is the value that would be returned by + /// getNullValue. + bool isNullValue() const; + + /// isAllOnesValue - Return true if this is the value that would be returned by + /// getAllOnesValue. + bool isAllOnesValue() const; + + /// isNegativeZeroValue - Return true if the value is what would be returned + /// by getZeroValueForNegation. + bool isNegativeZeroValue() const; + + /// Return true if the value is negative zero or null value. + bool isZeroValue() const; + + /// canTrap - Return true if evaluation of this constant could trap. This is + /// true for things like constant expressions that could divide by zero. + bool canTrap() const; + + /// isThreadDependent - Return true if the value can vary between threads. + bool isThreadDependent() const; + + /// isConstantUsed - Return true if the constant has users other than constant + /// exprs and other dangling things. + bool isConstantUsed() const; + + enum PossibleRelocationsTy { + NoRelocation = 0, + LocalRelocation = 1, + GlobalRelocations = 2 + }; + + /// getRelocationInfo - This method classifies the entry according to + /// whether or not it may generate a relocation entry. This must be + /// conservative, so if it might codegen to a relocatable entry, it should say + /// so. The return values are: + /// + /// NoRelocation: This constant pool entry is guaranteed to never have a + /// relocation applied to it (because it holds a simple constant like + /// '4'). + /// LocalRelocation: This entry has relocations, but the entries are + /// guaranteed to be resolvable by the static linker, so the dynamic + /// linker will never see them. + /// GlobalRelocations: This entry may have arbitrary relocations. + /// + /// FIXME: This really should not be in VMCore. + PossibleRelocationsTy getRelocationInfo() const; + + /// getAggregateElement - For aggregates (struct/array/vector) return the + /// constant that corresponds to the specified element if possible, or null if + /// not. This can return null if the element index is a ConstantExpr, or if + /// 'this' is a constant expr. + Constant *getAggregateElement(unsigned Elt) const; + Constant *getAggregateElement(Constant *Elt) const; + + /// getSplatValue - If this is a splat vector constant, meaning that all of + /// the elements have the same value, return that value. Otherwise return 0. + Constant *getSplatValue() const; + + /// If C is a constant integer then return its value, otherwise C must be a + /// vector of constant integers, all equal, and the common value is returned. + const APInt &getUniqueInteger() const; + + /// destroyConstant - Called if some element of this constant is no longer + /// valid. At this point only other constants may be on the use_list for this + /// constant. Any constants on our Use list must also be destroy'd. The + /// implementation must be sure to remove the constant from the list of + /// available cached constants. Implementations should call + /// destroyConstantImpl as the last thing they do, to destroy all users and + /// delete this. + virtual void destroyConstant() { llvm_unreachable("Not reached!"); } + + //// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Value *V) { + return V->getValueID() >= ConstantFirstVal && + V->getValueID() <= ConstantLastVal; + } + + /// replaceUsesOfWithOnConstant - This method is a special form of + /// User::replaceUsesOfWith (which does not work on constants) that does work + /// on constants. Basically this method goes through the trouble of building + /// a new constant that is equivalent to the current one, with all uses of + /// From replaced with uses of To. After this construction is completed, all + /// of the users of 'this' are replaced to use the new constant, and then + /// 'this' is deleted. In general, you should not call this method, instead, + /// use Value::replaceAllUsesWith, which automatically dispatches to this + /// method as needed. + /// + virtual void replaceUsesOfWithOnConstant(Value *, Value *, Use *) { + // Provide a default implementation for constants (like integers) that + // cannot use any other values. This cannot be called at runtime, but needs + // to be here to avoid link errors. + assert(getNumOperands() == 0 && "replaceUsesOfWithOnConstant must be " + "implemented for all constants that have operands!"); + llvm_unreachable("Constants that do not have operands cannot be using " + "'From'!"); + } + + static Constant *getNullValue(Type* Ty); + + /// @returns the value for an integer or vector of integer constant of the + /// given type that has all its bits set to true. + /// @brief Get the all ones value + static Constant *getAllOnesValue(Type* Ty); + + /// getIntegerValue - Return the value for an integer or pointer constant, + /// or a vector thereof, with the given scalar value. + static Constant *getIntegerValue(Type* Ty, const APInt &V); + + /// removeDeadConstantUsers - If there are any dead constant users dangling + /// off of this constant, remove them. This method is useful for clients + /// that want to check to see if a global is unused, but don't want to deal + /// with potentially dead constants hanging off of the globals. + void removeDeadConstantUsers() const; +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h new file mode 100644 index 0000000..ad258f9 --- /dev/null +++ b/include/llvm/IR/Constants.h @@ -0,0 +1,1163 @@ +//===-- llvm/Constants.h - Constant class subclass definitions --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// @file +/// This file contains the declarations for the subclasses of Constant, +/// which represent the different flavors of constant values that live in LLVM. +/// Note that Constants are immutable (once created they never change) and are +/// fully shared by structural equivalence. This means that two structurally +/// equivalent constants will always have the same address. Constant's are +/// created on demand as needed and never deleted: thus clients don't have to +/// worry about the lifetime of the objects. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_CONSTANTS_H +#define LLVM_IR_CONSTANTS_H + +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/IR/Constant.h" +#include "llvm/IR/OperandTraits.h" + +namespace llvm { + +class ArrayType; +class IntegerType; +class StructType; +class PointerType; +class VectorType; +class SequentialType; + +template<class ConstantClass, class TypeClass, class ValType> +struct ConstantCreator; +template<class ConstantClass, class TypeClass> +struct ConstantArrayCreator; +template<class ConstantClass, class TypeClass> +struct ConvertConstantType; + +//===----------------------------------------------------------------------===// +/// This is the shared class of boolean and integer constants. This class +/// represents both boolean and integral constants. +/// @brief Class for constant integers. +class ConstantInt : public Constant { + virtual void anchor(); + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + ConstantInt(const ConstantInt &) LLVM_DELETED_FUNCTION; + ConstantInt(IntegerType *Ty, const APInt& V); + APInt Val; +protected: + // allocate space for exactly zero operands + void *operator new(size_t s) { + return User::operator new(s, 0); + } +public: + static ConstantInt *getTrue(LLVMContext &Context); + static ConstantInt *getFalse(LLVMContext &Context); + static Constant *getTrue(Type *Ty); + static Constant *getFalse(Type *Ty); + + /// If Ty is a vector type, return a Constant with a splat of the given + /// value. Otherwise return a ConstantInt for the given value. + static Constant *get(Type *Ty, uint64_t V, bool isSigned = false); + + /// Return a ConstantInt with the specified integer value for the specified + /// type. If the type is wider than 64 bits, the value will be zero-extended + /// to fit the type, unless isSigned is true, in which case the value will + /// be interpreted as a 64-bit signed integer and sign-extended to fit + /// the type. + /// @brief Get a ConstantInt for a specific value. + static ConstantInt *get(IntegerType *Ty, uint64_t V, + bool isSigned = false); + + /// Return a ConstantInt with the specified value for the specified type. The + /// value V will be canonicalized to a an unsigned APInt. Accessing it with + /// either getSExtValue() or getZExtValue() will yield a correctly sized and + /// signed value for the type Ty. + /// @brief Get a ConstantInt for a specific signed value. + static ConstantInt *getSigned(IntegerType *Ty, int64_t V); + static Constant *getSigned(Type *Ty, int64_t V); + + /// Return a ConstantInt with the specified value and an implied Type. The + /// type is the integer type that corresponds to the bit width of the value. + static ConstantInt *get(LLVMContext &Context, const APInt &V); + + /// Return a ConstantInt constructed from the string strStart with the given + /// radix. + static ConstantInt *get(IntegerType *Ty, StringRef Str, + uint8_t radix); + + /// If Ty is a vector type, return a Constant with a splat of the given + /// value. Otherwise return a ConstantInt for the given value. + static Constant *get(Type* Ty, const APInt& V); + + /// Return the constant as an APInt value reference. This allows clients to + /// obtain a copy of the value, with all its precision in tact. + /// @brief Return the constant's value. + inline const APInt &getValue() const { + return Val; + } + + /// getBitWidth - Return the bitwidth of this constant. + unsigned getBitWidth() const { return Val.getBitWidth(); } + + /// Return the constant as a 64-bit unsigned integer value after it + /// has been zero extended as appropriate for the type of this constant. Note + /// that this method can assert if the value does not fit in 64 bits. + /// @deprecated + /// @brief Return the zero extended value. + inline uint64_t getZExtValue() const { + return Val.getZExtValue(); + } + + /// Return the constant as a 64-bit integer value after it has been sign + /// extended as appropriate for the type of this constant. Note that + /// this method can assert if the value does not fit in 64 bits. + /// @deprecated + /// @brief Return the sign extended value. + inline int64_t getSExtValue() const { + return Val.getSExtValue(); + } + + /// A helper method that can be used to determine if the constant contained + /// within is equal to a constant. This only works for very small values, + /// because this is all that can be represented with all types. + /// @brief Determine if this constant's value is same as an unsigned char. + bool equalsInt(uint64_t V) const { + return Val == V; + } + + /// getType - Specialize the getType() method to always return an IntegerType, + /// which reduces the amount of casting needed in parts of the compiler. + /// + inline IntegerType *getType() const { + return reinterpret_cast<IntegerType*>(Value::getType()); + } + + /// This static method returns true if the type Ty is big enough to + /// represent the value V. This can be used to avoid having the get method + /// assert when V is larger than Ty can represent. Note that there are two + /// versions of this method, one for unsigned and one for signed integers. + /// Although ConstantInt canonicalizes everything to an unsigned integer, + /// the signed version avoids callers having to convert a signed quantity + /// to the appropriate unsigned type before calling the method. + /// @returns true if V is a valid value for type Ty + /// @brief Determine if the value is in range for the given type. + static bool isValueValidForType(Type *Ty, uint64_t V); + static bool isValueValidForType(Type *Ty, int64_t V); + + bool isNegative() const { return Val.isNegative(); } + + /// This is just a convenience method to make client code smaller for a + /// common code. It also correctly performs the comparison without the + /// potential for an assertion from getZExtValue(). + bool isZero() const { + return Val == 0; + } + + /// This is just a convenience method to make client code smaller for a + /// common case. It also correctly performs the comparison without the + /// potential for an assertion from getZExtValue(). + /// @brief Determine if the value is one. + bool isOne() const { + return Val == 1; + } + + /// This function will return true iff every bit in this constant is set + /// to true. + /// @returns true iff this constant's bits are all set to true. + /// @brief Determine if the value is all ones. + bool isMinusOne() const { + return Val.isAllOnesValue(); + } + + /// This function will return true iff this constant represents the largest + /// value that may be represented by the constant's type. + /// @returns true iff this is the largest value that may be represented + /// by this type. + /// @brief Determine if the value is maximal. + bool isMaxValue(bool isSigned) const { + if (isSigned) + return Val.isMaxSignedValue(); + else + return Val.isMaxValue(); + } + + /// This function will return true iff this constant represents the smallest + /// value that may be represented by this constant's type. + /// @returns true if this is the smallest value that may be represented by + /// this type. + /// @brief Determine if the value is minimal. + bool isMinValue(bool isSigned) const { + if (isSigned) + return Val.isMinSignedValue(); + else + return Val.isMinValue(); + } + + /// This function will return true iff this constant represents a value with + /// active bits bigger than 64 bits or a value greater than the given uint64_t + /// value. + /// @returns true iff this constant is greater or equal to the given number. + /// @brief Determine if the value is greater or equal to the given number. + bool uge(uint64_t Num) const { + return Val.getActiveBits() > 64 || Val.getZExtValue() >= Num; + } + + /// getLimitedValue - If the value is smaller than the specified limit, + /// return it, otherwise return the limit value. This causes the value + /// to saturate to the limit. + /// @returns the min of the value of the constant and the specified value + /// @brief Get the constant's value with a saturation limit + uint64_t getLimitedValue(uint64_t Limit = ~0ULL) const { + return Val.getLimitedValue(Limit); + } + + /// @brief Methods to support type inquiry through isa, cast, and dyn_cast. + static bool classof(const Value *V) { + return V->getValueID() == ConstantIntVal; + } +}; + + +//===----------------------------------------------------------------------===// +/// ConstantFP - Floating Point Values [float, double] +/// +class ConstantFP : public Constant { + APFloat Val; + virtual void anchor(); + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + ConstantFP(const ConstantFP &) LLVM_DELETED_FUNCTION; + friend class LLVMContextImpl; +protected: + ConstantFP(Type *Ty, const APFloat& V); +protected: + // allocate space for exactly zero operands + void *operator new(size_t s) { + return User::operator new(s, 0); + } +public: + /// Floating point negation must be implemented with f(x) = -0.0 - x. This + /// method returns the negative zero constant for floating point or vector + /// floating point types; for all other types, it returns the null value. + static Constant *getZeroValueForNegation(Type *Ty); + + /// get() - This returns a ConstantFP, or a vector containing a splat of a + /// ConstantFP, for the specified value in the specified type. This should + /// only be used for simple constant values like 2.0/1.0 etc, that are + /// known-valid both as host double and as the target format. + static Constant *get(Type* Ty, double V); + static Constant *get(Type* Ty, StringRef Str); + static ConstantFP *get(LLVMContext &Context, const APFloat &V); + static ConstantFP *getNegativeZero(Type* Ty); + static ConstantFP *getInfinity(Type *Ty, bool Negative = false); + + /// isValueValidForType - return true if Ty is big enough to represent V. + static bool isValueValidForType(Type *Ty, const APFloat &V); + inline const APFloat &getValueAPF() const { return Val; } + + /// isZero - Return true if the value is positive or negative zero. + bool isZero() const { return Val.isZero(); } + + /// isNegative - Return true if the sign bit is set. + bool isNegative() const { return Val.isNegative(); } + + /// isNaN - Return true if the value is a NaN. + bool isNaN() const { return Val.isNaN(); } + + /// isExactlyValue - We don't rely on operator== working on double values, as + /// it returns true for things that are clearly not equal, like -0.0 and 0.0. + /// As such, this method can be used to do an exact bit-for-bit comparison of + /// two floating point values. The version with a double operand is retained + /// because it's so convenient to write isExactlyValue(2.0), but please use + /// it only for simple constants. + bool isExactlyValue(const APFloat &V) const; + + bool isExactlyValue(double V) const { + bool ignored; + APFloat FV(V); + FV.convert(Val.getSemantics(), APFloat::rmNearestTiesToEven, &ignored); + return isExactlyValue(FV); + } + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const Value *V) { + return V->getValueID() == ConstantFPVal; + } +}; + +//===----------------------------------------------------------------------===// +/// ConstantAggregateZero - All zero aggregate value +/// +class ConstantAggregateZero : public Constant { + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + ConstantAggregateZero(const ConstantAggregateZero &) LLVM_DELETED_FUNCTION; +protected: + explicit ConstantAggregateZero(Type *ty) + : Constant(ty, ConstantAggregateZeroVal, 0, 0) {} +protected: + // allocate space for exactly zero operands + void *operator new(size_t s) { + return User::operator new(s, 0); + } +public: + static ConstantAggregateZero *get(Type *Ty); + + virtual void destroyConstant(); + + /// getSequentialElement - If this CAZ has array or vector type, return a zero + /// with the right element type. + Constant *getSequentialElement() const; + + /// getStructElement - If this CAZ has struct type, return a zero with the + /// right element type for the specified element. + Constant *getStructElement(unsigned Elt) const; + + /// getElementValue - Return a zero of the right value for the specified GEP + /// index. + Constant *getElementValue(Constant *C) const; + + /// getElementValue - Return a zero of the right value for the specified GEP + /// index. + Constant *getElementValue(unsigned Idx) const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + /// + static bool classof(const Value *V) { + return V->getValueID() == ConstantAggregateZeroVal; + } +}; + + +//===----------------------------------------------------------------------===// +/// ConstantArray - Constant Array Declarations +/// +class ConstantArray : public Constant { + friend struct ConstantArrayCreator<ConstantArray, ArrayType>; + ConstantArray(const ConstantArray &) LLVM_DELETED_FUNCTION; +protected: + ConstantArray(ArrayType *T, ArrayRef<Constant *> Val); +public: + // ConstantArray accessors + static Constant *get(ArrayType *T, ArrayRef<Constant*> V); + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); + + /// getType - Specialize the getType() method to always return an ArrayType, + /// which reduces the amount of casting needed in parts of the compiler. + /// + inline ArrayType *getType() const { + return reinterpret_cast<ArrayType*>(Value::getType()); + } + + virtual void destroyConstant(); + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const Value *V) { + return V->getValueID() == ConstantArrayVal; + } +}; + +template <> +struct OperandTraits<ConstantArray> : + public VariadicOperandTraits<ConstantArray> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantArray, Constant) + +//===----------------------------------------------------------------------===// +// ConstantStruct - Constant Struct Declarations +// +class ConstantStruct : public Constant { + friend struct ConstantArrayCreator<ConstantStruct, StructType>; + ConstantStruct(const ConstantStruct &) LLVM_DELETED_FUNCTION; +protected: + ConstantStruct(StructType *T, ArrayRef<Constant *> Val); +public: + // ConstantStruct accessors + static Constant *get(StructType *T, ArrayRef<Constant*> V); + static Constant *get(StructType *T, ...) END_WITH_NULL; + + /// getAnon - Return an anonymous struct that has the specified + /// elements. If the struct is possibly empty, then you must specify a + /// context. + static Constant *getAnon(ArrayRef<Constant*> V, bool Packed = false) { + return get(getTypeForElements(V, Packed), V); + } + static Constant *getAnon(LLVMContext &Ctx, + ArrayRef<Constant*> V, bool Packed = false) { + return get(getTypeForElements(Ctx, V, Packed), V); + } + + /// getTypeForElements - Return an anonymous struct type to use for a constant + /// with the specified set of elements. The list must not be empty. + static StructType *getTypeForElements(ArrayRef<Constant*> V, + bool Packed = false); + /// getTypeForElements - This version of the method allows an empty list. + static StructType *getTypeForElements(LLVMContext &Ctx, + ArrayRef<Constant*> V, + bool Packed = false); + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); + + /// getType() specialization - Reduce amount of casting... + /// + inline StructType *getType() const { + return reinterpret_cast<StructType*>(Value::getType()); + } + + virtual void destroyConstant(); + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const Value *V) { + return V->getValueID() == ConstantStructVal; + } +}; + +template <> +struct OperandTraits<ConstantStruct> : + public VariadicOperandTraits<ConstantStruct> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantStruct, Constant) + + +//===----------------------------------------------------------------------===// +/// ConstantVector - Constant Vector Declarations +/// +class ConstantVector : public Constant { + friend struct ConstantArrayCreator<ConstantVector, VectorType>; + ConstantVector(const ConstantVector &) LLVM_DELETED_FUNCTION; +protected: + ConstantVector(VectorType *T, ArrayRef<Constant *> Val); +public: + // ConstantVector accessors + static Constant *get(ArrayRef<Constant*> V); + + /// getSplat - Return a ConstantVector with the specified constant in each + /// element. + static Constant *getSplat(unsigned NumElts, Constant *Elt); + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); + + /// getType - Specialize the getType() method to always return a VectorType, + /// which reduces the amount of casting needed in parts of the compiler. + /// + inline VectorType *getType() const { + return reinterpret_cast<VectorType*>(Value::getType()); + } + + /// getSplatValue - If this is a splat constant, meaning that all of the + /// elements have the same value, return that value. Otherwise return NULL. + Constant *getSplatValue() const; + + virtual void destroyConstant(); + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const Value *V) { + return V->getValueID() == ConstantVectorVal; + } +}; + +template <> +struct OperandTraits<ConstantVector> : + public VariadicOperandTraits<ConstantVector> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantVector, Constant) + +//===----------------------------------------------------------------------===// +/// ConstantPointerNull - a constant pointer value that points to null +/// +class ConstantPointerNull : public Constant { + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + ConstantPointerNull(const ConstantPointerNull &) LLVM_DELETED_FUNCTION; +protected: + explicit ConstantPointerNull(PointerType *T) + : Constant(reinterpret_cast<Type*>(T), + Value::ConstantPointerNullVal, 0, 0) {} + +protected: + // allocate space for exactly zero operands + void *operator new(size_t s) { + return User::operator new(s, 0); + } +public: + /// get() - Static factory methods - Return objects of the specified value + static ConstantPointerNull *get(PointerType *T); + + virtual void destroyConstant(); + + /// getType - Specialize the getType() method to always return an PointerType, + /// which reduces the amount of casting needed in parts of the compiler. + /// + inline PointerType *getType() const { + return reinterpret_cast<PointerType*>(Value::getType()); + } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const Value *V) { + return V->getValueID() == ConstantPointerNullVal; + } +}; + +//===----------------------------------------------------------------------===// +/// ConstantDataSequential - A vector or array constant whose element type is a +/// simple 1/2/4/8-byte integer or float/double, and whose elements are just +/// simple data values (i.e. ConstantInt/ConstantFP). This Constant node has no +/// operands because it stores all of the elements of the constant as densely +/// packed data, instead of as Value*'s. +/// +/// This is the common base class of ConstantDataArray and ConstantDataVector. +/// +class ConstantDataSequential : public Constant { + friend class LLVMContextImpl; + /// DataElements - A pointer to the bytes underlying this constant (which is + /// owned by the uniquing StringMap). + const char *DataElements; + + /// Next - This forms a link list of ConstantDataSequential nodes that have + /// the same value but different type. For example, 0,0,0,1 could be a 4 + /// element array of i8, or a 1-element array of i32. They'll both end up in + /// the same StringMap bucket, linked up. + ConstantDataSequential *Next; + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + ConstantDataSequential(const ConstantDataSequential &) LLVM_DELETED_FUNCTION; +protected: + explicit ConstantDataSequential(Type *ty, ValueTy VT, const char *Data) + : Constant(ty, VT, 0, 0), DataElements(Data), Next(0) {} + ~ConstantDataSequential() { delete Next; } + + static Constant *getImpl(StringRef Bytes, Type *Ty); + +protected: + // allocate space for exactly zero operands. + void *operator new(size_t s) { + return User::operator new(s, 0); + } +public: + + /// isElementTypeCompatible - Return true if a ConstantDataSequential can be + /// formed with a vector or array of the specified element type. + /// ConstantDataArray only works with normal float and int types that are + /// stored densely in memory, not with things like i42 or x86_f80. + static bool isElementTypeCompatible(const Type *Ty); + + /// getElementAsInteger - If this is a sequential container of integers (of + /// any size), return the specified element in the low bits of a uint64_t. + uint64_t getElementAsInteger(unsigned i) const; + + /// getElementAsAPFloat - If this is a sequential container of floating point + /// type, return the specified element as an APFloat. + APFloat getElementAsAPFloat(unsigned i) const; + + /// getElementAsFloat - If this is an sequential container of floats, return + /// the specified element as a float. + float getElementAsFloat(unsigned i) const; + + /// getElementAsDouble - If this is an sequential container of doubles, return + /// the specified element as a double. + double getElementAsDouble(unsigned i) const; + + /// getElementAsConstant - Return a Constant for a specified index's element. + /// Note that this has to compute a new constant to return, so it isn't as + /// efficient as getElementAsInteger/Float/Double. + Constant *getElementAsConstant(unsigned i) const; + + /// getType - Specialize the getType() method to always return a + /// SequentialType, which reduces the amount of casting needed in parts of the + /// compiler. + inline SequentialType *getType() const { + return reinterpret_cast<SequentialType*>(Value::getType()); + } + + /// getElementType - Return the element type of the array/vector. + Type *getElementType() const; + + /// getNumElements - Return the number of elements in the array or vector. + unsigned getNumElements() const; + + /// getElementByteSize - Return the size (in bytes) of each element in the + /// array/vector. The size of the elements is known to be a multiple of one + /// byte. + uint64_t getElementByteSize() const; + + + /// isString - This method returns true if this is an array of i8. + bool isString() const; + + /// isCString - This method returns true if the array "isString", ends with a + /// nul byte, and does not contains any other nul bytes. + bool isCString() const; + + /// getAsString - If this array is isString(), then this method returns the + /// array as a StringRef. Otherwise, it asserts out. + /// + StringRef getAsString() const { + assert(isString() && "Not a string"); + return getRawDataValues(); + } + + /// getAsCString - If this array is isCString(), then this method returns the + /// array (without the trailing null byte) as a StringRef. Otherwise, it + /// asserts out. + /// + StringRef getAsCString() const { + assert(isCString() && "Isn't a C string"); + StringRef Str = getAsString(); + return Str.substr(0, Str.size()-1); + } + + /// getRawDataValues - Return the raw, underlying, bytes of this data. Note + /// that this is an extremely tricky thing to work with, as it exposes the + /// host endianness of the data elements. + StringRef getRawDataValues() const; + + virtual void destroyConstant(); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + /// + static bool classof(const Value *V) { + return V->getValueID() == ConstantDataArrayVal || + V->getValueID() == ConstantDataVectorVal; + } +private: + const char *getElementPointer(unsigned Elt) const; +}; + +//===----------------------------------------------------------------------===// +/// ConstantDataArray - An array constant whose element type is a simple +/// 1/2/4/8-byte integer or float/double, and whose elements are just simple +/// data values (i.e. ConstantInt/ConstantFP). This Constant node has no +/// operands because it stores all of the elements of the constant as densely +/// packed data, instead of as Value*'s. +class ConstantDataArray : public ConstantDataSequential { + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + ConstantDataArray(const ConstantDataArray &) LLVM_DELETED_FUNCTION; + virtual void anchor(); + friend class ConstantDataSequential; + explicit ConstantDataArray(Type *ty, const char *Data) + : ConstantDataSequential(ty, ConstantDataArrayVal, Data) {} +protected: + // allocate space for exactly zero operands. + void *operator new(size_t s) { + return User::operator new(s, 0); + } +public: + + /// get() constructors - Return a constant with array type with an element + /// count and element type matching the ArrayRef passed in. Note that this + /// can return a ConstantAggregateZero object. + static Constant *get(LLVMContext &Context, ArrayRef<uint8_t> Elts); + static Constant *get(LLVMContext &Context, ArrayRef<uint16_t> Elts); + static Constant *get(LLVMContext &Context, ArrayRef<uint32_t> Elts); + static Constant *get(LLVMContext &Context, ArrayRef<uint64_t> Elts); + static Constant *get(LLVMContext &Context, ArrayRef<float> Elts); + static Constant *get(LLVMContext &Context, ArrayRef<double> Elts); + + /// getString - This method constructs a CDS and initializes it with a text + /// string. The default behavior (AddNull==true) causes a null terminator to + /// be placed at the end of the array (increasing the length of the string by + /// one more than the StringRef would normally indicate. Pass AddNull=false + /// to disable this behavior. + static Constant *getString(LLVMContext &Context, StringRef Initializer, + bool AddNull = true); + + /// getType - Specialize the getType() method to always return an ArrayType, + /// which reduces the amount of casting needed in parts of the compiler. + /// + inline ArrayType *getType() const { + return reinterpret_cast<ArrayType*>(Value::getType()); + } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + /// + static bool classof(const Value *V) { + return V->getValueID() == ConstantDataArrayVal; + } +}; + +//===----------------------------------------------------------------------===// +/// ConstantDataVector - A vector constant whose element type is a simple +/// 1/2/4/8-byte integer or float/double, and whose elements are just simple +/// data values (i.e. ConstantInt/ConstantFP). This Constant node has no +/// operands because it stores all of the elements of the constant as densely +/// packed data, instead of as Value*'s. +class ConstantDataVector : public ConstantDataSequential { + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + ConstantDataVector(const ConstantDataVector &) LLVM_DELETED_FUNCTION; + virtual void anchor(); + friend class ConstantDataSequential; + explicit ConstantDataVector(Type *ty, const char *Data) + : ConstantDataSequential(ty, ConstantDataVectorVal, Data) {} +protected: + // allocate space for exactly zero operands. + void *operator new(size_t s) { + return User::operator new(s, 0); + } +public: + + /// get() constructors - Return a constant with vector type with an element + /// count and element type matching the ArrayRef passed in. Note that this + /// can return a ConstantAggregateZero object. + static Constant *get(LLVMContext &Context, ArrayRef<uint8_t> Elts); + static Constant *get(LLVMContext &Context, ArrayRef<uint16_t> Elts); + static Constant *get(LLVMContext &Context, ArrayRef<uint32_t> Elts); + static Constant *get(LLVMContext &Context, ArrayRef<uint64_t> Elts); + static Constant *get(LLVMContext &Context, ArrayRef<float> Elts); + static Constant *get(LLVMContext &Context, ArrayRef<double> Elts); + + /// getSplat - Return a ConstantVector with the specified constant in each + /// element. The specified constant has to be a of a compatible type (i8/i16/ + /// i32/i64/float/double) and must be a ConstantFP or ConstantInt. + static Constant *getSplat(unsigned NumElts, Constant *Elt); + + /// getSplatValue - If this is a splat constant, meaning that all of the + /// elements have the same value, return that value. Otherwise return NULL. + Constant *getSplatValue() const; + + /// getType - Specialize the getType() method to always return a VectorType, + /// which reduces the amount of casting needed in parts of the compiler. + /// + inline VectorType *getType() const { + return reinterpret_cast<VectorType*>(Value::getType()); + } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + /// + static bool classof(const Value *V) { + return V->getValueID() == ConstantDataVectorVal; + } +}; + + + +/// BlockAddress - The address of a basic block. +/// +class BlockAddress : public Constant { + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t s) { return User::operator new(s, 2); } + BlockAddress(Function *F, BasicBlock *BB); +public: + /// get - Return a BlockAddress for the specified function and basic block. + static BlockAddress *get(Function *F, BasicBlock *BB); + + /// get - Return a BlockAddress for the specified basic block. The basic + /// block must be embedded into a function. + static BlockAddress *get(BasicBlock *BB); + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + Function *getFunction() const { return (Function*)Op<0>().get(); } + BasicBlock *getBasicBlock() const { return (BasicBlock*)Op<1>().get(); } + + virtual void destroyConstant(); + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Value *V) { + return V->getValueID() == BlockAddressVal; + } +}; + +template <> +struct OperandTraits<BlockAddress> : + public FixedNumOperandTraits<BlockAddress, 2> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BlockAddress, Value) + + +//===----------------------------------------------------------------------===// +/// ConstantExpr - a constant value that is initialized with an expression using +/// other constant values. +/// +/// This class uses the standard Instruction opcodes to define the various +/// constant expressions. The Opcode field for the ConstantExpr class is +/// maintained in the Value::SubclassData field. +class ConstantExpr : public Constant { + friend struct ConstantCreator<ConstantExpr,Type, + std::pair<unsigned, std::vector<Constant*> > >; + friend struct ConvertConstantType<ConstantExpr, Type>; + +protected: + ConstantExpr(Type *ty, unsigned Opcode, Use *Ops, unsigned NumOps) + : Constant(ty, ConstantExprVal, Ops, NumOps) { + // Operation type (an Instruction opcode) is stored as the SubclassData. + setValueSubclassData(Opcode); + } + +public: + // Static methods to construct a ConstantExpr of different kinds. Note that + // these methods may return a object that is not an instance of the + // ConstantExpr class, because they will attempt to fold the constant + // expression into something simpler if possible. + + /// getAlignOf constant expr - computes the alignment of a type in a target + /// independent way (Note: the return type is an i64). + static Constant *getAlignOf(Type *Ty); + + /// getSizeOf constant expr - computes the (alloc) size of a type (in + /// address-units, not bits) in a target independent way (Note: the return + /// type is an i64). + /// + static Constant *getSizeOf(Type *Ty); + + /// getOffsetOf constant expr - computes the offset of a struct field in a + /// target independent way (Note: the return type is an i64). + /// + static Constant *getOffsetOf(StructType *STy, unsigned FieldNo); + + /// getOffsetOf constant expr - This is a generalized form of getOffsetOf, + /// which supports any aggregate type, and any Constant index. + /// + static Constant *getOffsetOf(Type *Ty, Constant *FieldNo); + + static Constant *getNeg(Constant *C, bool HasNUW = false, bool HasNSW =false); + static Constant *getFNeg(Constant *C); + static Constant *getNot(Constant *C); + static Constant *getAdd(Constant *C1, Constant *C2, + bool HasNUW = false, bool HasNSW = false); + static Constant *getFAdd(Constant *C1, Constant *C2); + static Constant *getSub(Constant *C1, Constant *C2, + bool HasNUW = false, bool HasNSW = false); + static Constant *getFSub(Constant *C1, Constant *C2); + static Constant *getMul(Constant *C1, Constant *C2, + bool HasNUW = false, bool HasNSW = false); + static Constant *getFMul(Constant *C1, Constant *C2); + static Constant *getUDiv(Constant *C1, Constant *C2, bool isExact = false); + static Constant *getSDiv(Constant *C1, Constant *C2, bool isExact = false); + static Constant *getFDiv(Constant *C1, Constant *C2); + static Constant *getURem(Constant *C1, Constant *C2); + static Constant *getSRem(Constant *C1, Constant *C2); + static Constant *getFRem(Constant *C1, Constant *C2); + static Constant *getAnd(Constant *C1, Constant *C2); + static Constant *getOr(Constant *C1, Constant *C2); + static Constant *getXor(Constant *C1, Constant *C2); + static Constant *getShl(Constant *C1, Constant *C2, + bool HasNUW = false, bool HasNSW = false); + static Constant *getLShr(Constant *C1, Constant *C2, bool isExact = false); + static Constant *getAShr(Constant *C1, Constant *C2, bool isExact = false); + static Constant *getTrunc (Constant *C, Type *Ty); + static Constant *getSExt (Constant *C, Type *Ty); + static Constant *getZExt (Constant *C, Type *Ty); + static Constant *getFPTrunc (Constant *C, Type *Ty); + static Constant *getFPExtend(Constant *C, Type *Ty); + static Constant *getUIToFP (Constant *C, Type *Ty); + static Constant *getSIToFP (Constant *C, Type *Ty); + static Constant *getFPToUI (Constant *C, Type *Ty); + static Constant *getFPToSI (Constant *C, Type *Ty); + static Constant *getPtrToInt(Constant *C, Type *Ty); + static Constant *getIntToPtr(Constant *C, Type *Ty); + static Constant *getBitCast (Constant *C, Type *Ty); + + static Constant *getNSWNeg(Constant *C) { return getNeg(C, false, true); } + static Constant *getNUWNeg(Constant *C) { return getNeg(C, true, false); } + static Constant *getNSWAdd(Constant *C1, Constant *C2) { + return getAdd(C1, C2, false, true); + } + static Constant *getNUWAdd(Constant *C1, Constant *C2) { + return getAdd(C1, C2, true, false); + } + static Constant *getNSWSub(Constant *C1, Constant *C2) { + return getSub(C1, C2, false, true); + } + static Constant *getNUWSub(Constant *C1, Constant *C2) { + return getSub(C1, C2, true, false); + } + static Constant *getNSWMul(Constant *C1, Constant *C2) { + return getMul(C1, C2, false, true); + } + static Constant *getNUWMul(Constant *C1, Constant *C2) { + return getMul(C1, C2, true, false); + } + static Constant *getNSWShl(Constant *C1, Constant *C2) { + return getShl(C1, C2, false, true); + } + static Constant *getNUWShl(Constant *C1, Constant *C2) { + return getShl(C1, C2, true, false); + } + static Constant *getExactSDiv(Constant *C1, Constant *C2) { + return getSDiv(C1, C2, true); + } + static Constant *getExactUDiv(Constant *C1, Constant *C2) { + return getUDiv(C1, C2, true); + } + static Constant *getExactAShr(Constant *C1, Constant *C2) { + return getAShr(C1, C2, true); + } + static Constant *getExactLShr(Constant *C1, Constant *C2) { + return getLShr(C1, C2, true); + } + + /// getBinOpIdentity - Return the identity for the given binary operation, + /// i.e. a constant C such that X op C = X and C op X = X for every X. It + /// returns null if the operator doesn't have an identity. + static Constant *getBinOpIdentity(unsigned Opcode, Type *Ty); + + /// getBinOpAbsorber - Return the absorbing element for the given binary + /// operation, i.e. a constant C such that X op C = C and C op X = C for + /// every X. For example, this returns zero for integer multiplication. + /// It returns null if the operator doesn't have an absorbing element. + static Constant *getBinOpAbsorber(unsigned Opcode, Type *Ty); + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); + + // @brief Convenience function for getting one of the casting operations + // using a CastOps opcode. + static Constant *getCast( + unsigned ops, ///< The opcode for the conversion + Constant *C, ///< The constant to be converted + Type *Ty ///< The type to which the constant is converted + ); + + // @brief Create a ZExt or BitCast cast constant expression + static Constant *getZExtOrBitCast( + Constant *C, ///< The constant to zext or bitcast + Type *Ty ///< The type to zext or bitcast C to + ); + + // @brief Create a SExt or BitCast cast constant expression + static Constant *getSExtOrBitCast( + Constant *C, ///< The constant to sext or bitcast + Type *Ty ///< The type to sext or bitcast C to + ); + + // @brief Create a Trunc or BitCast cast constant expression + static Constant *getTruncOrBitCast( + Constant *C, ///< The constant to trunc or bitcast + Type *Ty ///< The type to trunc or bitcast C to + ); + + /// @brief Create a BitCast or a PtrToInt cast constant expression + static Constant *getPointerCast( + Constant *C, ///< The pointer value to be casted (operand 0) + Type *Ty ///< The type to which cast should be made + ); + + /// @brief Create a ZExt, Bitcast or Trunc for integer -> integer casts + static Constant *getIntegerCast( + Constant *C, ///< The integer constant to be casted + Type *Ty, ///< The integer type to cast to + bool isSigned ///< Whether C should be treated as signed or not + ); + + /// @brief Create a FPExt, Bitcast or FPTrunc for fp -> fp casts + static Constant *getFPCast( + Constant *C, ///< The integer constant to be casted + Type *Ty ///< The integer type to cast to + ); + + /// @brief Return true if this is a convert constant expression + bool isCast() const; + + /// @brief Return true if this is a compare constant expression + bool isCompare() const; + + /// @brief Return true if this is an insertvalue or extractvalue expression, + /// and the getIndices() method may be used. + bool hasIndices() const; + + /// @brief Return true if this is a getelementptr expression and all + /// the index operands are compile-time known integers within the + /// corresponding notional static array extents. Note that this is + /// not equivalant to, a subset of, or a superset of the "inbounds" + /// property. + bool isGEPWithNoNotionalOverIndexing() const; + + /// Select constant expr + /// + static Constant *getSelect(Constant *C, Constant *V1, Constant *V2); + + /// get - Return a binary or shift operator constant expression, + /// folding if possible. + /// + static Constant *get(unsigned Opcode, Constant *C1, Constant *C2, + unsigned Flags = 0); + + /// @brief Return an ICmp or FCmp comparison operator constant expression. + static Constant *getCompare(unsigned short pred, Constant *C1, Constant *C2); + + /// get* - Return some common constants without having to + /// specify the full Instruction::OPCODE identifier. + /// + static Constant *getICmp(unsigned short pred, Constant *LHS, Constant *RHS); + static Constant *getFCmp(unsigned short pred, Constant *LHS, Constant *RHS); + + /// Getelementptr form. Value* is only accepted for convenience; + /// all elements must be Constant's. + /// + static Constant *getGetElementPtr(Constant *C, + ArrayRef<Constant *> IdxList, + bool InBounds = false) { + return getGetElementPtr(C, makeArrayRef((Value * const *)IdxList.data(), + IdxList.size()), + InBounds); + } + static Constant *getGetElementPtr(Constant *C, + Constant *Idx, + bool InBounds = false) { + // This form of the function only exists to avoid ambiguous overload + // warnings about whether to convert Idx to ArrayRef<Constant *> or + // ArrayRef<Value *>. + return getGetElementPtr(C, cast<Value>(Idx), InBounds); + } + static Constant *getGetElementPtr(Constant *C, + ArrayRef<Value *> IdxList, + bool InBounds = false); + + /// Create an "inbounds" getelementptr. See the documentation for the + /// "inbounds" flag in LangRef.html for details. + static Constant *getInBoundsGetElementPtr(Constant *C, + ArrayRef<Constant *> IdxList) { + return getGetElementPtr(C, IdxList, true); + } + static Constant *getInBoundsGetElementPtr(Constant *C, + Constant *Idx) { + // This form of the function only exists to avoid ambiguous overload + // warnings about whether to convert Idx to ArrayRef<Constant *> or + // ArrayRef<Value *>. + return getGetElementPtr(C, Idx, true); + } + static Constant *getInBoundsGetElementPtr(Constant *C, + ArrayRef<Value *> IdxList) { + return getGetElementPtr(C, IdxList, true); + } + + static Constant *getExtractElement(Constant *Vec, Constant *Idx); + static Constant *getInsertElement(Constant *Vec, Constant *Elt,Constant *Idx); + static Constant *getShuffleVector(Constant *V1, Constant *V2, Constant *Mask); + static Constant *getExtractValue(Constant *Agg, ArrayRef<unsigned> Idxs); + static Constant *getInsertValue(Constant *Agg, Constant *Val, + ArrayRef<unsigned> Idxs); + + /// getOpcode - Return the opcode at the root of this constant expression + unsigned getOpcode() const { return getSubclassDataFromValue(); } + + /// getPredicate - Return the ICMP or FCMP predicate value. Assert if this is + /// not an ICMP or FCMP constant expression. + unsigned getPredicate() const; + + /// getIndices - Assert that this is an insertvalue or exactvalue + /// expression and return the list of indices. + ArrayRef<unsigned> getIndices() const; + + /// getOpcodeName - Return a string representation for an opcode. + const char *getOpcodeName() const; + + /// getWithOperandReplaced - Return a constant expression identical to this + /// one, but with the specified operand set to the specified value. + Constant *getWithOperandReplaced(unsigned OpNo, Constant *Op) const; + + /// getWithOperands - This returns the current constant expression with the + /// operands replaced with the specified values. The specified array must + /// have the same number of operands as our current one. + Constant *getWithOperands(ArrayRef<Constant*> Ops) const { + return getWithOperands(Ops, getType()); + } + + /// getWithOperands - This returns the current constant expression with the + /// operands replaced with the specified values and with the specified result + /// type. The specified array must have the same number of operands as our + /// current one. + Constant *getWithOperands(ArrayRef<Constant*> Ops, Type *Ty) const; + + /// getAsInstruction - Returns an Instruction which implements the same operation + /// as this ConstantExpr. The instruction is not linked to any basic block. + /// + /// A better approach to this could be to have a constructor for Instruction + /// which would take a ConstantExpr parameter, but that would have spread + /// implementation details of ConstantExpr outside of Constants.cpp, which + /// would make it harder to remove ConstantExprs altogether. + Instruction *getAsInstruction(); + + virtual void destroyConstant(); + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Value *V) { + return V->getValueID() == ConstantExprVal; + } + +private: + // Shadow Value::setValueSubclassData with a private forwarding method so that + // subclasses cannot accidentally use it. + void setValueSubclassData(unsigned short D) { + Value::setValueSubclassData(D); + } +}; + +template <> +struct OperandTraits<ConstantExpr> : + public VariadicOperandTraits<ConstantExpr, 1> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantExpr, Constant) + +//===----------------------------------------------------------------------===// +/// UndefValue - 'undef' values are things that do not have specified contents. +/// These are used for a variety of purposes, including global variable +/// initializers and operands to instructions. 'undef' values can occur with +/// any first-class type. +/// +/// Undef values aren't exactly constants; if they have multiple uses, they +/// can appear to have different bit patterns at each use. See +/// LangRef.html#undefvalues for details. +/// +class UndefValue : public Constant { + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + UndefValue(const UndefValue &) LLVM_DELETED_FUNCTION; +protected: + explicit UndefValue(Type *T) : Constant(T, UndefValueVal, 0, 0) {} +protected: + // allocate space for exactly zero operands + void *operator new(size_t s) { + return User::operator new(s, 0); + } +public: + /// get() - Static factory methods - Return an 'undef' object of the specified + /// type. + /// + static UndefValue *get(Type *T); + + /// getSequentialElement - If this Undef has array or vector type, return a + /// undef with the right element type. + UndefValue *getSequentialElement() const; + + /// getStructElement - If this undef has struct type, return a undef with the + /// right element type for the specified element. + UndefValue *getStructElement(unsigned Elt) const; + + /// getElementValue - Return an undef of the right value for the specified GEP + /// index. + UndefValue *getElementValue(Constant *C) const; + + /// getElementValue - Return an undef of the right value for the specified GEP + /// index. + UndefValue *getElementValue(unsigned Idx) const; + + virtual void destroyConstant(); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const Value *V) { + return V->getValueID() == UndefValueVal; + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/IR/DataLayout.h b/include/llvm/IR/DataLayout.h new file mode 100644 index 0000000..547d857 --- /dev/null +++ b/include/llvm/IR/DataLayout.h @@ -0,0 +1,477 @@ +//===--------- llvm/DataLayout.h - Data size & alignment info ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines layout properties related to datatype size/offset/alignment +// information. It uses lazy annotations to cache information about how +// structure types are laid out and used. +// +// This structure should be created once, filled in if the defaults are not +// correct and then passed around by const&. None of the members functions +// require modification to the object. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_DATALAYOUT_H +#define LLVM_IR_DATALAYOUT_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Type.h" +#include "llvm/Pass.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class Value; +class Type; +class IntegerType; +class StructType; +class StructLayout; +class GlobalVariable; +class LLVMContext; +template<typename T> +class ArrayRef; + +/// Enum used to categorize the alignment types stored by LayoutAlignElem +enum AlignTypeEnum { + INVALID_ALIGN = 0, ///< An invalid alignment + INTEGER_ALIGN = 'i', ///< Integer type alignment + VECTOR_ALIGN = 'v', ///< Vector type alignment + FLOAT_ALIGN = 'f', ///< Floating point type alignment + AGGREGATE_ALIGN = 'a', ///< Aggregate alignment + STACK_ALIGN = 's' ///< Stack objects alignment +}; + +/// Layout alignment element. +/// +/// Stores the alignment data associated with a given alignment type (integer, +/// vector, float) and type bit width. +/// +/// @note The unusual order of elements in the structure attempts to reduce +/// padding and make the structure slightly more cache friendly. +struct LayoutAlignElem { + unsigned AlignType : 8; ///< Alignment type (AlignTypeEnum) + unsigned TypeBitWidth : 24; ///< Type bit width + unsigned ABIAlign : 16; ///< ABI alignment for this type/bitw + unsigned PrefAlign : 16; ///< Pref. alignment for this type/bitw + + /// Initializer + static LayoutAlignElem get(AlignTypeEnum align_type, unsigned abi_align, + unsigned pref_align, uint32_t bit_width); + /// Equality predicate + bool operator==(const LayoutAlignElem &rhs) const; +}; + +/// Layout pointer alignment element. +/// +/// Stores the alignment data associated with a given pointer and address space. +/// +/// @note The unusual order of elements in the structure attempts to reduce +/// padding and make the structure slightly more cache friendly. +struct PointerAlignElem { + unsigned ABIAlign; ///< ABI alignment for this type/bitw + unsigned PrefAlign; ///< Pref. alignment for this type/bitw + uint32_t TypeBitWidth; ///< Type bit width + uint32_t AddressSpace; ///< Address space for the pointer type + + /// Initializer + static PointerAlignElem get(uint32_t addr_space, unsigned abi_align, + unsigned pref_align, uint32_t bit_width); + /// Equality predicate + bool operator==(const PointerAlignElem &rhs) const; +}; + + +/// DataLayout - This class holds a parsed version of the target data layout +/// string in a module and provides methods for querying it. The target data +/// layout string is specified *by the target* - a frontend generating LLVM IR +/// is required to generate the right target data for the target being codegen'd +/// to. If some measure of portability is desired, an empty string may be +/// specified in the module. +class DataLayout : public ImmutablePass { +private: + bool LittleEndian; ///< Defaults to false + unsigned StackNaturalAlign; ///< Stack natural alignment + + SmallVector<unsigned char, 8> LegalIntWidths; ///< Legal Integers. + + /// Alignments - Where the primitive type alignment data is stored. + /// + /// @sa init(). + /// @note Could support multiple size pointer alignments, e.g., 32-bit + /// pointers vs. 64-bit pointers by extending LayoutAlignment, but for now, + /// we don't. + SmallVector<LayoutAlignElem, 16> Alignments; + DenseMap<unsigned, PointerAlignElem> Pointers; + + /// InvalidAlignmentElem - This member is a signal that a requested alignment + /// type and bit width were not found in the SmallVector. + static const LayoutAlignElem InvalidAlignmentElem; + + /// InvalidPointerElem - This member is a signal that a requested pointer + /// type and bit width were not found in the DenseSet. + static const PointerAlignElem InvalidPointerElem; + + // The StructType -> StructLayout map. + mutable void *LayoutMap; + + //! Set/initialize target alignments + void setAlignment(AlignTypeEnum align_type, unsigned abi_align, + unsigned pref_align, uint32_t bit_width); + unsigned getAlignmentInfo(AlignTypeEnum align_type, uint32_t bit_width, + bool ABIAlign, Type *Ty) const; + + //! Set/initialize pointer alignments + void setPointerAlignment(uint32_t addr_space, unsigned abi_align, + unsigned pref_align, uint32_t bit_width); + + //! Internal helper method that returns requested alignment for type. + unsigned getAlignment(Type *Ty, bool abi_or_pref) const; + + /// Valid alignment predicate. + /// + /// Predicate that tests a LayoutAlignElem reference returned by get() against + /// InvalidAlignmentElem. + bool validAlignment(const LayoutAlignElem &align) const { + return &align != &InvalidAlignmentElem; + } + + /// Valid pointer predicate. + /// + /// Predicate that tests a PointerAlignElem reference returned by get() against + /// InvalidPointerElem. + bool validPointer(const PointerAlignElem &align) const { + return &align != &InvalidPointerElem; + } + + /// Parses a target data specification string. Assert if the string is + /// malformed. + void parseSpecifier(StringRef LayoutDescription); + +public: + /// Default ctor. + /// + /// @note This has to exist, because this is a pass, but it should never be + /// used. + DataLayout(); + + /// Constructs a DataLayout from a specification string. See init(). + explicit DataLayout(StringRef LayoutDescription) + : ImmutablePass(ID) { + init(LayoutDescription); + } + + /// Initialize target data from properties stored in the module. + explicit DataLayout(const Module *M); + + DataLayout(const DataLayout &TD) : + ImmutablePass(ID), + LittleEndian(TD.isLittleEndian()), + StackNaturalAlign(TD.StackNaturalAlign), + LegalIntWidths(TD.LegalIntWidths), + Alignments(TD.Alignments), + Pointers(TD.Pointers), + LayoutMap(0) + { } + + ~DataLayout(); // Not virtual, do not subclass this class + + /// DataLayout is an immutable pass, but holds state. This allows the pass + /// manager to clear its mutable state. + bool doFinalization(Module &M); + + /// Parse a data layout string (with fallback to default values). Ensure that + /// the data layout pass is registered. + void init(StringRef LayoutDescription); + + /// Layout endianness... + bool isLittleEndian() const { return LittleEndian; } + bool isBigEndian() const { return !LittleEndian; } + + /// getStringRepresentation - Return the string representation of the + /// DataLayout. This representation is in the same format accepted by the + /// string constructor above. + std::string getStringRepresentation() const; + + /// isLegalInteger - This function returns true if the specified type is + /// known to be a native integer type supported by the CPU. For example, + /// i64 is not native on most 32-bit CPUs and i37 is not native on any known + /// one. This returns false if the integer width is not legal. + /// + /// The width is specified in bits. + /// + bool isLegalInteger(unsigned Width) const { + for (unsigned i = 0, e = (unsigned)LegalIntWidths.size(); i != e; ++i) + if (LegalIntWidths[i] == Width) + return true; + return false; + } + + bool isIllegalInteger(unsigned Width) const { + return !isLegalInteger(Width); + } + + /// Returns true if the given alignment exceeds the natural stack alignment. + bool exceedsNaturalStackAlignment(unsigned Align) const { + return (StackNaturalAlign != 0) && (Align > StackNaturalAlign); + } + + /// fitsInLegalInteger - This function returns true if the specified type fits + /// in a native integer type supported by the CPU. For example, if the CPU + /// only supports i32 as a native integer type, then i27 fits in a legal + // integer type but i45 does not. + bool fitsInLegalInteger(unsigned Width) const { + for (unsigned i = 0, e = (unsigned)LegalIntWidths.size(); i != e; ++i) + if (Width <= LegalIntWidths[i]) + return true; + return false; + } + + /// Layout pointer alignment + /// FIXME: The defaults need to be removed once all of + /// the backends/clients are updated. + unsigned getPointerABIAlignment(unsigned AS = 0) const { + DenseMap<unsigned, PointerAlignElem>::const_iterator val = Pointers.find(AS); + if (val == Pointers.end()) { + val = Pointers.find(0); + } + return val->second.ABIAlign; + } + /// Return target's alignment for stack-based pointers + /// FIXME: The defaults need to be removed once all of + /// the backends/clients are updated. + unsigned getPointerPrefAlignment(unsigned AS = 0) const { + DenseMap<unsigned, PointerAlignElem>::const_iterator val = Pointers.find(AS); + if (val == Pointers.end()) { + val = Pointers.find(0); + } + return val->second.PrefAlign; + } + /// Layout pointer size + /// FIXME: The defaults need to be removed once all of + /// the backends/clients are updated. + unsigned getPointerSize(unsigned AS = 0) const { + DenseMap<unsigned, PointerAlignElem>::const_iterator val = Pointers.find(AS); + if (val == Pointers.end()) { + val = Pointers.find(0); + } + return val->second.TypeBitWidth; + } + /// Layout pointer size, in bits + /// FIXME: The defaults need to be removed once all of + /// the backends/clients are updated. + unsigned getPointerSizeInBits(unsigned AS = 0) const { + return getPointerSize(AS) * 8; + } + /// Size examples: + /// + /// Type SizeInBits StoreSizeInBits AllocSizeInBits[*] + /// ---- ---------- --------------- --------------- + /// i1 1 8 8 + /// i8 8 8 8 + /// i19 19 24 32 + /// i32 32 32 32 + /// i100 100 104 128 + /// i128 128 128 128 + /// Float 32 32 32 + /// Double 64 64 64 + /// X86_FP80 80 80 96 + /// + /// [*] The alloc size depends on the alignment, and thus on the target. + /// These values are for x86-32 linux. + + /// getTypeSizeInBits - Return the number of bits necessary to hold the + /// specified type. For example, returns 36 for i36 and 80 for x86_fp80. + /// The type passed must have a size (Type::isSized() must return true). + uint64_t getTypeSizeInBits(Type *Ty) const; + + /// getTypeStoreSize - Return the maximum number of bytes that may be + /// overwritten by storing the specified type. For example, returns 5 + /// for i36 and 10 for x86_fp80. + uint64_t getTypeStoreSize(Type *Ty) const { + return (getTypeSizeInBits(Ty)+7)/8; + } + + /// getTypeStoreSizeInBits - Return the maximum number of bits that may be + /// overwritten by storing the specified type; always a multiple of 8. For + /// example, returns 40 for i36 and 80 for x86_fp80. + uint64_t getTypeStoreSizeInBits(Type *Ty) const { + return 8*getTypeStoreSize(Ty); + } + + /// getTypeAllocSize - Return the offset in bytes between successive objects + /// of the specified type, including alignment padding. This is the amount + /// that alloca reserves for this type. For example, returns 12 or 16 for + /// x86_fp80, depending on alignment. + uint64_t getTypeAllocSize(Type *Ty) const { + // Round up to the next alignment boundary. + return RoundUpAlignment(getTypeStoreSize(Ty), getABITypeAlignment(Ty)); + } + + /// getTypeAllocSizeInBits - Return the offset in bits between successive + /// objects of the specified type, including alignment padding; always a + /// multiple of 8. This is the amount that alloca reserves for this type. + /// For example, returns 96 or 128 for x86_fp80, depending on alignment. + uint64_t getTypeAllocSizeInBits(Type *Ty) const { + return 8*getTypeAllocSize(Ty); + } + + /// getABITypeAlignment - Return the minimum ABI-required alignment for the + /// specified type. + unsigned getABITypeAlignment(Type *Ty) const; + + /// getABIIntegerTypeAlignment - Return the minimum ABI-required alignment for + /// an integer type of the specified bitwidth. + unsigned getABIIntegerTypeAlignment(unsigned BitWidth) const; + + /// getCallFrameTypeAlignment - Return the minimum ABI-required alignment + /// for the specified type when it is part of a call frame. + unsigned getCallFrameTypeAlignment(Type *Ty) const; + + /// getPrefTypeAlignment - Return the preferred stack/global alignment for + /// the specified type. This is always at least as good as the ABI alignment. + unsigned getPrefTypeAlignment(Type *Ty) const; + + /// getPreferredTypeAlignmentShift - Return the preferred alignment for the + /// specified type, returned as log2 of the value (a shift amount). + unsigned getPreferredTypeAlignmentShift(Type *Ty) const; + + /// getIntPtrType - Return an integer type with size at least as big as that + /// of a pointer in the given address space. + IntegerType *getIntPtrType(LLVMContext &C, unsigned AddressSpace = 0) const; + + /// getIntPtrType - Return an integer (vector of integer) type with size at + /// least as big as that of a pointer of the given pointer (vector of pointer) + /// type. + Type *getIntPtrType(Type *) const; + + /// getSmallestLegalIntType - Return the smallest integer type with size at + /// least as big as Width bits. + Type *getSmallestLegalIntType(LLVMContext &C, unsigned Width = 0) const; + + /// getIndexedOffset - return the offset from the beginning of the type for + /// the specified indices. This is used to implement getelementptr. + uint64_t getIndexedOffset(Type *Ty, ArrayRef<Value *> Indices) const; + + /// getStructLayout - Return a StructLayout object, indicating the alignment + /// of the struct, its size, and the offsets of its fields. Note that this + /// information is lazily cached. + const StructLayout *getStructLayout(StructType *Ty) const; + + /// getPreferredAlignment - Return the preferred alignment of the specified + /// global. This includes an explicitly requested alignment (if the global + /// has one). + unsigned getPreferredAlignment(const GlobalVariable *GV) const; + + /// getPreferredAlignmentLog - Return the preferred alignment of the + /// specified global, returned in log form. This includes an explicitly + /// requested alignment (if the global has one). + unsigned getPreferredAlignmentLog(const GlobalVariable *GV) const; + + /// RoundUpAlignment - Round the specified value up to the next alignment + /// boundary specified by Alignment. For example, 7 rounded up to an + /// alignment boundary of 4 is 8. 8 rounded up to the alignment boundary of 4 + /// is 8 because it is already aligned. + template <typename UIntTy> + static UIntTy RoundUpAlignment(UIntTy Val, unsigned Alignment) { + assert((Alignment & (Alignment-1)) == 0 && "Alignment must be power of 2!"); + return (Val + (Alignment-1)) & ~UIntTy(Alignment-1); + } + + static char ID; // Pass identification, replacement for typeid +}; + +/// StructLayout - used to lazily calculate structure layout information for a +/// target machine, based on the DataLayout structure. +/// +class StructLayout { + uint64_t StructSize; + unsigned StructAlignment; + unsigned NumElements; + uint64_t MemberOffsets[1]; // variable sized array! +public: + + uint64_t getSizeInBytes() const { + return StructSize; + } + + uint64_t getSizeInBits() const { + return 8*StructSize; + } + + unsigned getAlignment() const { + return StructAlignment; + } + + /// getElementContainingOffset - Given a valid byte offset into the structure, + /// return the structure index that contains it. + /// + unsigned getElementContainingOffset(uint64_t Offset) const; + + uint64_t getElementOffset(unsigned Idx) const { + assert(Idx < NumElements && "Invalid element idx!"); + return MemberOffsets[Idx]; + } + + uint64_t getElementOffsetInBits(unsigned Idx) const { + return getElementOffset(Idx)*8; + } + +private: + friend class DataLayout; // Only DataLayout can create this class + StructLayout(StructType *ST, const DataLayout &TD); +}; + + +// The implementation of this method is provided inline as it is particularly +// well suited to constant folding when called on a specific Type subclass. +inline uint64_t DataLayout::getTypeSizeInBits(Type *Ty) const { + assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!"); + switch (Ty->getTypeID()) { + case Type::LabelTyID: + return getPointerSizeInBits(0); + case Type::PointerTyID: + return getPointerSizeInBits(cast<PointerType>(Ty)->getAddressSpace()); + case Type::ArrayTyID: { + ArrayType *ATy = cast<ArrayType>(Ty); + return ATy->getNumElements() * + getTypeAllocSizeInBits(ATy->getElementType()); + } + case Type::StructTyID: + // Get the layout annotation... which is lazily created on demand. + return getStructLayout(cast<StructType>(Ty))->getSizeInBits(); + case Type::IntegerTyID: + return cast<IntegerType>(Ty)->getBitWidth(); + case Type::HalfTyID: + return 16; + case Type::FloatTyID: + return 32; + case Type::DoubleTyID: + case Type::X86_MMXTyID: + return 64; + case Type::PPC_FP128TyID: + case Type::FP128TyID: + return 128; + // In memory objects this is always aligned to a higher boundary, but + // only 80 bits contain information. + case Type::X86_FP80TyID: + return 80; + case Type::VectorTyID: { + VectorType *VTy = cast<VectorType>(Ty); + return VTy->getNumElements() * getTypeSizeInBits(VTy->getElementType()); + } + default: + llvm_unreachable("DataLayout::getTypeSizeInBits(): Unsupported type"); + } +} + +} // End llvm namespace + +#endif diff --git a/include/llvm/IR/DerivedTypes.h b/include/llvm/IR/DerivedTypes.h new file mode 100644 index 0000000..6c00f596 --- /dev/null +++ b/include/llvm/IR/DerivedTypes.h @@ -0,0 +1,455 @@ +//===-- llvm/DerivedTypes.h - Classes for handling data types ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declarations of classes that represent "derived +// types". These are things like "arrays of x" or "structure of x, y, z" or +// "function returning x taking (y,z) as parameters", etc... +// +// The implementations of these classes live in the Type.cpp file. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_DERIVEDTYPES_H +#define LLVM_IR_DERIVEDTYPES_H + +#include "llvm/IR/Type.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class Value; +class APInt; +class LLVMContext; +template<typename T> class ArrayRef; +class StringRef; + +/// Class to represent integer types. Note that this class is also used to +/// represent the built-in integer types: Int1Ty, Int8Ty, Int16Ty, Int32Ty and +/// Int64Ty. +/// @brief Integer representation type +class IntegerType : public Type { + friend class LLVMContextImpl; + +protected: + explicit IntegerType(LLVMContext &C, unsigned NumBits) : Type(C, IntegerTyID){ + setSubclassData(NumBits); + } +public: + /// This enum is just used to hold constants we need for IntegerType. + enum { + MIN_INT_BITS = 1, ///< Minimum number of bits that can be specified + MAX_INT_BITS = (1<<23)-1 ///< Maximum number of bits that can be specified + ///< Note that bit width is stored in the Type classes SubclassData field + ///< which has 23 bits. This yields a maximum bit width of 8,388,607 bits. + }; + + /// This static method is the primary way of constructing an IntegerType. + /// If an IntegerType with the same NumBits value was previously instantiated, + /// that instance will be returned. Otherwise a new one will be created. Only + /// one instance with a given NumBits value is ever created. + /// @brief Get or create an IntegerType instance. + static IntegerType *get(LLVMContext &C, unsigned NumBits); + + /// @brief Get the number of bits in this IntegerType + unsigned getBitWidth() const { return getSubclassData(); } + + /// getBitMask - Return a bitmask with ones set for all of the bits + /// that can be set by an unsigned version of this type. This is 0xFF for + /// i8, 0xFFFF for i16, etc. + uint64_t getBitMask() const { + return ~uint64_t(0UL) >> (64-getBitWidth()); + } + + /// getSignBit - Return a uint64_t with just the most significant bit set (the + /// sign bit, if the value is treated as a signed number). + uint64_t getSignBit() const { + return 1ULL << (getBitWidth()-1); + } + + /// For example, this is 0xFF for an 8 bit integer, 0xFFFF for i16, etc. + /// @returns a bit mask with ones set for all the bits of this type. + /// @brief Get a bit mask for this type. + APInt getMask() const; + + /// This method determines if the width of this IntegerType is a power-of-2 + /// in terms of 8 bit bytes. + /// @returns true if this is a power-of-2 byte width. + /// @brief Is this a power-of-2 byte-width IntegerType ? + bool isPowerOf2ByteWidth() const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast. + static inline bool classof(const Type *T) { + return T->getTypeID() == IntegerTyID; + } +}; + + +/// FunctionType - Class to represent function types +/// +class FunctionType : public Type { + FunctionType(const FunctionType &) LLVM_DELETED_FUNCTION; + const FunctionType &operator=(const FunctionType &) LLVM_DELETED_FUNCTION; + FunctionType(Type *Result, ArrayRef<Type*> Params, bool IsVarArgs); + +public: + /// FunctionType::get - This static method is the primary way of constructing + /// a FunctionType. + /// + static FunctionType *get(Type *Result, + ArrayRef<Type*> Params, bool isVarArg); + + /// FunctionType::get - Create a FunctionType taking no parameters. + /// + static FunctionType *get(Type *Result, bool isVarArg); + + /// isValidReturnType - Return true if the specified type is valid as a return + /// type. + static bool isValidReturnType(Type *RetTy); + + /// isValidArgumentType - Return true if the specified type is valid as an + /// argument type. + static bool isValidArgumentType(Type *ArgTy); + + bool isVarArg() const { return getSubclassData(); } + Type *getReturnType() const { return ContainedTys[0]; } + + typedef Type::subtype_iterator param_iterator; + param_iterator param_begin() const { return ContainedTys + 1; } + param_iterator param_end() const { return &ContainedTys[NumContainedTys]; } + + /// Parameter type accessors. + Type *getParamType(unsigned i) const { return ContainedTys[i+1]; } + + /// getNumParams - Return the number of fixed parameters this function type + /// requires. This does not consider varargs. + /// + unsigned getNumParams() const { return NumContainedTys - 1; } + + /// Methods for support type inquiry through isa, cast, and dyn_cast. + static inline bool classof(const Type *T) { + return T->getTypeID() == FunctionTyID; + } +}; + + +/// CompositeType - Common super class of ArrayType, StructType, PointerType +/// and VectorType. +class CompositeType : public Type { +protected: + explicit CompositeType(LLVMContext &C, TypeID tid) : Type(C, tid) { } +public: + + /// getTypeAtIndex - Given an index value into the type, return the type of + /// the element. + /// + Type *getTypeAtIndex(const Value *V); + Type *getTypeAtIndex(unsigned Idx); + bool indexValid(const Value *V) const; + bool indexValid(unsigned Idx) const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast. + static inline bool classof(const Type *T) { + return T->getTypeID() == ArrayTyID || + T->getTypeID() == StructTyID || + T->getTypeID() == PointerTyID || + T->getTypeID() == VectorTyID; + } +}; + + +/// StructType - Class to represent struct types. There are two different kinds +/// of struct types: Literal structs and Identified structs. +/// +/// Literal struct types (e.g. { i32, i32 }) are uniqued structurally, and must +/// always have a body when created. You can get one of these by using one of +/// the StructType::get() forms. +/// +/// Identified structs (e.g. %foo or %42) may optionally have a name and are not +/// uniqued. The names for identified structs are managed at the LLVMContext +/// level, so there can only be a single identified struct with a given name in +/// a particular LLVMContext. Identified structs may also optionally be opaque +/// (have no body specified). You get one of these by using one of the +/// StructType::create() forms. +/// +/// Independent of what kind of struct you have, the body of a struct type are +/// laid out in memory consequtively with the elements directly one after the +/// other (if the struct is packed) or (if not packed) with padding between the +/// elements as defined by DataLayout (which is required to match what the code +/// generator for a target expects). +/// +class StructType : public CompositeType { + StructType(const StructType &) LLVM_DELETED_FUNCTION; + const StructType &operator=(const StructType &) LLVM_DELETED_FUNCTION; + StructType(LLVMContext &C) + : CompositeType(C, StructTyID), SymbolTableEntry(0) {} + enum { + /// This is the contents of the SubClassData field. + SCDB_HasBody = 1, + SCDB_Packed = 2, + SCDB_IsLiteral = 4, + SCDB_IsSized = 8 + }; + + /// SymbolTableEntry - For a named struct that actually has a name, this is a + /// pointer to the symbol table entry (maintained by LLVMContext) for the + /// struct. This is null if the type is an literal struct or if it is + /// a identified type that has an empty name. + /// + void *SymbolTableEntry; +public: + ~StructType() { + delete [] ContainedTys; // Delete the body. + } + + /// StructType::create - This creates an identified struct. + static StructType *create(LLVMContext &Context, StringRef Name); + static StructType *create(LLVMContext &Context); + + static StructType *create(ArrayRef<Type*> Elements, + StringRef Name, + bool isPacked = false); + static StructType *create(ArrayRef<Type*> Elements); + static StructType *create(LLVMContext &Context, + ArrayRef<Type*> Elements, + StringRef Name, + bool isPacked = false); + static StructType *create(LLVMContext &Context, ArrayRef<Type*> Elements); + static StructType *create(StringRef Name, Type *elt1, ...) END_WITH_NULL; + + /// StructType::get - This static method is the primary way to create a + /// literal StructType. + static StructType *get(LLVMContext &Context, ArrayRef<Type*> Elements, + bool isPacked = false); + + /// StructType::get - Create an empty structure type. + /// + static StructType *get(LLVMContext &Context, bool isPacked = false); + + /// StructType::get - This static method is a convenience method for creating + /// structure types by specifying the elements as arguments. Note that this + /// method always returns a non-packed struct, and requires at least one + /// element type. + static StructType *get(Type *elt1, ...) END_WITH_NULL; + + bool isPacked() const { return (getSubclassData() & SCDB_Packed) != 0; } + + /// isLiteral - Return true if this type is uniqued by structural + /// equivalence, false if it is a struct definition. + bool isLiteral() const { return (getSubclassData() & SCDB_IsLiteral) != 0; } + + /// isOpaque - Return true if this is a type with an identity that has no body + /// specified yet. These prints as 'opaque' in .ll files. + bool isOpaque() const { return (getSubclassData() & SCDB_HasBody) == 0; } + + /// isSized - Return true if this is a sized type. + bool isSized() const; + + /// hasName - Return true if this is a named struct that has a non-empty name. + bool hasName() const { return SymbolTableEntry != 0; } + + /// getName - Return the name for this struct type if it has an identity. + /// This may return an empty string for an unnamed struct type. Do not call + /// this on an literal type. + StringRef getName() const; + + /// setName - Change the name of this type to the specified name, or to a name + /// with a suffix if there is a collision. Do not call this on an literal + /// type. + void setName(StringRef Name); + + /// setBody - Specify a body for an opaque identified type. + void setBody(ArrayRef<Type*> Elements, bool isPacked = false); + void setBody(Type *elt1, ...) END_WITH_NULL; + + /// isValidElementType - Return true if the specified type is valid as a + /// element type. + static bool isValidElementType(Type *ElemTy); + + + // Iterator access to the elements. + typedef Type::subtype_iterator element_iterator; + element_iterator element_begin() const { return ContainedTys; } + element_iterator element_end() const { return &ContainedTys[NumContainedTys];} + + /// isLayoutIdentical - Return true if this is layout identical to the + /// specified struct. + bool isLayoutIdentical(StructType *Other) const; + + /// Random access to the elements + unsigned getNumElements() const { return NumContainedTys; } + Type *getElementType(unsigned N) const { + assert(N < NumContainedTys && "Element number out of range!"); + return ContainedTys[N]; + } + + /// Methods for support type inquiry through isa, cast, and dyn_cast. + static inline bool classof(const Type *T) { + return T->getTypeID() == StructTyID; + } +}; + +/// SequentialType - This is the superclass of the array, pointer and vector +/// type classes. All of these represent "arrays" in memory. The array type +/// represents a specifically sized array, pointer types are unsized/unknown +/// size arrays, vector types represent specifically sized arrays that +/// allow for use of SIMD instructions. SequentialType holds the common +/// features of all, which stem from the fact that all three lay their +/// components out in memory identically. +/// +class SequentialType : public CompositeType { + Type *ContainedType; ///< Storage for the single contained type. + SequentialType(const SequentialType &) LLVM_DELETED_FUNCTION; + const SequentialType &operator=(const SequentialType &) LLVM_DELETED_FUNCTION; + +protected: + SequentialType(TypeID TID, Type *ElType) + : CompositeType(ElType->getContext(), TID), ContainedType(ElType) { + ContainedTys = &ContainedType; + NumContainedTys = 1; + } + +public: + Type *getElementType() const { return ContainedTys[0]; } + + /// Methods for support type inquiry through isa, cast, and dyn_cast. + static inline bool classof(const Type *T) { + return T->getTypeID() == ArrayTyID || + T->getTypeID() == PointerTyID || + T->getTypeID() == VectorTyID; + } +}; + + +/// ArrayType - Class to represent array types. +/// +class ArrayType : public SequentialType { + uint64_t NumElements; + + ArrayType(const ArrayType &) LLVM_DELETED_FUNCTION; + const ArrayType &operator=(const ArrayType &) LLVM_DELETED_FUNCTION; + ArrayType(Type *ElType, uint64_t NumEl); +public: + /// ArrayType::get - This static method is the primary way to construct an + /// ArrayType + /// + static ArrayType *get(Type *ElementType, uint64_t NumElements); + + /// isValidElementType - Return true if the specified type is valid as a + /// element type. + static bool isValidElementType(Type *ElemTy); + + uint64_t getNumElements() const { return NumElements; } + + /// Methods for support type inquiry through isa, cast, and dyn_cast. + static inline bool classof(const Type *T) { + return T->getTypeID() == ArrayTyID; + } +}; + +/// VectorType - Class to represent vector types. +/// +class VectorType : public SequentialType { + unsigned NumElements; + + VectorType(const VectorType &) LLVM_DELETED_FUNCTION; + const VectorType &operator=(const VectorType &) LLVM_DELETED_FUNCTION; + VectorType(Type *ElType, unsigned NumEl); +public: + /// VectorType::get - This static method is the primary way to construct an + /// VectorType. + /// + static VectorType *get(Type *ElementType, unsigned NumElements); + + /// VectorType::getInteger - This static method gets a VectorType with the + /// same number of elements as the input type, and the element type is an + /// integer type of the same width as the input element type. + /// + static VectorType *getInteger(VectorType *VTy) { + unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits(); + assert(EltBits && "Element size must be of a non-zero size"); + Type *EltTy = IntegerType::get(VTy->getContext(), EltBits); + return VectorType::get(EltTy, VTy->getNumElements()); + } + + /// VectorType::getExtendedElementVectorType - This static method is like + /// getInteger except that the element types are twice as wide as the + /// elements in the input type. + /// + static VectorType *getExtendedElementVectorType(VectorType *VTy) { + unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits(); + Type *EltTy = IntegerType::get(VTy->getContext(), EltBits * 2); + return VectorType::get(EltTy, VTy->getNumElements()); + } + + /// VectorType::getTruncatedElementVectorType - This static method is like + /// getInteger except that the element types are half as wide as the + /// elements in the input type. + /// + static VectorType *getTruncatedElementVectorType(VectorType *VTy) { + unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits(); + assert((EltBits & 1) == 0 && + "Cannot truncate vector element with odd bit-width"); + Type *EltTy = IntegerType::get(VTy->getContext(), EltBits / 2); + return VectorType::get(EltTy, VTy->getNumElements()); + } + + /// isValidElementType - Return true if the specified type is valid as a + /// element type. + static bool isValidElementType(Type *ElemTy); + + /// @brief Return the number of elements in the Vector type. + unsigned getNumElements() const { return NumElements; } + + /// @brief Return the number of bits in the Vector type. + /// Returns zero when the vector is a vector of pointers. + unsigned getBitWidth() const { + return NumElements * getElementType()->getPrimitiveSizeInBits(); + } + + /// Methods for support type inquiry through isa, cast, and dyn_cast. + static inline bool classof(const Type *T) { + return T->getTypeID() == VectorTyID; + } +}; + + +/// PointerType - Class to represent pointers. +/// +class PointerType : public SequentialType { + PointerType(const PointerType &) LLVM_DELETED_FUNCTION; + const PointerType &operator=(const PointerType &) LLVM_DELETED_FUNCTION; + explicit PointerType(Type *ElType, unsigned AddrSpace); +public: + /// PointerType::get - This constructs a pointer to an object of the specified + /// type in a numbered address space. + static PointerType *get(Type *ElementType, unsigned AddressSpace); + + /// PointerType::getUnqual - This constructs a pointer to an object of the + /// specified type in the generic address space (address space zero). + static PointerType *getUnqual(Type *ElementType) { + return PointerType::get(ElementType, 0); + } + + /// isValidElementType - Return true if the specified type is valid as a + /// element type. + static bool isValidElementType(Type *ElemTy); + + /// @brief Return the address space of the Pointer type. + inline unsigned getAddressSpace() const { return getSubclassData(); } + + /// Implement support type inquiry through isa, cast, and dyn_cast. + static inline bool classof(const Type *T) { + return T->getTypeID() == PointerTyID; + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h new file mode 100644 index 0000000..f97929f --- /dev/null +++ b/include/llvm/IR/Function.h @@ -0,0 +1,470 @@ +//===-- llvm/Function.h - Class to represent a single function --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the Function class, which represents a +// single function/procedure in LLVM. +// +// A function basically consists of a list of basic blocks, a list of arguments, +// and a symbol table. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_FUNCTION_H +#define LLVM_IR_FUNCTION_H + +#include "llvm/IR/Argument.h" +#include "llvm/IR/Attributes.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/CallingConv.h" +#include "llvm/IR/GlobalValue.h" +#include "llvm/Support/Compiler.h" + +namespace llvm { + +class FunctionType; +class LLVMContext; + +// Traits for intrusive list of basic blocks... +template<> struct ilist_traits<BasicBlock> + : public SymbolTableListTraits<BasicBlock, Function> { + + // createSentinel is used to get hold of the node that marks the end of the + // list... (same trick used here as in ilist_traits<Instruction>) + BasicBlock *createSentinel() const { + return static_cast<BasicBlock*>(&Sentinel); + } + static void destroySentinel(BasicBlock*) {} + + BasicBlock *provideInitialHead() const { return createSentinel(); } + BasicBlock *ensureHead(BasicBlock*) const { return createSentinel(); } + static void noteHead(BasicBlock*, BasicBlock*) {} + + static ValueSymbolTable *getSymTab(Function *ItemParent); +private: + mutable ilist_half_node<BasicBlock> Sentinel; +}; + +template<> struct ilist_traits<Argument> + : public SymbolTableListTraits<Argument, Function> { + + Argument *createSentinel() const { + return static_cast<Argument*>(&Sentinel); + } + static void destroySentinel(Argument*) {} + + Argument *provideInitialHead() const { return createSentinel(); } + Argument *ensureHead(Argument*) const { return createSentinel(); } + static void noteHead(Argument*, Argument*) {} + + static ValueSymbolTable *getSymTab(Function *ItemParent); +private: + mutable ilist_half_node<Argument> Sentinel; +}; + +class Function : public GlobalValue, + public ilist_node<Function> { +public: + typedef iplist<Argument> ArgumentListType; + typedef iplist<BasicBlock> BasicBlockListType; + + // BasicBlock iterators... + typedef BasicBlockListType::iterator iterator; + typedef BasicBlockListType::const_iterator const_iterator; + + typedef ArgumentListType::iterator arg_iterator; + typedef ArgumentListType::const_iterator const_arg_iterator; + +private: + // Important things that make up a function! + BasicBlockListType BasicBlocks; ///< The basic blocks + mutable ArgumentListType ArgumentList; ///< The formal arguments + ValueSymbolTable *SymTab; ///< Symbol table of args/instructions + AttributeSet AttributeSets; ///< Parameter attributes + + // HasLazyArguments is stored in Value::SubclassData. + /*bool HasLazyArguments;*/ + + // The Calling Convention is stored in Value::SubclassData. + /*CallingConv::ID CallingConvention;*/ + + friend class SymbolTableListTraits<Function, Module>; + + void setParent(Module *parent); + + /// hasLazyArguments/CheckLazyArguments - The argument list of a function is + /// built on demand, so that the list isn't allocated until the first client + /// needs it. The hasLazyArguments predicate returns true if the arg list + /// hasn't been set up yet. + bool hasLazyArguments() const { + return getSubclassDataFromValue() & 1; + } + void CheckLazyArguments() const { + if (hasLazyArguments()) + BuildLazyArguments(); + } + void BuildLazyArguments() const; + + Function(const Function&) LLVM_DELETED_FUNCTION; + void operator=(const Function&) LLVM_DELETED_FUNCTION; + + /// Do the actual lookup of an intrinsic ID when the query could not be + /// answered from the cache. + unsigned lookupIntrinsicID() const LLVM_READONLY; + + /// Function ctor - If the (optional) Module argument is specified, the + /// function is automatically inserted into the end of the function list for + /// the module. + /// + Function(FunctionType *Ty, LinkageTypes Linkage, + const Twine &N = "", Module *M = 0); + +public: + static Function *Create(FunctionType *Ty, LinkageTypes Linkage, + const Twine &N = "", Module *M = 0) { + return new(0) Function(Ty, Linkage, N, M); + } + + ~Function(); + + Type *getReturnType() const; // Return the type of the ret val + FunctionType *getFunctionType() const; // Return the FunctionType for me + + /// getContext - Return a pointer to the LLVMContext associated with this + /// function, or NULL if this function is not bound to a context yet. + LLVMContext &getContext() const; + + /// isVarArg - Return true if this function takes a variable number of + /// arguments. + bool isVarArg() const; + + /// getIntrinsicID - This method returns the ID number of the specified + /// function, or Intrinsic::not_intrinsic if the function is not an + /// intrinsic, or if the pointer is null. This value is always defined to be + /// zero to allow easy checking for whether a function is intrinsic or not. + /// The particular intrinsic functions which correspond to this value are + /// defined in llvm/Intrinsics.h. Results are cached in the LLVM context, + /// subsequent requests for the same ID return results much faster from the + /// cache. + /// + unsigned getIntrinsicID() const LLVM_READONLY; + bool isIntrinsic() const { return getName().startswith("llvm."); } + + /// getCallingConv()/setCallingConv(CC) - These method get and set the + /// calling convention of this function. The enum values for the known + /// calling conventions are defined in CallingConv.h. + CallingConv::ID getCallingConv() const { + return static_cast<CallingConv::ID>(getSubclassDataFromValue() >> 1); + } + void setCallingConv(CallingConv::ID CC) { + setValueSubclassData((getSubclassDataFromValue() & 1) | + (static_cast<unsigned>(CC) << 1)); + } + + /// getAttributes - Return the attribute list for this Function. + /// + AttributeSet getAttributes() const { return AttributeSets; } + + /// setAttributes - Set the attribute list for this Function. + /// + void setAttributes(AttributeSet attrs) { AttributeSets = attrs; } + + /// addFnAttr - Add function attributes to this function. + /// + void addFnAttr(Attribute::AttrKind N) { + setAttributes(AttributeSets.addAttribute(getContext(), + AttributeSet::FunctionIndex, N)); + } + + /// addFnAttr - Add function attributes to this function. + /// + void addFnAttr(StringRef Kind) { + setAttributes( + AttributeSets.addAttribute(getContext(), + AttributeSet::FunctionIndex, Kind)); + } + + /// \brief Return true if the function has the attribute. + bool hasFnAttribute(Attribute::AttrKind Kind) const { + return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Kind); + } + bool hasFnAttribute(StringRef Kind) const { + return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Kind); + } + + /// hasGC/getGC/setGC/clearGC - The name of the garbage collection algorithm + /// to use during code generation. + bool hasGC() const; + const char *getGC() const; + void setGC(const char *Str); + void clearGC(); + + /// @brief adds the attribute to the list of attributes. + void addAttribute(unsigned i, Attribute::AttrKind attr); + + /// @brief adds the attributes to the list of attributes. + void addAttributes(unsigned i, AttributeSet attrs); + + /// @brief removes the attributes from the list of attributes. + void removeAttributes(unsigned i, AttributeSet attr); + + /// @brief Extract the alignment for a call or parameter (0=unknown). + unsigned getParamAlignment(unsigned i) const { + return AttributeSets.getParamAlignment(i); + } + + /// @brief Determine if the function does not access memory. + bool doesNotAccessMemory() const { + return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, + Attribute::ReadNone); + } + void setDoesNotAccessMemory() { + addFnAttr(Attribute::ReadNone); + } + + /// @brief Determine if the function does not access or only reads memory. + bool onlyReadsMemory() const { + return doesNotAccessMemory() || + AttributeSets.hasAttribute(AttributeSet::FunctionIndex, + Attribute::ReadOnly); + } + void setOnlyReadsMemory() { + addFnAttr(Attribute::ReadOnly); + } + + /// @brief Determine if the function cannot return. + bool doesNotReturn() const { + return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, + Attribute::NoReturn); + } + void setDoesNotReturn() { + addFnAttr(Attribute::NoReturn); + } + + /// @brief Determine if the function cannot unwind. + bool doesNotThrow() const { + return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, + Attribute::NoUnwind); + } + void setDoesNotThrow() { + addFnAttr(Attribute::NoUnwind); + } + + /// @brief Determine if the call cannot be duplicated. + bool cannotDuplicate() const { + return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, + Attribute::NoDuplicate); + } + void setCannotDuplicate() { + addFnAttr(Attribute::NoDuplicate); + } + + /// @brief True if the ABI mandates (or the user requested) that this + /// function be in a unwind table. + bool hasUWTable() const { + return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, + Attribute::UWTable); + } + void setHasUWTable() { + addFnAttr(Attribute::UWTable); + } + + /// @brief True if this function needs an unwind table. + bool needsUnwindTableEntry() const { + return hasUWTable() || !doesNotThrow(); + } + + /// @brief Determine if the function returns a structure through first + /// pointer argument. + bool hasStructRetAttr() const { + return AttributeSets.hasAttribute(1, Attribute::StructRet); + } + + /// @brief Determine if the parameter does not alias other parameters. + /// @param n The parameter to check. 1 is the first parameter, 0 is the return + bool doesNotAlias(unsigned n) const { + return AttributeSets.hasAttribute(n, Attribute::NoAlias); + } + void setDoesNotAlias(unsigned n) { + addAttribute(n, Attribute::NoAlias); + } + + /// @brief Determine if the parameter can be captured. + /// @param n The parameter to check. 1 is the first parameter, 0 is the return + bool doesNotCapture(unsigned n) const { + return AttributeSets.hasAttribute(n, Attribute::NoCapture); + } + void setDoesNotCapture(unsigned n) { + addAttribute(n, Attribute::NoCapture); + } + + /// copyAttributesFrom - copy all additional attributes (those not needed to + /// create a Function) from the Function Src to this one. + void copyAttributesFrom(const GlobalValue *Src); + + /// deleteBody - This method deletes the body of the function, and converts + /// the linkage to external. + /// + void deleteBody() { + dropAllReferences(); + setLinkage(ExternalLinkage); + } + + /// removeFromParent - This method unlinks 'this' from the containing module, + /// but does not delete it. + /// + virtual void removeFromParent(); + + /// eraseFromParent - This method unlinks 'this' from the containing module + /// and deletes it. + /// + virtual void eraseFromParent(); + + + /// Get the underlying elements of the Function... the basic block list is + /// empty for external functions. + /// + const ArgumentListType &getArgumentList() const { + CheckLazyArguments(); + return ArgumentList; + } + ArgumentListType &getArgumentList() { + CheckLazyArguments(); + return ArgumentList; + } + static iplist<Argument> Function::*getSublistAccess(Argument*) { + return &Function::ArgumentList; + } + + const BasicBlockListType &getBasicBlockList() const { return BasicBlocks; } + BasicBlockListType &getBasicBlockList() { return BasicBlocks; } + static iplist<BasicBlock> Function::*getSublistAccess(BasicBlock*) { + return &Function::BasicBlocks; + } + + const BasicBlock &getEntryBlock() const { return front(); } + BasicBlock &getEntryBlock() { return front(); } + + //===--------------------------------------------------------------------===// + // Symbol Table Accessing functions... + + /// getSymbolTable() - Return the symbol table... + /// + inline ValueSymbolTable &getValueSymbolTable() { return *SymTab; } + inline const ValueSymbolTable &getValueSymbolTable() const { return *SymTab; } + + + //===--------------------------------------------------------------------===// + // BasicBlock iterator forwarding functions + // + iterator begin() { return BasicBlocks.begin(); } + const_iterator begin() const { return BasicBlocks.begin(); } + iterator end () { return BasicBlocks.end(); } + const_iterator end () const { return BasicBlocks.end(); } + + size_t size() const { return BasicBlocks.size(); } + bool empty() const { return BasicBlocks.empty(); } + const BasicBlock &front() const { return BasicBlocks.front(); } + BasicBlock &front() { return BasicBlocks.front(); } + const BasicBlock &back() const { return BasicBlocks.back(); } + BasicBlock &back() { return BasicBlocks.back(); } + + //===--------------------------------------------------------------------===// + // Argument iterator forwarding functions + // + arg_iterator arg_begin() { + CheckLazyArguments(); + return ArgumentList.begin(); + } + const_arg_iterator arg_begin() const { + CheckLazyArguments(); + return ArgumentList.begin(); + } + arg_iterator arg_end() { + CheckLazyArguments(); + return ArgumentList.end(); + } + const_arg_iterator arg_end() const { + CheckLazyArguments(); + return ArgumentList.end(); + } + + size_t arg_size() const; + bool arg_empty() const; + + /// viewCFG - This function is meant for use from the debugger. You can just + /// say 'call F->viewCFG()' and a ghostview window should pop up from the + /// program, displaying the CFG of the current function with the code for each + /// basic block inside. This depends on there being a 'dot' and 'gv' program + /// in your path. + /// + void viewCFG() const; + + /// viewCFGOnly - This function is meant for use from the debugger. It works + /// just like viewCFG, but it does not include the contents of basic blocks + /// into the nodes, just the label. If you are only interested in the CFG + /// this can make the graph smaller. + /// + void viewCFGOnly() const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Value *V) { + return V->getValueID() == Value::FunctionVal; + } + + /// dropAllReferences() - This method causes all the subinstructions to "let + /// go" of all references that they are maintaining. This allows one to + /// 'delete' a whole module at a time, even though there may be circular + /// references... first all references are dropped, and all use counts go to + /// zero. Then everything is deleted for real. Note that no operations are + /// valid on an object that has "dropped all references", except operator + /// delete. + /// + /// Since no other object in the module can have references into the body of a + /// function, dropping all references deletes the entire body of the function, + /// including any contained basic blocks. + /// + void dropAllReferences(); + + /// hasAddressTaken - returns true if there are any uses of this function + /// other than direct calls or invokes to it, or blockaddress expressions. + /// Optionally passes back an offending user for diagnostic purposes. + /// + bool hasAddressTaken(const User** = 0) const; + + /// isDefTriviallyDead - Return true if it is trivially safe to remove + /// this function definition from the module (because it isn't externally + /// visible, does not have its address taken, and has no callers). To make + /// this more accurate, call removeDeadConstantUsers first. + bool isDefTriviallyDead() const; + + /// callsFunctionThatReturnsTwice - Return true if the function has a call to + /// setjmp or other function that gcc recognizes as "returning twice". + bool callsFunctionThatReturnsTwice() const; + +private: + // Shadow Value::setValueSubclassData with a private forwarding method so that + // subclasses cannot accidentally use it. + void setValueSubclassData(unsigned short D) { + Value::setValueSubclassData(D); + } +}; + +inline ValueSymbolTable * +ilist_traits<BasicBlock>::getSymTab(Function *F) { + return F ? &F->getValueSymbolTable() : 0; +} + +inline ValueSymbolTable * +ilist_traits<Argument>::getSymTab(Function *F) { + return F ? &F->getValueSymbolTable() : 0; +} + +} // End llvm namespace + +#endif diff --git a/include/llvm/IR/GlobalAlias.h b/include/llvm/IR/GlobalAlias.h new file mode 100644 index 0000000..883814a --- /dev/null +++ b/include/llvm/IR/GlobalAlias.h @@ -0,0 +1,93 @@ +//===-------- llvm/GlobalAlias.h - GlobalAlias class ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the GlobalAlias class, which +// represents a single function or variable alias in the IR. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_GLOBALALIAS_H +#define LLVM_IR_GLOBALALIAS_H + +#include "llvm/ADT/Twine.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/IR/GlobalValue.h" +#include "llvm/IR/OperandTraits.h" + +namespace llvm { + +class Module; +template<typename ValueSubClass, typename ItemParentClass> + class SymbolTableListTraits; + +class GlobalAlias : public GlobalValue, public ilist_node<GlobalAlias> { + friend class SymbolTableListTraits<GlobalAlias, Module>; + void operator=(const GlobalAlias &) LLVM_DELETED_FUNCTION; + GlobalAlias(const GlobalAlias &) LLVM_DELETED_FUNCTION; + + void setParent(Module *parent); + +public: + // allocate space for exactly one operand + void *operator new(size_t s) { + return User::operator new(s, 1); + } + /// GlobalAlias ctor - If a parent module is specified, the alias is + /// automatically inserted into the end of the specified module's alias list. + GlobalAlias(Type *Ty, LinkageTypes Linkage, const Twine &Name = "", + Constant* Aliasee = 0, Module *Parent = 0); + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); + + /// removeFromParent - This method unlinks 'this' from the containing module, + /// but does not delete it. + /// + virtual void removeFromParent(); + + /// eraseFromParent - This method unlinks 'this' from the containing module + /// and deletes it. + /// + virtual void eraseFromParent(); + + /// set/getAliasee - These methods retrive and set alias target. + void setAliasee(Constant *GV); + const Constant *getAliasee() const { + return getOperand(0); + } + Constant *getAliasee() { + return getOperand(0); + } + /// getAliasedGlobal() - Aliasee can be either global or bitcast of + /// global. This method retrives the global for both aliasee flavours. + const GlobalValue *getAliasedGlobal() const; + + /// resolveAliasedGlobal() - This method tries to ultimately resolve the alias + /// by going through the aliasing chain and trying to find the very last + /// global. Returns NULL if a cycle was found. If stopOnWeak is false, then + /// the whole chain aliasing chain is traversed, otherwise - only strong + /// aliases. + const GlobalValue *resolveAliasedGlobal(bool stopOnWeak = true) const; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Value *V) { + return V->getValueID() == Value::GlobalAliasVal; + } +}; + +template <> +struct OperandTraits<GlobalAlias> : + public FixedNumOperandTraits<GlobalAlias, 1> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GlobalAlias, Constant) + +} // End llvm namespace + +#endif diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h new file mode 100644 index 0000000..f398bc1 --- /dev/null +++ b/include/llvm/IR/GlobalValue.h @@ -0,0 +1,299 @@ +//===-- llvm/GlobalValue.h - Class to represent a global value --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a common base class of all globally definable objects. As such, +// it is subclassed by GlobalVariable, GlobalAlias and by Function. This is +// used because you can do certain things with these global objects that you +// can't do to anything else. For example, use the address of one as a +// constant. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_GLOBALVALUE_H +#define LLVM_IR_GLOBALVALUE_H + +#include "llvm/IR/Constant.h" + +namespace llvm { + +class PointerType; +class Module; + +class GlobalValue : public Constant { + GlobalValue(const GlobalValue &) LLVM_DELETED_FUNCTION; +public: + /// @brief An enumeration for the kinds of linkage for global values. + enum LinkageTypes { + ExternalLinkage = 0,///< Externally visible function + AvailableExternallyLinkage, ///< Available for inspection, not emission. + LinkOnceAnyLinkage, ///< Keep one copy of function when linking (inline) + LinkOnceODRLinkage, ///< Same, but only replaced by something equivalent. + LinkOnceODRAutoHideLinkage, ///< Like LinkOnceODRLinkage but addr not taken. + WeakAnyLinkage, ///< Keep one copy of named function when linking (weak) + WeakODRLinkage, ///< Same, but only replaced by something equivalent. + AppendingLinkage, ///< Special purpose, only applies to global arrays + InternalLinkage, ///< Rename collisions when linking (static functions). + PrivateLinkage, ///< Like Internal, but omit from symbol table. + LinkerPrivateLinkage, ///< Like Private, but linker removes. + LinkerPrivateWeakLinkage, ///< Like LinkerPrivate, but weak. + DLLImportLinkage, ///< Function to be imported from DLL + DLLExportLinkage, ///< Function to be accessible from DLL. + ExternalWeakLinkage,///< ExternalWeak linkage description. + CommonLinkage ///< Tentative definitions. + }; + + /// @brief An enumeration for the kinds of visibility of global values. + enum VisibilityTypes { + DefaultVisibility = 0, ///< The GV is visible + HiddenVisibility, ///< The GV is hidden + ProtectedVisibility ///< The GV is protected + }; + +protected: + GlobalValue(Type *ty, ValueTy vty, Use *Ops, unsigned NumOps, + LinkageTypes linkage, const Twine &Name) + : Constant(ty, vty, Ops, NumOps), Linkage(linkage), + Visibility(DefaultVisibility), Alignment(0), UnnamedAddr(0), Parent(0) { + setName(Name); + } + + // Note: VC++ treats enums as signed, so an extra bit is required to prevent + // Linkage and Visibility from turning into negative values. + LinkageTypes Linkage : 5; // The linkage of this global + unsigned Visibility : 2; // The visibility style of this global + unsigned Alignment : 16; // Alignment of this symbol, must be power of two + unsigned UnnamedAddr : 1; // This value's address is not significant + Module *Parent; // The containing module. + std::string Section; // Section to emit this into, empty mean default +public: + ~GlobalValue() { + removeDeadConstantUsers(); // remove any dead constants using this. + } + + unsigned getAlignment() const { + return (1u << Alignment) >> 1; + } + void setAlignment(unsigned Align); + + bool hasUnnamedAddr() const { return UnnamedAddr; } + void setUnnamedAddr(bool Val) { UnnamedAddr = Val; } + + VisibilityTypes getVisibility() const { return VisibilityTypes(Visibility); } + bool hasDefaultVisibility() const { return Visibility == DefaultVisibility; } + bool hasHiddenVisibility() const { return Visibility == HiddenVisibility; } + bool hasProtectedVisibility() const { + return Visibility == ProtectedVisibility; + } + void setVisibility(VisibilityTypes V) { Visibility = V; } + + bool hasSection() const { return !Section.empty(); } + const std::string &getSection() const { return Section; } + void setSection(StringRef S) { Section = S; } + + /// If the usage is empty (except transitively dead constants), then this + /// global value can be safely deleted since the destructor will + /// delete the dead constants as well. + /// @brief Determine if the usage of this global value is empty except + /// for transitively dead constants. + bool use_empty_except_constants(); + + /// getType - Global values are always pointers. + inline PointerType *getType() const { + return reinterpret_cast<PointerType*>(User::getType()); + } + + static LinkageTypes getLinkOnceLinkage(bool ODR) { + return ODR ? LinkOnceODRLinkage : LinkOnceAnyLinkage; + } + static LinkageTypes getWeakLinkage(bool ODR) { + return ODR ? WeakODRLinkage : WeakAnyLinkage; + } + + static bool isExternalLinkage(LinkageTypes Linkage) { + return Linkage == ExternalLinkage; + } + static bool isAvailableExternallyLinkage(LinkageTypes Linkage) { + return Linkage == AvailableExternallyLinkage; + } + static bool isLinkOnceLinkage(LinkageTypes Linkage) { + return Linkage == LinkOnceAnyLinkage || + Linkage == LinkOnceODRLinkage || + Linkage == LinkOnceODRAutoHideLinkage; + } + static bool isLinkOnceODRAutoHideLinkage(LinkageTypes Linkage) { + return Linkage == LinkOnceODRAutoHideLinkage; + } + static bool isWeakLinkage(LinkageTypes Linkage) { + return Linkage == WeakAnyLinkage || Linkage == WeakODRLinkage; + } + static bool isAppendingLinkage(LinkageTypes Linkage) { + return Linkage == AppendingLinkage; + } + static bool isInternalLinkage(LinkageTypes Linkage) { + return Linkage == InternalLinkage; + } + static bool isPrivateLinkage(LinkageTypes Linkage) { + return Linkage == PrivateLinkage; + } + static bool isLinkerPrivateLinkage(LinkageTypes Linkage) { + return Linkage == LinkerPrivateLinkage; + } + static bool isLinkerPrivateWeakLinkage(LinkageTypes Linkage) { + return Linkage == LinkerPrivateWeakLinkage; + } + static bool isLocalLinkage(LinkageTypes Linkage) { + return isInternalLinkage(Linkage) || isPrivateLinkage(Linkage) || + isLinkerPrivateLinkage(Linkage) || isLinkerPrivateWeakLinkage(Linkage); + } + static bool isDLLImportLinkage(LinkageTypes Linkage) { + return Linkage == DLLImportLinkage; + } + static bool isDLLExportLinkage(LinkageTypes Linkage) { + return Linkage == DLLExportLinkage; + } + static bool isExternalWeakLinkage(LinkageTypes Linkage) { + return Linkage == ExternalWeakLinkage; + } + static bool isCommonLinkage(LinkageTypes Linkage) { + return Linkage == CommonLinkage; + } + + /// isDiscardableIfUnused - Whether the definition of this global may be + /// discarded if it is not used in its compilation unit. + static bool isDiscardableIfUnused(LinkageTypes Linkage) { + return isLinkOnceLinkage(Linkage) || isLocalLinkage(Linkage); + } + + /// mayBeOverridden - Whether the definition of this global may be replaced + /// by something non-equivalent at link time. For example, if a function has + /// weak linkage then the code defining it may be replaced by different code. + static bool mayBeOverridden(LinkageTypes Linkage) { + return Linkage == WeakAnyLinkage || + Linkage == LinkOnceAnyLinkage || + Linkage == CommonLinkage || + Linkage == ExternalWeakLinkage || + Linkage == LinkerPrivateWeakLinkage; + } + + /// isWeakForLinker - Whether the definition of this global may be replaced at + /// link time. NB: Using this method outside of the code generators is almost + /// always a mistake: when working at the IR level use mayBeOverridden instead + /// as it knows about ODR semantics. + static bool isWeakForLinker(LinkageTypes Linkage) { + return Linkage == AvailableExternallyLinkage || + Linkage == WeakAnyLinkage || + Linkage == WeakODRLinkage || + Linkage == LinkOnceAnyLinkage || + Linkage == LinkOnceODRLinkage || + Linkage == LinkOnceODRAutoHideLinkage || + Linkage == CommonLinkage || + Linkage == ExternalWeakLinkage || + Linkage == LinkerPrivateWeakLinkage; + } + + bool hasExternalLinkage() const { return isExternalLinkage(Linkage); } + bool hasAvailableExternallyLinkage() const { + return isAvailableExternallyLinkage(Linkage); + } + bool hasLinkOnceLinkage() const { + return isLinkOnceLinkage(Linkage); + } + bool hasLinkOnceODRAutoHideLinkage() const { + return isLinkOnceODRAutoHideLinkage(Linkage); + } + bool hasWeakLinkage() const { + return isWeakLinkage(Linkage); + } + bool hasAppendingLinkage() const { return isAppendingLinkage(Linkage); } + bool hasInternalLinkage() const { return isInternalLinkage(Linkage); } + bool hasPrivateLinkage() const { return isPrivateLinkage(Linkage); } + bool hasLinkerPrivateLinkage() const { return isLinkerPrivateLinkage(Linkage); } + bool hasLinkerPrivateWeakLinkage() const { + return isLinkerPrivateWeakLinkage(Linkage); + } + bool hasLocalLinkage() const { return isLocalLinkage(Linkage); } + bool hasDLLImportLinkage() const { return isDLLImportLinkage(Linkage); } + bool hasDLLExportLinkage() const { return isDLLExportLinkage(Linkage); } + bool hasExternalWeakLinkage() const { return isExternalWeakLinkage(Linkage); } + bool hasCommonLinkage() const { return isCommonLinkage(Linkage); } + + void setLinkage(LinkageTypes LT) { Linkage = LT; } + LinkageTypes getLinkage() const { return Linkage; } + + bool isDiscardableIfUnused() const { + return isDiscardableIfUnused(Linkage); + } + + bool mayBeOverridden() const { return mayBeOverridden(Linkage); } + + bool isWeakForLinker() const { return isWeakForLinker(Linkage); } + + /// copyAttributesFrom - copy all additional attributes (those not needed to + /// create a GlobalValue) from the GlobalValue Src to this one. + virtual void copyAttributesFrom(const GlobalValue *Src); + +/// @name Materialization +/// Materialization is used to construct functions only as they're needed. This +/// is useful to reduce memory usage in LLVM or parsing work done by the +/// BitcodeReader to load the Module. +/// @{ + + /// isMaterializable - If this function's Module is being lazily streamed in + /// functions from disk or some other source, this method can be used to check + /// to see if the function has been read in yet or not. + bool isMaterializable() const; + + /// isDematerializable - Returns true if this function was loaded from a + /// GVMaterializer that's still attached to its Module and that knows how to + /// dematerialize the function. + bool isDematerializable() const; + + /// Materialize - make sure this GlobalValue is fully read. If the module is + /// corrupt, this returns true and fills in the optional string with + /// information about the problem. If successful, this returns false. + bool Materialize(std::string *ErrInfo = 0); + + /// Dematerialize - If this GlobalValue is read in, and if the GVMaterializer + /// supports it, release the memory for the function, and set it up to be + /// materialized lazily. If !isDematerializable(), this method is a noop. + void Dematerialize(); + +/// @} + + /// Override from Constant class. + virtual void destroyConstant(); + + /// isDeclaration - Return true if the primary definition of this global + /// value is outside of the current translation unit. + bool isDeclaration() const; + + /// removeFromParent - This method unlinks 'this' from the containing module, + /// but does not delete it. + virtual void removeFromParent() = 0; + + /// eraseFromParent - This method unlinks 'this' from the containing module + /// and deletes it. + virtual void eraseFromParent() = 0; + + /// getParent - Get the module that this global value is contained inside + /// of... + inline Module *getParent() { return Parent; } + inline const Module *getParent() const { return Parent; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Value *V) { + return V->getValueID() == Value::FunctionVal || + V->getValueID() == Value::GlobalVariableVal || + V->getValueID() == Value::GlobalAliasVal; + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/IR/GlobalVariable.h b/include/llvm/IR/GlobalVariable.h new file mode 100644 index 0000000..bfed507 --- /dev/null +++ b/include/llvm/IR/GlobalVariable.h @@ -0,0 +1,210 @@ +//===-- llvm/GlobalVariable.h - GlobalVariable class ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the GlobalVariable class, which +// represents a single global variable (or constant) in the VM. +// +// Global variables are constant pointers that refer to hunks of space that are +// allocated by either the VM, or by the linker in a static compiler. A global +// variable may have an initial value, which is copied into the executables .data +// area. Global Constants are required to have initializers. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_GLOBALVARIABLE_H +#define LLVM_IR_GLOBALVARIABLE_H + +#include "llvm/ADT/Twine.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/IR/GlobalValue.h" +#include "llvm/IR/OperandTraits.h" + +namespace llvm { + +class Module; +class Constant; +template<typename ValueSubClass, typename ItemParentClass> + class SymbolTableListTraits; + +class GlobalVariable : public GlobalValue, public ilist_node<GlobalVariable> { + friend class SymbolTableListTraits<GlobalVariable, Module>; + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void operator=(const GlobalVariable &) LLVM_DELETED_FUNCTION; + GlobalVariable(const GlobalVariable &) LLVM_DELETED_FUNCTION; + + void setParent(Module *parent); + + bool isConstantGlobal : 1; // Is this a global constant? + unsigned threadLocalMode : 3; // Is this symbol "Thread Local", + // if so, what is the desired + // model? + bool isExternallyInitializedConstant : 1; // Is this a global whose value + // can change from its initial + // value before global + // initializers are run? + +public: + // allocate space for exactly one operand + void *operator new(size_t s) { + return User::operator new(s, 1); + } + + enum ThreadLocalMode { + NotThreadLocal = 0, + GeneralDynamicTLSModel, + LocalDynamicTLSModel, + InitialExecTLSModel, + LocalExecTLSModel + }; + + /// GlobalVariable ctor - If a parent module is specified, the global is + /// automatically inserted into the end of the specified modules global list. + GlobalVariable(Type *Ty, bool isConstant, LinkageTypes Linkage, + Constant *Initializer = 0, const Twine &Name = "", + ThreadLocalMode = NotThreadLocal, unsigned AddressSpace = 0, + bool isExternallyInitialized = false); + /// GlobalVariable ctor - This creates a global and inserts it before the + /// specified other global. + GlobalVariable(Module &M, Type *Ty, bool isConstant, + LinkageTypes Linkage, Constant *Initializer, + const Twine &Name = "", GlobalVariable *InsertBefore = 0, + ThreadLocalMode = NotThreadLocal, unsigned AddressSpace = 0, + bool isExternallyInitialized = false); + + ~GlobalVariable() { + NumOperands = 1; // FIXME: needed by operator delete + } + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// hasInitializer - Unless a global variable isExternal(), it has an + /// initializer. The initializer for the global variable/constant is held by + /// Initializer if an initializer is specified. + /// + inline bool hasInitializer() const { return !isDeclaration(); } + + /// hasDefinitiveInitializer - Whether the global variable has an initializer, + /// and any other instances of the global (this can happen due to weak + /// linkage) are guaranteed to have the same initializer. + /// + /// Note that if you want to transform a global, you must use + /// hasUniqueInitializer() instead, because of the *_odr linkage type. + /// + /// Example: + /// + /// @a = global SomeType* null - Initializer is both definitive and unique. + /// + /// @b = global weak SomeType* null - Initializer is neither definitive nor + /// unique. + /// + /// @c = global weak_odr SomeType* null - Initializer is definitive, but not + /// unique. + inline bool hasDefinitiveInitializer() const { + return hasInitializer() && + // The initializer of a global variable with weak linkage may change at + // link time. + !mayBeOverridden() && + // The initializer of a global variable with the externally_initialized + // marker may change at runtime before C++ initializers are evaluated. + !isExternallyInitialized(); + } + + /// hasUniqueInitializer - Whether the global variable has an initializer, and + /// any changes made to the initializer will turn up in the final executable. + inline bool hasUniqueInitializer() const { + return hasInitializer() && + // It's not safe to modify initializers of global variables with weak + // linkage, because the linker might choose to discard the initializer and + // use the initializer from another instance of the global variable + // instead. It is wrong to modify the initializer of a global variable + // with *_odr linkage because then different instances of the global may + // have different initializers, breaking the One Definition Rule. + !isWeakForLinker() && + // It is not safe to modify initializers of global variables with the + // external_initializer marker since the value may be changed at runtime + // before C++ initializers are evaluated. + !isExternallyInitialized(); + } + + /// getInitializer - Return the initializer for this global variable. It is + /// illegal to call this method if the global is external, because we cannot + /// tell what the value is initialized to! + /// + inline const Constant *getInitializer() const { + assert(hasInitializer() && "GV doesn't have initializer!"); + return static_cast<Constant*>(Op<0>().get()); + } + inline Constant *getInitializer() { + assert(hasInitializer() && "GV doesn't have initializer!"); + return static_cast<Constant*>(Op<0>().get()); + } + /// setInitializer - Sets the initializer for this global variable, removing + /// any existing initializer if InitVal==NULL. If this GV has type T*, the + /// initializer must have type T. + void setInitializer(Constant *InitVal); + + /// If the value is a global constant, its value is immutable throughout the + /// runtime execution of the program. Assigning a value into the constant + /// leads to undefined behavior. + /// + bool isConstant() const { return isConstantGlobal; } + void setConstant(bool Val) { isConstantGlobal = Val; } + + /// If the value is "Thread Local", its value isn't shared by the threads. + bool isThreadLocal() const { return threadLocalMode != NotThreadLocal; } + void setThreadLocal(bool Val) { + threadLocalMode = Val ? GeneralDynamicTLSModel : NotThreadLocal; + } + void setThreadLocalMode(ThreadLocalMode Val) { threadLocalMode = Val; } + ThreadLocalMode getThreadLocalMode() const { + return static_cast<ThreadLocalMode>(threadLocalMode); + } + + bool isExternallyInitialized() const { + return isExternallyInitializedConstant; + } + void setExternallyInitialized(bool Val) { + isExternallyInitializedConstant = Val; + } + + /// copyAttributesFrom - copy all additional attributes (those not needed to + /// create a GlobalVariable) from the GlobalVariable Src to this one. + void copyAttributesFrom(const GlobalValue *Src); + + /// removeFromParent - This method unlinks 'this' from the containing module, + /// but does not delete it. + /// + virtual void removeFromParent(); + + /// eraseFromParent - This method unlinks 'this' from the containing module + /// and deletes it. + /// + virtual void eraseFromParent(); + + /// Override Constant's implementation of this method so we can + /// replace constant initializers. + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Value *V) { + return V->getValueID() == Value::GlobalVariableVal; + } +}; + +template <> +struct OperandTraits<GlobalVariable> : + public OptionalOperandTraits<GlobalVariable> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GlobalVariable, Value) + +} // End llvm namespace + +#endif diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h new file mode 100644 index 0000000..1c71d0a --- /dev/null +++ b/include/llvm/IR/IRBuilder.h @@ -0,0 +1,1401 @@ +//===---- llvm/IRBuilder.h - Builder for LLVM Instructions ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the IRBuilder class, which is used as a convenient way +// to create LLVM instructions with a consistent and simplified interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_IRBUILDER_H +#define LLVM_IR_IRBUILDER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Operator.h" +#include "llvm/Support/ConstantFolder.h" + +namespace llvm { + class MDNode; + +/// \brief This provides the default implementation of the IRBuilder +/// 'InsertHelper' method that is called whenever an instruction is created by +/// IRBuilder and needs to be inserted. +/// +/// By default, this inserts the instruction at the insertion point. +template <bool preserveNames = true> +class IRBuilderDefaultInserter { +protected: + void InsertHelper(Instruction *I, const Twine &Name, + BasicBlock *BB, BasicBlock::iterator InsertPt) const { + if (BB) BB->getInstList().insert(InsertPt, I); + if (preserveNames) + I->setName(Name); + } +}; + +/// \brief Common base class shared among various IRBuilders. +class IRBuilderBase { + DebugLoc CurDbgLocation; +protected: + BasicBlock *BB; + BasicBlock::iterator InsertPt; + LLVMContext &Context; +public: + + IRBuilderBase(LLVMContext &context) + : Context(context) { + ClearInsertionPoint(); + } + + //===--------------------------------------------------------------------===// + // Builder configuration methods + //===--------------------------------------------------------------------===// + + /// \brief Clear the insertion point: created instructions will not be + /// inserted into a block. + void ClearInsertionPoint() { + BB = 0; + } + + BasicBlock *GetInsertBlock() const { return BB; } + BasicBlock::iterator GetInsertPoint() const { return InsertPt; } + LLVMContext &getContext() const { return Context; } + + /// \brief This specifies that created instructions should be appended to the + /// end of the specified block. + void SetInsertPoint(BasicBlock *TheBB) { + BB = TheBB; + InsertPt = BB->end(); + } + + /// \brief This specifies that created instructions should be inserted before + /// the specified instruction. + void SetInsertPoint(Instruction *I) { + BB = I->getParent(); + InsertPt = I; + SetCurrentDebugLocation(I->getDebugLoc()); + } + + /// \brief This specifies that created instructions should be inserted at the + /// specified point. + void SetInsertPoint(BasicBlock *TheBB, BasicBlock::iterator IP) { + BB = TheBB; + InsertPt = IP; + } + + /// \brief Find the nearest point that dominates this use, and specify that + /// created instructions should be inserted at this point. + void SetInsertPoint(Use &U) { + Instruction *UseInst = cast<Instruction>(U.getUser()); + if (PHINode *Phi = dyn_cast<PHINode>(UseInst)) { + BasicBlock *PredBB = Phi->getIncomingBlock(U); + assert(U != PredBB->getTerminator() && "critical edge not split"); + SetInsertPoint(PredBB, PredBB->getTerminator()); + return; + } + SetInsertPoint(UseInst); + } + + /// \brief Set location information used by debugging information. + void SetCurrentDebugLocation(const DebugLoc &L) { + CurDbgLocation = L; + } + + /// \brief Get location information used by debugging information. + DebugLoc getCurrentDebugLocation() const { return CurDbgLocation; } + + /// \brief If this builder has a current debug location, set it on the + /// specified instruction. + void SetInstDebugLocation(Instruction *I) const { + if (!CurDbgLocation.isUnknown()) + I->setDebugLoc(CurDbgLocation); + } + + /// \brief Get the return type of the current function that we're emitting + /// into. + Type *getCurrentFunctionReturnType() const; + + /// InsertPoint - A saved insertion point. + class InsertPoint { + BasicBlock *Block; + BasicBlock::iterator Point; + + public: + /// \brief Creates a new insertion point which doesn't point to anything. + InsertPoint() : Block(0) {} + + /// \brief Creates a new insertion point at the given location. + InsertPoint(BasicBlock *InsertBlock, BasicBlock::iterator InsertPoint) + : Block(InsertBlock), Point(InsertPoint) {} + + /// \brief Returns true if this insert point is set. + bool isSet() const { return (Block != 0); } + + llvm::BasicBlock *getBlock() const { return Block; } + llvm::BasicBlock::iterator getPoint() const { return Point; } + }; + + /// \brief Returns the current insert point. + InsertPoint saveIP() const { + return InsertPoint(GetInsertBlock(), GetInsertPoint()); + } + + /// \brief Returns the current insert point, clearing it in the process. + InsertPoint saveAndClearIP() { + InsertPoint IP(GetInsertBlock(), GetInsertPoint()); + ClearInsertionPoint(); + return IP; + } + + /// \brief Sets the current insert point to a previously-saved location. + void restoreIP(InsertPoint IP) { + if (IP.isSet()) + SetInsertPoint(IP.getBlock(), IP.getPoint()); + else + ClearInsertionPoint(); + } + + //===--------------------------------------------------------------------===// + // Miscellaneous creation methods. + //===--------------------------------------------------------------------===// + + /// \brief Make a new global variable with initializer type i8* + /// + /// Make a new global variable with an initializer that has array of i8 type + /// filled in with the null terminated string value specified. The new global + /// variable will be marked mergable with any others of the same contents. If + /// Name is specified, it is the name of the global variable created. + Value *CreateGlobalString(StringRef Str, const Twine &Name = ""); + + /// \brief Get a constant value representing either true or false. + ConstantInt *getInt1(bool V) { + return ConstantInt::get(getInt1Ty(), V); + } + + /// \brief Get the constant value for i1 true. + ConstantInt *getTrue() { + return ConstantInt::getTrue(Context); + } + + /// \brief Get the constant value for i1 false. + ConstantInt *getFalse() { + return ConstantInt::getFalse(Context); + } + + /// \brief Get a constant 8-bit value. + ConstantInt *getInt8(uint8_t C) { + return ConstantInt::get(getInt8Ty(), C); + } + + /// \brief Get a constant 16-bit value. + ConstantInt *getInt16(uint16_t C) { + return ConstantInt::get(getInt16Ty(), C); + } + + /// \brief Get a constant 32-bit value. + ConstantInt *getInt32(uint32_t C) { + return ConstantInt::get(getInt32Ty(), C); + } + + /// \brief Get a constant 64-bit value. + ConstantInt *getInt64(uint64_t C) { + return ConstantInt::get(getInt64Ty(), C); + } + + /// \brief Get a constant integer value. + ConstantInt *getInt(const APInt &AI) { + return ConstantInt::get(Context, AI); + } + + //===--------------------------------------------------------------------===// + // Type creation methods + //===--------------------------------------------------------------------===// + + /// \brief Fetch the type representing a single bit + IntegerType *getInt1Ty() { + return Type::getInt1Ty(Context); + } + + /// \brief Fetch the type representing an 8-bit integer. + IntegerType *getInt8Ty() { + return Type::getInt8Ty(Context); + } + + /// \brief Fetch the type representing a 16-bit integer. + IntegerType *getInt16Ty() { + return Type::getInt16Ty(Context); + } + + /// \brief Fetch the type representing a 32-bit integer. + IntegerType *getInt32Ty() { + return Type::getInt32Ty(Context); + } + + /// \brief Fetch the type representing a 64-bit integer. + IntegerType *getInt64Ty() { + return Type::getInt64Ty(Context); + } + + /// \brief Fetch the type representing a 32-bit floating point value. + Type *getFloatTy() { + return Type::getFloatTy(Context); + } + + /// \brief Fetch the type representing a 64-bit floating point value. + Type *getDoubleTy() { + return Type::getDoubleTy(Context); + } + + /// \brief Fetch the type representing void. + Type *getVoidTy() { + return Type::getVoidTy(Context); + } + + /// \brief Fetch the type representing a pointer to an 8-bit integer value. + PointerType *getInt8PtrTy(unsigned AddrSpace = 0) { + return Type::getInt8PtrTy(Context, AddrSpace); + } + + /// \brief Fetch the type representing a pointer to an integer value. + IntegerType* getIntPtrTy(DataLayout *DL, unsigned AddrSpace = 0) { + return DL->getIntPtrType(Context, AddrSpace); + } + + //===--------------------------------------------------------------------===// + // Intrinsic creation methods + //===--------------------------------------------------------------------===// + + /// \brief Create and insert a memset to the specified pointer and the + /// specified value. + /// + /// If the pointer isn't an i8*, it will be converted. If a TBAA tag is + /// specified, it will be added to the instruction. + CallInst *CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, unsigned Align, + bool isVolatile = false, MDNode *TBAATag = 0) { + return CreateMemSet(Ptr, Val, getInt64(Size), Align, isVolatile, TBAATag); + } + + CallInst *CreateMemSet(Value *Ptr, Value *Val, Value *Size, unsigned Align, + bool isVolatile = false, MDNode *TBAATag = 0); + + /// \brief Create and insert a memcpy between the specified pointers. + /// + /// If the pointers aren't i8*, they will be converted. If a TBAA tag is + /// specified, it will be added to the instruction. + CallInst *CreateMemCpy(Value *Dst, Value *Src, uint64_t Size, unsigned Align, + bool isVolatile = false, MDNode *TBAATag = 0, + MDNode *TBAAStructTag = 0) { + return CreateMemCpy(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag, + TBAAStructTag); + } + + CallInst *CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align, + bool isVolatile = false, MDNode *TBAATag = 0, + MDNode *TBAAStructTag = 0); + + /// \brief Create and insert a memmove between the specified + /// pointers. + /// + /// If the pointers aren't i8*, they will be converted. If a TBAA tag is + /// specified, it will be added to the instruction. + CallInst *CreateMemMove(Value *Dst, Value *Src, uint64_t Size, unsigned Align, + bool isVolatile = false, MDNode *TBAATag = 0) { + return CreateMemMove(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag); + } + + CallInst *CreateMemMove(Value *Dst, Value *Src, Value *Size, unsigned Align, + bool isVolatile = false, MDNode *TBAATag = 0); + + /// \brief Create a lifetime.start intrinsic. + /// + /// If the pointer isn't i8* it will be converted. + CallInst *CreateLifetimeStart(Value *Ptr, ConstantInt *Size = 0); + + /// \brief Create a lifetime.end intrinsic. + /// + /// If the pointer isn't i8* it will be converted. + CallInst *CreateLifetimeEnd(Value *Ptr, ConstantInt *Size = 0); + +private: + Value *getCastedInt8PtrValue(Value *Ptr); +}; + +/// \brief This provides a uniform API for creating instructions and inserting +/// them into a basic block: either at the end of a BasicBlock, or at a specific +/// iterator location in a block. +/// +/// Note that the builder does not expose the full generality of LLVM +/// instructions. For access to extra instruction properties, use the mutators +/// (e.g. setVolatile) on the instructions after they have been +/// created. Convenience state exists to specify fast-math flags and fp-math +/// tags. +/// +/// The first template argument handles whether or not to preserve names in the +/// final instruction output. This defaults to on. The second template argument +/// specifies a class to use for creating constants. This defaults to creating +/// minimally folded constants. The fourth template argument allows clients to +/// specify custom insertion hooks that are called on every newly created +/// insertion. +template<bool preserveNames = true, typename T = ConstantFolder, + typename Inserter = IRBuilderDefaultInserter<preserveNames> > +class IRBuilder : public IRBuilderBase, public Inserter { + T Folder; + MDNode *DefaultFPMathTag; + FastMathFlags FMF; +public: + IRBuilder(LLVMContext &C, const T &F, const Inserter &I = Inserter(), + MDNode *FPMathTag = 0) + : IRBuilderBase(C), Inserter(I), Folder(F), DefaultFPMathTag(FPMathTag), + FMF() { + } + + explicit IRBuilder(LLVMContext &C, MDNode *FPMathTag = 0) + : IRBuilderBase(C), Folder(), DefaultFPMathTag(FPMathTag), FMF() { + } + + explicit IRBuilder(BasicBlock *TheBB, const T &F, MDNode *FPMathTag = 0) + : IRBuilderBase(TheBB->getContext()), Folder(F), + DefaultFPMathTag(FPMathTag), FMF() { + SetInsertPoint(TheBB); + } + + explicit IRBuilder(BasicBlock *TheBB, MDNode *FPMathTag = 0) + : IRBuilderBase(TheBB->getContext()), Folder(), + DefaultFPMathTag(FPMathTag), FMF() { + SetInsertPoint(TheBB); + } + + explicit IRBuilder(Instruction *IP, MDNode *FPMathTag = 0) + : IRBuilderBase(IP->getContext()), Folder(), DefaultFPMathTag(FPMathTag), + FMF() { + SetInsertPoint(IP); + SetCurrentDebugLocation(IP->getDebugLoc()); + } + + explicit IRBuilder(Use &U, MDNode *FPMathTag = 0) + : IRBuilderBase(U->getContext()), Folder(), DefaultFPMathTag(FPMathTag), + FMF() { + SetInsertPoint(U); + SetCurrentDebugLocation(cast<Instruction>(U.getUser())->getDebugLoc()); + } + + IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, const T& F, + MDNode *FPMathTag = 0) + : IRBuilderBase(TheBB->getContext()), Folder(F), + DefaultFPMathTag(FPMathTag), FMF() { + SetInsertPoint(TheBB, IP); + } + + IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, MDNode *FPMathTag = 0) + : IRBuilderBase(TheBB->getContext()), Folder(), + DefaultFPMathTag(FPMathTag), FMF() { + SetInsertPoint(TheBB, IP); + } + + /// \brief Get the constant folder being used. + const T &getFolder() { return Folder; } + + /// \brief Get the floating point math metadata being used. + MDNode *getDefaultFPMathTag() const { return DefaultFPMathTag; } + + /// \brief Get the flags to be applied to created floating point ops + FastMathFlags getFastMathFlags() const { return FMF; } + + /// \brief Clear the fast-math flags. + void clearFastMathFlags() { FMF.clear(); } + + /// \brief SetDefaultFPMathTag - Set the floating point math metadata to be used. + void SetDefaultFPMathTag(MDNode *FPMathTag) { DefaultFPMathTag = FPMathTag; } + + /// \brief Set the fast-math flags to be used with generated fp-math operators + void SetFastMathFlags(FastMathFlags NewFMF) { FMF = NewFMF; } + + /// \brief Return true if this builder is configured to actually add the + /// requested names to IR created through it. + bool isNamePreserving() const { return preserveNames; } + + /// \brief Insert and return the specified instruction. + template<typename InstTy> + InstTy *Insert(InstTy *I, const Twine &Name = "") const { + this->InsertHelper(I, Name, BB, InsertPt); + this->SetInstDebugLocation(I); + return I; + } + + /// \brief No-op overload to handle constants. + Constant *Insert(Constant *C, const Twine& = "") const { + return C; + } + + //===--------------------------------------------------------------------===// + // Instruction creation methods: Terminators + //===--------------------------------------------------------------------===// + +private: + /// \brief Helper to add branch weight metadata onto an instruction. + /// \returns The annotated instruction. + template <typename InstTy> + InstTy *addBranchWeights(InstTy *I, MDNode *Weights) { + if (Weights) + I->setMetadata(LLVMContext::MD_prof, Weights); + return I; + } + +public: + /// \brief Create a 'ret void' instruction. + ReturnInst *CreateRetVoid() { + return Insert(ReturnInst::Create(Context)); + } + + /// \brief Create a 'ret <val>' instruction. + ReturnInst *CreateRet(Value *V) { + return Insert(ReturnInst::Create(Context, V)); + } + + /// \brief Create a sequence of N insertvalue instructions, + /// with one Value from the retVals array each, that build a aggregate + /// return value one value at a time, and a ret instruction to return + /// the resulting aggregate value. + /// + /// This is a convenience function for code that uses aggregate return values + /// as a vehicle for having multiple return values. + ReturnInst *CreateAggregateRet(Value *const *retVals, unsigned N) { + Value *V = UndefValue::get(getCurrentFunctionReturnType()); + for (unsigned i = 0; i != N; ++i) + V = CreateInsertValue(V, retVals[i], i, "mrv"); + return Insert(ReturnInst::Create(Context, V)); + } + + /// \brief Create an unconditional 'br label X' instruction. + BranchInst *CreateBr(BasicBlock *Dest) { + return Insert(BranchInst::Create(Dest)); + } + + /// \brief Create a conditional 'br Cond, TrueDest, FalseDest' + /// instruction. + BranchInst *CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, + MDNode *BranchWeights = 0) { + return Insert(addBranchWeights(BranchInst::Create(True, False, Cond), + BranchWeights)); + } + + /// \brief Create a switch instruction with the specified value, default dest, + /// and with a hint for the number of cases that will be added (for efficient + /// allocation). + SwitchInst *CreateSwitch(Value *V, BasicBlock *Dest, unsigned NumCases = 10, + MDNode *BranchWeights = 0) { + return Insert(addBranchWeights(SwitchInst::Create(V, Dest, NumCases), + BranchWeights)); + } + + /// \brief Create an indirect branch instruction with the specified address + /// operand, with an optional hint for the number of destinations that will be + /// added (for efficient allocation). + IndirectBrInst *CreateIndirectBr(Value *Addr, unsigned NumDests = 10) { + return Insert(IndirectBrInst::Create(Addr, NumDests)); + } + + InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest, + BasicBlock *UnwindDest, const Twine &Name = "") { + return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest, + ArrayRef<Value *>()), + Name); + } + InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest, + BasicBlock *UnwindDest, Value *Arg1, + const Twine &Name = "") { + return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest, Arg1), + Name); + } + InvokeInst *CreateInvoke3(Value *Callee, BasicBlock *NormalDest, + BasicBlock *UnwindDest, Value *Arg1, + Value *Arg2, Value *Arg3, + const Twine &Name = "") { + Value *Args[] = { Arg1, Arg2, Arg3 }; + return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest, Args), + Name); + } + /// \brief Create an invoke instruction. + InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest, + BasicBlock *UnwindDest, ArrayRef<Value *> Args, + const Twine &Name = "") { + return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest, Args), + Name); + } + + ResumeInst *CreateResume(Value *Exn) { + return Insert(ResumeInst::Create(Exn)); + } + + UnreachableInst *CreateUnreachable() { + return Insert(new UnreachableInst(Context)); + } + + //===--------------------------------------------------------------------===// + // Instruction creation methods: Binary Operators + //===--------------------------------------------------------------------===// +private: + BinaryOperator *CreateInsertNUWNSWBinOp(BinaryOperator::BinaryOps Opc, + Value *LHS, Value *RHS, + const Twine &Name, + bool HasNUW, bool HasNSW) { + BinaryOperator *BO = Insert(BinaryOperator::Create(Opc, LHS, RHS), Name); + if (HasNUW) BO->setHasNoUnsignedWrap(); + if (HasNSW) BO->setHasNoSignedWrap(); + return BO; + } + + Instruction *AddFPMathAttributes(Instruction *I, + MDNode *FPMathTag, + FastMathFlags FMF) const { + if (!FPMathTag) + FPMathTag = DefaultFPMathTag; + if (FPMathTag) + I->setMetadata(LLVMContext::MD_fpmath, FPMathTag); + I->setFastMathFlags(FMF); + return I; + } +public: + Value *CreateAdd(Value *LHS, Value *RHS, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { + if (Constant *LC = dyn_cast<Constant>(LHS)) + if (Constant *RC = dyn_cast<Constant>(RHS)) + return Insert(Folder.CreateAdd(LC, RC, HasNUW, HasNSW), Name); + return CreateInsertNUWNSWBinOp(Instruction::Add, LHS, RHS, Name, + HasNUW, HasNSW); + } + Value *CreateNSWAdd(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateAdd(LHS, RHS, Name, false, true); + } + Value *CreateNUWAdd(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateAdd(LHS, RHS, Name, true, false); + } + Value *CreateFAdd(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = 0) { + if (Constant *LC = dyn_cast<Constant>(LHS)) + if (Constant *RC = dyn_cast<Constant>(RHS)) + return Insert(Folder.CreateFAdd(LC, RC), Name); + return Insert(AddFPMathAttributes(BinaryOperator::CreateFAdd(LHS, RHS), + FPMathTag, FMF), Name); + } + Value *CreateSub(Value *LHS, Value *RHS, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { + if (Constant *LC = dyn_cast<Constant>(LHS)) + if (Constant *RC = dyn_cast<Constant>(RHS)) + return Insert(Folder.CreateSub(LC, RC), Name); + return CreateInsertNUWNSWBinOp(Instruction::Sub, LHS, RHS, Name, + HasNUW, HasNSW); + } + Value *CreateNSWSub(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateSub(LHS, RHS, Name, false, true); + } + Value *CreateNUWSub(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateSub(LHS, RHS, Name, true, false); + } + Value *CreateFSub(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = 0) { + if (Constant *LC = dyn_cast<Constant>(LHS)) + if (Constant *RC = dyn_cast<Constant>(RHS)) + return Insert(Folder.CreateFSub(LC, RC), Name); + return Insert(AddFPMathAttributes(BinaryOperator::CreateFSub(LHS, RHS), + FPMathTag, FMF), Name); + } + Value *CreateMul(Value *LHS, Value *RHS, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { + if (Constant *LC = dyn_cast<Constant>(LHS)) + if (Constant *RC = dyn_cast<Constant>(RHS)) + return Insert(Folder.CreateMul(LC, RC), Name); + return CreateInsertNUWNSWBinOp(Instruction::Mul, LHS, RHS, Name, + HasNUW, HasNSW); + } + Value *CreateNSWMul(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateMul(LHS, RHS, Name, false, true); + } + Value *CreateNUWMul(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateMul(LHS, RHS, Name, true, false); + } + Value *CreateFMul(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = 0) { + if (Constant *LC = dyn_cast<Constant>(LHS)) + if (Constant *RC = dyn_cast<Constant>(RHS)) + return Insert(Folder.CreateFMul(LC, RC), Name); + return Insert(AddFPMathAttributes(BinaryOperator::CreateFMul(LHS, RHS), + FPMathTag, FMF), Name); + } + Value *CreateUDiv(Value *LHS, Value *RHS, const Twine &Name = "", + bool isExact = false) { + if (Constant *LC = dyn_cast<Constant>(LHS)) + if (Constant *RC = dyn_cast<Constant>(RHS)) + return Insert(Folder.CreateUDiv(LC, RC, isExact), Name); + if (!isExact) + return Insert(BinaryOperator::CreateUDiv(LHS, RHS), Name); + return Insert(BinaryOperator::CreateExactUDiv(LHS, RHS), Name); + } + Value *CreateExactUDiv(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateUDiv(LHS, RHS, Name, true); + } + Value *CreateSDiv(Value *LHS, Value *RHS, const Twine &Name = "", + bool isExact = false) { + if (Constant *LC = dyn_cast<Constant>(LHS)) + if (Constant *RC = dyn_cast<Constant>(RHS)) + return Insert(Folder.CreateSDiv(LC, RC, isExact), Name); + if (!isExact) + return Insert(BinaryOperator::CreateSDiv(LHS, RHS), Name); + return Insert(BinaryOperator::CreateExactSDiv(LHS, RHS), Name); + } + Value *CreateExactSDiv(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateSDiv(LHS, RHS, Name, true); + } + Value *CreateFDiv(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = 0) { + if (Constant *LC = dyn_cast<Constant>(LHS)) + if (Constant *RC = dyn_cast<Constant>(RHS)) + return Insert(Folder.CreateFDiv(LC, RC), Name); + return Insert(AddFPMathAttributes(BinaryOperator::CreateFDiv(LHS, RHS), + FPMathTag, FMF), Name); + } + Value *CreateURem(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast<Constant>(LHS)) + if (Constant *RC = dyn_cast<Constant>(RHS)) + return Insert(Folder.CreateURem(LC, RC), Name); + return Insert(BinaryOperator::CreateURem(LHS, RHS), Name); + } + Value *CreateSRem(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast<Constant>(LHS)) + if (Constant *RC = dyn_cast<Constant>(RHS)) + return Insert(Folder.CreateSRem(LC, RC), Name); + return Insert(BinaryOperator::CreateSRem(LHS, RHS), Name); + } + Value *CreateFRem(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = 0) { + if (Constant *LC = dyn_cast<Constant>(LHS)) + if (Constant *RC = dyn_cast<Constant>(RHS)) + return Insert(Folder.CreateFRem(LC, RC), Name); + return Insert(AddFPMathAttributes(BinaryOperator::CreateFRem(LHS, RHS), + FPMathTag, FMF), Name); + } + + Value *CreateShl(Value *LHS, Value *RHS, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { + if (Constant *LC = dyn_cast<Constant>(LHS)) + if (Constant *RC = dyn_cast<Constant>(RHS)) + return Insert(Folder.CreateShl(LC, RC, HasNUW, HasNSW), Name); + return CreateInsertNUWNSWBinOp(Instruction::Shl, LHS, RHS, Name, + HasNUW, HasNSW); + } + Value *CreateShl(Value *LHS, const APInt &RHS, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { + return CreateShl(LHS, ConstantInt::get(LHS->getType(), RHS), Name, + HasNUW, HasNSW); + } + Value *CreateShl(Value *LHS, uint64_t RHS, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { + return CreateShl(LHS, ConstantInt::get(LHS->getType(), RHS), Name, + HasNUW, HasNSW); + } + + Value *CreateLShr(Value *LHS, Value *RHS, const Twine &Name = "", + bool isExact = false) { + if (Constant *LC = dyn_cast<Constant>(LHS)) + if (Constant *RC = dyn_cast<Constant>(RHS)) + return Insert(Folder.CreateLShr(LC, RC, isExact), Name); + if (!isExact) + return Insert(BinaryOperator::CreateLShr(LHS, RHS), Name); + return Insert(BinaryOperator::CreateExactLShr(LHS, RHS), Name); + } + Value *CreateLShr(Value *LHS, const APInt &RHS, const Twine &Name = "", + bool isExact = false) { + return CreateLShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact); + } + Value *CreateLShr(Value *LHS, uint64_t RHS, const Twine &Name = "", + bool isExact = false) { + return CreateLShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact); + } + + Value *CreateAShr(Value *LHS, Value *RHS, const Twine &Name = "", + bool isExact = false) { + if (Constant *LC = dyn_cast<Constant>(LHS)) + if (Constant *RC = dyn_cast<Constant>(RHS)) + return Insert(Folder.CreateAShr(LC, RC, isExact), Name); + if (!isExact) + return Insert(BinaryOperator::CreateAShr(LHS, RHS), Name); + return Insert(BinaryOperator::CreateExactAShr(LHS, RHS), Name); + } + Value *CreateAShr(Value *LHS, const APInt &RHS, const Twine &Name = "", + bool isExact = false) { + return CreateAShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact); + } + Value *CreateAShr(Value *LHS, uint64_t RHS, const Twine &Name = "", + bool isExact = false) { + return CreateAShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact); + } + + Value *CreateAnd(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *RC = dyn_cast<Constant>(RHS)) { + if (isa<ConstantInt>(RC) && cast<ConstantInt>(RC)->isAllOnesValue()) + return LHS; // LHS & -1 -> LHS + if (Constant *LC = dyn_cast<Constant>(LHS)) + return Insert(Folder.CreateAnd(LC, RC), Name); + } + return Insert(BinaryOperator::CreateAnd(LHS, RHS), Name); + } + Value *CreateAnd(Value *LHS, const APInt &RHS, const Twine &Name = "") { + return CreateAnd(LHS, ConstantInt::get(LHS->getType(), RHS), Name); + } + Value *CreateAnd(Value *LHS, uint64_t RHS, const Twine &Name = "") { + return CreateAnd(LHS, ConstantInt::get(LHS->getType(), RHS), Name); + } + + Value *CreateOr(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *RC = dyn_cast<Constant>(RHS)) { + if (RC->isNullValue()) + return LHS; // LHS | 0 -> LHS + if (Constant *LC = dyn_cast<Constant>(LHS)) + return Insert(Folder.CreateOr(LC, RC), Name); + } + return Insert(BinaryOperator::CreateOr(LHS, RHS), Name); + } + Value *CreateOr(Value *LHS, const APInt &RHS, const Twine &Name = "") { + return CreateOr(LHS, ConstantInt::get(LHS->getType(), RHS), Name); + } + Value *CreateOr(Value *LHS, uint64_t RHS, const Twine &Name = "") { + return CreateOr(LHS, ConstantInt::get(LHS->getType(), RHS), Name); + } + + Value *CreateXor(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast<Constant>(LHS)) + if (Constant *RC = dyn_cast<Constant>(RHS)) + return Insert(Folder.CreateXor(LC, RC), Name); + return Insert(BinaryOperator::CreateXor(LHS, RHS), Name); + } + Value *CreateXor(Value *LHS, const APInt &RHS, const Twine &Name = "") { + return CreateXor(LHS, ConstantInt::get(LHS->getType(), RHS), Name); + } + Value *CreateXor(Value *LHS, uint64_t RHS, const Twine &Name = "") { + return CreateXor(LHS, ConstantInt::get(LHS->getType(), RHS), Name); + } + + Value *CreateBinOp(Instruction::BinaryOps Opc, + Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast<Constant>(LHS)) + if (Constant *RC = dyn_cast<Constant>(RHS)) + return Insert(Folder.CreateBinOp(Opc, LC, RC), Name); + return Insert(BinaryOperator::Create(Opc, LHS, RHS), Name); + } + + Value *CreateNeg(Value *V, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { + if (Constant *VC = dyn_cast<Constant>(V)) + return Insert(Folder.CreateNeg(VC, HasNUW, HasNSW), Name); + BinaryOperator *BO = Insert(BinaryOperator::CreateNeg(V), Name); + if (HasNUW) BO->setHasNoUnsignedWrap(); + if (HasNSW) BO->setHasNoSignedWrap(); + return BO; + } + Value *CreateNSWNeg(Value *V, const Twine &Name = "") { + return CreateNeg(V, Name, false, true); + } + Value *CreateNUWNeg(Value *V, const Twine &Name = "") { + return CreateNeg(V, Name, true, false); + } + Value *CreateFNeg(Value *V, const Twine &Name = "", MDNode *FPMathTag = 0) { + if (Constant *VC = dyn_cast<Constant>(V)) + return Insert(Folder.CreateFNeg(VC), Name); + return Insert(AddFPMathAttributes(BinaryOperator::CreateFNeg(V), + FPMathTag, FMF), Name); + } + Value *CreateNot(Value *V, const Twine &Name = "") { + if (Constant *VC = dyn_cast<Constant>(V)) + return Insert(Folder.CreateNot(VC), Name); + return Insert(BinaryOperator::CreateNot(V), Name); + } + + //===--------------------------------------------------------------------===// + // Instruction creation methods: Memory Instructions + //===--------------------------------------------------------------------===// + + AllocaInst *CreateAlloca(Type *Ty, Value *ArraySize = 0, + const Twine &Name = "") { + return Insert(new AllocaInst(Ty, ArraySize), Name); + } + // \brief Provided to resolve 'CreateLoad(Ptr, "...")' correctly, instead of + // converting the string to 'bool' for the isVolatile parameter. + LoadInst *CreateLoad(Value *Ptr, const char *Name) { + return Insert(new LoadInst(Ptr), Name); + } + LoadInst *CreateLoad(Value *Ptr, const Twine &Name = "") { + return Insert(new LoadInst(Ptr), Name); + } + LoadInst *CreateLoad(Value *Ptr, bool isVolatile, const Twine &Name = "") { + return Insert(new LoadInst(Ptr, 0, isVolatile), Name); + } + StoreInst *CreateStore(Value *Val, Value *Ptr, bool isVolatile = false) { + return Insert(new StoreInst(Val, Ptr, isVolatile)); + } + // \brief Provided to resolve 'CreateAlignedLoad(Ptr, Align, "...")' + // correctly, instead of converting the string to 'bool' for the isVolatile + // parameter. + LoadInst *CreateAlignedLoad(Value *Ptr, unsigned Align, const char *Name) { + LoadInst *LI = CreateLoad(Ptr, Name); + LI->setAlignment(Align); + return LI; + } + LoadInst *CreateAlignedLoad(Value *Ptr, unsigned Align, + const Twine &Name = "") { + LoadInst *LI = CreateLoad(Ptr, Name); + LI->setAlignment(Align); + return LI; + } + LoadInst *CreateAlignedLoad(Value *Ptr, unsigned Align, bool isVolatile, + const Twine &Name = "") { + LoadInst *LI = CreateLoad(Ptr, isVolatile, Name); + LI->setAlignment(Align); + return LI; + } + StoreInst *CreateAlignedStore(Value *Val, Value *Ptr, unsigned Align, + bool isVolatile = false) { + StoreInst *SI = CreateStore(Val, Ptr, isVolatile); + SI->setAlignment(Align); + return SI; + } + FenceInst *CreateFence(AtomicOrdering Ordering, + SynchronizationScope SynchScope = CrossThread) { + return Insert(new FenceInst(Context, Ordering, SynchScope)); + } + AtomicCmpXchgInst *CreateAtomicCmpXchg(Value *Ptr, Value *Cmp, Value *New, + AtomicOrdering Ordering, + SynchronizationScope SynchScope = CrossThread) { + return Insert(new AtomicCmpXchgInst(Ptr, Cmp, New, Ordering, SynchScope)); + } + AtomicRMWInst *CreateAtomicRMW(AtomicRMWInst::BinOp Op, Value *Ptr, Value *Val, + AtomicOrdering Ordering, + SynchronizationScope SynchScope = CrossThread) { + return Insert(new AtomicRMWInst(Op, Ptr, Val, Ordering, SynchScope)); + } + Value *CreateGEP(Value *Ptr, ArrayRef<Value *> IdxList, + const Twine &Name = "") { + if (Constant *PC = dyn_cast<Constant>(Ptr)) { + // Every index must be constant. + size_t i, e; + for (i = 0, e = IdxList.size(); i != e; ++i) + if (!isa<Constant>(IdxList[i])) + break; + if (i == e) + return Insert(Folder.CreateGetElementPtr(PC, IdxList), Name); + } + return Insert(GetElementPtrInst::Create(Ptr, IdxList), Name); + } + Value *CreateInBoundsGEP(Value *Ptr, ArrayRef<Value *> IdxList, + const Twine &Name = "") { + if (Constant *PC = dyn_cast<Constant>(Ptr)) { + // Every index must be constant. + size_t i, e; + for (i = 0, e = IdxList.size(); i != e; ++i) + if (!isa<Constant>(IdxList[i])) + break; + if (i == e) + return Insert(Folder.CreateInBoundsGetElementPtr(PC, IdxList), Name); + } + return Insert(GetElementPtrInst::CreateInBounds(Ptr, IdxList), Name); + } + Value *CreateGEP(Value *Ptr, Value *Idx, const Twine &Name = "") { + if (Constant *PC = dyn_cast<Constant>(Ptr)) + if (Constant *IC = dyn_cast<Constant>(Idx)) + return Insert(Folder.CreateGetElementPtr(PC, IC), Name); + return Insert(GetElementPtrInst::Create(Ptr, Idx), Name); + } + Value *CreateInBoundsGEP(Value *Ptr, Value *Idx, const Twine &Name = "") { + if (Constant *PC = dyn_cast<Constant>(Ptr)) + if (Constant *IC = dyn_cast<Constant>(Idx)) + return Insert(Folder.CreateInBoundsGetElementPtr(PC, IC), Name); + return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idx), Name); + } + Value *CreateConstGEP1_32(Value *Ptr, unsigned Idx0, const Twine &Name = "") { + Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0); + + if (Constant *PC = dyn_cast<Constant>(Ptr)) + return Insert(Folder.CreateGetElementPtr(PC, Idx), Name); + + return Insert(GetElementPtrInst::Create(Ptr, Idx), Name); + } + Value *CreateConstInBoundsGEP1_32(Value *Ptr, unsigned Idx0, + const Twine &Name = "") { + Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0); + + if (Constant *PC = dyn_cast<Constant>(Ptr)) + return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idx), Name); + + return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idx), Name); + } + Value *CreateConstGEP2_32(Value *Ptr, unsigned Idx0, unsigned Idx1, + const Twine &Name = "") { + Value *Idxs[] = { + ConstantInt::get(Type::getInt32Ty(Context), Idx0), + ConstantInt::get(Type::getInt32Ty(Context), Idx1) + }; + + if (Constant *PC = dyn_cast<Constant>(Ptr)) + return Insert(Folder.CreateGetElementPtr(PC, Idxs), Name); + + return Insert(GetElementPtrInst::Create(Ptr, Idxs), Name); + } + Value *CreateConstInBoundsGEP2_32(Value *Ptr, unsigned Idx0, unsigned Idx1, + const Twine &Name = "") { + Value *Idxs[] = { + ConstantInt::get(Type::getInt32Ty(Context), Idx0), + ConstantInt::get(Type::getInt32Ty(Context), Idx1) + }; + + if (Constant *PC = dyn_cast<Constant>(Ptr)) + return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idxs), Name); + + return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idxs), Name); + } + Value *CreateConstGEP1_64(Value *Ptr, uint64_t Idx0, const Twine &Name = "") { + Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0); + + if (Constant *PC = dyn_cast<Constant>(Ptr)) + return Insert(Folder.CreateGetElementPtr(PC, Idx), Name); + + return Insert(GetElementPtrInst::Create(Ptr, Idx), Name); + } + Value *CreateConstInBoundsGEP1_64(Value *Ptr, uint64_t Idx0, + const Twine &Name = "") { + Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0); + + if (Constant *PC = dyn_cast<Constant>(Ptr)) + return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idx), Name); + + return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idx), Name); + } + Value *CreateConstGEP2_64(Value *Ptr, uint64_t Idx0, uint64_t Idx1, + const Twine &Name = "") { + Value *Idxs[] = { + ConstantInt::get(Type::getInt64Ty(Context), Idx0), + ConstantInt::get(Type::getInt64Ty(Context), Idx1) + }; + + if (Constant *PC = dyn_cast<Constant>(Ptr)) + return Insert(Folder.CreateGetElementPtr(PC, Idxs), Name); + + return Insert(GetElementPtrInst::Create(Ptr, Idxs), Name); + } + Value *CreateConstInBoundsGEP2_64(Value *Ptr, uint64_t Idx0, uint64_t Idx1, + const Twine &Name = "") { + Value *Idxs[] = { + ConstantInt::get(Type::getInt64Ty(Context), Idx0), + ConstantInt::get(Type::getInt64Ty(Context), Idx1) + }; + + if (Constant *PC = dyn_cast<Constant>(Ptr)) + return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idxs), Name); + + return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idxs), Name); + } + Value *CreateStructGEP(Value *Ptr, unsigned Idx, const Twine &Name = "") { + return CreateConstInBoundsGEP2_32(Ptr, 0, Idx, Name); + } + + /// \brief Same as CreateGlobalString, but return a pointer with "i8*" type + /// instead of a pointer to array of i8. + Value *CreateGlobalStringPtr(StringRef Str, const Twine &Name = "") { + Value *gv = CreateGlobalString(Str, Name); + Value *zero = ConstantInt::get(Type::getInt32Ty(Context), 0); + Value *Args[] = { zero, zero }; + return CreateInBoundsGEP(gv, Args, Name); + } + + //===--------------------------------------------------------------------===// + // Instruction creation methods: Cast/Conversion Operators + //===--------------------------------------------------------------------===// + + Value *CreateTrunc(Value *V, Type *DestTy, const Twine &Name = "") { + return CreateCast(Instruction::Trunc, V, DestTy, Name); + } + Value *CreateZExt(Value *V, Type *DestTy, const Twine &Name = "") { + return CreateCast(Instruction::ZExt, V, DestTy, Name); + } + Value *CreateSExt(Value *V, Type *DestTy, const Twine &Name = "") { + return CreateCast(Instruction::SExt, V, DestTy, Name); + } + /// \brief Create a ZExt or Trunc from the integer value V to DestTy. Return + /// the value untouched if the type of V is already DestTy. + Value *CreateZExtOrTrunc(Value *V, Type *DestTy, + const Twine &Name = "") { + assert(V->getType()->isIntOrIntVectorTy() && + DestTy->isIntOrIntVectorTy() && + "Can only zero extend/truncate integers!"); + Type *VTy = V->getType(); + if (VTy->getScalarSizeInBits() < DestTy->getScalarSizeInBits()) + return CreateZExt(V, DestTy, Name); + if (VTy->getScalarSizeInBits() > DestTy->getScalarSizeInBits()) + return CreateTrunc(V, DestTy, Name); + return V; + } + /// \brief Create a SExt or Trunc from the integer value V to DestTy. Return + /// the value untouched if the type of V is already DestTy. + Value *CreateSExtOrTrunc(Value *V, Type *DestTy, + const Twine &Name = "") { + assert(V->getType()->isIntOrIntVectorTy() && + DestTy->isIntOrIntVectorTy() && + "Can only sign extend/truncate integers!"); + Type *VTy = V->getType(); + if (VTy->getScalarSizeInBits() < DestTy->getScalarSizeInBits()) + return CreateSExt(V, DestTy, Name); + if (VTy->getScalarSizeInBits() > DestTy->getScalarSizeInBits()) + return CreateTrunc(V, DestTy, Name); + return V; + } + Value *CreateFPToUI(Value *V, Type *DestTy, const Twine &Name = ""){ + return CreateCast(Instruction::FPToUI, V, DestTy, Name); + } + Value *CreateFPToSI(Value *V, Type *DestTy, const Twine &Name = ""){ + return CreateCast(Instruction::FPToSI, V, DestTy, Name); + } + Value *CreateUIToFP(Value *V, Type *DestTy, const Twine &Name = ""){ + return CreateCast(Instruction::UIToFP, V, DestTy, Name); + } + Value *CreateSIToFP(Value *V, Type *DestTy, const Twine &Name = ""){ + return CreateCast(Instruction::SIToFP, V, DestTy, Name); + } + Value *CreateFPTrunc(Value *V, Type *DestTy, + const Twine &Name = "") { + return CreateCast(Instruction::FPTrunc, V, DestTy, Name); + } + Value *CreateFPExt(Value *V, Type *DestTy, const Twine &Name = "") { + return CreateCast(Instruction::FPExt, V, DestTy, Name); + } + Value *CreatePtrToInt(Value *V, Type *DestTy, + const Twine &Name = "") { + return CreateCast(Instruction::PtrToInt, V, DestTy, Name); + } + Value *CreateIntToPtr(Value *V, Type *DestTy, + const Twine &Name = "") { + return CreateCast(Instruction::IntToPtr, V, DestTy, Name); + } + Value *CreateBitCast(Value *V, Type *DestTy, + const Twine &Name = "") { + return CreateCast(Instruction::BitCast, V, DestTy, Name); + } + Value *CreateZExtOrBitCast(Value *V, Type *DestTy, + const Twine &Name = "") { + if (V->getType() == DestTy) + return V; + if (Constant *VC = dyn_cast<Constant>(V)) + return Insert(Folder.CreateZExtOrBitCast(VC, DestTy), Name); + return Insert(CastInst::CreateZExtOrBitCast(V, DestTy), Name); + } + Value *CreateSExtOrBitCast(Value *V, Type *DestTy, + const Twine &Name = "") { + if (V->getType() == DestTy) + return V; + if (Constant *VC = dyn_cast<Constant>(V)) + return Insert(Folder.CreateSExtOrBitCast(VC, DestTy), Name); + return Insert(CastInst::CreateSExtOrBitCast(V, DestTy), Name); + } + Value *CreateTruncOrBitCast(Value *V, Type *DestTy, + const Twine &Name = "") { + if (V->getType() == DestTy) + return V; + if (Constant *VC = dyn_cast<Constant>(V)) + return Insert(Folder.CreateTruncOrBitCast(VC, DestTy), Name); + return Insert(CastInst::CreateTruncOrBitCast(V, DestTy), Name); + } + Value *CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy, + const Twine &Name = "") { + if (V->getType() == DestTy) + return V; + if (Constant *VC = dyn_cast<Constant>(V)) + return Insert(Folder.CreateCast(Op, VC, DestTy), Name); + return Insert(CastInst::Create(Op, V, DestTy), Name); + } + Value *CreatePointerCast(Value *V, Type *DestTy, + const Twine &Name = "") { + if (V->getType() == DestTy) + return V; + if (Constant *VC = dyn_cast<Constant>(V)) + return Insert(Folder.CreatePointerCast(VC, DestTy), Name); + return Insert(CastInst::CreatePointerCast(V, DestTy), Name); + } + Value *CreateIntCast(Value *V, Type *DestTy, bool isSigned, + const Twine &Name = "") { + if (V->getType() == DestTy) + return V; + if (Constant *VC = dyn_cast<Constant>(V)) + return Insert(Folder.CreateIntCast(VC, DestTy, isSigned), Name); + return Insert(CastInst::CreateIntegerCast(V, DestTy, isSigned), Name); + } +private: + // \brief Provided to resolve 'CreateIntCast(Ptr, Ptr, "...")', giving a + // compile time error, instead of converting the string to bool for the + // isSigned parameter. + Value *CreateIntCast(Value *, Type *, const char *) LLVM_DELETED_FUNCTION; +public: + Value *CreateFPCast(Value *V, Type *DestTy, const Twine &Name = "") { + if (V->getType() == DestTy) + return V; + if (Constant *VC = dyn_cast<Constant>(V)) + return Insert(Folder.CreateFPCast(VC, DestTy), Name); + return Insert(CastInst::CreateFPCast(V, DestTy), Name); + } + + //===--------------------------------------------------------------------===// + // Instruction creation methods: Compare Instructions + //===--------------------------------------------------------------------===// + + Value *CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateICmp(ICmpInst::ICMP_EQ, LHS, RHS, Name); + } + Value *CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateICmp(ICmpInst::ICMP_NE, LHS, RHS, Name); + } + Value *CreateICmpUGT(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateICmp(ICmpInst::ICMP_UGT, LHS, RHS, Name); + } + Value *CreateICmpUGE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateICmp(ICmpInst::ICMP_UGE, LHS, RHS, Name); + } + Value *CreateICmpULT(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateICmp(ICmpInst::ICMP_ULT, LHS, RHS, Name); + } + Value *CreateICmpULE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateICmp(ICmpInst::ICMP_ULE, LHS, RHS, Name); + } + Value *CreateICmpSGT(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateICmp(ICmpInst::ICMP_SGT, LHS, RHS, Name); + } + Value *CreateICmpSGE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateICmp(ICmpInst::ICMP_SGE, LHS, RHS, Name); + } + Value *CreateICmpSLT(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateICmp(ICmpInst::ICMP_SLT, LHS, RHS, Name); + } + Value *CreateICmpSLE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateICmp(ICmpInst::ICMP_SLE, LHS, RHS, Name); + } + + Value *CreateFCmpOEQ(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_OEQ, LHS, RHS, Name); + } + Value *CreateFCmpOGT(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_OGT, LHS, RHS, Name); + } + Value *CreateFCmpOGE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_OGE, LHS, RHS, Name); + } + Value *CreateFCmpOLT(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_OLT, LHS, RHS, Name); + } + Value *CreateFCmpOLE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_OLE, LHS, RHS, Name); + } + Value *CreateFCmpONE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_ONE, LHS, RHS, Name); + } + Value *CreateFCmpORD(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_ORD, LHS, RHS, Name); + } + Value *CreateFCmpUNO(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_UNO, LHS, RHS, Name); + } + Value *CreateFCmpUEQ(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_UEQ, LHS, RHS, Name); + } + Value *CreateFCmpUGT(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_UGT, LHS, RHS, Name); + } + Value *CreateFCmpUGE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_UGE, LHS, RHS, Name); + } + Value *CreateFCmpULT(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_ULT, LHS, RHS, Name); + } + Value *CreateFCmpULE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_ULE, LHS, RHS, Name); + } + Value *CreateFCmpUNE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_UNE, LHS, RHS, Name); + } + + Value *CreateICmp(CmpInst::Predicate P, Value *LHS, Value *RHS, + const Twine &Name = "") { + if (Constant *LC = dyn_cast<Constant>(LHS)) + if (Constant *RC = dyn_cast<Constant>(RHS)) + return Insert(Folder.CreateICmp(P, LC, RC), Name); + return Insert(new ICmpInst(P, LHS, RHS), Name); + } + Value *CreateFCmp(CmpInst::Predicate P, Value *LHS, Value *RHS, + const Twine &Name = "") { + if (Constant *LC = dyn_cast<Constant>(LHS)) + if (Constant *RC = dyn_cast<Constant>(RHS)) + return Insert(Folder.CreateFCmp(P, LC, RC), Name); + return Insert(new FCmpInst(P, LHS, RHS), Name); + } + + //===--------------------------------------------------------------------===// + // Instruction creation methods: Other Instructions + //===--------------------------------------------------------------------===// + + PHINode *CreatePHI(Type *Ty, unsigned NumReservedValues, + const Twine &Name = "") { + return Insert(PHINode::Create(Ty, NumReservedValues), Name); + } + + CallInst *CreateCall(Value *Callee, const Twine &Name = "") { + return Insert(CallInst::Create(Callee), Name); + } + CallInst *CreateCall(Value *Callee, Value *Arg, const Twine &Name = "") { + return Insert(CallInst::Create(Callee, Arg), Name); + } + CallInst *CreateCall2(Value *Callee, Value *Arg1, Value *Arg2, + const Twine &Name = "") { + Value *Args[] = { Arg1, Arg2 }; + return Insert(CallInst::Create(Callee, Args), Name); + } + CallInst *CreateCall3(Value *Callee, Value *Arg1, Value *Arg2, Value *Arg3, + const Twine &Name = "") { + Value *Args[] = { Arg1, Arg2, Arg3 }; + return Insert(CallInst::Create(Callee, Args), Name); + } + CallInst *CreateCall4(Value *Callee, Value *Arg1, Value *Arg2, Value *Arg3, + Value *Arg4, const Twine &Name = "") { + Value *Args[] = { Arg1, Arg2, Arg3, Arg4 }; + return Insert(CallInst::Create(Callee, Args), Name); + } + CallInst *CreateCall5(Value *Callee, Value *Arg1, Value *Arg2, Value *Arg3, + Value *Arg4, Value *Arg5, const Twine &Name = "") { + Value *Args[] = { Arg1, Arg2, Arg3, Arg4, Arg5 }; + return Insert(CallInst::Create(Callee, Args), Name); + } + + CallInst *CreateCall(Value *Callee, ArrayRef<Value *> Args, + const Twine &Name = "") { + return Insert(CallInst::Create(Callee, Args), Name); + } + + Value *CreateSelect(Value *C, Value *True, Value *False, + const Twine &Name = "") { + if (Constant *CC = dyn_cast<Constant>(C)) + if (Constant *TC = dyn_cast<Constant>(True)) + if (Constant *FC = dyn_cast<Constant>(False)) + return Insert(Folder.CreateSelect(CC, TC, FC), Name); + return Insert(SelectInst::Create(C, True, False), Name); + } + + VAArgInst *CreateVAArg(Value *List, Type *Ty, const Twine &Name = "") { + return Insert(new VAArgInst(List, Ty), Name); + } + + Value *CreateExtractElement(Value *Vec, Value *Idx, + const Twine &Name = "") { + if (Constant *VC = dyn_cast<Constant>(Vec)) + if (Constant *IC = dyn_cast<Constant>(Idx)) + return Insert(Folder.CreateExtractElement(VC, IC), Name); + return Insert(ExtractElementInst::Create(Vec, Idx), Name); + } + + Value *CreateInsertElement(Value *Vec, Value *NewElt, Value *Idx, + const Twine &Name = "") { + if (Constant *VC = dyn_cast<Constant>(Vec)) + if (Constant *NC = dyn_cast<Constant>(NewElt)) + if (Constant *IC = dyn_cast<Constant>(Idx)) + return Insert(Folder.CreateInsertElement(VC, NC, IC), Name); + return Insert(InsertElementInst::Create(Vec, NewElt, Idx), Name); + } + + Value *CreateShuffleVector(Value *V1, Value *V2, Value *Mask, + const Twine &Name = "") { + if (Constant *V1C = dyn_cast<Constant>(V1)) + if (Constant *V2C = dyn_cast<Constant>(V2)) + if (Constant *MC = dyn_cast<Constant>(Mask)) + return Insert(Folder.CreateShuffleVector(V1C, V2C, MC), Name); + return Insert(new ShuffleVectorInst(V1, V2, Mask), Name); + } + + Value *CreateExtractValue(Value *Agg, + ArrayRef<unsigned> Idxs, + const Twine &Name = "") { + if (Constant *AggC = dyn_cast<Constant>(Agg)) + return Insert(Folder.CreateExtractValue(AggC, Idxs), Name); + return Insert(ExtractValueInst::Create(Agg, Idxs), Name); + } + + Value *CreateInsertValue(Value *Agg, Value *Val, + ArrayRef<unsigned> Idxs, + const Twine &Name = "") { + if (Constant *AggC = dyn_cast<Constant>(Agg)) + if (Constant *ValC = dyn_cast<Constant>(Val)) + return Insert(Folder.CreateInsertValue(AggC, ValC, Idxs), Name); + return Insert(InsertValueInst::Create(Agg, Val, Idxs), Name); + } + + LandingPadInst *CreateLandingPad(Type *Ty, Value *PersFn, unsigned NumClauses, + const Twine &Name = "") { + return Insert(LandingPadInst::Create(Ty, PersFn, NumClauses), Name); + } + + //===--------------------------------------------------------------------===// + // Utility creation methods + //===--------------------------------------------------------------------===// + + /// \brief Return an i1 value testing if \p Arg is null. + Value *CreateIsNull(Value *Arg, const Twine &Name = "") { + return CreateICmpEQ(Arg, Constant::getNullValue(Arg->getType()), + Name); + } + + /// \brief Return an i1 value testing if \p Arg is not null. + Value *CreateIsNotNull(Value *Arg, const Twine &Name = "") { + return CreateICmpNE(Arg, Constant::getNullValue(Arg->getType()), + Name); + } + + /// \brief Return the i64 difference between two pointer values, dividing out + /// the size of the pointed-to objects. + /// + /// This is intended to implement C-style pointer subtraction. As such, the + /// pointers must be appropriately aligned for their element types and + /// pointing into the same object. + Value *CreatePtrDiff(Value *LHS, Value *RHS, const Twine &Name = "") { + assert(LHS->getType() == RHS->getType() && + "Pointer subtraction operand types must match!"); + PointerType *ArgType = cast<PointerType>(LHS->getType()); + Value *LHS_int = CreatePtrToInt(LHS, Type::getInt64Ty(Context)); + Value *RHS_int = CreatePtrToInt(RHS, Type::getInt64Ty(Context)); + Value *Difference = CreateSub(LHS_int, RHS_int); + return CreateExactSDiv(Difference, + ConstantExpr::getSizeOf(ArgType->getElementType()), + Name); + } + + /// \brief Return a vector value that contains \arg V broadcasted to \p + /// NumElts elements. + Value *CreateVectorSplat(unsigned NumElts, Value *V, const Twine &Name = "") { + assert(NumElts > 0 && "Cannot splat to an empty vector!"); + + // First insert it into an undef vector so we can shuffle it. + Type *I32Ty = getInt32Ty(); + Value *Undef = UndefValue::get(VectorType::get(V->getType(), NumElts)); + V = CreateInsertElement(Undef, V, ConstantInt::get(I32Ty, 0), + Name + ".splatinsert"); + + // Shuffle the value across the desired number of elements. + Value *Zeros = ConstantAggregateZero::get(VectorType::get(I32Ty, NumElts)); + return CreateShuffleVector(V, Undef, Zeros, Name + ".splat"); + } +}; + +} + +#endif diff --git a/include/llvm/IR/InlineAsm.h b/include/llvm/IR/InlineAsm.h new file mode 100644 index 0000000..33e4ab8 --- /dev/null +++ b/include/llvm/IR/InlineAsm.h @@ -0,0 +1,309 @@ +//===-- llvm/InlineAsm.h - Class to represent inline asm strings-*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class represents the inline asm strings, which are Value*'s that are +// used as the callee operand of call instructions. InlineAsm's are uniqued +// like constants, and created via InlineAsm::get(...). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_INLINEASM_H +#define LLVM_IR_INLINEASM_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/IR/Value.h" +#include <vector> + +namespace llvm { + +class PointerType; +class FunctionType; +class Module; +struct InlineAsmKeyType; +template<class ValType, class ValRefType, class TypeClass, class ConstantClass, + bool HasLargeKey> +class ConstantUniqueMap; +template<class ConstantClass, class TypeClass, class ValType> +struct ConstantCreator; + +class InlineAsm : public Value { +public: + enum AsmDialect { + AD_ATT, + AD_Intel + }; + +private: + friend struct ConstantCreator<InlineAsm, PointerType, InlineAsmKeyType>; + friend class ConstantUniqueMap<InlineAsmKeyType, const InlineAsmKeyType&, + PointerType, InlineAsm, false>; + + InlineAsm(const InlineAsm &) LLVM_DELETED_FUNCTION; + void operator=(const InlineAsm&) LLVM_DELETED_FUNCTION; + + std::string AsmString, Constraints; + bool HasSideEffects; + bool IsAlignStack; + AsmDialect Dialect; + + InlineAsm(PointerType *Ty, const std::string &AsmString, + const std::string &Constraints, bool hasSideEffects, + bool isAlignStack, AsmDialect asmDialect); + virtual ~InlineAsm(); + + /// When the ConstantUniqueMap merges two types and makes two InlineAsms + /// identical, it destroys one of them with this method. + void destroyConstant(); +public: + + /// InlineAsm::get - Return the specified uniqued inline asm string. + /// + static InlineAsm *get(FunctionType *Ty, StringRef AsmString, + StringRef Constraints, bool hasSideEffects, + bool isAlignStack = false, + AsmDialect asmDialect = AD_ATT); + + bool hasSideEffects() const { return HasSideEffects; } + bool isAlignStack() const { return IsAlignStack; } + AsmDialect getDialect() const { return Dialect; } + + /// getType - InlineAsm's are always pointers. + /// + PointerType *getType() const { + return reinterpret_cast<PointerType*>(Value::getType()); + } + + /// getFunctionType - InlineAsm's are always pointers to functions. + /// + FunctionType *getFunctionType() const; + + const std::string &getAsmString() const { return AsmString; } + const std::string &getConstraintString() const { return Constraints; } + + /// Verify - This static method can be used by the parser to check to see if + /// the specified constraint string is legal for the type. This returns true + /// if legal, false if not. + /// + static bool Verify(FunctionType *Ty, StringRef Constraints); + + // Constraint String Parsing + enum ConstraintPrefix { + isInput, // 'x' + isOutput, // '=x' + isClobber // '~x' + }; + + typedef std::vector<std::string> ConstraintCodeVector; + + struct SubConstraintInfo { + /// MatchingInput - If this is not -1, this is an output constraint where an + /// input constraint is required to match it (e.g. "0"). The value is the + /// constraint number that matches this one (for example, if this is + /// constraint #0 and constraint #4 has the value "0", this will be 4). + signed char MatchingInput; + /// Code - The constraint code, either the register name (in braces) or the + /// constraint letter/number. + ConstraintCodeVector Codes; + /// Default constructor. + SubConstraintInfo() : MatchingInput(-1) {} + }; + + typedef std::vector<SubConstraintInfo> SubConstraintInfoVector; + struct ConstraintInfo; + typedef std::vector<ConstraintInfo> ConstraintInfoVector; + + struct ConstraintInfo { + /// Type - The basic type of the constraint: input/output/clobber + /// + ConstraintPrefix Type; + + /// isEarlyClobber - "&": output operand writes result before inputs are all + /// read. This is only ever set for an output operand. + bool isEarlyClobber; + + /// MatchingInput - If this is not -1, this is an output constraint where an + /// input constraint is required to match it (e.g. "0"). The value is the + /// constraint number that matches this one (for example, if this is + /// constraint #0 and constraint #4 has the value "0", this will be 4). + signed char MatchingInput; + + /// hasMatchingInput - Return true if this is an output constraint that has + /// a matching input constraint. + bool hasMatchingInput() const { return MatchingInput != -1; } + + /// isCommutative - This is set to true for a constraint that is commutative + /// with the next operand. + bool isCommutative; + + /// isIndirect - True if this operand is an indirect operand. This means + /// that the address of the source or destination is present in the call + /// instruction, instead of it being returned or passed in explicitly. This + /// is represented with a '*' in the asm string. + bool isIndirect; + + /// Code - The constraint code, either the register name (in braces) or the + /// constraint letter/number. + ConstraintCodeVector Codes; + + /// isMultipleAlternative - '|': has multiple-alternative constraints. + bool isMultipleAlternative; + + /// multipleAlternatives - If there are multiple alternative constraints, + /// this array will contain them. Otherwise it will be empty. + SubConstraintInfoVector multipleAlternatives; + + /// The currently selected alternative constraint index. + unsigned currentAlternativeIndex; + + ///Default constructor. + ConstraintInfo(); + + /// Copy constructor. + ConstraintInfo(const ConstraintInfo &other); + + /// Parse - Analyze the specified string (e.g. "=*&{eax}") and fill in the + /// fields in this structure. If the constraint string is not understood, + /// return true, otherwise return false. + bool Parse(StringRef Str, ConstraintInfoVector &ConstraintsSoFar); + + /// selectAlternative - Point this constraint to the alternative constraint + /// indicated by the index. + void selectAlternative(unsigned index); + }; + + /// ParseConstraints - Split up the constraint string into the specific + /// constraints and their prefixes. If this returns an empty vector, and if + /// the constraint string itself isn't empty, there was an error parsing. + static ConstraintInfoVector ParseConstraints(StringRef ConstraintString); + + /// ParseConstraints - Parse the constraints of this inlineasm object, + /// returning them the same way that ParseConstraints(str) does. + ConstraintInfoVector ParseConstraints() const { + return ParseConstraints(Constraints); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Value *V) { + return V->getValueID() == Value::InlineAsmVal; + } + + + // These are helper methods for dealing with flags in the INLINEASM SDNode + // in the backend. + + enum { + // Fixed operands on an INLINEASM SDNode. + Op_InputChain = 0, + Op_AsmString = 1, + Op_MDNode = 2, + Op_ExtraInfo = 3, // HasSideEffects, IsAlignStack, AsmDialect. + Op_FirstOperand = 4, + + // Fixed operands on an INLINEASM MachineInstr. + MIOp_AsmString = 0, + MIOp_ExtraInfo = 1, // HasSideEffects, IsAlignStack, AsmDialect. + MIOp_FirstOperand = 2, + + // Interpretation of the MIOp_ExtraInfo bit field. + Extra_HasSideEffects = 1, + Extra_IsAlignStack = 2, + Extra_AsmDialect = 4, + Extra_MayLoad = 8, + Extra_MayStore = 16, + + // Inline asm operands map to multiple SDNode / MachineInstr operands. + // The first operand is an immediate describing the asm operand, the low + // bits is the kind: + Kind_RegUse = 1, // Input register, "r". + Kind_RegDef = 2, // Output register, "=r". + Kind_RegDefEarlyClobber = 3, // Early-clobber output register, "=&r". + Kind_Clobber = 4, // Clobbered register, "~r". + Kind_Imm = 5, // Immediate. + Kind_Mem = 6, // Memory operand, "m". + + Flag_MatchingOperand = 0x80000000 + }; + + static unsigned getFlagWord(unsigned Kind, unsigned NumOps) { + assert(((NumOps << 3) & ~0xffff) == 0 && "Too many inline asm operands!"); + assert(Kind >= Kind_RegUse && Kind <= Kind_Mem && "Invalid Kind"); + return Kind | (NumOps << 3); + } + + /// getFlagWordForMatchingOp - Augment an existing flag word returned by + /// getFlagWord with information indicating that this input operand is tied + /// to a previous output operand. + static unsigned getFlagWordForMatchingOp(unsigned InputFlag, + unsigned MatchedOperandNo) { + assert(MatchedOperandNo <= 0x7fff && "Too big matched operand"); + assert((InputFlag & ~0xffff) == 0 && "High bits already contain data"); + return InputFlag | Flag_MatchingOperand | (MatchedOperandNo << 16); + } + + /// getFlagWordForRegClass - Augment an existing flag word returned by + /// getFlagWord with the required register class for the following register + /// operands. + /// A tied use operand cannot have a register class, use the register class + /// from the def operand instead. + static unsigned getFlagWordForRegClass(unsigned InputFlag, unsigned RC) { + // Store RC + 1, reserve the value 0 to mean 'no register class'. + ++RC; + assert(RC <= 0x7fff && "Too large register class ID"); + assert((InputFlag & ~0xffff) == 0 && "High bits already contain data"); + return InputFlag | (RC << 16); + } + + static unsigned getKind(unsigned Flags) { + return Flags & 7; + } + + static bool isRegDefKind(unsigned Flag){ return getKind(Flag) == Kind_RegDef;} + static bool isImmKind(unsigned Flag) { return getKind(Flag) == Kind_Imm; } + static bool isMemKind(unsigned Flag) { return getKind(Flag) == Kind_Mem; } + static bool isRegDefEarlyClobberKind(unsigned Flag) { + return getKind(Flag) == Kind_RegDefEarlyClobber; + } + static bool isClobberKind(unsigned Flag) { + return getKind(Flag) == Kind_Clobber; + } + + /// getNumOperandRegisters - Extract the number of registers field from the + /// inline asm operand flag. + static unsigned getNumOperandRegisters(unsigned Flag) { + return (Flag & 0xffff) >> 3; + } + + /// isUseOperandTiedToDef - Return true if the flag of the inline asm + /// operand indicates it is an use operand that's matched to a def operand. + static bool isUseOperandTiedToDef(unsigned Flag, unsigned &Idx) { + if ((Flag & Flag_MatchingOperand) == 0) + return false; + Idx = (Flag & ~Flag_MatchingOperand) >> 16; + return true; + } + + /// hasRegClassConstraint - Returns true if the flag contains a register + /// class constraint. Sets RC to the register class ID. + static bool hasRegClassConstraint(unsigned Flag, unsigned &RC) { + if (Flag & Flag_MatchingOperand) + return false; + unsigned High = Flag >> 16; + // getFlagWordForRegClass() uses 0 to mean no register class, and otherwise + // stores RC + 1. + if (!High) + return false; + RC = High - 1; + return true; + } + +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h new file mode 100644 index 0000000..3e6903c --- /dev/null +++ b/include/llvm/IR/InstrTypes.h @@ -0,0 +1,851 @@ +//===-- llvm/InstrTypes.h - Important Instruction subclasses ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines various meta classes of instructions that exist in the VM +// representation. Specific concrete subclasses of these may be found in the +// i*.h files... +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_INSTRTYPES_H +#define LLVM_IR_INSTRTYPES_H + +#include "llvm/ADT/Twine.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/OperandTraits.h" + +namespace llvm { + +class LLVMContext; + +//===----------------------------------------------------------------------===// +// TerminatorInst Class +//===----------------------------------------------------------------------===// + +/// TerminatorInst - Subclasses of this class are all able to terminate a basic +/// block. Thus, these are all the flow control type of operations. +/// +class TerminatorInst : public Instruction { +protected: + TerminatorInst(Type *Ty, Instruction::TermOps iType, + Use *Ops, unsigned NumOps, + Instruction *InsertBefore = 0) + : Instruction(Ty, iType, Ops, NumOps, InsertBefore) {} + + TerminatorInst(Type *Ty, Instruction::TermOps iType, + Use *Ops, unsigned NumOps, BasicBlock *InsertAtEnd) + : Instruction(Ty, iType, Ops, NumOps, InsertAtEnd) {} + + // Out of line virtual method, so the vtable, etc has a home. + ~TerminatorInst(); + + /// Virtual methods - Terminators should overload these and provide inline + /// overrides of non-V methods. + virtual BasicBlock *getSuccessorV(unsigned idx) const = 0; + virtual unsigned getNumSuccessorsV() const = 0; + virtual void setSuccessorV(unsigned idx, BasicBlock *B) = 0; + virtual TerminatorInst *clone_impl() const = 0; +public: + + /// getNumSuccessors - Return the number of successors that this terminator + /// has. + unsigned getNumSuccessors() const { + return getNumSuccessorsV(); + } + + /// getSuccessor - Return the specified successor. + /// + BasicBlock *getSuccessor(unsigned idx) const { + return getSuccessorV(idx); + } + + /// setSuccessor - Update the specified successor to point at the provided + /// block. + void setSuccessor(unsigned idx, BasicBlock *B) { + setSuccessorV(idx, B); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->isTerminator(); + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + + +//===----------------------------------------------------------------------===// +// UnaryInstruction Class +//===----------------------------------------------------------------------===// + +class UnaryInstruction : public Instruction { + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + +protected: + UnaryInstruction(Type *Ty, unsigned iType, Value *V, + Instruction *IB = 0) + : Instruction(Ty, iType, &Op<0>(), 1, IB) { + Op<0>() = V; + } + UnaryInstruction(Type *Ty, unsigned iType, Value *V, BasicBlock *IAE) + : Instruction(Ty, iType, &Op<0>(), 1, IAE) { + Op<0>() = V; + } +public: + // allocate space for exactly one operand + void *operator new(size_t s) { + return User::operator new(s, 1); + } + + // Out of line virtual method, so the vtable, etc has a home. + ~UnaryInstruction(); + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Alloca || + I->getOpcode() == Instruction::Load || + I->getOpcode() == Instruction::VAArg || + I->getOpcode() == Instruction::ExtractValue || + (I->getOpcode() >= CastOpsBegin && I->getOpcode() < CastOpsEnd); + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +template <> +struct OperandTraits<UnaryInstruction> : + public FixedNumOperandTraits<UnaryInstruction, 1> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(UnaryInstruction, Value) + +//===----------------------------------------------------------------------===// +// BinaryOperator Class +//===----------------------------------------------------------------------===// + +class BinaryOperator : public Instruction { + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; +protected: + void init(BinaryOps iType); + BinaryOperator(BinaryOps iType, Value *S1, Value *S2, Type *Ty, + const Twine &Name, Instruction *InsertBefore); + BinaryOperator(BinaryOps iType, Value *S1, Value *S2, Type *Ty, + const Twine &Name, BasicBlock *InsertAtEnd); + virtual BinaryOperator *clone_impl() const LLVM_OVERRIDE; +public: + // allocate space for exactly two operands + void *operator new(size_t s) { + return User::operator new(s, 2); + } + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// Create() - Construct a binary instruction, given the opcode and the two + /// operands. Optionally (if InstBefore is specified) insert the instruction + /// into a BasicBlock right before the specified instruction. The specified + /// Instruction is allowed to be a dereferenced end iterator. + /// + static BinaryOperator *Create(BinaryOps Op, Value *S1, Value *S2, + const Twine &Name = Twine(), + Instruction *InsertBefore = 0); + + /// Create() - Construct a binary instruction, given the opcode and the two + /// operands. Also automatically insert this instruction to the end of the + /// BasicBlock specified. + /// + static BinaryOperator *Create(BinaryOps Op, Value *S1, Value *S2, + const Twine &Name, BasicBlock *InsertAtEnd); + + /// Create* - These methods just forward to Create, and are useful when you + /// statically know what type of instruction you're going to create. These + /// helpers just save some typing. +#define HANDLE_BINARY_INST(N, OPC, CLASS) \ + static BinaryOperator *Create##OPC(Value *V1, Value *V2, \ + const Twine &Name = "") {\ + return Create(Instruction::OPC, V1, V2, Name);\ + } +#include "llvm/IR/Instruction.def" +#define HANDLE_BINARY_INST(N, OPC, CLASS) \ + static BinaryOperator *Create##OPC(Value *V1, Value *V2, \ + const Twine &Name, BasicBlock *BB) {\ + return Create(Instruction::OPC, V1, V2, Name, BB);\ + } +#include "llvm/IR/Instruction.def" +#define HANDLE_BINARY_INST(N, OPC, CLASS) \ + static BinaryOperator *Create##OPC(Value *V1, Value *V2, \ + const Twine &Name, Instruction *I) {\ + return Create(Instruction::OPC, V1, V2, Name, I);\ + } +#include "llvm/IR/Instruction.def" + + static BinaryOperator *CreateNSW(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name = "") { + BinaryOperator *BO = Create(Opc, V1, V2, Name); + BO->setHasNoSignedWrap(true); + return BO; + } + static BinaryOperator *CreateNSW(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name, BasicBlock *BB) { + BinaryOperator *BO = Create(Opc, V1, V2, Name, BB); + BO->setHasNoSignedWrap(true); + return BO; + } + static BinaryOperator *CreateNSW(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name, Instruction *I) { + BinaryOperator *BO = Create(Opc, V1, V2, Name, I); + BO->setHasNoSignedWrap(true); + return BO; + } + + static BinaryOperator *CreateNUW(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name = "") { + BinaryOperator *BO = Create(Opc, V1, V2, Name); + BO->setHasNoUnsignedWrap(true); + return BO; + } + static BinaryOperator *CreateNUW(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name, BasicBlock *BB) { + BinaryOperator *BO = Create(Opc, V1, V2, Name, BB); + BO->setHasNoUnsignedWrap(true); + return BO; + } + static BinaryOperator *CreateNUW(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name, Instruction *I) { + BinaryOperator *BO = Create(Opc, V1, V2, Name, I); + BO->setHasNoUnsignedWrap(true); + return BO; + } + + static BinaryOperator *CreateExact(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name = "") { + BinaryOperator *BO = Create(Opc, V1, V2, Name); + BO->setIsExact(true); + return BO; + } + static BinaryOperator *CreateExact(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name, BasicBlock *BB) { + BinaryOperator *BO = Create(Opc, V1, V2, Name, BB); + BO->setIsExact(true); + return BO; + } + static BinaryOperator *CreateExact(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name, Instruction *I) { + BinaryOperator *BO = Create(Opc, V1, V2, Name, I); + BO->setIsExact(true); + return BO; + } + +#define DEFINE_HELPERS(OPC, NUWNSWEXACT) \ + static BinaryOperator *Create ## NUWNSWEXACT ## OPC \ + (Value *V1, Value *V2, const Twine &Name = "") { \ + return Create ## NUWNSWEXACT(Instruction::OPC, V1, V2, Name); \ + } \ + static BinaryOperator *Create ## NUWNSWEXACT ## OPC \ + (Value *V1, Value *V2, const Twine &Name, BasicBlock *BB) { \ + return Create ## NUWNSWEXACT(Instruction::OPC, V1, V2, Name, BB); \ + } \ + static BinaryOperator *Create ## NUWNSWEXACT ## OPC \ + (Value *V1, Value *V2, const Twine &Name, Instruction *I) { \ + return Create ## NUWNSWEXACT(Instruction::OPC, V1, V2, Name, I); \ + } + + DEFINE_HELPERS(Add, NSW) // CreateNSWAdd + DEFINE_HELPERS(Add, NUW) // CreateNUWAdd + DEFINE_HELPERS(Sub, NSW) // CreateNSWSub + DEFINE_HELPERS(Sub, NUW) // CreateNUWSub + DEFINE_HELPERS(Mul, NSW) // CreateNSWMul + DEFINE_HELPERS(Mul, NUW) // CreateNUWMul + DEFINE_HELPERS(Shl, NSW) // CreateNSWShl + DEFINE_HELPERS(Shl, NUW) // CreateNUWShl + + DEFINE_HELPERS(SDiv, Exact) // CreateExactSDiv + DEFINE_HELPERS(UDiv, Exact) // CreateExactUDiv + DEFINE_HELPERS(AShr, Exact) // CreateExactAShr + DEFINE_HELPERS(LShr, Exact) // CreateExactLShr + +#undef DEFINE_HELPERS + + /// Helper functions to construct and inspect unary operations (NEG and NOT) + /// via binary operators SUB and XOR: + /// + /// CreateNeg, CreateNot - Create the NEG and NOT + /// instructions out of SUB and XOR instructions. + /// + static BinaryOperator *CreateNeg(Value *Op, const Twine &Name = "", + Instruction *InsertBefore = 0); + static BinaryOperator *CreateNeg(Value *Op, const Twine &Name, + BasicBlock *InsertAtEnd); + static BinaryOperator *CreateNSWNeg(Value *Op, const Twine &Name = "", + Instruction *InsertBefore = 0); + static BinaryOperator *CreateNSWNeg(Value *Op, const Twine &Name, + BasicBlock *InsertAtEnd); + static BinaryOperator *CreateNUWNeg(Value *Op, const Twine &Name = "", + Instruction *InsertBefore = 0); + static BinaryOperator *CreateNUWNeg(Value *Op, const Twine &Name, + BasicBlock *InsertAtEnd); + static BinaryOperator *CreateFNeg(Value *Op, const Twine &Name = "", + Instruction *InsertBefore = 0); + static BinaryOperator *CreateFNeg(Value *Op, const Twine &Name, + BasicBlock *InsertAtEnd); + static BinaryOperator *CreateNot(Value *Op, const Twine &Name = "", + Instruction *InsertBefore = 0); + static BinaryOperator *CreateNot(Value *Op, const Twine &Name, + BasicBlock *InsertAtEnd); + + /// isNeg, isFNeg, isNot - Check if the given Value is a + /// NEG, FNeg, or NOT instruction. + /// + static bool isNeg(const Value *V); + static bool isFNeg(const Value *V, bool IgnoreZeroSign=false); + static bool isNot(const Value *V); + + /// getNegArgument, getNotArgument - Helper functions to extract the + /// unary argument of a NEG, FNEG or NOT operation implemented via + /// Sub, FSub, or Xor. + /// + static const Value *getNegArgument(const Value *BinOp); + static Value *getNegArgument( Value *BinOp); + static const Value *getFNegArgument(const Value *BinOp); + static Value *getFNegArgument( Value *BinOp); + static const Value *getNotArgument(const Value *BinOp); + static Value *getNotArgument( Value *BinOp); + + BinaryOps getOpcode() const { + return static_cast<BinaryOps>(Instruction::getOpcode()); + } + + /// swapOperands - Exchange the two operands to this instruction. + /// This instruction is safe to use on any binary instruction and + /// does not modify the semantics of the instruction. If the instruction + /// cannot be reversed (ie, it's a Div), then return true. + /// + bool swapOperands(); + + /// setHasNoUnsignedWrap - Set or clear the nsw flag on this instruction, + /// which must be an operator which supports this flag. See LangRef.html + /// for the meaning of this flag. + void setHasNoUnsignedWrap(bool b = true); + + /// setHasNoSignedWrap - Set or clear the nsw flag on this instruction, + /// which must be an operator which supports this flag. See LangRef.html + /// for the meaning of this flag. + void setHasNoSignedWrap(bool b = true); + + /// setIsExact - Set or clear the exact flag on this instruction, + /// which must be an operator which supports this flag. See LangRef.html + /// for the meaning of this flag. + void setIsExact(bool b = true); + + /// hasNoUnsignedWrap - Determine whether the no unsigned wrap flag is set. + bool hasNoUnsignedWrap() const; + + /// hasNoSignedWrap - Determine whether the no signed wrap flag is set. + bool hasNoSignedWrap() const; + + /// isExact - Determine whether the exact flag is set. + bool isExact() const; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->isBinaryOp(); + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +template <> +struct OperandTraits<BinaryOperator> : + public FixedNumOperandTraits<BinaryOperator, 2> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryOperator, Value) + +//===----------------------------------------------------------------------===// +// CastInst Class +//===----------------------------------------------------------------------===// + +/// CastInst - This is the base class for all instructions that perform data +/// casts. It is simply provided so that instruction category testing +/// can be performed with code like: +/// +/// if (isa<CastInst>(Instr)) { ... } +/// @brief Base class of casting instructions. +class CastInst : public UnaryInstruction { + virtual void anchor() LLVM_OVERRIDE; +protected: + /// @brief Constructor with insert-before-instruction semantics for subclasses + CastInst(Type *Ty, unsigned iType, Value *S, + const Twine &NameStr = "", Instruction *InsertBefore = 0) + : UnaryInstruction(Ty, iType, S, InsertBefore) { + setName(NameStr); + } + /// @brief Constructor with insert-at-end-of-block semantics for subclasses + CastInst(Type *Ty, unsigned iType, Value *S, + const Twine &NameStr, BasicBlock *InsertAtEnd) + : UnaryInstruction(Ty, iType, S, InsertAtEnd) { + setName(NameStr); + } +public: + /// Provides a way to construct any of the CastInst subclasses using an + /// opcode instead of the subclass's constructor. The opcode must be in the + /// CastOps category (Instruction::isCast(opcode) returns true). This + /// constructor has insert-before-instruction semantics to automatically + /// insert the new CastInst before InsertBefore (if it is non-null). + /// @brief Construct any of the CastInst subclasses + static CastInst *Create( + Instruction::CastOps, ///< The opcode of the cast instruction + Value *S, ///< The value to be casted (operand 0) + Type *Ty, ///< The type to which cast should be made + const Twine &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + /// Provides a way to construct any of the CastInst subclasses using an + /// opcode instead of the subclass's constructor. The opcode must be in the + /// CastOps category. This constructor has insert-at-end-of-block semantics + /// to automatically insert the new CastInst at the end of InsertAtEnd (if + /// its non-null). + /// @brief Construct any of the CastInst subclasses + static CastInst *Create( + Instruction::CastOps, ///< The opcode for the cast instruction + Value *S, ///< The value to be casted (operand 0) + Type *Ty, ///< The type to which operand is casted + const Twine &Name, ///< The name for the instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Create a ZExt or BitCast cast instruction + static CastInst *CreateZExtOrBitCast( + Value *S, ///< The value to be casted (operand 0) + Type *Ty, ///< The type to which cast should be made + const Twine &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + + /// @brief Create a ZExt or BitCast cast instruction + static CastInst *CreateZExtOrBitCast( + Value *S, ///< The value to be casted (operand 0) + Type *Ty, ///< The type to which operand is casted + const Twine &Name, ///< The name for the instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Create a SExt or BitCast cast instruction + static CastInst *CreateSExtOrBitCast( + Value *S, ///< The value to be casted (operand 0) + Type *Ty, ///< The type to which cast should be made + const Twine &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + + /// @brief Create a SExt or BitCast cast instruction + static CastInst *CreateSExtOrBitCast( + Value *S, ///< The value to be casted (operand 0) + Type *Ty, ///< The type to which operand is casted + const Twine &Name, ///< The name for the instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Create a BitCast or a PtrToInt cast instruction + static CastInst *CreatePointerCast( + Value *S, ///< The pointer value to be casted (operand 0) + Type *Ty, ///< The type to which operand is casted + const Twine &Name, ///< The name for the instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Create a BitCast or a PtrToInt cast instruction + static CastInst *CreatePointerCast( + Value *S, ///< The pointer value to be casted (operand 0) + Type *Ty, ///< The type to which cast should be made + const Twine &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + + /// @brief Create a ZExt, BitCast, or Trunc for int -> int casts. + static CastInst *CreateIntegerCast( + Value *S, ///< The pointer value to be casted (operand 0) + Type *Ty, ///< The type to which cast should be made + bool isSigned, ///< Whether to regard S as signed or not + const Twine &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + + /// @brief Create a ZExt, BitCast, or Trunc for int -> int casts. + static CastInst *CreateIntegerCast( + Value *S, ///< The integer value to be casted (operand 0) + Type *Ty, ///< The integer type to which operand is casted + bool isSigned, ///< Whether to regard S as signed or not + const Twine &Name, ///< The name for the instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Create an FPExt, BitCast, or FPTrunc for fp -> fp casts + static CastInst *CreateFPCast( + Value *S, ///< The floating point value to be casted + Type *Ty, ///< The floating point type to cast to + const Twine &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + + /// @brief Create an FPExt, BitCast, or FPTrunc for fp -> fp casts + static CastInst *CreateFPCast( + Value *S, ///< The floating point value to be casted + Type *Ty, ///< The floating point type to cast to + const Twine &Name, ///< The name for the instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Create a Trunc or BitCast cast instruction + static CastInst *CreateTruncOrBitCast( + Value *S, ///< The value to be casted (operand 0) + Type *Ty, ///< The type to which cast should be made + const Twine &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + + /// @brief Create a Trunc or BitCast cast instruction + static CastInst *CreateTruncOrBitCast( + Value *S, ///< The value to be casted (operand 0) + Type *Ty, ///< The type to which operand is casted + const Twine &Name, ///< The name for the instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Check whether it is valid to call getCastOpcode for these types. + static bool isCastable( + Type *SrcTy, ///< The Type from which the value should be cast. + Type *DestTy ///< The Type to which the value should be cast. + ); + + /// Returns the opcode necessary to cast Val into Ty using usual casting + /// rules. + /// @brief Infer the opcode for cast operand and type + static Instruction::CastOps getCastOpcode( + const Value *Val, ///< The value to cast + bool SrcIsSigned, ///< Whether to treat the source as signed + Type *Ty, ///< The Type to which the value should be casted + bool DstIsSigned ///< Whether to treate the dest. as signed + ); + + /// There are several places where we need to know if a cast instruction + /// only deals with integer source and destination types. To simplify that + /// logic, this method is provided. + /// @returns true iff the cast has only integral typed operand and dest type. + /// @brief Determine if this is an integer-only cast. + bool isIntegerCast() const; + + /// A lossless cast is one that does not alter the basic value. It implies + /// a no-op cast but is more stringent, preventing things like int->float, + /// long->double, or int->ptr. + /// @returns true iff the cast is lossless. + /// @brief Determine if this is a lossless cast. + bool isLosslessCast() const; + + /// A no-op cast is one that can be effected without changing any bits. + /// It implies that the source and destination types are the same size. The + /// IntPtrTy argument is used to make accurate determinations for casts + /// involving Integer and Pointer types. They are no-op casts if the integer + /// is the same size as the pointer. However, pointer size varies with + /// platform. Generally, the result of DataLayout::getIntPtrType() should be + /// passed in. If that's not available, use Type::Int64Ty, which will make + /// the isNoopCast call conservative. + /// @brief Determine if the described cast is a no-op cast. + static bool isNoopCast( + Instruction::CastOps Opcode, ///< Opcode of cast + Type *SrcTy, ///< SrcTy of cast + Type *DstTy, ///< DstTy of cast + Type *IntPtrTy ///< Integer type corresponding to Ptr types, or null + ); + + /// @brief Determine if this cast is a no-op cast. + bool isNoopCast( + Type *IntPtrTy ///< Integer type corresponding to pointer + ) const; + + /// Determine how a pair of casts can be eliminated, if they can be at all. + /// This is a helper function for both CastInst and ConstantExpr. + /// @returns 0 if the CastInst pair can't be eliminated, otherwise + /// returns Instruction::CastOps value for a cast that can replace + /// the pair, casting SrcTy to DstTy. + /// @brief Determine if a cast pair is eliminable + static unsigned isEliminableCastPair( + Instruction::CastOps firstOpcode, ///< Opcode of first cast + Instruction::CastOps secondOpcode, ///< Opcode of second cast + Type *SrcTy, ///< SrcTy of 1st cast + Type *MidTy, ///< DstTy of 1st cast & SrcTy of 2nd cast + Type *DstTy, ///< DstTy of 2nd cast + Type *SrcIntPtrTy, ///< Integer type corresponding to Ptr SrcTy, or null + Type *MidIntPtrTy, ///< Integer type corresponding to Ptr MidTy, or null + Type *DstIntPtrTy ///< Integer type corresponding to Ptr DstTy, or null + ); + + /// @brief Return the opcode of this CastInst + Instruction::CastOps getOpcode() const { + return Instruction::CastOps(Instruction::getOpcode()); + } + + /// @brief Return the source type, as a convenience + Type* getSrcTy() const { return getOperand(0)->getType(); } + /// @brief Return the destination type, as a convenience + Type* getDestTy() const { return getType(); } + + /// This method can be used to determine if a cast from S to DstTy using + /// Opcode op is valid or not. + /// @returns true iff the proposed cast is valid. + /// @brief Determine if a cast is valid without creating one. + static bool castIsValid(Instruction::CastOps op, Value *S, Type *DstTy); + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->isCast(); + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// CmpInst Class +//===----------------------------------------------------------------------===// + +/// This class is the base class for the comparison instructions. +/// @brief Abstract base class of comparison instructions. +class CmpInst : public Instruction { + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + CmpInst() LLVM_DELETED_FUNCTION; +protected: + CmpInst(Type *ty, Instruction::OtherOps op, unsigned short pred, + Value *LHS, Value *RHS, const Twine &Name = "", + Instruction *InsertBefore = 0); + + CmpInst(Type *ty, Instruction::OtherOps op, unsigned short pred, + Value *LHS, Value *RHS, const Twine &Name, + BasicBlock *InsertAtEnd); + + virtual void anchor() LLVM_OVERRIDE; // Out of line virtual method. +public: + /// This enumeration lists the possible predicates for CmpInst subclasses. + /// Values in the range 0-31 are reserved for FCmpInst, while values in the + /// range 32-64 are reserved for ICmpInst. This is necessary to ensure the + /// predicate values are not overlapping between the classes. + enum Predicate { + // Opcode U L G E Intuitive operation + FCMP_FALSE = 0, ///< 0 0 0 0 Always false (always folded) + FCMP_OEQ = 1, ///< 0 0 0 1 True if ordered and equal + FCMP_OGT = 2, ///< 0 0 1 0 True if ordered and greater than + FCMP_OGE = 3, ///< 0 0 1 1 True if ordered and greater than or equal + FCMP_OLT = 4, ///< 0 1 0 0 True if ordered and less than + FCMP_OLE = 5, ///< 0 1 0 1 True if ordered and less than or equal + FCMP_ONE = 6, ///< 0 1 1 0 True if ordered and operands are unequal + FCMP_ORD = 7, ///< 0 1 1 1 True if ordered (no nans) + FCMP_UNO = 8, ///< 1 0 0 0 True if unordered: isnan(X) | isnan(Y) + FCMP_UEQ = 9, ///< 1 0 0 1 True if unordered or equal + FCMP_UGT = 10, ///< 1 0 1 0 True if unordered or greater than + FCMP_UGE = 11, ///< 1 0 1 1 True if unordered, greater than, or equal + FCMP_ULT = 12, ///< 1 1 0 0 True if unordered or less than + FCMP_ULE = 13, ///< 1 1 0 1 True if unordered, less than, or equal + FCMP_UNE = 14, ///< 1 1 1 0 True if unordered or not equal + FCMP_TRUE = 15, ///< 1 1 1 1 Always true (always folded) + FIRST_FCMP_PREDICATE = FCMP_FALSE, + LAST_FCMP_PREDICATE = FCMP_TRUE, + BAD_FCMP_PREDICATE = FCMP_TRUE + 1, + ICMP_EQ = 32, ///< equal + ICMP_NE = 33, ///< not equal + ICMP_UGT = 34, ///< unsigned greater than + ICMP_UGE = 35, ///< unsigned greater or equal + ICMP_ULT = 36, ///< unsigned less than + ICMP_ULE = 37, ///< unsigned less or equal + ICMP_SGT = 38, ///< signed greater than + ICMP_SGE = 39, ///< signed greater or equal + ICMP_SLT = 40, ///< signed less than + ICMP_SLE = 41, ///< signed less or equal + FIRST_ICMP_PREDICATE = ICMP_EQ, + LAST_ICMP_PREDICATE = ICMP_SLE, + BAD_ICMP_PREDICATE = ICMP_SLE + 1 + }; + + // allocate space for exactly two operands + void *operator new(size_t s) { + return User::operator new(s, 2); + } + /// Construct a compare instruction, given the opcode, the predicate and + /// the two operands. Optionally (if InstBefore is specified) insert the + /// instruction into a BasicBlock right before the specified instruction. + /// The specified Instruction is allowed to be a dereferenced end iterator. + /// @brief Create a CmpInst + static CmpInst *Create(OtherOps Op, + unsigned short predicate, Value *S1, + Value *S2, const Twine &Name = "", + Instruction *InsertBefore = 0); + + /// Construct a compare instruction, given the opcode, the predicate and the + /// two operands. Also automatically insert this instruction to the end of + /// the BasicBlock specified. + /// @brief Create a CmpInst + static CmpInst *Create(OtherOps Op, unsigned short predicate, Value *S1, + Value *S2, const Twine &Name, BasicBlock *InsertAtEnd); + + /// @brief Get the opcode casted to the right type + OtherOps getOpcode() const { + return static_cast<OtherOps>(Instruction::getOpcode()); + } + + /// @brief Return the predicate for this instruction. + Predicate getPredicate() const { + return Predicate(getSubclassDataFromInstruction()); + } + + /// @brief Set the predicate for this instruction to the specified value. + void setPredicate(Predicate P) { setInstructionSubclassData(P); } + + static bool isFPPredicate(Predicate P) { + return P >= FIRST_FCMP_PREDICATE && P <= LAST_FCMP_PREDICATE; + } + + static bool isIntPredicate(Predicate P) { + return P >= FIRST_ICMP_PREDICATE && P <= LAST_ICMP_PREDICATE; + } + + bool isFPPredicate() const { return isFPPredicate(getPredicate()); } + bool isIntPredicate() const { return isIntPredicate(getPredicate()); } + + + /// For example, EQ -> NE, UGT -> ULE, SLT -> SGE, + /// OEQ -> UNE, UGT -> OLE, OLT -> UGE, etc. + /// @returns the inverse predicate for the instruction's current predicate. + /// @brief Return the inverse of the instruction's predicate. + Predicate getInversePredicate() const { + return getInversePredicate(getPredicate()); + } + + /// For example, EQ -> NE, UGT -> ULE, SLT -> SGE, + /// OEQ -> UNE, UGT -> OLE, OLT -> UGE, etc. + /// @returns the inverse predicate for predicate provided in \p pred. + /// @brief Return the inverse of a given predicate + static Predicate getInversePredicate(Predicate pred); + + /// For example, EQ->EQ, SLE->SGE, ULT->UGT, + /// OEQ->OEQ, ULE->UGE, OLT->OGT, etc. + /// @returns the predicate that would be the result of exchanging the two + /// operands of the CmpInst instruction without changing the result + /// produced. + /// @brief Return the predicate as if the operands were swapped + Predicate getSwappedPredicate() const { + return getSwappedPredicate(getPredicate()); + } + + /// This is a static version that you can use without an instruction + /// available. + /// @brief Return the predicate as if the operands were swapped. + static Predicate getSwappedPredicate(Predicate pred); + + /// @brief Provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// This is just a convenience that dispatches to the subclasses. + /// @brief Swap the operands and adjust predicate accordingly to retain + /// the same comparison. + void swapOperands(); + + /// This is just a convenience that dispatches to the subclasses. + /// @brief Determine if this CmpInst is commutative. + bool isCommutative() const; + + /// This is just a convenience that dispatches to the subclasses. + /// @brief Determine if this is an equals/not equals predicate. + bool isEquality() const; + + /// @returns true if the comparison is signed, false otherwise. + /// @brief Determine if this instruction is using a signed comparison. + bool isSigned() const { + return isSigned(getPredicate()); + } + + /// @returns true if the comparison is unsigned, false otherwise. + /// @brief Determine if this instruction is using an unsigned comparison. + bool isUnsigned() const { + return isUnsigned(getPredicate()); + } + + /// This is just a convenience. + /// @brief Determine if this is true when both operands are the same. + bool isTrueWhenEqual() const { + return isTrueWhenEqual(getPredicate()); + } + + /// This is just a convenience. + /// @brief Determine if this is false when both operands are the same. + bool isFalseWhenEqual() const { + return isFalseWhenEqual(getPredicate()); + } + + /// @returns true if the predicate is unsigned, false otherwise. + /// @brief Determine if the predicate is an unsigned operation. + static bool isUnsigned(unsigned short predicate); + + /// @returns true if the predicate is signed, false otherwise. + /// @brief Determine if the predicate is an signed operation. + static bool isSigned(unsigned short predicate); + + /// @brief Determine if the predicate is an ordered operation. + static bool isOrdered(unsigned short predicate); + + /// @brief Determine if the predicate is an unordered operation. + static bool isUnordered(unsigned short predicate); + + /// Determine if the predicate is true when comparing a value with itself. + static bool isTrueWhenEqual(unsigned short predicate); + + /// Determine if the predicate is false when comparing a value with itself. + static bool isFalseWhenEqual(unsigned short predicate); + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::ICmp || + I->getOpcode() == Instruction::FCmp; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } + + /// @brief Create a result type for fcmp/icmp + static Type* makeCmpResultType(Type* opnd_type) { + if (VectorType* vt = dyn_cast<VectorType>(opnd_type)) { + return VectorType::get(Type::getInt1Ty(opnd_type->getContext()), + vt->getNumElements()); + } + return Type::getInt1Ty(opnd_type->getContext()); + } +private: + // Shadow Value::setValueSubclassData with a private forwarding method so that + // subclasses cannot accidentally use it. + void setValueSubclassData(unsigned short D) { + Value::setValueSubclassData(D); + } +}; + + +// FIXME: these are redundant if CmpInst < BinaryOperator +template <> +struct OperandTraits<CmpInst> : public FixedNumOperandTraits<CmpInst, 2> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CmpInst, Value) + +} // End llvm namespace + +#endif diff --git a/include/llvm/IR/Instruction.def b/include/llvm/IR/Instruction.def new file mode 100644 index 0000000..e59a052 --- /dev/null +++ b/include/llvm/IR/Instruction.def @@ -0,0 +1,199 @@ +//===-- llvm/Instruction.def - File that describes Instructions -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains descriptions of the various LLVM instructions. This is +// used as a central place for enumerating the different instructions and +// should eventually be the place to put comments about the instructions. +// +//===----------------------------------------------------------------------===// + +// NOTE: NO INCLUDE GUARD DESIRED! + +// Provide definitions of macros so that users of this file do not have to +// define everything to use it... +// +#ifndef FIRST_TERM_INST +#define FIRST_TERM_INST(num) +#endif +#ifndef HANDLE_TERM_INST +#ifndef HANDLE_INST +#define HANDLE_TERM_INST(num, opcode, Class) +#else +#define HANDLE_TERM_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) +#endif +#endif +#ifndef LAST_TERM_INST +#define LAST_TERM_INST(num) +#endif + +#ifndef FIRST_BINARY_INST +#define FIRST_BINARY_INST(num) +#endif +#ifndef HANDLE_BINARY_INST +#ifndef HANDLE_INST +#define HANDLE_BINARY_INST(num, opcode, instclass) +#else +#define HANDLE_BINARY_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) +#endif +#endif +#ifndef LAST_BINARY_INST +#define LAST_BINARY_INST(num) +#endif + +#ifndef FIRST_MEMORY_INST +#define FIRST_MEMORY_INST(num) +#endif +#ifndef HANDLE_MEMORY_INST +#ifndef HANDLE_INST +#define HANDLE_MEMORY_INST(num, opcode, Class) +#else +#define HANDLE_MEMORY_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) +#endif +#endif +#ifndef LAST_MEMORY_INST +#define LAST_MEMORY_INST(num) +#endif + +#ifndef FIRST_CAST_INST +#define FIRST_CAST_INST(num) +#endif +#ifndef HANDLE_CAST_INST +#ifndef HANDLE_INST +#define HANDLE_CAST_INST(num, opcode, Class) +#else +#define HANDLE_CAST_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) +#endif +#endif +#ifndef LAST_CAST_INST +#define LAST_CAST_INST(num) +#endif + +#ifndef FIRST_OTHER_INST +#define FIRST_OTHER_INST(num) +#endif +#ifndef HANDLE_OTHER_INST +#ifndef HANDLE_INST +#define HANDLE_OTHER_INST(num, opcode, Class) +#else +#define HANDLE_OTHER_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) +#endif +#endif +#ifndef LAST_OTHER_INST +#define LAST_OTHER_INST(num) +#endif + + +// Terminator Instructions - These instructions are used to terminate a basic +// block of the program. Every basic block must end with one of these +// instructions for it to be a well formed basic block. +// + FIRST_TERM_INST ( 1) +HANDLE_TERM_INST ( 1, Ret , ReturnInst) +HANDLE_TERM_INST ( 2, Br , BranchInst) +HANDLE_TERM_INST ( 3, Switch , SwitchInst) +HANDLE_TERM_INST ( 4, IndirectBr , IndirectBrInst) +HANDLE_TERM_INST ( 5, Invoke , InvokeInst) +HANDLE_TERM_INST ( 6, Resume , ResumeInst) +HANDLE_TERM_INST ( 7, Unreachable, UnreachableInst) + LAST_TERM_INST ( 7) + +// Standard binary operators... + FIRST_BINARY_INST( 8) +HANDLE_BINARY_INST( 8, Add , BinaryOperator) +HANDLE_BINARY_INST( 9, FAdd , BinaryOperator) +HANDLE_BINARY_INST(10, Sub , BinaryOperator) +HANDLE_BINARY_INST(11, FSub , BinaryOperator) +HANDLE_BINARY_INST(12, Mul , BinaryOperator) +HANDLE_BINARY_INST(13, FMul , BinaryOperator) +HANDLE_BINARY_INST(14, UDiv , BinaryOperator) +HANDLE_BINARY_INST(15, SDiv , BinaryOperator) +HANDLE_BINARY_INST(16, FDiv , BinaryOperator) +HANDLE_BINARY_INST(17, URem , BinaryOperator) +HANDLE_BINARY_INST(18, SRem , BinaryOperator) +HANDLE_BINARY_INST(19, FRem , BinaryOperator) + +// Logical operators (integer operands) +HANDLE_BINARY_INST(20, Shl , BinaryOperator) // Shift left (logical) +HANDLE_BINARY_INST(21, LShr , BinaryOperator) // Shift right (logical) +HANDLE_BINARY_INST(22, AShr , BinaryOperator) // Shift right (arithmetic) +HANDLE_BINARY_INST(23, And , BinaryOperator) +HANDLE_BINARY_INST(24, Or , BinaryOperator) +HANDLE_BINARY_INST(25, Xor , BinaryOperator) + LAST_BINARY_INST(25) + +// Memory operators... + FIRST_MEMORY_INST(26) +HANDLE_MEMORY_INST(26, Alloca, AllocaInst) // Stack management +HANDLE_MEMORY_INST(27, Load , LoadInst ) // Memory manipulation instrs +HANDLE_MEMORY_INST(28, Store , StoreInst ) +HANDLE_MEMORY_INST(29, GetElementPtr, GetElementPtrInst) +HANDLE_MEMORY_INST(30, Fence , FenceInst ) +HANDLE_MEMORY_INST(31, AtomicCmpXchg , AtomicCmpXchgInst ) +HANDLE_MEMORY_INST(32, AtomicRMW , AtomicRMWInst ) + LAST_MEMORY_INST(32) + +// Cast operators ... +// NOTE: The order matters here because CastInst::isEliminableCastPair +// NOTE: (see Instructions.cpp) encodes a table based on this ordering. + FIRST_CAST_INST(33) +HANDLE_CAST_INST(33, Trunc , TruncInst ) // Truncate integers +HANDLE_CAST_INST(34, ZExt , ZExtInst ) // Zero extend integers +HANDLE_CAST_INST(35, SExt , SExtInst ) // Sign extend integers +HANDLE_CAST_INST(36, FPToUI , FPToUIInst ) // floating point -> UInt +HANDLE_CAST_INST(37, FPToSI , FPToSIInst ) // floating point -> SInt +HANDLE_CAST_INST(38, UIToFP , UIToFPInst ) // UInt -> floating point +HANDLE_CAST_INST(39, SIToFP , SIToFPInst ) // SInt -> floating point +HANDLE_CAST_INST(40, FPTrunc , FPTruncInst ) // Truncate floating point +HANDLE_CAST_INST(41, FPExt , FPExtInst ) // Extend floating point +HANDLE_CAST_INST(42, PtrToInt, PtrToIntInst) // Pointer -> Integer +HANDLE_CAST_INST(43, IntToPtr, IntToPtrInst) // Integer -> Pointer +HANDLE_CAST_INST(44, BitCast , BitCastInst ) // Type cast + LAST_CAST_INST(44) + +// Other operators... + FIRST_OTHER_INST(45) +HANDLE_OTHER_INST(45, ICmp , ICmpInst ) // Integer comparison instruction +HANDLE_OTHER_INST(46, FCmp , FCmpInst ) // Floating point comparison instr. +HANDLE_OTHER_INST(47, PHI , PHINode ) // PHI node instruction +HANDLE_OTHER_INST(48, Call , CallInst ) // Call a function +HANDLE_OTHER_INST(49, Select , SelectInst ) // select instruction +HANDLE_OTHER_INST(50, UserOp1, Instruction) // May be used internally in a pass +HANDLE_OTHER_INST(51, UserOp2, Instruction) // Internal to passes only +HANDLE_OTHER_INST(52, VAArg , VAArgInst ) // vaarg instruction +HANDLE_OTHER_INST(53, ExtractElement, ExtractElementInst)// extract from vector +HANDLE_OTHER_INST(54, InsertElement, InsertElementInst) // insert into vector +HANDLE_OTHER_INST(55, ShuffleVector, ShuffleVectorInst) // shuffle two vectors. +HANDLE_OTHER_INST(56, ExtractValue, ExtractValueInst)// extract from aggregate +HANDLE_OTHER_INST(57, InsertValue, InsertValueInst) // insert into aggregate +HANDLE_OTHER_INST(58, LandingPad, LandingPadInst) // Landing pad instruction. + LAST_OTHER_INST(58) + +#undef FIRST_TERM_INST +#undef HANDLE_TERM_INST +#undef LAST_TERM_INST + +#undef FIRST_BINARY_INST +#undef HANDLE_BINARY_INST +#undef LAST_BINARY_INST + +#undef FIRST_MEMORY_INST +#undef HANDLE_MEMORY_INST +#undef LAST_MEMORY_INST + +#undef FIRST_CAST_INST +#undef HANDLE_CAST_INST +#undef LAST_CAST_INST + +#undef FIRST_OTHER_INST +#undef HANDLE_OTHER_INST +#undef LAST_OTHER_INST + +#ifdef HANDLE_INST +#undef HANDLE_INST +#endif diff --git a/include/llvm/IR/Instruction.h b/include/llvm/IR/Instruction.h new file mode 100644 index 0000000..5721d8f --- /dev/null +++ b/include/llvm/IR/Instruction.h @@ -0,0 +1,467 @@ +//===-- llvm/Instruction.h - Instruction class definition -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the Instruction class, which is the +// base class for all of the LLVM instructions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_INSTRUCTION_H +#define LLVM_IR_INSTRUCTION_H + +#include "llvm/ADT/ilist_node.h" +#include "llvm/IR/User.h" +#include "llvm/Support/DebugLoc.h" + +namespace llvm { + +class FastMathFlags; +class LLVMContext; +class MDNode; + +template<typename ValueSubClass, typename ItemParentClass> + class SymbolTableListTraits; + +class Instruction : public User, public ilist_node<Instruction> { + void operator=(const Instruction &) LLVM_DELETED_FUNCTION; + Instruction(const Instruction &) LLVM_DELETED_FUNCTION; + + BasicBlock *Parent; + DebugLoc DbgLoc; // 'dbg' Metadata cache. + + enum { + /// HasMetadataBit - This is a bit stored in the SubClassData field which + /// indicates whether this instruction has metadata attached to it or not. + HasMetadataBit = 1 << 15 + }; +public: + // Out of line virtual method, so the vtable, etc has a home. + ~Instruction(); + + /// use_back - Specialize the methods defined in Value, as we know that an + /// instruction can only be used by other instructions. + Instruction *use_back() { return cast<Instruction>(*use_begin());} + const Instruction *use_back() const { return cast<Instruction>(*use_begin());} + + inline const BasicBlock *getParent() const { return Parent; } + inline BasicBlock *getParent() { return Parent; } + + /// removeFromParent - This method unlinks 'this' from the containing basic + /// block, but does not delete it. + /// + void removeFromParent(); + + /// eraseFromParent - This method unlinks 'this' from the containing basic + /// block and deletes it. + /// + void eraseFromParent(); + + /// insertBefore - Insert an unlinked instructions into a basic block + /// immediately before the specified instruction. + void insertBefore(Instruction *InsertPos); + + /// insertAfter - Insert an unlinked instructions into a basic block + /// immediately after the specified instruction. + void insertAfter(Instruction *InsertPos); + + /// moveBefore - Unlink this instruction from its current basic block and + /// insert it into the basic block that MovePos lives in, right before + /// MovePos. + void moveBefore(Instruction *MovePos); + + //===--------------------------------------------------------------------===// + // Subclass classification. + //===--------------------------------------------------------------------===// + + /// getOpcode() returns a member of one of the enums like Instruction::Add. + unsigned getOpcode() const { return getValueID() - InstructionVal; } + + const char *getOpcodeName() const { return getOpcodeName(getOpcode()); } + bool isTerminator() const { return isTerminator(getOpcode()); } + bool isBinaryOp() const { return isBinaryOp(getOpcode()); } + bool isShift() { return isShift(getOpcode()); } + bool isCast() const { return isCast(getOpcode()); } + + static const char* getOpcodeName(unsigned OpCode); + + static inline bool isTerminator(unsigned OpCode) { + return OpCode >= TermOpsBegin && OpCode < TermOpsEnd; + } + + static inline bool isBinaryOp(unsigned Opcode) { + return Opcode >= BinaryOpsBegin && Opcode < BinaryOpsEnd; + } + + /// @brief Determine if the Opcode is one of the shift instructions. + static inline bool isShift(unsigned Opcode) { + return Opcode >= Shl && Opcode <= AShr; + } + + /// isLogicalShift - Return true if this is a logical shift left or a logical + /// shift right. + inline bool isLogicalShift() const { + return getOpcode() == Shl || getOpcode() == LShr; + } + + /// isArithmeticShift - Return true if this is an arithmetic shift right. + inline bool isArithmeticShift() const { + return getOpcode() == AShr; + } + + /// @brief Determine if the OpCode is one of the CastInst instructions. + static inline bool isCast(unsigned OpCode) { + return OpCode >= CastOpsBegin && OpCode < CastOpsEnd; + } + + //===--------------------------------------------------------------------===// + // Metadata manipulation. + //===--------------------------------------------------------------------===// + + /// hasMetadata() - Return true if this instruction has any metadata attached + /// to it. + bool hasMetadata() const { + return !DbgLoc.isUnknown() || hasMetadataHashEntry(); + } + + /// hasMetadataOtherThanDebugLoc - Return true if this instruction has + /// metadata attached to it other than a debug location. + bool hasMetadataOtherThanDebugLoc() const { + return hasMetadataHashEntry(); + } + + /// getMetadata - Get the metadata of given kind attached to this Instruction. + /// If the metadata is not found then return null. + MDNode *getMetadata(unsigned KindID) const { + if (!hasMetadata()) return 0; + return getMetadataImpl(KindID); + } + + /// getMetadata - Get the metadata of given kind attached to this Instruction. + /// If the metadata is not found then return null. + MDNode *getMetadata(StringRef Kind) const { + if (!hasMetadata()) return 0; + return getMetadataImpl(Kind); + } + + /// getAllMetadata - Get all metadata attached to this Instruction. The first + /// element of each pair returned is the KindID, the second element is the + /// metadata value. This list is returned sorted by the KindID. + void getAllMetadata(SmallVectorImpl<std::pair<unsigned, MDNode*> > &MDs)const{ + if (hasMetadata()) + getAllMetadataImpl(MDs); + } + + /// getAllMetadataOtherThanDebugLoc - This does the same thing as + /// getAllMetadata, except that it filters out the debug location. + void getAllMetadataOtherThanDebugLoc(SmallVectorImpl<std::pair<unsigned, + MDNode*> > &MDs) const { + if (hasMetadataOtherThanDebugLoc()) + getAllMetadataOtherThanDebugLocImpl(MDs); + } + + /// setMetadata - Set the metadata of the specified kind to the specified + /// node. This updates/replaces metadata if already present, or removes it if + /// Node is null. + void setMetadata(unsigned KindID, MDNode *Node); + void setMetadata(StringRef Kind, MDNode *Node); + + /// setDebugLoc - Set the debug location information for this instruction. + void setDebugLoc(const DebugLoc &Loc) { DbgLoc = Loc; } + + /// getDebugLoc - Return the debug location for this node as a DebugLoc. + const DebugLoc &getDebugLoc() const { return DbgLoc; } + + /// Set or clear the unsafe-algebra flag on this instruction, which must be an + /// operator which supports this flag. See LangRef.html for the meaning of + /// this flag. + void setHasUnsafeAlgebra(bool B); + + /// Set or clear the no-nans flag on this instruction, which must be an + /// operator which supports this flag. See LangRef.html for the meaning of + /// this flag. + void setHasNoNaNs(bool B); + + /// Set or clear the no-infs flag on this instruction, which must be an + /// operator which supports this flag. See LangRef.html for the meaning of + /// this flag. + void setHasNoInfs(bool B); + + /// Set or clear the no-signed-zeros flag on this instruction, which must be + /// an operator which supports this flag. See LangRef.html for the meaning of + /// this flag. + void setHasNoSignedZeros(bool B); + + /// Set or clear the allow-reciprocal flag on this instruction, which must be + /// an operator which supports this flag. See LangRef.html for the meaning of + /// this flag. + void setHasAllowReciprocal(bool B); + + /// Convenience function for setting all the fast-math flags on this + /// instruction, which must be an operator which supports these flags. See + /// LangRef.html for the meaning of these flats. + void setFastMathFlags(FastMathFlags FMF); + + /// Determine whether the unsafe-algebra flag is set. + bool hasUnsafeAlgebra() const; + + /// Determine whether the no-NaNs flag is set. + bool hasNoNaNs() const; + + /// Determine whether the no-infs flag is set. + bool hasNoInfs() const; + + /// Determine whether the no-signed-zeros flag is set. + bool hasNoSignedZeros() const; + + /// Determine whether the allow-reciprocal flag is set. + bool hasAllowReciprocal() const; + + /// Convenience function for getting all the fast-math flags, which must be an + /// operator which supports these flags. See LangRef.html for the meaning of + /// these flats. + FastMathFlags getFastMathFlags() const; + + /// Copy I's fast-math flags + void copyFastMathFlags(const Instruction *I); + +private: + /// hasMetadataHashEntry - Return true if we have an entry in the on-the-side + /// metadata hash. + bool hasMetadataHashEntry() const { + return (getSubclassDataFromValue() & HasMetadataBit) != 0; + } + + // These are all implemented in Metadata.cpp. + MDNode *getMetadataImpl(unsigned KindID) const; + MDNode *getMetadataImpl(StringRef Kind) const; + void getAllMetadataImpl(SmallVectorImpl<std::pair<unsigned,MDNode*> > &)const; + void getAllMetadataOtherThanDebugLocImpl(SmallVectorImpl<std::pair<unsigned, + MDNode*> > &) const; + void clearMetadataHashEntries(); +public: + //===--------------------------------------------------------------------===// + // Predicates and helper methods. + //===--------------------------------------------------------------------===// + + + /// isAssociative - Return true if the instruction is associative: + /// + /// Associative operators satisfy: x op (y op z) === (x op y) op z + /// + /// In LLVM, the Add, Mul, And, Or, and Xor operators are associative. + /// + bool isAssociative() const; + static bool isAssociative(unsigned op); + + /// isCommutative - Return true if the instruction is commutative: + /// + /// Commutative operators satisfy: (x op y) === (y op x) + /// + /// In LLVM, these are the associative operators, plus SetEQ and SetNE, when + /// applied to any type. + /// + bool isCommutative() const { return isCommutative(getOpcode()); } + static bool isCommutative(unsigned op); + + /// isIdempotent - Return true if the instruction is idempotent: + /// + /// Idempotent operators satisfy: x op x === x + /// + /// In LLVM, the And and Or operators are idempotent. + /// + bool isIdempotent() const { return isIdempotent(getOpcode()); } + static bool isIdempotent(unsigned op); + + /// isNilpotent - Return true if the instruction is nilpotent: + /// + /// Nilpotent operators satisfy: x op x === Id, + /// + /// where Id is the identity for the operator, i.e. a constant such that + /// x op Id === x and Id op x === x for all x. + /// + /// In LLVM, the Xor operator is nilpotent. + /// + bool isNilpotent() const { return isNilpotent(getOpcode()); } + static bool isNilpotent(unsigned op); + + /// mayWriteToMemory - Return true if this instruction may modify memory. + /// + bool mayWriteToMemory() const; + + /// mayReadFromMemory - Return true if this instruction may read memory. + /// + bool mayReadFromMemory() const; + + /// mayReadOrWriteMemory - Return true if this instruction may read or + /// write memory. + /// + bool mayReadOrWriteMemory() const { + return mayReadFromMemory() || mayWriteToMemory(); + } + + /// mayThrow - Return true if this instruction may throw an exception. + /// + bool mayThrow() const; + + /// mayReturn - Return true if this is a function that may return. + /// this is true for all normal instructions. The only exception + /// is functions that are marked with the 'noreturn' attribute. + /// + bool mayReturn() const; + + /// mayHaveSideEffects - Return true if the instruction may have side effects. + /// + /// Note that this does not consider malloc and alloca to have side + /// effects because the newly allocated memory is completely invisible to + /// instructions which don't used the returned value. For cases where this + /// matters, isSafeToSpeculativelyExecute may be more appropriate. + bool mayHaveSideEffects() const { + return mayWriteToMemory() || mayThrow() || !mayReturn(); + } + + /// clone() - Create a copy of 'this' instruction that is identical in all + /// ways except the following: + /// * The instruction has no parent + /// * The instruction has no name + /// + Instruction *clone() const; + + /// isIdenticalTo - Return true if the specified instruction is exactly + /// identical to the current one. This means that all operands match and any + /// extra information (e.g. load is volatile) agree. + bool isIdenticalTo(const Instruction *I) const; + + /// isIdenticalToWhenDefined - This is like isIdenticalTo, except that it + /// ignores the SubclassOptionalData flags, which specify conditions + /// under which the instruction's result is undefined. + bool isIdenticalToWhenDefined(const Instruction *I) const; + + /// When checking for operation equivalence (using isSameOperationAs) it is + /// sometimes useful to ignore certain attributes. + enum OperationEquivalenceFlags { + /// Check for equivalence ignoring load/store alignment. + CompareIgnoringAlignment = 1<<0, + /// Check for equivalence treating a type and a vector of that type + /// as equivalent. + CompareUsingScalarTypes = 1<<1 + }; + + /// This function determines if the specified instruction executes the same + /// operation as the current one. This means that the opcodes, type, operand + /// types and any other factors affecting the operation must be the same. This + /// is similar to isIdenticalTo except the operands themselves don't have to + /// be identical. + /// @returns true if the specified instruction is the same operation as + /// the current one. + /// @brief Determine if one instruction is the same operation as another. + bool isSameOperationAs(const Instruction *I, unsigned flags = 0) const; + + /// isUsedOutsideOfBlock - Return true if there are any uses of this + /// instruction in blocks other than the specified block. Note that PHI nodes + /// are considered to evaluate their operands in the corresponding predecessor + /// block. + bool isUsedOutsideOfBlock(const BasicBlock *BB) const; + + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Value *V) { + return V->getValueID() >= Value::InstructionVal; + } + + //---------------------------------------------------------------------- + // Exported enumerations. + // + enum TermOps { // These terminate basic blocks +#define FIRST_TERM_INST(N) TermOpsBegin = N, +#define HANDLE_TERM_INST(N, OPC, CLASS) OPC = N, +#define LAST_TERM_INST(N) TermOpsEnd = N+1 +#include "llvm/IR/Instruction.def" + }; + + enum BinaryOps { +#define FIRST_BINARY_INST(N) BinaryOpsBegin = N, +#define HANDLE_BINARY_INST(N, OPC, CLASS) OPC = N, +#define LAST_BINARY_INST(N) BinaryOpsEnd = N+1 +#include "llvm/IR/Instruction.def" + }; + + enum MemoryOps { +#define FIRST_MEMORY_INST(N) MemoryOpsBegin = N, +#define HANDLE_MEMORY_INST(N, OPC, CLASS) OPC = N, +#define LAST_MEMORY_INST(N) MemoryOpsEnd = N+1 +#include "llvm/IR/Instruction.def" + }; + + enum CastOps { +#define FIRST_CAST_INST(N) CastOpsBegin = N, +#define HANDLE_CAST_INST(N, OPC, CLASS) OPC = N, +#define LAST_CAST_INST(N) CastOpsEnd = N+1 +#include "llvm/IR/Instruction.def" + }; + + enum OtherOps { +#define FIRST_OTHER_INST(N) OtherOpsBegin = N, +#define HANDLE_OTHER_INST(N, OPC, CLASS) OPC = N, +#define LAST_OTHER_INST(N) OtherOpsEnd = N+1 +#include "llvm/IR/Instruction.def" + }; +private: + // Shadow Value::setValueSubclassData with a private forwarding method so that + // subclasses cannot accidentally use it. + void setValueSubclassData(unsigned short D) { + Value::setValueSubclassData(D); + } + unsigned short getSubclassDataFromValue() const { + return Value::getSubclassDataFromValue(); + } + + void setHasMetadataHashEntry(bool V) { + setValueSubclassData((getSubclassDataFromValue() & ~HasMetadataBit) | + (V ? HasMetadataBit : 0)); + } + + friend class SymbolTableListTraits<Instruction, BasicBlock>; + void setParent(BasicBlock *P); +protected: + // Instruction subclasses can stick up to 15 bits of stuff into the + // SubclassData field of instruction with these members. + + // Verify that only the low 15 bits are used. + void setInstructionSubclassData(unsigned short D) { + assert((D & HasMetadataBit) == 0 && "Out of range value put into field"); + setValueSubclassData((getSubclassDataFromValue() & HasMetadataBit) | D); + } + + unsigned getSubclassDataFromInstruction() const { + return getSubclassDataFromValue() & ~HasMetadataBit; + } + + Instruction(Type *Ty, unsigned iType, Use *Ops, unsigned NumOps, + Instruction *InsertBefore = 0); + Instruction(Type *Ty, unsigned iType, Use *Ops, unsigned NumOps, + BasicBlock *InsertAtEnd); + virtual Instruction *clone_impl() const = 0; + +}; + +// Instruction* is only 4-byte aligned. +template<> +class PointerLikeTypeTraits<Instruction*> { + typedef Instruction* PT; +public: + static inline void *getAsVoidPointer(PT P) { return P; } + static inline PT getFromVoidPointer(void *P) { + return static_cast<PT>(P); + } + enum { NumLowBitsAvailable = 2 }; +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h new file mode 100644 index 0000000..7e29699 --- /dev/null +++ b/include/llvm/IR/Instructions.h @@ -0,0 +1,3716 @@ +//===-- llvm/Instructions.h - Instruction subclass definitions --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file exposes the class definitions of all of the subclasses of the +// Instruction class. This is meant to be an easy way to get access to all +// instruction subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_INSTRUCTIONS_H +#define LLVM_IR_INSTRUCTIONS_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/IR/Attributes.h" +#include "llvm/IR/CallingConv.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/IntegersSubset.h" +#include "llvm/Support/IntegersSubsetMapping.h" +#include <iterator> + +namespace llvm { + +class APInt; +class ConstantInt; +class ConstantRange; +class DataLayout; +class LLVMContext; + +enum AtomicOrdering { + NotAtomic = 0, + Unordered = 1, + Monotonic = 2, + // Consume = 3, // Not specified yet. + Acquire = 4, + Release = 5, + AcquireRelease = 6, + SequentiallyConsistent = 7 +}; + +enum SynchronizationScope { + SingleThread = 0, + CrossThread = 1 +}; + +//===----------------------------------------------------------------------===// +// AllocaInst Class +//===----------------------------------------------------------------------===// + +/// AllocaInst - an instruction to allocate memory on the stack +/// +class AllocaInst : public UnaryInstruction { +protected: + virtual AllocaInst *clone_impl() const; +public: + explicit AllocaInst(Type *Ty, Value *ArraySize = 0, + const Twine &Name = "", Instruction *InsertBefore = 0); + AllocaInst(Type *Ty, Value *ArraySize, + const Twine &Name, BasicBlock *InsertAtEnd); + + AllocaInst(Type *Ty, const Twine &Name, Instruction *InsertBefore = 0); + AllocaInst(Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd); + + AllocaInst(Type *Ty, Value *ArraySize, unsigned Align, + const Twine &Name = "", Instruction *InsertBefore = 0); + AllocaInst(Type *Ty, Value *ArraySize, unsigned Align, + const Twine &Name, BasicBlock *InsertAtEnd); + + // Out of line virtual method, so the vtable, etc. has a home. + virtual ~AllocaInst(); + + /// isArrayAllocation - Return true if there is an allocation size parameter + /// to the allocation instruction that is not 1. + /// + bool isArrayAllocation() const; + + /// getArraySize - Get the number of elements allocated. For a simple + /// allocation of a single element, this will return a constant 1 value. + /// + const Value *getArraySize() const { return getOperand(0); } + Value *getArraySize() { return getOperand(0); } + + /// getType - Overload to return most specific pointer type + /// + PointerType *getType() const { + return cast<PointerType>(Instruction::getType()); + } + + /// getAllocatedType - Return the type that is being allocated by the + /// instruction. + /// + Type *getAllocatedType() const; + + /// getAlignment - Return the alignment of the memory that is being allocated + /// by the instruction. + /// + unsigned getAlignment() const { + return (1u << getSubclassDataFromInstruction()) >> 1; + } + void setAlignment(unsigned Align); + + /// isStaticAlloca - Return true if this alloca is in the entry block of the + /// function and is a constant size. If so, the code generator will fold it + /// into the prolog/epilog code, so it is basically free. + bool isStaticAlloca() const; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return (I->getOpcode() == Instruction::Alloca); + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +private: + // Shadow Instruction::setInstructionSubclassData with a private forwarding + // method so that subclasses cannot accidentally use it. + void setInstructionSubclassData(unsigned short D) { + Instruction::setInstructionSubclassData(D); + } +}; + + +//===----------------------------------------------------------------------===// +// LoadInst Class +//===----------------------------------------------------------------------===// + +/// LoadInst - an instruction for reading from memory. This uses the +/// SubclassData field in Value to store whether or not the load is volatile. +/// +class LoadInst : public UnaryInstruction { + void AssertOK(); +protected: + virtual LoadInst *clone_impl() const; +public: + LoadInst(Value *Ptr, const Twine &NameStr, Instruction *InsertBefore); + LoadInst(Value *Ptr, const Twine &NameStr, BasicBlock *InsertAtEnd); + LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile = false, + Instruction *InsertBefore = 0); + LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, + BasicBlock *InsertAtEnd); + LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, + unsigned Align, Instruction *InsertBefore = 0); + LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, + unsigned Align, BasicBlock *InsertAtEnd); + LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, + unsigned Align, AtomicOrdering Order, + SynchronizationScope SynchScope = CrossThread, + Instruction *InsertBefore = 0); + LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, + unsigned Align, AtomicOrdering Order, + SynchronizationScope SynchScope, + BasicBlock *InsertAtEnd); + + LoadInst(Value *Ptr, const char *NameStr, Instruction *InsertBefore); + LoadInst(Value *Ptr, const char *NameStr, BasicBlock *InsertAtEnd); + explicit LoadInst(Value *Ptr, const char *NameStr = 0, + bool isVolatile = false, Instruction *InsertBefore = 0); + LoadInst(Value *Ptr, const char *NameStr, bool isVolatile, + BasicBlock *InsertAtEnd); + + /// isVolatile - Return true if this is a load from a volatile memory + /// location. + /// + bool isVolatile() const { return getSubclassDataFromInstruction() & 1; } + + /// setVolatile - Specify whether this is a volatile load or not. + /// + void setVolatile(bool V) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~1) | + (V ? 1 : 0)); + } + + /// getAlignment - Return the alignment of the access that is being performed + /// + unsigned getAlignment() const { + return (1 << ((getSubclassDataFromInstruction() >> 1) & 31)) >> 1; + } + + void setAlignment(unsigned Align); + + /// Returns the ordering effect of this fence. + AtomicOrdering getOrdering() const { + return AtomicOrdering((getSubclassDataFromInstruction() >> 7) & 7); + } + + /// Set the ordering constraint on this load. May not be Release or + /// AcquireRelease. + void setOrdering(AtomicOrdering Ordering) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~(7 << 7)) | + (Ordering << 7)); + } + + SynchronizationScope getSynchScope() const { + return SynchronizationScope((getSubclassDataFromInstruction() >> 6) & 1); + } + + /// Specify whether this load is ordered with respect to all + /// concurrently executing threads, or only with respect to signal handlers + /// executing in the same thread. + void setSynchScope(SynchronizationScope xthread) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~(1 << 6)) | + (xthread << 6)); + } + + bool isAtomic() const { return getOrdering() != NotAtomic; } + void setAtomic(AtomicOrdering Ordering, + SynchronizationScope SynchScope = CrossThread) { + setOrdering(Ordering); + setSynchScope(SynchScope); + } + + bool isSimple() const { return !isAtomic() && !isVolatile(); } + bool isUnordered() const { + return getOrdering() <= Unordered && !isVolatile(); + } + + Value *getPointerOperand() { return getOperand(0); } + const Value *getPointerOperand() const { return getOperand(0); } + static unsigned getPointerOperandIndex() { return 0U; } + + /// \brief Returns the address space of the pointer operand. + unsigned getPointerAddressSpace() const { + return getPointerOperand()->getType()->getPointerAddressSpace(); + } + + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Load; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +private: + // Shadow Instruction::setInstructionSubclassData with a private forwarding + // method so that subclasses cannot accidentally use it. + void setInstructionSubclassData(unsigned short D) { + Instruction::setInstructionSubclassData(D); + } +}; + + +//===----------------------------------------------------------------------===// +// StoreInst Class +//===----------------------------------------------------------------------===// + +/// StoreInst - an instruction for storing to memory +/// +class StoreInst : public Instruction { + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void AssertOK(); +protected: + virtual StoreInst *clone_impl() const; +public: + // allocate space for exactly two operands + void *operator new(size_t s) { + return User::operator new(s, 2); + } + StoreInst(Value *Val, Value *Ptr, Instruction *InsertBefore); + StoreInst(Value *Val, Value *Ptr, BasicBlock *InsertAtEnd); + StoreInst(Value *Val, Value *Ptr, bool isVolatile = false, + Instruction *InsertBefore = 0); + StoreInst(Value *Val, Value *Ptr, bool isVolatile, BasicBlock *InsertAtEnd); + StoreInst(Value *Val, Value *Ptr, bool isVolatile, + unsigned Align, Instruction *InsertBefore = 0); + StoreInst(Value *Val, Value *Ptr, bool isVolatile, + unsigned Align, BasicBlock *InsertAtEnd); + StoreInst(Value *Val, Value *Ptr, bool isVolatile, + unsigned Align, AtomicOrdering Order, + SynchronizationScope SynchScope = CrossThread, + Instruction *InsertBefore = 0); + StoreInst(Value *Val, Value *Ptr, bool isVolatile, + unsigned Align, AtomicOrdering Order, + SynchronizationScope SynchScope, + BasicBlock *InsertAtEnd); + + + /// isVolatile - Return true if this is a store to a volatile memory + /// location. + /// + bool isVolatile() const { return getSubclassDataFromInstruction() & 1; } + + /// setVolatile - Specify whether this is a volatile store or not. + /// + void setVolatile(bool V) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~1) | + (V ? 1 : 0)); + } + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// getAlignment - Return the alignment of the access that is being performed + /// + unsigned getAlignment() const { + return (1 << ((getSubclassDataFromInstruction() >> 1) & 31)) >> 1; + } + + void setAlignment(unsigned Align); + + /// Returns the ordering effect of this store. + AtomicOrdering getOrdering() const { + return AtomicOrdering((getSubclassDataFromInstruction() >> 7) & 7); + } + + /// Set the ordering constraint on this store. May not be Acquire or + /// AcquireRelease. + void setOrdering(AtomicOrdering Ordering) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~(7 << 7)) | + (Ordering << 7)); + } + + SynchronizationScope getSynchScope() const { + return SynchronizationScope((getSubclassDataFromInstruction() >> 6) & 1); + } + + /// Specify whether this store instruction is ordered with respect to all + /// concurrently executing threads, or only with respect to signal handlers + /// executing in the same thread. + void setSynchScope(SynchronizationScope xthread) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~(1 << 6)) | + (xthread << 6)); + } + + bool isAtomic() const { return getOrdering() != NotAtomic; } + void setAtomic(AtomicOrdering Ordering, + SynchronizationScope SynchScope = CrossThread) { + setOrdering(Ordering); + setSynchScope(SynchScope); + } + + bool isSimple() const { return !isAtomic() && !isVolatile(); } + bool isUnordered() const { + return getOrdering() <= Unordered && !isVolatile(); + } + + Value *getValueOperand() { return getOperand(0); } + const Value *getValueOperand() const { return getOperand(0); } + + Value *getPointerOperand() { return getOperand(1); } + const Value *getPointerOperand() const { return getOperand(1); } + static unsigned getPointerOperandIndex() { return 1U; } + + /// \brief Returns the address space of the pointer operand. + unsigned getPointerAddressSpace() const { + return getPointerOperand()->getType()->getPointerAddressSpace(); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Store; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +private: + // Shadow Instruction::setInstructionSubclassData with a private forwarding + // method so that subclasses cannot accidentally use it. + void setInstructionSubclassData(unsigned short D) { + Instruction::setInstructionSubclassData(D); + } +}; + +template <> +struct OperandTraits<StoreInst> : public FixedNumOperandTraits<StoreInst, 2> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(StoreInst, Value) + +//===----------------------------------------------------------------------===// +// FenceInst Class +//===----------------------------------------------------------------------===// + +/// FenceInst - an instruction for ordering other memory operations +/// +class FenceInst : public Instruction { + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void Init(AtomicOrdering Ordering, SynchronizationScope SynchScope); +protected: + virtual FenceInst *clone_impl() const; +public: + // allocate space for exactly zero operands + void *operator new(size_t s) { + return User::operator new(s, 0); + } + + // Ordering may only be Acquire, Release, AcquireRelease, or + // SequentiallyConsistent. + FenceInst(LLVMContext &C, AtomicOrdering Ordering, + SynchronizationScope SynchScope = CrossThread, + Instruction *InsertBefore = 0); + FenceInst(LLVMContext &C, AtomicOrdering Ordering, + SynchronizationScope SynchScope, + BasicBlock *InsertAtEnd); + + /// Returns the ordering effect of this fence. + AtomicOrdering getOrdering() const { + return AtomicOrdering(getSubclassDataFromInstruction() >> 1); + } + + /// Set the ordering constraint on this fence. May only be Acquire, Release, + /// AcquireRelease, or SequentiallyConsistent. + void setOrdering(AtomicOrdering Ordering) { + setInstructionSubclassData((getSubclassDataFromInstruction() & 1) | + (Ordering << 1)); + } + + SynchronizationScope getSynchScope() const { + return SynchronizationScope(getSubclassDataFromInstruction() & 1); + } + + /// Specify whether this fence orders other operations with respect to all + /// concurrently executing threads, or only with respect to signal handlers + /// executing in the same thread. + void setSynchScope(SynchronizationScope xthread) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~1) | + xthread); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Fence; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +private: + // Shadow Instruction::setInstructionSubclassData with a private forwarding + // method so that subclasses cannot accidentally use it. + void setInstructionSubclassData(unsigned short D) { + Instruction::setInstructionSubclassData(D); + } +}; + +//===----------------------------------------------------------------------===// +// AtomicCmpXchgInst Class +//===----------------------------------------------------------------------===// + +/// AtomicCmpXchgInst - an instruction that atomically checks whether a +/// specified value is in a memory location, and, if it is, stores a new value +/// there. Returns the value that was loaded. +/// +class AtomicCmpXchgInst : public Instruction { + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void Init(Value *Ptr, Value *Cmp, Value *NewVal, + AtomicOrdering Ordering, SynchronizationScope SynchScope); +protected: + virtual AtomicCmpXchgInst *clone_impl() const; +public: + // allocate space for exactly three operands + void *operator new(size_t s) { + return User::operator new(s, 3); + } + AtomicCmpXchgInst(Value *Ptr, Value *Cmp, Value *NewVal, + AtomicOrdering Ordering, SynchronizationScope SynchScope, + Instruction *InsertBefore = 0); + AtomicCmpXchgInst(Value *Ptr, Value *Cmp, Value *NewVal, + AtomicOrdering Ordering, SynchronizationScope SynchScope, + BasicBlock *InsertAtEnd); + + /// isVolatile - Return true if this is a cmpxchg from a volatile memory + /// location. + /// + bool isVolatile() const { + return getSubclassDataFromInstruction() & 1; + } + + /// setVolatile - Specify whether this is a volatile cmpxchg. + /// + void setVolatile(bool V) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~1) | + (unsigned)V); + } + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// Set the ordering constraint on this cmpxchg. + void setOrdering(AtomicOrdering Ordering) { + assert(Ordering != NotAtomic && + "CmpXchg instructions can only be atomic."); + setInstructionSubclassData((getSubclassDataFromInstruction() & 3) | + (Ordering << 2)); + } + + /// Specify whether this cmpxchg is atomic and orders other operations with + /// respect to all concurrently executing threads, or only with respect to + /// signal handlers executing in the same thread. + void setSynchScope(SynchronizationScope SynchScope) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~2) | + (SynchScope << 1)); + } + + /// Returns the ordering constraint on this cmpxchg. + AtomicOrdering getOrdering() const { + return AtomicOrdering(getSubclassDataFromInstruction() >> 2); + } + + /// Returns whether this cmpxchg is atomic between threads or only within a + /// single thread. + SynchronizationScope getSynchScope() const { + return SynchronizationScope((getSubclassDataFromInstruction() & 2) >> 1); + } + + Value *getPointerOperand() { return getOperand(0); } + const Value *getPointerOperand() const { return getOperand(0); } + static unsigned getPointerOperandIndex() { return 0U; } + + Value *getCompareOperand() { return getOperand(1); } + const Value *getCompareOperand() const { return getOperand(1); } + + Value *getNewValOperand() { return getOperand(2); } + const Value *getNewValOperand() const { return getOperand(2); } + + /// \brief Returns the address space of the pointer operand. + unsigned getPointerAddressSpace() const { + return getPointerOperand()->getType()->getPointerAddressSpace(); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::AtomicCmpXchg; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +private: + // Shadow Instruction::setInstructionSubclassData with a private forwarding + // method so that subclasses cannot accidentally use it. + void setInstructionSubclassData(unsigned short D) { + Instruction::setInstructionSubclassData(D); + } +}; + +template <> +struct OperandTraits<AtomicCmpXchgInst> : + public FixedNumOperandTraits<AtomicCmpXchgInst, 3> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(AtomicCmpXchgInst, Value) + +//===----------------------------------------------------------------------===// +// AtomicRMWInst Class +//===----------------------------------------------------------------------===// + +/// AtomicRMWInst - an instruction that atomically reads a memory location, +/// combines it with another value, and then stores the result back. Returns +/// the old value. +/// +class AtomicRMWInst : public Instruction { + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; +protected: + virtual AtomicRMWInst *clone_impl() const; +public: + /// This enumeration lists the possible modifications atomicrmw can make. In + /// the descriptions, 'p' is the pointer to the instruction's memory location, + /// 'old' is the initial value of *p, and 'v' is the other value passed to the + /// instruction. These instructions always return 'old'. + enum BinOp { + /// *p = v + Xchg, + /// *p = old + v + Add, + /// *p = old - v + Sub, + /// *p = old & v + And, + /// *p = ~old & v + Nand, + /// *p = old | v + Or, + /// *p = old ^ v + Xor, + /// *p = old >signed v ? old : v + Max, + /// *p = old <signed v ? old : v + Min, + /// *p = old >unsigned v ? old : v + UMax, + /// *p = old <unsigned v ? old : v + UMin, + + FIRST_BINOP = Xchg, + LAST_BINOP = UMin, + BAD_BINOP + }; + + // allocate space for exactly two operands + void *operator new(size_t s) { + return User::operator new(s, 2); + } + AtomicRMWInst(BinOp Operation, Value *Ptr, Value *Val, + AtomicOrdering Ordering, SynchronizationScope SynchScope, + Instruction *InsertBefore = 0); + AtomicRMWInst(BinOp Operation, Value *Ptr, Value *Val, + AtomicOrdering Ordering, SynchronizationScope SynchScope, + BasicBlock *InsertAtEnd); + + BinOp getOperation() const { + return static_cast<BinOp>(getSubclassDataFromInstruction() >> 5); + } + + void setOperation(BinOp Operation) { + unsigned short SubclassData = getSubclassDataFromInstruction(); + setInstructionSubclassData((SubclassData & 31) | + (Operation << 5)); + } + + /// isVolatile - Return true if this is a RMW on a volatile memory location. + /// + bool isVolatile() const { + return getSubclassDataFromInstruction() & 1; + } + + /// setVolatile - Specify whether this is a volatile RMW or not. + /// + void setVolatile(bool V) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~1) | + (unsigned)V); + } + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// Set the ordering constraint on this RMW. + void setOrdering(AtomicOrdering Ordering) { + assert(Ordering != NotAtomic && + "atomicrmw instructions can only be atomic."); + setInstructionSubclassData((getSubclassDataFromInstruction() & ~(7 << 2)) | + (Ordering << 2)); + } + + /// Specify whether this RMW orders other operations with respect to all + /// concurrently executing threads, or only with respect to signal handlers + /// executing in the same thread. + void setSynchScope(SynchronizationScope SynchScope) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~2) | + (SynchScope << 1)); + } + + /// Returns the ordering constraint on this RMW. + AtomicOrdering getOrdering() const { + return AtomicOrdering((getSubclassDataFromInstruction() >> 2) & 7); + } + + /// Returns whether this RMW is atomic between threads or only within a + /// single thread. + SynchronizationScope getSynchScope() const { + return SynchronizationScope((getSubclassDataFromInstruction() & 2) >> 1); + } + + Value *getPointerOperand() { return getOperand(0); } + const Value *getPointerOperand() const { return getOperand(0); } + static unsigned getPointerOperandIndex() { return 0U; } + + Value *getValOperand() { return getOperand(1); } + const Value *getValOperand() const { return getOperand(1); } + + /// \brief Returns the address space of the pointer operand. + unsigned getPointerAddressSpace() const { + return getPointerOperand()->getType()->getPointerAddressSpace(); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::AtomicRMW; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +private: + void Init(BinOp Operation, Value *Ptr, Value *Val, + AtomicOrdering Ordering, SynchronizationScope SynchScope); + // Shadow Instruction::setInstructionSubclassData with a private forwarding + // method so that subclasses cannot accidentally use it. + void setInstructionSubclassData(unsigned short D) { + Instruction::setInstructionSubclassData(D); + } +}; + +template <> +struct OperandTraits<AtomicRMWInst> + : public FixedNumOperandTraits<AtomicRMWInst,2> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(AtomicRMWInst, Value) + +//===----------------------------------------------------------------------===// +// GetElementPtrInst Class +//===----------------------------------------------------------------------===// + +// checkGEPType - Simple wrapper function to give a better assertion failure +// message on bad indexes for a gep instruction. +// +inline Type *checkGEPType(Type *Ty) { + assert(Ty && "Invalid GetElementPtrInst indices for type!"); + return Ty; +} + +/// GetElementPtrInst - an instruction for type-safe pointer arithmetic to +/// access elements of arrays and structs +/// +class GetElementPtrInst : public Instruction { + GetElementPtrInst(const GetElementPtrInst &GEPI); + void init(Value *Ptr, ArrayRef<Value *> IdxList, const Twine &NameStr); + + /// Constructors - Create a getelementptr instruction with a base pointer an + /// list of indices. The first ctor can optionally insert before an existing + /// instruction, the second appends the new instruction to the specified + /// BasicBlock. + inline GetElementPtrInst(Value *Ptr, ArrayRef<Value *> IdxList, + unsigned Values, const Twine &NameStr, + Instruction *InsertBefore); + inline GetElementPtrInst(Value *Ptr, ArrayRef<Value *> IdxList, + unsigned Values, const Twine &NameStr, + BasicBlock *InsertAtEnd); +protected: + virtual GetElementPtrInst *clone_impl() const; +public: + static GetElementPtrInst *Create(Value *Ptr, ArrayRef<Value *> IdxList, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + unsigned Values = 1 + unsigned(IdxList.size()); + return new(Values) + GetElementPtrInst(Ptr, IdxList, Values, NameStr, InsertBefore); + } + static GetElementPtrInst *Create(Value *Ptr, ArrayRef<Value *> IdxList, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + unsigned Values = 1 + unsigned(IdxList.size()); + return new(Values) + GetElementPtrInst(Ptr, IdxList, Values, NameStr, InsertAtEnd); + } + + /// Create an "inbounds" getelementptr. See the documentation for the + /// "inbounds" flag in LangRef.html for details. + static GetElementPtrInst *CreateInBounds(Value *Ptr, + ArrayRef<Value *> IdxList, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + GetElementPtrInst *GEP = Create(Ptr, IdxList, NameStr, InsertBefore); + GEP->setIsInBounds(true); + return GEP; + } + static GetElementPtrInst *CreateInBounds(Value *Ptr, + ArrayRef<Value *> IdxList, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + GetElementPtrInst *GEP = Create(Ptr, IdxList, NameStr, InsertAtEnd); + GEP->setIsInBounds(true); + return GEP; + } + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + // getType - Overload to return most specific sequential type. + SequentialType *getType() const { + return cast<SequentialType>(Instruction::getType()); + } + + /// \brief Returns the address space of this instruction's pointer type. + unsigned getAddressSpace() const { + // Note that this is always the same as the pointer operand's address space + // and that is cheaper to compute, so cheat here. + return getPointerAddressSpace(); + } + + /// getIndexedType - Returns the type of the element that would be loaded with + /// a load instruction with the specified parameters. + /// + /// Null is returned if the indices are invalid for the specified + /// pointer type. + /// + static Type *getIndexedType(Type *Ptr, ArrayRef<Value *> IdxList); + static Type *getIndexedType(Type *Ptr, ArrayRef<Constant *> IdxList); + static Type *getIndexedType(Type *Ptr, ArrayRef<uint64_t> IdxList); + + inline op_iterator idx_begin() { return op_begin()+1; } + inline const_op_iterator idx_begin() const { return op_begin()+1; } + inline op_iterator idx_end() { return op_end(); } + inline const_op_iterator idx_end() const { return op_end(); } + + Value *getPointerOperand() { + return getOperand(0); + } + const Value *getPointerOperand() const { + return getOperand(0); + } + static unsigned getPointerOperandIndex() { + return 0U; // get index for modifying correct operand. + } + + /// getPointerOperandType - Method to return the pointer operand as a + /// PointerType. + Type *getPointerOperandType() const { + return getPointerOperand()->getType(); + } + + /// \brief Returns the address space of the pointer operand. + unsigned getPointerAddressSpace() const { + return getPointerOperandType()->getPointerAddressSpace(); + } + + /// GetGEPReturnType - Returns the pointer type returned by the GEP + /// instruction, which may be a vector of pointers. + static Type *getGEPReturnType(Value *Ptr, ArrayRef<Value *> IdxList) { + Type *PtrTy = PointerType::get(checkGEPType( + getIndexedType(Ptr->getType(), IdxList)), + Ptr->getType()->getPointerAddressSpace()); + // Vector GEP + if (Ptr->getType()->isVectorTy()) { + unsigned NumElem = cast<VectorType>(Ptr->getType())->getNumElements(); + return VectorType::get(PtrTy, NumElem); + } + + // Scalar GEP + return PtrTy; + } + + unsigned getNumIndices() const { // Note: always non-negative + return getNumOperands() - 1; + } + + bool hasIndices() const { + return getNumOperands() > 1; + } + + /// hasAllZeroIndices - Return true if all of the indices of this GEP are + /// zeros. If so, the result pointer and the first operand have the same + /// value, just potentially different types. + bool hasAllZeroIndices() const; + + /// hasAllConstantIndices - Return true if all of the indices of this GEP are + /// constant integers. If so, the result pointer and the first operand have + /// a constant offset between them. + bool hasAllConstantIndices() const; + + /// setIsInBounds - Set or clear the inbounds flag on this GEP instruction. + /// See LangRef.html for the meaning of inbounds on a getelementptr. + void setIsInBounds(bool b = true); + + /// isInBounds - Determine whether the GEP has the inbounds flag. + bool isInBounds() const; + + /// \brief Accumulate the constant address offset of this GEP if possible. + /// + /// This routine accepts an APInt into which it will accumulate the constant + /// offset of this GEP if the GEP is in fact constant. If the GEP is not + /// all-constant, it returns false and the value of the offset APInt is + /// undefined (it is *not* preserved!). The APInt passed into this routine + /// must be at least as wide as the IntPtr type for the address space of + /// the base GEP pointer. + bool accumulateConstantOffset(const DataLayout &DL, APInt &Offset) const; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return (I->getOpcode() == Instruction::GetElementPtr); + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +template <> +struct OperandTraits<GetElementPtrInst> : + public VariadicOperandTraits<GetElementPtrInst, 1> { +}; + +GetElementPtrInst::GetElementPtrInst(Value *Ptr, + ArrayRef<Value *> IdxList, + unsigned Values, + const Twine &NameStr, + Instruction *InsertBefore) + : Instruction(getGEPReturnType(Ptr, IdxList), + GetElementPtr, + OperandTraits<GetElementPtrInst>::op_end(this) - Values, + Values, InsertBefore) { + init(Ptr, IdxList, NameStr); +} +GetElementPtrInst::GetElementPtrInst(Value *Ptr, + ArrayRef<Value *> IdxList, + unsigned Values, + const Twine &NameStr, + BasicBlock *InsertAtEnd) + : Instruction(getGEPReturnType(Ptr, IdxList), + GetElementPtr, + OperandTraits<GetElementPtrInst>::op_end(this) - Values, + Values, InsertAtEnd) { + init(Ptr, IdxList, NameStr); +} + + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrInst, Value) + + +//===----------------------------------------------------------------------===// +// ICmpInst Class +//===----------------------------------------------------------------------===// + +/// This instruction compares its operands according to the predicate given +/// to the constructor. It only operates on integers or pointers. The operands +/// must be identical types. +/// \brief Represent an integer comparison operator. +class ICmpInst: public CmpInst { +protected: + /// \brief Clone an identical ICmpInst + virtual ICmpInst *clone_impl() const; +public: + /// \brief Constructor with insert-before-instruction semantics. + ICmpInst( + Instruction *InsertBefore, ///< Where to insert + Predicate pred, ///< The predicate to use for the comparison + Value *LHS, ///< The left-hand-side of the expression + Value *RHS, ///< The right-hand-side of the expression + const Twine &NameStr = "" ///< Name of the instruction + ) : CmpInst(makeCmpResultType(LHS->getType()), + Instruction::ICmp, pred, LHS, RHS, NameStr, + InsertBefore) { + assert(pred >= CmpInst::FIRST_ICMP_PREDICATE && + pred <= CmpInst::LAST_ICMP_PREDICATE && + "Invalid ICmp predicate value"); + assert(getOperand(0)->getType() == getOperand(1)->getType() && + "Both operands to ICmp instruction are not of the same type!"); + // Check that the operands are the right type + assert((getOperand(0)->getType()->isIntOrIntVectorTy() || + getOperand(0)->getType()->getScalarType()->isPointerTy()) && + "Invalid operand types for ICmp instruction"); + } + + /// \brief Constructor with insert-at-end semantics. + ICmpInst( + BasicBlock &InsertAtEnd, ///< Block to insert into. + Predicate pred, ///< The predicate to use for the comparison + Value *LHS, ///< The left-hand-side of the expression + Value *RHS, ///< The right-hand-side of the expression + const Twine &NameStr = "" ///< Name of the instruction + ) : CmpInst(makeCmpResultType(LHS->getType()), + Instruction::ICmp, pred, LHS, RHS, NameStr, + &InsertAtEnd) { + assert(pred >= CmpInst::FIRST_ICMP_PREDICATE && + pred <= CmpInst::LAST_ICMP_PREDICATE && + "Invalid ICmp predicate value"); + assert(getOperand(0)->getType() == getOperand(1)->getType() && + "Both operands to ICmp instruction are not of the same type!"); + // Check that the operands are the right type + assert((getOperand(0)->getType()->isIntOrIntVectorTy() || + getOperand(0)->getType()->getScalarType()->isPointerTy()) && + "Invalid operand types for ICmp instruction"); + } + + /// \brief Constructor with no-insertion semantics + ICmpInst( + Predicate pred, ///< The predicate to use for the comparison + Value *LHS, ///< The left-hand-side of the expression + Value *RHS, ///< The right-hand-side of the expression + const Twine &NameStr = "" ///< Name of the instruction + ) : CmpInst(makeCmpResultType(LHS->getType()), + Instruction::ICmp, pred, LHS, RHS, NameStr) { + assert(pred >= CmpInst::FIRST_ICMP_PREDICATE && + pred <= CmpInst::LAST_ICMP_PREDICATE && + "Invalid ICmp predicate value"); + assert(getOperand(0)->getType() == getOperand(1)->getType() && + "Both operands to ICmp instruction are not of the same type!"); + // Check that the operands are the right type + assert((getOperand(0)->getType()->isIntOrIntVectorTy() || + getOperand(0)->getType()->getScalarType()->isPointerTy()) && + "Invalid operand types for ICmp instruction"); + } + + /// For example, EQ->EQ, SLE->SLE, UGT->SGT, etc. + /// @returns the predicate that would be the result if the operand were + /// regarded as signed. + /// \brief Return the signed version of the predicate + Predicate getSignedPredicate() const { + return getSignedPredicate(getPredicate()); + } + + /// This is a static version that you can use without an instruction. + /// \brief Return the signed version of the predicate. + static Predicate getSignedPredicate(Predicate pred); + + /// For example, EQ->EQ, SLE->ULE, UGT->UGT, etc. + /// @returns the predicate that would be the result if the operand were + /// regarded as unsigned. + /// \brief Return the unsigned version of the predicate + Predicate getUnsignedPredicate() const { + return getUnsignedPredicate(getPredicate()); + } + + /// This is a static version that you can use without an instruction. + /// \brief Return the unsigned version of the predicate. + static Predicate getUnsignedPredicate(Predicate pred); + + /// isEquality - Return true if this predicate is either EQ or NE. This also + /// tests for commutativity. + static bool isEquality(Predicate P) { + return P == ICMP_EQ || P == ICMP_NE; + } + + /// isEquality - Return true if this predicate is either EQ or NE. This also + /// tests for commutativity. + bool isEquality() const { + return isEquality(getPredicate()); + } + + /// @returns true if the predicate of this ICmpInst is commutative + /// \brief Determine if this relation is commutative. + bool isCommutative() const { return isEquality(); } + + /// isRelational - Return true if the predicate is relational (not EQ or NE). + /// + bool isRelational() const { + return !isEquality(); + } + + /// isRelational - Return true if the predicate is relational (not EQ or NE). + /// + static bool isRelational(Predicate P) { + return !isEquality(P); + } + + /// Initialize a set of values that all satisfy the predicate with C. + /// \brief Make a ConstantRange for a relation with a constant value. + static ConstantRange makeConstantRange(Predicate pred, const APInt &C); + + /// Exchange the two operands to this instruction in such a way that it does + /// not modify the semantics of the instruction. The predicate value may be + /// changed to retain the same result if the predicate is order dependent + /// (e.g. ult). + /// \brief Swap operands and adjust predicate. + void swapOperands() { + setPredicate(getSwappedPredicate()); + Op<0>().swap(Op<1>()); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::ICmp; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } + +}; + +//===----------------------------------------------------------------------===// +// FCmpInst Class +//===----------------------------------------------------------------------===// + +/// This instruction compares its operands according to the predicate given +/// to the constructor. It only operates on floating point values or packed +/// vectors of floating point values. The operands must be identical types. +/// \brief Represents a floating point comparison operator. +class FCmpInst: public CmpInst { +protected: + /// \brief Clone an identical FCmpInst + virtual FCmpInst *clone_impl() const; +public: + /// \brief Constructor with insert-before-instruction semantics. + FCmpInst( + Instruction *InsertBefore, ///< Where to insert + Predicate pred, ///< The predicate to use for the comparison + Value *LHS, ///< The left-hand-side of the expression + Value *RHS, ///< The right-hand-side of the expression + const Twine &NameStr = "" ///< Name of the instruction + ) : CmpInst(makeCmpResultType(LHS->getType()), + Instruction::FCmp, pred, LHS, RHS, NameStr, + InsertBefore) { + assert(pred <= FCmpInst::LAST_FCMP_PREDICATE && + "Invalid FCmp predicate value"); + assert(getOperand(0)->getType() == getOperand(1)->getType() && + "Both operands to FCmp instruction are not of the same type!"); + // Check that the operands are the right type + assert(getOperand(0)->getType()->isFPOrFPVectorTy() && + "Invalid operand types for FCmp instruction"); + } + + /// \brief Constructor with insert-at-end semantics. + FCmpInst( + BasicBlock &InsertAtEnd, ///< Block to insert into. + Predicate pred, ///< The predicate to use for the comparison + Value *LHS, ///< The left-hand-side of the expression + Value *RHS, ///< The right-hand-side of the expression + const Twine &NameStr = "" ///< Name of the instruction + ) : CmpInst(makeCmpResultType(LHS->getType()), + Instruction::FCmp, pred, LHS, RHS, NameStr, + &InsertAtEnd) { + assert(pred <= FCmpInst::LAST_FCMP_PREDICATE && + "Invalid FCmp predicate value"); + assert(getOperand(0)->getType() == getOperand(1)->getType() && + "Both operands to FCmp instruction are not of the same type!"); + // Check that the operands are the right type + assert(getOperand(0)->getType()->isFPOrFPVectorTy() && + "Invalid operand types for FCmp instruction"); + } + + /// \brief Constructor with no-insertion semantics + FCmpInst( + Predicate pred, ///< The predicate to use for the comparison + Value *LHS, ///< The left-hand-side of the expression + Value *RHS, ///< The right-hand-side of the expression + const Twine &NameStr = "" ///< Name of the instruction + ) : CmpInst(makeCmpResultType(LHS->getType()), + Instruction::FCmp, pred, LHS, RHS, NameStr) { + assert(pred <= FCmpInst::LAST_FCMP_PREDICATE && + "Invalid FCmp predicate value"); + assert(getOperand(0)->getType() == getOperand(1)->getType() && + "Both operands to FCmp instruction are not of the same type!"); + // Check that the operands are the right type + assert(getOperand(0)->getType()->isFPOrFPVectorTy() && + "Invalid operand types for FCmp instruction"); + } + + /// @returns true if the predicate of this instruction is EQ or NE. + /// \brief Determine if this is an equality predicate. + bool isEquality() const { + return getPredicate() == FCMP_OEQ || getPredicate() == FCMP_ONE || + getPredicate() == FCMP_UEQ || getPredicate() == FCMP_UNE; + } + + /// @returns true if the predicate of this instruction is commutative. + /// \brief Determine if this is a commutative predicate. + bool isCommutative() const { + return isEquality() || + getPredicate() == FCMP_FALSE || + getPredicate() == FCMP_TRUE || + getPredicate() == FCMP_ORD || + getPredicate() == FCMP_UNO; + } + + /// @returns true if the predicate is relational (not EQ or NE). + /// \brief Determine if this a relational predicate. + bool isRelational() const { return !isEquality(); } + + /// Exchange the two operands to this instruction in such a way that it does + /// not modify the semantics of the instruction. The predicate value may be + /// changed to retain the same result if the predicate is order dependent + /// (e.g. ult). + /// \brief Swap operands and adjust predicate. + void swapOperands() { + setPredicate(getSwappedPredicate()); + Op<0>().swap(Op<1>()); + } + + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::FCmp; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +/// CallInst - This class represents a function call, abstracting a target +/// machine's calling convention. This class uses low bit of the SubClassData +/// field to indicate whether or not this is a tail call. The rest of the bits +/// hold the calling convention of the call. +/// +class CallInst : public Instruction { + AttributeSet AttributeList; ///< parameter attributes for call + CallInst(const CallInst &CI); + void init(Value *Func, ArrayRef<Value *> Args, const Twine &NameStr); + void init(Value *Func, const Twine &NameStr); + + /// Construct a CallInst given a range of arguments. + /// \brief Construct a CallInst from a range of arguments + inline CallInst(Value *Func, ArrayRef<Value *> Args, + const Twine &NameStr, Instruction *InsertBefore); + + /// Construct a CallInst given a range of arguments. + /// \brief Construct a CallInst from a range of arguments + inline CallInst(Value *Func, ArrayRef<Value *> Args, + const Twine &NameStr, BasicBlock *InsertAtEnd); + + CallInst(Value *F, Value *Actual, const Twine &NameStr, + Instruction *InsertBefore); + CallInst(Value *F, Value *Actual, const Twine &NameStr, + BasicBlock *InsertAtEnd); + explicit CallInst(Value *F, const Twine &NameStr, + Instruction *InsertBefore); + CallInst(Value *F, const Twine &NameStr, BasicBlock *InsertAtEnd); +protected: + virtual CallInst *clone_impl() const; +public: + static CallInst *Create(Value *Func, + ArrayRef<Value *> Args, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + return new(unsigned(Args.size() + 1)) + CallInst(Func, Args, NameStr, InsertBefore); + } + static CallInst *Create(Value *Func, + ArrayRef<Value *> Args, + const Twine &NameStr, BasicBlock *InsertAtEnd) { + return new(unsigned(Args.size() + 1)) + CallInst(Func, Args, NameStr, InsertAtEnd); + } + static CallInst *Create(Value *F, const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + return new(1) CallInst(F, NameStr, InsertBefore); + } + static CallInst *Create(Value *F, const Twine &NameStr, + BasicBlock *InsertAtEnd) { + return new(1) CallInst(F, NameStr, InsertAtEnd); + } + /// CreateMalloc - Generate the IR for a call to malloc: + /// 1. Compute the malloc call's argument as the specified type's size, + /// possibly multiplied by the array size if the array size is not + /// constant 1. + /// 2. Call malloc with that argument. + /// 3. Bitcast the result of the malloc call to the specified type. + static Instruction *CreateMalloc(Instruction *InsertBefore, + Type *IntPtrTy, Type *AllocTy, + Value *AllocSize, Value *ArraySize = 0, + Function* MallocF = 0, + const Twine &Name = ""); + static Instruction *CreateMalloc(BasicBlock *InsertAtEnd, + Type *IntPtrTy, Type *AllocTy, + Value *AllocSize, Value *ArraySize = 0, + Function* MallocF = 0, + const Twine &Name = ""); + /// CreateFree - Generate the IR for a call to the builtin free function. + static Instruction* CreateFree(Value* Source, Instruction *InsertBefore); + static Instruction* CreateFree(Value* Source, BasicBlock *InsertAtEnd); + + ~CallInst(); + + bool isTailCall() const { return getSubclassDataFromInstruction() & 1; } + void setTailCall(bool isTC = true) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~1) | + unsigned(isTC)); + } + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// getNumArgOperands - Return the number of call arguments. + /// + unsigned getNumArgOperands() const { return getNumOperands() - 1; } + + /// getArgOperand/setArgOperand - Return/set the i-th call argument. + /// + Value *getArgOperand(unsigned i) const { return getOperand(i); } + void setArgOperand(unsigned i, Value *v) { setOperand(i, v); } + + /// getCallingConv/setCallingConv - Get or set the calling convention of this + /// function call. + CallingConv::ID getCallingConv() const { + return static_cast<CallingConv::ID>(getSubclassDataFromInstruction() >> 1); + } + void setCallingConv(CallingConv::ID CC) { + setInstructionSubclassData((getSubclassDataFromInstruction() & 1) | + (static_cast<unsigned>(CC) << 1)); + } + + /// getAttributes - Return the parameter attributes for this call. + /// + const AttributeSet &getAttributes() const { return AttributeList; } + + /// setAttributes - Set the parameter attributes for this call. + /// + void setAttributes(const AttributeSet &Attrs) { AttributeList = Attrs; } + + /// addAttribute - adds the attribute to the list of attributes. + void addAttribute(unsigned i, Attribute::AttrKind attr); + + /// removeAttribute - removes the attribute from the list of attributes. + void removeAttribute(unsigned i, Attribute attr); + + /// \brief Determine whether this call has the given attribute. + bool hasFnAttr(Attribute::AttrKind A) const; + + /// \brief Determine whether the call or the callee has the given attributes. + bool paramHasAttr(unsigned i, Attribute::AttrKind A) const; + + /// \brief Extract the alignment for a call or parameter (0=unknown). + unsigned getParamAlignment(unsigned i) const { + return AttributeList.getParamAlignment(i); + } + + /// \brief Return true if the call should not be inlined. + bool isNoInline() const { return hasFnAttr(Attribute::NoInline); } + void setIsNoInline() { + addAttribute(AttributeSet::FunctionIndex, Attribute::NoInline); + } + + /// \brief Return true if the call can return twice + bool canReturnTwice() const { + return hasFnAttr(Attribute::ReturnsTwice); + } + void setCanReturnTwice() { + addAttribute(AttributeSet::FunctionIndex, Attribute::ReturnsTwice); + } + + /// \brief Determine if the call does not access memory. + bool doesNotAccessMemory() const { + return hasFnAttr(Attribute::ReadNone); + } + void setDoesNotAccessMemory() { + addAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone); + } + + /// \brief Determine if the call does not access or only reads memory. + bool onlyReadsMemory() const { + return doesNotAccessMemory() || hasFnAttr(Attribute::ReadOnly); + } + void setOnlyReadsMemory() { + addAttribute(AttributeSet::FunctionIndex, Attribute::ReadOnly); + } + + /// \brief Determine if the call cannot return. + bool doesNotReturn() const { return hasFnAttr(Attribute::NoReturn); } + void setDoesNotReturn() { + addAttribute(AttributeSet::FunctionIndex, Attribute::NoReturn); + } + + /// \brief Determine if the call cannot unwind. + bool doesNotThrow() const { return hasFnAttr(Attribute::NoUnwind); } + void setDoesNotThrow() { + addAttribute(AttributeSet::FunctionIndex, Attribute::NoUnwind); + } + + /// \brief Determine if the call cannot be duplicated. + bool cannotDuplicate() const {return hasFnAttr(Attribute::NoDuplicate); } + void setCannotDuplicate() { + addAttribute(AttributeSet::FunctionIndex, Attribute::NoDuplicate); + } + + /// \brief Determine if the call returns a structure through first + /// pointer argument. + bool hasStructRetAttr() const { + // Be friendly and also check the callee. + return paramHasAttr(1, Attribute::StructRet); + } + + /// \brief Determine if any call argument is an aggregate passed by value. + bool hasByValArgument() const { + return AttributeList.hasAttrSomewhere(Attribute::ByVal); + } + + /// getCalledFunction - Return the function called, or null if this is an + /// indirect function invocation. + /// + Function *getCalledFunction() const { + return dyn_cast<Function>(Op<-1>()); + } + + /// getCalledValue - Get a pointer to the function that is invoked by this + /// instruction. + const Value *getCalledValue() const { return Op<-1>(); } + Value *getCalledValue() { return Op<-1>(); } + + /// setCalledFunction - Set the function called. + void setCalledFunction(Value* Fn) { + Op<-1>() = Fn; + } + + /// isInlineAsm - Check if this call is an inline asm statement. + bool isInlineAsm() const { + return isa<InlineAsm>(Op<-1>()); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Call; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +private: + // Shadow Instruction::setInstructionSubclassData with a private forwarding + // method so that subclasses cannot accidentally use it. + void setInstructionSubclassData(unsigned short D) { + Instruction::setInstructionSubclassData(D); + } +}; + +template <> +struct OperandTraits<CallInst> : public VariadicOperandTraits<CallInst, 1> { +}; + +CallInst::CallInst(Value *Func, ArrayRef<Value *> Args, + const Twine &NameStr, BasicBlock *InsertAtEnd) + : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType()) + ->getElementType())->getReturnType(), + Instruction::Call, + OperandTraits<CallInst>::op_end(this) - (Args.size() + 1), + unsigned(Args.size() + 1), InsertAtEnd) { + init(Func, Args, NameStr); +} + +CallInst::CallInst(Value *Func, ArrayRef<Value *> Args, + const Twine &NameStr, Instruction *InsertBefore) + : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType()) + ->getElementType())->getReturnType(), + Instruction::Call, + OperandTraits<CallInst>::op_end(this) - (Args.size() + 1), + unsigned(Args.size() + 1), InsertBefore) { + init(Func, Args, NameStr); +} + + +// Note: if you get compile errors about private methods then +// please update your code to use the high-level operand +// interfaces. See line 943 above. +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CallInst, Value) + +//===----------------------------------------------------------------------===// +// SelectInst Class +//===----------------------------------------------------------------------===// + +/// SelectInst - This class represents the LLVM 'select' instruction. +/// +class SelectInst : public Instruction { + void init(Value *C, Value *S1, Value *S2) { + assert(!areInvalidOperands(C, S1, S2) && "Invalid operands for select"); + Op<0>() = C; + Op<1>() = S1; + Op<2>() = S2; + } + + SelectInst(Value *C, Value *S1, Value *S2, const Twine &NameStr, + Instruction *InsertBefore) + : Instruction(S1->getType(), Instruction::Select, + &Op<0>(), 3, InsertBefore) { + init(C, S1, S2); + setName(NameStr); + } + SelectInst(Value *C, Value *S1, Value *S2, const Twine &NameStr, + BasicBlock *InsertAtEnd) + : Instruction(S1->getType(), Instruction::Select, + &Op<0>(), 3, InsertAtEnd) { + init(C, S1, S2); + setName(NameStr); + } +protected: + virtual SelectInst *clone_impl() const; +public: + static SelectInst *Create(Value *C, Value *S1, Value *S2, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + return new(3) SelectInst(C, S1, S2, NameStr, InsertBefore); + } + static SelectInst *Create(Value *C, Value *S1, Value *S2, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + return new(3) SelectInst(C, S1, S2, NameStr, InsertAtEnd); + } + + const Value *getCondition() const { return Op<0>(); } + const Value *getTrueValue() const { return Op<1>(); } + const Value *getFalseValue() const { return Op<2>(); } + Value *getCondition() { return Op<0>(); } + Value *getTrueValue() { return Op<1>(); } + Value *getFalseValue() { return Op<2>(); } + + /// areInvalidOperands - Return a string if the specified operands are invalid + /// for a select operation, otherwise return null. + static const char *areInvalidOperands(Value *Cond, Value *True, Value *False); + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + OtherOps getOpcode() const { + return static_cast<OtherOps>(Instruction::getOpcode()); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Select; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +template <> +struct OperandTraits<SelectInst> : public FixedNumOperandTraits<SelectInst, 3> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SelectInst, Value) + +//===----------------------------------------------------------------------===// +// VAArgInst Class +//===----------------------------------------------------------------------===// + +/// VAArgInst - This class represents the va_arg llvm instruction, which returns +/// an argument of the specified type given a va_list and increments that list +/// +class VAArgInst : public UnaryInstruction { +protected: + virtual VAArgInst *clone_impl() const; + +public: + VAArgInst(Value *List, Type *Ty, const Twine &NameStr = "", + Instruction *InsertBefore = 0) + : UnaryInstruction(Ty, VAArg, List, InsertBefore) { + setName(NameStr); + } + VAArgInst(Value *List, Type *Ty, const Twine &NameStr, + BasicBlock *InsertAtEnd) + : UnaryInstruction(Ty, VAArg, List, InsertAtEnd) { + setName(NameStr); + } + + Value *getPointerOperand() { return getOperand(0); } + const Value *getPointerOperand() const { return getOperand(0); } + static unsigned getPointerOperandIndex() { return 0U; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == VAArg; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// ExtractElementInst Class +//===----------------------------------------------------------------------===// + +/// ExtractElementInst - This instruction extracts a single (scalar) +/// element from a VectorType value +/// +class ExtractElementInst : public Instruction { + ExtractElementInst(Value *Vec, Value *Idx, const Twine &NameStr = "", + Instruction *InsertBefore = 0); + ExtractElementInst(Value *Vec, Value *Idx, const Twine &NameStr, + BasicBlock *InsertAtEnd); +protected: + virtual ExtractElementInst *clone_impl() const; + +public: + static ExtractElementInst *Create(Value *Vec, Value *Idx, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + return new(2) ExtractElementInst(Vec, Idx, NameStr, InsertBefore); + } + static ExtractElementInst *Create(Value *Vec, Value *Idx, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + return new(2) ExtractElementInst(Vec, Idx, NameStr, InsertAtEnd); + } + + /// isValidOperands - Return true if an extractelement instruction can be + /// formed with the specified operands. + static bool isValidOperands(const Value *Vec, const Value *Idx); + + Value *getVectorOperand() { return Op<0>(); } + Value *getIndexOperand() { return Op<1>(); } + const Value *getVectorOperand() const { return Op<0>(); } + const Value *getIndexOperand() const { return Op<1>(); } + + VectorType *getVectorOperandType() const { + return cast<VectorType>(getVectorOperand()->getType()); + } + + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::ExtractElement; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +template <> +struct OperandTraits<ExtractElementInst> : + public FixedNumOperandTraits<ExtractElementInst, 2> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractElementInst, Value) + +//===----------------------------------------------------------------------===// +// InsertElementInst Class +//===----------------------------------------------------------------------===// + +/// InsertElementInst - This instruction inserts a single (scalar) +/// element into a VectorType value +/// +class InsertElementInst : public Instruction { + InsertElementInst(Value *Vec, Value *NewElt, Value *Idx, + const Twine &NameStr = "", + Instruction *InsertBefore = 0); + InsertElementInst(Value *Vec, Value *NewElt, Value *Idx, + const Twine &NameStr, BasicBlock *InsertAtEnd); +protected: + virtual InsertElementInst *clone_impl() const; + +public: + static InsertElementInst *Create(Value *Vec, Value *NewElt, Value *Idx, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + return new(3) InsertElementInst(Vec, NewElt, Idx, NameStr, InsertBefore); + } + static InsertElementInst *Create(Value *Vec, Value *NewElt, Value *Idx, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + return new(3) InsertElementInst(Vec, NewElt, Idx, NameStr, InsertAtEnd); + } + + /// isValidOperands - Return true if an insertelement instruction can be + /// formed with the specified operands. + static bool isValidOperands(const Value *Vec, const Value *NewElt, + const Value *Idx); + + /// getType - Overload to return most specific vector type. + /// + VectorType *getType() const { + return cast<VectorType>(Instruction::getType()); + } + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::InsertElement; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +template <> +struct OperandTraits<InsertElementInst> : + public FixedNumOperandTraits<InsertElementInst, 3> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertElementInst, Value) + +//===----------------------------------------------------------------------===// +// ShuffleVectorInst Class +//===----------------------------------------------------------------------===// + +/// ShuffleVectorInst - This instruction constructs a fixed permutation of two +/// input vectors. +/// +class ShuffleVectorInst : public Instruction { +protected: + virtual ShuffleVectorInst *clone_impl() const; + +public: + // allocate space for exactly three operands + void *operator new(size_t s) { + return User::operator new(s, 3); + } + ShuffleVectorInst(Value *V1, Value *V2, Value *Mask, + const Twine &NameStr = "", + Instruction *InsertBefor = 0); + ShuffleVectorInst(Value *V1, Value *V2, Value *Mask, + const Twine &NameStr, BasicBlock *InsertAtEnd); + + /// isValidOperands - Return true if a shufflevector instruction can be + /// formed with the specified operands. + static bool isValidOperands(const Value *V1, const Value *V2, + const Value *Mask); + + /// getType - Overload to return most specific vector type. + /// + VectorType *getType() const { + return cast<VectorType>(Instruction::getType()); + } + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + Constant *getMask() const { + return cast<Constant>(getOperand(2)); + } + + /// getMaskValue - Return the index from the shuffle mask for the specified + /// output result. This is either -1 if the element is undef or a number less + /// than 2*numelements. + static int getMaskValue(Constant *Mask, unsigned i); + + int getMaskValue(unsigned i) const { + return getMaskValue(getMask(), i); + } + + /// getShuffleMask - Return the full mask for this instruction, where each + /// element is the element number and undef's are returned as -1. + static void getShuffleMask(Constant *Mask, SmallVectorImpl<int> &Result); + + void getShuffleMask(SmallVectorImpl<int> &Result) const { + return getShuffleMask(getMask(), Result); + } + + SmallVector<int, 16> getShuffleMask() const { + SmallVector<int, 16> Mask; + getShuffleMask(Mask); + return Mask; + } + + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::ShuffleVector; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +template <> +struct OperandTraits<ShuffleVectorInst> : + public FixedNumOperandTraits<ShuffleVectorInst, 3> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ShuffleVectorInst, Value) + +//===----------------------------------------------------------------------===// +// ExtractValueInst Class +//===----------------------------------------------------------------------===// + +/// ExtractValueInst - This instruction extracts a struct member or array +/// element value from an aggregate value. +/// +class ExtractValueInst : public UnaryInstruction { + SmallVector<unsigned, 4> Indices; + + ExtractValueInst(const ExtractValueInst &EVI); + void init(ArrayRef<unsigned> Idxs, const Twine &NameStr); + + /// Constructors - Create a extractvalue instruction with a base aggregate + /// value and a list of indices. The first ctor can optionally insert before + /// an existing instruction, the second appends the new instruction to the + /// specified BasicBlock. + inline ExtractValueInst(Value *Agg, + ArrayRef<unsigned> Idxs, + const Twine &NameStr, + Instruction *InsertBefore); + inline ExtractValueInst(Value *Agg, + ArrayRef<unsigned> Idxs, + const Twine &NameStr, BasicBlock *InsertAtEnd); + + // allocate space for exactly one operand + void *operator new(size_t s) { + return User::operator new(s, 1); + } +protected: + virtual ExtractValueInst *clone_impl() const; + +public: + static ExtractValueInst *Create(Value *Agg, + ArrayRef<unsigned> Idxs, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + return new + ExtractValueInst(Agg, Idxs, NameStr, InsertBefore); + } + static ExtractValueInst *Create(Value *Agg, + ArrayRef<unsigned> Idxs, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + return new ExtractValueInst(Agg, Idxs, NameStr, InsertAtEnd); + } + + /// getIndexedType - Returns the type of the element that would be extracted + /// with an extractvalue instruction with the specified parameters. + /// + /// Null is returned if the indices are invalid for the specified type. + static Type *getIndexedType(Type *Agg, ArrayRef<unsigned> Idxs); + + typedef const unsigned* idx_iterator; + inline idx_iterator idx_begin() const { return Indices.begin(); } + inline idx_iterator idx_end() const { return Indices.end(); } + + Value *getAggregateOperand() { + return getOperand(0); + } + const Value *getAggregateOperand() const { + return getOperand(0); + } + static unsigned getAggregateOperandIndex() { + return 0U; // get index for modifying correct operand + } + + ArrayRef<unsigned> getIndices() const { + return Indices; + } + + unsigned getNumIndices() const { + return (unsigned)Indices.size(); + } + + bool hasIndices() const { + return true; + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::ExtractValue; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +ExtractValueInst::ExtractValueInst(Value *Agg, + ArrayRef<unsigned> Idxs, + const Twine &NameStr, + Instruction *InsertBefore) + : UnaryInstruction(checkGEPType(getIndexedType(Agg->getType(), Idxs)), + ExtractValue, Agg, InsertBefore) { + init(Idxs, NameStr); +} +ExtractValueInst::ExtractValueInst(Value *Agg, + ArrayRef<unsigned> Idxs, + const Twine &NameStr, + BasicBlock *InsertAtEnd) + : UnaryInstruction(checkGEPType(getIndexedType(Agg->getType(), Idxs)), + ExtractValue, Agg, InsertAtEnd) { + init(Idxs, NameStr); +} + + +//===----------------------------------------------------------------------===// +// InsertValueInst Class +//===----------------------------------------------------------------------===// + +/// InsertValueInst - This instruction inserts a struct field of array element +/// value into an aggregate value. +/// +class InsertValueInst : public Instruction { + SmallVector<unsigned, 4> Indices; + + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + InsertValueInst(const InsertValueInst &IVI); + void init(Value *Agg, Value *Val, ArrayRef<unsigned> Idxs, + const Twine &NameStr); + + /// Constructors - Create a insertvalue instruction with a base aggregate + /// value, a value to insert, and a list of indices. The first ctor can + /// optionally insert before an existing instruction, the second appends + /// the new instruction to the specified BasicBlock. + inline InsertValueInst(Value *Agg, Value *Val, + ArrayRef<unsigned> Idxs, + const Twine &NameStr, + Instruction *InsertBefore); + inline InsertValueInst(Value *Agg, Value *Val, + ArrayRef<unsigned> Idxs, + const Twine &NameStr, BasicBlock *InsertAtEnd); + + /// Constructors - These two constructors are convenience methods because one + /// and two index insertvalue instructions are so common. + InsertValueInst(Value *Agg, Value *Val, + unsigned Idx, const Twine &NameStr = "", + Instruction *InsertBefore = 0); + InsertValueInst(Value *Agg, Value *Val, unsigned Idx, + const Twine &NameStr, BasicBlock *InsertAtEnd); +protected: + virtual InsertValueInst *clone_impl() const; +public: + // allocate space for exactly two operands + void *operator new(size_t s) { + return User::operator new(s, 2); + } + + static InsertValueInst *Create(Value *Agg, Value *Val, + ArrayRef<unsigned> Idxs, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + return new InsertValueInst(Agg, Val, Idxs, NameStr, InsertBefore); + } + static InsertValueInst *Create(Value *Agg, Value *Val, + ArrayRef<unsigned> Idxs, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + return new InsertValueInst(Agg, Val, Idxs, NameStr, InsertAtEnd); + } + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + typedef const unsigned* idx_iterator; + inline idx_iterator idx_begin() const { return Indices.begin(); } + inline idx_iterator idx_end() const { return Indices.end(); } + + Value *getAggregateOperand() { + return getOperand(0); + } + const Value *getAggregateOperand() const { + return getOperand(0); + } + static unsigned getAggregateOperandIndex() { + return 0U; // get index for modifying correct operand + } + + Value *getInsertedValueOperand() { + return getOperand(1); + } + const Value *getInsertedValueOperand() const { + return getOperand(1); + } + static unsigned getInsertedValueOperandIndex() { + return 1U; // get index for modifying correct operand + } + + ArrayRef<unsigned> getIndices() const { + return Indices; + } + + unsigned getNumIndices() const { + return (unsigned)Indices.size(); + } + + bool hasIndices() const { + return true; + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::InsertValue; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +template <> +struct OperandTraits<InsertValueInst> : + public FixedNumOperandTraits<InsertValueInst, 2> { +}; + +InsertValueInst::InsertValueInst(Value *Agg, + Value *Val, + ArrayRef<unsigned> Idxs, + const Twine &NameStr, + Instruction *InsertBefore) + : Instruction(Agg->getType(), InsertValue, + OperandTraits<InsertValueInst>::op_begin(this), + 2, InsertBefore) { + init(Agg, Val, Idxs, NameStr); +} +InsertValueInst::InsertValueInst(Value *Agg, + Value *Val, + ArrayRef<unsigned> Idxs, + const Twine &NameStr, + BasicBlock *InsertAtEnd) + : Instruction(Agg->getType(), InsertValue, + OperandTraits<InsertValueInst>::op_begin(this), + 2, InsertAtEnd) { + init(Agg, Val, Idxs, NameStr); +} + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertValueInst, Value) + +//===----------------------------------------------------------------------===// +// PHINode Class +//===----------------------------------------------------------------------===// + +// PHINode - The PHINode class is used to represent the magical mystical PHI +// node, that can not exist in nature, but can be synthesized in a computer +// scientist's overactive imagination. +// +class PHINode : public Instruction { + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + /// ReservedSpace - The number of operands actually allocated. NumOperands is + /// the number actually in use. + unsigned ReservedSpace; + PHINode(const PHINode &PN); + // allocate space for exactly zero operands + void *operator new(size_t s) { + return User::operator new(s, 0); + } + explicit PHINode(Type *Ty, unsigned NumReservedValues, + const Twine &NameStr = "", Instruction *InsertBefore = 0) + : Instruction(Ty, Instruction::PHI, 0, 0, InsertBefore), + ReservedSpace(NumReservedValues) { + setName(NameStr); + OperandList = allocHungoffUses(ReservedSpace); + } + + PHINode(Type *Ty, unsigned NumReservedValues, const Twine &NameStr, + BasicBlock *InsertAtEnd) + : Instruction(Ty, Instruction::PHI, 0, 0, InsertAtEnd), + ReservedSpace(NumReservedValues) { + setName(NameStr); + OperandList = allocHungoffUses(ReservedSpace); + } +protected: + // allocHungoffUses - this is more complicated than the generic + // User::allocHungoffUses, because we have to allocate Uses for the incoming + // values and pointers to the incoming blocks, all in one allocation. + Use *allocHungoffUses(unsigned) const; + + virtual PHINode *clone_impl() const; +public: + /// Constructors - NumReservedValues is a hint for the number of incoming + /// edges that this phi node will have (use 0 if you really have no idea). + static PHINode *Create(Type *Ty, unsigned NumReservedValues, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + return new PHINode(Ty, NumReservedValues, NameStr, InsertBefore); + } + static PHINode *Create(Type *Ty, unsigned NumReservedValues, + const Twine &NameStr, BasicBlock *InsertAtEnd) { + return new PHINode(Ty, NumReservedValues, NameStr, InsertAtEnd); + } + ~PHINode(); + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + // Block iterator interface. This provides access to the list of incoming + // basic blocks, which parallels the list of incoming values. + + typedef BasicBlock **block_iterator; + typedef BasicBlock * const *const_block_iterator; + + block_iterator block_begin() { + Use::UserRef *ref = + reinterpret_cast<Use::UserRef*>(op_begin() + ReservedSpace); + return reinterpret_cast<block_iterator>(ref + 1); + } + + const_block_iterator block_begin() const { + const Use::UserRef *ref = + reinterpret_cast<const Use::UserRef*>(op_begin() + ReservedSpace); + return reinterpret_cast<const_block_iterator>(ref + 1); + } + + block_iterator block_end() { + return block_begin() + getNumOperands(); + } + + const_block_iterator block_end() const { + return block_begin() + getNumOperands(); + } + + /// getNumIncomingValues - Return the number of incoming edges + /// + unsigned getNumIncomingValues() const { return getNumOperands(); } + + /// getIncomingValue - Return incoming value number x + /// + Value *getIncomingValue(unsigned i) const { + return getOperand(i); + } + void setIncomingValue(unsigned i, Value *V) { + setOperand(i, V); + } + static unsigned getOperandNumForIncomingValue(unsigned i) { + return i; + } + static unsigned getIncomingValueNumForOperand(unsigned i) { + return i; + } + + /// getIncomingBlock - Return incoming basic block number @p i. + /// + BasicBlock *getIncomingBlock(unsigned i) const { + return block_begin()[i]; + } + + /// getIncomingBlock - Return incoming basic block corresponding + /// to an operand of the PHI. + /// + BasicBlock *getIncomingBlock(const Use &U) const { + assert(this == U.getUser() && "Iterator doesn't point to PHI's Uses?"); + return getIncomingBlock(unsigned(&U - op_begin())); + } + + /// getIncomingBlock - Return incoming basic block corresponding + /// to value use iterator. + /// + template <typename U> + BasicBlock *getIncomingBlock(value_use_iterator<U> I) const { + return getIncomingBlock(I.getUse()); + } + + void setIncomingBlock(unsigned i, BasicBlock *BB) { + block_begin()[i] = BB; + } + + /// addIncoming - Add an incoming value to the end of the PHI list + /// + void addIncoming(Value *V, BasicBlock *BB) { + assert(V && "PHI node got a null value!"); + assert(BB && "PHI node got a null basic block!"); + assert(getType() == V->getType() && + "All operands to PHI node must be the same type as the PHI node!"); + if (NumOperands == ReservedSpace) + growOperands(); // Get more space! + // Initialize some new operands. + ++NumOperands; + setIncomingValue(NumOperands - 1, V); + setIncomingBlock(NumOperands - 1, BB); + } + + /// removeIncomingValue - Remove an incoming value. This is useful if a + /// predecessor basic block is deleted. The value removed is returned. + /// + /// If the last incoming value for a PHI node is removed (and DeletePHIIfEmpty + /// is true), the PHI node is destroyed and any uses of it are replaced with + /// dummy values. The only time there should be zero incoming values to a PHI + /// node is when the block is dead, so this strategy is sound. + /// + Value *removeIncomingValue(unsigned Idx, bool DeletePHIIfEmpty = true); + + Value *removeIncomingValue(const BasicBlock *BB, bool DeletePHIIfEmpty=true) { + int Idx = getBasicBlockIndex(BB); + assert(Idx >= 0 && "Invalid basic block argument to remove!"); + return removeIncomingValue(Idx, DeletePHIIfEmpty); + } + + /// getBasicBlockIndex - Return the first index of the specified basic + /// block in the value list for this PHI. Returns -1 if no instance. + /// + int getBasicBlockIndex(const BasicBlock *BB) const { + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) + if (block_begin()[i] == BB) + return i; + return -1; + } + + Value *getIncomingValueForBlock(const BasicBlock *BB) const { + int Idx = getBasicBlockIndex(BB); + assert(Idx >= 0 && "Invalid basic block argument!"); + return getIncomingValue(Idx); + } + + /// hasConstantValue - If the specified PHI node always merges together the + /// same value, return the value, otherwise return null. + Value *hasConstantValue() const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::PHI; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } + private: + void growOperands(); +}; + +template <> +struct OperandTraits<PHINode> : public HungoffOperandTraits<2> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(PHINode, Value) + +//===----------------------------------------------------------------------===// +// LandingPadInst Class +//===----------------------------------------------------------------------===// + +//===--------------------------------------------------------------------------- +/// LandingPadInst - The landingpad instruction holds all of the information +/// necessary to generate correct exception handling. The landingpad instruction +/// cannot be moved from the top of a landing pad block, which itself is +/// accessible only from the 'unwind' edge of an invoke. This uses the +/// SubclassData field in Value to store whether or not the landingpad is a +/// cleanup. +/// +class LandingPadInst : public Instruction { + /// ReservedSpace - The number of operands actually allocated. NumOperands is + /// the number actually in use. + unsigned ReservedSpace; + LandingPadInst(const LandingPadInst &LP); +public: + enum ClauseType { Catch, Filter }; +private: + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + // Allocate space for exactly zero operands. + void *operator new(size_t s) { + return User::operator new(s, 0); + } + void growOperands(unsigned Size); + void init(Value *PersFn, unsigned NumReservedValues, const Twine &NameStr); + + explicit LandingPadInst(Type *RetTy, Value *PersonalityFn, + unsigned NumReservedValues, const Twine &NameStr, + Instruction *InsertBefore); + explicit LandingPadInst(Type *RetTy, Value *PersonalityFn, + unsigned NumReservedValues, const Twine &NameStr, + BasicBlock *InsertAtEnd); +protected: + virtual LandingPadInst *clone_impl() const; +public: + /// Constructors - NumReservedClauses is a hint for the number of incoming + /// clauses that this landingpad will have (use 0 if you really have no idea). + static LandingPadInst *Create(Type *RetTy, Value *PersonalityFn, + unsigned NumReservedClauses, + const Twine &NameStr = "", + Instruction *InsertBefore = 0); + static LandingPadInst *Create(Type *RetTy, Value *PersonalityFn, + unsigned NumReservedClauses, + const Twine &NameStr, BasicBlock *InsertAtEnd); + ~LandingPadInst(); + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// getPersonalityFn - Get the personality function associated with this + /// landing pad. + Value *getPersonalityFn() const { return getOperand(0); } + + /// isCleanup - Return 'true' if this landingpad instruction is a + /// cleanup. I.e., it should be run when unwinding even if its landing pad + /// doesn't catch the exception. + bool isCleanup() const { return getSubclassDataFromInstruction() & 1; } + + /// setCleanup - Indicate that this landingpad instruction is a cleanup. + void setCleanup(bool V) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~1) | + (V ? 1 : 0)); + } + + /// addClause - Add a catch or filter clause to the landing pad. + void addClause(Value *ClauseVal); + + /// getClause - Get the value of the clause at index Idx. Use isCatch/isFilter + /// to determine what type of clause this is. + Value *getClause(unsigned Idx) const { return OperandList[Idx + 1]; } + + /// isCatch - Return 'true' if the clause and index Idx is a catch clause. + bool isCatch(unsigned Idx) const { + return !isa<ArrayType>(OperandList[Idx + 1]->getType()); + } + + /// isFilter - Return 'true' if the clause and index Idx is a filter clause. + bool isFilter(unsigned Idx) const { + return isa<ArrayType>(OperandList[Idx + 1]->getType()); + } + + /// getNumClauses - Get the number of clauses for this landing pad. + unsigned getNumClauses() const { return getNumOperands() - 1; } + + /// reserveClauses - Grow the size of the operand list to accommodate the new + /// number of clauses. + void reserveClauses(unsigned Size) { growOperands(Size); } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::LandingPad; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +template <> +struct OperandTraits<LandingPadInst> : public HungoffOperandTraits<2> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(LandingPadInst, Value) + +//===----------------------------------------------------------------------===// +// ReturnInst Class +//===----------------------------------------------------------------------===// + +//===--------------------------------------------------------------------------- +/// ReturnInst - Return a value (possibly void), from a function. Execution +/// does not continue in this function any longer. +/// +class ReturnInst : public TerminatorInst { + ReturnInst(const ReturnInst &RI); + +private: + // ReturnInst constructors: + // ReturnInst() - 'ret void' instruction + // ReturnInst( null) - 'ret void' instruction + // ReturnInst(Value* X) - 'ret X' instruction + // ReturnInst( null, Inst *I) - 'ret void' instruction, insert before I + // ReturnInst(Value* X, Inst *I) - 'ret X' instruction, insert before I + // ReturnInst( null, BB *B) - 'ret void' instruction, insert @ end of B + // ReturnInst(Value* X, BB *B) - 'ret X' instruction, insert @ end of B + // + // NOTE: If the Value* passed is of type void then the constructor behaves as + // if it was passed NULL. + explicit ReturnInst(LLVMContext &C, Value *retVal = 0, + Instruction *InsertBefore = 0); + ReturnInst(LLVMContext &C, Value *retVal, BasicBlock *InsertAtEnd); + explicit ReturnInst(LLVMContext &C, BasicBlock *InsertAtEnd); +protected: + virtual ReturnInst *clone_impl() const; +public: + static ReturnInst* Create(LLVMContext &C, Value *retVal = 0, + Instruction *InsertBefore = 0) { + return new(!!retVal) ReturnInst(C, retVal, InsertBefore); + } + static ReturnInst* Create(LLVMContext &C, Value *retVal, + BasicBlock *InsertAtEnd) { + return new(!!retVal) ReturnInst(C, retVal, InsertAtEnd); + } + static ReturnInst* Create(LLVMContext &C, BasicBlock *InsertAtEnd) { + return new(0) ReturnInst(C, InsertAtEnd); + } + virtual ~ReturnInst(); + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// Convenience accessor. Returns null if there is no return value. + Value *getReturnValue() const { + return getNumOperands() != 0 ? getOperand(0) : 0; + } + + unsigned getNumSuccessors() const { return 0; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return (I->getOpcode() == Instruction::Ret); + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } + private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); +}; + +template <> +struct OperandTraits<ReturnInst> : public VariadicOperandTraits<ReturnInst> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ReturnInst, Value) + +//===----------------------------------------------------------------------===// +// BranchInst Class +//===----------------------------------------------------------------------===// + +//===--------------------------------------------------------------------------- +/// BranchInst - Conditional or Unconditional Branch instruction. +/// +class BranchInst : public TerminatorInst { + /// Ops list - Branches are strange. The operands are ordered: + /// [Cond, FalseDest,] TrueDest. This makes some accessors faster because + /// they don't have to check for cond/uncond branchness. These are mostly + /// accessed relative from op_end(). + BranchInst(const BranchInst &BI); + void AssertOK(); + // BranchInst constructors (where {B, T, F} are blocks, and C is a condition): + // BranchInst(BB *B) - 'br B' + // BranchInst(BB* T, BB *F, Value *C) - 'br C, T, F' + // BranchInst(BB* B, Inst *I) - 'br B' insert before I + // BranchInst(BB* T, BB *F, Value *C, Inst *I) - 'br C, T, F', insert before I + // BranchInst(BB* B, BB *I) - 'br B' insert at end + // BranchInst(BB* T, BB *F, Value *C, BB *I) - 'br C, T, F', insert at end + explicit BranchInst(BasicBlock *IfTrue, Instruction *InsertBefore = 0); + BranchInst(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond, + Instruction *InsertBefore = 0); + BranchInst(BasicBlock *IfTrue, BasicBlock *InsertAtEnd); + BranchInst(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond, + BasicBlock *InsertAtEnd); +protected: + virtual BranchInst *clone_impl() const; +public: + static BranchInst *Create(BasicBlock *IfTrue, Instruction *InsertBefore = 0) { + return new(1) BranchInst(IfTrue, InsertBefore); + } + static BranchInst *Create(BasicBlock *IfTrue, BasicBlock *IfFalse, + Value *Cond, Instruction *InsertBefore = 0) { + return new(3) BranchInst(IfTrue, IfFalse, Cond, InsertBefore); + } + static BranchInst *Create(BasicBlock *IfTrue, BasicBlock *InsertAtEnd) { + return new(1) BranchInst(IfTrue, InsertAtEnd); + } + static BranchInst *Create(BasicBlock *IfTrue, BasicBlock *IfFalse, + Value *Cond, BasicBlock *InsertAtEnd) { + return new(3) BranchInst(IfTrue, IfFalse, Cond, InsertAtEnd); + } + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + bool isUnconditional() const { return getNumOperands() == 1; } + bool isConditional() const { return getNumOperands() == 3; } + + Value *getCondition() const { + assert(isConditional() && "Cannot get condition of an uncond branch!"); + return Op<-3>(); + } + + void setCondition(Value *V) { + assert(isConditional() && "Cannot set condition of unconditional branch!"); + Op<-3>() = V; + } + + unsigned getNumSuccessors() const { return 1+isConditional(); } + + BasicBlock *getSuccessor(unsigned i) const { + assert(i < getNumSuccessors() && "Successor # out of range for Branch!"); + return cast_or_null<BasicBlock>((&Op<-1>() - i)->get()); + } + + void setSuccessor(unsigned idx, BasicBlock *NewSucc) { + assert(idx < getNumSuccessors() && "Successor # out of range for Branch!"); + *(&Op<-1>() - idx) = (Value*)NewSucc; + } + + /// \brief Swap the successors of this branch instruction. + /// + /// Swaps the successors of the branch instruction. This also swaps any + /// branch weight metadata associated with the instruction so that it + /// continues to map correctly to each operand. + void swapSuccessors(); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return (I->getOpcode() == Instruction::Br); + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); +}; + +template <> +struct OperandTraits<BranchInst> : public VariadicOperandTraits<BranchInst, 1> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BranchInst, Value) + +//===----------------------------------------------------------------------===// +// SwitchInst Class +//===----------------------------------------------------------------------===// + +//===--------------------------------------------------------------------------- +/// SwitchInst - Multiway switch +/// +class SwitchInst : public TerminatorInst { + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + unsigned ReservedSpace; + // Operands format: + // Operand[0] = Value to switch on + // Operand[1] = Default basic block destination + // Operand[2n ] = Value to match + // Operand[2n+1] = BasicBlock to go to on match + + // Store case values separately from operands list. We needn't User-Use + // concept here, since it is just a case value, it will always constant, + // and case value couldn't reused with another instructions/values. + // Additionally: + // It allows us to use custom type for case values that is not inherited + // from Value. Since case value is a complex type that implements + // the subset of integers, we needn't extract sub-constants within + // slow getAggregateElement method. + // For case values we will use std::list to by two reasons: + // 1. It allows to add/remove cases without whole collection reallocation. + // 2. In most of cases we needn't random access. + // Currently case values are also stored in Operands List, but it will moved + // out in future commits. + typedef std::list<IntegersSubset> Subsets; + typedef Subsets::iterator SubsetsIt; + typedef Subsets::const_iterator SubsetsConstIt; + + Subsets TheSubsets; + + SwitchInst(const SwitchInst &SI); + void init(Value *Value, BasicBlock *Default, unsigned NumReserved); + void growOperands(); + // allocate space for exactly zero operands + void *operator new(size_t s) { + return User::operator new(s, 0); + } + /// SwitchInst ctor - Create a new switch instruction, specifying a value to + /// switch on and a default destination. The number of additional cases can + /// be specified here to make memory allocation more efficient. This + /// constructor can also autoinsert before another instruction. + SwitchInst(Value *Value, BasicBlock *Default, unsigned NumCases, + Instruction *InsertBefore); + + /// SwitchInst ctor - Create a new switch instruction, specifying a value to + /// switch on and a default destination. The number of additional cases can + /// be specified here to make memory allocation more efficient. This + /// constructor also autoinserts at the end of the specified BasicBlock. + SwitchInst(Value *Value, BasicBlock *Default, unsigned NumCases, + BasicBlock *InsertAtEnd); +protected: + virtual SwitchInst *clone_impl() const; +public: + + // FIXME: Currently there are a lot of unclean template parameters, + // we need to make refactoring in future. + // All these parameters are used to implement both iterator and const_iterator + // without code duplication. + // SwitchInstTy may be "const SwitchInst" or "SwitchInst" + // ConstantIntTy may be "const ConstantInt" or "ConstantInt" + // SubsetsItTy may be SubsetsConstIt or SubsetsIt + // BasicBlockTy may be "const BasicBlock" or "BasicBlock" + template <class SwitchInstTy, class ConstantIntTy, + class SubsetsItTy, class BasicBlockTy> + class CaseIteratorT; + + typedef CaseIteratorT<const SwitchInst, const ConstantInt, + SubsetsConstIt, const BasicBlock> ConstCaseIt; + class CaseIt; + + // -2 + static const unsigned DefaultPseudoIndex = static_cast<unsigned>(~0L-1); + + static SwitchInst *Create(Value *Value, BasicBlock *Default, + unsigned NumCases, Instruction *InsertBefore = 0) { + return new SwitchInst(Value, Default, NumCases, InsertBefore); + } + static SwitchInst *Create(Value *Value, BasicBlock *Default, + unsigned NumCases, BasicBlock *InsertAtEnd) { + return new SwitchInst(Value, Default, NumCases, InsertAtEnd); + } + + ~SwitchInst(); + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + // Accessor Methods for Switch stmt + Value *getCondition() const { return getOperand(0); } + void setCondition(Value *V) { setOperand(0, V); } + + BasicBlock *getDefaultDest() const { + return cast<BasicBlock>(getOperand(1)); + } + + void setDefaultDest(BasicBlock *DefaultCase) { + setOperand(1, reinterpret_cast<Value*>(DefaultCase)); + } + + /// getNumCases - return the number of 'cases' in this switch instruction, + /// except the default case + unsigned getNumCases() const { + return getNumOperands()/2 - 1; + } + + /// Returns a read/write iterator that points to the first + /// case in SwitchInst. + CaseIt case_begin() { + return CaseIt(this, 0, TheSubsets.begin()); + } + /// Returns a read-only iterator that points to the first + /// case in the SwitchInst. + ConstCaseIt case_begin() const { + return ConstCaseIt(this, 0, TheSubsets.begin()); + } + + /// Returns a read/write iterator that points one past the last + /// in the SwitchInst. + CaseIt case_end() { + return CaseIt(this, getNumCases(), TheSubsets.end()); + } + /// Returns a read-only iterator that points one past the last + /// in the SwitchInst. + ConstCaseIt case_end() const { + return ConstCaseIt(this, getNumCases(), TheSubsets.end()); + } + /// Returns an iterator that points to the default case. + /// Note: this iterator allows to resolve successor only. Attempt + /// to resolve case value causes an assertion. + /// Also note, that increment and decrement also causes an assertion and + /// makes iterator invalid. + CaseIt case_default() { + return CaseIt(this, DefaultPseudoIndex, TheSubsets.end()); + } + ConstCaseIt case_default() const { + return ConstCaseIt(this, DefaultPseudoIndex, TheSubsets.end()); + } + + /// findCaseValue - Search all of the case values for the specified constant. + /// If it is explicitly handled, return the case iterator of it, otherwise + /// return default case iterator to indicate + /// that it is handled by the default handler. + CaseIt findCaseValue(const ConstantInt *C) { + for (CaseIt i = case_begin(), e = case_end(); i != e; ++i) + if (i.getCaseValueEx().isSatisfies(IntItem::fromConstantInt(C))) + return i; + return case_default(); + } + ConstCaseIt findCaseValue(const ConstantInt *C) const { + for (ConstCaseIt i = case_begin(), e = case_end(); i != e; ++i) + if (i.getCaseValueEx().isSatisfies(IntItem::fromConstantInt(C))) + return i; + return case_default(); + } + + /// findCaseDest - Finds the unique case value for a given successor. Returns + /// null if the successor is not found, not unique, or is the default case. + ConstantInt *findCaseDest(BasicBlock *BB) { + if (BB == getDefaultDest()) return NULL; + + ConstantInt *CI = NULL; + for (CaseIt i = case_begin(), e = case_end(); i != e; ++i) { + if (i.getCaseSuccessor() == BB) { + if (CI) return NULL; // Multiple cases lead to BB. + else CI = i.getCaseValue(); + } + } + return CI; + } + + /// addCase - Add an entry to the switch instruction... + /// @deprecated + /// Note: + /// This action invalidates case_end(). Old case_end() iterator will + /// point to the added case. + void addCase(ConstantInt *OnVal, BasicBlock *Dest); + + /// addCase - Add an entry to the switch instruction. + /// Note: + /// This action invalidates case_end(). Old case_end() iterator will + /// point to the added case. + void addCase(IntegersSubset& OnVal, BasicBlock *Dest); + + /// removeCase - This method removes the specified case and its successor + /// from the switch instruction. Note that this operation may reorder the + /// remaining cases at index idx and above. + /// Note: + /// This action invalidates iterators for all cases following the one removed, + /// including the case_end() iterator. + void removeCase(CaseIt& i); + + unsigned getNumSuccessors() const { return getNumOperands()/2; } + BasicBlock *getSuccessor(unsigned idx) const { + assert(idx < getNumSuccessors() &&"Successor idx out of range for switch!"); + return cast<BasicBlock>(getOperand(idx*2+1)); + } + void setSuccessor(unsigned idx, BasicBlock *NewSucc) { + assert(idx < getNumSuccessors() && "Successor # out of range for switch!"); + setOperand(idx*2+1, (Value*)NewSucc); + } + + uint16_t hash() const { + uint32_t NumberOfCases = (uint32_t)getNumCases(); + uint16_t Hash = (0xFFFF & NumberOfCases) ^ (NumberOfCases >> 16); + for (ConstCaseIt i = case_begin(), e = case_end(); + i != e; ++i) { + uint32_t NumItems = (uint32_t)i.getCaseValueEx().getNumItems(); + Hash = (Hash << 1) ^ (0xFFFF & NumItems) ^ (NumItems >> 16); + } + return Hash; + } + + // Case iterators definition. + + template <class SwitchInstTy, class ConstantIntTy, + class SubsetsItTy, class BasicBlockTy> + class CaseIteratorT { + protected: + + SwitchInstTy *SI; + unsigned Index; + SubsetsItTy SubsetIt; + + /// Initializes case iterator for given SwitchInst and for given + /// case number. + friend class SwitchInst; + CaseIteratorT(SwitchInstTy *SI, unsigned SuccessorIndex, + SubsetsItTy CaseValueIt) { + this->SI = SI; + Index = SuccessorIndex; + this->SubsetIt = CaseValueIt; + } + + public: + typedef typename SubsetsItTy::reference IntegersSubsetRef; + typedef CaseIteratorT<SwitchInstTy, ConstantIntTy, + SubsetsItTy, BasicBlockTy> Self; + + CaseIteratorT(SwitchInstTy *SI, unsigned CaseNum) { + this->SI = SI; + Index = CaseNum; + SubsetIt = SI->TheSubsets.begin(); + std::advance(SubsetIt, CaseNum); + } + + + /// Initializes case iterator for given SwitchInst and for given + /// TerminatorInst's successor index. + static Self fromSuccessorIndex(SwitchInstTy *SI, unsigned SuccessorIndex) { + assert(SuccessorIndex < SI->getNumSuccessors() && + "Successor index # out of range!"); + return SuccessorIndex != 0 ? + Self(SI, SuccessorIndex - 1) : + Self(SI, DefaultPseudoIndex); + } + + /// Resolves case value for current case. + /// @deprecated + ConstantIntTy *getCaseValue() { + assert(Index < SI->getNumCases() && "Index out the number of cases."); + IntegersSubsetRef CaseRanges = *SubsetIt; + + // FIXME: Currently we work with ConstantInt based cases. + // So return CaseValue as ConstantInt. + return CaseRanges.getSingleNumber(0).toConstantInt(); + } + + /// Resolves case value for current case. + IntegersSubsetRef getCaseValueEx() { + assert(Index < SI->getNumCases() && "Index out the number of cases."); + return *SubsetIt; + } + + /// Resolves successor for current case. + BasicBlockTy *getCaseSuccessor() { + assert((Index < SI->getNumCases() || + Index == DefaultPseudoIndex) && + "Index out the number of cases."); + return SI->getSuccessor(getSuccessorIndex()); + } + + /// Returns number of current case. + unsigned getCaseIndex() const { return Index; } + + /// Returns TerminatorInst's successor index for current case successor. + unsigned getSuccessorIndex() const { + assert((Index == DefaultPseudoIndex || Index < SI->getNumCases()) && + "Index out the number of cases."); + return Index != DefaultPseudoIndex ? Index + 1 : 0; + } + + Self operator++() { + // Check index correctness after increment. + // Note: Index == getNumCases() means end(). + assert(Index+1 <= SI->getNumCases() && "Index out the number of cases."); + ++Index; + if (Index == 0) + SubsetIt = SI->TheSubsets.begin(); + else + ++SubsetIt; + return *this; + } + Self operator++(int) { + Self tmp = *this; + ++(*this); + return tmp; + } + Self operator--() { + // Check index correctness after decrement. + // Note: Index == getNumCases() means end(). + // Also allow "-1" iterator here. That will became valid after ++. + unsigned NumCases = SI->getNumCases(); + assert((Index == 0 || Index-1 <= NumCases) && + "Index out the number of cases."); + --Index; + if (Index == NumCases) { + SubsetIt = SI->TheSubsets.end(); + return *this; + } + + if (Index != -1U) + --SubsetIt; + + return *this; + } + Self operator--(int) { + Self tmp = *this; + --(*this); + return tmp; + } + bool operator==(const Self& RHS) const { + assert(RHS.SI == SI && "Incompatible operators."); + return RHS.Index == Index; + } + bool operator!=(const Self& RHS) const { + assert(RHS.SI == SI && "Incompatible operators."); + return RHS.Index != Index; + } + }; + + class CaseIt : public CaseIteratorT<SwitchInst, ConstantInt, + SubsetsIt, BasicBlock> { + typedef CaseIteratorT<SwitchInst, ConstantInt, SubsetsIt, BasicBlock> + ParentTy; + + protected: + friend class SwitchInst; + CaseIt(SwitchInst *SI, unsigned CaseNum, SubsetsIt SubsetIt) : + ParentTy(SI, CaseNum, SubsetIt) {} + + void updateCaseValueOperand(IntegersSubset& V) { + SI->setOperand(2 + Index*2, reinterpret_cast<Value*>((Constant*)V)); + } + + public: + + CaseIt(SwitchInst *SI, unsigned CaseNum) : ParentTy(SI, CaseNum) {} + + CaseIt(const ParentTy& Src) : ParentTy(Src) {} + + /// Sets the new value for current case. + /// @deprecated. + void setValue(ConstantInt *V) { + assert(Index < SI->getNumCases() && "Index out the number of cases."); + IntegersSubsetToBB Mapping; + // FIXME: Currently we work with ConstantInt based cases. + // So inititalize IntItem container directly from ConstantInt. + Mapping.add(IntItem::fromConstantInt(V)); + *SubsetIt = Mapping.getCase(); + updateCaseValueOperand(*SubsetIt); + } + + /// Sets the new value for current case. + void setValueEx(IntegersSubset& V) { + assert(Index < SI->getNumCases() && "Index out the number of cases."); + *SubsetIt = V; + updateCaseValueOperand(*SubsetIt); + } + + /// Sets the new successor for current case. + void setSuccessor(BasicBlock *S) { + SI->setSuccessor(getSuccessorIndex(), S); + } + }; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Switch; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); +}; + +template <> +struct OperandTraits<SwitchInst> : public HungoffOperandTraits<2> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SwitchInst, Value) + + +//===----------------------------------------------------------------------===// +// IndirectBrInst Class +//===----------------------------------------------------------------------===// + +//===--------------------------------------------------------------------------- +/// IndirectBrInst - Indirect Branch Instruction. +/// +class IndirectBrInst : public TerminatorInst { + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + unsigned ReservedSpace; + // Operand[0] = Value to switch on + // Operand[1] = Default basic block destination + // Operand[2n ] = Value to match + // Operand[2n+1] = BasicBlock to go to on match + IndirectBrInst(const IndirectBrInst &IBI); + void init(Value *Address, unsigned NumDests); + void growOperands(); + // allocate space for exactly zero operands + void *operator new(size_t s) { + return User::operator new(s, 0); + } + /// IndirectBrInst ctor - Create a new indirectbr instruction, specifying an + /// Address to jump to. The number of expected destinations can be specified + /// here to make memory allocation more efficient. This constructor can also + /// autoinsert before another instruction. + IndirectBrInst(Value *Address, unsigned NumDests, Instruction *InsertBefore); + + /// IndirectBrInst ctor - Create a new indirectbr instruction, specifying an + /// Address to jump to. The number of expected destinations can be specified + /// here to make memory allocation more efficient. This constructor also + /// autoinserts at the end of the specified BasicBlock. + IndirectBrInst(Value *Address, unsigned NumDests, BasicBlock *InsertAtEnd); +protected: + virtual IndirectBrInst *clone_impl() const; +public: + static IndirectBrInst *Create(Value *Address, unsigned NumDests, + Instruction *InsertBefore = 0) { + return new IndirectBrInst(Address, NumDests, InsertBefore); + } + static IndirectBrInst *Create(Value *Address, unsigned NumDests, + BasicBlock *InsertAtEnd) { + return new IndirectBrInst(Address, NumDests, InsertAtEnd); + } + ~IndirectBrInst(); + + /// Provide fast operand accessors. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + // Accessor Methods for IndirectBrInst instruction. + Value *getAddress() { return getOperand(0); } + const Value *getAddress() const { return getOperand(0); } + void setAddress(Value *V) { setOperand(0, V); } + + + /// getNumDestinations - return the number of possible destinations in this + /// indirectbr instruction. + unsigned getNumDestinations() const { return getNumOperands()-1; } + + /// getDestination - Return the specified destination. + BasicBlock *getDestination(unsigned i) { return getSuccessor(i); } + const BasicBlock *getDestination(unsigned i) const { return getSuccessor(i); } + + /// addDestination - Add a destination. + /// + void addDestination(BasicBlock *Dest); + + /// removeDestination - This method removes the specified successor from the + /// indirectbr instruction. + void removeDestination(unsigned i); + + unsigned getNumSuccessors() const { return getNumOperands()-1; } + BasicBlock *getSuccessor(unsigned i) const { + return cast<BasicBlock>(getOperand(i+1)); + } + void setSuccessor(unsigned i, BasicBlock *NewSucc) { + setOperand(i+1, (Value*)NewSucc); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::IndirectBr; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); +}; + +template <> +struct OperandTraits<IndirectBrInst> : public HungoffOperandTraits<1> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(IndirectBrInst, Value) + + +//===----------------------------------------------------------------------===// +// InvokeInst Class +//===----------------------------------------------------------------------===// + +/// InvokeInst - Invoke instruction. The SubclassData field is used to hold the +/// calling convention of the call. +/// +class InvokeInst : public TerminatorInst { + AttributeSet AttributeList; + InvokeInst(const InvokeInst &BI); + void init(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, + ArrayRef<Value *> Args, const Twine &NameStr); + + /// Construct an InvokeInst given a range of arguments. + /// + /// \brief Construct an InvokeInst from a range of arguments + inline InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, + ArrayRef<Value *> Args, unsigned Values, + const Twine &NameStr, Instruction *InsertBefore); + + /// Construct an InvokeInst given a range of arguments. + /// + /// \brief Construct an InvokeInst from a range of arguments + inline InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, + ArrayRef<Value *> Args, unsigned Values, + const Twine &NameStr, BasicBlock *InsertAtEnd); +protected: + virtual InvokeInst *clone_impl() const; +public: + static InvokeInst *Create(Value *Func, + BasicBlock *IfNormal, BasicBlock *IfException, + ArrayRef<Value *> Args, const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + unsigned Values = unsigned(Args.size()) + 3; + return new(Values) InvokeInst(Func, IfNormal, IfException, Args, + Values, NameStr, InsertBefore); + } + static InvokeInst *Create(Value *Func, + BasicBlock *IfNormal, BasicBlock *IfException, + ArrayRef<Value *> Args, const Twine &NameStr, + BasicBlock *InsertAtEnd) { + unsigned Values = unsigned(Args.size()) + 3; + return new(Values) InvokeInst(Func, IfNormal, IfException, Args, + Values, NameStr, InsertAtEnd); + } + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// getNumArgOperands - Return the number of invoke arguments. + /// + unsigned getNumArgOperands() const { return getNumOperands() - 3; } + + /// getArgOperand/setArgOperand - Return/set the i-th invoke argument. + /// + Value *getArgOperand(unsigned i) const { return getOperand(i); } + void setArgOperand(unsigned i, Value *v) { setOperand(i, v); } + + /// getCallingConv/setCallingConv - Get or set the calling convention of this + /// function call. + CallingConv::ID getCallingConv() const { + return static_cast<CallingConv::ID>(getSubclassDataFromInstruction()); + } + void setCallingConv(CallingConv::ID CC) { + setInstructionSubclassData(static_cast<unsigned>(CC)); + } + + /// getAttributes - Return the parameter attributes for this invoke. + /// + const AttributeSet &getAttributes() const { return AttributeList; } + + /// setAttributes - Set the parameter attributes for this invoke. + /// + void setAttributes(const AttributeSet &Attrs) { AttributeList = Attrs; } + + /// addAttribute - adds the attribute to the list of attributes. + void addAttribute(unsigned i, Attribute::AttrKind attr); + + /// removeAttribute - removes the attribute from the list of attributes. + void removeAttribute(unsigned i, Attribute attr); + + /// \brief Determine whether this call has the NoAlias attribute. + bool hasFnAttr(Attribute::AttrKind A) const; + + /// \brief Determine whether the call or the callee has the given attributes. + bool paramHasAttr(unsigned i, Attribute::AttrKind A) const; + + /// \brief Extract the alignment for a call or parameter (0=unknown). + unsigned getParamAlignment(unsigned i) const { + return AttributeList.getParamAlignment(i); + } + + /// \brief Return true if the call should not be inlined. + bool isNoInline() const { return hasFnAttr(Attribute::NoInline); } + void setIsNoInline() { + addAttribute(AttributeSet::FunctionIndex, Attribute::NoInline); + } + + /// \brief Determine if the call does not access memory. + bool doesNotAccessMemory() const { + return hasFnAttr(Attribute::ReadNone); + } + void setDoesNotAccessMemory() { + addAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone); + } + + /// \brief Determine if the call does not access or only reads memory. + bool onlyReadsMemory() const { + return doesNotAccessMemory() || hasFnAttr(Attribute::ReadOnly); + } + void setOnlyReadsMemory() { + addAttribute(AttributeSet::FunctionIndex, Attribute::ReadOnly); + } + + /// \brief Determine if the call cannot return. + bool doesNotReturn() const { return hasFnAttr(Attribute::NoReturn); } + void setDoesNotReturn() { + addAttribute(AttributeSet::FunctionIndex, Attribute::NoReturn); + } + + /// \brief Determine if the call cannot unwind. + bool doesNotThrow() const { return hasFnAttr(Attribute::NoUnwind); } + void setDoesNotThrow() { + addAttribute(AttributeSet::FunctionIndex, Attribute::NoUnwind); + } + + /// \brief Determine if the call returns a structure through first + /// pointer argument. + bool hasStructRetAttr() const { + // Be friendly and also check the callee. + return paramHasAttr(1, Attribute::StructRet); + } + + /// \brief Determine if any call argument is an aggregate passed by value. + bool hasByValArgument() const { + return AttributeList.hasAttrSomewhere(Attribute::ByVal); + } + + /// getCalledFunction - Return the function called, or null if this is an + /// indirect function invocation. + /// + Function *getCalledFunction() const { + return dyn_cast<Function>(Op<-3>()); + } + + /// getCalledValue - Get a pointer to the function that is invoked by this + /// instruction + const Value *getCalledValue() const { return Op<-3>(); } + Value *getCalledValue() { return Op<-3>(); } + + /// setCalledFunction - Set the function called. + void setCalledFunction(Value* Fn) { + Op<-3>() = Fn; + } + + // get*Dest - Return the destination basic blocks... + BasicBlock *getNormalDest() const { + return cast<BasicBlock>(Op<-2>()); + } + BasicBlock *getUnwindDest() const { + return cast<BasicBlock>(Op<-1>()); + } + void setNormalDest(BasicBlock *B) { + Op<-2>() = reinterpret_cast<Value*>(B); + } + void setUnwindDest(BasicBlock *B) { + Op<-1>() = reinterpret_cast<Value*>(B); + } + + /// getLandingPadInst - Get the landingpad instruction from the landing pad + /// block (the unwind destination). + LandingPadInst *getLandingPadInst() const; + + BasicBlock *getSuccessor(unsigned i) const { + assert(i < 2 && "Successor # out of range for invoke!"); + return i == 0 ? getNormalDest() : getUnwindDest(); + } + + void setSuccessor(unsigned idx, BasicBlock *NewSucc) { + assert(idx < 2 && "Successor # out of range for invoke!"); + *(&Op<-2>() + idx) = reinterpret_cast<Value*>(NewSucc); + } + + unsigned getNumSuccessors() const { return 2; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return (I->getOpcode() == Instruction::Invoke); + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } + +private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); + + // Shadow Instruction::setInstructionSubclassData with a private forwarding + // method so that subclasses cannot accidentally use it. + void setInstructionSubclassData(unsigned short D) { + Instruction::setInstructionSubclassData(D); + } +}; + +template <> +struct OperandTraits<InvokeInst> : public VariadicOperandTraits<InvokeInst, 3> { +}; + +InvokeInst::InvokeInst(Value *Func, + BasicBlock *IfNormal, BasicBlock *IfException, + ArrayRef<Value *> Args, unsigned Values, + const Twine &NameStr, Instruction *InsertBefore) + : TerminatorInst(cast<FunctionType>(cast<PointerType>(Func->getType()) + ->getElementType())->getReturnType(), + Instruction::Invoke, + OperandTraits<InvokeInst>::op_end(this) - Values, + Values, InsertBefore) { + init(Func, IfNormal, IfException, Args, NameStr); +} +InvokeInst::InvokeInst(Value *Func, + BasicBlock *IfNormal, BasicBlock *IfException, + ArrayRef<Value *> Args, unsigned Values, + const Twine &NameStr, BasicBlock *InsertAtEnd) + : TerminatorInst(cast<FunctionType>(cast<PointerType>(Func->getType()) + ->getElementType())->getReturnType(), + Instruction::Invoke, + OperandTraits<InvokeInst>::op_end(this) - Values, + Values, InsertAtEnd) { + init(Func, IfNormal, IfException, Args, NameStr); +} + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InvokeInst, Value) + +//===----------------------------------------------------------------------===// +// ResumeInst Class +//===----------------------------------------------------------------------===// + +//===--------------------------------------------------------------------------- +/// ResumeInst - Resume the propagation of an exception. +/// +class ResumeInst : public TerminatorInst { + ResumeInst(const ResumeInst &RI); + + explicit ResumeInst(Value *Exn, Instruction *InsertBefore=0); + ResumeInst(Value *Exn, BasicBlock *InsertAtEnd); +protected: + virtual ResumeInst *clone_impl() const; +public: + static ResumeInst *Create(Value *Exn, Instruction *InsertBefore = 0) { + return new(1) ResumeInst(Exn, InsertBefore); + } + static ResumeInst *Create(Value *Exn, BasicBlock *InsertAtEnd) { + return new(1) ResumeInst(Exn, InsertAtEnd); + } + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// Convenience accessor. + Value *getValue() const { return Op<0>(); } + + unsigned getNumSuccessors() const { return 0; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Resume; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); +}; + +template <> +struct OperandTraits<ResumeInst> : + public FixedNumOperandTraits<ResumeInst, 1> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ResumeInst, Value) + +//===----------------------------------------------------------------------===// +// UnreachableInst Class +//===----------------------------------------------------------------------===// + +//===--------------------------------------------------------------------------- +/// UnreachableInst - This function has undefined behavior. In particular, the +/// presence of this instruction indicates some higher level knowledge that the +/// end of the block cannot be reached. +/// +class UnreachableInst : public TerminatorInst { + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; +protected: + virtual UnreachableInst *clone_impl() const; + +public: + // allocate space for exactly zero operands + void *operator new(size_t s) { + return User::operator new(s, 0); + } + explicit UnreachableInst(LLVMContext &C, Instruction *InsertBefore = 0); + explicit UnreachableInst(LLVMContext &C, BasicBlock *InsertAtEnd); + + unsigned getNumSuccessors() const { return 0; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Unreachable; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); +}; + +//===----------------------------------------------------------------------===// +// TruncInst Class +//===----------------------------------------------------------------------===// + +/// \brief This class represents a truncation of integer types. +class TruncInst : public CastInst { +protected: + /// \brief Clone an identical TruncInst + virtual TruncInst *clone_impl() const; + +public: + /// \brief Constructor with insert-before-instruction semantics + TruncInst( + Value *S, ///< The value to be truncated + Type *Ty, ///< The (smaller) type to truncate to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// \brief Constructor with insert-at-end-of-block semantics + TruncInst( + Value *S, ///< The value to be truncated + Type *Ty, ///< The (smaller) type to truncate to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Trunc; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// ZExtInst Class +//===----------------------------------------------------------------------===// + +/// \brief This class represents zero extension of integer types. +class ZExtInst : public CastInst { +protected: + /// \brief Clone an identical ZExtInst + virtual ZExtInst *clone_impl() const; + +public: + /// \brief Constructor with insert-before-instruction semantics + ZExtInst( + Value *S, ///< The value to be zero extended + Type *Ty, ///< The type to zero extend to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// \brief Constructor with insert-at-end semantics. + ZExtInst( + Value *S, ///< The value to be zero extended + Type *Ty, ///< The type to zero extend to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == ZExt; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// SExtInst Class +//===----------------------------------------------------------------------===// + +/// \brief This class represents a sign extension of integer types. +class SExtInst : public CastInst { +protected: + /// \brief Clone an identical SExtInst + virtual SExtInst *clone_impl() const; + +public: + /// \brief Constructor with insert-before-instruction semantics + SExtInst( + Value *S, ///< The value to be sign extended + Type *Ty, ///< The type to sign extend to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// \brief Constructor with insert-at-end-of-block semantics + SExtInst( + Value *S, ///< The value to be sign extended + Type *Ty, ///< The type to sign extend to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == SExt; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// FPTruncInst Class +//===----------------------------------------------------------------------===// + +/// \brief This class represents a truncation of floating point types. +class FPTruncInst : public CastInst { +protected: + /// \brief Clone an identical FPTruncInst + virtual FPTruncInst *clone_impl() const; + +public: + /// \brief Constructor with insert-before-instruction semantics + FPTruncInst( + Value *S, ///< The value to be truncated + Type *Ty, ///< The type to truncate to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// \brief Constructor with insert-before-instruction semantics + FPTruncInst( + Value *S, ///< The value to be truncated + Type *Ty, ///< The type to truncate to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == FPTrunc; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// FPExtInst Class +//===----------------------------------------------------------------------===// + +/// \brief This class represents an extension of floating point types. +class FPExtInst : public CastInst { +protected: + /// \brief Clone an identical FPExtInst + virtual FPExtInst *clone_impl() const; + +public: + /// \brief Constructor with insert-before-instruction semantics + FPExtInst( + Value *S, ///< The value to be extended + Type *Ty, ///< The type to extend to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// \brief Constructor with insert-at-end-of-block semantics + FPExtInst( + Value *S, ///< The value to be extended + Type *Ty, ///< The type to extend to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == FPExt; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// UIToFPInst Class +//===----------------------------------------------------------------------===// + +/// \brief This class represents a cast unsigned integer to floating point. +class UIToFPInst : public CastInst { +protected: + /// \brief Clone an identical UIToFPInst + virtual UIToFPInst *clone_impl() const; + +public: + /// \brief Constructor with insert-before-instruction semantics + UIToFPInst( + Value *S, ///< The value to be converted + Type *Ty, ///< The type to convert to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// \brief Constructor with insert-at-end-of-block semantics + UIToFPInst( + Value *S, ///< The value to be converted + Type *Ty, ///< The type to convert to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == UIToFP; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// SIToFPInst Class +//===----------------------------------------------------------------------===// + +/// \brief This class represents a cast from signed integer to floating point. +class SIToFPInst : public CastInst { +protected: + /// \brief Clone an identical SIToFPInst + virtual SIToFPInst *clone_impl() const; + +public: + /// \brief Constructor with insert-before-instruction semantics + SIToFPInst( + Value *S, ///< The value to be converted + Type *Ty, ///< The type to convert to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// \brief Constructor with insert-at-end-of-block semantics + SIToFPInst( + Value *S, ///< The value to be converted + Type *Ty, ///< The type to convert to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == SIToFP; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// FPToUIInst Class +//===----------------------------------------------------------------------===// + +/// \brief This class represents a cast from floating point to unsigned integer +class FPToUIInst : public CastInst { +protected: + /// \brief Clone an identical FPToUIInst + virtual FPToUIInst *clone_impl() const; + +public: + /// \brief Constructor with insert-before-instruction semantics + FPToUIInst( + Value *S, ///< The value to be converted + Type *Ty, ///< The type to convert to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// \brief Constructor with insert-at-end-of-block semantics + FPToUIInst( + Value *S, ///< The value to be converted + Type *Ty, ///< The type to convert to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< Where to insert the new instruction + ); + + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == FPToUI; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// FPToSIInst Class +//===----------------------------------------------------------------------===// + +/// \brief This class represents a cast from floating point to signed integer. +class FPToSIInst : public CastInst { +protected: + /// \brief Clone an identical FPToSIInst + virtual FPToSIInst *clone_impl() const; + +public: + /// \brief Constructor with insert-before-instruction semantics + FPToSIInst( + Value *S, ///< The value to be converted + Type *Ty, ///< The type to convert to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// \brief Constructor with insert-at-end-of-block semantics + FPToSIInst( + Value *S, ///< The value to be converted + Type *Ty, ///< The type to convert to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == FPToSI; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// IntToPtrInst Class +//===----------------------------------------------------------------------===// + +/// \brief This class represents a cast from an integer to a pointer. +class IntToPtrInst : public CastInst { +public: + /// \brief Constructor with insert-before-instruction semantics + IntToPtrInst( + Value *S, ///< The value to be converted + Type *Ty, ///< The type to convert to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// \brief Constructor with insert-at-end-of-block semantics + IntToPtrInst( + Value *S, ///< The value to be converted + Type *Ty, ///< The type to convert to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// \brief Clone an identical IntToPtrInst + virtual IntToPtrInst *clone_impl() const; + + /// \brief Returns the address space of this instruction's pointer type. + unsigned getAddressSpace() const { + return getType()->getPointerAddressSpace(); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == IntToPtr; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// PtrToIntInst Class +//===----------------------------------------------------------------------===// + +/// \brief This class represents a cast from a pointer to an integer +class PtrToIntInst : public CastInst { +protected: + /// \brief Clone an identical PtrToIntInst + virtual PtrToIntInst *clone_impl() const; + +public: + /// \brief Constructor with insert-before-instruction semantics + PtrToIntInst( + Value *S, ///< The value to be converted + Type *Ty, ///< The type to convert to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// \brief Constructor with insert-at-end-of-block semantics + PtrToIntInst( + Value *S, ///< The value to be converted + Type *Ty, ///< The type to convert to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// \brief Gets the pointer operand. + Value *getPointerOperand() { return getOperand(0); } + /// \brief Gets the pointer operand. + const Value *getPointerOperand() const { return getOperand(0); } + /// \brief Gets the operand index of the pointer operand. + static unsigned getPointerOperandIndex() { return 0U; } + + /// \brief Returns the address space of the pointer operand. + unsigned getPointerAddressSpace() const { + return getPointerOperand()->getType()->getPointerAddressSpace(); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == PtrToInt; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// BitCastInst Class +//===----------------------------------------------------------------------===// + +/// \brief This class represents a no-op cast from one type to another. +class BitCastInst : public CastInst { +protected: + /// \brief Clone an identical BitCastInst + virtual BitCastInst *clone_impl() const; + +public: + /// \brief Constructor with insert-before-instruction semantics + BitCastInst( + Value *S, ///< The value to be casted + Type *Ty, ///< The type to casted to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// \brief Constructor with insert-at-end-of-block semantics + BitCastInst( + Value *S, ///< The value to be casted + Type *Ty, ///< The type to casted to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == BitCast; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/IR/IntrinsicInst.h b/include/llvm/IR/IntrinsicInst.h new file mode 100644 index 0000000..8344c56 --- /dev/null +++ b/include/llvm/IR/IntrinsicInst.h @@ -0,0 +1,316 @@ +//===-- llvm/IntrinsicInst.h - Intrinsic Instruction Wrappers ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines classes that make it really easy to deal with intrinsic +// functions with the isa/dyncast family of functions. In particular, this +// allows you to do things like: +// +// if (MemCpyInst *MCI = dyn_cast<MemCpyInst>(Inst)) +// ... MCI->getDest() ... MCI->getSource() ... +// +// All intrinsic function calls are instances of the call instruction, so these +// are all subclasses of the CallInst class. Note that none of these classes +// has state or virtual methods, which is an important part of this gross/neat +// hack working. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_INTRINSICINST_H +#define LLVM_IR_INTRINSICINST_H + +#include "llvm/IR/Constants.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Intrinsics.h" + +namespace llvm { + /// IntrinsicInst - A useful wrapper class for inspecting calls to intrinsic + /// functions. This allows the standard isa/dyncast/cast functionality to + /// work with calls to intrinsic functions. + class IntrinsicInst : public CallInst { + IntrinsicInst() LLVM_DELETED_FUNCTION; + IntrinsicInst(const IntrinsicInst&) LLVM_DELETED_FUNCTION; + void operator=(const IntrinsicInst&) LLVM_DELETED_FUNCTION; + public: + /// getIntrinsicID - Return the intrinsic ID of this intrinsic. + /// + Intrinsic::ID getIntrinsicID() const { + return (Intrinsic::ID)getCalledFunction()->getIntrinsicID(); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const CallInst *I) { + if (const Function *CF = I->getCalledFunction()) + return CF->isIntrinsic(); + return false; + } + static inline bool classof(const Value *V) { + return isa<CallInst>(V) && classof(cast<CallInst>(V)); + } + }; + + /// DbgInfoIntrinsic - This is the common base class for debug info intrinsics + /// + class DbgInfoIntrinsic : public IntrinsicInst { + public: + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const IntrinsicInst *I) { + switch (I->getIntrinsicID()) { + case Intrinsic::dbg_declare: + case Intrinsic::dbg_value: + return true; + default: return false; + } + } + static inline bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + + static Value *StripCast(Value *C); + }; + + /// DbgDeclareInst - This represents the llvm.dbg.declare instruction. + /// + class DbgDeclareInst : public DbgInfoIntrinsic { + public: + Value *getAddress() const; + MDNode *getVariable() const { return cast<MDNode>(getArgOperand(1)); } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::dbg_declare; + } + static inline bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + }; + + /// DbgValueInst - This represents the llvm.dbg.value instruction. + /// + class DbgValueInst : public DbgInfoIntrinsic { + public: + const Value *getValue() const; + Value *getValue(); + uint64_t getOffset() const { + return cast<ConstantInt>( + const_cast<Value*>(getArgOperand(1)))->getZExtValue(); + } + MDNode *getVariable() const { return cast<MDNode>(getArgOperand(2)); } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::dbg_value; + } + static inline bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + }; + + /// MemIntrinsic - This is the common base class for memset/memcpy/memmove. + /// + class MemIntrinsic : public IntrinsicInst { + public: + Value *getRawDest() const { return const_cast<Value*>(getArgOperand(0)); } + + Value *getLength() const { return const_cast<Value*>(getArgOperand(2)); } + ConstantInt *getAlignmentCst() const { + return cast<ConstantInt>(const_cast<Value*>(getArgOperand(3))); + } + + unsigned getAlignment() const { + return getAlignmentCst()->getZExtValue(); + } + + ConstantInt *getVolatileCst() const { + return cast<ConstantInt>(const_cast<Value*>(getArgOperand(4))); + } + bool isVolatile() const { + return !getVolatileCst()->isZero(); + } + + unsigned getDestAddressSpace() const { + return cast<PointerType>(getRawDest()->getType())->getAddressSpace(); + } + + /// getDest - 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* - 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 setVolatile(Constant* V) { + setArgOperand(4, V); + } + + Type *getAlignmentType() const { + return getArgOperand(3)->getType(); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const IntrinsicInst *I) { + switch (I->getIntrinsicID()) { + case Intrinsic::memcpy: + case Intrinsic::memmove: + case Intrinsic::memset: + return true; + default: return false; + } + } + static inline bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + }; + + /// MemSetInst - This class wraps the llvm.memset intrinsic. + /// + class MemSetInst : public MemIntrinsic { + public: + /// get* - Return the arguments to the instruction. + /// + Value *getValue() const { return const_cast<Value*>(getArgOperand(1)); } + + void setValue(Value *Val) { + assert(getValue()->getType() == Val->getType() && + "setValue called with value of wrong type!"); + setArgOperand(1, Val); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::memset; + } + static inline bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + }; + + /// MemTransferInst - This class wraps the llvm.memcpy/memmove intrinsics. + /// + class MemTransferInst : public MemIntrinsic { + public: + /// get* - Return the arguments to the instruction. + /// + Value *getRawSource() const { return const_cast<Value*>(getArgOperand(1)); } + + /// getSource - 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(1, Ptr); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::memcpy || + I->getIntrinsicID() == Intrinsic::memmove; + } + static inline bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + }; + + + /// MemCpyInst - This class wraps the llvm.memcpy intrinsic. + /// + class MemCpyInst : public MemTransferInst { + public: + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::memcpy; + } + static inline bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + }; + + /// MemMoveInst - This class wraps the llvm.memmove intrinsic. + /// + class MemMoveInst : public MemTransferInst { + public: + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::memmove; + } + static inline bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + }; + + /// VAStartInst - This represents the llvm.va_start intrinsic. + /// + class VAStartInst : public IntrinsicInst { + public: + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::vastart; + } + static inline bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + + Value *getArgList() const { return const_cast<Value*>(getArgOperand(0)); } + }; + + /// VAEndInst - This represents the llvm.va_end intrinsic. + /// + class VAEndInst : public IntrinsicInst { + public: + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::vaend; + } + static inline bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + + Value *getArgList() const { return const_cast<Value*>(getArgOperand(0)); } + }; + + /// VACopyInst - This represents the llvm.va_copy intrinsic. + /// + class VACopyInst : public IntrinsicInst { + public: + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::vacopy; + } + static inline bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + + Value *getDest() const { return const_cast<Value*>(getArgOperand(0)); } + Value *getSrc() const { return const_cast<Value*>(getArgOperand(1)); } + }; + +} + +#endif diff --git a/include/llvm/IR/Intrinsics.h b/include/llvm/IR/Intrinsics.h new file mode 100644 index 0000000..c97cd91 --- /dev/null +++ b/include/llvm/IR/Intrinsics.h @@ -0,0 +1,128 @@ +//===-- llvm/Instrinsics.h - LLVM Intrinsic Function Handling ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a set of enums which allow processing of intrinsic +// functions. Values of these enum types are returned by +// Function::getIntrinsicID. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_INTRINSICS_H +#define LLVM_IR_INTRINSICS_H + +#include "llvm/ADT/ArrayRef.h" +#include <string> + +namespace llvm { + +class Type; +class FunctionType; +class Function; +class LLVMContext; +class Module; +class AttributeSet; + +/// Intrinsic Namespace - This namespace contains an enum with a value for +/// every intrinsic/builtin function known by LLVM. These enum values are +/// returned by Function::getIntrinsicID(). +/// +namespace Intrinsic { + enum ID { + not_intrinsic = 0, // Must be zero + + // Get the intrinsic enums generated from Intrinsics.td +#define GET_INTRINSIC_ENUM_VALUES +#include "llvm/IR/Intrinsics.gen" +#undef GET_INTRINSIC_ENUM_VALUES + , num_intrinsics + }; + + /// Intrinsic::getName(ID) - Return the LLVM name for an intrinsic, such as + /// "llvm.ppc.altivec.lvx". + std::string getName(ID id, ArrayRef<Type*> Tys = ArrayRef<Type*>()); + + /// Intrinsic::getType(ID) - Return the function type for an intrinsic. + /// + FunctionType *getType(LLVMContext &Context, ID id, + ArrayRef<Type*> Tys = ArrayRef<Type*>()); + + /// Intrinsic::isOverloaded(ID) - Returns true if the intrinsic can be + /// overloaded. + bool isOverloaded(ID id); + + /// Intrinsic::getAttributes(ID) - Return the attributes for an intrinsic. + /// + AttributeSet getAttributes(LLVMContext &C, ID id); + + /// Intrinsic::getDeclaration(M, ID) - Create or insert an LLVM Function + /// declaration for an intrinsic, and return it. + /// + /// The Tys and numTys parameters are for intrinsics with overloaded types + /// (e.g., those using iAny, fAny, vAny, or iPTRAny). For a declaration for an + /// overloaded intrinsic, Tys should point to an array of numTys pointers to + /// Type, and must provide exactly one type for each overloaded type in the + /// intrinsic. + Function *getDeclaration(Module *M, ID id, + ArrayRef<Type*> Tys = ArrayRef<Type*>()); + + /// Map a GCC builtin name to an intrinsic ID. + ID getIntrinsicForGCCBuiltin(const char *Prefix, const char *BuiltinName); + + /// IITDescriptor - This is a type descriptor which explains the type + /// requirements of an intrinsic. This is returned by + /// getIntrinsicInfoTableEntries. + struct IITDescriptor { + enum IITDescriptorKind { + Void, MMX, Metadata, Half, Float, Double, + Integer, Vector, Pointer, Struct, + Argument, ExtendVecArgument, TruncVecArgument + } Kind; + + union { + unsigned Integer_Width; + unsigned Float_Width; + unsigned Vector_Width; + unsigned Pointer_AddressSpace; + unsigned Struct_NumElements; + unsigned Argument_Info; + }; + + enum ArgKind { + AK_AnyInteger, + AK_AnyFloat, + AK_AnyVector, + AK_AnyPointer + }; + unsigned getArgumentNumber() const { + assert(Kind == Argument || Kind == ExtendVecArgument || + Kind == TruncVecArgument); + return Argument_Info >> 2; + } + ArgKind getArgumentKind() const { + assert(Kind == Argument || Kind == ExtendVecArgument || + Kind == TruncVecArgument); + return (ArgKind)(Argument_Info&3); + } + + static IITDescriptor get(IITDescriptorKind K, unsigned Field) { + IITDescriptor Result = { K, { Field } }; + return Result; + } + }; + + /// getIntrinsicInfoTableEntries - Return the IIT table descriptor for the + /// specified intrinsic into an array of IITDescriptors. + /// + void getIntrinsicInfoTableEntries(ID id, SmallVectorImpl<IITDescriptor> &T); + +} // End Intrinsic namespace + +} // End llvm namespace + +#endif diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td new file mode 100644 index 0000000..e252664 --- /dev/null +++ b/include/llvm/IR/Intrinsics.td @@ -0,0 +1,484 @@ +//===- Intrinsics.td - Defines all LLVM intrinsics ---------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines properties of all LLVM intrinsics. +// +//===----------------------------------------------------------------------===// + +include "llvm/CodeGen/ValueTypes.td" + +//===----------------------------------------------------------------------===// +// Properties we keep track of for intrinsics. +//===----------------------------------------------------------------------===// + +class IntrinsicProperty; + +// Intr*Mem - Memory properties. An intrinsic is allowed to have at most one of +// these properties set. They are listed from the most aggressive (best to use +// if correct) to the least aggressive. If no property is set, the worst case +// is assumed (it may read and write any memory it can get access to and it may +// have other side effects). + +// IntrNoMem - The intrinsic does not access memory or have any other side +// effects. It may be CSE'd deleted if dead, etc. +def IntrNoMem : IntrinsicProperty; + +// IntrReadArgMem - This intrinsic reads only from memory that one of its +// pointer-typed arguments points to, but may read an unspecified amount. +def IntrReadArgMem : IntrinsicProperty; + +// IntrReadMem - This intrinsic reads from unspecified memory, so it cannot be +// moved across stores. However, it can be reordered otherwise and can be +// deleted if dead. +def IntrReadMem : IntrinsicProperty; + +// IntrReadWriteArgMem - This intrinsic reads and writes only from memory that +// one of its arguments points to, but may access an unspecified amount. The +// reads and writes may be volatile, but except for this it has no other side +// effects. +def IntrReadWriteArgMem : IntrinsicProperty; + +// Commutative - This intrinsic is commutative: X op Y == Y op X. +def Commutative : IntrinsicProperty; + +// Throws - This intrinsic can throw. +def Throws : IntrinsicProperty; + +// NoCapture - The specified argument pointer is not captured by the intrinsic. +class NoCapture<int argNo> : IntrinsicProperty { + int ArgNo = argNo; +} + +def IntrNoReturn : IntrinsicProperty; + +//===----------------------------------------------------------------------===// +// Types used by intrinsics. +//===----------------------------------------------------------------------===// + +class LLVMType<ValueType vt> { + ValueType VT = vt; +} + +class LLVMQualPointerType<LLVMType elty, int addrspace> + : LLVMType<iPTR>{ + LLVMType ElTy = elty; + int AddrSpace = addrspace; +} + +class LLVMPointerType<LLVMType elty> + : LLVMQualPointerType<elty, 0>; + +class LLVMAnyPointerType<LLVMType elty> + : LLVMType<iPTRAny>{ + LLVMType ElTy = elty; +} + +// Match the type of another intrinsic parameter. Number is an index into the +// list of overloaded types for the intrinsic, excluding all the fixed types. +// The Number value must refer to a previously listed type. For example: +// Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_anyfloat_ty, LLVMMatchType<0>]> +// has two overloaded types, the 2nd and 3rd arguments. LLVMMatchType<0> +// refers to the first overloaded type, which is the 2nd argument. +class LLVMMatchType<int num> + : LLVMType<OtherVT>{ + int Number = num; +} + +// Match the type of another intrinsic parameter that is expected to be +// an integral vector type, but change the element size to be twice as wide +// or half as wide as the other type. This is only useful when the intrinsic +// is overloaded, so the matched type should be declared as iAny. +class LLVMExtendedElementVectorType<int num> : LLVMMatchType<num>; +class LLVMTruncatedElementVectorType<int num> : LLVMMatchType<num>; + +def llvm_void_ty : LLVMType<isVoid>; +def llvm_anyint_ty : LLVMType<iAny>; +def llvm_anyfloat_ty : LLVMType<fAny>; +def llvm_anyvector_ty : LLVMType<vAny>; +def llvm_i1_ty : LLVMType<i1>; +def llvm_i8_ty : LLVMType<i8>; +def llvm_i16_ty : LLVMType<i16>; +def llvm_i32_ty : LLVMType<i32>; +def llvm_i64_ty : LLVMType<i64>; +def llvm_half_ty : LLVMType<f16>; +def llvm_float_ty : LLVMType<f32>; +def llvm_double_ty : LLVMType<f64>; +def llvm_f80_ty : LLVMType<f80>; +def llvm_f128_ty : LLVMType<f128>; +def llvm_ppcf128_ty : LLVMType<ppcf128>; +def llvm_ptr_ty : LLVMPointerType<llvm_i8_ty>; // i8* +def llvm_ptrptr_ty : LLVMPointerType<llvm_ptr_ty>; // i8** +def llvm_anyptr_ty : LLVMAnyPointerType<llvm_i8_ty>; // (space)i8* +def llvm_empty_ty : LLVMType<OtherVT>; // { } +def llvm_descriptor_ty : LLVMPointerType<llvm_empty_ty>; // { }* +def llvm_metadata_ty : LLVMType<MetadataVT>; // !{...} + +def llvm_x86mmx_ty : LLVMType<x86mmx>; +def llvm_ptrx86mmx_ty : LLVMPointerType<llvm_x86mmx_ty>; // <1 x i64>* + +def llvm_v2i1_ty : LLVMType<v2i1>; // 2 x i1 +def llvm_v4i1_ty : LLVMType<v4i1>; // 4 x i1 +def llvm_v8i1_ty : LLVMType<v8i1>; // 8 x i1 +def llvm_v16i1_ty : LLVMType<v16i1>; // 16 x i1 +def llvm_v32i1_ty : LLVMType<v32i1>; // 32 x i1 +def llvm_v64i1_ty : LLVMType<v64i1>; // 64 x i1 +def llvm_v2i8_ty : LLVMType<v2i8>; // 2 x i8 +def llvm_v4i8_ty : LLVMType<v4i8>; // 4 x i8 +def llvm_v8i8_ty : LLVMType<v8i8>; // 8 x i8 +def llvm_v16i8_ty : LLVMType<v16i8>; // 16 x i8 +def llvm_v32i8_ty : LLVMType<v32i8>; // 32 x i8 +def llvm_v64i8_ty : LLVMType<v64i8>; // 64 x i8 + +def llvm_v1i16_ty : LLVMType<v1i16>; // 1 x i16 +def llvm_v2i16_ty : LLVMType<v2i16>; // 2 x i16 +def llvm_v4i16_ty : LLVMType<v4i16>; // 4 x i16 +def llvm_v8i16_ty : LLVMType<v8i16>; // 8 x i16 +def llvm_v16i16_ty : LLVMType<v16i16>; // 16 x i16 +def llvm_v32i16_ty : LLVMType<v32i16>; // 32 x i16 + +def llvm_v1i32_ty : LLVMType<v1i32>; // 1 x i32 +def llvm_v2i32_ty : LLVMType<v2i32>; // 2 x i32 +def llvm_v4i32_ty : LLVMType<v4i32>; // 4 x i32 +def llvm_v8i32_ty : LLVMType<v8i32>; // 8 x i32 +def llvm_v16i32_ty : LLVMType<v16i32>; // 16 x i32 +def llvm_v1i64_ty : LLVMType<v1i64>; // 1 x i64 +def llvm_v2i64_ty : LLVMType<v2i64>; // 2 x i64 +def llvm_v4i64_ty : LLVMType<v4i64>; // 4 x i64 +def llvm_v8i64_ty : LLVMType<v8i64>; // 8 x i64 +def llvm_v16i64_ty : LLVMType<v16i64>; // 16 x i64 + +def llvm_v2f32_ty : LLVMType<v2f32>; // 2 x float +def llvm_v4f32_ty : LLVMType<v4f32>; // 4 x float +def llvm_v8f32_ty : LLVMType<v8f32>; // 8 x float +def llvm_v16f32_ty : LLVMType<v16f32>; // 16 x float +def llvm_v2f64_ty : LLVMType<v2f64>; // 2 x double +def llvm_v4f64_ty : LLVMType<v4f64>; // 4 x double +def llvm_v8f64_ty : LLVMType<v8f64>; // 8 x double + +def llvm_vararg_ty : LLVMType<isVoid>; // this means vararg here + + +//===----------------------------------------------------------------------===// +// Intrinsic Definitions. +//===----------------------------------------------------------------------===// + +// Intrinsic class - This is used to define one LLVM intrinsic. The name of the +// intrinsic definition should start with "int_", then match the LLVM intrinsic +// name with the "llvm." prefix removed, and all "."s turned into "_"s. For +// example, llvm.bswap.i16 -> int_bswap_i16. +// +// * RetTypes is a list containing the return types expected for the +// intrinsic. +// * ParamTypes is a list containing the parameter types expected for the +// intrinsic. +// * Properties can be set to describe the behavior of the intrinsic. +// +class SDPatternOperator; +class Intrinsic<list<LLVMType> ret_types, + list<LLVMType> param_types = [], + list<IntrinsicProperty> properties = [], + string name = ""> : SDPatternOperator { + string LLVMName = name; + string TargetPrefix = ""; // Set to a prefix for target-specific intrinsics. + list<LLVMType> RetTypes = ret_types; + list<LLVMType> ParamTypes = param_types; + list<IntrinsicProperty> Properties = properties; + + bit isTarget = 0; +} + +/// GCCBuiltin - If this intrinsic exactly corresponds to a GCC builtin, this +/// specifies the name of the builtin. This provides automatic CBE and CFE +/// support. +class GCCBuiltin<string name> { + string GCCBuiltinName = name; +} + + +//===--------------- Variable Argument Handling Intrinsics ----------------===// +// + +def int_vastart : Intrinsic<[], [llvm_ptr_ty], [], "llvm.va_start">; +def int_vacopy : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty], [], + "llvm.va_copy">; +def int_vaend : Intrinsic<[], [llvm_ptr_ty], [], "llvm.va_end">; + +//===------------------- Garbage Collection Intrinsics --------------------===// +// +def int_gcroot : Intrinsic<[], + [llvm_ptrptr_ty, llvm_ptr_ty]>; +def int_gcread : Intrinsic<[llvm_ptr_ty], + [llvm_ptr_ty, llvm_ptrptr_ty], + [IntrReadArgMem]>; +def int_gcwrite : Intrinsic<[], + [llvm_ptr_ty, llvm_ptr_ty, llvm_ptrptr_ty], + [IntrReadWriteArgMem, NoCapture<1>, NoCapture<2>]>; + +//===--------------------- Code Generator Intrinsics ----------------------===// +// +def int_returnaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>; +def int_frameaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>; + +// Note: we treat stacksave/stackrestore as writemem because we don't otherwise +// model their dependencies on allocas. +def int_stacksave : Intrinsic<[llvm_ptr_ty]>, + GCCBuiltin<"__builtin_stack_save">; +def int_stackrestore : Intrinsic<[], [llvm_ptr_ty]>, + GCCBuiltin<"__builtin_stack_restore">; + +// IntrReadWriteArgMem is more pessimistic than strictly necessary for prefetch, +// however it does conveniently prevent the prefetch from being reordered +// with respect to nearby accesses to the same memory. +def int_prefetch : Intrinsic<[], + [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty], + [IntrReadWriteArgMem, NoCapture<0>]>; +def int_pcmarker : Intrinsic<[], [llvm_i32_ty]>; + +def int_readcyclecounter : Intrinsic<[llvm_i64_ty]>; + +// Stack Protector Intrinsic - The stackprotector intrinsic writes the stack +// guard to the correct place on the stack frame. +def int_stackprotector : Intrinsic<[], [llvm_ptr_ty, llvm_ptrptr_ty], []>; + +//===------------------- Standard C Library Intrinsics --------------------===// +// + +def int_memcpy : Intrinsic<[], + [llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, + llvm_i32_ty, llvm_i1_ty], + [IntrReadWriteArgMem, NoCapture<0>, NoCapture<1>]>; +def int_memmove : Intrinsic<[], + [llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, + llvm_i32_ty, llvm_i1_ty], + [IntrReadWriteArgMem, NoCapture<0>, NoCapture<1>]>; +def int_memset : Intrinsic<[], + [llvm_anyptr_ty, llvm_i8_ty, llvm_anyint_ty, + llvm_i32_ty, llvm_i1_ty], + [IntrReadWriteArgMem, NoCapture<0>]>; + +// These functions do not actually read memory, but they are sensitive to the +// rounding mode. This needs to be modelled separately; in the meantime +// declaring them as reading memory is conservatively correct. +let Properties = [IntrReadMem] in { + def int_sqrt : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_powi : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_i32_ty]>; + def int_sin : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_cos : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_pow : Intrinsic<[llvm_anyfloat_ty], + [LLVMMatchType<0>, LLVMMatchType<0>]>; + def int_log : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_log10: Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_log2 : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_exp : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_exp2 : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_fabs : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_floor : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_ceil : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_trunc : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_rint : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_nearbyint : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; +} + +let Properties = [IntrNoMem] in { + def int_fma : Intrinsic<[llvm_anyfloat_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, + LLVMMatchType<0>]>; + + def int_fmuladd : Intrinsic<[llvm_anyfloat_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, + LLVMMatchType<0>]>; +} + +// NOTE: these are internal interfaces. +def int_setjmp : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>; +def int_longjmp : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], [IntrNoReturn]>; +def int_sigsetjmp : Intrinsic<[llvm_i32_ty] , [llvm_ptr_ty, llvm_i32_ty]>; +def int_siglongjmp : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], [IntrNoReturn]>; + +// Internal interface for object size checking +def int_objectsize : Intrinsic<[llvm_anyint_ty], [llvm_ptr_ty, llvm_i1_ty], + [IntrNoMem]>, + GCCBuiltin<"__builtin_object_size">; + +//===------------------------- Expect Intrinsics --------------------------===// +// +def int_expect : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, + LLVMMatchType<0>], [IntrNoMem]>; + +//===-------------------- Bit Manipulation Intrinsics ---------------------===// +// + +// None of these intrinsics accesses memory at all. +let Properties = [IntrNoMem] in { + def int_bswap: Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; + def int_ctpop: Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; + def int_ctlz : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, llvm_i1_ty]>; + def int_cttz : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, llvm_i1_ty]>; +} + +//===------------------------ Debugger Intrinsics -------------------------===// +// + +// None of these intrinsics accesses memory at all...but that doesn't mean the +// optimizers can change them aggressively. Special handling needed in a few +// places. +let Properties = [IntrNoMem] in { + def int_dbg_declare : Intrinsic<[], + [llvm_metadata_ty, llvm_metadata_ty]>; + def int_dbg_value : Intrinsic<[], + [llvm_metadata_ty, llvm_i64_ty, + llvm_metadata_ty]>; +} + +//===------------------ Exception Handling Intrinsics----------------------===// +// + +// The result of eh.typeid.for depends on the enclosing function, but inside a +// given function it is 'const' and may be CSE'd etc. +def int_eh_typeid_for : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], [IntrNoMem]>; + +def int_eh_return_i32 : Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty]>; +def int_eh_return_i64 : Intrinsic<[], [llvm_i64_ty, llvm_ptr_ty]>; + +def int_eh_unwind_init: Intrinsic<[]>, + GCCBuiltin<"__builtin_unwind_init">; + +def int_eh_dwarf_cfa : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty]>; + +let Properties = [IntrNoMem] in { + def int_eh_sjlj_lsda : Intrinsic<[llvm_ptr_ty]>; + def int_eh_sjlj_callsite : Intrinsic<[], [llvm_i32_ty]>; +} +def int_eh_sjlj_functioncontext : Intrinsic<[], [llvm_ptr_ty]>; +def int_eh_sjlj_setjmp : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>; +def int_eh_sjlj_longjmp : Intrinsic<[], [llvm_ptr_ty], [IntrNoReturn]>; + +//===---------------- Generic Variable Attribute Intrinsics----------------===// +// +def int_var_annotation : Intrinsic<[], + [llvm_ptr_ty, llvm_ptr_ty, + llvm_ptr_ty, llvm_i32_ty], + [], "llvm.var.annotation">; +def int_ptr_annotation : Intrinsic<[LLVMAnyPointerType<llvm_anyint_ty>], + [LLVMMatchType<0>, llvm_ptr_ty, llvm_ptr_ty, + llvm_i32_ty], + [], "llvm.ptr.annotation">; +def int_annotation : Intrinsic<[llvm_anyint_ty], + [LLVMMatchType<0>, llvm_ptr_ty, + llvm_ptr_ty, llvm_i32_ty], + [], "llvm.annotation">; + +//===------------------------ Trampoline Intrinsics -----------------------===// +// +def int_init_trampoline : Intrinsic<[], + [llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty], + [IntrReadWriteArgMem, NoCapture<0>]>, + GCCBuiltin<"__builtin_init_trampoline">; + +def int_adjust_trampoline : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty], + [IntrReadArgMem]>, + GCCBuiltin<"__builtin_adjust_trampoline">; + +//===------------------------ Overflow Intrinsics -------------------------===// +// + +// Expose the carry flag from add operations on two integrals. +def int_sadd_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; +def int_uadd_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; + +def int_ssub_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; +def int_usub_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; + +def int_smul_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; +def int_umul_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; + +//===------------------------- Memory Use Markers -------------------------===// +// +def int_lifetime_start : Intrinsic<[], + [llvm_i64_ty, llvm_ptr_ty], + [IntrReadWriteArgMem, NoCapture<1>]>; +def int_lifetime_end : Intrinsic<[], + [llvm_i64_ty, llvm_ptr_ty], + [IntrReadWriteArgMem, NoCapture<1>]>; +def int_invariant_start : Intrinsic<[llvm_descriptor_ty], + [llvm_i64_ty, llvm_ptr_ty], + [IntrReadWriteArgMem, NoCapture<1>]>; +def int_invariant_end : Intrinsic<[], + [llvm_descriptor_ty, llvm_i64_ty, + llvm_ptr_ty], + [IntrReadWriteArgMem, NoCapture<2>]>; + +//===-------------------------- Other Intrinsics --------------------------===// +// +def int_flt_rounds : Intrinsic<[llvm_i32_ty]>, + GCCBuiltin<"__builtin_flt_rounds">; +def int_trap : Intrinsic<[], [], [IntrNoReturn]>, + GCCBuiltin<"__builtin_trap">; +def int_debugtrap : Intrinsic<[]>, + GCCBuiltin<"__builtin_debugtrap">; + +// NOP: calls/invokes to this intrinsic are removed by codegen +def int_donothing : Intrinsic<[], [], [IntrNoMem]>; + +// Intrisics to support half precision floating point format +let Properties = [IntrNoMem] in { +def int_convert_to_fp16 : Intrinsic<[llvm_i16_ty], [llvm_float_ty]>, + GCCBuiltin<"__gnu_f2h_ieee">; +def int_convert_from_fp16 : Intrinsic<[llvm_float_ty], [llvm_i16_ty]>, + GCCBuiltin<"__gnu_h2f_ieee">; +} + +// These convert intrinsics are to support various conversions between +// various types with rounding and saturation. NOTE: avoid using these +// intrinsics as they might be removed sometime in the future and +// most targets don't support them. +def int_convertff : Intrinsic<[llvm_anyfloat_ty], + [llvm_anyfloat_ty, llvm_i32_ty, llvm_i32_ty]>; +def int_convertfsi : Intrinsic<[llvm_anyfloat_ty], + [llvm_anyint_ty, llvm_i32_ty, llvm_i32_ty]>; +def int_convertfui : Intrinsic<[llvm_anyfloat_ty], + [llvm_anyint_ty, llvm_i32_ty, llvm_i32_ty]>; +def int_convertsif : Intrinsic<[llvm_anyint_ty], + [llvm_anyfloat_ty, llvm_i32_ty, llvm_i32_ty]>; +def int_convertuif : Intrinsic<[llvm_anyint_ty], + [llvm_anyfloat_ty, llvm_i32_ty, llvm_i32_ty]>; +def int_convertss : Intrinsic<[llvm_anyint_ty], + [llvm_anyint_ty, llvm_i32_ty, llvm_i32_ty]>; +def int_convertsu : Intrinsic<[llvm_anyint_ty], + [llvm_anyint_ty, llvm_i32_ty, llvm_i32_ty]>; +def int_convertus : Intrinsic<[llvm_anyint_ty], + [llvm_anyint_ty, llvm_i32_ty, llvm_i32_ty]>; +def int_convertuu : Intrinsic<[llvm_anyint_ty], + [llvm_anyint_ty, llvm_i32_ty, llvm_i32_ty]>; + +//===----------------------------------------------------------------------===// +// Target-specific intrinsics +//===----------------------------------------------------------------------===// + +include "llvm/IR/IntrinsicsPowerPC.td" +include "llvm/IR/IntrinsicsX86.td" +include "llvm/IR/IntrinsicsARM.td" +include "llvm/IR/IntrinsicsXCore.td" +include "llvm/IR/IntrinsicsHexagon.td" +include "llvm/IR/IntrinsicsNVVM.td" +include "llvm/IR/IntrinsicsMips.td" +include "llvm/IR/IntrinsicsR600.td" diff --git a/include/llvm/IR/IntrinsicsARM.td b/include/llvm/IR/IntrinsicsARM.td new file mode 100644 index 0000000..93b1ae1 --- /dev/null +++ b/include/llvm/IR/IntrinsicsARM.td @@ -0,0 +1,429 @@ +//===- IntrinsicsARM.td - Defines ARM intrinsics -----------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the ARM-specific intrinsics. +// +//===----------------------------------------------------------------------===// + + +//===----------------------------------------------------------------------===// +// TLS + +let TargetPrefix = "arm" in { // All intrinsics start with "llvm.arm.". + +def int_arm_thread_pointer : GCCBuiltin<"__builtin_thread_pointer">, + Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; + +//===----------------------------------------------------------------------===// +// Saturating Arithmentic + +def int_arm_qadd : GCCBuiltin<"__builtin_arm_qadd">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, Commutative]>; +def int_arm_qsub : GCCBuiltin<"__builtin_arm_qsub">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_arm_ssat : GCCBuiltin<"__builtin_arm_ssat">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_arm_usat : GCCBuiltin<"__builtin_arm_usat">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; + +//===----------------------------------------------------------------------===// +// Load and Store exclusive doubleword + +def int_arm_strexd : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, + llvm_ptr_ty], [IntrReadWriteArgMem]>; +def int_arm_ldrexd : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [llvm_ptr_ty], + [IntrReadArgMem]>; + +//===----------------------------------------------------------------------===// +// VFP + +def int_arm_get_fpscr : GCCBuiltin<"__builtin_arm_get_fpscr">, + Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>; +def int_arm_set_fpscr : GCCBuiltin<"__builtin_arm_set_fpscr">, + Intrinsic<[], [llvm_i32_ty], []>; +def int_arm_vcvtr : Intrinsic<[llvm_float_ty], [llvm_anyfloat_ty], + [IntrNoMem]>; +def int_arm_vcvtru : Intrinsic<[llvm_float_ty], [llvm_anyfloat_ty], + [IntrNoMem]>; + +//===----------------------------------------------------------------------===// +// Coprocessor + +// Move to coprocessor +def int_arm_mcr : GCCBuiltin<"__builtin_arm_mcr">, + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; +def int_arm_mcr2 : GCCBuiltin<"__builtin_arm_mcr2">, + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; + +// Move from coprocessor +def int_arm_mrc : GCCBuiltin<"__builtin_arm_mrc">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], []>; +def int_arm_mrc2 : GCCBuiltin<"__builtin_arm_mrc2">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], []>; + +// Coprocessor data processing +def int_arm_cdp : GCCBuiltin<"__builtin_arm_cdp">, + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; +def int_arm_cdp2 : GCCBuiltin<"__builtin_arm_cdp2">, + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; + +// Move from two registers to coprocessor +def int_arm_mcrr : GCCBuiltin<"__builtin_arm_mcrr">, + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], []>; +def int_arm_mcrr2 : GCCBuiltin<"__builtin_arm_mcrr2">, + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], []>; + +//===----------------------------------------------------------------------===// +// Advanced SIMD (NEON) + +// The following classes do not correspond directly to GCC builtins. +class Neon_1Arg_Intrinsic + : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>], [IntrNoMem]>; +class Neon_1Arg_Narrow_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMExtendedElementVectorType<0>], [IntrNoMem]>; +class Neon_2Arg_Intrinsic + : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; +class Neon_2Arg_Narrow_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMExtendedElementVectorType<0>, + LLVMExtendedElementVectorType<0>], + [IntrNoMem]>; +class Neon_2Arg_Long_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMTruncatedElementVectorType<0>, + LLVMTruncatedElementVectorType<0>], + [IntrNoMem]>; +class Neon_3Arg_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; +class Neon_3Arg_Long_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, + LLVMTruncatedElementVectorType<0>, + LLVMTruncatedElementVectorType<0>], + [IntrNoMem]>; +class Neon_CvtFxToFP_Intrinsic + : Intrinsic<[llvm_anyfloat_ty], [llvm_anyint_ty, llvm_i32_ty], [IntrNoMem]>; +class Neon_CvtFPToFx_Intrinsic + : Intrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty, llvm_i32_ty], [IntrNoMem]>; + +// The table operands for VTBL and VTBX consist of 1 to 4 v8i8 vectors. +// Besides the table, VTBL has one other v8i8 argument and VTBX has two. +// Overall, the classes range from 2 to 6 v8i8 arguments. +class Neon_Tbl2Arg_Intrinsic + : Intrinsic<[llvm_v8i8_ty], + [llvm_v8i8_ty, llvm_v8i8_ty], [IntrNoMem]>; +class Neon_Tbl3Arg_Intrinsic + : Intrinsic<[llvm_v8i8_ty], + [llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty], [IntrNoMem]>; +class Neon_Tbl4Arg_Intrinsic + : Intrinsic<[llvm_v8i8_ty], + [llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty], + [IntrNoMem]>; +class Neon_Tbl5Arg_Intrinsic + : Intrinsic<[llvm_v8i8_ty], + [llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty, + llvm_v8i8_ty], [IntrNoMem]>; +class Neon_Tbl6Arg_Intrinsic + : Intrinsic<[llvm_v8i8_ty], + [llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty, + llvm_v8i8_ty, llvm_v8i8_ty], [IntrNoMem]>; + +// Arithmetic ops + +let Properties = [IntrNoMem, Commutative] in { + + // Vector Add. + def int_arm_neon_vhadds : Neon_2Arg_Intrinsic; + def int_arm_neon_vhaddu : Neon_2Arg_Intrinsic; + def int_arm_neon_vrhadds : Neon_2Arg_Intrinsic; + def int_arm_neon_vrhaddu : Neon_2Arg_Intrinsic; + def int_arm_neon_vqadds : Neon_2Arg_Intrinsic; + def int_arm_neon_vqaddu : Neon_2Arg_Intrinsic; + def int_arm_neon_vaddhn : Neon_2Arg_Narrow_Intrinsic; + def int_arm_neon_vraddhn : Neon_2Arg_Narrow_Intrinsic; + + // Vector Multiply. + def int_arm_neon_vmulp : Neon_2Arg_Intrinsic; + def int_arm_neon_vqdmulh : Neon_2Arg_Intrinsic; + def int_arm_neon_vqrdmulh : Neon_2Arg_Intrinsic; + def int_arm_neon_vmulls : Neon_2Arg_Long_Intrinsic; + def int_arm_neon_vmullu : Neon_2Arg_Long_Intrinsic; + def int_arm_neon_vmullp : Neon_2Arg_Long_Intrinsic; + def int_arm_neon_vqdmull : Neon_2Arg_Long_Intrinsic; + + // Vector Multiply and Accumulate/Subtract. + def int_arm_neon_vqdmlal : Neon_3Arg_Long_Intrinsic; + def int_arm_neon_vqdmlsl : Neon_3Arg_Long_Intrinsic; + + // Vector Maximum. + def int_arm_neon_vmaxs : Neon_2Arg_Intrinsic; + def int_arm_neon_vmaxu : Neon_2Arg_Intrinsic; + + // Vector Minimum. + def int_arm_neon_vmins : Neon_2Arg_Intrinsic; + def int_arm_neon_vminu : Neon_2Arg_Intrinsic; + + // Vector Reciprocal Step. + def int_arm_neon_vrecps : Neon_2Arg_Intrinsic; + + // Vector Reciprocal Square Root Step. + def int_arm_neon_vrsqrts : Neon_2Arg_Intrinsic; +} + +// Vector Subtract. +def int_arm_neon_vhsubs : Neon_2Arg_Intrinsic; +def int_arm_neon_vhsubu : Neon_2Arg_Intrinsic; +def int_arm_neon_vqsubs : Neon_2Arg_Intrinsic; +def int_arm_neon_vqsubu : Neon_2Arg_Intrinsic; +def int_arm_neon_vsubhn : Neon_2Arg_Narrow_Intrinsic; +def int_arm_neon_vrsubhn : Neon_2Arg_Narrow_Intrinsic; + +// Vector Absolute Compare. +def int_arm_neon_vacged : Intrinsic<[llvm_v2i32_ty], + [llvm_v2f32_ty, llvm_v2f32_ty], + [IntrNoMem]>; +def int_arm_neon_vacgeq : Intrinsic<[llvm_v4i32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; +def int_arm_neon_vacgtd : Intrinsic<[llvm_v2i32_ty], + [llvm_v2f32_ty, llvm_v2f32_ty], + [IntrNoMem]>; +def int_arm_neon_vacgtq : Intrinsic<[llvm_v4i32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + +// Vector Absolute Differences. +def int_arm_neon_vabds : Neon_2Arg_Intrinsic; +def int_arm_neon_vabdu : Neon_2Arg_Intrinsic; + +// Vector Pairwise Add. +def int_arm_neon_vpadd : Neon_2Arg_Intrinsic; + +// Vector Pairwise Add Long. +// Note: This is different than the other "long" NEON intrinsics because +// the result vector has half as many elements as the source vector. +// The source and destination vector types must be specified separately. +def int_arm_neon_vpaddls : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], + [IntrNoMem]>; +def int_arm_neon_vpaddlu : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], + [IntrNoMem]>; + +// Vector Pairwise Add and Accumulate Long. +// Note: This is similar to vpaddl but the destination vector also appears +// as the first argument. +def int_arm_neon_vpadals : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_anyvector_ty], + [IntrNoMem]>; +def int_arm_neon_vpadalu : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_anyvector_ty], + [IntrNoMem]>; + +// Vector Pairwise Maximum and Minimum. +def int_arm_neon_vpmaxs : Neon_2Arg_Intrinsic; +def int_arm_neon_vpmaxu : Neon_2Arg_Intrinsic; +def int_arm_neon_vpmins : Neon_2Arg_Intrinsic; +def int_arm_neon_vpminu : Neon_2Arg_Intrinsic; + +// Vector Shifts: +// +// The various saturating and rounding vector shift operations need to be +// represented by intrinsics in LLVM, and even the basic VSHL variable shift +// operation cannot be safely translated to LLVM's shift operators. VSHL can +// be used for both left and right shifts, or even combinations of the two, +// depending on the signs of the shift amounts. It also has well-defined +// behavior for shift amounts that LLVM leaves undefined. Only basic shifts +// by constants can be represented with LLVM's shift operators. +// +// The shift counts for these intrinsics are always vectors, even for constant +// shifts, where the constant is replicated. For consistency with VSHL (and +// other variable shift instructions), left shifts have positive shift counts +// and right shifts have negative shift counts. This convention is also used +// for constant right shift intrinsics, and to help preserve sanity, the +// intrinsic names use "shift" instead of either "shl" or "shr". Where +// applicable, signed and unsigned versions of the intrinsics are +// distinguished with "s" and "u" suffixes. A few NEON shift instructions, +// such as VQSHLU, take signed operands but produce unsigned results; these +// use a "su" suffix. + +// Vector Shift. +def int_arm_neon_vshifts : Neon_2Arg_Intrinsic; +def int_arm_neon_vshiftu : Neon_2Arg_Intrinsic; +def int_arm_neon_vshiftls : Neon_2Arg_Long_Intrinsic; +def int_arm_neon_vshiftlu : Neon_2Arg_Long_Intrinsic; +def int_arm_neon_vshiftn : Neon_2Arg_Narrow_Intrinsic; + +// Vector Rounding Shift. +def int_arm_neon_vrshifts : Neon_2Arg_Intrinsic; +def int_arm_neon_vrshiftu : Neon_2Arg_Intrinsic; +def int_arm_neon_vrshiftn : Neon_2Arg_Narrow_Intrinsic; + +// Vector Saturating Shift. +def int_arm_neon_vqshifts : Neon_2Arg_Intrinsic; +def int_arm_neon_vqshiftu : Neon_2Arg_Intrinsic; +def int_arm_neon_vqshiftsu : Neon_2Arg_Intrinsic; +def int_arm_neon_vqshiftns : Neon_2Arg_Narrow_Intrinsic; +def int_arm_neon_vqshiftnu : Neon_2Arg_Narrow_Intrinsic; +def int_arm_neon_vqshiftnsu : Neon_2Arg_Narrow_Intrinsic; + +// Vector Saturating Rounding Shift. +def int_arm_neon_vqrshifts : Neon_2Arg_Intrinsic; +def int_arm_neon_vqrshiftu : Neon_2Arg_Intrinsic; +def int_arm_neon_vqrshiftns : Neon_2Arg_Narrow_Intrinsic; +def int_arm_neon_vqrshiftnu : Neon_2Arg_Narrow_Intrinsic; +def int_arm_neon_vqrshiftnsu : Neon_2Arg_Narrow_Intrinsic; + +// Vector Shift and Insert. +def int_arm_neon_vshiftins : Neon_3Arg_Intrinsic; + +// Vector Absolute Value and Saturating Absolute Value. +def int_arm_neon_vabs : Neon_1Arg_Intrinsic; +def int_arm_neon_vqabs : Neon_1Arg_Intrinsic; + +// Vector Saturating Negate. +def int_arm_neon_vqneg : Neon_1Arg_Intrinsic; + +// Vector Count Leading Sign/Zero Bits. +def int_arm_neon_vcls : Neon_1Arg_Intrinsic; +def int_arm_neon_vclz : Neon_1Arg_Intrinsic; + +// Vector Count One Bits. +def int_arm_neon_vcnt : Neon_1Arg_Intrinsic; + +// Vector Reciprocal Estimate. +def int_arm_neon_vrecpe : Neon_1Arg_Intrinsic; + +// Vector Reciprocal Square Root Estimate. +def int_arm_neon_vrsqrte : Neon_1Arg_Intrinsic; + +// Vector Conversions Between Floating-point and Fixed-point. +def int_arm_neon_vcvtfp2fxs : Neon_CvtFPToFx_Intrinsic; +def int_arm_neon_vcvtfp2fxu : Neon_CvtFPToFx_Intrinsic; +def int_arm_neon_vcvtfxs2fp : Neon_CvtFxToFP_Intrinsic; +def int_arm_neon_vcvtfxu2fp : Neon_CvtFxToFP_Intrinsic; + +// Vector Conversions Between Half-Precision and Single-Precision. +def int_arm_neon_vcvtfp2hf + : Intrinsic<[llvm_v4i16_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_arm_neon_vcvthf2fp + : Intrinsic<[llvm_v4f32_ty], [llvm_v4i16_ty], [IntrNoMem]>; + +// Narrowing Saturating Vector Moves. +def int_arm_neon_vqmovns : Neon_1Arg_Narrow_Intrinsic; +def int_arm_neon_vqmovnu : Neon_1Arg_Narrow_Intrinsic; +def int_arm_neon_vqmovnsu : Neon_1Arg_Narrow_Intrinsic; + +// Vector Table Lookup. +// The first 1-4 arguments are the table. +def int_arm_neon_vtbl1 : Neon_Tbl2Arg_Intrinsic; +def int_arm_neon_vtbl2 : Neon_Tbl3Arg_Intrinsic; +def int_arm_neon_vtbl3 : Neon_Tbl4Arg_Intrinsic; +def int_arm_neon_vtbl4 : Neon_Tbl5Arg_Intrinsic; + +// Vector Table Extension. +// Some elements of the destination vector may not be updated, so the original +// value of that vector is passed as the first argument. The next 1-4 +// arguments after that are the table. +def int_arm_neon_vtbx1 : Neon_Tbl3Arg_Intrinsic; +def int_arm_neon_vtbx2 : Neon_Tbl4Arg_Intrinsic; +def int_arm_neon_vtbx3 : Neon_Tbl5Arg_Intrinsic; +def int_arm_neon_vtbx4 : Neon_Tbl6Arg_Intrinsic; + +// De-interleaving vector loads from N-element structures. +// Source operands are the address and alignment. +def int_arm_neon_vld1 : Intrinsic<[llvm_anyvector_ty], + [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; +def int_arm_neon_vld2 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>], + [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; +def int_arm_neon_vld3 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, + LLVMMatchType<0>], + [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; +def int_arm_neon_vld4 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, + LLVMMatchType<0>, LLVMMatchType<0>], + [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; + +// Vector load N-element structure to one lane. +// Source operands are: the address, the N input vectors (since only one +// lane is assigned), the lane number, and the alignment. +def int_arm_neon_vld2lane : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>], + [llvm_ptr_ty, LLVMMatchType<0>, + LLVMMatchType<0>, llvm_i32_ty, + llvm_i32_ty], [IntrReadArgMem]>; +def int_arm_neon_vld3lane : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, + LLVMMatchType<0>], + [llvm_ptr_ty, LLVMMatchType<0>, + LLVMMatchType<0>, LLVMMatchType<0>, + llvm_i32_ty, llvm_i32_ty], + [IntrReadArgMem]>; +def int_arm_neon_vld4lane : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, + LLVMMatchType<0>, LLVMMatchType<0>], + [llvm_ptr_ty, LLVMMatchType<0>, + LLVMMatchType<0>, LLVMMatchType<0>, + LLVMMatchType<0>, llvm_i32_ty, + llvm_i32_ty], [IntrReadArgMem]>; + +// Interleaving vector stores from N-element structures. +// Source operands are: the address, the N vectors, and the alignment. +def int_arm_neon_vst1 : Intrinsic<[], + [llvm_ptr_ty, llvm_anyvector_ty, + llvm_i32_ty], [IntrReadWriteArgMem]>; +def int_arm_neon_vst2 : Intrinsic<[], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>, llvm_i32_ty], + [IntrReadWriteArgMem]>; +def int_arm_neon_vst3 : Intrinsic<[], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>, LLVMMatchType<0>, + llvm_i32_ty], [IntrReadWriteArgMem]>; +def int_arm_neon_vst4 : Intrinsic<[], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>, LLVMMatchType<0>, + LLVMMatchType<0>, llvm_i32_ty], + [IntrReadWriteArgMem]>; + +// Vector store N-element structure from one lane. +// Source operands are: the address, the N vectors, the lane number, and +// the alignment. +def int_arm_neon_vst2lane : Intrinsic<[], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>, llvm_i32_ty, + llvm_i32_ty], [IntrReadWriteArgMem]>; +def int_arm_neon_vst3lane : Intrinsic<[], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>, LLVMMatchType<0>, + llvm_i32_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; +def int_arm_neon_vst4lane : Intrinsic<[], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>, LLVMMatchType<0>, + LLVMMatchType<0>, llvm_i32_ty, + llvm_i32_ty], [IntrReadWriteArgMem]>; + +// Vector bitwise select. +def int_arm_neon_vbsl : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; + +} // end TargetPrefix diff --git a/include/llvm/IR/IntrinsicsHexagon.td b/include/llvm/IR/IntrinsicsHexagon.td new file mode 100644 index 0000000..8a88729 --- /dev/null +++ b/include/llvm/IR/IntrinsicsHexagon.td @@ -0,0 +1,4877 @@ +//===- IntrinsicsHexagon.td - Defines Hexagon intrinsics ---*- tablegen -*-===// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the Hexagon-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Definitions for all Hexagon intrinsics. +// +// All Hexagon intrinsics start with "llvm.hexagon.". +let TargetPrefix = "hexagon" in { + /// Hexagon_Intrinsic - Base class for all Hexagon intrinsics. + class Hexagon_Intrinsic<string GCCIntSuffix, list<LLVMType> ret_types, + list<LLVMType> param_types, + list<IntrinsicProperty> properties> + : GCCBuiltin<!strconcat("__builtin_", GCCIntSuffix)>, + Intrinsic<ret_types, param_types, properties>; +} + +//===----------------------------------------------------------------------===// +// +// DEF_FUNCTION_TYPE_1(QI_ftype_MEM,BT_BOOL,BT_PTR) -> +// Hexagon_qi_mem_Intrinsic<string GCCIntSuffix> +// +class Hexagon_qi_mem_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i1_ty], [llvm_ptr_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_1(void_ftype_SI,BT_VOID,BT_INT) -> +// Hexagon_void_si_Intrinsic<string GCCIntSuffix> +// +class Hexagon_void_si_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_void_ty], [llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_1(HI_ftype_SI,BT_I16,BT_INT) -> +// Hexagon_hi_si_Intrinsic<string GCCIntSuffix> +// +class Hexagon_hi_si_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i16_ty], [llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_1(SI_ftype_SI,BT_INT,BT_INT) -> +// Hexagon_si_si_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_si_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_1(DI_ftype_SI,BT_LONGLONG,BT_INT) -> +// Hexagon_di_si_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_si_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_1(SI_ftype_DI,BT_INT,BT_LONGLONG) -> +// Hexagon_si_di_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_di_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i64_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_1(DI_ftype_DI,BT_LONGLONG,BT_LONGLONG) -> +// Hexagon_di_di_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_di_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i64_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_1(QI_ftype_QI,BT_BOOL,BT_BOOL) -> +// Hexagon_qi_qi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_qi_qi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i1_ty], [llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_1(QI_ftype_SI,BT_BOOL,BT_INT) -> +// Hexagon_qi_si_Intrinsic<string GCCIntSuffix> +// +class Hexagon_qi_si_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i1_ty], [llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_1(DI_ftype_QI,BT_LONGLONG,BT_BOOL) -> +// Hexagon_di_qi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_qi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_1(SI_ftype_QI,BT_INT,BT_BOOL) -> +// Hexagon_si_qi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_qi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(QI_ftype_SISI,BT_BOOL,BT_INT,BT_INT) -> +// Hexagon_qi_sisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_qi_sisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i1_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(void_ftype_SISI,BT_VOID,BT_INT,BT_INT) -> +// Hexagon_void_sisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_void_sisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_void_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(SI_ftype_SISI,BT_INT,BT_INT,BT_INT) -> +// Hexagon_si_sisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_sisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(USI_ftype_SISI,BT_UINT,BT_INT,BT_INT) -> +// Hexagon_usi_sisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_usi_sisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(DI_ftype_SISI,BT_LONGLONG,BT_INT,BT_INT) -> +// Hexagon_di_sisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_sisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(UDI_ftype_SISI,BT_ULONGLONG,BT_INT,BT_INT) -> +// Hexagon_udi_sisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_udi_sisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(DI_ftype_SIDI,BT_LONGLONG,BT_INT,BT_LONGLONG) -> +// Hexagon_di_sidi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_sidi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i32_ty, llvm_i64_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(DI_ftype_DISI,BT_LONGLONG,BT_LONGLONG,BT_INT) -> +// Hexagon_di_disi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_disi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(SI_ftype_SIDI,BT_INT,BT_INT,BT_LONGLONG) -> +// Hexagon_si_sidi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_sidi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i32_ty, llvm_i64_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(SI_ftype_DIDI,BT_INT,BT_LONGLONG,BT_LONGLONG) -> +// Hexagon_si_didi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_didi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i64_ty, llvm_i64_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(DI_ftype_DIDI,BT_LONGLONG,BT_LONGLONG,BT_LONGLONG) -> +// Hexagon_di_didi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_didi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(UDI_ftype_DIDI,BT_ULONGLONG,BT_LONGLONG,BT_LONGLONG) -> +// Hexagon_udi_didi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_udi_didi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(SI_ftype_DISI,BT_INT,BT_LONGLONG,BT_INT) -> +// Hexagon_si_disi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_disi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i64_ty, llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(QI_ftype_DIDI,BT_BOOL,BT_LONGLONG,BT_LONGLONG) -> +// Hexagon_qi_didi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_qi_didi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i1_ty], [llvm_i64_ty, llvm_i64_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(QI_ftype_SIDI,BT_BOOL,BT_INT,BT_LONGLONG) -> +// Hexagon_qi_didi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_qi_sidi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i1_ty], [llvm_i32_ty, llvm_i64_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(QI_ftype_DISI,BT_BOOL,BT_LONGLONG,BT_INT) -> +// Hexagon_qi_disi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_qi_disi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i1_ty], [llvm_i64_ty, llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(QI_ftype_QIQI,BT_BOOL,BT_BOOL,BT_BOOL) -> +// Hexagon_qi_qiqi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_qi_qiqi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i1_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(QI_ftype_QIQIQI,BT_BOOL,BT_BOOL,BT_BOOL) -> +// Hexagon_qi_qiqiqi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_qi_qiqiqi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i1_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(SI_ftype_QIQI,BT_INT,BT_BOOL,BT_BOOL) -> +// Hexagon_si_qiqi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_qiqi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(SI_ftype_QISI,BT_INT,BT_BOOL,BT_INT) -> +// Hexagon_si_qisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_qisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i1_ty, llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_3(void_ftype_SISISI,BT_VOID,BT_INT,BT_INT,BT_INT) -> +// Hexagon_void_sisisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_void_sisisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_void_ty], [llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_3(SI_ftype_SISISI,BT_INT,BT_INT,BT_INT,BT_INT) -> +// Hexagon_si_sisisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_sisisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_3(DI_ftype_SISISI,BT_LONGLONG,BT_INT,BT_INT,BT_INT) -> +// Hexagon_di_sisisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_sisisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_3(SI_ftype_DISISI,BT_INT,BT_LONGLONG,BT_INT,BT_INT) -> +// Hexagon_si_disisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_disisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i64_ty, llvm_i32_ty, + llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_3(DI_ftype_DISISI,BT_LONGLONG,BT_LONGLONG,BT_INT,BT_INT) -> +// Hexagon_di_disisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_disisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty, + llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_3(SI_ftype_SIDISI,BT_INT,BT_INT,BT_LONGLONG,BT_INT) -> +// Hexagon_si_sidisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_sidisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i32_ty, llvm_i64_ty, + llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_3(DI_ftype_DIDISI,BT_LONGLONG,BT_LONGLONG, +// BT_LONGLONG,BT_INT) -> +// Hexagon_di_didisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_didisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty, + llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_3(SI_ftype_SIDIDI,BT_INT,BT_INT,BT_LONGLONG,BT_LONGLONG) -> +// Hexagon_si_sididi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_sididi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i32_ty, llvm_i64_ty, + llvm_i64_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_3(DI_ftype_DIDIDI,BT_LONGLONG,BT_LONGLONG,BT_LONGLONG, +// BT_LONGLONG) -> +// Hexagon_di_dididi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_dididi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty, + llvm_i64_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_3(SI_ftype_SISIDI,BT_INT,BT_INT,BT_INT,BT_LONGLONG) -> +// Hexagon_si_sisidi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_sisidi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, + llvm_i64_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_3(SI_ftype_QISISI,BT_INT,BT_BOOL,BT_INT,BT_INT) -> +// Hexagon_si_qisisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_qisisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_3(DI_ftype_QISISI,BT_LONGLONG,BT_BOOL,BT_INT,BT_INT) -> +// Hexagon_di_qisisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_qisisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i1_ty, llvm_i32_ty, + llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_3(DI_ftype_QIDIDI,BT_LONGLONG,BT_BOOL,BT_LONGLONG, +// BT_LONGLONG) -> +// Hexagon_di_qididi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_qididi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i32_ty, llvm_i64_ty, + llvm_i64_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_3(DI_ftype_DIDIQI,BT_LONGLONG,BT_LONGLONG,BT_LONGLONG, +// BT_BOOL) -> +// Hexagon_di_didiqi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_didiqi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty, + llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_4(SI_ftype_SISISISI,BT_INT,BT_INT,BT_INT,BT_INT,BT_INT) -> +// Hexagon_si_sisisisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_sisisisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_4(DI_ftype_DIDISISI,BT_LONGLONG,BT_LONGLONG, +// BT_LONGLONG,BT_INT,BT_INT) -> +// Hexagon_di_didisisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_didisisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty, + llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + +class Hexagon_mem_memmemsisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_ptr_ty], [llvm_ptr_ty, llvm_ptr_ty, + llvm_i32_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + +// +// Hexagon_sf_df_Intrinsic<string GCCIntSuffix> +// +class Hexagon_sf_si_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_float_ty], [llvm_i32_ty], + [IntrNoMem]>; +// +// Hexagon_sf_df_Intrinsic<string GCCIntSuffix> +// +class Hexagon_sf_df_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_float_ty], [llvm_double_ty], + [IntrNoMem]>; +// +// Hexagon_sf_di_Intrinsic<string GCCIntSuffix> +// +class Hexagon_sf_di_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_float_ty], [llvm_i64_ty], + [IntrNoMem]>; +// +// Hexagon_df_sf_Intrinsic<string GCCIntSuffix> +// +class Hexagon_df_sf_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_double_ty], [llvm_float_ty], + [IntrNoMem]>; +// +// Hexagon_di_sf_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_sf_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_float_ty], + [IntrNoMem]>; +// +// Hexagon_sf_sf_Intrinsic<string GCCIntSuffix> +// +class Hexagon_sf_sf_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_float_ty], [llvm_float_ty], + [IntrNoMem]>; +// +// Hexagon_si_sf_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_sf_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_float_ty], + [IntrNoMem]>; +// +// Hexagon_si_df_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_df_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_double_ty], + [IntrNoMem]>; +// +// Hexagon_sf_sfsf_Intrinsic<string GCCIntSuffix> +// +class Hexagon_sf_sfsf_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_float_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem]>; +// +// Hexagon_qi_sfsf_Intrinsic<string GCCIntSuffix> +// +class Hexagon_qi_sfsf_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i1_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem]>; +// +// Hexagon_qi_sfsi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_qi_sfsi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i1_ty], [llvm_float_ty, llvm_i32_ty], + [IntrNoMem]>; +// +// Hexagon_qi_sfqi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_qi_sfqi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i1_ty], [llvm_float_ty, llvm_i32_ty], + [IntrNoMem]>; +// +// Hexagon_sf_sfsfsf_Intrinsic<string GCCIntSuffix> +// +class Hexagon_sf_sfsfsf_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_float_ty], [llvm_float_ty, llvm_float_ty, + llvm_float_ty], + [IntrNoMem]>; +// +// Hexagon_sf_sfsfsfqi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_sf_sfsfsfqi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_float_ty], [llvm_float_ty, llvm_float_ty, + llvm_float_ty, + llvm_i32_ty], + [IntrNoMem]>; +// +// Hexagon_di_dididi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_dididisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty, + llvm_i64_ty, llvm_i32_ty], + [IntrNoMem]>; +// +// Hexagon_df_si_Intrinsic<string GCCIntSuffix> +// +class Hexagon_df_si_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_double_ty], [llvm_i32_ty], + [IntrNoMem]>; +// +// Hexagon_df_di_Intrinsic<string GCCIntSuffix> +// +class Hexagon_df_di_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_double_ty], [llvm_i64_ty], + [IntrNoMem]>; +// +// Hexagon_di_df_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_df_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_double_ty], + [IntrNoMem]>; +// +// Hexagon_df_df_Intrinsic<string GCCIntSuffix> +// +class Hexagon_df_df_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_double_ty], [llvm_double_ty], + [IntrNoMem]>; +// +// Hexagon_df_dfdf_Intrinsic<string GCCIntSuffix> +// +class Hexagon_df_dfdf_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_double_ty], [llvm_double_ty, llvm_double_ty], + [IntrNoMem]>; +// +// Hexagon_qi_dfdf_Intrinsic<string GCCIntSuffix> +// +class Hexagon_qi_dfdf_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i1_ty], [llvm_double_ty, llvm_double_ty], + [IntrNoMem]>; +// +// Hexagon_qi_dfsi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_qi_dfsi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i1_ty], [llvm_double_ty, llvm_i32_ty], + [IntrNoMem]>; +// +// +// Hexagon_df_dfdfdf_Intrinsic<string GCCIntSuffix> +// +class Hexagon_df_dfdfdf_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_double_ty], [llvm_double_ty, llvm_double_ty, + llvm_double_ty], + [IntrNoMem]>; +// +// Hexagon_df_dfdfdf_Intrinsic<string GCCIntSuffix> +// +class Hexagon_df_dfdfdfqi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_double_ty], [llvm_double_ty, llvm_double_ty, + llvm_double_ty, + llvm_i32_ty], + [IntrNoMem]>; + + +// This one below will not be generated from iset.py. +// So make sure, you don't overwrite this one. +// +// BUILTIN_INFO(SI_to_SXTHI_asrh,SI_ftype_SI,1) +// +def int_hexagon_SI_to_SXTHI_asrh : +Hexagon_si_si_Intrinsic<"SI_to_SXTHI_asrh">; +// +// BUILTIN_INFO_NONCONST(circ_ldd,PTR_ftype_PTRPTRSISI,4) +// +def int_hexagon_circ_ldd : +Hexagon_mem_memmemsisi_Intrinsic<"circ_ldd">; +// This one above will not be generated from iset.py. +// So make sure, you don't overwrite this one. +// +// BUILTIN_INFO(HEXAGON.C2_cmpeq,QI_ftype_SISI,2) +// +def int_hexagon_C2_cmpeq : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpeq">; +// +// BUILTIN_INFO(HEXAGON.C2_cmpgt,QI_ftype_SISI,2) +// +def int_hexagon_C2_cmpgt : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgt">; +// +// BUILTIN_INFO(HEXAGON.C2_cmpgtu,QI_ftype_SISI,2) +// +def int_hexagon_C2_cmpgtu : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgtu">; +// +// BUILTIN_INFO(HEXAGON.C2_cmpeqp,QI_ftype_DIDI,2) +// +def int_hexagon_C2_cmpeqp : +Hexagon_qi_didi_Intrinsic<"HEXAGON_C2_cmpeqp">; +// +// BUILTIN_INFO(HEXAGON.C2_cmpgtp,QI_ftype_DIDI,2) +// +def int_hexagon_C2_cmpgtp : +Hexagon_qi_didi_Intrinsic<"HEXAGON_C2_cmpgtp">; +// +// BUILTIN_INFO(HEXAGON.C2_cmpgtup,QI_ftype_DIDI,2) +// +def int_hexagon_C2_cmpgtup : +Hexagon_qi_didi_Intrinsic<"HEXAGON_C2_cmpgtup">; +// +// BUILTIN_INFO(HEXAGON.A4_rcmpeqi,SI_ftype_SISI,2) +// +def int_hexagon_A4_rcmpeqi : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_rcmpeqi">; +// +// BUILTIN_INFO(HEXAGON.A4_rcmpneqi,SI_ftype_SISI,2) +// +def int_hexagon_A4_rcmpneqi : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_rcmpneqi">; +// +// BUILTIN_INFO(HEXAGON.A4_rcmpeq,SI_ftype_SISI,2) +// +def int_hexagon_A4_rcmpeq : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_rcmpeq">; +// +// BUILTIN_INFO(HEXAGON.A4_rcmpneq,SI_ftype_SISI,2) +// +def int_hexagon_A4_rcmpneq : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_rcmpneq">; +// +// BUILTIN_INFO(HEXAGON.C2_bitsset,QI_ftype_SISI,2) +// +def int_hexagon_C2_bitsset : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_bitsset">; +// +// BUILTIN_INFO(HEXAGON.C2_bitsclr,QI_ftype_SISI,2) +// +def int_hexagon_C2_bitsclr : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_bitsclr">; +// +// BUILTIN_INFO(HEXAGON.C4_nbitsset,QI_ftype_SISI,2) +// +def int_hexagon_C4_nbitsset : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_nbitsset">; +// +// BUILTIN_INFO(HEXAGON.C4_nbitsclr,QI_ftype_SISI,2) +// +def int_hexagon_C4_nbitsclr : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_nbitsclr">; +// +// BUILTIN_INFO(HEXAGON.C2_cmpeqi,QI_ftype_SISI,2) +// +def int_hexagon_C2_cmpeqi : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpeqi">; +// +// BUILTIN_INFO(HEXAGON.C2_cmpgti,QI_ftype_SISI,2) +// +def int_hexagon_C2_cmpgti : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgti">; +// +// BUILTIN_INFO(HEXAGON.C2_cmpgtui,QI_ftype_SISI,2) +// +def int_hexagon_C2_cmpgtui : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgtui">; +// +// BUILTIN_INFO(HEXAGON.C2_cmpgei,QI_ftype_SISI,2) +// +def int_hexagon_C2_cmpgei : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgei">; +// +// BUILTIN_INFO(HEXAGON.C2_cmpgeui,QI_ftype_SISI,2) +// +def int_hexagon_C2_cmpgeui : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgeui">; +// +// BUILTIN_INFO(HEXAGON.C2_cmplt,QI_ftype_SISI,2) +// +def int_hexagon_C2_cmplt : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmplt">; +// +// BUILTIN_INFO(HEXAGON.C2_cmpltu,QI_ftype_SISI,2) +// +def int_hexagon_C2_cmpltu : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpltu">; +// +// BUILTIN_INFO(HEXAGON.C2_bitsclri,QI_ftype_SISI,2) +// +def int_hexagon_C2_bitsclri : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_bitsclri">; +// +// BUILTIN_INFO(HEXAGON.C4_nbitsclri,QI_ftype_SISI,2) +// +def int_hexagon_C4_nbitsclri : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_nbitsclri">; +// +// BUILTIN_INFO(HEXAGON.C4_cmpneqi,QI_ftype_SISI,2) +// +def int_hexagon_C4_cmpneqi : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmpneqi">; +// +// BUILTIN_INFO(HEXAGON.C4_cmpltei,QI_ftype_SISI,2) +// +def int_hexagon_C4_cmpltei : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmpltei">; +// +// BUILTIN_INFO(HEXAGON.C4_cmplteui,QI_ftype_SISI,2) +// +def int_hexagon_C4_cmplteui : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmplteui">; +// +// BUILTIN_INFO(HEXAGON.C4_cmpneq,QI_ftype_SISI,2) +// +def int_hexagon_C4_cmpneq : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmpneq">; +// +// BUILTIN_INFO(HEXAGON.C4_cmplte,QI_ftype_SISI,2) +// +def int_hexagon_C4_cmplte : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmplte">; +// +// BUILTIN_INFO(HEXAGON.C4_cmplteu,QI_ftype_SISI,2) +// +def int_hexagon_C4_cmplteu : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmplteu">; +// +// BUILTIN_INFO(HEXAGON.C2_and,QI_ftype_QIQI,2) +// +def int_hexagon_C2_and : +Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_and">; +// +// BUILTIN_INFO(HEXAGON.C2_or,QI_ftype_QIQI,2) +// +def int_hexagon_C2_or : +Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_or">; +// +// BUILTIN_INFO(HEXAGON.C2_xor,QI_ftype_QIQI,2) +// +def int_hexagon_C2_xor : +Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_xor">; +// +// BUILTIN_INFO(HEXAGON.C2_andn,QI_ftype_QIQI,2) +// +def int_hexagon_C2_andn : +Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_andn">; +// +// BUILTIN_INFO(HEXAGON.C2_not,QI_ftype_QI,1) +// +def int_hexagon_C2_not : +Hexagon_qi_qi_Intrinsic<"HEXAGON_C2_not">; +// +// BUILTIN_INFO(HEXAGON.C2_orn,QI_ftype_QIQI,2) +// +def int_hexagon_C2_orn : +Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_orn">; +// +// BUILTIN_INFO(HEXAGON.C4_and_and,QI_ftype_QIQIQI,3) +// +def int_hexagon_C4_and_and : +Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_and_and">; +// +// BUILTIN_INFO(HEXAGON.C4_and_or,QI_ftype_QIQIQI,3) +// +def int_hexagon_C4_and_or : +Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_and_or">; +// +// BUILTIN_INFO(HEXAGON.C4_or_and,QI_ftype_QIQIQI,3) +// +def int_hexagon_C4_or_and : +Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_or_and">; +// +// BUILTIN_INFO(HEXAGON.C4_or_or,QI_ftype_QIQIQI,3) +// +def int_hexagon_C4_or_or : +Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_or_or">; +// +// BUILTIN_INFO(HEXAGON.C4_and_andn,QI_ftype_QIQIQI,3) +// +def int_hexagon_C4_and_andn : +Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_and_andn">; +// +// BUILTIN_INFO(HEXAGON.C4_and_orn,QI_ftype_QIQIQI,3) +// +def int_hexagon_C4_and_orn : +Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_and_orn">; +// +// BUILTIN_INFO(HEXAGON.C4_or_andn,QI_ftype_QIQIQI,3) +// +def int_hexagon_C4_or_andn : +Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_or_andn">; +// +// BUILTIN_INFO(HEXAGON.C4_or_orn,QI_ftype_QIQIQI,3) +// +def int_hexagon_C4_or_orn : +Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_or_orn">; +// +// BUILTIN_INFO(HEXAGON.C2_pxfer_map,QI_ftype_QI,1) +// +def int_hexagon_C2_pxfer_map : +Hexagon_qi_qi_Intrinsic<"HEXAGON_C2_pxfer_map">; +// +// BUILTIN_INFO(HEXAGON.C2_any8,QI_ftype_QI,1) +// +def int_hexagon_C2_any8 : +Hexagon_qi_qi_Intrinsic<"HEXAGON_C2_any8">; +// +// BUILTIN_INFO(HEXAGON.C2_all8,QI_ftype_QI,1) +// +def int_hexagon_C2_all8 : +Hexagon_qi_qi_Intrinsic<"HEXAGON_C2_all8">; +// +// BUILTIN_INFO(HEXAGON.C2_vitpack,SI_ftype_QIQI,2) +// +def int_hexagon_C2_vitpack : +Hexagon_si_qiqi_Intrinsic<"HEXAGON_C2_vitpack">; +// +// BUILTIN_INFO(HEXAGON.C2_mux,SI_ftype_QISISI,3) +// +def int_hexagon_C2_mux : +Hexagon_si_qisisi_Intrinsic<"HEXAGON_C2_mux">; +// +// BUILTIN_INFO(HEXAGON.C2_muxii,SI_ftype_QISISI,3) +// +def int_hexagon_C2_muxii : +Hexagon_si_qisisi_Intrinsic<"HEXAGON_C2_muxii">; +// +// BUILTIN_INFO(HEXAGON.C2_muxir,SI_ftype_QISISI,3) +// +def int_hexagon_C2_muxir : +Hexagon_si_qisisi_Intrinsic<"HEXAGON_C2_muxir">; +// +// BUILTIN_INFO(HEXAGON.C2_muxri,SI_ftype_QISISI,3) +// +def int_hexagon_C2_muxri : +Hexagon_si_qisisi_Intrinsic<"HEXAGON_C2_muxri">; +// +// BUILTIN_INFO(HEXAGON.C2_vmux,DI_ftype_QIDIDI,3) +// +def int_hexagon_C2_vmux : +Hexagon_di_qididi_Intrinsic<"HEXAGON_C2_vmux">; +// +// BUILTIN_INFO(HEXAGON.C2_mask,DI_ftype_QI,1) +// +def int_hexagon_C2_mask : +Hexagon_di_qi_Intrinsic<"HEXAGON_C2_mask">; +// +// BUILTIN_INFO(HEXAGON.A2_vcmpbeq,QI_ftype_DIDI,2) +// +def int_hexagon_A2_vcmpbeq : +Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpbeq">; +// +// BUILTIN_INFO(HEXAGON.A4_vcmpbeqi,QI_ftype_DISI,2) +// +def int_hexagon_A4_vcmpbeqi : +Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpbeqi">; +// +// BUILTIN_INFO(HEXAGON.A4_vcmpbeq_any,QI_ftype_DIDI,2) +// +def int_hexagon_A4_vcmpbeq_any : +Hexagon_qi_didi_Intrinsic<"HEXAGON_A4_vcmpbeq_any">; +// +// BUILTIN_INFO(HEXAGON.A2_vcmpbgtu,QI_ftype_DIDI,2) +// +def int_hexagon_A2_vcmpbgtu : +Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpbgtu">; +// +// BUILTIN_INFO(HEXAGON.A4_vcmpbgtui,QI_ftype_DISI,2) +// +def int_hexagon_A4_vcmpbgtui : +Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpbgtui">; +// +// BUILTIN_INFO(HEXAGON.A4_vcmpbgt,QI_ftype_DIDI,2) +// +def int_hexagon_A4_vcmpbgt : +Hexagon_qi_didi_Intrinsic<"HEXAGON_A4_vcmpbgt">; +// +// BUILTIN_INFO(HEXAGON.A4_vcmpbgti,QI_ftype_DISI,2) +// +def int_hexagon_A4_vcmpbgti : +Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpbgti">; +// +// BUILTIN_INFO(HEXAGON.A4_cmpbeq,QI_ftype_SISI,2) +// +def int_hexagon_A4_cmpbeq : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbeq">; +// +// BUILTIN_INFO(HEXAGON.A4_cmpbeqi,QI_ftype_SISI,2) +// +def int_hexagon_A4_cmpbeqi : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbeqi">; +// +// BUILTIN_INFO(HEXAGON.A4_cmpbgtu,QI_ftype_SISI,2) +// +def int_hexagon_A4_cmpbgtu : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbgtu">; +// +// BUILTIN_INFO(HEXAGON.A4_cmpbgtui,QI_ftype_SISI,2) +// +def int_hexagon_A4_cmpbgtui : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbgtui">; +// +// BUILTIN_INFO(HEXAGON.A4_cmpbgt,QI_ftype_SISI,2) +// +def int_hexagon_A4_cmpbgt : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbgt">; +// +// BUILTIN_INFO(HEXAGON.A4_cmpbgti,QI_ftype_SISI,2) +// +def int_hexagon_A4_cmpbgti : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbgti">; +// +// BUILTIN_INFO(HEXAGON.A2_vcmpheq,QI_ftype_DIDI,2) +// +def int_hexagon_A2_vcmpheq : +Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpheq">; +// +// BUILTIN_INFO(HEXAGON.A2_vcmphgt,QI_ftype_DIDI,2) +// +def int_hexagon_A2_vcmphgt : +Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmphgt">; +// +// BUILTIN_INFO(HEXAGON.A2_vcmphgtu,QI_ftype_DIDI,2) +// +def int_hexagon_A2_vcmphgtu : +Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmphgtu">; +// +// BUILTIN_INFO(HEXAGON.A4_vcmpheqi,QI_ftype_DISI,2) +// +def int_hexagon_A4_vcmpheqi : +Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpheqi">; +// +// BUILTIN_INFO(HEXAGON.A4_vcmphgti,QI_ftype_DISI,2) +// +def int_hexagon_A4_vcmphgti : +Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmphgti">; +// +// BUILTIN_INFO(HEXAGON.A4_vcmphgtui,QI_ftype_DISI,2) +// +def int_hexagon_A4_vcmphgtui : +Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmphgtui">; +// +// BUILTIN_INFO(HEXAGON.A4_cmpheq,QI_ftype_SISI,2) +// +def int_hexagon_A4_cmpheq : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpheq">; +// +// BUILTIN_INFO(HEXAGON.A4_cmphgt,QI_ftype_SISI,2) +// +def int_hexagon_A4_cmphgt : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmphgt">; +// +// BUILTIN_INFO(HEXAGON.A4_cmphgtu,QI_ftype_SISI,2) +// +def int_hexagon_A4_cmphgtu : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmphgtu">; +// +// BUILTIN_INFO(HEXAGON.A4_cmpheqi,QI_ftype_SISI,2) +// +def int_hexagon_A4_cmpheqi : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpheqi">; +// +// BUILTIN_INFO(HEXAGON.A4_cmphgti,QI_ftype_SISI,2) +// +def int_hexagon_A4_cmphgti : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmphgti">; +// +// BUILTIN_INFO(HEXAGON.A4_cmphgtui,QI_ftype_SISI,2) +// +def int_hexagon_A4_cmphgtui : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmphgtui">; +// +// BUILTIN_INFO(HEXAGON.A2_vcmpweq,QI_ftype_DIDI,2) +// +def int_hexagon_A2_vcmpweq : +Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpweq">; +// +// BUILTIN_INFO(HEXAGON.A2_vcmpwgt,QI_ftype_DIDI,2) +// +def int_hexagon_A2_vcmpwgt : +Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpwgt">; +// +// BUILTIN_INFO(HEXAGON.A2_vcmpwgtu,QI_ftype_DIDI,2) +// +def int_hexagon_A2_vcmpwgtu : +Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpwgtu">; +// +// BUILTIN_INFO(HEXAGON.A4_vcmpweqi,QI_ftype_DISI,2) +// +def int_hexagon_A4_vcmpweqi : +Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpweqi">; +// +// BUILTIN_INFO(HEXAGON.A4_vcmpwgti,QI_ftype_DISI,2) +// +def int_hexagon_A4_vcmpwgti : +Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpwgti">; +// +// BUILTIN_INFO(HEXAGON.A4_vcmpwgtui,QI_ftype_DISI,2) +// +def int_hexagon_A4_vcmpwgtui : +Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpwgtui">; +// +// BUILTIN_INFO(HEXAGON.A4_boundscheck,QI_ftype_SIDI,2) +// +def int_hexagon_A4_boundscheck : +Hexagon_qi_sidi_Intrinsic<"HEXAGON_A4_boundscheck">; +// +// BUILTIN_INFO(HEXAGON.A4_tlbmatch,QI_ftype_DISI,2) +// +def int_hexagon_A4_tlbmatch : +Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_tlbmatch">; +// +// BUILTIN_INFO(HEXAGON.C2_tfrpr,SI_ftype_QI,1) +// +def int_hexagon_C2_tfrpr : +Hexagon_si_qi_Intrinsic<"HEXAGON_C2_tfrpr">; +// +// BUILTIN_INFO(HEXAGON.C2_tfrrp,QI_ftype_SI,1) +// +def int_hexagon_C2_tfrrp : +Hexagon_qi_si_Intrinsic<"HEXAGON_C2_tfrrp">; +// +// BUILTIN_INFO(HEXAGON.C4_fastcorner9,QI_ftype_QIQI,2) +// +def int_hexagon_C4_fastcorner9 : +Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C4_fastcorner9">; +// +// BUILTIN_INFO(HEXAGON.C4_fastcorner9_not,QI_ftype_QIQI,2) +// +def int_hexagon_C4_fastcorner9_not : +Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C4_fastcorner9_not">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_acc_hh_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_acc_hh_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpy_acc_hh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_acc_hh_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_acc_hh_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpy_acc_hh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_acc_hl_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_acc_hl_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpy_acc_hl_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_acc_hl_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_acc_hl_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpy_acc_hl_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_acc_lh_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_acc_lh_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpy_acc_lh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_acc_lh_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_acc_lh_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpy_acc_lh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_acc_ll_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_acc_ll_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpy_acc_ll_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_acc_ll_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_acc_ll_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpy_acc_ll_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_nac_hh_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_nac_hh_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpy_nac_hh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_nac_hh_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_nac_hh_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpy_nac_hh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_nac_hl_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_nac_hl_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpy_nac_hl_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_nac_hl_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_nac_hl_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpy_nac_hl_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_nac_lh_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_nac_lh_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpy_nac_lh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_nac_lh_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_nac_lh_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpy_nac_lh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_nac_ll_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_nac_ll_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpy_nac_ll_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_nac_ll_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_nac_ll_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpy_nac_ll_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_acc_sat_hh_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_acc_sat_hh_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpy_acc_sat_hh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_acc_sat_hh_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_acc_sat_hh_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpy_acc_sat_hh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_acc_sat_hl_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_acc_sat_hl_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpy_acc_sat_hl_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_acc_sat_hl_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_acc_sat_hl_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpy_acc_sat_hl_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_acc_sat_lh_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_acc_sat_lh_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpy_acc_sat_lh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_acc_sat_lh_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_acc_sat_lh_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpy_acc_sat_lh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_acc_sat_ll_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_acc_sat_ll_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpy_acc_sat_ll_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_acc_sat_ll_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_acc_sat_ll_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpy_acc_sat_ll_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_nac_sat_hh_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_nac_sat_hh_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpy_nac_sat_hh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_nac_sat_hh_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_nac_sat_hh_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpy_nac_sat_hh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_nac_sat_hl_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_nac_sat_hl_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpy_nac_sat_hl_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_nac_sat_hl_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_nac_sat_hl_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpy_nac_sat_hl_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_nac_sat_lh_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_nac_sat_lh_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpy_nac_sat_lh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_nac_sat_lh_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_nac_sat_lh_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpy_nac_sat_lh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_nac_sat_ll_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_nac_sat_ll_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpy_nac_sat_ll_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_nac_sat_ll_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_nac_sat_ll_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpy_nac_sat_ll_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_hh_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_hh_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_hh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_hh_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_hh_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_hh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_hl_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_hl_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_hl_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_hl_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_hl_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_hl_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_lh_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_lh_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_lh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_lh_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_lh_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_lh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_ll_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_ll_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_ll_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_ll_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_ll_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_ll_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_sat_hh_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_sat_hh_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_sat_hh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_sat_hh_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_sat_hh_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_sat_hh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_sat_hl_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_sat_hl_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_sat_hl_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_sat_hl_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_sat_hl_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_sat_hl_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_sat_lh_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_sat_lh_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_sat_lh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_sat_lh_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_sat_lh_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_sat_lh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_sat_ll_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_sat_ll_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_sat_ll_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_sat_ll_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_sat_ll_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_sat_ll_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_rnd_hh_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_rnd_hh_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_rnd_hh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_rnd_hh_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_rnd_hh_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_rnd_hh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_rnd_hl_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_rnd_hl_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_rnd_hl_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_rnd_hl_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_rnd_hl_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_rnd_hl_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_rnd_lh_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_rnd_lh_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_rnd_lh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_rnd_lh_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_rnd_lh_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_rnd_lh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_rnd_ll_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_rnd_ll_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_rnd_ll_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_rnd_ll_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_rnd_ll_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_rnd_ll_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_sat_rnd_hh_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_sat_rnd_hh_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_sat_rnd_hh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_sat_rnd_hh_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_sat_rnd_hh_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_sat_rnd_hh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_sat_rnd_hl_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_sat_rnd_hl_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_sat_rnd_hl_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_sat_rnd_hl_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_sat_rnd_hl_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_sat_rnd_hl_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_sat_rnd_lh_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_sat_rnd_lh_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_sat_rnd_lh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_sat_rnd_lh_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_sat_rnd_lh_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_sat_rnd_lh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_sat_rnd_ll_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_sat_rnd_ll_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_sat_rnd_ll_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_sat_rnd_ll_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_sat_rnd_ll_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_sat_rnd_ll_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_acc_hh_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyd_acc_hh_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_mpyd_acc_hh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_acc_hh_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyd_acc_hh_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_mpyd_acc_hh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_acc_hl_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyd_acc_hl_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_mpyd_acc_hl_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_acc_hl_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyd_acc_hl_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_mpyd_acc_hl_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_acc_lh_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyd_acc_lh_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_mpyd_acc_lh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_acc_lh_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyd_acc_lh_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_mpyd_acc_lh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_acc_ll_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyd_acc_ll_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_mpyd_acc_ll_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_acc_ll_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyd_acc_ll_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_mpyd_acc_ll_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_nac_hh_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyd_nac_hh_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_mpyd_nac_hh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_nac_hh_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyd_nac_hh_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_mpyd_nac_hh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_nac_hl_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyd_nac_hl_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_mpyd_nac_hl_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_nac_hl_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyd_nac_hl_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_mpyd_nac_hl_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_nac_lh_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyd_nac_lh_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_mpyd_nac_lh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_nac_lh_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyd_nac_lh_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_mpyd_nac_lh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_nac_ll_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyd_nac_ll_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_mpyd_nac_ll_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_nac_ll_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyd_nac_ll_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_mpyd_nac_ll_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_hh_s0,DI_ftype_SISI,2) +// +def int_hexagon_M2_mpyd_hh_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_mpyd_hh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_hh_s1,DI_ftype_SISI,2) +// +def int_hexagon_M2_mpyd_hh_s1 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_mpyd_hh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_hl_s0,DI_ftype_SISI,2) +// +def int_hexagon_M2_mpyd_hl_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_mpyd_hl_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_hl_s1,DI_ftype_SISI,2) +// +def int_hexagon_M2_mpyd_hl_s1 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_mpyd_hl_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_lh_s0,DI_ftype_SISI,2) +// +def int_hexagon_M2_mpyd_lh_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_mpyd_lh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_lh_s1,DI_ftype_SISI,2) +// +def int_hexagon_M2_mpyd_lh_s1 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_mpyd_lh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_ll_s0,DI_ftype_SISI,2) +// +def int_hexagon_M2_mpyd_ll_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_mpyd_ll_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_ll_s1,DI_ftype_SISI,2) +// +def int_hexagon_M2_mpyd_ll_s1 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_mpyd_ll_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_rnd_hh_s0,DI_ftype_SISI,2) +// +def int_hexagon_M2_mpyd_rnd_hh_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_mpyd_rnd_hh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_rnd_hh_s1,DI_ftype_SISI,2) +// +def int_hexagon_M2_mpyd_rnd_hh_s1 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_mpyd_rnd_hh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_rnd_hl_s0,DI_ftype_SISI,2) +// +def int_hexagon_M2_mpyd_rnd_hl_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_mpyd_rnd_hl_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_rnd_hl_s1,DI_ftype_SISI,2) +// +def int_hexagon_M2_mpyd_rnd_hl_s1 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_mpyd_rnd_hl_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_rnd_lh_s0,DI_ftype_SISI,2) +// +def int_hexagon_M2_mpyd_rnd_lh_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_mpyd_rnd_lh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_rnd_lh_s1,DI_ftype_SISI,2) +// +def int_hexagon_M2_mpyd_rnd_lh_s1 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_mpyd_rnd_lh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_rnd_ll_s0,DI_ftype_SISI,2) +// +def int_hexagon_M2_mpyd_rnd_ll_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_mpyd_rnd_ll_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_rnd_ll_s1,DI_ftype_SISI,2) +// +def int_hexagon_M2_mpyd_rnd_ll_s1 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_mpyd_rnd_ll_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_acc_hh_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpyu_acc_hh_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpyu_acc_hh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_acc_hh_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpyu_acc_hh_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpyu_acc_hh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_acc_hl_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpyu_acc_hl_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpyu_acc_hl_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_acc_hl_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpyu_acc_hl_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpyu_acc_hl_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_acc_lh_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpyu_acc_lh_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpyu_acc_lh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_acc_lh_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpyu_acc_lh_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpyu_acc_lh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_acc_ll_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpyu_acc_ll_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpyu_acc_ll_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_acc_ll_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpyu_acc_ll_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpyu_acc_ll_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_nac_hh_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpyu_nac_hh_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpyu_nac_hh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_nac_hh_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpyu_nac_hh_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpyu_nac_hh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_nac_hl_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpyu_nac_hl_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpyu_nac_hl_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_nac_hl_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpyu_nac_hl_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpyu_nac_hl_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_nac_lh_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpyu_nac_lh_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpyu_nac_lh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_nac_lh_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpyu_nac_lh_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpyu_nac_lh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_nac_ll_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpyu_nac_ll_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpyu_nac_ll_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_nac_ll_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpyu_nac_ll_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_mpyu_nac_ll_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_hh_s0,USI_ftype_SISI,2) +// +def int_hexagon_M2_mpyu_hh_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpyu_hh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_hh_s1,USI_ftype_SISI,2) +// +def int_hexagon_M2_mpyu_hh_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpyu_hh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_hl_s0,USI_ftype_SISI,2) +// +def int_hexagon_M2_mpyu_hl_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpyu_hl_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_hl_s1,USI_ftype_SISI,2) +// +def int_hexagon_M2_mpyu_hl_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpyu_hl_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_lh_s0,USI_ftype_SISI,2) +// +def int_hexagon_M2_mpyu_lh_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpyu_lh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_lh_s1,USI_ftype_SISI,2) +// +def int_hexagon_M2_mpyu_lh_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpyu_lh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_ll_s0,USI_ftype_SISI,2) +// +def int_hexagon_M2_mpyu_ll_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpyu_ll_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_ll_s1,USI_ftype_SISI,2) +// +def int_hexagon_M2_mpyu_ll_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpyu_ll_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_acc_hh_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyud_acc_hh_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_mpyud_acc_hh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_acc_hh_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyud_acc_hh_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_mpyud_acc_hh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_acc_hl_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyud_acc_hl_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_mpyud_acc_hl_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_acc_hl_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyud_acc_hl_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_mpyud_acc_hl_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_acc_lh_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyud_acc_lh_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_mpyud_acc_lh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_acc_lh_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyud_acc_lh_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_mpyud_acc_lh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_acc_ll_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyud_acc_ll_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_mpyud_acc_ll_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_acc_ll_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyud_acc_ll_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_mpyud_acc_ll_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_nac_hh_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyud_nac_hh_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_mpyud_nac_hh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_nac_hh_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyud_nac_hh_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_mpyud_nac_hh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_nac_hl_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyud_nac_hl_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_mpyud_nac_hl_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_nac_hl_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyud_nac_hl_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_mpyud_nac_hl_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_nac_lh_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyud_nac_lh_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_mpyud_nac_lh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_nac_lh_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyud_nac_lh_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_mpyud_nac_lh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_nac_ll_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyud_nac_ll_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_mpyud_nac_ll_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_nac_ll_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyud_nac_ll_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_mpyud_nac_ll_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_hh_s0,UDI_ftype_SISI,2) +// +def int_hexagon_M2_mpyud_hh_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_mpyud_hh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_hh_s1,UDI_ftype_SISI,2) +// +def int_hexagon_M2_mpyud_hh_s1 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_mpyud_hh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_hl_s0,UDI_ftype_SISI,2) +// +def int_hexagon_M2_mpyud_hl_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_mpyud_hl_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_hl_s1,UDI_ftype_SISI,2) +// +def int_hexagon_M2_mpyud_hl_s1 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_mpyud_hl_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_lh_s0,UDI_ftype_SISI,2) +// +def int_hexagon_M2_mpyud_lh_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_mpyud_lh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_lh_s1,UDI_ftype_SISI,2) +// +def int_hexagon_M2_mpyud_lh_s1 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_mpyud_lh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_ll_s0,UDI_ftype_SISI,2) +// +def int_hexagon_M2_mpyud_ll_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_mpyud_ll_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_ll_s1,UDI_ftype_SISI,2) +// +def int_hexagon_M2_mpyud_ll_s1 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_mpyud_ll_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpysmi,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpysmi : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpysmi">; +// +// BUILTIN_INFO(HEXAGON.M2_macsip,SI_ftype_SISISI,3) +// +def int_hexagon_M2_macsip : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_macsip">; +// +// BUILTIN_INFO(HEXAGON.M2_macsin,SI_ftype_SISISI,3) +// +def int_hexagon_M2_macsin : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_macsin">; +// +// BUILTIN_INFO(HEXAGON.M2_dpmpyss_s0,DI_ftype_SISI,2) +// +def int_hexagon_M2_dpmpyss_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_dpmpyss_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_dpmpyss_acc_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_dpmpyss_acc_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_dpmpyss_acc_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_dpmpyss_nac_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_dpmpyss_nac_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_dpmpyss_nac_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_dpmpyuu_s0,UDI_ftype_SISI,2) +// +def int_hexagon_M2_dpmpyuu_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_dpmpyuu_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_dpmpyuu_acc_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_dpmpyuu_acc_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_dpmpyuu_acc_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_dpmpyuu_nac_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_dpmpyuu_nac_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_dpmpyuu_nac_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_up,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_up : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_up">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_up_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_up_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_up_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_up_s1_sat,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_up_s1_sat : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpy_up_s1_sat">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_up,USI_ftype_SISI,2) +// +def int_hexagon_M2_mpyu_up : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpyu_up">; +// +// BUILTIN_INFO(HEXAGON.M2_mpysu_up,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpysu_up : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpysu_up">; +// +// BUILTIN_INFO(HEXAGON.M2_dpmpyss_rnd_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_dpmpyss_rnd_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_dpmpyss_rnd_s0">; +// +// BUILTIN_INFO(HEXAGON.M4_mac_up_s1_sat,SI_ftype_SISISI,3) +// +def int_hexagon_M4_mac_up_s1_sat : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M4_mac_up_s1_sat">; +// +// BUILTIN_INFO(HEXAGON.M4_nac_up_s1_sat,SI_ftype_SISISI,3) +// +def int_hexagon_M4_nac_up_s1_sat : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M4_nac_up_s1_sat">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyi,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpyi : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpyi">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyui,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpyui : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_mpyui">; +// +// BUILTIN_INFO(HEXAGON.M2_maci,SI_ftype_SISISI,3) +// +def int_hexagon_M2_maci : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_maci">; +// +// BUILTIN_INFO(HEXAGON.M2_acci,SI_ftype_SISISI,3) +// +def int_hexagon_M2_acci : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_acci">; +// +// BUILTIN_INFO(HEXAGON.M2_accii,SI_ftype_SISISI,3) +// +def int_hexagon_M2_accii : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_accii">; +// +// BUILTIN_INFO(HEXAGON.M2_nacci,SI_ftype_SISISI,3) +// +def int_hexagon_M2_nacci : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_nacci">; +// +// BUILTIN_INFO(HEXAGON.M2_naccii,SI_ftype_SISISI,3) +// +def int_hexagon_M2_naccii : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_naccii">; +// +// BUILTIN_INFO(HEXAGON.M2_subacc,SI_ftype_SISISI,3) +// +def int_hexagon_M2_subacc : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_subacc">; +// +// BUILTIN_INFO(HEXAGON.M4_mpyrr_addr,SI_ftype_SISISI,3) +// +def int_hexagon_M4_mpyrr_addr : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M4_mpyrr_addr">; +// +// BUILTIN_INFO(HEXAGON.M4_mpyri_addr_u2,SI_ftype_SISISI,3) +// +def int_hexagon_M4_mpyri_addr_u2 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M4_mpyri_addr_u2">; +// +// BUILTIN_INFO(HEXAGON.M4_mpyri_addr,SI_ftype_SISISI,3) +// +def int_hexagon_M4_mpyri_addr : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M4_mpyri_addr">; +// +// BUILTIN_INFO(HEXAGON.M4_mpyri_addi,SI_ftype_SISISI,3) +// +def int_hexagon_M4_mpyri_addi : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M4_mpyri_addi">; +// +// BUILTIN_INFO(HEXAGON.M4_mpyrr_addi,SI_ftype_SISISI,3) +// +def int_hexagon_M4_mpyrr_addi : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M4_mpyrr_addi">; +// +// BUILTIN_INFO(HEXAGON.M2_vmpy2s_s0,DI_ftype_SISI,2) +// +def int_hexagon_M2_vmpy2s_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_vmpy2s_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_vmpy2s_s1,DI_ftype_SISI,2) +// +def int_hexagon_M2_vmpy2s_s1 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_vmpy2s_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_vmac2s_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_vmac2s_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_vmac2s_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_vmac2s_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_vmac2s_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_vmac2s_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_vmpy2su_s0,DI_ftype_SISI,2) +// +def int_hexagon_M2_vmpy2su_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_vmpy2su_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_vmpy2su_s1,DI_ftype_SISI,2) +// +def int_hexagon_M2_vmpy2su_s1 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_vmpy2su_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_vmac2su_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_vmac2su_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_vmac2su_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_vmac2su_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_vmac2su_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_vmac2su_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_vmpy2s_s0pack,SI_ftype_SISI,2) +// +def int_hexagon_M2_vmpy2s_s0pack : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_vmpy2s_s0pack">; +// +// BUILTIN_INFO(HEXAGON.M2_vmpy2s_s1pack,SI_ftype_SISI,2) +// +def int_hexagon_M2_vmpy2s_s1pack : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_vmpy2s_s1pack">; +// +// BUILTIN_INFO(HEXAGON.M2_vmac2,DI_ftype_DISISI,3) +// +def int_hexagon_M2_vmac2 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_vmac2">; +// +// BUILTIN_INFO(HEXAGON.M2_vmpy2es_s0,DI_ftype_DIDI,2) +// +def int_hexagon_M2_vmpy2es_s0 : +Hexagon_di_didi_Intrinsic<"HEXAGON_M2_vmpy2es_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_vmpy2es_s1,DI_ftype_DIDI,2) +// +def int_hexagon_M2_vmpy2es_s1 : +Hexagon_di_didi_Intrinsic<"HEXAGON_M2_vmpy2es_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_vmac2es_s0,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_vmac2es_s0 : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M2_vmac2es_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_vmac2es_s1,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_vmac2es_s1 : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M2_vmac2es_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_vmac2es,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_vmac2es : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M2_vmac2es">; +// +// BUILTIN_INFO(HEXAGON.M2_vrmac_s0,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_vrmac_s0 : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M2_vrmac_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_vrmpy_s0,DI_ftype_DIDI,2) +// +def int_hexagon_M2_vrmpy_s0 : +Hexagon_di_didi_Intrinsic<"HEXAGON_M2_vrmpy_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_vdmpyrs_s0,SI_ftype_DIDI,2) +// +def int_hexagon_M2_vdmpyrs_s0 : +Hexagon_si_didi_Intrinsic<"HEXAGON_M2_vdmpyrs_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_vdmpyrs_s1,SI_ftype_DIDI,2) +// +def int_hexagon_M2_vdmpyrs_s1 : +Hexagon_si_didi_Intrinsic<"HEXAGON_M2_vdmpyrs_s1">; +// +// BUILTIN_INFO(HEXAGON.M5_vrmpybuu,DI_ftype_DIDI,2) +// +def int_hexagon_M5_vrmpybuu : +Hexagon_di_didi_Intrinsic<"HEXAGON_M5_vrmpybuu">; +// +// BUILTIN_INFO(HEXAGON.M5_vrmacbuu,DI_ftype_DIDIDI,3) +// +def int_hexagon_M5_vrmacbuu : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M5_vrmacbuu">; +// +// BUILTIN_INFO(HEXAGON.M5_vrmpybsu,DI_ftype_DIDI,2) +// +def int_hexagon_M5_vrmpybsu : +Hexagon_di_didi_Intrinsic<"HEXAGON_M5_vrmpybsu">; +// +// BUILTIN_INFO(HEXAGON.M5_vrmacbsu,DI_ftype_DIDIDI,3) +// +def int_hexagon_M5_vrmacbsu : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M5_vrmacbsu">; +// +// BUILTIN_INFO(HEXAGON.M5_vmpybuu,DI_ftype_SISI,2) +// +def int_hexagon_M5_vmpybuu : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M5_vmpybuu">; +// +// BUILTIN_INFO(HEXAGON.M5_vmpybsu,DI_ftype_SISI,2) +// +def int_hexagon_M5_vmpybsu : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M5_vmpybsu">; +// +// BUILTIN_INFO(HEXAGON.M5_vmacbuu,DI_ftype_DISISI,3) +// +def int_hexagon_M5_vmacbuu : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M5_vmacbuu">; +// +// BUILTIN_INFO(HEXAGON.M5_vmacbsu,DI_ftype_DISISI,3) +// +def int_hexagon_M5_vmacbsu : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M5_vmacbsu">; +// +// BUILTIN_INFO(HEXAGON.M5_vdmpybsu,DI_ftype_DIDI,2) +// +def int_hexagon_M5_vdmpybsu : +Hexagon_di_didi_Intrinsic<"HEXAGON_M5_vdmpybsu">; +// +// BUILTIN_INFO(HEXAGON.M5_vdmacbsu,DI_ftype_DIDIDI,3) +// +def int_hexagon_M5_vdmacbsu : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M5_vdmacbsu">; +// +// BUILTIN_INFO(HEXAGON.M2_vdmacs_s0,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_vdmacs_s0 : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M2_vdmacs_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_vdmacs_s1,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_vdmacs_s1 : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M2_vdmacs_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_vdmpys_s0,DI_ftype_DIDI,2) +// +def int_hexagon_M2_vdmpys_s0 : +Hexagon_di_didi_Intrinsic<"HEXAGON_M2_vdmpys_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_vdmpys_s1,DI_ftype_DIDI,2) +// +def int_hexagon_M2_vdmpys_s1 : +Hexagon_di_didi_Intrinsic<"HEXAGON_M2_vdmpys_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_cmpyrs_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_cmpyrs_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_cmpyrs_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_cmpyrs_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_cmpyrs_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_cmpyrs_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_cmpyrsc_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_cmpyrsc_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_cmpyrsc_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_cmpyrsc_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_cmpyrsc_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_cmpyrsc_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_cmacs_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_cmacs_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_cmacs_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_cmacs_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_cmacs_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_cmacs_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_cmacsc_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_cmacsc_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_cmacsc_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_cmacsc_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_cmacsc_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_cmacsc_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_cmpys_s0,DI_ftype_SISI,2) +// +def int_hexagon_M2_cmpys_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_cmpys_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_cmpys_s1,DI_ftype_SISI,2) +// +def int_hexagon_M2_cmpys_s1 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_cmpys_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_cmpysc_s0,DI_ftype_SISI,2) +// +def int_hexagon_M2_cmpysc_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_cmpysc_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_cmpysc_s1,DI_ftype_SISI,2) +// +def int_hexagon_M2_cmpysc_s1 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_cmpysc_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_cnacs_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_cnacs_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_cnacs_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_cnacs_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_cnacs_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_cnacs_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_cnacsc_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_cnacsc_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_cnacsc_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_cnacsc_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_cnacsc_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_cnacsc_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_vrcmpys_s1,DI_ftype_DISI,2) +// +def int_hexagon_M2_vrcmpys_s1 : +Hexagon_di_disi_Intrinsic<"HEXAGON_M2_vrcmpys_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_vrcmpys_acc_s1,DI_ftype_DIDISI,3) +// +def int_hexagon_M2_vrcmpys_acc_s1 : +Hexagon_di_didisi_Intrinsic<"HEXAGON_M2_vrcmpys_acc_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_vrcmpys_s1rp,SI_ftype_DISI,2) +// +def int_hexagon_M2_vrcmpys_s1rp : +Hexagon_si_disi_Intrinsic<"HEXAGON_M2_vrcmpys_s1rp">; +// +// BUILTIN_INFO(HEXAGON.M2_mmacls_s0,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_mmacls_s0 : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M2_mmacls_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mmacls_s1,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_mmacls_s1 : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M2_mmacls_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mmachs_s0,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_mmachs_s0 : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M2_mmachs_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mmachs_s1,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_mmachs_s1 : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M2_mmachs_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mmpyl_s0,DI_ftype_DIDI,2) +// +def int_hexagon_M2_mmpyl_s0 : +Hexagon_di_didi_Intrinsic<"HEXAGON_M2_mmpyl_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mmpyl_s1,DI_ftype_DIDI,2) +// +def int_hexagon_M2_mmpyl_s1 : +Hexagon_di_didi_Intrinsic<"HEXAGON_M2_mmpyl_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mmpyh_s0,DI_ftype_DIDI,2) +// +def int_hexagon_M2_mmpyh_s0 : +Hexagon_di_didi_Intrinsic<"HEXAGON_M2_mmpyh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mmpyh_s1,DI_ftype_DIDI,2) +// +def int_hexagon_M2_mmpyh_s1 : +Hexagon_di_didi_Intrinsic<"HEXAGON_M2_mmpyh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mmacls_rs0,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_mmacls_rs0 : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M2_mmacls_rs0">; +// +// BUILTIN_INFO(HEXAGON.M2_mmacls_rs1,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_mmacls_rs1 : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M2_mmacls_rs1">; +// +// BUILTIN_INFO(HEXAGON.M2_mmachs_rs0,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_mmachs_rs0 : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M2_mmachs_rs0">; +// +// BUILTIN_INFO(HEXAGON.M2_mmachs_rs1,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_mmachs_rs1 : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M2_mmachs_rs1">; +// +// BUILTIN_INFO(HEXAGON.M2_mmpyl_rs0,DI_ftype_DIDI,2) +// +def int_hexagon_M2_mmpyl_rs0 : +Hexagon_di_didi_Intrinsic<"HEXAGON_M2_mmpyl_rs0">; +// +// BUILTIN_INFO(HEXAGON.M2_mmpyl_rs1,DI_ftype_DIDI,2) +// +def int_hexagon_M2_mmpyl_rs1 : +Hexagon_di_didi_Intrinsic<"HEXAGON_M2_mmpyl_rs1">; +// +// BUILTIN_INFO(HEXAGON.M2_mmpyh_rs0,DI_ftype_DIDI,2) +// +def int_hexagon_M2_mmpyh_rs0 : +Hexagon_di_didi_Intrinsic<"HEXAGON_M2_mmpyh_rs0">; +// +// BUILTIN_INFO(HEXAGON.M2_mmpyh_rs1,DI_ftype_DIDI,2) +// +def int_hexagon_M2_mmpyh_rs1 : +Hexagon_di_didi_Intrinsic<"HEXAGON_M2_mmpyh_rs1">; +// +// BUILTIN_INFO(HEXAGON.M4_vrmpyeh_s0,DI_ftype_DIDI,2) +// +def int_hexagon_M4_vrmpyeh_s0 : +Hexagon_di_didi_Intrinsic<"HEXAGON_M4_vrmpyeh_s0">; +// +// BUILTIN_INFO(HEXAGON.M4_vrmpyeh_s1,DI_ftype_DIDI,2) +// +def int_hexagon_M4_vrmpyeh_s1 : +Hexagon_di_didi_Intrinsic<"HEXAGON_M4_vrmpyeh_s1">; +// +// BUILTIN_INFO(HEXAGON.M4_vrmpyeh_acc_s0,DI_ftype_DIDIDI,3) +// +def int_hexagon_M4_vrmpyeh_acc_s0 : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M4_vrmpyeh_acc_s0">; +// +// BUILTIN_INFO(HEXAGON.M4_vrmpyeh_acc_s1,DI_ftype_DIDIDI,3) +// +def int_hexagon_M4_vrmpyeh_acc_s1 : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M4_vrmpyeh_acc_s1">; +// +// BUILTIN_INFO(HEXAGON.M4_vrmpyoh_s0,DI_ftype_DIDI,2) +// +def int_hexagon_M4_vrmpyoh_s0 : +Hexagon_di_didi_Intrinsic<"HEXAGON_M4_vrmpyoh_s0">; +// +// BUILTIN_INFO(HEXAGON.M4_vrmpyoh_s1,DI_ftype_DIDI,2) +// +def int_hexagon_M4_vrmpyoh_s1 : +Hexagon_di_didi_Intrinsic<"HEXAGON_M4_vrmpyoh_s1">; +// +// BUILTIN_INFO(HEXAGON.M4_vrmpyoh_acc_s0,DI_ftype_DIDIDI,3) +// +def int_hexagon_M4_vrmpyoh_acc_s0 : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M4_vrmpyoh_acc_s0">; +// +// BUILTIN_INFO(HEXAGON.M4_vrmpyoh_acc_s1,DI_ftype_DIDIDI,3) +// +def int_hexagon_M4_vrmpyoh_acc_s1 : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M4_vrmpyoh_acc_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_hmmpyl_rs1,SI_ftype_SISI,2) +// +def int_hexagon_M2_hmmpyl_rs1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_hmmpyl_rs1">; +// +// BUILTIN_INFO(HEXAGON.M2_hmmpyh_rs1,SI_ftype_SISI,2) +// +def int_hexagon_M2_hmmpyh_rs1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_hmmpyh_rs1">; +// +// BUILTIN_INFO(HEXAGON.M2_hmmpyl_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_hmmpyl_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_hmmpyl_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_hmmpyh_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_hmmpyh_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON_M2_hmmpyh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mmaculs_s0,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_mmaculs_s0 : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M2_mmaculs_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mmaculs_s1,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_mmaculs_s1 : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M2_mmaculs_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mmacuhs_s0,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_mmacuhs_s0 : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M2_mmacuhs_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mmacuhs_s1,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_mmacuhs_s1 : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M2_mmacuhs_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mmpyul_s0,DI_ftype_DIDI,2) +// +def int_hexagon_M2_mmpyul_s0 : +Hexagon_di_didi_Intrinsic<"HEXAGON_M2_mmpyul_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mmpyul_s1,DI_ftype_DIDI,2) +// +def int_hexagon_M2_mmpyul_s1 : +Hexagon_di_didi_Intrinsic<"HEXAGON_M2_mmpyul_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mmpyuh_s0,DI_ftype_DIDI,2) +// +def int_hexagon_M2_mmpyuh_s0 : +Hexagon_di_didi_Intrinsic<"HEXAGON_M2_mmpyuh_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mmpyuh_s1,DI_ftype_DIDI,2) +// +def int_hexagon_M2_mmpyuh_s1 : +Hexagon_di_didi_Intrinsic<"HEXAGON_M2_mmpyuh_s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mmaculs_rs0,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_mmaculs_rs0 : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M2_mmaculs_rs0">; +// +// BUILTIN_INFO(HEXAGON.M2_mmaculs_rs1,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_mmaculs_rs1 : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M2_mmaculs_rs1">; +// +// BUILTIN_INFO(HEXAGON.M2_mmacuhs_rs0,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_mmacuhs_rs0 : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M2_mmacuhs_rs0">; +// +// BUILTIN_INFO(HEXAGON.M2_mmacuhs_rs1,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_mmacuhs_rs1 : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M2_mmacuhs_rs1">; +// +// BUILTIN_INFO(HEXAGON.M2_mmpyul_rs0,DI_ftype_DIDI,2) +// +def int_hexagon_M2_mmpyul_rs0 : +Hexagon_di_didi_Intrinsic<"HEXAGON_M2_mmpyul_rs0">; +// +// BUILTIN_INFO(HEXAGON.M2_mmpyul_rs1,DI_ftype_DIDI,2) +// +def int_hexagon_M2_mmpyul_rs1 : +Hexagon_di_didi_Intrinsic<"HEXAGON_M2_mmpyul_rs1">; +// +// BUILTIN_INFO(HEXAGON.M2_mmpyuh_rs0,DI_ftype_DIDI,2) +// +def int_hexagon_M2_mmpyuh_rs0 : +Hexagon_di_didi_Intrinsic<"HEXAGON_M2_mmpyuh_rs0">; +// +// BUILTIN_INFO(HEXAGON.M2_mmpyuh_rs1,DI_ftype_DIDI,2) +// +def int_hexagon_M2_mmpyuh_rs1 : +Hexagon_di_didi_Intrinsic<"HEXAGON_M2_mmpyuh_rs1">; +// +// BUILTIN_INFO(HEXAGON.M2_vrcmaci_s0,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_vrcmaci_s0 : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M2_vrcmaci_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_vrcmacr_s0,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_vrcmacr_s0 : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M2_vrcmacr_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_vrcmaci_s0c,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_vrcmaci_s0c : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M2_vrcmaci_s0c">; +// +// BUILTIN_INFO(HEXAGON.M2_vrcmacr_s0c,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_vrcmacr_s0c : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M2_vrcmacr_s0c">; +// +// BUILTIN_INFO(HEXAGON.M2_cmaci_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_cmaci_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_cmaci_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_cmacr_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_cmacr_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M2_cmacr_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_vrcmpyi_s0,DI_ftype_DIDI,2) +// +def int_hexagon_M2_vrcmpyi_s0 : +Hexagon_di_didi_Intrinsic<"HEXAGON_M2_vrcmpyi_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_vrcmpyr_s0,DI_ftype_DIDI,2) +// +def int_hexagon_M2_vrcmpyr_s0 : +Hexagon_di_didi_Intrinsic<"HEXAGON_M2_vrcmpyr_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_vrcmpyi_s0c,DI_ftype_DIDI,2) +// +def int_hexagon_M2_vrcmpyi_s0c : +Hexagon_di_didi_Intrinsic<"HEXAGON_M2_vrcmpyi_s0c">; +// +// BUILTIN_INFO(HEXAGON.M2_vrcmpyr_s0c,DI_ftype_DIDI,2) +// +def int_hexagon_M2_vrcmpyr_s0c : +Hexagon_di_didi_Intrinsic<"HEXAGON_M2_vrcmpyr_s0c">; +// +// BUILTIN_INFO(HEXAGON.M2_cmpyi_s0,DI_ftype_SISI,2) +// +def int_hexagon_M2_cmpyi_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_cmpyi_s0">; +// +// BUILTIN_INFO(HEXAGON.M2_cmpyr_s0,DI_ftype_SISI,2) +// +def int_hexagon_M2_cmpyr_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M2_cmpyr_s0">; +// +// BUILTIN_INFO(HEXAGON.M4_cmpyi_wh,SI_ftype_DISI,2) +// +def int_hexagon_M4_cmpyi_wh : +Hexagon_si_disi_Intrinsic<"HEXAGON_M4_cmpyi_wh">; +// +// BUILTIN_INFO(HEXAGON.M4_cmpyr_wh,SI_ftype_DISI,2) +// +def int_hexagon_M4_cmpyr_wh : +Hexagon_si_disi_Intrinsic<"HEXAGON_M4_cmpyr_wh">; +// +// BUILTIN_INFO(HEXAGON.M4_cmpyi_whc,SI_ftype_DISI,2) +// +def int_hexagon_M4_cmpyi_whc : +Hexagon_si_disi_Intrinsic<"HEXAGON_M4_cmpyi_whc">; +// +// BUILTIN_INFO(HEXAGON.M4_cmpyr_whc,SI_ftype_DISI,2) +// +def int_hexagon_M4_cmpyr_whc : +Hexagon_si_disi_Intrinsic<"HEXAGON_M4_cmpyr_whc">; +// +// BUILTIN_INFO(HEXAGON.M2_vcmpy_s0_sat_i,DI_ftype_DIDI,2) +// +def int_hexagon_M2_vcmpy_s0_sat_i : +Hexagon_di_didi_Intrinsic<"HEXAGON_M2_vcmpy_s0_sat_i">; +// +// BUILTIN_INFO(HEXAGON.M2_vcmpy_s0_sat_r,DI_ftype_DIDI,2) +// +def int_hexagon_M2_vcmpy_s0_sat_r : +Hexagon_di_didi_Intrinsic<"HEXAGON_M2_vcmpy_s0_sat_r">; +// +// BUILTIN_INFO(HEXAGON.M2_vcmpy_s1_sat_i,DI_ftype_DIDI,2) +// +def int_hexagon_M2_vcmpy_s1_sat_i : +Hexagon_di_didi_Intrinsic<"HEXAGON_M2_vcmpy_s1_sat_i">; +// +// BUILTIN_INFO(HEXAGON.M2_vcmpy_s1_sat_r,DI_ftype_DIDI,2) +// +def int_hexagon_M2_vcmpy_s1_sat_r : +Hexagon_di_didi_Intrinsic<"HEXAGON_M2_vcmpy_s1_sat_r">; +// +// BUILTIN_INFO(HEXAGON.M2_vcmac_s0_sat_i,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_vcmac_s0_sat_i : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M2_vcmac_s0_sat_i">; +// +// BUILTIN_INFO(HEXAGON.M2_vcmac_s0_sat_r,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_vcmac_s0_sat_r : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M2_vcmac_s0_sat_r">; +// +// BUILTIN_INFO(HEXAGON.S2_vcrotate,DI_ftype_DISI,2) +// +def int_hexagon_S2_vcrotate : +Hexagon_di_disi_Intrinsic<"HEXAGON_S2_vcrotate">; +// +// BUILTIN_INFO(HEXAGON.S4_vrcrotate_acc,DI_ftype_DIDISISI,4) +// +def int_hexagon_S4_vrcrotate_acc : +Hexagon_di_didisisi_Intrinsic<"HEXAGON_S4_vrcrotate_acc">; +// +// BUILTIN_INFO(HEXAGON.S4_vrcrotate,DI_ftype_DISISI,3) +// +def int_hexagon_S4_vrcrotate : +Hexagon_di_disisi_Intrinsic<"HEXAGON_S4_vrcrotate">; +// +// BUILTIN_INFO(HEXAGON.S2_vcnegh,DI_ftype_DISI,2) +// +def int_hexagon_S2_vcnegh : +Hexagon_di_disi_Intrinsic<"HEXAGON_S2_vcnegh">; +// +// BUILTIN_INFO(HEXAGON.S2_vrcnegh,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_vrcnegh : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_vrcnegh">; +// +// BUILTIN_INFO(HEXAGON.M4_pmpyw,DI_ftype_SISI,2) +// +def int_hexagon_M4_pmpyw : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M4_pmpyw">; +// +// BUILTIN_INFO(HEXAGON.M4_vpmpyh,DI_ftype_SISI,2) +// +def int_hexagon_M4_vpmpyh : +Hexagon_di_sisi_Intrinsic<"HEXAGON_M4_vpmpyh">; +// +// BUILTIN_INFO(HEXAGON.M4_pmpyw_acc,DI_ftype_DISISI,3) +// +def int_hexagon_M4_pmpyw_acc : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M4_pmpyw_acc">; +// +// BUILTIN_INFO(HEXAGON.M4_vpmpyh_acc,DI_ftype_DISISI,3) +// +def int_hexagon_M4_vpmpyh_acc : +Hexagon_di_disisi_Intrinsic<"HEXAGON_M4_vpmpyh_acc">; +// +// BUILTIN_INFO(HEXAGON.A2_add,SI_ftype_SISI,2) +// +def int_hexagon_A2_add : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_add">; +// +// BUILTIN_INFO(HEXAGON.A2_sub,SI_ftype_SISI,2) +// +def int_hexagon_A2_sub : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_sub">; +// +// BUILTIN_INFO(HEXAGON.A2_addsat,SI_ftype_SISI,2) +// +def int_hexagon_A2_addsat : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_addsat">; +// +// BUILTIN_INFO(HEXAGON.A2_subsat,SI_ftype_SISI,2) +// +def int_hexagon_A2_subsat : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_subsat">; +// +// BUILTIN_INFO(HEXAGON.A2_addi,SI_ftype_SISI,2) +// +def int_hexagon_A2_addi : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_addi">; +// +// BUILTIN_INFO(HEXAGON.A2_addh_l16_ll,SI_ftype_SISI,2) +// +def int_hexagon_A2_addh_l16_ll : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_addh_l16_ll">; +// +// BUILTIN_INFO(HEXAGON.A2_addh_l16_hl,SI_ftype_SISI,2) +// +def int_hexagon_A2_addh_l16_hl : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_addh_l16_hl">; +// +// BUILTIN_INFO(HEXAGON.A2_addh_l16_sat_ll,SI_ftype_SISI,2) +// +def int_hexagon_A2_addh_l16_sat_ll : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_addh_l16_sat_ll">; +// +// BUILTIN_INFO(HEXAGON.A2_addh_l16_sat_hl,SI_ftype_SISI,2) +// +def int_hexagon_A2_addh_l16_sat_hl : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_addh_l16_sat_hl">; +// +// BUILTIN_INFO(HEXAGON.A2_subh_l16_ll,SI_ftype_SISI,2) +// +def int_hexagon_A2_subh_l16_ll : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_subh_l16_ll">; +// +// BUILTIN_INFO(HEXAGON.A2_subh_l16_hl,SI_ftype_SISI,2) +// +def int_hexagon_A2_subh_l16_hl : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_subh_l16_hl">; +// +// BUILTIN_INFO(HEXAGON.A2_subh_l16_sat_ll,SI_ftype_SISI,2) +// +def int_hexagon_A2_subh_l16_sat_ll : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_subh_l16_sat_ll">; +// +// BUILTIN_INFO(HEXAGON.A2_subh_l16_sat_hl,SI_ftype_SISI,2) +// +def int_hexagon_A2_subh_l16_sat_hl : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_subh_l16_sat_hl">; +// +// BUILTIN_INFO(HEXAGON.A2_addh_h16_ll,SI_ftype_SISI,2) +// +def int_hexagon_A2_addh_h16_ll : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_addh_h16_ll">; +// +// BUILTIN_INFO(HEXAGON.A2_addh_h16_lh,SI_ftype_SISI,2) +// +def int_hexagon_A2_addh_h16_lh : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_addh_h16_lh">; +// +// BUILTIN_INFO(HEXAGON.A2_addh_h16_hl,SI_ftype_SISI,2) +// +def int_hexagon_A2_addh_h16_hl : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_addh_h16_hl">; +// +// BUILTIN_INFO(HEXAGON.A2_addh_h16_hh,SI_ftype_SISI,2) +// +def int_hexagon_A2_addh_h16_hh : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_addh_h16_hh">; +// +// BUILTIN_INFO(HEXAGON.A2_addh_h16_sat_ll,SI_ftype_SISI,2) +// +def int_hexagon_A2_addh_h16_sat_ll : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_addh_h16_sat_ll">; +// +// BUILTIN_INFO(HEXAGON.A2_addh_h16_sat_lh,SI_ftype_SISI,2) +// +def int_hexagon_A2_addh_h16_sat_lh : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_addh_h16_sat_lh">; +// +// BUILTIN_INFO(HEXAGON.A2_addh_h16_sat_hl,SI_ftype_SISI,2) +// +def int_hexagon_A2_addh_h16_sat_hl : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_addh_h16_sat_hl">; +// +// BUILTIN_INFO(HEXAGON.A2_addh_h16_sat_hh,SI_ftype_SISI,2) +// +def int_hexagon_A2_addh_h16_sat_hh : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_addh_h16_sat_hh">; +// +// BUILTIN_INFO(HEXAGON.A2_subh_h16_ll,SI_ftype_SISI,2) +// +def int_hexagon_A2_subh_h16_ll : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_subh_h16_ll">; +// +// BUILTIN_INFO(HEXAGON.A2_subh_h16_lh,SI_ftype_SISI,2) +// +def int_hexagon_A2_subh_h16_lh : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_subh_h16_lh">; +// +// BUILTIN_INFO(HEXAGON.A2_subh_h16_hl,SI_ftype_SISI,2) +// +def int_hexagon_A2_subh_h16_hl : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_subh_h16_hl">; +// +// BUILTIN_INFO(HEXAGON.A2_subh_h16_hh,SI_ftype_SISI,2) +// +def int_hexagon_A2_subh_h16_hh : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_subh_h16_hh">; +// +// BUILTIN_INFO(HEXAGON.A2_subh_h16_sat_ll,SI_ftype_SISI,2) +// +def int_hexagon_A2_subh_h16_sat_ll : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_subh_h16_sat_ll">; +// +// BUILTIN_INFO(HEXAGON.A2_subh_h16_sat_lh,SI_ftype_SISI,2) +// +def int_hexagon_A2_subh_h16_sat_lh : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_subh_h16_sat_lh">; +// +// BUILTIN_INFO(HEXAGON.A2_subh_h16_sat_hl,SI_ftype_SISI,2) +// +def int_hexagon_A2_subh_h16_sat_hl : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_subh_h16_sat_hl">; +// +// BUILTIN_INFO(HEXAGON.A2_subh_h16_sat_hh,SI_ftype_SISI,2) +// +def int_hexagon_A2_subh_h16_sat_hh : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_subh_h16_sat_hh">; +// +// BUILTIN_INFO(HEXAGON.A2_aslh,SI_ftype_SI,1) +// +def int_hexagon_A2_aslh : +Hexagon_si_si_Intrinsic<"HEXAGON_A2_aslh">; +// +// BUILTIN_INFO(HEXAGON.A2_asrh,SI_ftype_SI,1) +// +def int_hexagon_A2_asrh : +Hexagon_si_si_Intrinsic<"HEXAGON_A2_asrh">; +// +// BUILTIN_INFO(HEXAGON.A2_addp,DI_ftype_DIDI,2) +// +def int_hexagon_A2_addp : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_addp">; +// +// BUILTIN_INFO(HEXAGON.A2_addpsat,DI_ftype_DIDI,2) +// +def int_hexagon_A2_addpsat : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_addpsat">; +// +// BUILTIN_INFO(HEXAGON.A2_addsp,DI_ftype_SIDI,2) +// +def int_hexagon_A2_addsp : +Hexagon_di_sidi_Intrinsic<"HEXAGON_A2_addsp">; +// +// BUILTIN_INFO(HEXAGON.A2_subp,DI_ftype_DIDI,2) +// +def int_hexagon_A2_subp : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_subp">; +// +// BUILTIN_INFO(HEXAGON.A2_neg,SI_ftype_SI,1) +// +def int_hexagon_A2_neg : +Hexagon_si_si_Intrinsic<"HEXAGON_A2_neg">; +// +// BUILTIN_INFO(HEXAGON.A2_negsat,SI_ftype_SI,1) +// +def int_hexagon_A2_negsat : +Hexagon_si_si_Intrinsic<"HEXAGON_A2_negsat">; +// +// BUILTIN_INFO(HEXAGON.A2_abs,SI_ftype_SI,1) +// +def int_hexagon_A2_abs : +Hexagon_si_si_Intrinsic<"HEXAGON_A2_abs">; +// +// BUILTIN_INFO(HEXAGON.A2_abssat,SI_ftype_SI,1) +// +def int_hexagon_A2_abssat : +Hexagon_si_si_Intrinsic<"HEXAGON_A2_abssat">; +// +// BUILTIN_INFO(HEXAGON.A2_vconj,DI_ftype_DI,1) +// +def int_hexagon_A2_vconj : +Hexagon_di_di_Intrinsic<"HEXAGON_A2_vconj">; +// +// BUILTIN_INFO(HEXAGON.A2_negp,DI_ftype_DI,1) +// +def int_hexagon_A2_negp : +Hexagon_di_di_Intrinsic<"HEXAGON_A2_negp">; +// +// BUILTIN_INFO(HEXAGON.A2_absp,DI_ftype_DI,1) +// +def int_hexagon_A2_absp : +Hexagon_di_di_Intrinsic<"HEXAGON_A2_absp">; +// +// BUILTIN_INFO(HEXAGON.A2_max,SI_ftype_SISI,2) +// +def int_hexagon_A2_max : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_max">; +// +// BUILTIN_INFO(HEXAGON.A2_maxu,USI_ftype_SISI,2) +// +def int_hexagon_A2_maxu : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_maxu">; +// +// BUILTIN_INFO(HEXAGON.A2_min,SI_ftype_SISI,2) +// +def int_hexagon_A2_min : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_min">; +// +// BUILTIN_INFO(HEXAGON.A2_minu,USI_ftype_SISI,2) +// +def int_hexagon_A2_minu : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_minu">; +// +// BUILTIN_INFO(HEXAGON.A2_maxp,DI_ftype_DIDI,2) +// +def int_hexagon_A2_maxp : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_maxp">; +// +// BUILTIN_INFO(HEXAGON.A2_maxup,UDI_ftype_DIDI,2) +// +def int_hexagon_A2_maxup : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_maxup">; +// +// BUILTIN_INFO(HEXAGON.A2_minp,DI_ftype_DIDI,2) +// +def int_hexagon_A2_minp : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_minp">; +// +// BUILTIN_INFO(HEXAGON.A2_minup,UDI_ftype_DIDI,2) +// +def int_hexagon_A2_minup : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_minup">; +// +// BUILTIN_INFO(HEXAGON.A2_tfr,SI_ftype_SI,1) +// +def int_hexagon_A2_tfr : +Hexagon_si_si_Intrinsic<"HEXAGON_A2_tfr">; +// +// BUILTIN_INFO(HEXAGON.A2_tfrsi,SI_ftype_SI,1) +// +def int_hexagon_A2_tfrsi : +Hexagon_si_si_Intrinsic<"HEXAGON_A2_tfrsi">; +// +// BUILTIN_INFO(HEXAGON.A2_tfrp,DI_ftype_DI,1) +// +def int_hexagon_A2_tfrp : +Hexagon_di_di_Intrinsic<"HEXAGON_A2_tfrp">; +// +// BUILTIN_INFO(HEXAGON.A2_tfrpi,DI_ftype_SI,1) +// +def int_hexagon_A2_tfrpi : +Hexagon_di_si_Intrinsic<"HEXAGON_A2_tfrpi">; +// +// BUILTIN_INFO(HEXAGON.A2_zxtb,SI_ftype_SI,1) +// +def int_hexagon_A2_zxtb : +Hexagon_si_si_Intrinsic<"HEXAGON_A2_zxtb">; +// +// BUILTIN_INFO(HEXAGON.A2_sxtb,SI_ftype_SI,1) +// +def int_hexagon_A2_sxtb : +Hexagon_si_si_Intrinsic<"HEXAGON_A2_sxtb">; +// +// BUILTIN_INFO(HEXAGON.A2_zxth,SI_ftype_SI,1) +// +def int_hexagon_A2_zxth : +Hexagon_si_si_Intrinsic<"HEXAGON_A2_zxth">; +// +// BUILTIN_INFO(HEXAGON.A2_sxth,SI_ftype_SI,1) +// +def int_hexagon_A2_sxth : +Hexagon_si_si_Intrinsic<"HEXAGON_A2_sxth">; +// +// BUILTIN_INFO(HEXAGON.A2_combinew,DI_ftype_SISI,2) +// +def int_hexagon_A2_combinew : +Hexagon_di_sisi_Intrinsic<"HEXAGON_A2_combinew">; +// +// BUILTIN_INFO(HEXAGON.A4_combineri,DI_ftype_SISI,2) +// +def int_hexagon_A4_combineri : +Hexagon_di_sisi_Intrinsic<"HEXAGON_A4_combineri">; +// +// BUILTIN_INFO(HEXAGON.A4_combineir,DI_ftype_SISI,2) +// +def int_hexagon_A4_combineir : +Hexagon_di_sisi_Intrinsic<"HEXAGON_A4_combineir">; +// +// BUILTIN_INFO(HEXAGON.A2_combineii,DI_ftype_SISI,2) +// +def int_hexagon_A2_combineii : +Hexagon_di_sisi_Intrinsic<"HEXAGON_A2_combineii">; +// +// BUILTIN_INFO(HEXAGON.A2_combine_hh,SI_ftype_SISI,2) +// +def int_hexagon_A2_combine_hh : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_combine_hh">; +// +// BUILTIN_INFO(HEXAGON.A2_combine_hl,SI_ftype_SISI,2) +// +def int_hexagon_A2_combine_hl : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_combine_hl">; +// +// BUILTIN_INFO(HEXAGON.A2_combine_lh,SI_ftype_SISI,2) +// +def int_hexagon_A2_combine_lh : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_combine_lh">; +// +// BUILTIN_INFO(HEXAGON.A2_combine_ll,SI_ftype_SISI,2) +// +def int_hexagon_A2_combine_ll : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_combine_ll">; +// +// BUILTIN_INFO(HEXAGON.A2_tfril,SI_ftype_SISI,2) +// +def int_hexagon_A2_tfril : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_tfril">; +// +// BUILTIN_INFO(HEXAGON.A2_tfrih,SI_ftype_SISI,2) +// +def int_hexagon_A2_tfrih : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_tfrih">; +// +// BUILTIN_INFO(HEXAGON.A2_and,SI_ftype_SISI,2) +// +def int_hexagon_A2_and : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_and">; +// +// BUILTIN_INFO(HEXAGON.A2_or,SI_ftype_SISI,2) +// +def int_hexagon_A2_or : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_or">; +// +// BUILTIN_INFO(HEXAGON.A2_xor,SI_ftype_SISI,2) +// +def int_hexagon_A2_xor : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_xor">; +// +// BUILTIN_INFO(HEXAGON.A2_not,SI_ftype_SI,1) +// +def int_hexagon_A2_not : +Hexagon_si_si_Intrinsic<"HEXAGON_A2_not">; +// +// BUILTIN_INFO(HEXAGON.M2_xor_xacc,SI_ftype_SISISI,3) +// +def int_hexagon_M2_xor_xacc : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M2_xor_xacc">; +// +// BUILTIN_INFO(HEXAGON.M4_xor_xacc,DI_ftype_DIDIDI,3) +// +def int_hexagon_M4_xor_xacc : +Hexagon_di_dididi_Intrinsic<"HEXAGON_M4_xor_xacc">; +// +// BUILTIN_INFO(HEXAGON.A4_andn,SI_ftype_SISI,2) +// +def int_hexagon_A4_andn : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_andn">; +// +// BUILTIN_INFO(HEXAGON.A4_orn,SI_ftype_SISI,2) +// +def int_hexagon_A4_orn : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_orn">; +// +// BUILTIN_INFO(HEXAGON.A4_andnp,DI_ftype_DIDI,2) +// +def int_hexagon_A4_andnp : +Hexagon_di_didi_Intrinsic<"HEXAGON_A4_andnp">; +// +// BUILTIN_INFO(HEXAGON.A4_ornp,DI_ftype_DIDI,2) +// +def int_hexagon_A4_ornp : +Hexagon_di_didi_Intrinsic<"HEXAGON_A4_ornp">; +// +// BUILTIN_INFO(HEXAGON.S4_addaddi,SI_ftype_SISISI,3) +// +def int_hexagon_S4_addaddi : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S4_addaddi">; +// +// BUILTIN_INFO(HEXAGON.S4_subaddi,SI_ftype_SISISI,3) +// +def int_hexagon_S4_subaddi : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S4_subaddi">; +// +// BUILTIN_INFO(HEXAGON.M4_and_and,SI_ftype_SISISI,3) +// +def int_hexagon_M4_and_and : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M4_and_and">; +// +// BUILTIN_INFO(HEXAGON.M4_and_andn,SI_ftype_SISISI,3) +// +def int_hexagon_M4_and_andn : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M4_and_andn">; +// +// BUILTIN_INFO(HEXAGON.M4_and_or,SI_ftype_SISISI,3) +// +def int_hexagon_M4_and_or : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M4_and_or">; +// +// BUILTIN_INFO(HEXAGON.M4_and_xor,SI_ftype_SISISI,3) +// +def int_hexagon_M4_and_xor : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M4_and_xor">; +// +// BUILTIN_INFO(HEXAGON.M4_or_and,SI_ftype_SISISI,3) +// +def int_hexagon_M4_or_and : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M4_or_and">; +// +// BUILTIN_INFO(HEXAGON.M4_or_andn,SI_ftype_SISISI,3) +// +def int_hexagon_M4_or_andn : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M4_or_andn">; +// +// BUILTIN_INFO(HEXAGON.M4_or_or,SI_ftype_SISISI,3) +// +def int_hexagon_M4_or_or : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M4_or_or">; +// +// BUILTIN_INFO(HEXAGON.M4_or_xor,SI_ftype_SISISI,3) +// +def int_hexagon_M4_or_xor : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M4_or_xor">; +// +// BUILTIN_INFO(HEXAGON.S4_or_andix,SI_ftype_SISISI,3) +// +def int_hexagon_S4_or_andix : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S4_or_andix">; +// +// BUILTIN_INFO(HEXAGON.S4_or_andi,SI_ftype_SISISI,3) +// +def int_hexagon_S4_or_andi : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S4_or_andi">; +// +// BUILTIN_INFO(HEXAGON.S4_or_ori,SI_ftype_SISISI,3) +// +def int_hexagon_S4_or_ori : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S4_or_ori">; +// +// BUILTIN_INFO(HEXAGON.M4_xor_and,SI_ftype_SISISI,3) +// +def int_hexagon_M4_xor_and : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M4_xor_and">; +// +// BUILTIN_INFO(HEXAGON.M4_xor_or,SI_ftype_SISISI,3) +// +def int_hexagon_M4_xor_or : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M4_xor_or">; +// +// BUILTIN_INFO(HEXAGON.M4_xor_andn,SI_ftype_SISISI,3) +// +def int_hexagon_M4_xor_andn : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_M4_xor_andn">; +// +// BUILTIN_INFO(HEXAGON.A2_subri,SI_ftype_SISI,2) +// +def int_hexagon_A2_subri : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_subri">; +// +// BUILTIN_INFO(HEXAGON.A2_andir,SI_ftype_SISI,2) +// +def int_hexagon_A2_andir : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_andir">; +// +// BUILTIN_INFO(HEXAGON.A2_orir,SI_ftype_SISI,2) +// +def int_hexagon_A2_orir : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_orir">; +// +// BUILTIN_INFO(HEXAGON.A2_andp,DI_ftype_DIDI,2) +// +def int_hexagon_A2_andp : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_andp">; +// +// BUILTIN_INFO(HEXAGON.A2_orp,DI_ftype_DIDI,2) +// +def int_hexagon_A2_orp : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_orp">; +// +// BUILTIN_INFO(HEXAGON.A2_xorp,DI_ftype_DIDI,2) +// +def int_hexagon_A2_xorp : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_xorp">; +// +// BUILTIN_INFO(HEXAGON.A2_notp,DI_ftype_DI,1) +// +def int_hexagon_A2_notp : +Hexagon_di_di_Intrinsic<"HEXAGON_A2_notp">; +// +// BUILTIN_INFO(HEXAGON.A2_sxtw,DI_ftype_SI,1) +// +def int_hexagon_A2_sxtw : +Hexagon_di_si_Intrinsic<"HEXAGON_A2_sxtw">; +// +// BUILTIN_INFO(HEXAGON.A2_sat,SI_ftype_DI,1) +// +def int_hexagon_A2_sat : +Hexagon_si_di_Intrinsic<"HEXAGON_A2_sat">; +// +// BUILTIN_INFO(HEXAGON.A2_roundsat,SI_ftype_DI,1) +// +def int_hexagon_A2_roundsat : +Hexagon_si_di_Intrinsic<"HEXAGON_A2_roundsat">; +// +// BUILTIN_INFO(HEXAGON.A2_sath,SI_ftype_SI,1) +// +def int_hexagon_A2_sath : +Hexagon_si_si_Intrinsic<"HEXAGON_A2_sath">; +// +// BUILTIN_INFO(HEXAGON.A2_satuh,SI_ftype_SI,1) +// +def int_hexagon_A2_satuh : +Hexagon_si_si_Intrinsic<"HEXAGON_A2_satuh">; +// +// BUILTIN_INFO(HEXAGON.A2_satub,SI_ftype_SI,1) +// +def int_hexagon_A2_satub : +Hexagon_si_si_Intrinsic<"HEXAGON_A2_satub">; +// +// BUILTIN_INFO(HEXAGON.A2_satb,SI_ftype_SI,1) +// +def int_hexagon_A2_satb : +Hexagon_si_si_Intrinsic<"HEXAGON_A2_satb">; +// +// BUILTIN_INFO(HEXAGON.A2_vaddub,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vaddub : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vaddub">; +// +// BUILTIN_INFO(HEXAGON.A2_vaddb_map,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vaddb_map : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vaddb_map">; +// +// BUILTIN_INFO(HEXAGON.A2_vaddubs,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vaddubs : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vaddubs">; +// +// BUILTIN_INFO(HEXAGON.A2_vaddh,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vaddh : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vaddh">; +// +// BUILTIN_INFO(HEXAGON.A2_vaddhs,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vaddhs : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vaddhs">; +// +// BUILTIN_INFO(HEXAGON.A2_vadduhs,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vadduhs : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vadduhs">; +// +// BUILTIN_INFO(HEXAGON.A5_vaddhubs,SI_ftype_DIDI,2) +// +def int_hexagon_A5_vaddhubs : +Hexagon_si_didi_Intrinsic<"HEXAGON_A5_vaddhubs">; +// +// BUILTIN_INFO(HEXAGON.A2_vaddw,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vaddw : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vaddw">; +// +// BUILTIN_INFO(HEXAGON.A2_vaddws,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vaddws : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vaddws">; +// +// BUILTIN_INFO(HEXAGON.S4_vxaddsubw,DI_ftype_DIDI,2) +// +def int_hexagon_S4_vxaddsubw : +Hexagon_di_didi_Intrinsic<"HEXAGON_S4_vxaddsubw">; +// +// BUILTIN_INFO(HEXAGON.S4_vxsubaddw,DI_ftype_DIDI,2) +// +def int_hexagon_S4_vxsubaddw : +Hexagon_di_didi_Intrinsic<"HEXAGON_S4_vxsubaddw">; +// +// BUILTIN_INFO(HEXAGON.S4_vxaddsubh,DI_ftype_DIDI,2) +// +def int_hexagon_S4_vxaddsubh : +Hexagon_di_didi_Intrinsic<"HEXAGON_S4_vxaddsubh">; +// +// BUILTIN_INFO(HEXAGON.S4_vxsubaddh,DI_ftype_DIDI,2) +// +def int_hexagon_S4_vxsubaddh : +Hexagon_di_didi_Intrinsic<"HEXAGON_S4_vxsubaddh">; +// +// BUILTIN_INFO(HEXAGON.S4_vxaddsubhr,DI_ftype_DIDI,2) +// +def int_hexagon_S4_vxaddsubhr : +Hexagon_di_didi_Intrinsic<"HEXAGON_S4_vxaddsubhr">; +// +// BUILTIN_INFO(HEXAGON.S4_vxsubaddhr,DI_ftype_DIDI,2) +// +def int_hexagon_S4_vxsubaddhr : +Hexagon_di_didi_Intrinsic<"HEXAGON_S4_vxsubaddhr">; +// +// BUILTIN_INFO(HEXAGON.A2_svavgh,SI_ftype_SISI,2) +// +def int_hexagon_A2_svavgh : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_svavgh">; +// +// BUILTIN_INFO(HEXAGON.A2_svavghs,SI_ftype_SISI,2) +// +def int_hexagon_A2_svavghs : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_svavghs">; +// +// BUILTIN_INFO(HEXAGON.A2_svnavgh,SI_ftype_SISI,2) +// +def int_hexagon_A2_svnavgh : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_svnavgh">; +// +// BUILTIN_INFO(HEXAGON.A2_svaddh,SI_ftype_SISI,2) +// +def int_hexagon_A2_svaddh : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_svaddh">; +// +// BUILTIN_INFO(HEXAGON.A2_svaddhs,SI_ftype_SISI,2) +// +def int_hexagon_A2_svaddhs : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_svaddhs">; +// +// BUILTIN_INFO(HEXAGON.A2_svadduhs,SI_ftype_SISI,2) +// +def int_hexagon_A2_svadduhs : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_svadduhs">; +// +// BUILTIN_INFO(HEXAGON.A2_svsubh,SI_ftype_SISI,2) +// +def int_hexagon_A2_svsubh : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_svsubh">; +// +// BUILTIN_INFO(HEXAGON.A2_svsubhs,SI_ftype_SISI,2) +// +def int_hexagon_A2_svsubhs : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_svsubhs">; +// +// BUILTIN_INFO(HEXAGON.A2_svsubuhs,SI_ftype_SISI,2) +// +def int_hexagon_A2_svsubuhs : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_svsubuhs">; +// +// BUILTIN_INFO(HEXAGON.A2_vraddub,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vraddub : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vraddub">; +// +// BUILTIN_INFO(HEXAGON.A2_vraddub_acc,DI_ftype_DIDIDI,3) +// +def int_hexagon_A2_vraddub_acc : +Hexagon_di_dididi_Intrinsic<"HEXAGON_A2_vraddub_acc">; +// +// BUILTIN_INFO(HEXAGON.M2_vraddh,SI_ftype_DIDI,2) +// +def int_hexagon_M2_vraddh : +Hexagon_si_didi_Intrinsic<"HEXAGON_M2_vraddh">; +// +// BUILTIN_INFO(HEXAGON.M2_vradduh,SI_ftype_DIDI,2) +// +def int_hexagon_M2_vradduh : +Hexagon_si_didi_Intrinsic<"HEXAGON_M2_vradduh">; +// +// BUILTIN_INFO(HEXAGON.A2_vsubub,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vsubub : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vsubub">; +// +// BUILTIN_INFO(HEXAGON.A2_vsubb_map,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vsubb_map : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vsubb_map">; +// +// BUILTIN_INFO(HEXAGON.A2_vsububs,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vsububs : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vsububs">; +// +// BUILTIN_INFO(HEXAGON.A2_vsubh,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vsubh : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vsubh">; +// +// BUILTIN_INFO(HEXAGON.A2_vsubhs,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vsubhs : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vsubhs">; +// +// BUILTIN_INFO(HEXAGON.A2_vsubuhs,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vsubuhs : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vsubuhs">; +// +// BUILTIN_INFO(HEXAGON.A2_vsubw,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vsubw : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vsubw">; +// +// BUILTIN_INFO(HEXAGON.A2_vsubws,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vsubws : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vsubws">; +// +// BUILTIN_INFO(HEXAGON.A2_vabsh,DI_ftype_DI,1) +// +def int_hexagon_A2_vabsh : +Hexagon_di_di_Intrinsic<"HEXAGON_A2_vabsh">; +// +// BUILTIN_INFO(HEXAGON.A2_vabshsat,DI_ftype_DI,1) +// +def int_hexagon_A2_vabshsat : +Hexagon_di_di_Intrinsic<"HEXAGON_A2_vabshsat">; +// +// BUILTIN_INFO(HEXAGON.A2_vabsw,DI_ftype_DI,1) +// +def int_hexagon_A2_vabsw : +Hexagon_di_di_Intrinsic<"HEXAGON_A2_vabsw">; +// +// BUILTIN_INFO(HEXAGON.A2_vabswsat,DI_ftype_DI,1) +// +def int_hexagon_A2_vabswsat : +Hexagon_di_di_Intrinsic<"HEXAGON_A2_vabswsat">; +// +// BUILTIN_INFO(HEXAGON.M2_vabsdiffw,DI_ftype_DIDI,2) +// +def int_hexagon_M2_vabsdiffw : +Hexagon_di_didi_Intrinsic<"HEXAGON_M2_vabsdiffw">; +// +// BUILTIN_INFO(HEXAGON.M2_vabsdiffh,DI_ftype_DIDI,2) +// +def int_hexagon_M2_vabsdiffh : +Hexagon_di_didi_Intrinsic<"HEXAGON_M2_vabsdiffh">; +// +// BUILTIN_INFO(HEXAGON.A2_vrsadub,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vrsadub : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vrsadub">; +// +// BUILTIN_INFO(HEXAGON.A2_vrsadub_acc,DI_ftype_DIDIDI,3) +// +def int_hexagon_A2_vrsadub_acc : +Hexagon_di_dididi_Intrinsic<"HEXAGON_A2_vrsadub_acc">; +// +// BUILTIN_INFO(HEXAGON.A2_vavgub,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vavgub : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vavgub">; +// +// BUILTIN_INFO(HEXAGON.A2_vavguh,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vavguh : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vavguh">; +// +// BUILTIN_INFO(HEXAGON.A2_vavgh,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vavgh : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vavgh">; +// +// BUILTIN_INFO(HEXAGON.A2_vnavgh,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vnavgh : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vnavgh">; +// +// BUILTIN_INFO(HEXAGON.A2_vavgw,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vavgw : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vavgw">; +// +// BUILTIN_INFO(HEXAGON.A2_vnavgw,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vnavgw : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vnavgw">; +// +// BUILTIN_INFO(HEXAGON.A2_vavgwr,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vavgwr : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vavgwr">; +// +// BUILTIN_INFO(HEXAGON.A2_vnavgwr,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vnavgwr : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vnavgwr">; +// +// BUILTIN_INFO(HEXAGON.A2_vavgwcr,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vavgwcr : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vavgwcr">; +// +// BUILTIN_INFO(HEXAGON.A2_vnavgwcr,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vnavgwcr : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vnavgwcr">; +// +// BUILTIN_INFO(HEXAGON.A2_vavghcr,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vavghcr : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vavghcr">; +// +// BUILTIN_INFO(HEXAGON.A2_vnavghcr,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vnavghcr : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vnavghcr">; +// +// BUILTIN_INFO(HEXAGON.A2_vavguw,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vavguw : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vavguw">; +// +// BUILTIN_INFO(HEXAGON.A2_vavguwr,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vavguwr : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vavguwr">; +// +// BUILTIN_INFO(HEXAGON.A2_vavgubr,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vavgubr : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vavgubr">; +// +// BUILTIN_INFO(HEXAGON.A2_vavguhr,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vavguhr : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vavguhr">; +// +// BUILTIN_INFO(HEXAGON.A2_vavghr,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vavghr : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vavghr">; +// +// BUILTIN_INFO(HEXAGON.A2_vnavghr,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vnavghr : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vnavghr">; +// +// BUILTIN_INFO(HEXAGON.A4_round_ri,SI_ftype_SISI,2) +// +def int_hexagon_A4_round_ri : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_round_ri">; +// +// BUILTIN_INFO(HEXAGON.A4_round_rr,SI_ftype_SISI,2) +// +def int_hexagon_A4_round_rr : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_round_rr">; +// +// BUILTIN_INFO(HEXAGON.A4_round_ri_sat,SI_ftype_SISI,2) +// +def int_hexagon_A4_round_ri_sat : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_round_ri_sat">; +// +// BUILTIN_INFO(HEXAGON.A4_round_rr_sat,SI_ftype_SISI,2) +// +def int_hexagon_A4_round_rr_sat : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_round_rr_sat">; +// +// BUILTIN_INFO(HEXAGON.A4_cround_ri,SI_ftype_SISI,2) +// +def int_hexagon_A4_cround_ri : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cround_ri">; +// +// BUILTIN_INFO(HEXAGON.A4_cround_rr,SI_ftype_SISI,2) +// +def int_hexagon_A4_cround_rr : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cround_rr">; +// +// BUILTIN_INFO(HEXAGON.A4_vrminh,DI_ftype_DIDISI,3) +// +def int_hexagon_A4_vrminh : +Hexagon_di_didisi_Intrinsic<"HEXAGON_A4_vrminh">; +// +// BUILTIN_INFO(HEXAGON.A4_vrmaxh,DI_ftype_DIDISI,3) +// +def int_hexagon_A4_vrmaxh : +Hexagon_di_didisi_Intrinsic<"HEXAGON_A4_vrmaxh">; +// +// BUILTIN_INFO(HEXAGON.A4_vrminuh,DI_ftype_DIDISI,3) +// +def int_hexagon_A4_vrminuh : +Hexagon_di_didisi_Intrinsic<"HEXAGON_A4_vrminuh">; +// +// BUILTIN_INFO(HEXAGON.A4_vrmaxuh,DI_ftype_DIDISI,3) +// +def int_hexagon_A4_vrmaxuh : +Hexagon_di_didisi_Intrinsic<"HEXAGON_A4_vrmaxuh">; +// +// BUILTIN_INFO(HEXAGON.A4_vrminw,DI_ftype_DIDISI,3) +// +def int_hexagon_A4_vrminw : +Hexagon_di_didisi_Intrinsic<"HEXAGON_A4_vrminw">; +// +// BUILTIN_INFO(HEXAGON.A4_vrmaxw,DI_ftype_DIDISI,3) +// +def int_hexagon_A4_vrmaxw : +Hexagon_di_didisi_Intrinsic<"HEXAGON_A4_vrmaxw">; +// +// BUILTIN_INFO(HEXAGON.A4_vrminuw,DI_ftype_DIDISI,3) +// +def int_hexagon_A4_vrminuw : +Hexagon_di_didisi_Intrinsic<"HEXAGON_A4_vrminuw">; +// +// BUILTIN_INFO(HEXAGON.A4_vrmaxuw,DI_ftype_DIDISI,3) +// +def int_hexagon_A4_vrmaxuw : +Hexagon_di_didisi_Intrinsic<"HEXAGON_A4_vrmaxuw">; +// +// BUILTIN_INFO(HEXAGON.A2_vminb,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vminb : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vminb">; +// +// BUILTIN_INFO(HEXAGON.A2_vmaxb,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vmaxb : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vmaxb">; +// +// BUILTIN_INFO(HEXAGON.A2_vminub,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vminub : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vminub">; +// +// BUILTIN_INFO(HEXAGON.A2_vmaxub,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vmaxub : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vmaxub">; +// +// BUILTIN_INFO(HEXAGON.A2_vminh,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vminh : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vminh">; +// +// BUILTIN_INFO(HEXAGON.A2_vmaxh,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vmaxh : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vmaxh">; +// +// BUILTIN_INFO(HEXAGON.A2_vminuh,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vminuh : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vminuh">; +// +// BUILTIN_INFO(HEXAGON.A2_vmaxuh,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vmaxuh : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vmaxuh">; +// +// BUILTIN_INFO(HEXAGON.A2_vminw,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vminw : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vminw">; +// +// BUILTIN_INFO(HEXAGON.A2_vmaxw,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vmaxw : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vmaxw">; +// +// BUILTIN_INFO(HEXAGON.A2_vminuw,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vminuw : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vminuw">; +// +// BUILTIN_INFO(HEXAGON.A2_vmaxuw,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vmaxuw : +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vmaxuw">; +// +// BUILTIN_INFO(HEXAGON.A4_modwrapu,SI_ftype_SISI,2) +// +def int_hexagon_A4_modwrapu : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_modwrapu">; +// +// BUILTIN_INFO(HEXAGON.F2_sfadd,SF_ftype_SFSF,2) +// +def int_hexagon_F2_sfadd : +Hexagon_sf_sfsf_Intrinsic<"HEXAGON_F2_sfadd">; +// +// BUILTIN_INFO(HEXAGON.F2_sfsub,SF_ftype_SFSF,2) +// +def int_hexagon_F2_sfsub : +Hexagon_sf_sfsf_Intrinsic<"HEXAGON_F2_sfsub">; +// +// BUILTIN_INFO(HEXAGON.F2_sfmpy,SF_ftype_SFSF,2) +// +def int_hexagon_F2_sfmpy : +Hexagon_sf_sfsf_Intrinsic<"HEXAGON_F2_sfmpy">; +// +// BUILTIN_INFO(HEXAGON.F2_sffma,SF_ftype_SFSFSF,3) +// +def int_hexagon_F2_sffma : +Hexagon_sf_sfsfsf_Intrinsic<"HEXAGON_F2_sffma">; +// +// BUILTIN_INFO(HEXAGON.F2_sffma_sc,SF_ftype_SFSFSFQI,4) +// +def int_hexagon_F2_sffma_sc : +Hexagon_sf_sfsfsfqi_Intrinsic<"HEXAGON_F2_sffma_sc">; +// +// BUILTIN_INFO(HEXAGON.F2_sffms,SF_ftype_SFSFSF,3) +// +def int_hexagon_F2_sffms : +Hexagon_sf_sfsfsf_Intrinsic<"HEXAGON_F2_sffms">; +// +// BUILTIN_INFO(HEXAGON.F2_sffma_lib,SF_ftype_SFSFSF,3) +// +def int_hexagon_F2_sffma_lib : +Hexagon_sf_sfsfsf_Intrinsic<"HEXAGON_F2_sffma_lib">; +// +// BUILTIN_INFO(HEXAGON.F2_sffms_lib,SF_ftype_SFSFSF,3) +// +def int_hexagon_F2_sffms_lib : +Hexagon_sf_sfsfsf_Intrinsic<"HEXAGON_F2_sffms_lib">; +// +// BUILTIN_INFO(HEXAGON.F2_sfcmpeq,QI_ftype_SFSF,2) +// +def int_hexagon_F2_sfcmpeq : +Hexagon_qi_sfsf_Intrinsic<"HEXAGON_F2_sfcmpeq">; +// +// BUILTIN_INFO(HEXAGON.F2_sfcmpgt,QI_ftype_SFSF,2) +// +def int_hexagon_F2_sfcmpgt : +Hexagon_qi_sfsf_Intrinsic<"HEXAGON_F2_sfcmpgt">; +// +// BUILTIN_INFO(HEXAGON.F2_sfcmpge,QI_ftype_SFSF,2) +// +def int_hexagon_F2_sfcmpge : +Hexagon_qi_sfsf_Intrinsic<"HEXAGON_F2_sfcmpge">; +// +// BUILTIN_INFO(HEXAGON.F2_sfcmpuo,QI_ftype_SFSF,2) +// +def int_hexagon_F2_sfcmpuo : +Hexagon_qi_sfsf_Intrinsic<"HEXAGON_F2_sfcmpuo">; +// +// BUILTIN_INFO(HEXAGON.F2_sfmax,SF_ftype_SFSF,2) +// +def int_hexagon_F2_sfmax : +Hexagon_sf_sfsf_Intrinsic<"HEXAGON_F2_sfmax">; +// +// BUILTIN_INFO(HEXAGON.F2_sfmin,SF_ftype_SFSF,2) +// +def int_hexagon_F2_sfmin : +Hexagon_sf_sfsf_Intrinsic<"HEXAGON_F2_sfmin">; +// +// BUILTIN_INFO(HEXAGON.F2_sfclass,QI_ftype_SFSI,2) +// +def int_hexagon_F2_sfclass : +Hexagon_qi_sfsi_Intrinsic<"HEXAGON_F2_sfclass">; +// +// BUILTIN_INFO(HEXAGON.F2_sfimm_p,SF_ftype_SI,1) +// +def int_hexagon_F2_sfimm_p : +Hexagon_sf_si_Intrinsic<"HEXAGON_F2_sfimm_p">; +// +// BUILTIN_INFO(HEXAGON.F2_sfimm_n,SF_ftype_SI,1) +// +def int_hexagon_F2_sfimm_n : +Hexagon_sf_si_Intrinsic<"HEXAGON_F2_sfimm_n">; +// +// BUILTIN_INFO(HEXAGON.F2_sffixupn,SF_ftype_SFSF,2) +// +def int_hexagon_F2_sffixupn : +Hexagon_sf_sfsf_Intrinsic<"HEXAGON_F2_sffixupn">; +// +// BUILTIN_INFO(HEXAGON.F2_sffixupd,SF_ftype_SFSF,2) +// +def int_hexagon_F2_sffixupd : +Hexagon_sf_sfsf_Intrinsic<"HEXAGON_F2_sffixupd">; +// +// BUILTIN_INFO(HEXAGON.F2_sffixupr,SF_ftype_SF,1) +// +def int_hexagon_F2_sffixupr : +Hexagon_sf_sf_Intrinsic<"HEXAGON_F2_sffixupr">; +// +// BUILTIN_INFO(HEXAGON.F2_dfadd,DF_ftype_DFDF,2) +// +def int_hexagon_F2_dfadd : +Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfadd">; +// +// BUILTIN_INFO(HEXAGON.F2_dfsub,DF_ftype_DFDF,2) +// +def int_hexagon_F2_dfsub : +Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfsub">; +// +// BUILTIN_INFO(HEXAGON.F2_dfmpy,DF_ftype_DFDF,2) +// +def int_hexagon_F2_dfmpy : +Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfmpy">; +// +// BUILTIN_INFO(HEXAGON.F2_dffma,DF_ftype_DFDFDF,3) +// +def int_hexagon_F2_dffma : +Hexagon_df_dfdfdf_Intrinsic<"HEXAGON_F2_dffma">; +// +// BUILTIN_INFO(HEXAGON.F2_dffms,DF_ftype_DFDFDF,3) +// +def int_hexagon_F2_dffms : +Hexagon_df_dfdfdf_Intrinsic<"HEXAGON_F2_dffms">; +// +// BUILTIN_INFO(HEXAGON.F2_dffma_lib,DF_ftype_DFDFDF,3) +// +def int_hexagon_F2_dffma_lib : +Hexagon_df_dfdfdf_Intrinsic<"HEXAGON_F2_dffma_lib">; +// +// BUILTIN_INFO(HEXAGON.F2_dffms_lib,DF_ftype_DFDFDF,3) +// +def int_hexagon_F2_dffms_lib : +Hexagon_df_dfdfdf_Intrinsic<"HEXAGON_F2_dffms_lib">; +// +// BUILTIN_INFO(HEXAGON.F2_dffma_sc,DF_ftype_DFDFDFQI,4) +// +def int_hexagon_F2_dffma_sc : +Hexagon_df_dfdfdfqi_Intrinsic<"HEXAGON_F2_dffma_sc">; +// +// BUILTIN_INFO(HEXAGON.F2_dfmax,DF_ftype_DFDF,2) +// +def int_hexagon_F2_dfmax : +Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfmax">; +// +// BUILTIN_INFO(HEXAGON.F2_dfmin,DF_ftype_DFDF,2) +// +def int_hexagon_F2_dfmin : +Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfmin">; +// +// BUILTIN_INFO(HEXAGON.F2_dfcmpeq,QI_ftype_DFDF,2) +// +def int_hexagon_F2_dfcmpeq : +Hexagon_qi_dfdf_Intrinsic<"HEXAGON_F2_dfcmpeq">; +// +// BUILTIN_INFO(HEXAGON.F2_dfcmpgt,QI_ftype_DFDF,2) +// +def int_hexagon_F2_dfcmpgt : +Hexagon_qi_dfdf_Intrinsic<"HEXAGON_F2_dfcmpgt">; +// +// BUILTIN_INFO(HEXAGON.F2_dfcmpge,QI_ftype_DFDF,2) +// +def int_hexagon_F2_dfcmpge : +Hexagon_qi_dfdf_Intrinsic<"HEXAGON_F2_dfcmpge">; +// +// BUILTIN_INFO(HEXAGON.F2_dfcmpuo,QI_ftype_DFDF,2) +// +def int_hexagon_F2_dfcmpuo : +Hexagon_qi_dfdf_Intrinsic<"HEXAGON_F2_dfcmpuo">; +// +// BUILTIN_INFO(HEXAGON.F2_dfclass,QI_ftype_DFSI,2) +// +def int_hexagon_F2_dfclass : +Hexagon_qi_dfsi_Intrinsic<"HEXAGON_F2_dfclass">; +// +// BUILTIN_INFO(HEXAGON.F2_dfimm_p,DF_ftype_SI,1) +// +def int_hexagon_F2_dfimm_p : +Hexagon_df_si_Intrinsic<"HEXAGON_F2_dfimm_p">; +// +// BUILTIN_INFO(HEXAGON.F2_dfimm_n,DF_ftype_SI,1) +// +def int_hexagon_F2_dfimm_n : +Hexagon_df_si_Intrinsic<"HEXAGON_F2_dfimm_n">; +// +// BUILTIN_INFO(HEXAGON.F2_dffixupn,DF_ftype_DFDF,2) +// +def int_hexagon_F2_dffixupn : +Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dffixupn">; +// +// BUILTIN_INFO(HEXAGON.F2_dffixupd,DF_ftype_DFDF,2) +// +def int_hexagon_F2_dffixupd : +Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dffixupd">; +// +// BUILTIN_INFO(HEXAGON.F2_dffixupr,DF_ftype_DF,1) +// +def int_hexagon_F2_dffixupr : +Hexagon_df_df_Intrinsic<"HEXAGON_F2_dffixupr">; +// +// BUILTIN_INFO(HEXAGON.F2_conv_sf2df,DF_ftype_SF,1) +// +def int_hexagon_F2_conv_sf2df : +Hexagon_df_sf_Intrinsic<"HEXAGON_F2_conv_sf2df">; +// +// BUILTIN_INFO(HEXAGON.F2_conv_df2sf,SF_ftype_DF,1) +// +def int_hexagon_F2_conv_df2sf : +Hexagon_sf_df_Intrinsic<"HEXAGON_F2_conv_df2sf">; +// +// BUILTIN_INFO(HEXAGON.F2_conv_uw2sf,SF_ftype_SI,1) +// +def int_hexagon_F2_conv_uw2sf : +Hexagon_sf_si_Intrinsic<"HEXAGON_F2_conv_uw2sf">; +// +// BUILTIN_INFO(HEXAGON.F2_conv_uw2df,DF_ftype_SI,1) +// +def int_hexagon_F2_conv_uw2df : +Hexagon_df_si_Intrinsic<"HEXAGON_F2_conv_uw2df">; +// +// BUILTIN_INFO(HEXAGON.F2_conv_w2sf,SF_ftype_SI,1) +// +def int_hexagon_F2_conv_w2sf : +Hexagon_sf_si_Intrinsic<"HEXAGON_F2_conv_w2sf">; +// +// BUILTIN_INFO(HEXAGON.F2_conv_w2df,DF_ftype_SI,1) +// +def int_hexagon_F2_conv_w2df : +Hexagon_df_si_Intrinsic<"HEXAGON_F2_conv_w2df">; +// +// BUILTIN_INFO(HEXAGON.F2_conv_ud2sf,SF_ftype_DI,1) +// +def int_hexagon_F2_conv_ud2sf : +Hexagon_sf_di_Intrinsic<"HEXAGON_F2_conv_ud2sf">; +// +// BUILTIN_INFO(HEXAGON.F2_conv_ud2df,DF_ftype_DI,1) +// +def int_hexagon_F2_conv_ud2df : +Hexagon_df_di_Intrinsic<"HEXAGON_F2_conv_ud2df">; +// +// BUILTIN_INFO(HEXAGON.F2_conv_d2sf,SF_ftype_DI,1) +// +def int_hexagon_F2_conv_d2sf : +Hexagon_sf_di_Intrinsic<"HEXAGON_F2_conv_d2sf">; +// +// BUILTIN_INFO(HEXAGON.F2_conv_d2df,DF_ftype_DI,1) +// +def int_hexagon_F2_conv_d2df : +Hexagon_df_di_Intrinsic<"HEXAGON_F2_conv_d2df">; +// +// BUILTIN_INFO(HEXAGON.F2_conv_sf2uw,SI_ftype_SF,1) +// +def int_hexagon_F2_conv_sf2uw : +Hexagon_si_sf_Intrinsic<"HEXAGON_F2_conv_sf2uw">; +// +// BUILTIN_INFO(HEXAGON.F2_conv_sf2w,SI_ftype_SF,1) +// +def int_hexagon_F2_conv_sf2w : +Hexagon_si_sf_Intrinsic<"HEXAGON_F2_conv_sf2w">; +// +// BUILTIN_INFO(HEXAGON.F2_conv_sf2ud,DI_ftype_SF,1) +// +def int_hexagon_F2_conv_sf2ud : +Hexagon_di_sf_Intrinsic<"HEXAGON_F2_conv_sf2ud">; +// +// BUILTIN_INFO(HEXAGON.F2_conv_sf2d,DI_ftype_SF,1) +// +def int_hexagon_F2_conv_sf2d : +Hexagon_di_sf_Intrinsic<"HEXAGON_F2_conv_sf2d">; +// +// BUILTIN_INFO(HEXAGON.F2_conv_df2uw,SI_ftype_DF,1) +// +def int_hexagon_F2_conv_df2uw : +Hexagon_si_df_Intrinsic<"HEXAGON_F2_conv_df2uw">; +// +// BUILTIN_INFO(HEXAGON.F2_conv_df2w,SI_ftype_DF,1) +// +def int_hexagon_F2_conv_df2w : +Hexagon_si_df_Intrinsic<"HEXAGON_F2_conv_df2w">; +// +// BUILTIN_INFO(HEXAGON.F2_conv_df2ud,DI_ftype_DF,1) +// +def int_hexagon_F2_conv_df2ud : +Hexagon_di_df_Intrinsic<"HEXAGON_F2_conv_df2ud">; +// +// BUILTIN_INFO(HEXAGON.F2_conv_df2d,DI_ftype_DF,1) +// +def int_hexagon_F2_conv_df2d : +Hexagon_di_df_Intrinsic<"HEXAGON_F2_conv_df2d">; +// +// BUILTIN_INFO(HEXAGON.F2_conv_sf2uw_chop,SI_ftype_SF,1) +// +def int_hexagon_F2_conv_sf2uw_chop : +Hexagon_si_sf_Intrinsic<"HEXAGON_F2_conv_sf2uw_chop">; +// +// BUILTIN_INFO(HEXAGON.F2_conv_sf2w_chop,SI_ftype_SF,1) +// +def int_hexagon_F2_conv_sf2w_chop : +Hexagon_si_sf_Intrinsic<"HEXAGON_F2_conv_sf2w_chop">; +// +// BUILTIN_INFO(HEXAGON.F2_conv_sf2ud_chop,DI_ftype_SF,1) +// +def int_hexagon_F2_conv_sf2ud_chop : +Hexagon_di_sf_Intrinsic<"HEXAGON_F2_conv_sf2ud_chop">; +// +// BUILTIN_INFO(HEXAGON.F2_conv_sf2d_chop,DI_ftype_SF,1) +// +def int_hexagon_F2_conv_sf2d_chop : +Hexagon_di_sf_Intrinsic<"HEXAGON_F2_conv_sf2d_chop">; +// +// BUILTIN_INFO(HEXAGON.F2_conv_df2uw_chop,SI_ftype_DF,1) +// +def int_hexagon_F2_conv_df2uw_chop : +Hexagon_si_df_Intrinsic<"HEXAGON_F2_conv_df2uw_chop">; +// +// BUILTIN_INFO(HEXAGON.F2_conv_df2w_chop,SI_ftype_DF,1) +// +def int_hexagon_F2_conv_df2w_chop : +Hexagon_si_df_Intrinsic<"HEXAGON_F2_conv_df2w_chop">; +// +// BUILTIN_INFO(HEXAGON.F2_conv_df2ud_chop,DI_ftype_DF,1) +// +def int_hexagon_F2_conv_df2ud_chop : +Hexagon_di_df_Intrinsic<"HEXAGON_F2_conv_df2ud_chop">; +// +// BUILTIN_INFO(HEXAGON.F2_conv_df2d_chop,DI_ftype_DF,1) +// +def int_hexagon_F2_conv_df2d_chop : +Hexagon_di_df_Intrinsic<"HEXAGON_F2_conv_df2d_chop">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_r_r,SI_ftype_SISI,2) +// +def int_hexagon_S2_asr_r_r : +Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_asr_r_r">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_r_r,SI_ftype_SISI,2) +// +def int_hexagon_S2_asl_r_r : +Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_asl_r_r">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_r_r,SI_ftype_SISI,2) +// +def int_hexagon_S2_lsr_r_r : +Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_lsr_r_r">; +// +// BUILTIN_INFO(HEXAGON.S2_lsl_r_r,SI_ftype_SISI,2) +// +def int_hexagon_S2_lsl_r_r : +Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_lsl_r_r">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_r_p,DI_ftype_DISI,2) +// +def int_hexagon_S2_asr_r_p : +Hexagon_di_disi_Intrinsic<"HEXAGON_S2_asr_r_p">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_r_p,DI_ftype_DISI,2) +// +def int_hexagon_S2_asl_r_p : +Hexagon_di_disi_Intrinsic<"HEXAGON_S2_asl_r_p">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_r_p,DI_ftype_DISI,2) +// +def int_hexagon_S2_lsr_r_p : +Hexagon_di_disi_Intrinsic<"HEXAGON_S2_lsr_r_p">; +// +// BUILTIN_INFO(HEXAGON.S2_lsl_r_p,DI_ftype_DISI,2) +// +def int_hexagon_S2_lsl_r_p : +Hexagon_di_disi_Intrinsic<"HEXAGON_S2_lsl_r_p">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_r_r_acc,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asr_r_r_acc : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S2_asr_r_r_acc">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_r_r_acc,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asl_r_r_acc : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S2_asl_r_r_acc">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_r_r_acc,SI_ftype_SISISI,3) +// +def int_hexagon_S2_lsr_r_r_acc : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S2_lsr_r_r_acc">; +// +// BUILTIN_INFO(HEXAGON.S2_lsl_r_r_acc,SI_ftype_SISISI,3) +// +def int_hexagon_S2_lsl_r_r_acc : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S2_lsl_r_r_acc">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_r_p_acc,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asr_r_p_acc : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_asr_r_p_acc">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_r_p_acc,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asl_r_p_acc : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_asl_r_p_acc">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_r_p_acc,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_lsr_r_p_acc : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_lsr_r_p_acc">; +// +// BUILTIN_INFO(HEXAGON.S2_lsl_r_p_acc,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_lsl_r_p_acc : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_lsl_r_p_acc">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_r_r_nac,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asr_r_r_nac : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S2_asr_r_r_nac">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_r_r_nac,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asl_r_r_nac : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S2_asl_r_r_nac">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_r_r_nac,SI_ftype_SISISI,3) +// +def int_hexagon_S2_lsr_r_r_nac : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S2_lsr_r_r_nac">; +// +// BUILTIN_INFO(HEXAGON.S2_lsl_r_r_nac,SI_ftype_SISISI,3) +// +def int_hexagon_S2_lsl_r_r_nac : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S2_lsl_r_r_nac">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_r_p_nac,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asr_r_p_nac : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_asr_r_p_nac">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_r_p_nac,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asl_r_p_nac : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_asl_r_p_nac">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_r_p_nac,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_lsr_r_p_nac : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_lsr_r_p_nac">; +// +// BUILTIN_INFO(HEXAGON.S2_lsl_r_p_nac,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_lsl_r_p_nac : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_lsl_r_p_nac">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_r_r_and,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asr_r_r_and : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S2_asr_r_r_and">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_r_r_and,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asl_r_r_and : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S2_asl_r_r_and">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_r_r_and,SI_ftype_SISISI,3) +// +def int_hexagon_S2_lsr_r_r_and : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S2_lsr_r_r_and">; +// +// BUILTIN_INFO(HEXAGON.S2_lsl_r_r_and,SI_ftype_SISISI,3) +// +def int_hexagon_S2_lsl_r_r_and : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S2_lsl_r_r_and">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_r_r_or,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asr_r_r_or : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S2_asr_r_r_or">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_r_r_or,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asl_r_r_or : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S2_asl_r_r_or">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_r_r_or,SI_ftype_SISISI,3) +// +def int_hexagon_S2_lsr_r_r_or : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S2_lsr_r_r_or">; +// +// BUILTIN_INFO(HEXAGON.S2_lsl_r_r_or,SI_ftype_SISISI,3) +// +def int_hexagon_S2_lsl_r_r_or : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S2_lsl_r_r_or">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_r_p_and,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asr_r_p_and : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_asr_r_p_and">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_r_p_and,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asl_r_p_and : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_asl_r_p_and">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_r_p_and,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_lsr_r_p_and : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_lsr_r_p_and">; +// +// BUILTIN_INFO(HEXAGON.S2_lsl_r_p_and,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_lsl_r_p_and : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_lsl_r_p_and">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_r_p_or,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asr_r_p_or : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_asr_r_p_or">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_r_p_or,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asl_r_p_or : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_asl_r_p_or">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_r_p_or,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_lsr_r_p_or : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_lsr_r_p_or">; +// +// BUILTIN_INFO(HEXAGON.S2_lsl_r_p_or,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_lsl_r_p_or : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_lsl_r_p_or">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_r_p_xor,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asr_r_p_xor : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_asr_r_p_xor">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_r_p_xor,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asl_r_p_xor : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_asl_r_p_xor">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_r_p_xor,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_lsr_r_p_xor : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_lsr_r_p_xor">; +// +// BUILTIN_INFO(HEXAGON.S2_lsl_r_p_xor,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_lsl_r_p_xor : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_lsl_r_p_xor">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_r_r_sat,SI_ftype_SISI,2) +// +def int_hexagon_S2_asr_r_r_sat : +Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_asr_r_r_sat">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_r_r_sat,SI_ftype_SISI,2) +// +def int_hexagon_S2_asl_r_r_sat : +Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_asl_r_r_sat">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_i_r,SI_ftype_SISI,2) +// +def int_hexagon_S2_asr_i_r : +Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_asr_i_r">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_i_r,SI_ftype_SISI,2) +// +def int_hexagon_S2_lsr_i_r : +Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_lsr_i_r">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_i_r,SI_ftype_SISI,2) +// +def int_hexagon_S2_asl_i_r : +Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_asl_i_r">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_i_p,DI_ftype_DISI,2) +// +def int_hexagon_S2_asr_i_p : +Hexagon_di_disi_Intrinsic<"HEXAGON_S2_asr_i_p">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_i_p,DI_ftype_DISI,2) +// +def int_hexagon_S2_lsr_i_p : +Hexagon_di_disi_Intrinsic<"HEXAGON_S2_lsr_i_p">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_i_p,DI_ftype_DISI,2) +// +def int_hexagon_S2_asl_i_p : +Hexagon_di_disi_Intrinsic<"HEXAGON_S2_asl_i_p">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_i_r_acc,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asr_i_r_acc : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S2_asr_i_r_acc">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_i_r_acc,SI_ftype_SISISI,3) +// +def int_hexagon_S2_lsr_i_r_acc : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S2_lsr_i_r_acc">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_i_r_acc,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asl_i_r_acc : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S2_asl_i_r_acc">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_i_p_acc,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asr_i_p_acc : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_asr_i_p_acc">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_i_p_acc,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_lsr_i_p_acc : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_lsr_i_p_acc">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_i_p_acc,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asl_i_p_acc : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_asl_i_p_acc">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_i_r_nac,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asr_i_r_nac : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S2_asr_i_r_nac">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_i_r_nac,SI_ftype_SISISI,3) +// +def int_hexagon_S2_lsr_i_r_nac : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S2_lsr_i_r_nac">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_i_r_nac,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asl_i_r_nac : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S2_asl_i_r_nac">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_i_p_nac,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asr_i_p_nac : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_asr_i_p_nac">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_i_p_nac,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_lsr_i_p_nac : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_lsr_i_p_nac">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_i_p_nac,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asl_i_p_nac : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_asl_i_p_nac">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_i_r_xacc,SI_ftype_SISISI,3) +// +def int_hexagon_S2_lsr_i_r_xacc : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S2_lsr_i_r_xacc">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_i_r_xacc,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asl_i_r_xacc : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S2_asl_i_r_xacc">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_i_p_xacc,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_lsr_i_p_xacc : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_lsr_i_p_xacc">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_i_p_xacc,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asl_i_p_xacc : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_asl_i_p_xacc">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_i_r_and,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asr_i_r_and : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S2_asr_i_r_and">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_i_r_and,SI_ftype_SISISI,3) +// +def int_hexagon_S2_lsr_i_r_and : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S2_lsr_i_r_and">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_i_r_and,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asl_i_r_and : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S2_asl_i_r_and">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_i_r_or,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asr_i_r_or : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S2_asr_i_r_or">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_i_r_or,SI_ftype_SISISI,3) +// +def int_hexagon_S2_lsr_i_r_or : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S2_lsr_i_r_or">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_i_r_or,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asl_i_r_or : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S2_asl_i_r_or">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_i_p_and,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asr_i_p_and : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_asr_i_p_and">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_i_p_and,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_lsr_i_p_and : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_lsr_i_p_and">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_i_p_and,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asl_i_p_and : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_asl_i_p_and">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_i_p_or,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asr_i_p_or : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_asr_i_p_or">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_i_p_or,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_lsr_i_p_or : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_lsr_i_p_or">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_i_p_or,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asl_i_p_or : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_asl_i_p_or">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_i_r_sat,SI_ftype_SISI,2) +// +def int_hexagon_S2_asl_i_r_sat : +Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_asl_i_r_sat">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_i_r_rnd,SI_ftype_SISI,2) +// +def int_hexagon_S2_asr_i_r_rnd : +Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_asr_i_r_rnd">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_i_r_rnd_goodsyntax,SI_ftype_SISI,2) +// +def int_hexagon_S2_asr_i_r_rnd_goodsyntax : +Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_asr_i_r_rnd_goodsyntax">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_i_p_rnd,DI_ftype_DISI,2) +// +def int_hexagon_S2_asr_i_p_rnd : +Hexagon_di_disi_Intrinsic<"HEXAGON_S2_asr_i_p_rnd">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_i_p_rnd_goodsyntax,DI_ftype_DISI,2) +// +def int_hexagon_S2_asr_i_p_rnd_goodsyntax : +Hexagon_di_disi_Intrinsic<"HEXAGON_S2_asr_i_p_rnd_goodsyntax">; +// +// BUILTIN_INFO(HEXAGON.S4_lsli,SI_ftype_SISI,2) +// +def int_hexagon_S4_lsli : +Hexagon_si_sisi_Intrinsic<"HEXAGON_S4_lsli">; +// +// BUILTIN_INFO(HEXAGON.S2_addasl_rrri,SI_ftype_SISISI,3) +// +def int_hexagon_S2_addasl_rrri : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S2_addasl_rrri">; +// +// BUILTIN_INFO(HEXAGON.S4_andi_asl_ri,SI_ftype_SISISI,3) +// +def int_hexagon_S4_andi_asl_ri : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S4_andi_asl_ri">; +// +// BUILTIN_INFO(HEXAGON.S4_ori_asl_ri,SI_ftype_SISISI,3) +// +def int_hexagon_S4_ori_asl_ri : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S4_ori_asl_ri">; +// +// BUILTIN_INFO(HEXAGON.S4_addi_asl_ri,SI_ftype_SISISI,3) +// +def int_hexagon_S4_addi_asl_ri : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S4_addi_asl_ri">; +// +// BUILTIN_INFO(HEXAGON.S4_subi_asl_ri,SI_ftype_SISISI,3) +// +def int_hexagon_S4_subi_asl_ri : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S4_subi_asl_ri">; +// +// BUILTIN_INFO(HEXAGON.S4_andi_lsr_ri,SI_ftype_SISISI,3) +// +def int_hexagon_S4_andi_lsr_ri : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S4_andi_lsr_ri">; +// +// BUILTIN_INFO(HEXAGON.S4_ori_lsr_ri,SI_ftype_SISISI,3) +// +def int_hexagon_S4_ori_lsr_ri : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S4_ori_lsr_ri">; +// +// BUILTIN_INFO(HEXAGON.S4_addi_lsr_ri,SI_ftype_SISISI,3) +// +def int_hexagon_S4_addi_lsr_ri : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S4_addi_lsr_ri">; +// +// BUILTIN_INFO(HEXAGON.S4_subi_lsr_ri,SI_ftype_SISISI,3) +// +def int_hexagon_S4_subi_lsr_ri : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S4_subi_lsr_ri">; +// +// BUILTIN_INFO(HEXAGON.S2_valignib,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_valignib : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_valignib">; +// +// BUILTIN_INFO(HEXAGON.S2_valignrb,DI_ftype_DIDIQI,3) +// +def int_hexagon_S2_valignrb : +Hexagon_di_didiqi_Intrinsic<"HEXAGON_S2_valignrb">; +// +// BUILTIN_INFO(HEXAGON.S2_vspliceib,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_vspliceib : +Hexagon_di_didisi_Intrinsic<"HEXAGON_S2_vspliceib">; +// +// BUILTIN_INFO(HEXAGON.S2_vsplicerb,DI_ftype_DIDIQI,3) +// +def int_hexagon_S2_vsplicerb : +Hexagon_di_didiqi_Intrinsic<"HEXAGON_S2_vsplicerb">; +// +// BUILTIN_INFO(HEXAGON.S2_vsplatrh,DI_ftype_SI,1) +// +def int_hexagon_S2_vsplatrh : +Hexagon_di_si_Intrinsic<"HEXAGON_S2_vsplatrh">; +// +// BUILTIN_INFO(HEXAGON.S2_vsplatrb,SI_ftype_SI,1) +// +def int_hexagon_S2_vsplatrb : +Hexagon_si_si_Intrinsic<"HEXAGON_S2_vsplatrb">; +// +// BUILTIN_INFO(HEXAGON.S2_insert,SI_ftype_SISISISI,4) +// +def int_hexagon_S2_insert : +Hexagon_si_sisisisi_Intrinsic<"HEXAGON_S2_insert">; +// +// BUILTIN_INFO(HEXAGON.S2_tableidxb_goodsyntax,SI_ftype_SISISISI,4) +// +def int_hexagon_S2_tableidxb_goodsyntax : +Hexagon_si_sisisisi_Intrinsic<"HEXAGON_S2_tableidxb_goodsyntax">; +// +// BUILTIN_INFO(HEXAGON.S2_tableidxh_goodsyntax,SI_ftype_SISISISI,4) +// +def int_hexagon_S2_tableidxh_goodsyntax : +Hexagon_si_sisisisi_Intrinsic<"HEXAGON_S2_tableidxh_goodsyntax">; +// +// BUILTIN_INFO(HEXAGON.S2_tableidxw_goodsyntax,SI_ftype_SISISISI,4) +// +def int_hexagon_S2_tableidxw_goodsyntax : +Hexagon_si_sisisisi_Intrinsic<"HEXAGON_S2_tableidxw_goodsyntax">; +// +// BUILTIN_INFO(HEXAGON.S2_tableidxd_goodsyntax,SI_ftype_SISISISI,4) +// +def int_hexagon_S2_tableidxd_goodsyntax : +Hexagon_si_sisisisi_Intrinsic<"HEXAGON_S2_tableidxd_goodsyntax">; +// +// BUILTIN_INFO(HEXAGON.A4_bitspliti,DI_ftype_SISI,2) +// +def int_hexagon_A4_bitspliti : +Hexagon_di_sisi_Intrinsic<"HEXAGON_A4_bitspliti">; +// +// BUILTIN_INFO(HEXAGON.A4_bitsplit,DI_ftype_SISI,2) +// +def int_hexagon_A4_bitsplit : +Hexagon_di_sisi_Intrinsic<"HEXAGON_A4_bitsplit">; +// +// BUILTIN_INFO(HEXAGON.S4_extract,SI_ftype_SISISI,3) +// +def int_hexagon_S4_extract : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S4_extract">; +// +// BUILTIN_INFO(HEXAGON.S2_extractu,SI_ftype_SISISI,3) +// +def int_hexagon_S2_extractu : +Hexagon_si_sisisi_Intrinsic<"HEXAGON_S2_extractu">; +// +// BUILTIN_INFO(HEXAGON.S2_insertp,DI_ftype_DIDISISI,4) +// +def int_hexagon_S2_insertp : +Hexagon_di_didisisi_Intrinsic<"HEXAGON_S2_insertp">; +// +// BUILTIN_INFO(HEXAGON.S4_extractp,DI_ftype_DISISI,3) +// +def int_hexagon_S4_extractp : +Hexagon_di_disisi_Intrinsic<"HEXAGON_S4_extractp">; +// +// BUILTIN_INFO(HEXAGON.S2_extractup,DI_ftype_DISISI,3) +// +def int_hexagon_S2_extractup : +Hexagon_di_disisi_Intrinsic<"HEXAGON_S2_extractup">; +// +// BUILTIN_INFO(HEXAGON.S2_insert_rp,SI_ftype_SISIDI,3) +// +def int_hexagon_S2_insert_rp : +Hexagon_si_sisidi_Intrinsic<"HEXAGON_S2_insert_rp">; +// +// BUILTIN_INFO(HEXAGON.S4_extract_rp,SI_ftype_SIDI,2) +// +def int_hexagon_S4_extract_rp : +Hexagon_si_sidi_Intrinsic<"HEXAGON_S4_extract_rp">; +// +// BUILTIN_INFO(HEXAGON.S2_extractu_rp,SI_ftype_SIDI,2) +// +def int_hexagon_S2_extractu_rp : +Hexagon_si_sidi_Intrinsic<"HEXAGON_S2_extractu_rp">; +// +// BUILTIN_INFO(HEXAGON.S2_insertp_rp,DI_ftype_DIDIDI,3) +// +def int_hexagon_S2_insertp_rp : +Hexagon_di_dididi_Intrinsic<"HEXAGON_S2_insertp_rp">; +// +// BUILTIN_INFO(HEXAGON.S4_extractp_rp,DI_ftype_DIDI,2) +// +def int_hexagon_S4_extractp_rp : +Hexagon_di_didi_Intrinsic<"HEXAGON_S4_extractp_rp">; +// +// BUILTIN_INFO(HEXAGON.S2_extractup_rp,DI_ftype_DIDI,2) +// +def int_hexagon_S2_extractup_rp : +Hexagon_di_didi_Intrinsic<"HEXAGON_S2_extractup_rp">; +// +// BUILTIN_INFO(HEXAGON.S2_tstbit_i,QI_ftype_SISI,2) +// +def int_hexagon_S2_tstbit_i : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_S2_tstbit_i">; +// +// BUILTIN_INFO(HEXAGON.S4_ntstbit_i,QI_ftype_SISI,2) +// +def int_hexagon_S4_ntstbit_i : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_S4_ntstbit_i">; +// +// BUILTIN_INFO(HEXAGON.S2_setbit_i,SI_ftype_SISI,2) +// +def int_hexagon_S2_setbit_i : +Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_setbit_i">; +// +// BUILTIN_INFO(HEXAGON.S2_togglebit_i,SI_ftype_SISI,2) +// +def int_hexagon_S2_togglebit_i : +Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_togglebit_i">; +// +// BUILTIN_INFO(HEXAGON.S2_clrbit_i,SI_ftype_SISI,2) +// +def int_hexagon_S2_clrbit_i : +Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_clrbit_i">; +// +// BUILTIN_INFO(HEXAGON.S2_tstbit_r,QI_ftype_SISI,2) +// +def int_hexagon_S2_tstbit_r : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_S2_tstbit_r">; +// +// BUILTIN_INFO(HEXAGON.S4_ntstbit_r,QI_ftype_SISI,2) +// +def int_hexagon_S4_ntstbit_r : +Hexagon_qi_sisi_Intrinsic<"HEXAGON_S4_ntstbit_r">; +// +// BUILTIN_INFO(HEXAGON.S2_setbit_r,SI_ftype_SISI,2) +// +def int_hexagon_S2_setbit_r : +Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_setbit_r">; +// +// BUILTIN_INFO(HEXAGON.S2_togglebit_r,SI_ftype_SISI,2) +// +def int_hexagon_S2_togglebit_r : +Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_togglebit_r">; +// +// BUILTIN_INFO(HEXAGON.S2_clrbit_r,SI_ftype_SISI,2) +// +def int_hexagon_S2_clrbit_r : +Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_clrbit_r">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_i_vh,DI_ftype_DISI,2) +// +def int_hexagon_S2_asr_i_vh : +Hexagon_di_disi_Intrinsic<"HEXAGON_S2_asr_i_vh">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_i_vh,DI_ftype_DISI,2) +// +def int_hexagon_S2_lsr_i_vh : +Hexagon_di_disi_Intrinsic<"HEXAGON_S2_lsr_i_vh">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_i_vh,DI_ftype_DISI,2) +// +def int_hexagon_S2_asl_i_vh : +Hexagon_di_disi_Intrinsic<"HEXAGON_S2_asl_i_vh">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_r_vh,DI_ftype_DISI,2) +// +def int_hexagon_S2_asr_r_vh : +Hexagon_di_disi_Intrinsic<"HEXAGON_S2_asr_r_vh">; +// +// BUILTIN_INFO(HEXAGON.S5_asrhub_rnd_sat_goodsyntax,SI_ftype_DISI,2) +// +def int_hexagon_S5_asrhub_rnd_sat_goodsyntax : +Hexagon_si_disi_Intrinsic<"HEXAGON_S5_asrhub_rnd_sat_goodsyntax">; +// +// BUILTIN_INFO(HEXAGON.S5_asrhub_sat,SI_ftype_DISI,2) +// +def int_hexagon_S5_asrhub_sat : +Hexagon_si_disi_Intrinsic<"HEXAGON_S5_asrhub_sat">; +// +// BUILTIN_INFO(HEXAGON.S5_vasrhrnd_goodsyntax,DI_ftype_DISI,2) +// +def int_hexagon_S5_vasrhrnd_goodsyntax : +Hexagon_di_disi_Intrinsic<"HEXAGON_S5_vasrhrnd_goodsyntax">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_r_vh,DI_ftype_DISI,2) +// +def int_hexagon_S2_asl_r_vh : +Hexagon_di_disi_Intrinsic<"HEXAGON_S2_asl_r_vh">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_r_vh,DI_ftype_DISI,2) +// +def int_hexagon_S2_lsr_r_vh : +Hexagon_di_disi_Intrinsic<"HEXAGON_S2_lsr_r_vh">; +// +// BUILTIN_INFO(HEXAGON.S2_lsl_r_vh,DI_ftype_DISI,2) +// +def int_hexagon_S2_lsl_r_vh : +Hexagon_di_disi_Intrinsic<"HEXAGON_S2_lsl_r_vh">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_i_vw,DI_ftype_DISI,2) +// +def int_hexagon_S2_asr_i_vw : +Hexagon_di_disi_Intrinsic<"HEXAGON_S2_asr_i_vw">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_i_svw_trun,SI_ftype_DISI,2) +// +def int_hexagon_S2_asr_i_svw_trun : +Hexagon_si_disi_Intrinsic<"HEXAGON_S2_asr_i_svw_trun">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_r_svw_trun,SI_ftype_DISI,2) +// +def int_hexagon_S2_asr_r_svw_trun : +Hexagon_si_disi_Intrinsic<"HEXAGON_S2_asr_r_svw_trun">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_i_vw,DI_ftype_DISI,2) +// +def int_hexagon_S2_lsr_i_vw : +Hexagon_di_disi_Intrinsic<"HEXAGON_S2_lsr_i_vw">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_i_vw,DI_ftype_DISI,2) +// +def int_hexagon_S2_asl_i_vw : +Hexagon_di_disi_Intrinsic<"HEXAGON_S2_asl_i_vw">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_r_vw,DI_ftype_DISI,2) +// +def int_hexagon_S2_asr_r_vw : +Hexagon_di_disi_Intrinsic<"HEXAGON_S2_asr_r_vw">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_r_vw,DI_ftype_DISI,2) +// +def int_hexagon_S2_asl_r_vw : +Hexagon_di_disi_Intrinsic<"HEXAGON_S2_asl_r_vw">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_r_vw,DI_ftype_DISI,2) +// +def int_hexagon_S2_lsr_r_vw : +Hexagon_di_disi_Intrinsic<"HEXAGON_S2_lsr_r_vw">; +// +// BUILTIN_INFO(HEXAGON.S2_lsl_r_vw,DI_ftype_DISI,2) +// +def int_hexagon_S2_lsl_r_vw : +Hexagon_di_disi_Intrinsic<"HEXAGON_S2_lsl_r_vw">; +// +// BUILTIN_INFO(HEXAGON.S2_vrndpackwh,SI_ftype_DI,1) +// +def int_hexagon_S2_vrndpackwh : +Hexagon_si_di_Intrinsic<"HEXAGON_S2_vrndpackwh">; +// +// BUILTIN_INFO(HEXAGON.S2_vrndpackwhs,SI_ftype_DI,1) +// +def int_hexagon_S2_vrndpackwhs : +Hexagon_si_di_Intrinsic<"HEXAGON_S2_vrndpackwhs">; +// +// BUILTIN_INFO(HEXAGON.S2_vsxtbh,DI_ftype_SI,1) +// +def int_hexagon_S2_vsxtbh : +Hexagon_di_si_Intrinsic<"HEXAGON_S2_vsxtbh">; +// +// BUILTIN_INFO(HEXAGON.S2_vzxtbh,DI_ftype_SI,1) +// +def int_hexagon_S2_vzxtbh : +Hexagon_di_si_Intrinsic<"HEXAGON_S2_vzxtbh">; +// +// BUILTIN_INFO(HEXAGON.S2_vsathub,SI_ftype_DI,1) +// +def int_hexagon_S2_vsathub : +Hexagon_si_di_Intrinsic<"HEXAGON_S2_vsathub">; +// +// BUILTIN_INFO(HEXAGON.S2_svsathub,SI_ftype_SI,1) +// +def int_hexagon_S2_svsathub : +Hexagon_si_si_Intrinsic<"HEXAGON_S2_svsathub">; +// +// BUILTIN_INFO(HEXAGON.S2_svsathb,SI_ftype_SI,1) +// +def int_hexagon_S2_svsathb : +Hexagon_si_si_Intrinsic<"HEXAGON_S2_svsathb">; +// +// BUILTIN_INFO(HEXAGON.S2_vsathb,SI_ftype_DI,1) +// +def int_hexagon_S2_vsathb : +Hexagon_si_di_Intrinsic<"HEXAGON_S2_vsathb">; +// +// BUILTIN_INFO(HEXAGON.S2_vtrunohb,SI_ftype_DI,1) +// +def int_hexagon_S2_vtrunohb : +Hexagon_si_di_Intrinsic<"HEXAGON_S2_vtrunohb">; +// +// BUILTIN_INFO(HEXAGON.S2_vtrunewh,DI_ftype_DIDI,2) +// +def int_hexagon_S2_vtrunewh : +Hexagon_di_didi_Intrinsic<"HEXAGON_S2_vtrunewh">; +// +// BUILTIN_INFO(HEXAGON.S2_vtrunowh,DI_ftype_DIDI,2) +// +def int_hexagon_S2_vtrunowh : +Hexagon_di_didi_Intrinsic<"HEXAGON_S2_vtrunowh">; +// +// BUILTIN_INFO(HEXAGON.S2_vtrunehb,SI_ftype_DI,1) +// +def int_hexagon_S2_vtrunehb : +Hexagon_si_di_Intrinsic<"HEXAGON_S2_vtrunehb">; +// +// BUILTIN_INFO(HEXAGON.S2_vsxthw,DI_ftype_SI,1) +// +def int_hexagon_S2_vsxthw : +Hexagon_di_si_Intrinsic<"HEXAGON_S2_vsxthw">; +// +// BUILTIN_INFO(HEXAGON.S2_vzxthw,DI_ftype_SI,1) +// +def int_hexagon_S2_vzxthw : +Hexagon_di_si_Intrinsic<"HEXAGON_S2_vzxthw">; +// +// BUILTIN_INFO(HEXAGON.S2_vsatwh,SI_ftype_DI,1) +// +def int_hexagon_S2_vsatwh : +Hexagon_si_di_Intrinsic<"HEXAGON_S2_vsatwh">; +// +// BUILTIN_INFO(HEXAGON.S2_vsatwuh,SI_ftype_DI,1) +// +def int_hexagon_S2_vsatwuh : +Hexagon_si_di_Intrinsic<"HEXAGON_S2_vsatwuh">; +// +// BUILTIN_INFO(HEXAGON.S2_packhl,DI_ftype_SISI,2) +// +def int_hexagon_S2_packhl : +Hexagon_di_sisi_Intrinsic<"HEXAGON_S2_packhl">; +// +// BUILTIN_INFO(HEXAGON.A2_swiz,SI_ftype_SI,1) +// +def int_hexagon_A2_swiz : +Hexagon_si_si_Intrinsic<"HEXAGON_A2_swiz">; +// +// BUILTIN_INFO(HEXAGON.S2_vsathub_nopack,DI_ftype_DI,1) +// +def int_hexagon_S2_vsathub_nopack : +Hexagon_di_di_Intrinsic<"HEXAGON_S2_vsathub_nopack">; +// +// BUILTIN_INFO(HEXAGON.S2_vsathb_nopack,DI_ftype_DI,1) +// +def int_hexagon_S2_vsathb_nopack : +Hexagon_di_di_Intrinsic<"HEXAGON_S2_vsathb_nopack">; +// +// BUILTIN_INFO(HEXAGON.S2_vsatwh_nopack,DI_ftype_DI,1) +// +def int_hexagon_S2_vsatwh_nopack : +Hexagon_di_di_Intrinsic<"HEXAGON_S2_vsatwh_nopack">; +// +// BUILTIN_INFO(HEXAGON.S2_vsatwuh_nopack,DI_ftype_DI,1) +// +def int_hexagon_S2_vsatwuh_nopack : +Hexagon_di_di_Intrinsic<"HEXAGON_S2_vsatwuh_nopack">; +// +// BUILTIN_INFO(HEXAGON.S2_shuffob,DI_ftype_DIDI,2) +// +def int_hexagon_S2_shuffob : +Hexagon_di_didi_Intrinsic<"HEXAGON_S2_shuffob">; +// +// BUILTIN_INFO(HEXAGON.S2_shuffeb,DI_ftype_DIDI,2) +// +def int_hexagon_S2_shuffeb : +Hexagon_di_didi_Intrinsic<"HEXAGON_S2_shuffeb">; +// +// BUILTIN_INFO(HEXAGON.S2_shuffoh,DI_ftype_DIDI,2) +// +def int_hexagon_S2_shuffoh : +Hexagon_di_didi_Intrinsic<"HEXAGON_S2_shuffoh">; +// +// BUILTIN_INFO(HEXAGON.S2_shuffeh,DI_ftype_DIDI,2) +// +def int_hexagon_S2_shuffeh : +Hexagon_di_didi_Intrinsic<"HEXAGON_S2_shuffeh">; +// +// BUILTIN_INFO(HEXAGON.S5_popcountp,SI_ftype_DI,1) +// +def int_hexagon_S5_popcountp : +Hexagon_si_di_Intrinsic<"HEXAGON_S5_popcountp">; +// +// BUILTIN_INFO(HEXAGON.S4_parity,SI_ftype_SISI,2) +// +def int_hexagon_S4_parity : +Hexagon_si_sisi_Intrinsic<"HEXAGON_S4_parity">; +// +// BUILTIN_INFO(HEXAGON.S2_parityp,SI_ftype_DIDI,2) +// +def int_hexagon_S2_parityp : +Hexagon_si_didi_Intrinsic<"HEXAGON_S2_parityp">; +// +// BUILTIN_INFO(HEXAGON.S2_lfsp,DI_ftype_DIDI,2) +// +def int_hexagon_S2_lfsp : +Hexagon_di_didi_Intrinsic<"HEXAGON_S2_lfsp">; +// +// BUILTIN_INFO(HEXAGON.S2_clbnorm,SI_ftype_SI,1) +// +def int_hexagon_S2_clbnorm : +Hexagon_si_si_Intrinsic<"HEXAGON_S2_clbnorm">; +// +// BUILTIN_INFO(HEXAGON.S4_clbaddi,SI_ftype_SISI,2) +// +def int_hexagon_S4_clbaddi : +Hexagon_si_sisi_Intrinsic<"HEXAGON_S4_clbaddi">; +// +// BUILTIN_INFO(HEXAGON.S4_clbpnorm,SI_ftype_DI,1) +// +def int_hexagon_S4_clbpnorm : +Hexagon_si_di_Intrinsic<"HEXAGON_S4_clbpnorm">; +// +// BUILTIN_INFO(HEXAGON.S4_clbpaddi,SI_ftype_DISI,2) +// +def int_hexagon_S4_clbpaddi : +Hexagon_si_disi_Intrinsic<"HEXAGON_S4_clbpaddi">; +// +// BUILTIN_INFO(HEXAGON.S2_clb,SI_ftype_SI,1) +// +def int_hexagon_S2_clb : +Hexagon_si_si_Intrinsic<"HEXAGON_S2_clb">; +// +// BUILTIN_INFO(HEXAGON.S2_cl0,SI_ftype_SI,1) +// +def int_hexagon_S2_cl0 : +Hexagon_si_si_Intrinsic<"HEXAGON_S2_cl0">; +// +// BUILTIN_INFO(HEXAGON.S2_cl1,SI_ftype_SI,1) +// +def int_hexagon_S2_cl1 : +Hexagon_si_si_Intrinsic<"HEXAGON_S2_cl1">; +// +// BUILTIN_INFO(HEXAGON.S2_clbp,SI_ftype_DI,1) +// +def int_hexagon_S2_clbp : +Hexagon_si_di_Intrinsic<"HEXAGON_S2_clbp">; +// +// BUILTIN_INFO(HEXAGON.S2_cl0p,SI_ftype_DI,1) +// +def int_hexagon_S2_cl0p : +Hexagon_si_di_Intrinsic<"HEXAGON_S2_cl0p">; +// +// BUILTIN_INFO(HEXAGON.S2_cl1p,SI_ftype_DI,1) +// +def int_hexagon_S2_cl1p : +Hexagon_si_di_Intrinsic<"HEXAGON_S2_cl1p">; +// +// BUILTIN_INFO(HEXAGON.S2_brev,SI_ftype_SI,1) +// +def int_hexagon_S2_brev : +Hexagon_si_si_Intrinsic<"HEXAGON_S2_brev">; +// +// BUILTIN_INFO(HEXAGON.S2_brevp,DI_ftype_DI,1) +// +def int_hexagon_S2_brevp : +Hexagon_di_di_Intrinsic<"HEXAGON_S2_brevp">; +// +// BUILTIN_INFO(HEXAGON.S2_ct0,SI_ftype_SI,1) +// +def int_hexagon_S2_ct0 : +Hexagon_si_si_Intrinsic<"HEXAGON_S2_ct0">; +// +// BUILTIN_INFO(HEXAGON.S2_ct1,SI_ftype_SI,1) +// +def int_hexagon_S2_ct1 : +Hexagon_si_si_Intrinsic<"HEXAGON_S2_ct1">; +// +// BUILTIN_INFO(HEXAGON.S2_ct0p,SI_ftype_DI,1) +// +def int_hexagon_S2_ct0p : +Hexagon_si_di_Intrinsic<"HEXAGON_S2_ct0p">; +// +// BUILTIN_INFO(HEXAGON.S2_ct1p,SI_ftype_DI,1) +// +def int_hexagon_S2_ct1p : +Hexagon_si_di_Intrinsic<"HEXAGON_S2_ct1p">; +// +// BUILTIN_INFO(HEXAGON.S2_interleave,DI_ftype_DI,1) +// +def int_hexagon_S2_interleave : +Hexagon_di_di_Intrinsic<"HEXAGON_S2_interleave">; +// +// BUILTIN_INFO(HEXAGON.S2_deinterleave,DI_ftype_DI,1) +// +def int_hexagon_S2_deinterleave : +Hexagon_di_di_Intrinsic<"HEXAGON_S2_deinterleave">; diff --git a/include/llvm/IR/IntrinsicsMips.td b/include/llvm/IR/IntrinsicsMips.td new file mode 100644 index 0000000..e40e162 --- /dev/null +++ b/include/llvm/IR/IntrinsicsMips.td @@ -0,0 +1,389 @@ +//===- IntrinsicsMips.td - Defines Mips intrinsics ---------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the MIPS-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// MIPS DSP data types +def mips_v2q15_ty: LLVMType<v2i16>; +def mips_v4q7_ty: LLVMType<v4i8>; +def mips_q31_ty: LLVMType<i32>; + +let TargetPrefix = "mips" in { // All intrinsics start with "llvm.mips.". + +//===----------------------------------------------------------------------===// +// MIPS DSP Rev 1 + +//===----------------------------------------------------------------------===// +// Addition/subtraction + +def int_mips_addu_qb : GCCBuiltin<"__builtin_mips_addu_qb">, + Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_v4i8_ty], [Commutative]>; +def int_mips_addu_s_qb : GCCBuiltin<"__builtin_mips_addu_s_qb">, + Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_v4i8_ty], [Commutative]>; +def int_mips_subu_qb : GCCBuiltin<"__builtin_mips_subu_qb">, + Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_v4i8_ty], []>; +def int_mips_subu_s_qb : GCCBuiltin<"__builtin_mips_subu_s_qb">, + Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_v4i8_ty], []>; + +def int_mips_addq_ph : GCCBuiltin<"__builtin_mips_addq_ph">, + Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, mips_v2q15_ty], [Commutative]>; +def int_mips_addq_s_ph : GCCBuiltin<"__builtin_mips_addq_s_ph">, + Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, mips_v2q15_ty], [Commutative]>; +def int_mips_subq_ph : GCCBuiltin<"__builtin_mips_subq_ph">, + Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, mips_v2q15_ty], []>; +def int_mips_subq_s_ph : GCCBuiltin<"__builtin_mips_subq_s_ph">, + Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, mips_v2q15_ty], []>; + +def int_mips_madd: GCCBuiltin<"__builtin_mips_madd">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, Commutative]>; +def int_mips_maddu: GCCBuiltin<"__builtin_mips_maddu">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, Commutative]>; + +def int_mips_msub: GCCBuiltin<"__builtin_mips_msub">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_mips_msubu: GCCBuiltin<"__builtin_mips_msubu">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + +def int_mips_addq_s_w: GCCBuiltin<"__builtin_mips_addq_s_w">, + Intrinsic<[mips_q31_ty], [mips_q31_ty, mips_q31_ty], [Commutative]>; +def int_mips_subq_s_w: GCCBuiltin<"__builtin_mips_subq_s_w">, + Intrinsic<[mips_q31_ty], [mips_q31_ty, mips_q31_ty], []>; + +def int_mips_addsc: GCCBuiltin<"__builtin_mips_addsc">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [Commutative]>; +def int_mips_addwc: GCCBuiltin<"__builtin_mips_addwc">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [Commutative]>; + +def int_mips_modsub: GCCBuiltin<"__builtin_mips_modsub">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_raddu_w_qb: GCCBuiltin<"__builtin_mips_raddu_w_qb">, + Intrinsic<[llvm_i32_ty], [llvm_v4i8_ty], [IntrNoMem]>; + +//===----------------------------------------------------------------------===// +// Absolute value + +def int_mips_absq_s_ph: GCCBuiltin<"__builtin_mips_absq_s_ph">, + Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty], []>; +def int_mips_absq_s_w: GCCBuiltin<"__builtin_mips_absq_s_w">, + Intrinsic<[mips_q31_ty], [mips_q31_ty], []>; + +//===----------------------------------------------------------------------===// +// Precision reduce/expand + +def int_mips_precrq_qb_ph: GCCBuiltin<"__builtin_mips_precrq_qb_ph">, + Intrinsic<[llvm_v4i8_ty], [mips_v2q15_ty, mips_v2q15_ty], [IntrNoMem]>; +def int_mips_precrqu_s_qb_ph: GCCBuiltin<"__builtin_mips_precrqu_s_qb_ph">, + Intrinsic<[llvm_v4i8_ty], [mips_v2q15_ty, mips_v2q15_ty], []>; +def int_mips_precrq_ph_w: GCCBuiltin<"__builtin_mips_precrq_ph_w">, + Intrinsic<[mips_v2q15_ty], [mips_q31_ty, mips_q31_ty], [IntrNoMem]>; +def int_mips_precrq_rs_ph_w: GCCBuiltin<"__builtin_mips_precrq_rs_ph_w">, + Intrinsic<[mips_v2q15_ty], [mips_q31_ty, mips_q31_ty], []>; +def int_mips_preceq_w_phl: GCCBuiltin<"__builtin_mips_preceq_w_phl">, + Intrinsic<[mips_q31_ty], [mips_v2q15_ty], [IntrNoMem]>; +def int_mips_preceq_w_phr: GCCBuiltin<"__builtin_mips_preceq_w_phr">, + Intrinsic<[mips_q31_ty], [mips_v2q15_ty], [IntrNoMem]>; +def int_mips_precequ_ph_qbl: GCCBuiltin<"__builtin_mips_precequ_ph_qbl">, + Intrinsic<[mips_v2q15_ty], [llvm_v4i8_ty], [IntrNoMem]>; +def int_mips_precequ_ph_qbr: GCCBuiltin<"__builtin_mips_precequ_ph_qbr">, + Intrinsic<[mips_v2q15_ty], [llvm_v4i8_ty], [IntrNoMem]>; +def int_mips_precequ_ph_qbla: GCCBuiltin<"__builtin_mips_precequ_ph_qbla">, + Intrinsic<[mips_v2q15_ty], [llvm_v4i8_ty], [IntrNoMem]>; +def int_mips_precequ_ph_qbra: GCCBuiltin<"__builtin_mips_precequ_ph_qbra">, + Intrinsic<[mips_v2q15_ty], [llvm_v4i8_ty], [IntrNoMem]>; +def int_mips_preceu_ph_qbl: GCCBuiltin<"__builtin_mips_preceu_ph_qbl">, + Intrinsic<[mips_v2q15_ty], [llvm_v4i8_ty], [IntrNoMem]>; +def int_mips_preceu_ph_qbr: GCCBuiltin<"__builtin_mips_preceu_ph_qbr">, + Intrinsic<[mips_v2q15_ty], [llvm_v4i8_ty], [IntrNoMem]>; +def int_mips_preceu_ph_qbla: GCCBuiltin<"__builtin_mips_preceu_ph_qbla">, + Intrinsic<[mips_v2q15_ty], [llvm_v4i8_ty], [IntrNoMem]>; +def int_mips_preceu_ph_qbra: GCCBuiltin<"__builtin_mips_preceu_ph_qbra">, + Intrinsic<[mips_v2q15_ty], [llvm_v4i8_ty], [IntrNoMem]>; + +//===----------------------------------------------------------------------===// +// Shift + +def int_mips_shll_qb: GCCBuiltin<"__builtin_mips_shll_qb">, + Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_i32_ty], []>; +def int_mips_shrl_qb: GCCBuiltin<"__builtin_mips_shrl_qb">, + Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_shll_ph: GCCBuiltin<"__builtin_mips_shll_ph">, + Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, llvm_i32_ty], []>; +def int_mips_shll_s_ph: GCCBuiltin<"__builtin_mips_shll_s_ph">, + Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, llvm_i32_ty], []>; +def int_mips_shra_ph: GCCBuiltin<"__builtin_mips_shra_ph">, + Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_shra_r_ph: GCCBuiltin<"__builtin_mips_shra_r_ph">, + Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_shll_s_w: GCCBuiltin<"__builtin_mips_shll_s_w">, + Intrinsic<[mips_q31_ty], [mips_q31_ty, llvm_i32_ty], []>; +def int_mips_shra_r_w: GCCBuiltin<"__builtin_mips_shra_r_w">, + Intrinsic<[mips_q31_ty], [mips_q31_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_shilo: GCCBuiltin<"__builtin_mips_shilo">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty], [IntrNoMem]>; + +//===----------------------------------------------------------------------===// +// Multiplication + +def int_mips_muleu_s_ph_qbl: GCCBuiltin<"__builtin_mips_muleu_s_ph_qbl">, + Intrinsic<[mips_v2q15_ty], [llvm_v4i8_ty, mips_v2q15_ty], []>; +def int_mips_muleu_s_ph_qbr: GCCBuiltin<"__builtin_mips_muleu_s_ph_qbr">, + Intrinsic<[mips_v2q15_ty], [llvm_v4i8_ty, mips_v2q15_ty], []>; +def int_mips_mulq_rs_ph: GCCBuiltin<"__builtin_mips_mulq_rs_ph">, + Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, mips_v2q15_ty], [Commutative]>; +def int_mips_muleq_s_w_phl: GCCBuiltin<"__builtin_mips_muleq_s_w_phl">, + Intrinsic<[mips_q31_ty], [mips_v2q15_ty, mips_v2q15_ty], [Commutative]>; +def int_mips_muleq_s_w_phr: GCCBuiltin<"__builtin_mips_muleq_s_w_phr">, + Intrinsic<[mips_q31_ty], [mips_v2q15_ty, mips_v2q15_ty], [Commutative]>; +def int_mips_mulsaq_s_w_ph: GCCBuiltin<"__builtin_mips_mulsaq_s_w_ph">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, mips_v2q15_ty, mips_v2q15_ty], []>; +def int_mips_maq_s_w_phl: GCCBuiltin<"__builtin_mips_maq_s_w_phl">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, mips_v2q15_ty, mips_v2q15_ty], []>; +def int_mips_maq_s_w_phr: GCCBuiltin<"__builtin_mips_maq_s_w_phr">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, mips_v2q15_ty, mips_v2q15_ty], []>; +def int_mips_maq_sa_w_phl: GCCBuiltin<"__builtin_mips_maq_sa_w_phl">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, mips_v2q15_ty, mips_v2q15_ty], []>; +def int_mips_maq_sa_w_phr: GCCBuiltin<"__builtin_mips_maq_sa_w_phr">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, mips_v2q15_ty, mips_v2q15_ty], []>; +def int_mips_mult: GCCBuiltin<"__builtin_mips_mult">, + Intrinsic<[llvm_i64_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, Commutative]>; +def int_mips_multu: GCCBuiltin<"__builtin_mips_multu">, + Intrinsic<[llvm_i64_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, Commutative]>; + +//===----------------------------------------------------------------------===// +// Dot product with accumulate/subtract + +def int_mips_dpau_h_qbl: GCCBuiltin<"__builtin_mips_dpau_h_qbl">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_v4i8_ty, llvm_v4i8_ty], + [IntrNoMem]>; +def int_mips_dpau_h_qbr: GCCBuiltin<"__builtin_mips_dpau_h_qbr">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_v4i8_ty, llvm_v4i8_ty], + [IntrNoMem]>; +def int_mips_dpsu_h_qbl: GCCBuiltin<"__builtin_mips_dpsu_h_qbl">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_v4i8_ty, llvm_v4i8_ty], + [IntrNoMem]>; +def int_mips_dpsu_h_qbr: GCCBuiltin<"__builtin_mips_dpsu_h_qbr">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_v4i8_ty, llvm_v4i8_ty], + [IntrNoMem]>; +def int_mips_dpaq_s_w_ph: GCCBuiltin<"__builtin_mips_dpaq_s_w_ph">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, mips_v2q15_ty, mips_v2q15_ty], []>; +def int_mips_dpsq_s_w_ph: GCCBuiltin<"__builtin_mips_dpsq_s_w_ph">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, mips_v2q15_ty, mips_v2q15_ty], []>; +def int_mips_dpaq_sa_l_w: GCCBuiltin<"__builtin_mips_dpaq_sa_l_w">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, mips_q31_ty, mips_q31_ty], []>; +def int_mips_dpsq_sa_l_w: GCCBuiltin<"__builtin_mips_dpsq_sa_l_w">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, mips_q31_ty, mips_q31_ty], []>; + +//===----------------------------------------------------------------------===// +// Comparison + +def int_mips_cmpu_eq_qb: GCCBuiltin<"__builtin_mips_cmpu_eq_qb">, + Intrinsic<[], [llvm_v4i8_ty, llvm_v4i8_ty], [Commutative]>; +def int_mips_cmpu_lt_qb: GCCBuiltin<"__builtin_mips_cmpu_lt_qb">, + Intrinsic<[], [llvm_v4i8_ty, llvm_v4i8_ty], [Commutative]>; +def int_mips_cmpu_le_qb: GCCBuiltin<"__builtin_mips_cmpu_le_qb">, + Intrinsic<[], [llvm_v4i8_ty, llvm_v4i8_ty], [Commutative]>; +def int_mips_cmpgu_eq_qb: GCCBuiltin<"__builtin_mips_cmpgu_eq_qb">, + Intrinsic<[llvm_i32_ty], [llvm_v4i8_ty, llvm_v4i8_ty], [Commutative]>; +def int_mips_cmpgu_lt_qb: GCCBuiltin<"__builtin_mips_cmpgu_lt_qb">, + Intrinsic<[llvm_i32_ty], [llvm_v4i8_ty, llvm_v4i8_ty], [Commutative]>; +def int_mips_cmpgu_le_qb: GCCBuiltin<"__builtin_mips_cmpgu_le_qb">, + Intrinsic<[llvm_i32_ty], [llvm_v4i8_ty, llvm_v4i8_ty], [Commutative]>; +def int_mips_cmp_eq_ph: GCCBuiltin<"__builtin_mips_cmp_eq_ph">, + Intrinsic<[], [mips_v2q15_ty, mips_v2q15_ty], [Commutative]>; +def int_mips_cmp_lt_ph: GCCBuiltin<"__builtin_mips_cmp_lt_ph">, + Intrinsic<[], [mips_v2q15_ty, mips_v2q15_ty], [Commutative]>; +def int_mips_cmp_le_ph: GCCBuiltin<"__builtin_mips_cmp_le_ph">, + Intrinsic<[], [mips_v2q15_ty, mips_v2q15_ty], [Commutative]>; + +//===----------------------------------------------------------------------===// +// Extracting + +def int_mips_extr_s_h: GCCBuiltin<"__builtin_mips_extr_s_h">, + Intrinsic<[llvm_i32_ty], [llvm_i64_ty, llvm_i32_ty], []>; +def int_mips_extr_w: GCCBuiltin<"__builtin_mips_extr_w">, + Intrinsic<[llvm_i32_ty], [llvm_i64_ty, llvm_i32_ty], []>; +def int_mips_extr_rs_w: GCCBuiltin<"__builtin_mips_extr_rs_w">, + Intrinsic<[llvm_i32_ty], [llvm_i64_ty, llvm_i32_ty], []>; +def int_mips_extr_r_w: GCCBuiltin<"__builtin_mips_extr_r_w">, + Intrinsic<[llvm_i32_ty], [llvm_i64_ty, llvm_i32_ty], []>; +def int_mips_extp: GCCBuiltin<"__builtin_mips_extp">, + Intrinsic<[llvm_i32_ty], [llvm_i64_ty, llvm_i32_ty], []>; +def int_mips_extpdp: GCCBuiltin<"__builtin_mips_extpdp">, + Intrinsic<[llvm_i32_ty], [llvm_i64_ty, llvm_i32_ty], []>; + +//===----------------------------------------------------------------------===// +// Misc + +def int_mips_wrdsp: GCCBuiltin<"__builtin_mips_wrdsp">, + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], []>; +def int_mips_rddsp: GCCBuiltin<"__builtin_mips_rddsp">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrReadMem]>; + +def int_mips_insv: GCCBuiltin<"__builtin_mips_insv">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrReadMem]>; +def int_mips_bitrev: GCCBuiltin<"__builtin_mips_bitrev">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>; + +def int_mips_packrl_ph: GCCBuiltin<"__builtin_mips_packrl_ph">, + Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, mips_v2q15_ty], [IntrNoMem]>; + +def int_mips_repl_qb: GCCBuiltin<"__builtin_mips_repl_qb">, + Intrinsic<[llvm_v4i8_ty], [llvm_i32_ty], [IntrNoMem]>; +def int_mips_repl_ph: GCCBuiltin<"__builtin_mips_repl_ph">, + Intrinsic<[mips_v2q15_ty], [llvm_i32_ty], [IntrNoMem]>; + +def int_mips_pick_qb: GCCBuiltin<"__builtin_mips_pick_qb">, + Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_v4i8_ty], [IntrReadMem]>; +def int_mips_pick_ph: GCCBuiltin<"__builtin_mips_pick_ph">, + Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, mips_v2q15_ty], [IntrReadMem]>; + +def int_mips_mthlip: GCCBuiltin<"__builtin_mips_mthlip">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty], []>; + +def int_mips_bposge32: GCCBuiltin<"__builtin_mips_bposge32">, + Intrinsic<[llvm_i32_ty], [], [IntrReadMem]>; + +def int_mips_lbux: GCCBuiltin<"__builtin_mips_lbux">, + Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrReadArgMem]>; +def int_mips_lhx: GCCBuiltin<"__builtin_mips_lhx">, + Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrReadArgMem]>; +def int_mips_lwx: GCCBuiltin<"__builtin_mips_lwx">, + Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrReadArgMem]>; + +//===----------------------------------------------------------------------===// +// MIPS DSP Rev 2 + +def int_mips_absq_s_qb: GCCBuiltin<"__builtin_mips_absq_s_qb">, + Intrinsic<[mips_v4q7_ty], [mips_v4q7_ty], []>; + +def int_mips_addqh_ph: GCCBuiltin<"__builtin_mips_addqh_ph">, + Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, mips_v2q15_ty], + [IntrNoMem, Commutative]>; +def int_mips_addqh_r_ph: GCCBuiltin<"__builtin_mips_addqh_r_ph">, + Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, mips_v2q15_ty], + [IntrNoMem, Commutative]>; +def int_mips_addqh_w: GCCBuiltin<"__builtin_mips_addqh_w">, + Intrinsic<[mips_q31_ty], [mips_q31_ty, mips_q31_ty], + [IntrNoMem, Commutative]>; +def int_mips_addqh_r_w: GCCBuiltin<"__builtin_mips_addqh_r_w">, + Intrinsic<[mips_q31_ty], [mips_q31_ty, mips_q31_ty], + [IntrNoMem, Commutative]>; + +def int_mips_addu_ph: GCCBuiltin<"__builtin_mips_addu_ph">, + Intrinsic<[llvm_v2i16_ty], [llvm_v2i16_ty, llvm_v2i16_ty], [Commutative]>; +def int_mips_addu_s_ph: GCCBuiltin<"__builtin_mips_addu_s_ph">, + Intrinsic<[llvm_v2i16_ty], [llvm_v2i16_ty, llvm_v2i16_ty], [Commutative]>; + +def int_mips_adduh_qb: GCCBuiltin<"__builtin_mips_adduh_qb">, + Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_v4i8_ty], + [IntrNoMem, Commutative]>; +def int_mips_adduh_r_qb: GCCBuiltin<"__builtin_mips_adduh_r_qb">, + Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_v4i8_ty], + [IntrNoMem, Commutative]>; + +def int_mips_append: GCCBuiltin<"__builtin_mips_append">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_mips_balign: GCCBuiltin<"__builtin_mips_balign">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + +def int_mips_cmpgdu_eq_qb: GCCBuiltin<"__builtin_mips_cmpgdu_eq_qb">, + Intrinsic<[llvm_i32_ty], [llvm_v4i8_ty, llvm_v4i8_ty], [Commutative]>; +def int_mips_cmpgdu_lt_qb: GCCBuiltin<"__builtin_mips_cmpgdu_lt_qb">, + Intrinsic<[llvm_i32_ty], [llvm_v4i8_ty, llvm_v4i8_ty], [Commutative]>; +def int_mips_cmpgdu_le_qb: GCCBuiltin<"__builtin_mips_cmpgdu_le_qb">, + Intrinsic<[llvm_i32_ty], [llvm_v4i8_ty, llvm_v4i8_ty], [Commutative]>; + +def int_mips_dpa_w_ph: GCCBuiltin<"__builtin_mips_dpa_w_ph">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_v2i16_ty, llvm_v2i16_ty], + [IntrNoMem]>; +def int_mips_dps_w_ph: GCCBuiltin<"__builtin_mips_dps_w_ph">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_v2i16_ty, llvm_v2i16_ty], + [IntrNoMem]>; + +def int_mips_dpaqx_s_w_ph: GCCBuiltin<"__builtin_mips_dpaqx_s_w_ph">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, mips_v2q15_ty, mips_v2q15_ty], []>; +def int_mips_dpaqx_sa_w_ph: GCCBuiltin<"__builtin_mips_dpaqx_sa_w_ph">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, mips_v2q15_ty, mips_v2q15_ty], []>; +def int_mips_dpax_w_ph: GCCBuiltin<"__builtin_mips_dpax_w_ph">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_v2i16_ty, llvm_v2i16_ty], + [IntrNoMem]>; +def int_mips_dpsx_w_ph: GCCBuiltin<"__builtin_mips_dpsx_w_ph">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_v2i16_ty, llvm_v2i16_ty], + [IntrNoMem]>; +def int_mips_dpsqx_s_w_ph: GCCBuiltin<"__builtin_mips_dpsqx_s_w_ph">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, mips_v2q15_ty, mips_v2q15_ty], []>; +def int_mips_dpsqx_sa_w_ph: GCCBuiltin<"__builtin_mips_dpsqx_sa_w_ph">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, mips_v2q15_ty, mips_v2q15_ty], []>; + +def int_mips_mul_ph: GCCBuiltin<"__builtin_mips_mul_ph">, + Intrinsic<[llvm_v2i16_ty], [llvm_v2i16_ty, llvm_v2i16_ty], [Commutative]>; +def int_mips_mul_s_ph: GCCBuiltin<"__builtin_mips_mul_s_ph">, + Intrinsic<[llvm_v2i16_ty], [llvm_v2i16_ty, llvm_v2i16_ty], [Commutative]>; + +def int_mips_mulq_rs_w: GCCBuiltin<"__builtin_mips_mulq_rs_w">, + Intrinsic<[mips_q31_ty], [mips_q31_ty, mips_q31_ty], [Commutative]>; +def int_mips_mulq_s_ph: GCCBuiltin<"__builtin_mips_mulq_s_ph">, + Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, mips_v2q15_ty], [Commutative]>; +def int_mips_mulq_s_w: GCCBuiltin<"__builtin_mips_mulq_s_w">, + Intrinsic<[mips_q31_ty], [mips_q31_ty, mips_q31_ty], [Commutative]>; +def int_mips_mulsa_w_ph: GCCBuiltin<"__builtin_mips_mulsa_w_ph">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_v2i16_ty, llvm_v2i16_ty], + [IntrNoMem]>; + +def int_mips_precr_qb_ph: GCCBuiltin<"__builtin_mips_precr_qb_ph">, + Intrinsic<[llvm_v4i8_ty], [llvm_v2i16_ty, llvm_v2i16_ty], []>; +def int_mips_precr_sra_ph_w: GCCBuiltin<"__builtin_mips_precr_sra_ph_w">, + Intrinsic<[llvm_v2i16_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_mips_precr_sra_r_ph_w: GCCBuiltin<"__builtin_mips_precr_sra_r_ph_w">, + Intrinsic<[llvm_v2i16_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + +def int_mips_prepend: GCCBuiltin<"__builtin_mips_prepend">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + +def int_mips_shra_qb: GCCBuiltin<"__builtin_mips_shra_qb">, + Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_shra_r_qb: GCCBuiltin<"__builtin_mips_shra_r_qb">, + Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_shrl_ph: GCCBuiltin<"__builtin_mips_shrl_ph">, + Intrinsic<[llvm_v2i16_ty], [llvm_v2i16_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_subqh_ph: GCCBuiltin<"__builtin_mips_subqh_ph">, + Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, mips_v2q15_ty], [IntrNoMem]>; +def int_mips_subqh_r_ph: GCCBuiltin<"__builtin_mips_subqh_r_ph">, + Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, mips_v2q15_ty], [IntrNoMem]>; +def int_mips_subqh_w: GCCBuiltin<"__builtin_mips_subqh_w">, + Intrinsic<[mips_q31_ty], [mips_q31_ty, mips_q31_ty], [IntrNoMem]>; +def int_mips_subqh_r_w: GCCBuiltin<"__builtin_mips_subqh_r_w">, + Intrinsic<[mips_q31_ty], [mips_q31_ty, mips_q31_ty], [IntrNoMem]>; + +def int_mips_subu_ph: GCCBuiltin<"__builtin_mips_subu_ph">, + Intrinsic<[llvm_v2i16_ty], [llvm_v2i16_ty, llvm_v2i16_ty], []>; +def int_mips_subu_s_ph: GCCBuiltin<"__builtin_mips_subu_s_ph">, + Intrinsic<[llvm_v2i16_ty], [llvm_v2i16_ty, llvm_v2i16_ty], []>; + +def int_mips_subuh_qb: GCCBuiltin<"__builtin_mips_subuh_qb">, + Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_v4i8_ty], [IntrNoMem]>; +def int_mips_subuh_r_qb: GCCBuiltin<"__builtin_mips_subuh_r_qb">, + Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_v4i8_ty], [IntrNoMem]>; +} diff --git a/include/llvm/IR/IntrinsicsNVVM.td b/include/llvm/IR/IntrinsicsNVVM.td new file mode 100644 index 0000000..ebfd03e --- /dev/null +++ b/include/llvm/IR/IntrinsicsNVVM.td @@ -0,0 +1,962 @@ +//===- IntrinsicsNVVM.td - Defines NVVM intrinsics ---------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the NVVM-specific intrinsics for use with NVPTX. +// +//===----------------------------------------------------------------------===// + +def llvm_anyi64ptr_ty : LLVMAnyPointerType<llvm_i64_ty>; // (space)i64* + +// +// MISC +// + + def int_nvvm_clz_i : GCCBuiltin<"__nvvm_clz_i">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>; + def int_nvvm_clz_ll : GCCBuiltin<"__nvvm_clz_ll">, + Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem]>; + + def int_nvvm_popc_i : GCCBuiltin<"__nvvm_popc_i">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>; + def int_nvvm_popc_ll : GCCBuiltin<"__nvvm_popc_ll">, + Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem]>; + + def int_nvvm_prmt : GCCBuiltin<"__nvvm_prmt">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, Commutative]>; + +// +// Min Max +// + + def int_nvvm_min_i : GCCBuiltin<"__nvvm_min_i">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_min_ui : GCCBuiltin<"__nvvm_min_ui">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, Commutative]>; + + def int_nvvm_min_ll : GCCBuiltin<"__nvvm_min_ll">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_min_ull : GCCBuiltin<"__nvvm_min_ull">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], + [IntrNoMem, Commutative]>; + + def int_nvvm_max_i : GCCBuiltin<"__nvvm_max_i">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_max_ui : GCCBuiltin<"__nvvm_max_ui">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, Commutative]>; + + def int_nvvm_max_ll : GCCBuiltin<"__nvvm_max_ll">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_max_ull : GCCBuiltin<"__nvvm_max_ull">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], + [IntrNoMem, Commutative]>; + + def int_nvvm_fmin_f : GCCBuiltin<"__nvvm_fmin_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_fmin_ftz_f : GCCBuiltin<"__nvvm_fmin_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + + def int_nvvm_fmax_f : GCCBuiltin<"__nvvm_fmax_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty] + , [IntrNoMem, Commutative]>; + def int_nvvm_fmax_ftz_f : GCCBuiltin<"__nvvm_fmax_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + + def int_nvvm_fmin_d : GCCBuiltin<"__nvvm_fmin_d">, + Intrinsic<[llvm_double_ty], [llvm_double_ty, llvm_double_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_fmax_d : GCCBuiltin<"__nvvm_fmax_d">, + Intrinsic<[llvm_double_ty], [llvm_double_ty, llvm_double_ty], + [IntrNoMem, Commutative]>; + +// +// Multiplication +// + + def int_nvvm_mulhi_i : GCCBuiltin<"__nvvm_mulhi_i">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_mulhi_ui : GCCBuiltin<"__nvvm_mulhi_ui">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, Commutative]>; + + def int_nvvm_mulhi_ll : GCCBuiltin<"__nvvm_mulhi_ll">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_mulhi_ull : GCCBuiltin<"__nvvm_mulhi_ull">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], + [IntrNoMem, Commutative]>; + + def int_nvvm_mul_rn_ftz_f : GCCBuiltin<"__nvvm_mul_rn_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_mul_rn_f : GCCBuiltin<"__nvvm_mul_rn_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_mul_rz_ftz_f : GCCBuiltin<"__nvvm_mul_rz_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_mul_rz_f : GCCBuiltin<"__nvvm_mul_rz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_mul_rm_ftz_f : GCCBuiltin<"__nvvm_mul_rm_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_mul_rm_f : GCCBuiltin<"__nvvm_mul_rm_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_mul_rp_ftz_f : GCCBuiltin<"__nvvm_mul_rp_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_mul_rp_f : GCCBuiltin<"__nvvm_mul_rp_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + + def int_nvvm_mul_rn_d : GCCBuiltin<"__nvvm_mul_rn_d">, + Intrinsic<[llvm_double_ty], [llvm_double_ty, llvm_double_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_mul_rz_d : GCCBuiltin<"__nvvm_mul_rz_d">, + Intrinsic<[llvm_double_ty], [llvm_double_ty, llvm_double_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_mul_rm_d : GCCBuiltin<"__nvvm_mul_rm_d">, + Intrinsic<[llvm_double_ty], [llvm_double_ty, llvm_double_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_mul_rp_d : GCCBuiltin<"__nvvm_mul_rp_d">, + Intrinsic<[llvm_double_ty], [llvm_double_ty, llvm_double_ty], + [IntrNoMem, Commutative]>; + + def int_nvvm_mul24_i : GCCBuiltin<"__nvvm_mul24_i">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_mul24_ui : GCCBuiltin<"__nvvm_mul24_ui">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, Commutative]>; + +// +// Div +// + + def int_nvvm_div_approx_ftz_f : GCCBuiltin<"__nvvm_div_approx_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_div_approx_f : GCCBuiltin<"__nvvm_div_approx_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + + def int_nvvm_div_rn_ftz_f : GCCBuiltin<"__nvvm_div_rn_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_div_rn_f : GCCBuiltin<"__nvvm_div_rn_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + + def int_nvvm_div_rz_ftz_f : GCCBuiltin<"__nvvm_div_rz_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_div_rz_f : GCCBuiltin<"__nvvm_div_rz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + + def int_nvvm_div_rm_ftz_f : GCCBuiltin<"__nvvm_div_rm_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_div_rm_f : GCCBuiltin<"__nvvm_div_rm_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + + def int_nvvm_div_rp_ftz_f : GCCBuiltin<"__nvvm_div_rp_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_div_rp_f : GCCBuiltin<"__nvvm_div_rp_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + + def int_nvvm_div_rn_d : GCCBuiltin<"__nvvm_div_rn_d">, + Intrinsic<[llvm_double_ty], [llvm_double_ty, llvm_double_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_div_rz_d : GCCBuiltin<"__nvvm_div_rz_d">, + Intrinsic<[llvm_double_ty], [llvm_double_ty, llvm_double_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_div_rm_d : GCCBuiltin<"__nvvm_div_rm_d">, + Intrinsic<[llvm_double_ty], [llvm_double_ty, llvm_double_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_div_rp_d : GCCBuiltin<"__nvvm_div_rp_d">, + Intrinsic<[llvm_double_ty], [llvm_double_ty, llvm_double_ty], + [IntrNoMem, Commutative]>; + +// +// Brev +// + + def int_nvvm_brev32 : GCCBuiltin<"__nvvm_brev32">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>; + def int_nvvm_brev64 : GCCBuiltin<"__nvvm_brev64">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty], [IntrNoMem]>; + +// +// Sad +// + + def int_nvvm_sad_i : GCCBuiltin<"__nvvm_sad_i">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_sad_ui : GCCBuiltin<"__nvvm_sad_ui">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, Commutative]>; + +// +// Floor Ceil +// + + def int_nvvm_floor_ftz_f : GCCBuiltin<"__nvvm_floor_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_floor_f : GCCBuiltin<"__nvvm_floor_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_floor_d : GCCBuiltin<"__nvvm_floor_d">, + Intrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; + + def int_nvvm_ceil_ftz_f : GCCBuiltin<"__nvvm_ceil_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_ceil_f : GCCBuiltin<"__nvvm_ceil_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_ceil_d : GCCBuiltin<"__nvvm_ceil_d">, + Intrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; + +// +// Abs +// + + def int_nvvm_abs_i : GCCBuiltin<"__nvvm_abs_i">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>; + def int_nvvm_abs_ll : GCCBuiltin<"__nvvm_abs_ll">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty], [IntrNoMem]>; + + def int_nvvm_fabs_ftz_f : GCCBuiltin<"__nvvm_fabs_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_fabs_f : GCCBuiltin<"__nvvm_fabs_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + + def int_nvvm_fabs_d : GCCBuiltin<"__nvvm_fabs_d">, + Intrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; + +// +// Round +// + + def int_nvvm_round_ftz_f : GCCBuiltin<"__nvvm_round_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_round_f : GCCBuiltin<"__nvvm_round_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + + def int_nvvm_round_d : GCCBuiltin<"__nvvm_round_d">, + Intrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; + +// +// Trunc +// + + def int_nvvm_trunc_ftz_f : GCCBuiltin<"__nvvm_trunc_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_trunc_f : GCCBuiltin<"__nvvm_trunc_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + + def int_nvvm_trunc_d : GCCBuiltin<"__nvvm_trunc_d">, + Intrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; + +// +// Saturate +// + + def int_nvvm_saturate_ftz_f : GCCBuiltin<"__nvvm_saturate_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_saturate_f : GCCBuiltin<"__nvvm_saturate_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + + def int_nvvm_saturate_d : GCCBuiltin<"__nvvm_saturate_d">, + Intrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; + +// +// Exp2 Log2 +// + + def int_nvvm_ex2_approx_ftz_f : GCCBuiltin<"__nvvm_ex2_approx_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_ex2_approx_f : GCCBuiltin<"__nvvm_ex2_approx_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_ex2_approx_d : GCCBuiltin<"__nvvm_ex2_approx_d">, + Intrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; + + def int_nvvm_lg2_approx_ftz_f : GCCBuiltin<"__nvvm_lg2_approx_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_lg2_approx_f : GCCBuiltin<"__nvvm_lg2_approx_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_lg2_approx_d : GCCBuiltin<"__nvvm_lg2_approx_d">, + Intrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; + +// +// Sin Cos +// + + def int_nvvm_sin_approx_ftz_f : GCCBuiltin<"__nvvm_sin_approx_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_sin_approx_f : GCCBuiltin<"__nvvm_sin_approx_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + + def int_nvvm_cos_approx_ftz_f : GCCBuiltin<"__nvvm_cos_approx_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_cos_approx_f : GCCBuiltin<"__nvvm_cos_approx_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + +// +// Fma +// + + def int_nvvm_fma_rn_ftz_f : GCCBuiltin<"__nvvm_fma_rn_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_fma_rn_f : GCCBuiltin<"__nvvm_fma_rn_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_fma_rz_ftz_f : GCCBuiltin<"__nvvm_fma_rz_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_fma_rz_f : GCCBuiltin<"__nvvm_fma_rz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_fma_rm_ftz_f : GCCBuiltin<"__nvvm_fma_rm_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_fma_rm_f : GCCBuiltin<"__nvvm_fma_rm_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_fma_rp_ftz_f : GCCBuiltin<"__nvvm_fma_rp_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_fma_rp_f : GCCBuiltin<"__nvvm_fma_rp_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + + def int_nvvm_fma_rn_d : GCCBuiltin<"__nvvm_fma_rn_d">, + Intrinsic<[llvm_double_ty], + [llvm_double_ty, llvm_double_ty, llvm_double_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_fma_rz_d : GCCBuiltin<"__nvvm_fma_rz_d">, + Intrinsic<[llvm_double_ty], + [llvm_double_ty, llvm_double_ty, llvm_double_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_fma_rm_d : GCCBuiltin<"__nvvm_fma_rm_d">, + Intrinsic<[llvm_double_ty], + [llvm_double_ty, llvm_double_ty, llvm_double_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_fma_rp_d : GCCBuiltin<"__nvvm_fma_rp_d">, + Intrinsic<[llvm_double_ty], + [llvm_double_ty, llvm_double_ty, llvm_double_ty], + [IntrNoMem, Commutative]>; + +// +// Rcp +// + + def int_nvvm_rcp_rn_ftz_f : GCCBuiltin<"__nvvm_rcp_rn_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_rcp_rn_f : GCCBuiltin<"__nvvm_rcp_rn_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_rcp_rz_ftz_f : GCCBuiltin<"__nvvm_rcp_rz_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_rcp_rz_f : GCCBuiltin<"__nvvm_rcp_rz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_rcp_rm_ftz_f : GCCBuiltin<"__nvvm_rcp_rm_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_rcp_rm_f : GCCBuiltin<"__nvvm_rcp_rm_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_rcp_rp_ftz_f : GCCBuiltin<"__nvvm_rcp_rp_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_rcp_rp_f : GCCBuiltin<"__nvvm_rcp_rp_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + + def int_nvvm_rcp_rn_d : GCCBuiltin<"__nvvm_rcp_rn_d">, + Intrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; + def int_nvvm_rcp_rz_d : GCCBuiltin<"__nvvm_rcp_rz_d">, + Intrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; + def int_nvvm_rcp_rm_d : GCCBuiltin<"__nvvm_rcp_rm_d">, + Intrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; + def int_nvvm_rcp_rp_d : GCCBuiltin<"__nvvm_rcp_rp_d">, + Intrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; + + def int_nvvm_rcp_approx_ftz_d : GCCBuiltin<"__nvvm_rcp_approx_ftz_d">, + Intrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; + +// +// Sqrt +// + + def int_nvvm_sqrt_rn_ftz_f : GCCBuiltin<"__nvvm_sqrt_rn_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_sqrt_rn_f : GCCBuiltin<"__nvvm_sqrt_rn_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_sqrt_rz_ftz_f : GCCBuiltin<"__nvvm_sqrt_rz_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_sqrt_rz_f : GCCBuiltin<"__nvvm_sqrt_rz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_sqrt_rm_ftz_f : GCCBuiltin<"__nvvm_sqrt_rm_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_sqrt_rm_f : GCCBuiltin<"__nvvm_sqrt_rm_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_sqrt_rp_ftz_f : GCCBuiltin<"__nvvm_sqrt_rp_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_sqrt_rp_f : GCCBuiltin<"__nvvm_sqrt_rp_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_sqrt_approx_ftz_f : GCCBuiltin<"__nvvm_sqrt_approx_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_sqrt_approx_f : GCCBuiltin<"__nvvm_sqrt_approx_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + + def int_nvvm_sqrt_rn_d : GCCBuiltin<"__nvvm_sqrt_rn_d">, + Intrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; + def int_nvvm_sqrt_rz_d : GCCBuiltin<"__nvvm_sqrt_rz_d">, + Intrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; + def int_nvvm_sqrt_rm_d : GCCBuiltin<"__nvvm_sqrt_rm_d">, + Intrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; + def int_nvvm_sqrt_rp_d : GCCBuiltin<"__nvvm_sqrt_rp_d">, + Intrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; + +// +// Rsqrt +// + + def int_nvvm_rsqrt_approx_ftz_f : GCCBuiltin<"__nvvm_rsqrt_approx_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_rsqrt_approx_f : GCCBuiltin<"__nvvm_rsqrt_approx_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_rsqrt_approx_d : GCCBuiltin<"__nvvm_rsqrt_approx_d">, + Intrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; + +// +// Add +// + + def int_nvvm_add_rn_ftz_f : GCCBuiltin<"__nvvm_add_rn_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_add_rn_f : GCCBuiltin<"__nvvm_add_rn_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_add_rz_ftz_f : GCCBuiltin<"__nvvm_add_rz_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_add_rz_f : GCCBuiltin<"__nvvm_add_rz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_add_rm_ftz_f : GCCBuiltin<"__nvvm_add_rm_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_add_rm_f : GCCBuiltin<"__nvvm_add_rm_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_add_rp_ftz_f : GCCBuiltin<"__nvvm_add_rp_ftz_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_add_rp_f : GCCBuiltin<"__nvvm_add_rp_f">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Commutative]>; + + def int_nvvm_add_rn_d : GCCBuiltin<"__nvvm_add_rn_d">, + Intrinsic<[llvm_double_ty], [llvm_double_ty, llvm_double_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_add_rz_d : GCCBuiltin<"__nvvm_add_rz_d">, + Intrinsic<[llvm_double_ty], [llvm_double_ty, llvm_double_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_add_rm_d : GCCBuiltin<"__nvvm_add_rm_d">, + Intrinsic<[llvm_double_ty], [llvm_double_ty, llvm_double_ty], + [IntrNoMem, Commutative]>; + def int_nvvm_add_rp_d : GCCBuiltin<"__nvvm_add_rp_d">, + Intrinsic<[llvm_double_ty], [llvm_double_ty, llvm_double_ty], + [IntrNoMem, Commutative]>; + +// +// Convert +// + + def int_nvvm_d2f_rn_ftz : GCCBuiltin<"__nvvm_d2f_rn_ftz">, + Intrinsic<[llvm_float_ty], [llvm_double_ty], [IntrNoMem]>; + def int_nvvm_d2f_rn : GCCBuiltin<"__nvvm_d2f_rn">, + Intrinsic<[llvm_float_ty], [llvm_double_ty], [IntrNoMem]>; + def int_nvvm_d2f_rz_ftz : GCCBuiltin<"__nvvm_d2f_rz_ftz">, + Intrinsic<[llvm_float_ty], [llvm_double_ty], [IntrNoMem]>; + def int_nvvm_d2f_rz : GCCBuiltin<"__nvvm_d2f_rz">, + Intrinsic<[llvm_float_ty], [llvm_double_ty], [IntrNoMem]>; + def int_nvvm_d2f_rm_ftz : GCCBuiltin<"__nvvm_d2f_rm_ftz">, + Intrinsic<[llvm_float_ty], [llvm_double_ty], [IntrNoMem]>; + def int_nvvm_d2f_rm : GCCBuiltin<"__nvvm_d2f_rm">, + Intrinsic<[llvm_float_ty], [llvm_double_ty], [IntrNoMem]>; + def int_nvvm_d2f_rp_ftz : GCCBuiltin<"__nvvm_d2f_rp_ftz">, + Intrinsic<[llvm_float_ty], [llvm_double_ty], [IntrNoMem]>; + def int_nvvm_d2f_rp : GCCBuiltin<"__nvvm_d2f_rp">, + Intrinsic<[llvm_float_ty], [llvm_double_ty], [IntrNoMem]>; + + def int_nvvm_d2i_rn : GCCBuiltin<"__nvvm_d2i_rn">, + Intrinsic<[llvm_i32_ty], [llvm_double_ty], [IntrNoMem]>; + def int_nvvm_d2i_rz : GCCBuiltin<"__nvvm_d2i_rz">, + Intrinsic<[llvm_i32_ty], [llvm_double_ty], [IntrNoMem]>; + def int_nvvm_d2i_rm : GCCBuiltin<"__nvvm_d2i_rm">, + Intrinsic<[llvm_i32_ty], [llvm_double_ty], [IntrNoMem]>; + def int_nvvm_d2i_rp : GCCBuiltin<"__nvvm_d2i_rp">, + Intrinsic<[llvm_i32_ty], [llvm_double_ty], [IntrNoMem]>; + + def int_nvvm_d2ui_rn : GCCBuiltin<"__nvvm_d2ui_rn">, + Intrinsic<[llvm_i32_ty], [llvm_double_ty], [IntrNoMem]>; + def int_nvvm_d2ui_rz : GCCBuiltin<"__nvvm_d2ui_rz">, + Intrinsic<[llvm_i32_ty], [llvm_double_ty], [IntrNoMem]>; + def int_nvvm_d2ui_rm : GCCBuiltin<"__nvvm_d2ui_rm">, + Intrinsic<[llvm_i32_ty], [llvm_double_ty], [IntrNoMem]>; + def int_nvvm_d2ui_rp : GCCBuiltin<"__nvvm_d2ui_rp">, + Intrinsic<[llvm_i32_ty], [llvm_double_ty], [IntrNoMem]>; + + def int_nvvm_i2d_rn : GCCBuiltin<"__nvvm_i2d_rn">, + Intrinsic<[llvm_double_ty], [llvm_i32_ty], [IntrNoMem]>; + def int_nvvm_i2d_rz : GCCBuiltin<"__nvvm_i2d_rz">, + Intrinsic<[llvm_double_ty], [llvm_i32_ty], [IntrNoMem]>; + def int_nvvm_i2d_rm : GCCBuiltin<"__nvvm_i2d_rm">, + Intrinsic<[llvm_double_ty], [llvm_i32_ty], [IntrNoMem]>; + def int_nvvm_i2d_rp : GCCBuiltin<"__nvvm_i2d_rp">, + Intrinsic<[llvm_double_ty], [llvm_i32_ty], [IntrNoMem]>; + + def int_nvvm_ui2d_rn : GCCBuiltin<"__nvvm_ui2d_rn">, + Intrinsic<[llvm_double_ty], [llvm_i32_ty], [IntrNoMem]>; + def int_nvvm_ui2d_rz : GCCBuiltin<"__nvvm_ui2d_rz">, + Intrinsic<[llvm_double_ty], [llvm_i32_ty], [IntrNoMem]>; + def int_nvvm_ui2d_rm : GCCBuiltin<"__nvvm_ui2d_rm">, + Intrinsic<[llvm_double_ty], [llvm_i32_ty], [IntrNoMem]>; + def int_nvvm_ui2d_rp : GCCBuiltin<"__nvvm_ui2d_rp">, + Intrinsic<[llvm_double_ty], [llvm_i32_ty], [IntrNoMem]>; + + def int_nvvm_f2i_rn_ftz : GCCBuiltin<"__nvvm_f2i_rn_ftz">, + Intrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_f2i_rn : GCCBuiltin<"__nvvm_f2i_rn">, + Intrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_f2i_rz_ftz : GCCBuiltin<"__nvvm_f2i_rz_ftz">, + Intrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_f2i_rz : GCCBuiltin<"__nvvm_f2i_rz">, + Intrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_f2i_rm_ftz : GCCBuiltin<"__nvvm_f2i_rm_ftz">, + Intrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_f2i_rm : GCCBuiltin<"__nvvm_f2i_rm">, + Intrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_f2i_rp_ftz : GCCBuiltin<"__nvvm_f2i_rp_ftz">, + Intrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_f2i_rp : GCCBuiltin<"__nvvm_f2i_rp">, + Intrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem]>; + + def int_nvvm_f2ui_rn_ftz : GCCBuiltin<"__nvvm_f2ui_rn_ftz">, + Intrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_f2ui_rn : GCCBuiltin<"__nvvm_f2ui_rn">, + Intrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_f2ui_rz_ftz : GCCBuiltin<"__nvvm_f2ui_rz_ftz">, + Intrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_f2ui_rz : GCCBuiltin<"__nvvm_f2ui_rz">, + Intrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_f2ui_rm_ftz : GCCBuiltin<"__nvvm_f2ui_rm_ftz">, + Intrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_f2ui_rm : GCCBuiltin<"__nvvm_f2ui_rm">, + Intrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_f2ui_rp_ftz : GCCBuiltin<"__nvvm_f2ui_rp_ftz">, + Intrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_f2ui_rp : GCCBuiltin<"__nvvm_f2ui_rp">, + Intrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem]>; + + def int_nvvm_i2f_rn : GCCBuiltin<"__nvvm_i2f_rn">, + Intrinsic<[llvm_float_ty], [llvm_i32_ty], [IntrNoMem]>; + def int_nvvm_i2f_rz : GCCBuiltin<"__nvvm_i2f_rz">, + Intrinsic<[llvm_float_ty], [llvm_i32_ty], [IntrNoMem]>; + def int_nvvm_i2f_rm : GCCBuiltin<"__nvvm_i2f_rm">, + Intrinsic<[llvm_float_ty], [llvm_i32_ty], [IntrNoMem]>; + def int_nvvm_i2f_rp : GCCBuiltin<"__nvvm_i2f_rp">, + Intrinsic<[llvm_float_ty], [llvm_i32_ty], [IntrNoMem]>; + + def int_nvvm_ui2f_rn : GCCBuiltin<"__nvvm_ui2f_rn">, + Intrinsic<[llvm_float_ty], [llvm_i32_ty], [IntrNoMem]>; + def int_nvvm_ui2f_rz : GCCBuiltin<"__nvvm_ui2f_rz">, + Intrinsic<[llvm_float_ty], [llvm_i32_ty], [IntrNoMem]>; + def int_nvvm_ui2f_rm : GCCBuiltin<"__nvvm_ui2f_rm">, + Intrinsic<[llvm_float_ty], [llvm_i32_ty], [IntrNoMem]>; + def int_nvvm_ui2f_rp : GCCBuiltin<"__nvvm_ui2f_rp">, + Intrinsic<[llvm_float_ty], [llvm_i32_ty], [IntrNoMem]>; + + def int_nvvm_lohi_i2d : GCCBuiltin<"__nvvm_lohi_i2d">, + Intrinsic<[llvm_double_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, Commutative]>; + + def int_nvvm_d2i_lo : GCCBuiltin<"__nvvm_d2i_lo">, + Intrinsic<[llvm_i32_ty], [llvm_double_ty], [IntrNoMem]>; + def int_nvvm_d2i_hi : GCCBuiltin<"__nvvm_d2i_hi">, + Intrinsic<[llvm_i32_ty], [llvm_double_ty], [IntrNoMem]>; + + def int_nvvm_f2ll_rn_ftz : GCCBuiltin<"__nvvm_f2ll_rn_ftz">, + Intrinsic<[llvm_i64_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_f2ll_rn : GCCBuiltin<"__nvvm_f2ll_rn">, + Intrinsic<[llvm_i64_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_f2ll_rz_ftz : GCCBuiltin<"__nvvm_f2ll_rz_ftz">, + Intrinsic<[llvm_i64_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_f2ll_rz : GCCBuiltin<"__nvvm_f2ll_rz">, + Intrinsic<[llvm_i64_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_f2ll_rm_ftz : GCCBuiltin<"__nvvm_f2ll_rm_ftz">, + Intrinsic<[llvm_i64_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_f2ll_rm : GCCBuiltin<"__nvvm_f2ll_rm">, + Intrinsic<[llvm_i64_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_f2ll_rp_ftz : GCCBuiltin<"__nvvm_f2ll_rp_ftz">, + Intrinsic<[llvm_i64_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_f2ll_rp : GCCBuiltin<"__nvvm_f2ll_rp">, + Intrinsic<[llvm_i64_ty], [llvm_float_ty], [IntrNoMem]>; + + def int_nvvm_f2ull_rn_ftz : GCCBuiltin<"__nvvm_f2ull_rn_ftz">, + Intrinsic<[llvm_i64_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_f2ull_rn : GCCBuiltin<"__nvvm_f2ull_rn">, + Intrinsic<[llvm_i64_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_f2ull_rz_ftz : GCCBuiltin<"__nvvm_f2ull_rz_ftz">, + Intrinsic<[llvm_i64_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_f2ull_rz : GCCBuiltin<"__nvvm_f2ull_rz">, + Intrinsic<[llvm_i64_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_f2ull_rm_ftz : GCCBuiltin<"__nvvm_f2ull_rm_ftz">, + Intrinsic<[llvm_i64_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_f2ull_rm : GCCBuiltin<"__nvvm_f2ull_rm">, + Intrinsic<[llvm_i64_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_f2ull_rp_ftz : GCCBuiltin<"__nvvm_f2ull_rp_ftz">, + Intrinsic<[llvm_i64_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_f2ull_rp : GCCBuiltin<"__nvvm_f2ull_rp">, + Intrinsic<[llvm_i64_ty], [llvm_float_ty], [IntrNoMem]>; + + def int_nvvm_d2ll_rn : GCCBuiltin<"__nvvm_d2ll_rn">, + Intrinsic<[llvm_i64_ty], [llvm_double_ty], [IntrNoMem]>; + def int_nvvm_d2ll_rz : GCCBuiltin<"__nvvm_d2ll_rz">, + Intrinsic<[llvm_i64_ty], [llvm_double_ty], [IntrNoMem]>; + def int_nvvm_d2ll_rm : GCCBuiltin<"__nvvm_d2ll_rm">, + Intrinsic<[llvm_i64_ty], [llvm_double_ty], [IntrNoMem]>; + def int_nvvm_d2ll_rp : GCCBuiltin<"__nvvm_d2ll_rp">, + Intrinsic<[llvm_i64_ty], [llvm_double_ty], [IntrNoMem]>; + + def int_nvvm_d2ull_rn : GCCBuiltin<"__nvvm_d2ull_rn">, + Intrinsic<[llvm_i64_ty], [llvm_double_ty], [IntrNoMem]>; + def int_nvvm_d2ull_rz : GCCBuiltin<"__nvvm_d2ull_rz">, + Intrinsic<[llvm_i64_ty], [llvm_double_ty], [IntrNoMem]>; + def int_nvvm_d2ull_rm : GCCBuiltin<"__nvvm_d2ull_rm">, + Intrinsic<[llvm_i64_ty], [llvm_double_ty], [IntrNoMem]>; + def int_nvvm_d2ull_rp : GCCBuiltin<"__nvvm_d2ull_rp">, + Intrinsic<[llvm_i64_ty], [llvm_double_ty], [IntrNoMem]>; + + def int_nvvm_ll2f_rn : GCCBuiltin<"__nvvm_ll2f_rn">, + Intrinsic<[llvm_float_ty], [llvm_i64_ty], [IntrNoMem]>; + def int_nvvm_ll2f_rz : GCCBuiltin<"__nvvm_ll2f_rz">, + Intrinsic<[llvm_float_ty], [llvm_i64_ty], [IntrNoMem]>; + def int_nvvm_ll2f_rm : GCCBuiltin<"__nvvm_ll2f_rm">, + Intrinsic<[llvm_float_ty], [llvm_i64_ty], [IntrNoMem]>; + def int_nvvm_ll2f_rp : GCCBuiltin<"__nvvm_ll2f_rp">, + Intrinsic<[llvm_float_ty], [llvm_i64_ty], [IntrNoMem]>; + def int_nvvm_ull2f_rn : GCCBuiltin<"__nvvm_ull2f_rn">, + Intrinsic<[llvm_float_ty], [llvm_i64_ty], [IntrNoMem]>; + def int_nvvm_ull2f_rz : GCCBuiltin<"__nvvm_ull2f_rz">, + Intrinsic<[llvm_float_ty], [llvm_i64_ty], [IntrNoMem]>; + def int_nvvm_ull2f_rm : GCCBuiltin<"__nvvm_ull2f_rm">, + Intrinsic<[llvm_float_ty], [llvm_i64_ty], [IntrNoMem]>; + def int_nvvm_ull2f_rp : GCCBuiltin<"__nvvm_ull2f_rp">, + Intrinsic<[llvm_float_ty], [llvm_i64_ty], [IntrNoMem]>; + + def int_nvvm_ll2d_rn : GCCBuiltin<"__nvvm_ll2d_rn">, + Intrinsic<[llvm_double_ty], [llvm_i64_ty], [IntrNoMem]>; + def int_nvvm_ll2d_rz : GCCBuiltin<"__nvvm_ll2d_rz">, + Intrinsic<[llvm_double_ty], [llvm_i64_ty], [IntrNoMem]>; + def int_nvvm_ll2d_rm : GCCBuiltin<"__nvvm_ll2d_rm">, + Intrinsic<[llvm_double_ty], [llvm_i64_ty], [IntrNoMem]>; + def int_nvvm_ll2d_rp : GCCBuiltin<"__nvvm_ll2d_rp">, + Intrinsic<[llvm_double_ty], [llvm_i64_ty], [IntrNoMem]>; + def int_nvvm_ull2d_rn : GCCBuiltin<"__nvvm_ull2d_rn">, + Intrinsic<[llvm_double_ty], [llvm_i64_ty], [IntrNoMem]>; + def int_nvvm_ull2d_rz : GCCBuiltin<"__nvvm_ull2d_rz">, + Intrinsic<[llvm_double_ty], [llvm_i64_ty], [IntrNoMem]>; + def int_nvvm_ull2d_rm : GCCBuiltin<"__nvvm_ull2d_rm">, + Intrinsic<[llvm_double_ty], [llvm_i64_ty], [IntrNoMem]>; + def int_nvvm_ull2d_rp : GCCBuiltin<"__nvvm_ull2d_rp">, + Intrinsic<[llvm_double_ty], [llvm_i64_ty], [IntrNoMem]>; + + def int_nvvm_f2h_rn_ftz : GCCBuiltin<"__nvvm_f2h_rn_ftz">, + Intrinsic<[llvm_i16_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_f2h_rn : GCCBuiltin<"__nvvm_f2h_rn">, + Intrinsic<[llvm_i16_ty], [llvm_float_ty], [IntrNoMem]>; + + def int_nvvm_h2f : GCCBuiltin<"__nvvm_h2f">, + Intrinsic<[llvm_float_ty], [llvm_i16_ty], [IntrNoMem]>; + +// +// Bitcast +// + + def int_nvvm_bitcast_f2i : GCCBuiltin<"__nvvm_bitcast_f2i">, + Intrinsic<[llvm_i32_ty], [llvm_float_ty], [IntrNoMem]>; + def int_nvvm_bitcast_i2f : GCCBuiltin<"__nvvm_bitcast_i2f">, + Intrinsic<[llvm_float_ty], [llvm_i32_ty], [IntrNoMem]>; + + def int_nvvm_bitcast_ll2d : GCCBuiltin<"__nvvm_bitcast_ll2d">, + Intrinsic<[llvm_double_ty], [llvm_i64_ty], [IntrNoMem]>; + def int_nvvm_bitcast_d2ll : GCCBuiltin<"__nvvm_bitcast_d2ll">, + Intrinsic<[llvm_i64_ty], [llvm_double_ty], [IntrNoMem]>; + + +// Atomic not available as an llvm intrinsic. + def int_nvvm_atomic_load_add_f32 : Intrinsic<[llvm_float_ty], + [LLVMAnyPointerType<llvm_float_ty>, llvm_float_ty], + [IntrReadWriteArgMem, NoCapture<0>]>; + def int_nvvm_atomic_load_inc_32 : Intrinsic<[llvm_i32_ty], + [LLVMAnyPointerType<llvm_i32_ty>, llvm_i32_ty], + [IntrReadWriteArgMem, NoCapture<0>]>; + def int_nvvm_atomic_load_dec_32 : Intrinsic<[llvm_i32_ty], + [LLVMAnyPointerType<llvm_i32_ty>, llvm_i32_ty], + [IntrReadWriteArgMem, NoCapture<0>]>; + +// Bar.Sync + def int_cuda_syncthreads : GCCBuiltin<"__syncthreads">, + Intrinsic<[], [], []>; + def int_nvvm_barrier0 : GCCBuiltin<"__nvvm_bar0">, + Intrinsic<[], [], []>; + def int_nvvm_barrier0_popc : GCCBuiltin<"__nvvm_bar0_popc">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; + def int_nvvm_barrier0_and : GCCBuiltin<"__nvvm_bar0_and">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; + def int_nvvm_barrier0_or : GCCBuiltin<"__nvvm_bar0_or">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; + + // Membar + def int_nvvm_membar_cta : GCCBuiltin<"__nvvm_membar_cta">, + Intrinsic<[], [], []>; + def int_nvvm_membar_gl : GCCBuiltin<"__nvvm_membar_gl">, + Intrinsic<[], [], []>; + def int_nvvm_membar_sys : GCCBuiltin<"__nvvm_membar_sys">, + Intrinsic<[], [], []>; + + +// Accessing special registers + def int_nvvm_read_ptx_sreg_tid_x : + Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, + GCCBuiltin<"__nvvm_read_ptx_sreg_tid_x">; + def int_nvvm_read_ptx_sreg_tid_y : + Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, + GCCBuiltin<"__nvvm_read_ptx_sreg_tid_y">; + def int_nvvm_read_ptx_sreg_tid_z : + Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, + GCCBuiltin<"__nvvm_read_ptx_sreg_tid_z">; + + def int_nvvm_read_ptx_sreg_ntid_x : + Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, + GCCBuiltin<"__nvvm_read_ptx_sreg_ntid_x">; + def int_nvvm_read_ptx_sreg_ntid_y : + Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, + GCCBuiltin<"__nvvm_read_ptx_sreg_ntid_y">; + def int_nvvm_read_ptx_sreg_ntid_z : + Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, + GCCBuiltin<"__nvvm_read_ptx_sreg_ntid_z">; + + def int_nvvm_read_ptx_sreg_ctaid_x : + Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, + GCCBuiltin<"__nvvm_read_ptx_sreg_ctaid_x">; + def int_nvvm_read_ptx_sreg_ctaid_y : + Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, + GCCBuiltin<"__nvvm_read_ptx_sreg_ctaid_y">; + def int_nvvm_read_ptx_sreg_ctaid_z : + Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, + GCCBuiltin<"__nvvm_read_ptx_sreg_ctaid_z">; + + def int_nvvm_read_ptx_sreg_nctaid_x : + Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, + GCCBuiltin<"__nvvm_read_ptx_sreg_nctaid_x">; + def int_nvvm_read_ptx_sreg_nctaid_y : + Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, + GCCBuiltin<"__nvvm_read_ptx_sreg_nctaid_y">; + def int_nvvm_read_ptx_sreg_nctaid_z : + Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, + GCCBuiltin<"__nvvm_read_ptx_sreg_nctaid_z">; + + def int_nvvm_read_ptx_sreg_warpsize : + Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, + GCCBuiltin<"__nvvm_read_ptx_sreg_warpsize">; + + +// Generated within nvvm. Use for ldu on sm_20 or later +// @TODO: Revisit this, Changed LLVMAnyPointerType to LLVMPointerType +def int_nvvm_ldu_global_i : Intrinsic<[llvm_anyint_ty], + [LLVMPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>], + "llvm.nvvm.ldu.global.i">; +def int_nvvm_ldu_global_f : Intrinsic<[llvm_anyfloat_ty], + [LLVMPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>], + "llvm.nvvm.ldu.global.f">; +def int_nvvm_ldu_global_p : Intrinsic<[llvm_anyptr_ty], + [LLVMPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>], + "llvm.nvvm.ldu.global.p">; + +// Generated within nvvm. Use for ldg on sm_35 or later +def int_nvvm_ldg_global_i : Intrinsic<[llvm_anyint_ty], + [LLVMPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>], + "llvm.nvvm.ldg.global.i">; +def int_nvvm_ldg_global_f : Intrinsic<[llvm_anyfloat_ty], + [LLVMPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>], + "llvm.nvvm.ldg.global.f">; +def int_nvvm_ldg_global_p : Intrinsic<[llvm_anyptr_ty], + [LLVMPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>], + "llvm.nvvm.ldg.global.p">; + +// Use for generic pointers +// - These intrinsics are used to convert address spaces. +// - The input pointer and output pointer must have the same type, except for +// the address-space. (This restriction is not enforced here as there is +// currently no way to describe it). +// - This complements the llvm bitcast, which can be used to cast one type +// of pointer to another type of pointer, while the address space remains +// the same. +def int_nvvm_ptr_local_to_gen: Intrinsic<[llvm_anyptr_ty], + [llvm_anyptr_ty], [IntrNoMem], + "llvm.nvvm.ptr.local.to.gen">; +def int_nvvm_ptr_shared_to_gen: Intrinsic<[llvm_anyptr_ty], + [llvm_anyptr_ty], [IntrNoMem], + "llvm.nvvm.ptr.shared.to.gen">; +def int_nvvm_ptr_global_to_gen: Intrinsic<[llvm_anyptr_ty], + [llvm_anyptr_ty], [IntrNoMem], + "llvm.nvvm.ptr.global.to.gen">; +def int_nvvm_ptr_constant_to_gen: Intrinsic<[llvm_anyptr_ty], + [llvm_anyptr_ty], [IntrNoMem], + "llvm.nvvm.ptr.constant.to.gen">; + +def int_nvvm_ptr_gen_to_global: Intrinsic<[llvm_anyptr_ty], + [llvm_anyptr_ty], [IntrNoMem], + "llvm.nvvm.ptr.gen.to.global">; +def int_nvvm_ptr_gen_to_shared: Intrinsic<[llvm_anyptr_ty], + [llvm_anyptr_ty], [IntrNoMem], + "llvm.nvvm.ptr.gen.to.shared">; +def int_nvvm_ptr_gen_to_local: Intrinsic<[llvm_anyptr_ty], + [llvm_anyptr_ty], [IntrNoMem], + "llvm.nvvm.ptr.gen.to.local">; +def int_nvvm_ptr_gen_to_constant: Intrinsic<[llvm_anyptr_ty], + [llvm_anyptr_ty], [IntrNoMem], + "llvm.nvvm.ptr.gen.to.constant">; + +// Used in nvvm internally to help address space opt and ptx code generation +// This is for params that are passed to kernel functions by pointer by-val. +def int_nvvm_ptr_gen_to_param: Intrinsic<[llvm_anyptr_ty], + [llvm_anyptr_ty], + [IntrNoMem], + "llvm.nvvm.ptr.gen.to.param">; + +// Move intrinsics, used in nvvm internally + +def int_nvvm_move_i8 : Intrinsic<[llvm_i8_ty], [llvm_i8_ty], [IntrNoMem], + "llvm.nvvm.move.i8">; +def int_nvvm_move_i16 : Intrinsic<[llvm_i16_ty], [llvm_i16_ty], [IntrNoMem], + "llvm.nvvm.move.i16">; +def int_nvvm_move_i32 : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem], + "llvm.nvvm.move.i32">; +def int_nvvm_move_i64 : Intrinsic<[llvm_i64_ty], [llvm_i64_ty], [IntrNoMem], + "llvm.nvvm.move.i64">; +def int_nvvm_move_float : Intrinsic<[llvm_float_ty], [llvm_float_ty], + [IntrNoMem], "llvm.nvvm.move.float">; +def int_nvvm_move_double : Intrinsic<[llvm_double_ty], [llvm_double_ty], + [IntrNoMem], "llvm.nvvm.move.double">; +def int_nvvm_move_ptr : Intrinsic<[llvm_anyptr_ty], [llvm_anyptr_ty], + [IntrNoMem, NoCapture<0>], "llvm.nvvm.move.ptr">; + + +/// Error / Warn +def int_nvvm_compiler_error : + Intrinsic<[], [llvm_anyptr_ty], [], "llvm.nvvm.compiler.error">; +def int_nvvm_compiler_warn : + Intrinsic<[], [llvm_anyptr_ty], [], "llvm.nvvm.compiler.warn">; + + +// Old PTX back-end intrinsics retained here for backwards-compatibility + +multiclass PTXReadSpecialRegisterIntrinsic_v4i32<string prefix> { +// FIXME: Do we need the 128-bit integer type version? +// def _r64 : Intrinsic<[llvm_i128_ty], [], [IntrNoMem]>; + +// FIXME: Enable this once v4i32 support is enabled in back-end. +// def _v4i16 : Intrinsic<[llvm_v4i32_ty], [], [IntrNoMem]>; + + def _x : Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, + GCCBuiltin<!strconcat(prefix, "_x")>; + def _y : Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, + GCCBuiltin<!strconcat(prefix, "_y")>; + def _z : Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, + GCCBuiltin<!strconcat(prefix, "_z")>; + def _w : Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, + GCCBuiltin<!strconcat(prefix, "_w")>; +} + +class PTXReadSpecialRegisterIntrinsic_r32<string name> + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, + GCCBuiltin<name>; + +class PTXReadSpecialRegisterIntrinsic_r64<string name> + : Intrinsic<[llvm_i64_ty], [], [IntrNoMem]>, + GCCBuiltin<name>; + +defm int_ptx_read_tid : PTXReadSpecialRegisterIntrinsic_v4i32 + <"__builtin_ptx_read_tid">; +defm int_ptx_read_ntid : PTXReadSpecialRegisterIntrinsic_v4i32 + <"__builtin_ptx_read_ntid">; + +def int_ptx_read_laneid : PTXReadSpecialRegisterIntrinsic_r32 + <"__builtin_ptx_read_laneid">; +def int_ptx_read_warpid : PTXReadSpecialRegisterIntrinsic_r32 + <"__builtin_ptx_read_warpid">; +def int_ptx_read_nwarpid : PTXReadSpecialRegisterIntrinsic_r32 + <"__builtin_ptx_read_nwarpid">; + +defm int_ptx_read_ctaid : PTXReadSpecialRegisterIntrinsic_v4i32 + <"__builtin_ptx_read_ctaid">; +defm int_ptx_read_nctaid : PTXReadSpecialRegisterIntrinsic_v4i32 + <"__builtin_ptx_read_nctaid">; + +def int_ptx_read_smid : PTXReadSpecialRegisterIntrinsic_r32 + <"__builtin_ptx_read_smid">; +def int_ptx_read_nsmid : PTXReadSpecialRegisterIntrinsic_r32 + <"__builtin_ptx_read_nsmid">; +def int_ptx_read_gridid : PTXReadSpecialRegisterIntrinsic_r32 + <"__builtin_ptx_read_gridid">; + +def int_ptx_read_lanemask_eq : PTXReadSpecialRegisterIntrinsic_r32 + <"__builtin_ptx_read_lanemask_eq">; +def int_ptx_read_lanemask_le : PTXReadSpecialRegisterIntrinsic_r32 + <"__builtin_ptx_read_lanemask_le">; +def int_ptx_read_lanemask_lt : PTXReadSpecialRegisterIntrinsic_r32 + <"__builtin_ptx_read_lanemask_lt">; +def int_ptx_read_lanemask_ge : PTXReadSpecialRegisterIntrinsic_r32 + <"__builtin_ptx_read_lanemask_ge">; +def int_ptx_read_lanemask_gt : PTXReadSpecialRegisterIntrinsic_r32 + <"__builtin_ptx_read_lanemask_gt">; + +def int_ptx_read_clock : PTXReadSpecialRegisterIntrinsic_r32 + <"__builtin_ptx_read_clock">; +def int_ptx_read_clock64 : PTXReadSpecialRegisterIntrinsic_r64 + <"__builtin_ptx_read_clock64">; + +def int_ptx_read_pm0 : PTXReadSpecialRegisterIntrinsic_r32 + <"__builtin_ptx_read_pm0">; +def int_ptx_read_pm1 : PTXReadSpecialRegisterIntrinsic_r32 + <"__builtin_ptx_read_pm1">; +def int_ptx_read_pm2 : PTXReadSpecialRegisterIntrinsic_r32 + <"__builtin_ptx_read_pm2">; +def int_ptx_read_pm3 : PTXReadSpecialRegisterIntrinsic_r32 + <"__builtin_ptx_read_pm3">; + +def int_ptx_bar_sync : Intrinsic<[], [llvm_i32_ty], []>, + GCCBuiltin<"__builtin_ptx_bar_sync">; diff --git a/include/llvm/IR/IntrinsicsPowerPC.td b/include/llvm/IR/IntrinsicsPowerPC.td new file mode 100644 index 0000000..cde39cc --- /dev/null +++ b/include/llvm/IR/IntrinsicsPowerPC.td @@ -0,0 +1,466 @@ +//===- IntrinsicsPowerPC.td - Defines PowerPC intrinsics ---*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the PowerPC-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Definitions for all PowerPC intrinsics. +// + +// Non-altivec intrinsics. +let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". + // dcba/dcbf/dcbi/dcbst/dcbt/dcbz/dcbzl(PPC970) instructions. + def int_ppc_dcba : Intrinsic<[], [llvm_ptr_ty], []>; + def int_ppc_dcbf : Intrinsic<[], [llvm_ptr_ty], []>; + def int_ppc_dcbi : Intrinsic<[], [llvm_ptr_ty], []>; + def int_ppc_dcbst : Intrinsic<[], [llvm_ptr_ty], []>; + def int_ppc_dcbt : Intrinsic<[], [llvm_ptr_ty], + [IntrReadWriteArgMem, NoCapture<0>]>; + def int_ppc_dcbtst: Intrinsic<[], [llvm_ptr_ty], []>; + def int_ppc_dcbz : Intrinsic<[], [llvm_ptr_ty], []>; + def int_ppc_dcbzl : Intrinsic<[], [llvm_ptr_ty], []>; + + // sync instruction + def int_ppc_sync : Intrinsic<[], [], []>; +} + + +let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". + /// PowerPC_Vec_Intrinsic - Base class for all altivec intrinsics. + class PowerPC_Vec_Intrinsic<string GCCIntSuffix, list<LLVMType> ret_types, + list<LLVMType> param_types, + list<IntrinsicProperty> properties> + : GCCBuiltin<!strconcat("__builtin_altivec_", GCCIntSuffix)>, + Intrinsic<ret_types, param_types, properties>; +} + +//===----------------------------------------------------------------------===// +// PowerPC Altivec Intrinsic Class Definitions. +// + +/// PowerPC_Vec_FF_Intrinsic - A PowerPC intrinsic that takes one v4f32 +/// vector and returns one. These intrinsics have no side effects. +class PowerPC_Vec_FF_Intrinsic<string GCCIntSuffix> + : PowerPC_Vec_Intrinsic<GCCIntSuffix, + [llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + +/// PowerPC_Vec_FFF_Intrinsic - A PowerPC intrinsic that takes two v4f32 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_Vec_FFF_Intrinsic<string GCCIntSuffix> + : PowerPC_Vec_Intrinsic<GCCIntSuffix, + [llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + +/// PowerPC_Vec_BBB_Intrinsic - A PowerPC intrinsic that takes two v16f8 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_Vec_BBB_Intrinsic<string GCCIntSuffix> + : PowerPC_Vec_Intrinsic<GCCIntSuffix, + [llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + +/// PowerPC_Vec_HHH_Intrinsic - A PowerPC intrinsic that takes two v8i16 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_Vec_HHH_Intrinsic<string GCCIntSuffix> + : PowerPC_Vec_Intrinsic<GCCIntSuffix, + [llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + +/// PowerPC_Vec_WWW_Intrinsic - A PowerPC intrinsic that takes two v4i32 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_Vec_WWW_Intrinsic<string GCCIntSuffix> + : PowerPC_Vec_Intrinsic<GCCIntSuffix, + [llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + + +//===----------------------------------------------------------------------===// +// PowerPC Altivec Intrinsic Definitions. + +let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". + // Data Stream Control. + def int_ppc_altivec_dss : GCCBuiltin<"__builtin_altivec_dss">, + Intrinsic<[], [llvm_i32_ty], []>; + def int_ppc_altivec_dssall : GCCBuiltin<"__builtin_altivec_dssall">, + Intrinsic<[], [], []>; + def int_ppc_altivec_dst : GCCBuiltin<"__builtin_altivec_dst">, + Intrinsic<[], + [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], + []>; + def int_ppc_altivec_dstt : GCCBuiltin<"__builtin_altivec_dstt">, + Intrinsic<[], + [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], + []>; + def int_ppc_altivec_dstst : GCCBuiltin<"__builtin_altivec_dstst">, + Intrinsic<[], + [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], + []>; + def int_ppc_altivec_dststt : GCCBuiltin<"__builtin_altivec_dststt">, + Intrinsic<[], + [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], + []>; + + // VSCR access. + def int_ppc_altivec_mfvscr : GCCBuiltin<"__builtin_altivec_mfvscr">, + Intrinsic<[llvm_v8i16_ty], [], [IntrReadMem]>; + def int_ppc_altivec_mtvscr : GCCBuiltin<"__builtin_altivec_mtvscr">, + Intrinsic<[], [llvm_v4i32_ty], []>; + + + // Loads. These don't map directly to GCC builtins because they represent the + // source address with a single pointer. + def int_ppc_altivec_lvx : + Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty], [IntrReadMem]>; + def int_ppc_altivec_lvxl : + Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty], [IntrReadMem]>; + def int_ppc_altivec_lvebx : + Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty], [IntrReadMem]>; + def int_ppc_altivec_lvehx : + Intrinsic<[llvm_v8i16_ty], [llvm_ptr_ty], [IntrReadMem]>; + def int_ppc_altivec_lvewx : + Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty], [IntrReadMem]>; + + // Stores. These don't map directly to GCC builtins because they represent the + // source address with a single pointer. + def int_ppc_altivec_stvx : + Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty], []>; + def int_ppc_altivec_stvxl : + Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty], []>; + def int_ppc_altivec_stvebx : + Intrinsic<[], [llvm_v16i8_ty, llvm_ptr_ty], []>; + def int_ppc_altivec_stvehx : + Intrinsic<[], [llvm_v8i16_ty, llvm_ptr_ty], []>; + def int_ppc_altivec_stvewx : + Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty], []>; + + // Comparisons setting a vector. + def int_ppc_altivec_vcmpbfp : GCCBuiltin<"__builtin_altivec_vcmpbfp">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpeqfp : GCCBuiltin<"__builtin_altivec_vcmpeqfp">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgefp : GCCBuiltin<"__builtin_altivec_vcmpgefp">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtfp : GCCBuiltin<"__builtin_altivec_vcmpgtfp">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + + def int_ppc_altivec_vcmpequw : GCCBuiltin<"__builtin_altivec_vcmpequw">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtsw : GCCBuiltin<"__builtin_altivec_vcmpgtsw">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtuw : GCCBuiltin<"__builtin_altivec_vcmpgtuw">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + + def int_ppc_altivec_vcmpequh : GCCBuiltin<"__builtin_altivec_vcmpequh">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtsh : GCCBuiltin<"__builtin_altivec_vcmpgtsh">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtuh : GCCBuiltin<"__builtin_altivec_vcmpgtuh">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + + def int_ppc_altivec_vcmpequb : GCCBuiltin<"__builtin_altivec_vcmpequb">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtsb : GCCBuiltin<"__builtin_altivec_vcmpgtsb">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtub : GCCBuiltin<"__builtin_altivec_vcmpgtub">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + + // Predicate Comparisons. The first operand specifies interpretation of CR6. + def int_ppc_altivec_vcmpbfp_p : GCCBuiltin<"__builtin_altivec_vcmpbfp_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4f32_ty,llvm_v4f32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpeqfp_p : GCCBuiltin<"__builtin_altivec_vcmpeqfp_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4f32_ty,llvm_v4f32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgefp_p : GCCBuiltin<"__builtin_altivec_vcmpgefp_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4f32_ty,llvm_v4f32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtfp_p : GCCBuiltin<"__builtin_altivec_vcmpgtfp_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4f32_ty,llvm_v4f32_ty], + [IntrNoMem]>; + + def int_ppc_altivec_vcmpequw_p : GCCBuiltin<"__builtin_altivec_vcmpequw_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4i32_ty,llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtsw_p : GCCBuiltin<"__builtin_altivec_vcmpgtsw_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4i32_ty,llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtuw_p : GCCBuiltin<"__builtin_altivec_vcmpgtuw_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4i32_ty,llvm_v4i32_ty], + [IntrNoMem]>; + + def int_ppc_altivec_vcmpequh_p : GCCBuiltin<"__builtin_altivec_vcmpequh_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v8i16_ty,llvm_v8i16_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtsh_p : GCCBuiltin<"__builtin_altivec_vcmpgtsh_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v8i16_ty,llvm_v8i16_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtuh_p : GCCBuiltin<"__builtin_altivec_vcmpgtuh_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v8i16_ty,llvm_v8i16_ty], + [IntrNoMem]>; + + def int_ppc_altivec_vcmpequb_p : GCCBuiltin<"__builtin_altivec_vcmpequb_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v16i8_ty,llvm_v16i8_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtsb_p : GCCBuiltin<"__builtin_altivec_vcmpgtsb_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v16i8_ty,llvm_v16i8_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtub_p : GCCBuiltin<"__builtin_altivec_vcmpgtub_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v16i8_ty,llvm_v16i8_ty], + [IntrNoMem]>; +} + +// Vector average. +def int_ppc_altivec_vavgsb : PowerPC_Vec_BBB_Intrinsic<"vavgsb">; +def int_ppc_altivec_vavgsh : PowerPC_Vec_HHH_Intrinsic<"vavgsh">; +def int_ppc_altivec_vavgsw : PowerPC_Vec_WWW_Intrinsic<"vavgsw">; +def int_ppc_altivec_vavgub : PowerPC_Vec_BBB_Intrinsic<"vavgub">; +def int_ppc_altivec_vavguh : PowerPC_Vec_HHH_Intrinsic<"vavguh">; +def int_ppc_altivec_vavguw : PowerPC_Vec_WWW_Intrinsic<"vavguw">; + +// Vector maximum. +def int_ppc_altivec_vmaxfp : PowerPC_Vec_FFF_Intrinsic<"vmaxfp">; +def int_ppc_altivec_vmaxsb : PowerPC_Vec_BBB_Intrinsic<"vmaxsb">; +def int_ppc_altivec_vmaxsh : PowerPC_Vec_HHH_Intrinsic<"vmaxsh">; +def int_ppc_altivec_vmaxsw : PowerPC_Vec_WWW_Intrinsic<"vmaxsw">; +def int_ppc_altivec_vmaxub : PowerPC_Vec_BBB_Intrinsic<"vmaxub">; +def int_ppc_altivec_vmaxuh : PowerPC_Vec_HHH_Intrinsic<"vmaxuh">; +def int_ppc_altivec_vmaxuw : PowerPC_Vec_WWW_Intrinsic<"vmaxuw">; + +// Vector minimum. +def int_ppc_altivec_vminfp : PowerPC_Vec_FFF_Intrinsic<"vminfp">; +def int_ppc_altivec_vminsb : PowerPC_Vec_BBB_Intrinsic<"vminsb">; +def int_ppc_altivec_vminsh : PowerPC_Vec_HHH_Intrinsic<"vminsh">; +def int_ppc_altivec_vminsw : PowerPC_Vec_WWW_Intrinsic<"vminsw">; +def int_ppc_altivec_vminub : PowerPC_Vec_BBB_Intrinsic<"vminub">; +def int_ppc_altivec_vminuh : PowerPC_Vec_HHH_Intrinsic<"vminuh">; +def int_ppc_altivec_vminuw : PowerPC_Vec_WWW_Intrinsic<"vminuw">; + +// Saturating adds. +def int_ppc_altivec_vaddubs : PowerPC_Vec_BBB_Intrinsic<"vaddubs">; +def int_ppc_altivec_vaddsbs : PowerPC_Vec_BBB_Intrinsic<"vaddsbs">; +def int_ppc_altivec_vadduhs : PowerPC_Vec_HHH_Intrinsic<"vadduhs">; +def int_ppc_altivec_vaddshs : PowerPC_Vec_HHH_Intrinsic<"vaddshs">; +def int_ppc_altivec_vadduws : PowerPC_Vec_WWW_Intrinsic<"vadduws">; +def int_ppc_altivec_vaddsws : PowerPC_Vec_WWW_Intrinsic<"vaddsws">; +def int_ppc_altivec_vaddcuw : PowerPC_Vec_WWW_Intrinsic<"vaddcuw">; + +// Saturating subs. +def int_ppc_altivec_vsububs : PowerPC_Vec_BBB_Intrinsic<"vsububs">; +def int_ppc_altivec_vsubsbs : PowerPC_Vec_BBB_Intrinsic<"vsubsbs">; +def int_ppc_altivec_vsubuhs : PowerPC_Vec_HHH_Intrinsic<"vsubuhs">; +def int_ppc_altivec_vsubshs : PowerPC_Vec_HHH_Intrinsic<"vsubshs">; +def int_ppc_altivec_vsubuws : PowerPC_Vec_WWW_Intrinsic<"vsubuws">; +def int_ppc_altivec_vsubsws : PowerPC_Vec_WWW_Intrinsic<"vsubsws">; +def int_ppc_altivec_vsubcuw : PowerPC_Vec_WWW_Intrinsic<"vsubcuw">; + +let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". + // Saturating multiply-adds. + def int_ppc_altivec_vmhaddshs : GCCBuiltin<"__builtin_altivec_vmhaddshs">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vmhraddshs : GCCBuiltin<"__builtin_altivec_vmhraddshs">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; + + def int_ppc_altivec_vmaddfp : GCCBuiltin<"__builtin_altivec_vmaddfp">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; + def int_ppc_altivec_vnmsubfp : GCCBuiltin<"__builtin_altivec_vnmsubfp">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; + + // Vector Multiply Sum Intructions. + def int_ppc_altivec_vmsummbm : GCCBuiltin<"__builtin_altivec_vmsummbm">, + Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_ppc_altivec_vmsumshm : GCCBuiltin<"__builtin_altivec_vmsumshm">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_ppc_altivec_vmsumshs : GCCBuiltin<"__builtin_altivec_vmsumshs">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_ppc_altivec_vmsumubm : GCCBuiltin<"__builtin_altivec_vmsumubm">, + Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_ppc_altivec_vmsumuhm : GCCBuiltin<"__builtin_altivec_vmsumuhm">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_ppc_altivec_vmsumuhs : GCCBuiltin<"__builtin_altivec_vmsumuhs">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v4i32_ty], [IntrNoMem]>; + + // Vector Multiply Intructions. + def int_ppc_altivec_vmulesb : GCCBuiltin<"__builtin_altivec_vmulesb">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + def int_ppc_altivec_vmulesh : GCCBuiltin<"__builtin_altivec_vmulesh">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_ppc_altivec_vmuleub : GCCBuiltin<"__builtin_altivec_vmuleub">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + def int_ppc_altivec_vmuleuh : GCCBuiltin<"__builtin_altivec_vmuleuh">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + + def int_ppc_altivec_vmulosb : GCCBuiltin<"__builtin_altivec_vmulosb">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + def int_ppc_altivec_vmulosh : GCCBuiltin<"__builtin_altivec_vmulosh">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_ppc_altivec_vmuloub : GCCBuiltin<"__builtin_altivec_vmuloub">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + def int_ppc_altivec_vmulouh : GCCBuiltin<"__builtin_altivec_vmulouh">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + + // Vector Sum Intructions. + def int_ppc_altivec_vsumsws : GCCBuiltin<"__builtin_altivec_vsumsws">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vsum2sws : GCCBuiltin<"__builtin_altivec_vsum2sws">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vsum4sbs : GCCBuiltin<"__builtin_altivec_vsum4sbs">, + Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vsum4shs : GCCBuiltin<"__builtin_altivec_vsum4shs">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vsum4ubs : GCCBuiltin<"__builtin_altivec_vsum4ubs">, + Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty, llvm_v4i32_ty], + [IntrNoMem]>; + + // Other multiplies. + def int_ppc_altivec_vmladduhm : GCCBuiltin<"__builtin_altivec_vmladduhm">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + + // Packs. + def int_ppc_altivec_vpkpx : GCCBuiltin<"__builtin_altivec_vpkpx">, + Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vpkshss : GCCBuiltin<"__builtin_altivec_vpkshss">, + Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_ppc_altivec_vpkshus : GCCBuiltin<"__builtin_altivec_vpkshus">, + Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_ppc_altivec_vpkswss : GCCBuiltin<"__builtin_altivec_vpkswss">, + Intrinsic<[llvm_v16i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vpkswus : GCCBuiltin<"__builtin_altivec_vpkswus">, + Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + // vpkuhum is lowered to a shuffle. + def int_ppc_altivec_vpkuhus : GCCBuiltin<"__builtin_altivec_vpkuhus">, + Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + // vpkuwum is lowered to a shuffle. + def int_ppc_altivec_vpkuwus : GCCBuiltin<"__builtin_altivec_vpkuwus">, + Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + + // Unpacks. + def int_ppc_altivec_vupkhpx : GCCBuiltin<"__builtin_altivec_vupkhpx">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vupkhsb : GCCBuiltin<"__builtin_altivec_vupkhsb">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty], [IntrNoMem]>; + def int_ppc_altivec_vupkhsh : GCCBuiltin<"__builtin_altivec_vupkhsh">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vupklpx : GCCBuiltin<"__builtin_altivec_vupklpx">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vupklsb : GCCBuiltin<"__builtin_altivec_vupklsb">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty], [IntrNoMem]>; + def int_ppc_altivec_vupklsh : GCCBuiltin<"__builtin_altivec_vupklsh">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; + + + // FP <-> integer conversion. + def int_ppc_altivec_vcfsx : GCCBuiltin<"__builtin_altivec_vcfsx">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcfux : GCCBuiltin<"__builtin_altivec_vcfux">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vctsxs : GCCBuiltin<"__builtin_altivec_vctsxs">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vctuxs : GCCBuiltin<"__builtin_altivec_vctuxs">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_ppc_altivec_vrfim : GCCBuiltin<"__builtin_altivec_vrfim">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_ppc_altivec_vrfin : GCCBuiltin<"__builtin_altivec_vrfin">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_ppc_altivec_vrfip : GCCBuiltin<"__builtin_altivec_vrfip">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_ppc_altivec_vrfiz : GCCBuiltin<"__builtin_altivec_vrfiz">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +} + +def int_ppc_altivec_vsl : PowerPC_Vec_WWW_Intrinsic<"vsl">; +def int_ppc_altivec_vslo : PowerPC_Vec_WWW_Intrinsic<"vslo">; + +def int_ppc_altivec_vslb : PowerPC_Vec_BBB_Intrinsic<"vslb">; +def int_ppc_altivec_vslh : PowerPC_Vec_HHH_Intrinsic<"vslh">; +def int_ppc_altivec_vslw : PowerPC_Vec_WWW_Intrinsic<"vslw">; + +// Right Shifts. +def int_ppc_altivec_vsr : PowerPC_Vec_WWW_Intrinsic<"vsr">; +def int_ppc_altivec_vsro : PowerPC_Vec_WWW_Intrinsic<"vsro">; + +def int_ppc_altivec_vsrb : PowerPC_Vec_BBB_Intrinsic<"vsrb">; +def int_ppc_altivec_vsrh : PowerPC_Vec_HHH_Intrinsic<"vsrh">; +def int_ppc_altivec_vsrw : PowerPC_Vec_WWW_Intrinsic<"vsrw">; +def int_ppc_altivec_vsrab : PowerPC_Vec_BBB_Intrinsic<"vsrab">; +def int_ppc_altivec_vsrah : PowerPC_Vec_HHH_Intrinsic<"vsrah">; +def int_ppc_altivec_vsraw : PowerPC_Vec_WWW_Intrinsic<"vsraw">; + +// Rotates. +def int_ppc_altivec_vrlb : PowerPC_Vec_BBB_Intrinsic<"vrlb">; +def int_ppc_altivec_vrlh : PowerPC_Vec_HHH_Intrinsic<"vrlh">; +def int_ppc_altivec_vrlw : PowerPC_Vec_WWW_Intrinsic<"vrlw">; + +let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". + // Miscellaneous. + def int_ppc_altivec_lvsl : + Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty], [IntrNoMem]>; + def int_ppc_altivec_lvsr : + Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty], [IntrNoMem]>; + + def int_ppc_altivec_vperm : GCCBuiltin<"__builtin_altivec_vperm_4si">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_v4i32_ty, llvm_v16i8_ty], [IntrNoMem]>; + def int_ppc_altivec_vsel : GCCBuiltin<"__builtin_altivec_vsel_4si">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +} + +def int_ppc_altivec_vexptefp : PowerPC_Vec_FF_Intrinsic<"vexptefp">; +def int_ppc_altivec_vlogefp : PowerPC_Vec_FF_Intrinsic<"vlogefp">; +def int_ppc_altivec_vrefp : PowerPC_Vec_FF_Intrinsic<"vrefp">; +def int_ppc_altivec_vrsqrtefp : PowerPC_Vec_FF_Intrinsic<"vrsqrtefp">; diff --git a/include/llvm/IR/IntrinsicsR600.td b/include/llvm/IR/IntrinsicsR600.td new file mode 100644 index 0000000..ecb5668 --- /dev/null +++ b/include/llvm/IR/IntrinsicsR600.td @@ -0,0 +1,36 @@ +//===- IntrinsicsR600.td - Defines R600 intrinsics ---------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the R600-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +let TargetPrefix = "r600" in { + +class R600ReadPreloadRegisterIntrinsic<string name> + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, + GCCBuiltin<name>; + +multiclass R600ReadPreloadRegisterIntrinsic_xyz<string prefix> { + def _x : R600ReadPreloadRegisterIntrinsic<!strconcat(prefix, "_x")>; + def _y : R600ReadPreloadRegisterIntrinsic<!strconcat(prefix, "_y")>; + def _z : R600ReadPreloadRegisterIntrinsic<!strconcat(prefix, "_z")>; +} + +defm int_r600_read_global_size : R600ReadPreloadRegisterIntrinsic_xyz < + "__builtin_r600_read_global_size">; +defm int_r600_read_local_size : R600ReadPreloadRegisterIntrinsic_xyz < + "__builtin_r600_read_local_size">; +defm int_r600_read_ngroups : R600ReadPreloadRegisterIntrinsic_xyz < + "__builtin_r600_read_ngroups">; +defm int_r600_read_tgid : R600ReadPreloadRegisterIntrinsic_xyz < + "__builtin_r600_read_tgid">; +defm int_r600_read_tidig : R600ReadPreloadRegisterIntrinsic_xyz < + "__builtin_r600_read_tidig">; +} // End TargetPrefix = "r600" diff --git a/include/llvm/IR/IntrinsicsX86.td b/include/llvm/IR/IntrinsicsX86.td new file mode 100644 index 0000000..69e0ab4 --- /dev/null +++ b/include/llvm/IR/IntrinsicsX86.td @@ -0,0 +1,2580 @@ +//===- IntrinsicsX86.td - Defines X86 intrinsics -----------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the X86-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Interrupt traps +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_int : Intrinsic<[], [llvm_i8_ty]>; +} + +//===----------------------------------------------------------------------===// +// 3DNow! + +let TargetPrefix = "x86" in { + def int_x86_3dnow_pavgusb : GCCBuiltin<"__builtin_ia32_pavgusb">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pf2id : GCCBuiltin<"__builtin_ia32_pf2id">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_3dnow_pfacc : GCCBuiltin<"__builtin_ia32_pfacc">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfadd : GCCBuiltin<"__builtin_ia32_pfadd">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfcmpeq : GCCBuiltin<"__builtin_ia32_pfcmpeq">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfcmpge : GCCBuiltin<"__builtin_ia32_pfcmpge">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfcmpgt : GCCBuiltin<"__builtin_ia32_pfcmpgt">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfmax : GCCBuiltin<"__builtin_ia32_pfmax">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfmin : GCCBuiltin<"__builtin_ia32_pfmin">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfmul : GCCBuiltin<"__builtin_ia32_pfmul">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfrcp : GCCBuiltin<"__builtin_ia32_pfrcp">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_3dnow_pfrcpit1 : GCCBuiltin<"__builtin_ia32_pfrcpit1">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfrcpit2 : GCCBuiltin<"__builtin_ia32_pfrcpit2">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfrsqrt : GCCBuiltin<"__builtin_ia32_pfrsqrt">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_3dnow_pfrsqit1 : GCCBuiltin<"__builtin_ia32_pfrsqit1">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfsub : GCCBuiltin<"__builtin_ia32_pfsub">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfsubr : GCCBuiltin<"__builtin_ia32_pfsubr">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pi2fd : GCCBuiltin<"__builtin_ia32_pi2fd">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_3dnow_pmulhrw : GCCBuiltin<"__builtin_ia32_pmulhrw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// 3DNow! extensions + +let TargetPrefix = "x86" in { + def int_x86_3dnowa_pf2iw : GCCBuiltin<"__builtin_ia32_pf2iw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_3dnowa_pfnacc : GCCBuiltin<"__builtin_ia32_pfnacc">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnowa_pfpnacc : GCCBuiltin<"__builtin_ia32_pfpnacc">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnowa_pi2fw : GCCBuiltin<"__builtin_ia32_pi2fw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_3dnowa_pswapd : + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// SSE1 + +// Arithmetic ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse_add_ss : GCCBuiltin<"__builtin_ia32_addss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_sub_ss : GCCBuiltin<"__builtin_ia32_subss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_mul_ss : GCCBuiltin<"__builtin_ia32_mulss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_div_ss : GCCBuiltin<"__builtin_ia32_divss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_sqrt_ss : GCCBuiltin<"__builtin_ia32_sqrtss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_sse_sqrt_ps : GCCBuiltin<"__builtin_ia32_sqrtps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_sse_rcp_ss : GCCBuiltin<"__builtin_ia32_rcpss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_sse_rcp_ps : GCCBuiltin<"__builtin_ia32_rcpps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_sse_rsqrt_ss : GCCBuiltin<"__builtin_ia32_rsqrtss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_sse_rsqrt_ps : GCCBuiltin<"__builtin_ia32_rsqrtps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_sse_min_ss : GCCBuiltin<"__builtin_ia32_minss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_min_ps : GCCBuiltin<"__builtin_ia32_minps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_max_ss : GCCBuiltin<"__builtin_ia32_maxss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_max_ps : GCCBuiltin<"__builtin_ia32_maxps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; +} + +// Comparison ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse_cmp_ss : GCCBuiltin<"__builtin_ia32_cmpss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_sse_cmp_ps : GCCBuiltin<"__builtin_ia32_cmpps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_sse_comieq_ss : GCCBuiltin<"__builtin_ia32_comieq">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_comilt_ss : GCCBuiltin<"__builtin_ia32_comilt">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_comile_ss : GCCBuiltin<"__builtin_ia32_comile">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_comigt_ss : GCCBuiltin<"__builtin_ia32_comigt">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_comige_ss : GCCBuiltin<"__builtin_ia32_comige">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_comineq_ss : GCCBuiltin<"__builtin_ia32_comineq">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_ucomieq_ss : GCCBuiltin<"__builtin_ia32_ucomieq">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_ucomilt_ss : GCCBuiltin<"__builtin_ia32_ucomilt">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_ucomile_ss : GCCBuiltin<"__builtin_ia32_ucomile">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_ucomigt_ss : GCCBuiltin<"__builtin_ia32_ucomigt">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_ucomige_ss : GCCBuiltin<"__builtin_ia32_ucomige">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_ucomineq_ss : GCCBuiltin<"__builtin_ia32_ucomineq">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; +} + + +// Conversion ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse_cvtss2si : GCCBuiltin<"__builtin_ia32_cvtss2si">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_cvtss2si64 : GCCBuiltin<"__builtin_ia32_cvtss2si64">, + Intrinsic<[llvm_i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_cvttss2si : GCCBuiltin<"__builtin_ia32_cvttss2si">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_cvttss2si64 : GCCBuiltin<"__builtin_ia32_cvttss2si64">, + Intrinsic<[llvm_i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_cvtsi2ss : GCCBuiltin<"__builtin_ia32_cvtsi2ss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse_cvtsi642ss : GCCBuiltin<"__builtin_ia32_cvtsi642ss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_i64_ty], [IntrNoMem]>; + def int_x86_sse_cvtps2pi : GCCBuiltin<"__builtin_ia32_cvtps2pi">, + Intrinsic<[llvm_x86mmx_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_cvttps2pi: GCCBuiltin<"__builtin_ia32_cvttps2pi">, + Intrinsic<[llvm_x86mmx_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_cvtpi2ps : GCCBuiltin<"__builtin_ia32_cvtpi2ps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_x86mmx_ty], [IntrNoMem]>; +} + +// SIMD store ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse_storeu_ps : GCCBuiltin<"__builtin_ia32_storeups">, + Intrinsic<[], [llvm_ptr_ty, + llvm_v4f32_ty], [IntrReadWriteArgMem]>; +} + +// Cacheability support ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse_sfence : GCCBuiltin<"__builtin_ia32_sfence">, + Intrinsic<[], [], []>; +} + +// Control register. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse_stmxcsr : + Intrinsic<[], [llvm_ptr_ty], []>; + def int_x86_sse_ldmxcsr : + Intrinsic<[], [llvm_ptr_ty], []>; +} + +// Misc. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse_movmsk_ps : GCCBuiltin<"__builtin_ia32_movmskps">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// SSE2 + +// FP arithmetic ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_add_sd : GCCBuiltin<"__builtin_ia32_addsd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_sub_sd : GCCBuiltin<"__builtin_ia32_subsd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_mul_sd : GCCBuiltin<"__builtin_ia32_mulsd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_div_sd : GCCBuiltin<"__builtin_ia32_divsd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_sqrt_sd : GCCBuiltin<"__builtin_ia32_sqrtsd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], + [IntrNoMem]>; + def int_x86_sse2_sqrt_pd : GCCBuiltin<"__builtin_ia32_sqrtpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], + [IntrNoMem]>; + def int_x86_sse2_min_sd : GCCBuiltin<"__builtin_ia32_minsd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_min_pd : GCCBuiltin<"__builtin_ia32_minpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_max_sd : GCCBuiltin<"__builtin_ia32_maxsd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_max_pd : GCCBuiltin<"__builtin_ia32_maxpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; +} + +// FP comparison ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_cmp_sd : GCCBuiltin<"__builtin_ia32_cmpsd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_sse2_cmp_pd : GCCBuiltin<"__builtin_ia32_cmppd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_sse2_comieq_sd : GCCBuiltin<"__builtin_ia32_comisdeq">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_comilt_sd : GCCBuiltin<"__builtin_ia32_comisdlt">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_comile_sd : GCCBuiltin<"__builtin_ia32_comisdle">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_comigt_sd : GCCBuiltin<"__builtin_ia32_comisdgt">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_comige_sd : GCCBuiltin<"__builtin_ia32_comisdge">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_comineq_sd : GCCBuiltin<"__builtin_ia32_comisdneq">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_ucomieq_sd : GCCBuiltin<"__builtin_ia32_ucomisdeq">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_ucomilt_sd : GCCBuiltin<"__builtin_ia32_ucomisdlt">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_ucomile_sd : GCCBuiltin<"__builtin_ia32_ucomisdle">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_ucomigt_sd : GCCBuiltin<"__builtin_ia32_ucomisdgt">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_ucomige_sd : GCCBuiltin<"__builtin_ia32_ucomisdge">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_ucomineq_sd : GCCBuiltin<"__builtin_ia32_ucomisdneq">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; +} + +// Integer arithmetic ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_padds_b : GCCBuiltin<"__builtin_ia32_paddsb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_padds_w : GCCBuiltin<"__builtin_ia32_paddsw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_paddus_b : GCCBuiltin<"__builtin_ia32_paddusb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_paddus_w : GCCBuiltin<"__builtin_ia32_paddusw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_psubs_b : GCCBuiltin<"__builtin_ia32_psubsb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_sse2_psubs_w : GCCBuiltin<"__builtin_ia32_psubsw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_psubus_b : GCCBuiltin<"__builtin_ia32_psubusb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_sse2_psubus_w : GCCBuiltin<"__builtin_ia32_psubusw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_pmulhu_w : GCCBuiltin<"__builtin_ia32_pmulhuw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_pmulh_w : GCCBuiltin<"__builtin_ia32_pmulhw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_pmulu_dq : GCCBuiltin<"__builtin_ia32_pmuludq128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_pmadd_wd : GCCBuiltin<"__builtin_ia32_pmaddwd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_pavg_b : GCCBuiltin<"__builtin_ia32_pavgb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_pavg_w : GCCBuiltin<"__builtin_ia32_pavgw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_pmaxu_b : GCCBuiltin<"__builtin_ia32_pmaxub128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_pmaxs_w : GCCBuiltin<"__builtin_ia32_pmaxsw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_pminu_b : GCCBuiltin<"__builtin_ia32_pminub128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_pmins_w : GCCBuiltin<"__builtin_ia32_pminsw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_psad_bw : GCCBuiltin<"__builtin_ia32_psadbw128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem, Commutative]>; +} + +// Integer shift ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_psll_w : GCCBuiltin<"__builtin_ia32_psllw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_psll_d : GCCBuiltin<"__builtin_ia32_pslld128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sse2_psll_q : GCCBuiltin<"__builtin_ia32_psllq128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, + llvm_v2i64_ty], [IntrNoMem]>; + def int_x86_sse2_psrl_w : GCCBuiltin<"__builtin_ia32_psrlw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_psrl_d : GCCBuiltin<"__builtin_ia32_psrld128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sse2_psrl_q : GCCBuiltin<"__builtin_ia32_psrlq128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, + llvm_v2i64_ty], [IntrNoMem]>; + def int_x86_sse2_psra_w : GCCBuiltin<"__builtin_ia32_psraw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_psra_d : GCCBuiltin<"__builtin_ia32_psrad128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; + + def int_x86_sse2_pslli_w : GCCBuiltin<"__builtin_ia32_psllwi128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_pslli_d : GCCBuiltin<"__builtin_ia32_pslldi128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_pslli_q : GCCBuiltin<"__builtin_ia32_psllqi128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_psrli_w : GCCBuiltin<"__builtin_ia32_psrlwi128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_psrli_d : GCCBuiltin<"__builtin_ia32_psrldi128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_psrli_q : GCCBuiltin<"__builtin_ia32_psrlqi128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_psrai_w : GCCBuiltin<"__builtin_ia32_psrawi128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_psrai_d : GCCBuiltin<"__builtin_ia32_psradi128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_sse2_psll_dq : GCCBuiltin<"__builtin_ia32_pslldqi128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_psrl_dq : GCCBuiltin<"__builtin_ia32_psrldqi128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_psll_dq_bs : GCCBuiltin<"__builtin_ia32_pslldqi128_byteshift">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_psrl_dq_bs : GCCBuiltin<"__builtin_ia32_psrldqi128_byteshift">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, + llvm_i32_ty], [IntrNoMem]>; +} + +// Conversion ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_cvtdq2pd : GCCBuiltin<"__builtin_ia32_cvtdq2pd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sse2_cvtdq2ps : GCCBuiltin<"__builtin_ia32_cvtdq2ps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sse2_cvtpd2dq : GCCBuiltin<"__builtin_ia32_cvtpd2dq">, + Intrinsic<[llvm_v4i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_cvttpd2dq : GCCBuiltin<"__builtin_ia32_cvttpd2dq">, + Intrinsic<[llvm_v4i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_cvtpd2ps : GCCBuiltin<"__builtin_ia32_cvtpd2ps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_cvtps2dq : GCCBuiltin<"__builtin_ia32_cvtps2dq">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse2_cvttps2dq : GCCBuiltin<"__builtin_ia32_cvttps2dq">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse2_cvtps2pd : GCCBuiltin<"__builtin_ia32_cvtps2pd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse2_cvtsd2si : GCCBuiltin<"__builtin_ia32_cvtsd2si">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_cvtsd2si64 : GCCBuiltin<"__builtin_ia32_cvtsd2si64">, + Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_cvttsd2si : GCCBuiltin<"__builtin_ia32_cvttsd2si">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_cvttsd2si64 : GCCBuiltin<"__builtin_ia32_cvttsd2si64">, + Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_cvtsi2sd : GCCBuiltin<"__builtin_ia32_cvtsi2sd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_cvtsi642sd : GCCBuiltin<"__builtin_ia32_cvtsi642sd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_i64_ty], [IntrNoMem]>; + def int_x86_sse2_cvtsd2ss : GCCBuiltin<"__builtin_ia32_cvtsd2ss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_cvtss2sd : GCCBuiltin<"__builtin_ia32_cvtss2sd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_cvtpd2pi : GCCBuiltin<"__builtin_ia32_cvtpd2pi">, + Intrinsic<[llvm_x86mmx_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse_cvttpd2pi: GCCBuiltin<"__builtin_ia32_cvttpd2pi">, + Intrinsic<[llvm_x86mmx_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse_cvtpi2pd : GCCBuiltin<"__builtin_ia32_cvtpi2pd">, + Intrinsic<[llvm_v2f64_ty], [llvm_x86mmx_ty], [IntrNoMem]>; +} + +// SIMD store ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_storeu_pd : GCCBuiltin<"__builtin_ia32_storeupd">, + Intrinsic<[], [llvm_ptr_ty, + llvm_v2f64_ty], [IntrReadWriteArgMem]>; + def int_x86_sse2_storeu_dq : GCCBuiltin<"__builtin_ia32_storedqu">, + Intrinsic<[], [llvm_ptr_ty, + llvm_v16i8_ty], [IntrReadWriteArgMem]>; + def int_x86_sse2_storel_dq : GCCBuiltin<"__builtin_ia32_storelv4si">, + Intrinsic<[], [llvm_ptr_ty, + llvm_v4i32_ty], [IntrReadWriteArgMem]>; +} + +// Misc. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_packsswb_128 : GCCBuiltin<"__builtin_ia32_packsswb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_packssdw_128 : GCCBuiltin<"__builtin_ia32_packssdw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sse2_packuswb_128 : GCCBuiltin<"__builtin_ia32_packuswb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_movmsk_pd : GCCBuiltin<"__builtin_ia32_movmskpd">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_pmovmskb_128 : GCCBuiltin<"__builtin_ia32_pmovmskb128">, + Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_sse2_maskmov_dqu : GCCBuiltin<"__builtin_ia32_maskmovdqu">, + Intrinsic<[], [llvm_v16i8_ty, + llvm_v16i8_ty, llvm_ptr_ty], []>; + def int_x86_sse2_clflush : GCCBuiltin<"__builtin_ia32_clflush">, + Intrinsic<[], [llvm_ptr_ty], []>; + def int_x86_sse2_lfence : GCCBuiltin<"__builtin_ia32_lfence">, + Intrinsic<[], [], []>; + def int_x86_sse2_mfence : GCCBuiltin<"__builtin_ia32_mfence">, + Intrinsic<[], [], []>; +} + +//===----------------------------------------------------------------------===// +// SSE3 + +// Addition / subtraction ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse3_addsub_ps : GCCBuiltin<"__builtin_ia32_addsubps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse3_addsub_pd : GCCBuiltin<"__builtin_ia32_addsubpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; +} + +// Horizontal ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse3_hadd_ps : GCCBuiltin<"__builtin_ia32_haddps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse3_hadd_pd : GCCBuiltin<"__builtin_ia32_haddpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse3_hsub_ps : GCCBuiltin<"__builtin_ia32_hsubps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse3_hsub_pd : GCCBuiltin<"__builtin_ia32_hsubpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; +} + +// Specialized unaligned load. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse3_ldu_dq : GCCBuiltin<"__builtin_ia32_lddqu">, + Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty], [IntrReadMem]>; +} + +// Thread synchronization ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse3_monitor : GCCBuiltin<"__builtin_ia32_monitor">, + Intrinsic<[], [llvm_ptr_ty, + llvm_i32_ty, llvm_i32_ty], []>; + def int_x86_sse3_mwait : GCCBuiltin<"__builtin_ia32_mwait">, + Intrinsic<[], [llvm_i32_ty, + llvm_i32_ty], []>; +} + +//===----------------------------------------------------------------------===// +// SSSE3 + +// Horizontal arithmetic ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_ssse3_phadd_w : GCCBuiltin<"__builtin_ia32_phaddw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_ssse3_phadd_w_128 : GCCBuiltin<"__builtin_ia32_phaddw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + + def int_x86_ssse3_phadd_d : GCCBuiltin<"__builtin_ia32_phaddd">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_ssse3_phadd_d_128 : GCCBuiltin<"__builtin_ia32_phaddd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; + + def int_x86_ssse3_phadd_sw : GCCBuiltin<"__builtin_ia32_phaddsw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_ssse3_phadd_sw_128 : GCCBuiltin<"__builtin_ia32_phaddsw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + + def int_x86_ssse3_phsub_w : GCCBuiltin<"__builtin_ia32_phsubw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_ssse3_phsub_w_128 : GCCBuiltin<"__builtin_ia32_phsubw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + + def int_x86_ssse3_phsub_d : GCCBuiltin<"__builtin_ia32_phsubd">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_ssse3_phsub_d_128 : GCCBuiltin<"__builtin_ia32_phsubd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; + + def int_x86_ssse3_phsub_sw : GCCBuiltin<"__builtin_ia32_phsubsw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_ssse3_phsub_sw_128 : GCCBuiltin<"__builtin_ia32_phsubsw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + + def int_x86_ssse3_pmadd_ub_sw : GCCBuiltin<"__builtin_ia32_pmaddubsw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_ssse3_pmadd_ub_sw_128 : GCCBuiltin<"__builtin_ia32_pmaddubsw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem]>; +} + +// Packed multiply high with round and scale +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_ssse3_pmul_hr_sw : GCCBuiltin<"__builtin_ia32_pmulhrsw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + def int_x86_ssse3_pmul_hr_sw_128 : GCCBuiltin<"__builtin_ia32_pmulhrsw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem, Commutative]>; +} + +// Shuffle ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_ssse3_pshuf_b : GCCBuiltin<"__builtin_ia32_pshufb">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_ssse3_pshuf_b_128 : GCCBuiltin<"__builtin_ia32_pshufb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_sse_pshuf_w : GCCBuiltin<"__builtin_ia32_pshufw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_i8_ty], + [IntrNoMem]>; +} + +// Sign ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_ssse3_psign_b : GCCBuiltin<"__builtin_ia32_psignb">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_ssse3_psign_b_128 : GCCBuiltin<"__builtin_ia32_psignb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem]>; + + def int_x86_ssse3_psign_w : GCCBuiltin<"__builtin_ia32_psignw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_ssse3_psign_w_128 : GCCBuiltin<"__builtin_ia32_psignw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + + def int_x86_ssse3_psign_d : GCCBuiltin<"__builtin_ia32_psignd">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_ssse3_psign_d_128 : GCCBuiltin<"__builtin_ia32_psignd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; +} + +// Absolute value ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_ssse3_pabs_b : GCCBuiltin<"__builtin_ia32_pabsb">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_ssse3_pabs_b_128 : GCCBuiltin<"__builtin_ia32_pabsb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; + + def int_x86_ssse3_pabs_w : GCCBuiltin<"__builtin_ia32_pabsw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_ssse3_pabs_w_128 : GCCBuiltin<"__builtin_ia32_pabsw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; + + def int_x86_ssse3_pabs_d : GCCBuiltin<"__builtin_ia32_pabsd">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_ssse3_pabs_d_128 : GCCBuiltin<"__builtin_ia32_pabsd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// SSE4.1 + +// FP rounding ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_round_ss : GCCBuiltin<"__builtin_ia32_roundss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse41_round_ps : GCCBuiltin<"__builtin_ia32_roundps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse41_round_sd : GCCBuiltin<"__builtin_ia32_roundsd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse41_round_pd : GCCBuiltin<"__builtin_ia32_roundpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_i32_ty], [IntrNoMem]>; +} + +// Vector sign and zero extend +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_pmovsxbd : GCCBuiltin<"__builtin_ia32_pmovsxbd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovsxbq : GCCBuiltin<"__builtin_ia32_pmovsxbq128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovsxbw : GCCBuiltin<"__builtin_ia32_pmovsxbw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovsxdq : GCCBuiltin<"__builtin_ia32_pmovsxdq128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovsxwd : GCCBuiltin<"__builtin_ia32_pmovsxwd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovsxwq : GCCBuiltin<"__builtin_ia32_pmovsxwq128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v8i16_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovzxbd : GCCBuiltin<"__builtin_ia32_pmovzxbd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovzxbq : GCCBuiltin<"__builtin_ia32_pmovzxbq128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovzxbw : GCCBuiltin<"__builtin_ia32_pmovzxbw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovzxdq : GCCBuiltin<"__builtin_ia32_pmovzxdq128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovzxwd : GCCBuiltin<"__builtin_ia32_pmovzxwd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovzxwq : GCCBuiltin<"__builtin_ia32_pmovzxwq128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v8i16_ty], + [IntrNoMem]>; +} + +// Vector min element +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_phminposuw : GCCBuiltin<"__builtin_ia32_phminposuw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], + [IntrNoMem]>; +} + +// Vector compare, min, max +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_pmaxsb : GCCBuiltin<"__builtin_ia32_pmaxsb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem, Commutative]>; + def int_x86_sse41_pmaxsd : GCCBuiltin<"__builtin_ia32_pmaxsd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem, Commutative]>; + def int_x86_sse41_pmaxud : GCCBuiltin<"__builtin_ia32_pmaxud128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem, Commutative]>; + def int_x86_sse41_pmaxuw : GCCBuiltin<"__builtin_ia32_pmaxuw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem, Commutative]>; + def int_x86_sse41_pminsb : GCCBuiltin<"__builtin_ia32_pminsb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem, Commutative]>; + def int_x86_sse41_pminsd : GCCBuiltin<"__builtin_ia32_pminsd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem, Commutative]>; + def int_x86_sse41_pminud : GCCBuiltin<"__builtin_ia32_pminud128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem, Commutative]>; + def int_x86_sse41_pminuw : GCCBuiltin<"__builtin_ia32_pminuw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem, Commutative]>; +} + +// Advanced Encryption Standard (AES) Instructions +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_aesni_aesimc : GCCBuiltin<"__builtin_ia32_aesimc128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], + [IntrNoMem]>; + def int_x86_aesni_aesenc : GCCBuiltin<"__builtin_ia32_aesenc128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_x86_aesni_aesenclast : GCCBuiltin<"__builtin_ia32_aesenclast128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_x86_aesni_aesdec : GCCBuiltin<"__builtin_ia32_aesdec128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_x86_aesni_aesdeclast : GCCBuiltin<"__builtin_ia32_aesdeclast128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_x86_aesni_aeskeygenassist : + GCCBuiltin<"__builtin_ia32_aeskeygenassist128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i8_ty], + [IntrNoMem]>; +} + +// PCLMUL instruction +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_pclmulqdq : GCCBuiltin<"__builtin_ia32_pclmulqdq128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrNoMem]>; +} + +// Vector pack +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_packusdw : GCCBuiltin<"__builtin_ia32_packusdw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; +} + +// Vector multiply +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_pmuldq : GCCBuiltin<"__builtin_ia32_pmuldq128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem, Commutative]>; +} + +// Vector extract +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_pextrb : + Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_sse41_pextrd : + Intrinsic<[llvm_i32_ty], [llvm_v4i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_sse41_pextrq : + Intrinsic<[llvm_i64_ty], [llvm_v2i64_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_sse41_extractps : GCCBuiltin<"__builtin_ia32_extractps128">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, llvm_i32_ty], + [IntrNoMem]>; +} + +// Vector insert +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_insertps : GCCBuiltin<"__builtin_ia32_insertps128">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,llvm_i32_ty], + [IntrNoMem]>; +} + +// Vector blend +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_pblendvb : GCCBuiltin<"__builtin_ia32_pblendvb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_sse41_pblendw : GCCBuiltin<"__builtin_ia32_pblendw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_sse41_blendpd : GCCBuiltin<"__builtin_ia32_blendpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_sse41_blendps : GCCBuiltin<"__builtin_ia32_blendps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_sse41_blendvpd : GCCBuiltin<"__builtin_ia32_blendvpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,llvm_v2f64_ty], + [IntrNoMem]>; + def int_x86_sse41_blendvps : GCCBuiltin<"__builtin_ia32_blendvps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,llvm_v4f32_ty], + [IntrNoMem]>; +} + +// Vector dot product +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_dppd : GCCBuiltin<"__builtin_ia32_dppd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,llvm_i32_ty], + [IntrNoMem, Commutative]>; + def int_x86_sse41_dpps : GCCBuiltin<"__builtin_ia32_dpps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,llvm_i32_ty], + [IntrNoMem, Commutative]>; +} + +// Vector sum of absolute differences +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_mpsadbw : GCCBuiltin<"__builtin_ia32_mpsadbw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty,llvm_i32_ty], + [IntrNoMem, Commutative]>; +} + +// Cacheability support ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_movntdqa : GCCBuiltin<"__builtin_ia32_movntdqa">, + Intrinsic<[llvm_v2i64_ty], [llvm_ptr_ty], [IntrReadMem]>; +} + +// Test instruction with bitwise comparison. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_ptestz : GCCBuiltin<"__builtin_ia32_ptestz128">, + Intrinsic<[llvm_i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_x86_sse41_ptestc : GCCBuiltin<"__builtin_ia32_ptestc128">, + Intrinsic<[llvm_i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_x86_sse41_ptestnzc : GCCBuiltin<"__builtin_ia32_ptestnzc128">, + Intrinsic<[llvm_i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// SSE4.2 + +// Miscellaneous +// CRC Instruction +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse42_crc32_32_8 : GCCBuiltin<"__builtin_ia32_crc32qi">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_crc32_32_16 : GCCBuiltin<"__builtin_ia32_crc32hi">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_sse42_crc32_32_32 : GCCBuiltin<"__builtin_ia32_crc32si">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_sse42_crc32_64_8 : + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_crc32_64_64 : GCCBuiltin<"__builtin_ia32_crc32di">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], + [IntrNoMem]>; +} + +// String/text processing ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse42_pcmpistrm128 : GCCBuiltin<"__builtin_ia32_pcmpistrm128">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpistri128 : GCCBuiltin<"__builtin_ia32_pcmpistri128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpistria128 : GCCBuiltin<"__builtin_ia32_pcmpistria128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpistric128 : GCCBuiltin<"__builtin_ia32_pcmpistric128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpistrio128 : GCCBuiltin<"__builtin_ia32_pcmpistrio128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpistris128 : GCCBuiltin<"__builtin_ia32_pcmpistris128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpistriz128 : GCCBuiltin<"__builtin_ia32_pcmpistriz128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpestrm128 : GCCBuiltin<"__builtin_ia32_pcmpestrm128">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpestri128 : GCCBuiltin<"__builtin_ia32_pcmpestri128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpestria128 : GCCBuiltin<"__builtin_ia32_pcmpestria128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpestric128 : GCCBuiltin<"__builtin_ia32_pcmpestric128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpestrio128 : GCCBuiltin<"__builtin_ia32_pcmpestrio128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpestris128 : GCCBuiltin<"__builtin_ia32_pcmpestris128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpestriz128 : GCCBuiltin<"__builtin_ia32_pcmpestriz128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// SSE4A + +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse4a_extrqi : GCCBuiltin<"__builtin_ia32_extrqi">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse4a_extrq : GCCBuiltin<"__builtin_ia32_extrq">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v16i8_ty], [IntrNoMem]>; + + def int_x86_sse4a_insertqi : GCCBuiltin<"__builtin_ia32_insertqi">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_sse4a_insertq : GCCBuiltin<"__builtin_ia32_insertq">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + + def int_x86_sse4a_movnt_ss : GCCBuiltin<"__builtin_ia32_movntss">, + Intrinsic<[], [llvm_ptr_ty, llvm_v4f32_ty], []>; + def int_x86_sse4a_movnt_sd : GCCBuiltin<"__builtin_ia32_movntsd">, + Intrinsic<[], [llvm_ptr_ty, llvm_v2f64_ty], []>; +} + +//===----------------------------------------------------------------------===// +// AVX + +// Arithmetic ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_addsub_pd_256 : GCCBuiltin<"__builtin_ia32_addsubpd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, + llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_avx_addsub_ps_256 : GCCBuiltin<"__builtin_ia32_addsubps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, + llvm_v8f32_ty], [IntrNoMem]>; + def int_x86_avx_max_pd_256 : GCCBuiltin<"__builtin_ia32_maxpd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, + llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_avx_max_ps_256 : GCCBuiltin<"__builtin_ia32_maxps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, + llvm_v8f32_ty], [IntrNoMem]>; + def int_x86_avx_min_pd_256 : GCCBuiltin<"__builtin_ia32_minpd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, + llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_avx_min_ps_256 : GCCBuiltin<"__builtin_ia32_minps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, + llvm_v8f32_ty], [IntrNoMem]>; + + def int_x86_avx_sqrt_pd_256 : GCCBuiltin<"__builtin_ia32_sqrtpd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_avx_sqrt_ps_256 : GCCBuiltin<"__builtin_ia32_sqrtps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty], [IntrNoMem]>; + + def int_x86_avx_rsqrt_ps_256 : GCCBuiltin<"__builtin_ia32_rsqrtps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty], [IntrNoMem]>; + + def int_x86_avx_rcp_ps_256 : GCCBuiltin<"__builtin_ia32_rcpps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty], [IntrNoMem]>; + + def int_x86_avx_round_pd_256 : GCCBuiltin<"__builtin_ia32_roundpd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx_round_ps_256 : GCCBuiltin<"__builtin_ia32_roundps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, + llvm_i32_ty], [IntrNoMem]>; +} + +// Horizontal ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_hadd_pd_256 : GCCBuiltin<"__builtin_ia32_haddpd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, + llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_avx_hsub_ps_256 : GCCBuiltin<"__builtin_ia32_hsubps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, + llvm_v8f32_ty], [IntrNoMem]>; + def int_x86_avx_hsub_pd_256 : GCCBuiltin<"__builtin_ia32_hsubpd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, + llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_avx_hadd_ps_256 : GCCBuiltin<"__builtin_ia32_haddps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, + llvm_v8f32_ty], [IntrNoMem]>; +} + +// Vector permutation +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_vpermilvar_pd : GCCBuiltin<"__builtin_ia32_vpermilvarpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2i64_ty], [IntrNoMem]>; + def int_x86_avx_vpermilvar_ps : GCCBuiltin<"__builtin_ia32_vpermilvarps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4i32_ty], [IntrNoMem]>; + + def int_x86_avx_vpermilvar_pd_256 : + GCCBuiltin<"__builtin_ia32_vpermilvarpd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4i64_ty], [IntrNoMem]>; + def int_x86_avx_vpermilvar_ps_256 : + GCCBuiltin<"__builtin_ia32_vpermilvarps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8i32_ty], [IntrNoMem]>; + + def int_x86_avx_vperm2f128_pd_256 : + GCCBuiltin<"__builtin_ia32_vperm2f128_pd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx_vperm2f128_ps_256 : + GCCBuiltin<"__builtin_ia32_vperm2f128_ps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx_vperm2f128_si_256 : + GCCBuiltin<"__builtin_ia32_vperm2f128_si256">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, + llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; +} + +// Vector blend +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_blend_pd_256 : GCCBuiltin<"__builtin_ia32_blendpd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx_blend_ps_256 : GCCBuiltin<"__builtin_ia32_blendps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx_blendv_pd_256 : GCCBuiltin<"__builtin_ia32_blendvpd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, + llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_avx_blendv_ps_256 : GCCBuiltin<"__builtin_ia32_blendvps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, + llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; +} + +// Vector dot product +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_dp_ps_256 : GCCBuiltin<"__builtin_ia32_dpps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i32_ty], [IntrNoMem]>; +} + +// Vector compare +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_cmp_pd_256 : GCCBuiltin<"__builtin_ia32_cmppd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx_cmp_ps_256 : GCCBuiltin<"__builtin_ia32_cmpps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; +} + +// Vector extract and insert +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_vextractf128_pd_256 : + GCCBuiltin<"__builtin_ia32_vextractf128_pd256">, + Intrinsic<[llvm_v2f64_ty], [llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx_vextractf128_ps_256 : + GCCBuiltin<"__builtin_ia32_vextractf128_ps256">, + Intrinsic<[llvm_v4f32_ty], [llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx_vextractf128_si_256 : + GCCBuiltin<"__builtin_ia32_vextractf128_si256">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx_vinsertf128_pd_256 : + GCCBuiltin<"__builtin_ia32_vinsertf128_pd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx_vinsertf128_ps_256 : + GCCBuiltin<"__builtin_ia32_vinsertf128_ps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx_vinsertf128_si_256 : + GCCBuiltin<"__builtin_ia32_vinsertf128_si256">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, + llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; +} + +// Vector convert +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_cvtdq2_pd_256 : GCCBuiltin<"__builtin_ia32_cvtdq2pd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_avx_cvtdq2_ps_256 : GCCBuiltin<"__builtin_ia32_cvtdq2ps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8i32_ty], [IntrNoMem]>; + def int_x86_avx_cvt_pd2_ps_256 : GCCBuiltin<"__builtin_ia32_cvtpd2ps256">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_avx_cvt_ps2dq_256 : GCCBuiltin<"__builtin_ia32_cvtps2dq256">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; + def int_x86_avx_cvt_ps2_pd_256 : GCCBuiltin<"__builtin_ia32_cvtps2pd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_avx_cvtt_pd2dq_256 : GCCBuiltin<"__builtin_ia32_cvttpd2dq256">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_avx_cvt_pd2dq_256 : GCCBuiltin<"__builtin_ia32_cvtpd2dq256">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_avx_cvtt_ps2dq_256 : GCCBuiltin<"__builtin_ia32_cvttps2dq256">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; +} + +// Vector bit test +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_vtestz_pd : GCCBuiltin<"__builtin_ia32_vtestzpd">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_avx_vtestc_pd : GCCBuiltin<"__builtin_ia32_vtestcpd">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_avx_vtestnzc_pd : GCCBuiltin<"__builtin_ia32_vtestnzcpd">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_avx_vtestz_ps : GCCBuiltin<"__builtin_ia32_vtestzps">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_avx_vtestc_ps : GCCBuiltin<"__builtin_ia32_vtestcps">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_avx_vtestnzc_ps : GCCBuiltin<"__builtin_ia32_vtestnzcps">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_avx_vtestz_pd_256 : GCCBuiltin<"__builtin_ia32_vtestzpd256">, + Intrinsic<[llvm_i32_ty], [llvm_v4f64_ty, + llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_avx_vtestc_pd_256 : GCCBuiltin<"__builtin_ia32_vtestcpd256">, + Intrinsic<[llvm_i32_ty], [llvm_v4f64_ty, + llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_avx_vtestnzc_pd_256 : GCCBuiltin<"__builtin_ia32_vtestnzcpd256">, + Intrinsic<[llvm_i32_ty], [llvm_v4f64_ty, + llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_avx_vtestz_ps_256 : GCCBuiltin<"__builtin_ia32_vtestzps256">, + Intrinsic<[llvm_i32_ty], [llvm_v8f32_ty, + llvm_v8f32_ty], [IntrNoMem]>; + def int_x86_avx_vtestc_ps_256 : GCCBuiltin<"__builtin_ia32_vtestcps256">, + Intrinsic<[llvm_i32_ty], [llvm_v8f32_ty, + llvm_v8f32_ty], [IntrNoMem]>; + def int_x86_avx_vtestnzc_ps_256 : GCCBuiltin<"__builtin_ia32_vtestnzcps256">, + Intrinsic<[llvm_i32_ty], [llvm_v8f32_ty, + llvm_v8f32_ty], [IntrNoMem]>; + def int_x86_avx_ptestz_256 : GCCBuiltin<"__builtin_ia32_ptestz256">, + Intrinsic<[llvm_i32_ty], [llvm_v4i64_ty, + llvm_v4i64_ty], [IntrNoMem]>; + def int_x86_avx_ptestc_256 : GCCBuiltin<"__builtin_ia32_ptestc256">, + Intrinsic<[llvm_i32_ty], [llvm_v4i64_ty, + llvm_v4i64_ty], [IntrNoMem]>; + def int_x86_avx_ptestnzc_256 : GCCBuiltin<"__builtin_ia32_ptestnzc256">, + Intrinsic<[llvm_i32_ty], [llvm_v4i64_ty, + llvm_v4i64_ty], [IntrNoMem]>; +} + +// Vector extract sign mask +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_movmsk_pd_256 : GCCBuiltin<"__builtin_ia32_movmskpd256">, + Intrinsic<[llvm_i32_ty], [llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_avx_movmsk_ps_256 : GCCBuiltin<"__builtin_ia32_movmskps256">, + Intrinsic<[llvm_i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; +} + +// Vector zero +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_vzeroall : GCCBuiltin<"__builtin_ia32_vzeroall">, + Intrinsic<[], [], []>; + def int_x86_avx_vzeroupper : GCCBuiltin<"__builtin_ia32_vzeroupper">, + Intrinsic<[], [], []>; +} + +// Vector load with broadcast +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_vbroadcast_ss : + GCCBuiltin<"__builtin_ia32_vbroadcastss">, + Intrinsic<[llvm_v4f32_ty], [llvm_ptr_ty], [IntrReadArgMem]>; + def int_x86_avx_vbroadcast_sd_256 : + GCCBuiltin<"__builtin_ia32_vbroadcastsd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_ptr_ty], [IntrReadArgMem]>; + def int_x86_avx_vbroadcast_ss_256 : + GCCBuiltin<"__builtin_ia32_vbroadcastss256">, + Intrinsic<[llvm_v8f32_ty], [llvm_ptr_ty], [IntrReadArgMem]>; + def int_x86_avx_vbroadcastf128_pd_256 : + GCCBuiltin<"__builtin_ia32_vbroadcastf128_pd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_ptr_ty], [IntrReadArgMem]>; + def int_x86_avx_vbroadcastf128_ps_256 : + GCCBuiltin<"__builtin_ia32_vbroadcastf128_ps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_ptr_ty], [IntrReadArgMem]>; +} + +// SIMD load ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_ldu_dq_256 : GCCBuiltin<"__builtin_ia32_lddqu256">, + Intrinsic<[llvm_v32i8_ty], [llvm_ptr_ty], [IntrReadMem]>; +} + +// SIMD store ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_storeu_pd_256 : GCCBuiltin<"__builtin_ia32_storeupd256">, + Intrinsic<[], [llvm_ptr_ty, llvm_v4f64_ty], [IntrReadWriteArgMem]>; + def int_x86_avx_storeu_ps_256 : GCCBuiltin<"__builtin_ia32_storeups256">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8f32_ty], [IntrReadWriteArgMem]>; + def int_x86_avx_storeu_dq_256 : GCCBuiltin<"__builtin_ia32_storedqu256">, + Intrinsic<[], [llvm_ptr_ty, llvm_v32i8_ty], [IntrReadWriteArgMem]>; +} + +// Conditional load ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_maskload_pd : GCCBuiltin<"__builtin_ia32_maskloadpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_ptr_ty, llvm_v2f64_ty], + [IntrReadArgMem]>; + def int_x86_avx_maskload_ps : GCCBuiltin<"__builtin_ia32_maskloadps">, + Intrinsic<[llvm_v4f32_ty], [llvm_ptr_ty, llvm_v4f32_ty], + [IntrReadArgMem]>; + def int_x86_avx_maskload_pd_256 : GCCBuiltin<"__builtin_ia32_maskloadpd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_ptr_ty, llvm_v4f64_ty], + [IntrReadArgMem]>; + def int_x86_avx_maskload_ps_256 : GCCBuiltin<"__builtin_ia32_maskloadps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_ptr_ty, llvm_v8f32_ty], + [IntrReadArgMem]>; +} + +// Conditional store ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_maskstore_pd : GCCBuiltin<"__builtin_ia32_maskstorepd">, + Intrinsic<[], [llvm_ptr_ty, + llvm_v2f64_ty, llvm_v2f64_ty], [IntrReadWriteArgMem]>; + def int_x86_avx_maskstore_ps : GCCBuiltin<"__builtin_ia32_maskstoreps">, + Intrinsic<[], [llvm_ptr_ty, + llvm_v4f32_ty, llvm_v4f32_ty], [IntrReadWriteArgMem]>; + def int_x86_avx_maskstore_pd_256 : + GCCBuiltin<"__builtin_ia32_maskstorepd256">, + Intrinsic<[], [llvm_ptr_ty, + llvm_v4f64_ty, llvm_v4f64_ty], [IntrReadWriteArgMem]>; + def int_x86_avx_maskstore_ps_256 : + GCCBuiltin<"__builtin_ia32_maskstoreps256">, + Intrinsic<[], [llvm_ptr_ty, + llvm_v8f32_ty, llvm_v8f32_ty], [IntrReadWriteArgMem]>; +} + +//===----------------------------------------------------------------------===// +// AVX2 + +// Integer arithmetic ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx2_padds_b : GCCBuiltin<"__builtin_ia32_paddsb256">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, + llvm_v32i8_ty], [IntrNoMem, Commutative]>; + def int_x86_avx2_padds_w : GCCBuiltin<"__builtin_ia32_paddsw256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, + llvm_v16i16_ty], [IntrNoMem, Commutative]>; + def int_x86_avx2_paddus_b : GCCBuiltin<"__builtin_ia32_paddusb256">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, + llvm_v32i8_ty], [IntrNoMem, Commutative]>; + def int_x86_avx2_paddus_w : GCCBuiltin<"__builtin_ia32_paddusw256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, + llvm_v16i16_ty], [IntrNoMem, Commutative]>; + def int_x86_avx2_psubs_b : GCCBuiltin<"__builtin_ia32_psubsb256">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, + llvm_v32i8_ty], [IntrNoMem]>; + def int_x86_avx2_psubs_w : GCCBuiltin<"__builtin_ia32_psubsw256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, + llvm_v16i16_ty], [IntrNoMem]>; + def int_x86_avx2_psubus_b : GCCBuiltin<"__builtin_ia32_psubusb256">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, + llvm_v32i8_ty], [IntrNoMem]>; + def int_x86_avx2_psubus_w : GCCBuiltin<"__builtin_ia32_psubusw256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, + llvm_v16i16_ty], [IntrNoMem]>; + def int_x86_avx2_pmulhu_w : GCCBuiltin<"__builtin_ia32_pmulhuw256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, + llvm_v16i16_ty], [IntrNoMem, Commutative]>; + def int_x86_avx2_pmulh_w : GCCBuiltin<"__builtin_ia32_pmulhw256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, + llvm_v16i16_ty], [IntrNoMem, Commutative]>; + def int_x86_avx2_pmulu_dq : GCCBuiltin<"__builtin_ia32_pmuludq256">, + Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, + llvm_v8i32_ty], [IntrNoMem, Commutative]>; + def int_x86_avx2_pmul_dq : GCCBuiltin<"__builtin_ia32_pmuldq256">, + Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, + llvm_v8i32_ty], [IntrNoMem, Commutative]>; + def int_x86_avx2_pmadd_wd : GCCBuiltin<"__builtin_ia32_pmaddwd256">, + Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, + llvm_v16i16_ty], [IntrNoMem, Commutative]>; + def int_x86_avx2_pavg_b : GCCBuiltin<"__builtin_ia32_pavgb256">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, + llvm_v32i8_ty], [IntrNoMem, Commutative]>; + def int_x86_avx2_pavg_w : GCCBuiltin<"__builtin_ia32_pavgw256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, + llvm_v16i16_ty], [IntrNoMem, Commutative]>; + def int_x86_avx2_psad_bw : GCCBuiltin<"__builtin_ia32_psadbw256">, + Intrinsic<[llvm_v4i64_ty], [llvm_v32i8_ty, + llvm_v32i8_ty], [IntrNoMem, Commutative]>; +} + +// Vector min, max +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx2_pmaxu_b : GCCBuiltin<"__builtin_ia32_pmaxub256">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, + llvm_v32i8_ty], [IntrNoMem, Commutative]>; + def int_x86_avx2_pmaxu_w : GCCBuiltin<"__builtin_ia32_pmaxuw256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, + llvm_v16i16_ty], [IntrNoMem, Commutative]>; + def int_x86_avx2_pmaxu_d : GCCBuiltin<"__builtin_ia32_pmaxud256">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, + llvm_v8i32_ty], [IntrNoMem, Commutative]>; + def int_x86_avx2_pmaxs_b : GCCBuiltin<"__builtin_ia32_pmaxsb256">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, + llvm_v32i8_ty], [IntrNoMem, Commutative]>; + def int_x86_avx2_pmaxs_w : GCCBuiltin<"__builtin_ia32_pmaxsw256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, + llvm_v16i16_ty], [IntrNoMem, Commutative]>; + def int_x86_avx2_pmaxs_d : GCCBuiltin<"__builtin_ia32_pmaxsd256">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, + llvm_v8i32_ty], [IntrNoMem, Commutative]>; + def int_x86_avx2_pminu_b : GCCBuiltin<"__builtin_ia32_pminub256">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, + llvm_v32i8_ty], [IntrNoMem, Commutative]>; + def int_x86_avx2_pminu_w : GCCBuiltin<"__builtin_ia32_pminuw256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, + llvm_v16i16_ty], [IntrNoMem, Commutative]>; + def int_x86_avx2_pminu_d : GCCBuiltin<"__builtin_ia32_pminud256">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, + llvm_v8i32_ty], [IntrNoMem, Commutative]>; + def int_x86_avx2_pmins_b : GCCBuiltin<"__builtin_ia32_pminsb256">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, + llvm_v32i8_ty], [IntrNoMem, Commutative]>; + def int_x86_avx2_pmins_w : GCCBuiltin<"__builtin_ia32_pminsw256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, + llvm_v16i16_ty], [IntrNoMem, Commutative]>; + def int_x86_avx2_pmins_d : GCCBuiltin<"__builtin_ia32_pminsd256">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, + llvm_v8i32_ty], [IntrNoMem, Commutative]>; +} + +// Integer shift ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx2_psll_w : GCCBuiltin<"__builtin_ia32_psllw256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_avx2_psll_d : GCCBuiltin<"__builtin_ia32_pslld256">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_avx2_psll_q : GCCBuiltin<"__builtin_ia32_psllq256">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, + llvm_v2i64_ty], [IntrNoMem]>; + def int_x86_avx2_psrl_w : GCCBuiltin<"__builtin_ia32_psrlw256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_avx2_psrl_d : GCCBuiltin<"__builtin_ia32_psrld256">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_avx2_psrl_q : GCCBuiltin<"__builtin_ia32_psrlq256">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, + llvm_v2i64_ty], [IntrNoMem]>; + def int_x86_avx2_psra_w : GCCBuiltin<"__builtin_ia32_psraw256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_avx2_psra_d : GCCBuiltin<"__builtin_ia32_psrad256">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; + + def int_x86_avx2_pslli_w : GCCBuiltin<"__builtin_ia32_psllwi256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx2_pslli_d : GCCBuiltin<"__builtin_ia32_pslldi256">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx2_pslli_q : GCCBuiltin<"__builtin_ia32_psllqi256">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx2_psrli_w : GCCBuiltin<"__builtin_ia32_psrlwi256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx2_psrli_d : GCCBuiltin<"__builtin_ia32_psrldi256">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx2_psrli_q : GCCBuiltin<"__builtin_ia32_psrlqi256">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx2_psrai_w : GCCBuiltin<"__builtin_ia32_psrawi256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx2_psrai_d : GCCBuiltin<"__builtin_ia32_psradi256">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx2_psll_dq : GCCBuiltin<"__builtin_ia32_pslldqi256">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx2_psrl_dq : GCCBuiltin<"__builtin_ia32_psrldqi256">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx2_psll_dq_bs : GCCBuiltin<"__builtin_ia32_pslldqi256_byteshift">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx2_psrl_dq_bs : GCCBuiltin<"__builtin_ia32_psrldqi256_byteshift">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, + llvm_i32_ty], [IntrNoMem]>; +} + +// Pack ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx2_packsswb : GCCBuiltin<"__builtin_ia32_packsswb256">, + Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty, + llvm_v16i16_ty], [IntrNoMem]>; + def int_x86_avx2_packssdw : GCCBuiltin<"__builtin_ia32_packssdw256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, + llvm_v8i32_ty], [IntrNoMem]>; + def int_x86_avx2_packuswb : GCCBuiltin<"__builtin_ia32_packuswb256">, + Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty, + llvm_v16i16_ty], [IntrNoMem]>; + def int_x86_avx2_packusdw : GCCBuiltin<"__builtin_ia32_packusdw256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, + llvm_v8i32_ty], [IntrNoMem]>; +} + +// Absolute value ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx2_pabs_b : GCCBuiltin<"__builtin_ia32_pabsb256">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty], [IntrNoMem]>; + def int_x86_avx2_pabs_w : GCCBuiltin<"__builtin_ia32_pabsw256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty], [IntrNoMem]>; + def int_x86_avx2_pabs_d : GCCBuiltin<"__builtin_ia32_pabsd256">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty], [IntrNoMem]>; +} + +// Horizontal arithmetic ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx2_phadd_w : GCCBuiltin<"__builtin_ia32_phaddw256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, + llvm_v16i16_ty], [IntrNoMem]>; + def int_x86_avx2_phadd_d : GCCBuiltin<"__builtin_ia32_phaddd256">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, + llvm_v8i32_ty], [IntrNoMem]>; + def int_x86_avx2_phadd_sw : GCCBuiltin<"__builtin_ia32_phaddsw256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, + llvm_v16i16_ty], [IntrNoMem]>; + def int_x86_avx2_phsub_w : GCCBuiltin<"__builtin_ia32_phsubw256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, + llvm_v16i16_ty], [IntrNoMem]>; + def int_x86_avx2_phsub_d : GCCBuiltin<"__builtin_ia32_phsubd256">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, + llvm_v8i32_ty], [IntrNoMem]>; + def int_x86_avx2_phsub_sw : GCCBuiltin<"__builtin_ia32_phsubsw256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, + llvm_v16i16_ty], [IntrNoMem]>; + def int_x86_avx2_pmadd_ub_sw : GCCBuiltin<"__builtin_ia32_pmaddubsw256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, + llvm_v32i8_ty], [IntrNoMem]>; +} + +// Sign ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx2_psign_b : GCCBuiltin<"__builtin_ia32_psignb256">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, + llvm_v32i8_ty], [IntrNoMem]>; + def int_x86_avx2_psign_w : GCCBuiltin<"__builtin_ia32_psignw256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, + llvm_v16i16_ty], [IntrNoMem]>; + def int_x86_avx2_psign_d : GCCBuiltin<"__builtin_ia32_psignd256">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, + llvm_v8i32_ty], [IntrNoMem]>; +} + +// Packed multiply high with round and scale +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx2_pmul_hr_sw : GCCBuiltin<"__builtin_ia32_pmulhrsw256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, + llvm_v16i16_ty], [IntrNoMem, Commutative]>; +} + +// Vector sign and zero extend +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx2_pmovsxbd : GCCBuiltin<"__builtin_ia32_pmovsxbd256">, + Intrinsic<[llvm_v8i32_ty], [llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_avx2_pmovsxbq : GCCBuiltin<"__builtin_ia32_pmovsxbq256">, + Intrinsic<[llvm_v4i64_ty], [llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_avx2_pmovsxbw : GCCBuiltin<"__builtin_ia32_pmovsxbw256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_avx2_pmovsxdq : GCCBuiltin<"__builtin_ia32_pmovsxdq256">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i32_ty], + [IntrNoMem]>; + def int_x86_avx2_pmovsxwd : GCCBuiltin<"__builtin_ia32_pmovsxwd256">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i16_ty], + [IntrNoMem]>; + def int_x86_avx2_pmovsxwq : GCCBuiltin<"__builtin_ia32_pmovsxwq256">, + Intrinsic<[llvm_v4i64_ty], [llvm_v8i16_ty], + [IntrNoMem]>; + def int_x86_avx2_pmovzxbd : GCCBuiltin<"__builtin_ia32_pmovzxbd256">, + Intrinsic<[llvm_v8i32_ty], [llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_avx2_pmovzxbq : GCCBuiltin<"__builtin_ia32_pmovzxbq256">, + Intrinsic<[llvm_v4i64_ty], [llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_avx2_pmovzxbw : GCCBuiltin<"__builtin_ia32_pmovzxbw256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_avx2_pmovzxdq : GCCBuiltin<"__builtin_ia32_pmovzxdq256">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i32_ty], + [IntrNoMem]>; + def int_x86_avx2_pmovzxwd : GCCBuiltin<"__builtin_ia32_pmovzxwd256">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i16_ty], + [IntrNoMem]>; + def int_x86_avx2_pmovzxwq : GCCBuiltin<"__builtin_ia32_pmovzxwq256">, + Intrinsic<[llvm_v4i64_ty], [llvm_v8i16_ty], + [IntrNoMem]>; +} + +// Vector blend +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx2_pblendvb : GCCBuiltin<"__builtin_ia32_pblendvb256">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, + llvm_v32i8_ty], [IntrNoMem]>; + def int_x86_avx2_pblendw : GCCBuiltin<"__builtin_ia32_pblendw256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx2_pblendd_128 : GCCBuiltin<"__builtin_ia32_pblendd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx2_pblendd_256 : GCCBuiltin<"__builtin_ia32_pblendd256">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_i32_ty], [IntrNoMem]>; +} + +// Vector load with broadcast +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx2_vbroadcast_ss_ps : + GCCBuiltin<"__builtin_ia32_vbroadcastss_ps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_avx2_vbroadcast_sd_pd_256 : + GCCBuiltin<"__builtin_ia32_vbroadcastsd_pd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_avx2_vbroadcast_ss_ps_256 : + GCCBuiltin<"__builtin_ia32_vbroadcastss_ps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_avx2_vbroadcasti128 : + GCCBuiltin<"__builtin_ia32_vbroadcastsi256">, + Intrinsic<[llvm_v4i64_ty], [llvm_ptr_ty], [IntrReadArgMem]>; + def int_x86_avx2_pbroadcastb_128 : + GCCBuiltin<"__builtin_ia32_pbroadcastb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_avx2_pbroadcastb_256 : + GCCBuiltin<"__builtin_ia32_pbroadcastb256">, + Intrinsic<[llvm_v32i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_avx2_pbroadcastw_128 : + GCCBuiltin<"__builtin_ia32_pbroadcastw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_avx2_pbroadcastw_256 : + GCCBuiltin<"__builtin_ia32_pbroadcastw256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_avx2_pbroadcastd_128 : + GCCBuiltin<"__builtin_ia32_pbroadcastd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_avx2_pbroadcastd_256 : + GCCBuiltin<"__builtin_ia32_pbroadcastd256">, + Intrinsic<[llvm_v8i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_avx2_pbroadcastq_128 : + GCCBuiltin<"__builtin_ia32_pbroadcastq128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; + def int_x86_avx2_pbroadcastq_256 : + GCCBuiltin<"__builtin_ia32_pbroadcastq256">, + Intrinsic<[llvm_v4i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; +} + +// Vector permutation +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx2_permd : GCCBuiltin<"__builtin_ia32_permvarsi256">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], + [IntrNoMem]>; + def int_x86_avx2_permps : GCCBuiltin<"__builtin_ia32_permvarsf256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], + [IntrNoMem]>; + def int_x86_avx2_vperm2i128 : GCCBuiltin<"__builtin_ia32_permti256">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; +} + +// Vector extract and insert +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx2_vextracti128 : GCCBuiltin<"__builtin_ia32_extract128i256">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx2_vinserti128 : GCCBuiltin<"__builtin_ia32_insert128i256">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; +} + +// Conditional load ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx2_maskload_d : GCCBuiltin<"__builtin_ia32_maskloadd">, + Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty, llvm_v4i32_ty], + [IntrReadArgMem]>; + def int_x86_avx2_maskload_q : GCCBuiltin<"__builtin_ia32_maskloadq">, + Intrinsic<[llvm_v2i64_ty], [llvm_ptr_ty, llvm_v2i64_ty], + [IntrReadArgMem]>; + def int_x86_avx2_maskload_d_256 : GCCBuiltin<"__builtin_ia32_maskloadd256">, + Intrinsic<[llvm_v8i32_ty], [llvm_ptr_ty, llvm_v8i32_ty], + [IntrReadArgMem]>; + def int_x86_avx2_maskload_q_256 : GCCBuiltin<"__builtin_ia32_maskloadq256">, + Intrinsic<[llvm_v4i64_ty], [llvm_ptr_ty, llvm_v4i64_ty], + [IntrReadArgMem]>; +} + +// Conditional store ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx2_maskstore_d : GCCBuiltin<"__builtin_ia32_maskstored">, + Intrinsic<[], [llvm_ptr_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx2_maskstore_q : GCCBuiltin<"__builtin_ia32_maskstoreq">, + Intrinsic<[], [llvm_ptr_ty, llvm_v2i64_ty, llvm_v2i64_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx2_maskstore_d_256 : + GCCBuiltin<"__builtin_ia32_maskstored256">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8i32_ty, llvm_v8i32_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx2_maskstore_q_256 : + GCCBuiltin<"__builtin_ia32_maskstoreq256">, + Intrinsic<[], [llvm_ptr_ty, llvm_v4i64_ty, llvm_v4i64_ty], + [IntrReadWriteArgMem]>; +} + +// Variable bit shift ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx2_psllv_d : GCCBuiltin<"__builtin_ia32_psllv4si">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_x86_avx2_psllv_d_256 : GCCBuiltin<"__builtin_ia32_psllv8si">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], + [IntrNoMem]>; + def int_x86_avx2_psllv_q : GCCBuiltin<"__builtin_ia32_psllv2di">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_x86_avx2_psllv_q_256 : GCCBuiltin<"__builtin_ia32_psllv4di">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], + [IntrNoMem]>; + + def int_x86_avx2_psrlv_d : GCCBuiltin<"__builtin_ia32_psrlv4si">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_x86_avx2_psrlv_d_256 : GCCBuiltin<"__builtin_ia32_psrlv8si">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], + [IntrNoMem]>; + def int_x86_avx2_psrlv_q : GCCBuiltin<"__builtin_ia32_psrlv2di">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_x86_avx2_psrlv_q_256 : GCCBuiltin<"__builtin_ia32_psrlv4di">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty], + [IntrNoMem]>; + + def int_x86_avx2_psrav_d : GCCBuiltin<"__builtin_ia32_psrav4si">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_x86_avx2_psrav_d_256 : GCCBuiltin<"__builtin_ia32_psrav8si">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], + [IntrNoMem]>; +} + +// Gather ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx2_gather_d_pd : GCCBuiltin<"__builtin_ia32_gatherd_pd">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v2f64_ty, llvm_i8_ty], + [IntrReadMem]>; + def int_x86_avx2_gather_d_pd_256 : GCCBuiltin<"__builtin_ia32_gatherd_pd256">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4f64_ty, llvm_i8_ty], + [IntrReadMem]>; + def int_x86_avx2_gather_q_pd : GCCBuiltin<"__builtin_ia32_gatherq_pd">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v2f64_ty, llvm_i8_ty], + [IntrReadMem]>; + def int_x86_avx2_gather_q_pd_256 : GCCBuiltin<"__builtin_ia32_gatherq_pd256">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4f64_ty, llvm_i8_ty], + [IntrReadMem]>; + def int_x86_avx2_gather_d_ps : GCCBuiltin<"__builtin_ia32_gatherd_ps">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrReadMem]>; + def int_x86_avx2_gather_d_ps_256 : GCCBuiltin<"__builtin_ia32_gatherd_ps256">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_v8f32_ty, llvm_i8_ty], + [IntrReadMem]>; + def int_x86_avx2_gather_q_ps : GCCBuiltin<"__builtin_ia32_gatherq_ps">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrReadMem]>; + def int_x86_avx2_gather_q_ps_256 : GCCBuiltin<"__builtin_ia32_gatherq_ps256">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrReadMem]>; + + def int_x86_avx2_gather_d_q : GCCBuiltin<"__builtin_ia32_gatherd_q">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v2i64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrReadMem]>; + def int_x86_avx2_gather_d_q_256 : GCCBuiltin<"__builtin_ia32_gatherd_q256">, + Intrinsic<[llvm_v4i64_ty], + [llvm_v4i64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrReadMem]>; + def int_x86_avx2_gather_q_q : GCCBuiltin<"__builtin_ia32_gatherq_q">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v2i64_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrReadMem]>; + def int_x86_avx2_gather_q_q_256 : GCCBuiltin<"__builtin_ia32_gatherq_q256">, + Intrinsic<[llvm_v4i64_ty], + [llvm_v4i64_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrReadMem]>; + def int_x86_avx2_gather_d_d : GCCBuiltin<"__builtin_ia32_gatherd_d">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4i32_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrReadMem]>; + def int_x86_avx2_gather_d_d_256 : GCCBuiltin<"__builtin_ia32_gatherd_d256">, + Intrinsic<[llvm_v8i32_ty], + [llvm_v8i32_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], + [IntrReadMem]>; + def int_x86_avx2_gather_q_d : GCCBuiltin<"__builtin_ia32_gatherq_d">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4i32_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrReadMem]>; + def int_x86_avx2_gather_q_d_256 : GCCBuiltin<"__builtin_ia32_gatherq_d256">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4i32_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrReadMem]>; +} + +// Misc. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx2_pmovmskb : GCCBuiltin<"__builtin_ia32_pmovmskb256">, + Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty], [IntrNoMem]>; + def int_x86_avx2_pshuf_b : GCCBuiltin<"__builtin_ia32_pshufb256">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, + llvm_v32i8_ty], [IntrNoMem]>; + def int_x86_avx2_mpsadbw : GCCBuiltin<"__builtin_ia32_mpsadbw256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty, + llvm_i32_ty], [IntrNoMem, Commutative]>; + def int_x86_avx2_movntdqa : GCCBuiltin<"__builtin_ia32_movntdqa256">, + Intrinsic<[llvm_v4i64_ty], [llvm_ptr_ty], [IntrReadMem]>; +} + +//===----------------------------------------------------------------------===// +// FMA3 and FMA4 + +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_fma_vfmadd_ss : GCCBuiltin<"__builtin_ia32_vfmaddss">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfmadd_sd : GCCBuiltin<"__builtin_ia32_vfmaddsd">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], + [IntrNoMem]>; + def int_x86_fma_vfmadd_ps : GCCBuiltin<"__builtin_ia32_vfmaddps">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfmadd_pd : GCCBuiltin<"__builtin_ia32_vfmaddpd">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], + [IntrNoMem]>; + def int_x86_fma_vfmadd_ps_256 : GCCBuiltin<"__builtin_ia32_vfmaddps256">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfmadd_pd_256 : GCCBuiltin<"__builtin_ia32_vfmaddpd256">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], + [IntrNoMem]>; + def int_x86_fma_vfmsub_ss : GCCBuiltin<"__builtin_ia32_vfmsubss">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfmsub_sd : GCCBuiltin<"__builtin_ia32_vfmsubsd">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], + [IntrNoMem]>; + def int_x86_fma_vfmsub_ps : GCCBuiltin<"__builtin_ia32_vfmsubps">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfmsub_pd : GCCBuiltin<"__builtin_ia32_vfmsubpd">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], + [IntrNoMem]>; + def int_x86_fma_vfmsub_ps_256 : GCCBuiltin<"__builtin_ia32_vfmsubps256">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfmsub_pd_256 : GCCBuiltin<"__builtin_ia32_vfmsubpd256">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], + [IntrNoMem]>; + def int_x86_fma_vfnmadd_ss : GCCBuiltin<"__builtin_ia32_vfnmaddss">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfnmadd_sd : GCCBuiltin<"__builtin_ia32_vfnmaddsd">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], + [IntrNoMem]>; + def int_x86_fma_vfnmadd_ps : GCCBuiltin<"__builtin_ia32_vfnmaddps">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfnmadd_pd : GCCBuiltin<"__builtin_ia32_vfnmaddpd">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], + [IntrNoMem]>; + def int_x86_fma_vfnmadd_ps_256 : GCCBuiltin<"__builtin_ia32_vfnmaddps256">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfnmadd_pd_256 : GCCBuiltin<"__builtin_ia32_vfnmaddpd256">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], + [IntrNoMem]>; + def int_x86_fma_vfnmsub_ss : GCCBuiltin<"__builtin_ia32_vfnmsubss">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfnmsub_sd : GCCBuiltin<"__builtin_ia32_vfnmsubsd">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], + [IntrNoMem]>; + def int_x86_fma_vfnmsub_ps : GCCBuiltin<"__builtin_ia32_vfnmsubps">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfnmsub_pd : GCCBuiltin<"__builtin_ia32_vfnmsubpd">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], + [IntrNoMem]>; + def int_x86_fma_vfnmsub_ps_256 : GCCBuiltin<"__builtin_ia32_vfnmsubps256">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfnmsub_pd_256 : GCCBuiltin<"__builtin_ia32_vfnmsubpd256">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], + [IntrNoMem]>; + def int_x86_fma_vfmaddsub_ps : GCCBuiltin<"__builtin_ia32_vfmaddsubps">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfmaddsub_pd : GCCBuiltin<"__builtin_ia32_vfmaddsubpd">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], + [IntrNoMem]>; + def int_x86_fma_vfmaddsub_ps_256 : + GCCBuiltin<"__builtin_ia32_vfmaddsubps256">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfmaddsub_pd_256 : + GCCBuiltin<"__builtin_ia32_vfmaddsubpd256">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], + [IntrNoMem]>; + def int_x86_fma_vfmsubadd_ps : GCCBuiltin<"__builtin_ia32_vfmsubaddps">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfmsubadd_pd : GCCBuiltin<"__builtin_ia32_vfmsubaddpd">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], + [IntrNoMem]>; + def int_x86_fma_vfmsubadd_ps_256 : + GCCBuiltin<"__builtin_ia32_vfmsubaddps256">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfmsubadd_pd_256 : + GCCBuiltin<"__builtin_ia32_vfmsubaddpd256">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], + [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// XOP + + def int_x86_xop_vpermil2pd : GCCBuiltin<"__builtin_ia32_vpermil2pd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_xop_vpermil2pd_256 : + GCCBuiltin<"__builtin_ia32_vpermil2pd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_xop_vpermil2ps : GCCBuiltin<"__builtin_ia32_vpermil2ps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_xop_vpermil2ps_256 : + GCCBuiltin<"__builtin_ia32_vpermil2ps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_xop_vfrcz_pd : GCCBuiltin<"__builtin_ia32_vfrczpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_xop_vfrcz_ps : GCCBuiltin<"__builtin_ia32_vfrczps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_xop_vfrcz_sd : GCCBuiltin<"__builtin_ia32_vfrczsd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_xop_vfrcz_ss : GCCBuiltin<"__builtin_ia32_vfrczss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_xop_vfrcz_pd_256 : GCCBuiltin<"__builtin_ia32_vfrczpd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_xop_vfrcz_ps_256 : GCCBuiltin<"__builtin_ia32_vfrczps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty], [IntrNoMem]>; + + def int_x86_xop_vpcmov : + GCCBuiltin<"__builtin_ia32_vpcmov">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_x86_xop_vpcmov_256 : + GCCBuiltin<"__builtin_ia32_vpcmov_256">, + Intrinsic<[llvm_v4i64_ty], + [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty], + [IntrNoMem]>; + + def int_x86_xop_vpcomb : GCCBuiltin<"__builtin_ia32_vpcomb">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_xop_vpcomw : GCCBuiltin<"__builtin_ia32_vpcomw">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_xop_vpcomd : GCCBuiltin<"__builtin_ia32_vpcomd">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_xop_vpcomq : GCCBuiltin<"__builtin_ia32_vpcomq">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_xop_vpcomub : GCCBuiltin<"__builtin_ia32_vpcomub">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_xop_vpcomuw : GCCBuiltin<"__builtin_ia32_vpcomuw">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_xop_vpcomud : GCCBuiltin<"__builtin_ia32_vpcomud">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_xop_vpcomuq : GCCBuiltin<"__builtin_ia32_vpcomuq">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_i8_ty], [IntrNoMem]>; + + def int_x86_xop_vphaddbd : + GCCBuiltin<"__builtin_ia32_vphaddbd">, + Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_xop_vphaddbq : + GCCBuiltin<"__builtin_ia32_vphaddbq">, + Intrinsic<[llvm_v2i64_ty], [llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_xop_vphaddbw : + GCCBuiltin<"__builtin_ia32_vphaddbw">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_xop_vphadddq : + GCCBuiltin<"__builtin_ia32_vphadddq">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_xop_vphaddubd : + GCCBuiltin<"__builtin_ia32_vphaddubd">, + Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_xop_vphaddubq : + GCCBuiltin<"__builtin_ia32_vphaddubq">, + Intrinsic<[llvm_v2i64_ty], [llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_xop_vphaddubw : + GCCBuiltin<"__builtin_ia32_vphaddubw">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_xop_vphaddudq : + GCCBuiltin<"__builtin_ia32_vphaddudq">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_xop_vphadduwd : + GCCBuiltin<"__builtin_ia32_vphadduwd">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_xop_vphadduwq : + GCCBuiltin<"__builtin_ia32_vphadduwq">, + Intrinsic<[llvm_v2i64_ty], [llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_xop_vphaddwd : + GCCBuiltin<"__builtin_ia32_vphaddwd">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_xop_vphaddwq : + GCCBuiltin<"__builtin_ia32_vphaddwq">, + Intrinsic<[llvm_v2i64_ty], [llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_xop_vphsubbw : + GCCBuiltin<"__builtin_ia32_vphsubbw">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_xop_vphsubdq : + GCCBuiltin<"__builtin_ia32_vphsubdq">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_xop_vphsubwd : + GCCBuiltin<"__builtin_ia32_vphsubwd">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_xop_vpmacsdd : + GCCBuiltin<"__builtin_ia32_vpmacsdd">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_x86_xop_vpmacsdqh : + GCCBuiltin<"__builtin_ia32_vpmacsdqh">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_x86_xop_vpmacsdql : + GCCBuiltin<"__builtin_ia32_vpmacsdql">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_x86_xop_vpmacssdd : + GCCBuiltin<"__builtin_ia32_vpmacssdd">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_x86_xop_vpmacssdqh : + GCCBuiltin<"__builtin_ia32_vpmacssdqh">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_x86_xop_vpmacssdql : + GCCBuiltin<"__builtin_ia32_vpmacssdql">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_x86_xop_vpmacsswd : + GCCBuiltin<"__builtin_ia32_vpmacsswd">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_x86_xop_vpmacssww : + GCCBuiltin<"__builtin_ia32_vpmacssww">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_x86_xop_vpmacswd : + GCCBuiltin<"__builtin_ia32_vpmacswd">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_x86_xop_vpmacsww : + GCCBuiltin<"__builtin_ia32_vpmacsww">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_x86_xop_vpmadcsswd : + GCCBuiltin<"__builtin_ia32_vpmadcsswd">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_x86_xop_vpmadcswd : + GCCBuiltin<"__builtin_ia32_vpmadcswd">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_x86_xop_vpperm : + GCCBuiltin<"__builtin_ia32_vpperm">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + + def int_x86_xop_vprotb : GCCBuiltin<"__builtin_ia32_vprotb">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_xop_vprotd : GCCBuiltin<"__builtin_ia32_vprotd">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_x86_xop_vprotq : GCCBuiltin<"__builtin_ia32_vprotq">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_x86_xop_vprotw : GCCBuiltin<"__builtin_ia32_vprotw">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_x86_xop_vprotbi : GCCBuiltin<"__builtin_ia32_vprotbi">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_xop_vprotdi : GCCBuiltin<"__builtin_ia32_vprotdi">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_xop_vprotqi : GCCBuiltin<"__builtin_ia32_vprotqi">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_xop_vprotwi : GCCBuiltin<"__builtin_ia32_vprotwi">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_xop_vpshab : + GCCBuiltin<"__builtin_ia32_vpshab">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_xop_vpshad : + GCCBuiltin<"__builtin_ia32_vpshad">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_x86_xop_vpshaq : + GCCBuiltin<"__builtin_ia32_vpshaq">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_x86_xop_vpshaw : + GCCBuiltin<"__builtin_ia32_vpshaw">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_x86_xop_vpshlb : + GCCBuiltin<"__builtin_ia32_vpshlb">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_xop_vpshld : + GCCBuiltin<"__builtin_ia32_vpshld">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_x86_xop_vpshlq : + GCCBuiltin<"__builtin_ia32_vpshlq">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_x86_xop_vpshlw : + GCCBuiltin<"__builtin_ia32_vpshlw">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + +//===----------------------------------------------------------------------===// +// MMX + +// Empty MMX state op. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_mmx_emms : GCCBuiltin<"__builtin_ia32_emms">, + Intrinsic<[], [], []>; + def int_x86_mmx_femms : GCCBuiltin<"__builtin_ia32_femms">, + Intrinsic<[], [], []>; +} + +// Integer arithmetic ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + // Addition + def int_x86_mmx_padd_b : GCCBuiltin<"__builtin_ia32_paddb">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_mmx_padd_w : GCCBuiltin<"__builtin_ia32_paddw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_mmx_padd_d : GCCBuiltin<"__builtin_ia32_paddd">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_mmx_padd_q : GCCBuiltin<"__builtin_ia32_paddq">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + + def int_x86_mmx_padds_b : GCCBuiltin<"__builtin_ia32_paddsb">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + def int_x86_mmx_padds_w : GCCBuiltin<"__builtin_ia32_paddsw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + + def int_x86_mmx_paddus_b : GCCBuiltin<"__builtin_ia32_paddusb">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + def int_x86_mmx_paddus_w : GCCBuiltin<"__builtin_ia32_paddusw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + + // Subtraction + def int_x86_mmx_psub_b : GCCBuiltin<"__builtin_ia32_psubb">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_mmx_psub_w : GCCBuiltin<"__builtin_ia32_psubw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_mmx_psub_d : GCCBuiltin<"__builtin_ia32_psubd">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_mmx_psub_q : GCCBuiltin<"__builtin_ia32_psubq">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + + def int_x86_mmx_psubs_b : GCCBuiltin<"__builtin_ia32_psubsb">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_mmx_psubs_w : GCCBuiltin<"__builtin_ia32_psubsw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + + def int_x86_mmx_psubus_b : GCCBuiltin<"__builtin_ia32_psubusb">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_mmx_psubus_w : GCCBuiltin<"__builtin_ia32_psubusw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + + // Multiplication + def int_x86_mmx_pmulh_w : GCCBuiltin<"__builtin_ia32_pmulhw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + def int_x86_mmx_pmull_w : GCCBuiltin<"__builtin_ia32_pmullw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + def int_x86_mmx_pmulhu_w : GCCBuiltin<"__builtin_ia32_pmulhuw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + def int_x86_mmx_pmulu_dq : GCCBuiltin<"__builtin_ia32_pmuludq">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + def int_x86_mmx_pmadd_wd : GCCBuiltin<"__builtin_ia32_pmaddwd">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + + // Bitwise operations + def int_x86_mmx_pand : GCCBuiltin<"__builtin_ia32_pand">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_mmx_pandn : GCCBuiltin<"__builtin_ia32_pandn">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_mmx_por : GCCBuiltin<"__builtin_ia32_por">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_mmx_pxor : GCCBuiltin<"__builtin_ia32_pxor">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + + // Averages + def int_x86_mmx_pavg_b : GCCBuiltin<"__builtin_ia32_pavgb">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + def int_x86_mmx_pavg_w : GCCBuiltin<"__builtin_ia32_pavgw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + + // Maximum + def int_x86_mmx_pmaxu_b : GCCBuiltin<"__builtin_ia32_pmaxub">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + def int_x86_mmx_pmaxs_w : GCCBuiltin<"__builtin_ia32_pmaxsw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + + // Minimum + def int_x86_mmx_pminu_b : GCCBuiltin<"__builtin_ia32_pminub">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + def int_x86_mmx_pmins_w : GCCBuiltin<"__builtin_ia32_pminsw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + + // Packed sum of absolute differences + def int_x86_mmx_psad_bw : GCCBuiltin<"__builtin_ia32_psadbw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; +} + +// Integer shift ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + // Shift left logical + def int_x86_mmx_psll_w : GCCBuiltin<"__builtin_ia32_psllw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_mmx_psll_d : GCCBuiltin<"__builtin_ia32_pslld">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_mmx_psll_q : GCCBuiltin<"__builtin_ia32_psllq">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + + def int_x86_mmx_psrl_w : GCCBuiltin<"__builtin_ia32_psrlw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_mmx_psrl_d : GCCBuiltin<"__builtin_ia32_psrld">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_mmx_psrl_q : GCCBuiltin<"__builtin_ia32_psrlq">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + + def int_x86_mmx_psra_w : GCCBuiltin<"__builtin_ia32_psraw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_mmx_psra_d : GCCBuiltin<"__builtin_ia32_psrad">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + + def int_x86_mmx_pslli_w : GCCBuiltin<"__builtin_ia32_psllwi">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_mmx_pslli_d : GCCBuiltin<"__builtin_ia32_pslldi">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_mmx_pslli_q : GCCBuiltin<"__builtin_ia32_psllqi">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_mmx_psrli_w : GCCBuiltin<"__builtin_ia32_psrlwi">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_mmx_psrli_d : GCCBuiltin<"__builtin_ia32_psrldi">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_mmx_psrli_q : GCCBuiltin<"__builtin_ia32_psrlqi">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_mmx_psrai_w : GCCBuiltin<"__builtin_ia32_psrawi">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_mmx_psrai_d : GCCBuiltin<"__builtin_ia32_psradi">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_i32_ty], [IntrNoMem]>; +} + +// Pack ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_mmx_packsswb : GCCBuiltin<"__builtin_ia32_packsswb">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_mmx_packssdw : GCCBuiltin<"__builtin_ia32_packssdw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_mmx_packuswb : GCCBuiltin<"__builtin_ia32_packuswb">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; +} + +// Unpacking ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_mmx_punpckhbw : GCCBuiltin<"__builtin_ia32_punpckhbw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_mmx_punpckhwd : GCCBuiltin<"__builtin_ia32_punpckhwd">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_mmx_punpckhdq : GCCBuiltin<"__builtin_ia32_punpckhdq">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_mmx_punpcklbw : GCCBuiltin<"__builtin_ia32_punpcklbw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_mmx_punpcklwd : GCCBuiltin<"__builtin_ia32_punpcklwd">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_mmx_punpckldq : GCCBuiltin<"__builtin_ia32_punpckldq">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; +} + +// Integer comparison ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_mmx_pcmpeq_b : GCCBuiltin<"__builtin_ia32_pcmpeqb">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + def int_x86_mmx_pcmpeq_w : GCCBuiltin<"__builtin_ia32_pcmpeqw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + def int_x86_mmx_pcmpeq_d : GCCBuiltin<"__builtin_ia32_pcmpeqd">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + + def int_x86_mmx_pcmpgt_b : GCCBuiltin<"__builtin_ia32_pcmpgtb">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_mmx_pcmpgt_w : GCCBuiltin<"__builtin_ia32_pcmpgtw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_mmx_pcmpgt_d : GCCBuiltin<"__builtin_ia32_pcmpgtd">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; +} + +// Misc. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_mmx_maskmovq : GCCBuiltin<"__builtin_ia32_maskmovq">, + Intrinsic<[], [llvm_x86mmx_ty, llvm_x86mmx_ty, llvm_ptr_ty], []>; + + def int_x86_mmx_pmovmskb : GCCBuiltin<"__builtin_ia32_pmovmskb">, + Intrinsic<[llvm_i32_ty], [llvm_x86mmx_ty], [IntrNoMem]>; + + def int_x86_mmx_movnt_dq : GCCBuiltin<"__builtin_ia32_movntq">, + Intrinsic<[], [llvm_ptrx86mmx_ty, llvm_x86mmx_ty], []>; + + def int_x86_mmx_palignr_b : GCCBuiltin<"__builtin_ia32_palignr">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty, llvm_i8_ty], [IntrNoMem]>; + + def int_x86_mmx_pextr_w : GCCBuiltin<"__builtin_ia32_vec_ext_v4hi">, + Intrinsic<[llvm_i32_ty], [llvm_x86mmx_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_mmx_pinsr_w : GCCBuiltin<"__builtin_ia32_vec_set_v4hi">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// BMI + +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_bmi_bextr_32 : GCCBuiltin<"__builtin_ia32_bextr_u32">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_bmi_bextr_64 : GCCBuiltin<"__builtin_ia32_bextr_u64">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_bmi_bzhi_32 : GCCBuiltin<"__builtin_ia32_bzhi_si">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_bmi_bzhi_64 : GCCBuiltin<"__builtin_ia32_bzhi_di">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_bmi_pdep_32 : GCCBuiltin<"__builtin_ia32_pdep_si">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_bmi_pdep_64 : GCCBuiltin<"__builtin_ia32_pdep_di">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_bmi_pext_32 : GCCBuiltin<"__builtin_ia32_pext_si">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_bmi_pext_64 : GCCBuiltin<"__builtin_ia32_pext_di">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// FS/GS Base + +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_rdfsbase_32 : GCCBuiltin<"__builtin_ia32_rdfsbase32">, + Intrinsic<[llvm_i32_ty], []>; + def int_x86_rdgsbase_32 : GCCBuiltin<"__builtin_ia32_rdgsbase32">, + Intrinsic<[llvm_i32_ty], []>; + def int_x86_rdfsbase_64 : GCCBuiltin<"__builtin_ia32_rdfsbase64">, + Intrinsic<[llvm_i64_ty], []>; + def int_x86_rdgsbase_64 : GCCBuiltin<"__builtin_ia32_rdgsbase64">, + Intrinsic<[llvm_i64_ty], []>; + def int_x86_wrfsbase_32 : GCCBuiltin<"__builtin_ia32_wrfsbase32">, + Intrinsic<[], [llvm_i32_ty]>; + def int_x86_wrgsbase_32 : GCCBuiltin<"__builtin_ia32_wrgsbase32">, + Intrinsic<[], [llvm_i32_ty]>; + def int_x86_wrfsbase_64 : GCCBuiltin<"__builtin_ia32_wrfsbase64">, + Intrinsic<[], [llvm_i64_ty]>; + def int_x86_wrgsbase_64 : GCCBuiltin<"__builtin_ia32_wrgsbase64">, + Intrinsic<[], [llvm_i64_ty]>; +} + +//===----------------------------------------------------------------------===// +// Half float conversion + +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_vcvtph2ps_128 : GCCBuiltin<"__builtin_ia32_vcvtph2ps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_vcvtph2ps_256 : GCCBuiltin<"__builtin_ia32_vcvtph2ps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_vcvtps2ph_128 : GCCBuiltin<"__builtin_ia32_vcvtps2ph">, + Intrinsic<[llvm_v8i16_ty], [llvm_v4f32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_vcvtps2ph_256 : GCCBuiltin<"__builtin_ia32_vcvtps2ph256">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8f32_ty, llvm_i32_ty], + [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// RDRAND intrinsics - Return a random value and whether it is valid. +// RDSEED intrinsics - Return a NIST SP800-90B & C compliant random value and +// whether it is valid. + +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + // These are declared side-effecting so they don't get eliminated by CSE or + // LICM. + def int_x86_rdrand_16 : Intrinsic<[llvm_i16_ty, llvm_i32_ty], [], []>; + def int_x86_rdrand_32 : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [], []>; + def int_x86_rdrand_64 : Intrinsic<[llvm_i64_ty, llvm_i32_ty], [], []>; + def int_x86_rdseed_16 : Intrinsic<[llvm_i16_ty, llvm_i32_ty], [], []>; + def int_x86_rdseed_32 : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [], []>; + def int_x86_rdseed_64 : Intrinsic<[llvm_i64_ty, llvm_i32_ty], [], []>; +} + +//===----------------------------------------------------------------------===// +// RTM intrinsics. Transactional Memory support. + +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_xbegin : GCCBuiltin<"__builtin_ia32_xbegin">, + Intrinsic<[llvm_i32_ty], [], []>; + def int_x86_xend : GCCBuiltin<"__builtin_ia32_xend">, + Intrinsic<[], [], []>; + def int_x86_xabort : GCCBuiltin<"__builtin_ia32_xabort">, + Intrinsic<[], [llvm_i8_ty], [IntrNoReturn]>; + def int_x86_xtest : GCCBuiltin<"__builtin_ia32_xtest">, + Intrinsic<[llvm_i32_ty], [], []>; +} diff --git a/include/llvm/IR/IntrinsicsXCore.td b/include/llvm/IR/IntrinsicsXCore.td new file mode 100644 index 0000000..a481313 --- /dev/null +++ b/include/llvm/IR/IntrinsicsXCore.td @@ -0,0 +1,114 @@ +//==- IntrinsicsXCore.td - XCore intrinsics -*- tablegen -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the XCore-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +let TargetPrefix = "xcore" in { // All intrinsics start with "llvm.xcore.". + // Miscellaneous instructions. + def int_xcore_bitrev : Intrinsic<[llvm_i32_ty],[llvm_i32_ty],[IntrNoMem]>; + def int_xcore_crc8 : Intrinsic<[llvm_i32_ty, llvm_i32_ty], + [llvm_i32_ty,llvm_i32_ty,llvm_i32_ty], + [IntrNoMem]>; + def int_xcore_crc32 : Intrinsic<[llvm_i32_ty], + [llvm_i32_ty,llvm_i32_ty,llvm_i32_ty], + [IntrNoMem]>; + def int_xcore_sext : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_xcore_zext : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_xcore_getid : Intrinsic<[llvm_i32_ty],[],[IntrNoMem]>; + def int_xcore_getps : Intrinsic<[llvm_i32_ty],[llvm_i32_ty]>; + def int_xcore_setps : Intrinsic<[],[llvm_i32_ty, llvm_i32_ty]>; + def int_xcore_geted : Intrinsic<[llvm_i32_ty],[]>; + def int_xcore_getet : Intrinsic<[llvm_i32_ty],[]>; + def int_xcore_setsr : Intrinsic<[],[llvm_i32_ty]>; + def int_xcore_clrsr : Intrinsic<[],[llvm_i32_ty]>; + + // Resource instructions. + def int_xcore_getr : Intrinsic<[llvm_anyptr_ty],[llvm_i32_ty]>; + def int_xcore_freer : Intrinsic<[],[llvm_anyptr_ty], + [NoCapture<0>]>; + def int_xcore_in : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty],[NoCapture<0>]>; + def int_xcore_int : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty], + [NoCapture<0>]>; + def int_xcore_inct : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty], + [NoCapture<0>]>; + def int_xcore_out : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_outt : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_outct : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_chkct : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_testct : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty], + [NoCapture<0>]>; + def int_xcore_testwct : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty], + [NoCapture<0>]>; + def int_xcore_setd : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_setc : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_inshr : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_outshr : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_setpt : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_getts : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty], + [NoCapture<0>]>; + def int_xcore_syncr : Intrinsic<[],[llvm_anyptr_ty], + [NoCapture<0>]>; + def int_xcore_settw : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_setv : Intrinsic<[],[llvm_anyptr_ty, llvm_ptr_ty], + [NoCapture<0>]>; + def int_xcore_setev : Intrinsic<[],[llvm_anyptr_ty, llvm_ptr_ty], + [NoCapture<0>]>; + def int_xcore_eeu : Intrinsic<[],[llvm_anyptr_ty], [NoCapture<0>]>; + def int_xcore_setclk : Intrinsic<[],[llvm_anyptr_ty, llvm_anyptr_ty], + [NoCapture<0>, NoCapture<1>]>; + def int_xcore_setrdy : Intrinsic<[],[llvm_anyptr_ty, llvm_anyptr_ty], + [NoCapture<0>, NoCapture<1>]>; + def int_xcore_setpsc : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_peek : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty], + [NoCapture<0>]>; + def int_xcore_endin : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty], + [NoCapture<0>]>; + + // Intrinsics for events. + def int_xcore_waitevent : Intrinsic<[llvm_ptr_ty],[], [IntrReadMem]>; + + // If any of the resources owned by the thread are ready this returns the + // vector of one of the ready resources. If no resources owned by the thread + // are ready then the operand passed to the intrinsic is returned. + def int_xcore_checkevent : Intrinsic<[llvm_ptr_ty],[llvm_ptr_ty]>; + + def int_xcore_clre : Intrinsic<[],[],[]>; + + // Intrinsics for threads. + def int_xcore_getst : Intrinsic <[llvm_anyptr_ty],[llvm_anyptr_ty], + [NoCapture<0>]>; + def int_xcore_msync : Intrinsic <[],[llvm_anyptr_ty], [NoCapture<0>]>; + def int_xcore_ssync : Intrinsic <[],[]>; + def int_xcore_mjoin : Intrinsic <[],[llvm_anyptr_ty], [NoCapture<0>]>; + def int_xcore_initsp : Intrinsic <[],[llvm_anyptr_ty, llvm_ptr_ty], + [NoCapture<0>]>; + def int_xcore_initpc : Intrinsic <[],[llvm_anyptr_ty, llvm_ptr_ty], + [NoCapture<0>]>; + def int_xcore_initlr : Intrinsic <[],[llvm_anyptr_ty, llvm_ptr_ty], + [NoCapture<0>]>; + def int_xcore_initcp : Intrinsic <[],[llvm_anyptr_ty, llvm_ptr_ty], + [NoCapture<0>]>; + def int_xcore_initdp : Intrinsic <[],[llvm_anyptr_ty, llvm_ptr_ty], + [NoCapture<0>]>; +} diff --git a/include/llvm/IR/LLVMContext.h b/include/llvm/IR/LLVMContext.h new file mode 100644 index 0000000..ae81e5b --- /dev/null +++ b/include/llvm/IR/LLVMContext.h @@ -0,0 +1,114 @@ +//===-- llvm/LLVMContext.h - Class for managing "global" state --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares LLVMContext, a container of "global" state in LLVM, such +// as the global type and constant uniquing tables. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_LLVMCONTEXT_H +#define LLVM_IR_LLVMCONTEXT_H + +#include "llvm/Support/Compiler.h" + +namespace llvm { + +class LLVMContextImpl; +class StringRef; +class Twine; +class Instruction; +class Module; +class SMDiagnostic; +template <typename T> class SmallVectorImpl; + +/// This is an important class for using LLVM in a threaded context. It +/// (opaquely) owns and manages the core "global" data of LLVM's core +/// infrastructure, including the type and constant uniquing tables. +/// LLVMContext itself provides no locking guarantees, so you should be careful +/// to have one context per thread. +class LLVMContext { +public: + LLVMContextImpl *const pImpl; + LLVMContext(); + ~LLVMContext(); + + // Pinned metadata names, which always have the same value. This is a + // compile-time performance optimization, not a correctness optimization. + enum { + MD_dbg = 0, // "dbg" + MD_tbaa = 1, // "tbaa" + MD_prof = 2, // "prof" + MD_fpmath = 3, // "fpmath" + MD_range = 4, // "range" + MD_tbaa_struct = 5, // "tbaa.struct" + MD_invariant_load = 6 // "invariant.load" + }; + + /// getMDKindID - Return a unique non-zero ID for the specified metadata kind. + /// This ID is uniqued across modules in the current LLVMContext. + unsigned getMDKindID(StringRef Name) const; + + /// getMDKindNames - Populate client supplied SmallVector with the name for + /// custom metadata IDs registered in this LLVMContext. + void getMDKindNames(SmallVectorImpl<StringRef> &Result) const; + + + typedef void (*InlineAsmDiagHandlerTy)(const SMDiagnostic&, void *Context, + unsigned LocCookie); + + /// setInlineAsmDiagnosticHandler - This method sets a handler that is invoked + /// when problems with inline asm are detected by the backend. The first + /// argument is a function pointer and the second is a context pointer that + /// gets passed into the DiagHandler. + /// + /// LLVMContext doesn't take ownership or interpret either of these + /// pointers. + void setInlineAsmDiagnosticHandler(InlineAsmDiagHandlerTy DiagHandler, + void *DiagContext = 0); + + /// getInlineAsmDiagnosticHandler - Return the diagnostic handler set by + /// setInlineAsmDiagnosticHandler. + InlineAsmDiagHandlerTy getInlineAsmDiagnosticHandler() const; + + /// getInlineAsmDiagnosticContext - Return the diagnostic context set by + /// setInlineAsmDiagnosticHandler. + void *getInlineAsmDiagnosticContext() const; + + + /// emitError - Emit an error message to the currently installed error handler + /// with optional location information. This function returns, so code should + /// be prepared to drop the erroneous construct on the floor and "not crash". + /// The generated code need not be correct. The error message will be + /// implicitly prefixed with "error: " and should not end with a ".". + void emitError(unsigned LocCookie, const Twine &ErrorStr); + void emitError(const Instruction *I, const Twine &ErrorStr); + void emitError(const Twine &ErrorStr); + +private: + LLVMContext(LLVMContext&) LLVM_DELETED_FUNCTION; + void operator=(LLVMContext&) LLVM_DELETED_FUNCTION; + + /// addModule - Register a module as being instantiated in this context. If + /// the context is deleted, the module will be deleted as well. + void addModule(Module*); + + /// removeModule - Unregister a module from this context. + void removeModule(Module*); + + // Module needs access to the add/removeModule methods. + friend class Module; +}; + +/// getGlobalContext - Returns a global context. This is for LLVM clients that +/// only care about operating on a single thread. +extern LLVMContext &getGlobalContext(); + +} + +#endif diff --git a/include/llvm/IR/MDBuilder.h b/include/llvm/IR/MDBuilder.h new file mode 100644 index 0000000..a1e3fb1 --- /dev/null +++ b/include/llvm/IR/MDBuilder.h @@ -0,0 +1,186 @@ +//===---- llvm/MDBuilder.h - Builder for LLVM metadata ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the MDBuilder class, which is used as a convenient way to +// create LLVM metadata with a consistent and simplified interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_MDBUILDER_H +#define LLVM_IR_MDBUILDER_H + +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Metadata.h" + +namespace llvm { + +class APInt; +class LLVMContext; + +class MDBuilder { + LLVMContext &Context; + +public: + MDBuilder(LLVMContext &context) : Context(context) {} + + /// \brief Return the given string as metadata. + MDString *createString(StringRef Str) { + return MDString::get(Context, Str); + } + + //===------------------------------------------------------------------===// + // FPMath metadata. + //===------------------------------------------------------------------===// + + /// \brief Return metadata with the given settings. The special value 0.0 + /// for the Accuracy parameter indicates the default (maximal precision) + /// setting. + MDNode *createFPMath(float Accuracy) { + if (Accuracy == 0.0) + return 0; + assert(Accuracy > 0.0 && "Invalid fpmath accuracy!"); + Value *Op = ConstantFP::get(Type::getFloatTy(Context), Accuracy); + return MDNode::get(Context, Op); + } + + //===------------------------------------------------------------------===// + // Prof metadata. + //===------------------------------------------------------------------===// + + /// \brief Return metadata containing two branch weights. + MDNode *createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight) { + uint32_t Weights[] = { TrueWeight, FalseWeight }; + return createBranchWeights(Weights); + } + + /// \brief Return metadata containing a number of branch weights. + MDNode *createBranchWeights(ArrayRef<uint32_t> Weights) { + assert(Weights.size() >= 2 && "Need at least two branch weights!"); + + SmallVector<Value *, 4> Vals(Weights.size()+1); + Vals[0] = createString("branch_weights"); + + Type *Int32Ty = Type::getInt32Ty(Context); + for (unsigned i = 0, e = Weights.size(); i != e; ++i) + Vals[i+1] = ConstantInt::get(Int32Ty, Weights[i]); + + return MDNode::get(Context, Vals); + } + + //===------------------------------------------------------------------===// + // Range metadata. + //===------------------------------------------------------------------===// + + /// \brief Return metadata describing the range [Lo, Hi). + MDNode *createRange(const APInt &Lo, const APInt &Hi) { + assert(Lo.getBitWidth() == Hi.getBitWidth() && "Mismatched bitwidths!"); + // If the range is everything then it is useless. + if (Hi == Lo) + return 0; + + // Return the range [Lo, Hi). + Type *Ty = IntegerType::get(Context, Lo.getBitWidth()); + Value *Range[2] = { ConstantInt::get(Ty, Lo), ConstantInt::get(Ty, Hi) }; + return MDNode::get(Context, Range); + } + + + //===------------------------------------------------------------------===// + // TBAA metadata. + //===------------------------------------------------------------------===// + + /// \brief Return metadata appropriate for a TBAA root node. Each returned + /// node is distinct from all other metadata and will never be identified + /// (uniqued) with anything else. + MDNode *createAnonymousTBAARoot() { + // To ensure uniqueness the root node is self-referential. + MDNode *Dummy = MDNode::getTemporary(Context, ArrayRef<Value*>()); + MDNode *Root = MDNode::get(Context, Dummy); + // At this point we have + // !0 = metadata !{} <- dummy + // !1 = metadata !{metadata !0} <- root + // Replace the dummy operand with the root node itself and delete the dummy. + Root->replaceOperandWith(0, Root); + MDNode::deleteTemporary(Dummy); + // We now have + // !1 = metadata !{metadata !1} <- self-referential root + return Root; + } + + /// \brief Return metadata appropriate for a TBAA root node with the given + /// name. This may be identified (uniqued) with other roots with the same + /// name. + MDNode *createTBAARoot(StringRef Name) { + return MDNode::get(Context, createString(Name)); + } + + /// \brief Return metadata for a non-root TBAA node with the given name, + /// parent in the TBAA tree, and value for 'pointsToConstantMemory'. + MDNode *createTBAANode(StringRef Name, MDNode *Parent, + bool isConstant = false) { + if (isConstant) { + Constant *Flags = ConstantInt::get(Type::getInt64Ty(Context), 1); + Value *Ops[3] = { createString(Name), Parent, Flags }; + return MDNode::get(Context, Ops); + } else { + Value *Ops[2] = { createString(Name), Parent }; + return MDNode::get(Context, Ops); + } + } + + struct TBAAStructField { + uint64_t Offset; + uint64_t Size; + MDNode *TBAA; + TBAAStructField(uint64_t Offset, uint64_t Size, MDNode *TBAA) : + Offset(Offset), Size(Size), TBAA(TBAA) {} + }; + + /// \brief Return metadata for a tbaa.struct node with the given + /// struct field descriptions. + MDNode *createTBAAStructNode(ArrayRef<TBAAStructField> Fields) { + SmallVector<Value *, 4> Vals(Fields.size() * 3); + Type *Int64 = IntegerType::get(Context, 64); + for (unsigned i = 0, e = Fields.size(); i != e; ++i) { + Vals[i * 3 + 0] = ConstantInt::get(Int64, Fields[i].Offset); + Vals[i * 3 + 1] = ConstantInt::get(Int64, Fields[i].Size); + Vals[i * 3 + 2] = Fields[i].TBAA; + } + return MDNode::get(Context, Vals); + } + + /// \brief Return metadata for a TBAA struct node in the type DAG + /// with the given name, parents in the TBAA DAG. + MDNode *createTBAAStructTypeNode(StringRef Name, + ArrayRef<std::pair<uint64_t, MDNode*> > Fields) { + SmallVector<Value *, 4> Ops(Fields.size() * 2 + 1); + Type *Int64 = IntegerType::get(Context, 64); + Ops[0] = createString(Name); + for (unsigned i = 0, e = Fields.size(); i != e; ++i) { + Ops[i * 2 + 1] = ConstantInt::get(Int64, Fields[i].first); + Ops[i * 2 + 2] = Fields[i].second; + } + return MDNode::get(Context, Ops); + } + + /// \brief Return metadata for a TBAA tag node with the given + /// base type, access type and offset relative to the base type. + MDNode *createTBAAStructTagNode(MDNode *BaseType, MDNode *AccessType, + uint64_t Offset) { + Type *Int64 = IntegerType::get(Context, 64); + Value *Ops[3] = { BaseType, AccessType, ConstantInt::get(Int64, Offset) }; + return MDNode::get(Context, Ops); + } + +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h new file mode 100644 index 0000000..8c2cfac --- /dev/null +++ b/include/llvm/IR/Metadata.h @@ -0,0 +1,242 @@ +//===-- llvm/Metadata.h - Metadata definitions ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// @file +/// This file contains the declarations for metadata subclasses. +/// They represent the different flavors of metadata that live in LLVM. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_METADATA_H +#define LLVM_IR_METADATA_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/IR/Value.h" + +namespace llvm { +class Constant; +class Instruction; +class LLVMContext; +class Module; +template <typename T> class SmallVectorImpl; +template<typename ValueSubClass, typename ItemParentClass> + class SymbolTableListTraits; + + +//===----------------------------------------------------------------------===// +/// MDString - a single uniqued string. +/// These are used to efficiently contain a byte sequence for metadata. +/// MDString is always unnamed. +class MDString : public Value { + virtual void anchor(); + MDString(const MDString &) LLVM_DELETED_FUNCTION; + + explicit MDString(LLVMContext &C); +public: + static MDString *get(LLVMContext &Context, StringRef Str); + static MDString *get(LLVMContext &Context, const char *Str) { + return get(Context, Str ? StringRef(Str) : StringRef()); + } + + StringRef getString() const { return getName(); } + + unsigned getLength() const { return (unsigned)getName().size(); } + + typedef StringRef::iterator iterator; + + /// begin() - Pointer to the first byte of the string. + iterator begin() const { return getName().begin(); } + + /// end() - Pointer to one byte past the end of the string. + iterator end() const { return getName().end(); } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const Value *V) { + return V->getValueID() == MDStringVal; + } +}; + + +class MDNodeOperand; + +//===----------------------------------------------------------------------===// +/// MDNode - a tuple of other values. +class MDNode : public Value, public FoldingSetNode { + MDNode(const MDNode &) LLVM_DELETED_FUNCTION; + void operator=(const MDNode &) LLVM_DELETED_FUNCTION; + friend class MDNodeOperand; + friend class LLVMContextImpl; + friend struct FoldingSetTrait<MDNode>; + + /// Hash - If the MDNode is uniqued cache the hash to speed up lookup. + unsigned Hash; + + /// NumOperands - This many 'MDNodeOperand' items are co-allocated onto the + /// end of this MDNode. + unsigned NumOperands; + + // Subclass data enums. + enum { + /// FunctionLocalBit - This bit is set if this MDNode is function local. + /// This is true when it (potentially transitively) contains a reference to + /// something in a function, like an argument, basicblock, or instruction. + FunctionLocalBit = 1 << 0, + + /// NotUniquedBit - This is set on MDNodes that are not uniqued because they + /// have a null operand. + NotUniquedBit = 1 << 1, + + /// DestroyFlag - This bit is set by destroy() so the destructor can assert + /// that the node isn't being destroyed with a plain 'delete'. + DestroyFlag = 1 << 2 + }; + + // FunctionLocal enums. + enum FunctionLocalness { + FL_Unknown = -1, + FL_No = 0, + FL_Yes = 1 + }; + + /// replaceOperand - Replace each instance of F from the operand list of this + /// node with T. + void replaceOperand(MDNodeOperand *Op, Value *NewVal); + ~MDNode(); + + MDNode(LLVMContext &C, ArrayRef<Value*> Vals, bool isFunctionLocal); + + static MDNode *getMDNode(LLVMContext &C, ArrayRef<Value*> Vals, + FunctionLocalness FL, bool Insert = true); +public: + // Constructors and destructors. + static MDNode *get(LLVMContext &Context, ArrayRef<Value*> Vals); + // getWhenValsUnresolved - Construct MDNode determining function-localness + // from isFunctionLocal argument, not by analyzing Vals. + static MDNode *getWhenValsUnresolved(LLVMContext &Context, + ArrayRef<Value*> Vals, + bool isFunctionLocal); + + static MDNode *getIfExists(LLVMContext &Context, ArrayRef<Value*> Vals); + + /// getTemporary - Return a temporary MDNode, for use in constructing + /// cyclic MDNode structures. A temporary MDNode is not uniqued, + /// may be RAUW'd, and must be manually deleted with deleteTemporary. + static MDNode *getTemporary(LLVMContext &Context, ArrayRef<Value*> Vals); + + /// deleteTemporary - Deallocate a node created by getTemporary. The + /// node must not have any users. + static void deleteTemporary(MDNode *N); + + /// replaceOperandWith - Replace a specific operand. + void replaceOperandWith(unsigned i, Value *NewVal); + + /// getOperand - Return specified operand. + Value *getOperand(unsigned i) const; + + /// getNumOperands - Return number of MDNode operands. + unsigned getNumOperands() const { return NumOperands; } + + /// isFunctionLocal - Return whether MDNode is local to a function. + bool isFunctionLocal() const { + return (getSubclassDataFromValue() & FunctionLocalBit) != 0; + } + + // getFunction - If this metadata is function-local and recursively has a + // function-local operand, return the first such operand's parent function. + // Otherwise, return null. getFunction() should not be used for performance- + // critical code because it recursively visits all the MDNode's operands. + const Function *getFunction() const; + + /// Profile - calculate a unique identifier for this MDNode to collapse + /// duplicates + void Profile(FoldingSetNodeID &ID) const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const Value *V) { + return V->getValueID() == MDNodeVal; + } + + /// Methods for metadata merging. + static MDNode *getMostGenericTBAA(MDNode *A, MDNode *B); + static MDNode *getMostGenericFPMath(MDNode *A, MDNode *B); + static MDNode *getMostGenericRange(MDNode *A, MDNode *B); +private: + // destroy - Delete this node. Only when there are no uses. + void destroy(); + + bool isNotUniqued() const { + return (getSubclassDataFromValue() & NotUniquedBit) != 0; + } + void setIsNotUniqued(); + + // Shadow Value::setValueSubclassData with a private forwarding method so that + // any future subclasses cannot accidentally use it. + void setValueSubclassData(unsigned short D) { + Value::setValueSubclassData(D); + } +}; + +//===----------------------------------------------------------------------===// +/// NamedMDNode - a tuple of MDNodes. Despite its name, a NamedMDNode isn't +/// itself an MDNode. NamedMDNodes belong to modules, have names, and contain +/// lists of MDNodes. +class NamedMDNode : public ilist_node<NamedMDNode> { + friend class SymbolTableListTraits<NamedMDNode, Module>; + friend struct ilist_traits<NamedMDNode>; + friend class LLVMContextImpl; + friend class Module; + NamedMDNode(const NamedMDNode &) LLVM_DELETED_FUNCTION; + + std::string Name; + Module *Parent; + void *Operands; // SmallVector<TrackingVH<MDNode>, 4> + + void setParent(Module *M) { Parent = M; } + + explicit NamedMDNode(const Twine &N); + +public: + /// eraseFromParent - Drop all references and remove the node from parent + /// module. + void eraseFromParent(); + + /// dropAllReferences - Remove all uses and clear node vector. + void dropAllReferences(); + + /// ~NamedMDNode - Destroy NamedMDNode. + ~NamedMDNode(); + + /// getParent - Get the module that holds this named metadata collection. + inline Module *getParent() { return Parent; } + inline const Module *getParent() const { return Parent; } + + /// getOperand - Return specified operand. + MDNode *getOperand(unsigned i) const; + + /// getNumOperands - Return the number of NamedMDNode operands. + unsigned getNumOperands() const; + + /// addOperand - Add metadata operand. + void addOperand(MDNode *M); + + /// getName - Return a constant reference to this named metadata's name. + StringRef getName() const; + + /// print - Implement operator<< on NamedMDNode. + void print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW = 0) const; + + /// dump() - Allow printing of NamedMDNodes from the debugger. + void dump() const; +}; + +} // end llvm namespace + +#endif diff --git a/include/llvm/IR/Module.h b/include/llvm/IR/Module.h new file mode 100644 index 0000000..4460aa4 --- /dev/null +++ b/include/llvm/IR/Module.h @@ -0,0 +1,589 @@ +//===-- llvm/Module.h - C++ class to represent a VM module ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// @file +/// Module.h This file contains the declarations for the Module class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_MODULE_H +#define LLVM_IR_MODULE_H + +#include "llvm/ADT/OwningPtr.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/GlobalAlias.h" +#include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/Metadata.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class FunctionType; +class GVMaterializer; +class LLVMContext; +class StructType; +template<typename T> struct DenseMapInfo; +template<typename KeyT, typename ValueT, typename KeyInfoT> class DenseMap; + +template<> struct ilist_traits<Function> + : public SymbolTableListTraits<Function, Module> { + + // createSentinel is used to get hold of the node that marks the end of the + // list... (same trick used here as in ilist_traits<Instruction>) + Function *createSentinel() const { + return static_cast<Function*>(&Sentinel); + } + static void destroySentinel(Function*) {} + + Function *provideInitialHead() const { return createSentinel(); } + Function *ensureHead(Function*) const { return createSentinel(); } + static void noteHead(Function*, Function*) {} + +private: + mutable ilist_node<Function> Sentinel; +}; + +template<> struct ilist_traits<GlobalVariable> + : public SymbolTableListTraits<GlobalVariable, Module> { + // createSentinel is used to create a node that marks the end of the list. + GlobalVariable *createSentinel() const { + return static_cast<GlobalVariable*>(&Sentinel); + } + static void destroySentinel(GlobalVariable*) {} + + GlobalVariable *provideInitialHead() const { return createSentinel(); } + GlobalVariable *ensureHead(GlobalVariable*) const { return createSentinel(); } + static void noteHead(GlobalVariable*, GlobalVariable*) {} +private: + mutable ilist_node<GlobalVariable> Sentinel; +}; + +template<> struct ilist_traits<GlobalAlias> + : public SymbolTableListTraits<GlobalAlias, Module> { + // createSentinel is used to create a node that marks the end of the list. + GlobalAlias *createSentinel() const { + return static_cast<GlobalAlias*>(&Sentinel); + } + static void destroySentinel(GlobalAlias*) {} + + GlobalAlias *provideInitialHead() const { return createSentinel(); } + GlobalAlias *ensureHead(GlobalAlias*) const { return createSentinel(); } + static void noteHead(GlobalAlias*, GlobalAlias*) {} +private: + mutable ilist_node<GlobalAlias> Sentinel; +}; + +template<> struct ilist_traits<NamedMDNode> + : public ilist_default_traits<NamedMDNode> { + // createSentinel is used to get hold of a node that marks the end of + // the list... + NamedMDNode *createSentinel() const { + return static_cast<NamedMDNode*>(&Sentinel); + } + static void destroySentinel(NamedMDNode*) {} + + NamedMDNode *provideInitialHead() const { return createSentinel(); } + NamedMDNode *ensureHead(NamedMDNode*) const { return createSentinel(); } + static void noteHead(NamedMDNode*, NamedMDNode*) {} + void addNodeToList(NamedMDNode *) {} + void removeNodeFromList(NamedMDNode *) {} +private: + mutable ilist_node<NamedMDNode> Sentinel; +}; + +/// A Module instance is used to store all the information related to an +/// LLVM module. Modules are the top level container of all other LLVM +/// Intermediate Representation (IR) objects. Each module directly contains a +/// list of globals variables, a list of functions, a list of libraries (or +/// other modules) this module depends on, a symbol table, and various data +/// about the target's characteristics. +/// +/// A module maintains a GlobalValRefMap object that is used to hold all +/// constant references to global variables in the module. When a global +/// variable is destroyed, it should have no entries in the GlobalValueRefMap. +/// @brief The main container class for the LLVM Intermediate Representation. +class Module { +/// @name Types And Enumerations +/// @{ +public: + /// The type for the list of global variables. + typedef iplist<GlobalVariable> GlobalListType; + /// The type for the list of functions. + typedef iplist<Function> FunctionListType; + /// The type for the list of aliases. + typedef iplist<GlobalAlias> AliasListType; + /// The type for the list of named metadata. + typedef ilist<NamedMDNode> NamedMDListType; + + /// The Global Variable iterator. + typedef GlobalListType::iterator global_iterator; + /// The Global Variable constant iterator. + typedef GlobalListType::const_iterator const_global_iterator; + + /// The Function iterators. + typedef FunctionListType::iterator iterator; + /// The Function constant iterator + typedef FunctionListType::const_iterator const_iterator; + + /// The Global Alias iterators. + typedef AliasListType::iterator alias_iterator; + /// The Global Alias constant iterator + typedef AliasListType::const_iterator const_alias_iterator; + + /// The named metadata iterators. + typedef NamedMDListType::iterator named_metadata_iterator; + /// The named metadata constant interators. + typedef NamedMDListType::const_iterator const_named_metadata_iterator; + + /// An enumeration for describing the endianess of the target machine. + enum Endianness { AnyEndianness, LittleEndian, BigEndian }; + + /// An enumeration for describing the size of a pointer on the target machine. + enum PointerSize { AnyPointerSize, Pointer32, Pointer64 }; + + /// This enumeration defines the supported behaviors of module flags. + enum ModFlagBehavior { + /// Emits an error if two values disagree, otherwise the resulting value is + /// that of the operands. + Error = 1, + + /// Emits a warning if two values disagree. The result value will be the + /// operand for the flag from the first module being linked. + Warning = 2, + + /// Adds a requirement that another module flag be present and have a + /// specified value after linking is performed. The value must be a metadata + /// pair, where the first element of the pair is the ID of the module flag + /// to be restricted, and the second element of the pair is the value the + /// module flag should be restricted to. This behavior can be used to + /// restrict the allowable results (via triggering of an error) of linking + /// IDs with the **Override** behavior. + Require = 3, + + /// Uses the specified value, regardless of the behavior or value of the + /// other module. If both modules specify **Override**, but the values + /// differ, an error will be emitted. + Override = 4, + + /// Appends the two values, which are required to be metadata nodes. + Append = 5, + + /// Appends the two values, which are required to be metadata + /// nodes. However, duplicate entries in the second list are dropped + /// during the append operation. + AppendUnique = 6 + }; + + struct ModuleFlagEntry { + ModFlagBehavior Behavior; + MDString *Key; + Value *Val; + ModuleFlagEntry(ModFlagBehavior B, MDString *K, Value *V) + : Behavior(B), Key(K), Val(V) {} + }; + +/// @} +/// @name Member Variables +/// @{ +private: + LLVMContext &Context; ///< The LLVMContext from which types and + ///< constants are allocated. + GlobalListType GlobalList; ///< The Global Variables in the module + FunctionListType FunctionList; ///< The Functions in the module + AliasListType AliasList; ///< The Aliases in the module + NamedMDListType NamedMDList; ///< The named metadata in the module + std::string GlobalScopeAsm; ///< Inline Asm at global scope. + ValueSymbolTable *ValSymTab; ///< Symbol table for values + OwningPtr<GVMaterializer> Materializer; ///< Used to materialize GlobalValues + std::string ModuleID; ///< Human readable identifier for the module + std::string TargetTriple; ///< Platform target triple Module compiled on + std::string DataLayout; ///< Target data description + void *NamedMDSymTab; ///< NamedMDNode names. + + friend class Constant; + +/// @} +/// @name Constructors +/// @{ +public: + /// The Module constructor. Note that there is no default constructor. You + /// must provide a name for the module upon construction. + explicit Module(StringRef ModuleID, LLVMContext& C); + /// The module destructor. This will dropAllReferences. + ~Module(); + +/// @} +/// @name Module Level Accessors +/// @{ + + /// Get the module identifier which is, essentially, the name of the module. + /// @returns the module identifier as a string + const std::string &getModuleIdentifier() const { return ModuleID; } + + /// Get the data layout string for the module's target platform. This encodes + /// the type sizes and alignments expected by this module. + /// @returns the data layout as a string + const std::string &getDataLayout() const { return DataLayout; } + + /// Get the target triple which is a string describing the target host. + /// @returns a string containing the target triple. + const std::string &getTargetTriple() const { return TargetTriple; } + + /// Get the target endian information. + /// @returns Endianess - an enumeration for the endianess of the target + Endianness getEndianness() const; + + /// Get the target pointer size. + /// @returns PointerSize - an enumeration for the size of the target's pointer + PointerSize getPointerSize() const; + + /// Get the global data context. + /// @returns LLVMContext - a container for LLVM's global information + LLVMContext &getContext() const { return Context; } + + /// Get any module-scope inline assembly blocks. + /// @returns a string containing the module-scope inline assembly blocks. + const std::string &getModuleInlineAsm() const { return GlobalScopeAsm; } + +/// @} +/// @name Module Level Mutators +/// @{ + + /// Set the module identifier. + void setModuleIdentifier(StringRef ID) { ModuleID = ID; } + + /// Set the data layout + void setDataLayout(StringRef DL) { DataLayout = DL; } + + /// Set the target triple. + void setTargetTriple(StringRef T) { TargetTriple = T; } + + /// Set the module-scope inline assembly blocks. + void setModuleInlineAsm(StringRef Asm) { + GlobalScopeAsm = Asm; + if (!GlobalScopeAsm.empty() && + GlobalScopeAsm[GlobalScopeAsm.size()-1] != '\n') + GlobalScopeAsm += '\n'; + } + + /// Append to the module-scope inline assembly blocks, automatically inserting + /// a separating newline if necessary. + void appendModuleInlineAsm(StringRef Asm) { + GlobalScopeAsm += Asm; + if (!GlobalScopeAsm.empty() && + GlobalScopeAsm[GlobalScopeAsm.size()-1] != '\n') + GlobalScopeAsm += '\n'; + } + +/// @} +/// @name Generic Value Accessors +/// @{ + + /// getNamedValue - Return the global value in the module with + /// the specified name, of arbitrary type. This method returns null + /// if a global with the specified name is not found. + GlobalValue *getNamedValue(StringRef Name) const; + + /// getMDKindID - Return a unique non-zero ID for the specified metadata kind. + /// This ID is uniqued across modules in the current LLVMContext. + unsigned getMDKindID(StringRef Name) const; + + /// getMDKindNames - Populate client supplied SmallVector with the name for + /// custom metadata IDs registered in this LLVMContext. + void getMDKindNames(SmallVectorImpl<StringRef> &Result) const; + + + typedef DenseMap<StructType*, unsigned, DenseMapInfo<StructType*> > + NumeredTypesMapTy; + + /// getTypeByName - Return the type with the specified name, or null if there + /// is none by that name. + StructType *getTypeByName(StringRef Name) const; + +/// @} +/// @name Function Accessors +/// @{ + + /// getOrInsertFunction - Look up the specified function in the module symbol + /// table. Four possibilities: + /// 1. If it does not exist, add a prototype for the function and return it. + /// 2. If it exists, and has a local linkage, the existing function is + /// renamed and a new one is inserted. + /// 3. Otherwise, if the existing function has the correct prototype, return + /// the existing function. + /// 4. Finally, the function exists but has the wrong prototype: return the + /// function with a constantexpr cast to the right prototype. + Constant *getOrInsertFunction(StringRef Name, FunctionType *T, + AttributeSet AttributeList); + + Constant *getOrInsertFunction(StringRef Name, FunctionType *T); + + /// getOrInsertFunction - Look up the specified function in the module symbol + /// table. If it does not exist, add a prototype for the function and return + /// it. This function guarantees to return a constant of pointer to the + /// specified function type or a ConstantExpr BitCast of that type if the + /// named function has a different type. This version of the method takes a + /// null terminated list of function arguments, which makes it easier for + /// clients to use. + Constant *getOrInsertFunction(StringRef Name, + AttributeSet AttributeList, + Type *RetTy, ...) END_WITH_NULL; + + /// getOrInsertFunction - Same as above, but without the attributes. + Constant *getOrInsertFunction(StringRef Name, Type *RetTy, ...) + END_WITH_NULL; + + Constant *getOrInsertTargetIntrinsic(StringRef Name, + FunctionType *Ty, + AttributeSet AttributeList); + + /// getFunction - Look up the specified function in the module symbol table. + /// If it does not exist, return null. + Function *getFunction(StringRef Name) const; + +/// @} +/// @name Global Variable Accessors +/// @{ + + /// getGlobalVariable - Look up the specified global variable in the module + /// symbol table. If it does not exist, return null. If AllowInternal is set + /// to true, this function will return types that have InternalLinkage. By + /// default, these types are not returned. + GlobalVariable *getGlobalVariable(StringRef Name, + bool AllowInternal = false) const; + + /// getNamedGlobal - Return the global variable in the module with the + /// specified name, of arbitrary type. This method returns null if a global + /// with the specified name is not found. + GlobalVariable *getNamedGlobal(StringRef Name) const { + return getGlobalVariable(Name, true); + } + + /// getOrInsertGlobal - Look up the specified global in the module symbol + /// table. + /// 1. If it does not exist, add a declaration of the global and return it. + /// 2. Else, the global exists but has the wrong type: return the function + /// with a constantexpr cast to the right type. + /// 3. Finally, if the existing global is the correct declaration, return + /// the existing global. + Constant *getOrInsertGlobal(StringRef Name, Type *Ty); + +/// @} +/// @name Global Alias Accessors +/// @{ + + /// getNamedAlias - Return the global alias in the module with the + /// specified name, of arbitrary type. This method returns null if a global + /// with the specified name is not found. + GlobalAlias *getNamedAlias(StringRef Name) const; + +/// @} +/// @name Named Metadata Accessors +/// @{ + + /// getNamedMetadata - Return the NamedMDNode in the module with the + /// specified name. This method returns null if a NamedMDNode with the + /// specified name is not found. + NamedMDNode *getNamedMetadata(const Twine &Name) const; + + /// getOrInsertNamedMetadata - Return the named MDNode in the module + /// with the specified name. This method returns a new NamedMDNode if a + /// NamedMDNode with the specified name is not found. + NamedMDNode *getOrInsertNamedMetadata(StringRef Name); + + /// eraseNamedMetadata - Remove the given NamedMDNode from this module + /// and delete it. + void eraseNamedMetadata(NamedMDNode *NMD); + +/// @} +/// @name Module Flags Accessors +/// @{ + + /// getModuleFlagsMetadata - Returns the module flags in the provided vector. + void getModuleFlagsMetadata(SmallVectorImpl<ModuleFlagEntry> &Flags) const; + + /// getModuleFlagsMetadata - Returns the NamedMDNode in the module that + /// represents module-level flags. This method returns null if there are no + /// module-level flags. + NamedMDNode *getModuleFlagsMetadata() const; + + /// getOrInsertModuleFlagsMetadata - Returns the NamedMDNode in the module + /// that represents module-level flags. If module-level flags aren't found, + /// it creates the named metadata that contains them. + NamedMDNode *getOrInsertModuleFlagsMetadata(); + + /// addModuleFlag - Add a module-level flag to the module-level flags + /// metadata. It will create the module-level flags named metadata if it + /// doesn't already exist. + void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, Value *Val); + void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, uint32_t Val); + void addModuleFlag(MDNode *Node); + +/// @} +/// @name Materialization +/// @{ + + /// setMaterializer - Sets the GVMaterializer to GVM. This module must not + /// yet have a Materializer. To reset the materializer for a module that + /// already has one, call MaterializeAllPermanently first. Destroying this + /// module will destroy its materializer without materializing any more + /// GlobalValues. Without destroying the Module, there is no way to detach or + /// destroy a materializer without materializing all the GVs it controls, to + /// avoid leaving orphan unmaterialized GVs. + void setMaterializer(GVMaterializer *GVM); + /// getMaterializer - Retrieves the GVMaterializer, if any, for this Module. + GVMaterializer *getMaterializer() const { return Materializer.get(); } + + /// isMaterializable - True if the definition of GV has yet to be materialized + /// from the GVMaterializer. + bool isMaterializable(const GlobalValue *GV) const; + /// isDematerializable - Returns true if this GV was loaded from this Module's + /// GVMaterializer and the GVMaterializer knows how to dematerialize the GV. + bool isDematerializable(const GlobalValue *GV) const; + + /// Materialize - Make sure the GlobalValue is fully read. If the module is + /// corrupt, this returns true and fills in the optional string with + /// information about the problem. If successful, this returns false. + bool Materialize(GlobalValue *GV, std::string *ErrInfo = 0); + /// Dematerialize - If the GlobalValue is read in, and if the GVMaterializer + /// supports it, release the memory for the function, and set it up to be + /// materialized lazily. If !isDematerializable(), this method is a noop. + void Dematerialize(GlobalValue *GV); + + /// MaterializeAll - Make sure all GlobalValues in this Module are fully read. + /// If the module is corrupt, this returns true and fills in the optional + /// string with information about the problem. If successful, this returns + /// false. + bool MaterializeAll(std::string *ErrInfo = 0); + + /// MaterializeAllPermanently - Make sure all GlobalValues in this Module are + /// fully read and clear the Materializer. If the module is corrupt, this + /// returns true, fills in the optional string with information about the + /// problem, and DOES NOT clear the old Materializer. If successful, this + /// returns false. + bool MaterializeAllPermanently(std::string *ErrInfo = 0); + +/// @} +/// @name Direct access to the globals list, functions list, and symbol table +/// @{ + + /// Get the Module's list of global variables (constant). + const GlobalListType &getGlobalList() const { return GlobalList; } + /// Get the Module's list of global variables. + GlobalListType &getGlobalList() { return GlobalList; } + static iplist<GlobalVariable> Module::*getSublistAccess(GlobalVariable*) { + return &Module::GlobalList; + } + /// Get the Module's list of functions (constant). + const FunctionListType &getFunctionList() const { return FunctionList; } + /// Get the Module's list of functions. + FunctionListType &getFunctionList() { return FunctionList; } + static iplist<Function> Module::*getSublistAccess(Function*) { + return &Module::FunctionList; + } + /// Get the Module's list of aliases (constant). + const AliasListType &getAliasList() const { return AliasList; } + /// Get the Module's list of aliases. + AliasListType &getAliasList() { return AliasList; } + static iplist<GlobalAlias> Module::*getSublistAccess(GlobalAlias*) { + return &Module::AliasList; + } + /// Get the Module's list of named metadata (constant). + const NamedMDListType &getNamedMDList() const { return NamedMDList; } + /// Get the Module's list of named metadata. + NamedMDListType &getNamedMDList() { return NamedMDList; } + static ilist<NamedMDNode> Module::*getSublistAccess(NamedMDNode*) { + return &Module::NamedMDList; + } + /// Get the symbol table of global variable and function identifiers + const ValueSymbolTable &getValueSymbolTable() const { return *ValSymTab; } + /// Get the Module's symbol table of global variable and function identifiers. + ValueSymbolTable &getValueSymbolTable() { return *ValSymTab; } + +/// @} +/// @name Global Variable Iteration +/// @{ + + global_iterator global_begin() { return GlobalList.begin(); } + const_global_iterator global_begin() const { return GlobalList.begin(); } + global_iterator global_end () { return GlobalList.end(); } + const_global_iterator global_end () const { return GlobalList.end(); } + bool global_empty() const { return GlobalList.empty(); } + +/// @} +/// @name Function Iteration +/// @{ + + iterator begin() { return FunctionList.begin(); } + const_iterator begin() const { return FunctionList.begin(); } + iterator end () { return FunctionList.end(); } + const_iterator end () const { return FunctionList.end(); } + size_t size() const { return FunctionList.size(); } + bool empty() const { return FunctionList.empty(); } + +/// @} +/// @name Alias Iteration +/// @{ + + alias_iterator alias_begin() { return AliasList.begin(); } + const_alias_iterator alias_begin() const { return AliasList.begin(); } + alias_iterator alias_end () { return AliasList.end(); } + const_alias_iterator alias_end () const { return AliasList.end(); } + size_t alias_size () const { return AliasList.size(); } + bool alias_empty() const { return AliasList.empty(); } + + +/// @} +/// @name Named Metadata Iteration +/// @{ + + named_metadata_iterator named_metadata_begin() { return NamedMDList.begin(); } + const_named_metadata_iterator named_metadata_begin() const { + return NamedMDList.begin(); + } + + named_metadata_iterator named_metadata_end() { return NamedMDList.end(); } + const_named_metadata_iterator named_metadata_end() const { + return NamedMDList.end(); + } + + size_t named_metadata_size() const { return NamedMDList.size(); } + bool named_metadata_empty() const { return NamedMDList.empty(); } + + +/// @} +/// @name Utility functions for printing and dumping Module objects +/// @{ + + /// Print the module to an output stream with an optional + /// AssemblyAnnotationWriter. + void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW) const; + + /// Dump the module to stderr (for debugging). + void dump() const; + + /// This function causes all the subinstructions to "let go" of all references + /// that they are maintaining. This allows one to 'delete' a whole class at + /// a time, even though there may be circular references... first all + /// references are dropped, and all use counts go to zero. Then everything + /// is delete'd for real. Note that no operations are valid on an object + /// that has "dropped all references", except operator delete. + void dropAllReferences(); +/// @} +}; + +/// An raw_ostream inserter for modules. +inline raw_ostream &operator<<(raw_ostream &O, const Module &M) { + M.print(O, 0); + return O; +} + +} // End llvm namespace + +#endif diff --git a/include/llvm/IR/OperandTraits.h b/include/llvm/IR/OperandTraits.h new file mode 100644 index 0000000..0e4b195 --- /dev/null +++ b/include/llvm/IR/OperandTraits.h @@ -0,0 +1,160 @@ +//===-- llvm/OperandTraits.h - OperandTraits class definition ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the traits classes that are handy for enforcing the correct +// layout of various User subclasses. It also provides the means for accessing +// the operands in the most efficient manner. +// + +#ifndef LLVM_IR_OPERANDTRAITS_H +#define LLVM_IR_OPERANDTRAITS_H + +#include "llvm/IR/User.h" + +namespace llvm { + +//===----------------------------------------------------------------------===// +// FixedNumOperand Trait Class +//===----------------------------------------------------------------------===// + +/// FixedNumOperandTraits - determine the allocation regime of the Use array +/// when it is a prefix to the User object, and the number of Use objects is +/// known at compile time. + +template <typename SubClass, unsigned ARITY> +struct FixedNumOperandTraits { + static Use *op_begin(SubClass* U) { + return reinterpret_cast<Use*>(U) - ARITY; + } + static Use *op_end(SubClass* U) { + return reinterpret_cast<Use*>(U); + } + static unsigned operands(const User*) { + return ARITY; + } +}; + +//===----------------------------------------------------------------------===// +// OptionalOperand Trait Class +//===----------------------------------------------------------------------===// + +/// OptionalOperandTraits - when the number of operands may change at runtime. +/// Naturally it may only decrease, because the allocations may not change. + +template <typename SubClass, unsigned ARITY = 1> +struct OptionalOperandTraits : public FixedNumOperandTraits<SubClass, ARITY> { + static unsigned operands(const User *U) { + return U->getNumOperands(); + } +}; + +//===----------------------------------------------------------------------===// +// VariadicOperand Trait Class +//===----------------------------------------------------------------------===// + +/// VariadicOperandTraits - determine the allocation regime of the Use array +/// when it is a prefix to the User object, and the number of Use objects is +/// only known at allocation time. + +template <typename SubClass, unsigned MINARITY = 0> +struct VariadicOperandTraits { + static Use *op_begin(SubClass* U) { + return reinterpret_cast<Use*>(U) - static_cast<User*>(U)->getNumOperands(); + } + static Use *op_end(SubClass* U) { + return reinterpret_cast<Use*>(U); + } + static unsigned operands(const User *U) { + return U->getNumOperands(); + } +}; + +//===----------------------------------------------------------------------===// +// HungoffOperand Trait Class +//===----------------------------------------------------------------------===// + +/// HungoffOperandTraits - determine the allocation regime of the Use array +/// when it is not a prefix to the User object, but allocated at an unrelated +/// heap address. +/// Assumes that the User subclass that is determined by this traits class +/// has an OperandList member of type User::op_iterator. [Note: this is now +/// trivially satisfied, because User has that member for historic reasons.] +/// +/// This is the traits class that is needed when the Use array must be +/// resizable. + +template <unsigned MINARITY = 1> +struct HungoffOperandTraits { + static Use *op_begin(User* U) { + return U->OperandList; + } + static Use *op_end(User* U) { + return U->OperandList + U->getNumOperands(); + } + static unsigned operands(const User *U) { + return U->getNumOperands(); + } +}; + +/// Macro for generating in-class operand accessor declarations. +/// It should only be called in the public section of the interface. +/// +#define DECLARE_TRANSPARENT_OPERAND_ACCESSORS(VALUECLASS) \ + public: \ + inline VALUECLASS *getOperand(unsigned) const; \ + inline void setOperand(unsigned, VALUECLASS*); \ + inline op_iterator op_begin(); \ + inline const_op_iterator op_begin() const; \ + inline op_iterator op_end(); \ + inline const_op_iterator op_end() const; \ + protected: \ + template <int> inline Use &Op(); \ + template <int> inline const Use &Op() const; \ + public: \ + inline unsigned getNumOperands() const + +/// Macro for generating out-of-class operand accessor definitions +#define DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CLASS, VALUECLASS) \ +CLASS::op_iterator CLASS::op_begin() { \ + return OperandTraits<CLASS>::op_begin(this); \ +} \ +CLASS::const_op_iterator CLASS::op_begin() const { \ + return OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this)); \ +} \ +CLASS::op_iterator CLASS::op_end() { \ + return OperandTraits<CLASS>::op_end(this); \ +} \ +CLASS::const_op_iterator CLASS::op_end() const { \ + return OperandTraits<CLASS>::op_end(const_cast<CLASS*>(this)); \ +} \ +VALUECLASS *CLASS::getOperand(unsigned i_nocapture) const { \ + assert(i_nocapture < OperandTraits<CLASS>::operands(this) \ + && "getOperand() out of range!"); \ + return cast_or_null<VALUECLASS>( \ + OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this))[i_nocapture].get()); \ +} \ +void CLASS::setOperand(unsigned i_nocapture, VALUECLASS *Val_nocapture) { \ + assert(i_nocapture < OperandTraits<CLASS>::operands(this) \ + && "setOperand() out of range!"); \ + OperandTraits<CLASS>::op_begin(this)[i_nocapture] = Val_nocapture; \ +} \ +unsigned CLASS::getNumOperands() const { \ + return OperandTraits<CLASS>::operands(this); \ +} \ +template <int Idx_nocapture> Use &CLASS::Op() { \ + return this->OpFrom<Idx_nocapture>(this); \ +} \ +template <int Idx_nocapture> const Use &CLASS::Op() const { \ + return this->OpFrom<Idx_nocapture>(this); \ +} + + +} // End llvm namespace + +#endif diff --git a/include/llvm/IR/Operator.h b/include/llvm/IR/Operator.h new file mode 100644 index 0000000..13ab72c --- /dev/null +++ b/include/llvm/IR/Operator.h @@ -0,0 +1,478 @@ +//===-- llvm/Operator.h - Operator utility subclass -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines various classes for working with Instructions and +// ConstantExprs. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_OPERATOR_H +#define LLVM_IR_OPERATOR_H + +#include "llvm/IR/Constants.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Type.h" +#include "llvm/Support/GetElementPtrTypeIterator.h" + +namespace llvm { + +class GetElementPtrInst; +class BinaryOperator; +class ConstantExpr; + +/// Operator - This is a utility class that provides an abstraction for the +/// common functionality between Instructions and ConstantExprs. +/// +class Operator : public User { +private: + // The Operator class is intended to be used as a utility, and is never itself + // instantiated. + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t s) LLVM_DELETED_FUNCTION; + Operator() LLVM_DELETED_FUNCTION; + +protected: + // NOTE: Cannot use LLVM_DELETED_FUNCTION because it's not legal to delete + // an overridden method that's not deleted in the base class. Cannot leave + // this unimplemented because that leads to an ODR-violation. + ~Operator(); + +public: + /// getOpcode - Return the opcode for this Instruction or ConstantExpr. + /// + unsigned getOpcode() const { + if (const Instruction *I = dyn_cast<Instruction>(this)) + return I->getOpcode(); + return cast<ConstantExpr>(this)->getOpcode(); + } + + /// getOpcode - If V is an Instruction or ConstantExpr, return its + /// opcode. Otherwise return UserOp1. + /// + static unsigned getOpcode(const Value *V) { + if (const Instruction *I = dyn_cast<Instruction>(V)) + return I->getOpcode(); + if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) + return CE->getOpcode(); + return Instruction::UserOp1; + } + + static inline bool classof(const Instruction *) { return true; } + static inline bool classof(const ConstantExpr *) { return true; } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) || isa<ConstantExpr>(V); + } +}; + +/// OverflowingBinaryOperator - Utility class for integer arithmetic operators +/// which may exhibit overflow - Add, Sub, and Mul. It does not include SDiv, +/// despite that operator having the potential for overflow. +/// +class OverflowingBinaryOperator : public Operator { +public: + enum { + NoUnsignedWrap = (1 << 0), + NoSignedWrap = (1 << 1) + }; + +private: + friend class BinaryOperator; + friend class ConstantExpr; + void setHasNoUnsignedWrap(bool B) { + SubclassOptionalData = + (SubclassOptionalData & ~NoUnsignedWrap) | (B * NoUnsignedWrap); + } + void setHasNoSignedWrap(bool B) { + SubclassOptionalData = + (SubclassOptionalData & ~NoSignedWrap) | (B * NoSignedWrap); + } + +public: + /// hasNoUnsignedWrap - Test whether this operation is known to never + /// undergo unsigned overflow, aka the nuw property. + bool hasNoUnsignedWrap() const { + return SubclassOptionalData & NoUnsignedWrap; + } + + /// hasNoSignedWrap - Test whether this operation is known to never + /// undergo signed overflow, aka the nsw property. + bool hasNoSignedWrap() const { + return (SubclassOptionalData & NoSignedWrap) != 0; + } + + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Add || + I->getOpcode() == Instruction::Sub || + I->getOpcode() == Instruction::Mul || + I->getOpcode() == Instruction::Shl; + } + static inline bool classof(const ConstantExpr *CE) { + return CE->getOpcode() == Instruction::Add || + CE->getOpcode() == Instruction::Sub || + CE->getOpcode() == Instruction::Mul || + CE->getOpcode() == Instruction::Shl; + } + static inline bool classof(const Value *V) { + return (isa<Instruction>(V) && classof(cast<Instruction>(V))) || + (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V))); + } +}; + +/// PossiblyExactOperator - A udiv or sdiv instruction, which can be marked as +/// "exact", indicating that no bits are destroyed. +class PossiblyExactOperator : public Operator { +public: + enum { + IsExact = (1 << 0) + }; + +private: + friend class BinaryOperator; + friend class ConstantExpr; + void setIsExact(bool B) { + SubclassOptionalData = (SubclassOptionalData & ~IsExact) | (B * IsExact); + } + +public: + /// isExact - Test whether this division is known to be exact, with + /// zero remainder. + bool isExact() const { + return SubclassOptionalData & IsExact; + } + + static bool isPossiblyExactOpcode(unsigned OpC) { + return OpC == Instruction::SDiv || + OpC == Instruction::UDiv || + OpC == Instruction::AShr || + OpC == Instruction::LShr; + } + static inline bool classof(const ConstantExpr *CE) { + return isPossiblyExactOpcode(CE->getOpcode()); + } + static inline bool classof(const Instruction *I) { + return isPossiblyExactOpcode(I->getOpcode()); + } + static inline bool classof(const Value *V) { + return (isa<Instruction>(V) && classof(cast<Instruction>(V))) || + (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V))); + } +}; + +/// Convenience struct for specifying and reasoning about fast-math flags. +class FastMathFlags { +private: + friend class FPMathOperator; + unsigned Flags; + FastMathFlags(unsigned F) : Flags(F) { } + +public: + enum { + UnsafeAlgebra = (1 << 0), + NoNaNs = (1 << 1), + NoInfs = (1 << 2), + NoSignedZeros = (1 << 3), + AllowReciprocal = (1 << 4) + }; + + FastMathFlags() : Flags(0) + { } + + /// Whether any flag is set + bool any() { return Flags != 0; } + + /// Set all the flags to false + void clear() { Flags = 0; } + + /// Flag queries + bool noNaNs() { return 0 != (Flags & NoNaNs); } + bool noInfs() { return 0 != (Flags & NoInfs); } + bool noSignedZeros() { return 0 != (Flags & NoSignedZeros); } + bool allowReciprocal() { return 0 != (Flags & AllowReciprocal); } + bool unsafeAlgebra() { return 0 != (Flags & UnsafeAlgebra); } + + /// Flag setters + void setNoNaNs() { Flags |= NoNaNs; } + void setNoInfs() { Flags |= NoInfs; } + void setNoSignedZeros() { Flags |= NoSignedZeros; } + void setAllowReciprocal() { Flags |= AllowReciprocal; } + void setUnsafeAlgebra() { + Flags |= UnsafeAlgebra; + setNoNaNs(); + setNoInfs(); + setNoSignedZeros(); + setAllowReciprocal(); + } +}; + + +/// FPMathOperator - Utility class for floating point operations which can have +/// information about relaxed accuracy requirements attached to them. +class FPMathOperator : public Operator { +private: + friend class Instruction; + + void setHasUnsafeAlgebra(bool B) { + SubclassOptionalData = + (SubclassOptionalData & ~FastMathFlags::UnsafeAlgebra) | + (B * FastMathFlags::UnsafeAlgebra); + + // Unsafe algebra implies all the others + if (B) { + setHasNoNaNs(true); + setHasNoInfs(true); + setHasNoSignedZeros(true); + setHasAllowReciprocal(true); + } + } + void setHasNoNaNs(bool B) { + SubclassOptionalData = + (SubclassOptionalData & ~FastMathFlags::NoNaNs) | + (B * FastMathFlags::NoNaNs); + } + void setHasNoInfs(bool B) { + SubclassOptionalData = + (SubclassOptionalData & ~FastMathFlags::NoInfs) | + (B * FastMathFlags::NoInfs); + } + void setHasNoSignedZeros(bool B) { + SubclassOptionalData = + (SubclassOptionalData & ~FastMathFlags::NoSignedZeros) | + (B * FastMathFlags::NoSignedZeros); + } + void setHasAllowReciprocal(bool B) { + SubclassOptionalData = + (SubclassOptionalData & ~FastMathFlags::AllowReciprocal) | + (B * FastMathFlags::AllowReciprocal); + } + + /// Convenience function for setting all the fast-math flags + void setFastMathFlags(FastMathFlags FMF) { + SubclassOptionalData |= FMF.Flags; + } + +public: + /// Test whether this operation is permitted to be + /// algebraically transformed, aka the 'A' fast-math property. + bool hasUnsafeAlgebra() const { + return (SubclassOptionalData & FastMathFlags::UnsafeAlgebra) != 0; + } + + /// Test whether this operation's arguments and results are to be + /// treated as non-NaN, aka the 'N' fast-math property. + bool hasNoNaNs() const { + return (SubclassOptionalData & FastMathFlags::NoNaNs) != 0; + } + + /// Test whether this operation's arguments and results are to be + /// treated as NoN-Inf, aka the 'I' fast-math property. + bool hasNoInfs() const { + return (SubclassOptionalData & FastMathFlags::NoInfs) != 0; + } + + /// Test whether this operation can treat the sign of zero + /// as insignificant, aka the 'S' fast-math property. + bool hasNoSignedZeros() const { + return (SubclassOptionalData & FastMathFlags::NoSignedZeros) != 0; + } + + /// Test whether this operation is permitted to use + /// reciprocal instead of division, aka the 'R' fast-math property. + bool hasAllowReciprocal() const { + return (SubclassOptionalData & FastMathFlags::AllowReciprocal) != 0; + } + + /// Convenience function for getting all the fast-math flags + FastMathFlags getFastMathFlags() const { + return FastMathFlags(SubclassOptionalData); + } + + /// \brief Get the maximum error permitted by this operation in ULPs. An + /// accuracy of 0.0 means that the operation should be performed with the + /// default precision. + float getFPAccuracy() const; + + static inline bool classof(const Instruction *I) { + return I->getType()->isFPOrFPVectorTy(); + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + + +/// ConcreteOperator - A helper template for defining operators for individual +/// opcodes. +template<typename SuperClass, unsigned Opc> +class ConcreteOperator : public SuperClass { +public: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Opc; + } + static inline bool classof(const ConstantExpr *CE) { + return CE->getOpcode() == Opc; + } + static inline bool classof(const Value *V) { + return (isa<Instruction>(V) && classof(cast<Instruction>(V))) || + (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V))); + } +}; + +class AddOperator + : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Add> { +}; +class SubOperator + : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Sub> { +}; +class MulOperator + : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Mul> { +}; +class ShlOperator + : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Shl> { +}; + + +class SDivOperator + : public ConcreteOperator<PossiblyExactOperator, Instruction::SDiv> { +}; +class UDivOperator + : public ConcreteOperator<PossiblyExactOperator, Instruction::UDiv> { +}; +class AShrOperator + : public ConcreteOperator<PossiblyExactOperator, Instruction::AShr> { +}; +class LShrOperator + : public ConcreteOperator<PossiblyExactOperator, Instruction::LShr> { +}; + + + +class GEPOperator + : public ConcreteOperator<Operator, Instruction::GetElementPtr> { + enum { + IsInBounds = (1 << 0) + }; + + friend class GetElementPtrInst; + friend class ConstantExpr; + void setIsInBounds(bool B) { + SubclassOptionalData = + (SubclassOptionalData & ~IsInBounds) | (B * IsInBounds); + } + +public: + /// isInBounds - Test whether this is an inbounds GEP, as defined + /// by LangRef.html. + bool isInBounds() const { + return SubclassOptionalData & IsInBounds; + } + + inline op_iterator idx_begin() { return op_begin()+1; } + inline const_op_iterator idx_begin() const { return op_begin()+1; } + inline op_iterator idx_end() { return op_end(); } + inline const_op_iterator idx_end() const { return op_end(); } + + Value *getPointerOperand() { + return getOperand(0); + } + const Value *getPointerOperand() const { + return getOperand(0); + } + static unsigned getPointerOperandIndex() { + return 0U; // get index for modifying correct operand + } + + /// getPointerOperandType - Method to return the pointer operand as a + /// PointerType. + Type *getPointerOperandType() const { + return getPointerOperand()->getType(); + } + + /// getPointerAddressSpace - Method to return the address space of the + /// pointer operand. + unsigned getPointerAddressSpace() const { + return cast<PointerType>(getPointerOperandType())->getAddressSpace(); + } + + unsigned getNumIndices() const { // Note: always non-negative + return getNumOperands() - 1; + } + + bool hasIndices() const { + return getNumOperands() > 1; + } + + /// hasAllZeroIndices - Return true if all of the indices of this GEP are + /// zeros. If so, the result pointer and the first operand have the same + /// value, just potentially different types. + bool hasAllZeroIndices() const { + for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) { + if (ConstantInt *C = dyn_cast<ConstantInt>(I)) + if (C->isZero()) + continue; + return false; + } + return true; + } + + /// hasAllConstantIndices - Return true if all of the indices of this GEP are + /// constant integers. If so, the result pointer and the first operand have + /// a constant offset between them. + bool hasAllConstantIndices() const { + for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) { + if (!isa<ConstantInt>(I)) + return false; + } + return true; + } + + /// \brief Accumulate the constant address offset of this GEP if possible. + /// + /// This routine accepts an APInt into which it will accumulate the constant + /// offset of this GEP if the GEP is in fact constant. If the GEP is not + /// all-constant, it returns false and the value of the offset APInt is + /// undefined (it is *not* preserved!). The APInt passed into this routine + /// must be at least as wide as the IntPtr type for the address space of + /// the base GEP pointer. + bool accumulateConstantOffset(const DataLayout &DL, APInt &Offset) const { + assert(Offset.getBitWidth() == + DL.getPointerSizeInBits(getPointerAddressSpace()) && + "The offset must have exactly as many bits as our pointer."); + + for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this); + GTI != GTE; ++GTI) { + ConstantInt *OpC = dyn_cast<ConstantInt>(GTI.getOperand()); + if (!OpC) + return false; + if (OpC->isZero()) + continue; + + // Handle a struct index, which adds its field offset to the pointer. + if (StructType *STy = dyn_cast<StructType>(*GTI)) { + unsigned ElementIdx = OpC->getZExtValue(); + const StructLayout *SL = DL.getStructLayout(STy); + Offset += APInt(Offset.getBitWidth(), + SL->getElementOffset(ElementIdx)); + continue; + } + + // For array or vector indices, scale the index by the size of the type. + APInt Index = OpC->getValue().sextOrTrunc(Offset.getBitWidth()); + Offset += Index * APInt(Offset.getBitWidth(), + DL.getTypeAllocSize(GTI.getIndexedType())); + } + return true; + } + +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/IR/SymbolTableListTraits.h b/include/llvm/IR/SymbolTableListTraits.h new file mode 100644 index 0000000..561ce01 --- /dev/null +++ b/include/llvm/IR/SymbolTableListTraits.h @@ -0,0 +1,78 @@ +//===-- llvm/SymbolTableListTraits.h - Traits for iplist --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a generic class that is used to implement the automatic +// symbol table manipulation that occurs when you put (for example) a named +// instruction into a basic block. +// +// The way that this is implemented is by using a special traits class with the +// intrusive list that makes up the list of instructions in a basic block. When +// a new element is added to the list of instructions, the traits class is +// notified, allowing the symbol table to be updated. +// +// This generic class implements the traits class. It must be generic so that +// it can work for all uses it, which include lists of instructions, basic +// blocks, arguments, functions, global variables, etc... +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_SYMBOLTABLELISTTRAITS_H +#define LLVM_IR_SYMBOLTABLELISTTRAITS_H + +#include "llvm/ADT/ilist.h" + +namespace llvm { +class ValueSymbolTable; + +template<typename NodeTy> class ilist_iterator; +template<typename NodeTy, typename Traits> class iplist; +template<typename Ty> struct ilist_traits; + +// ValueSubClass - The type of objects that I hold, e.g. Instruction. +// ItemParentClass - The type of object that owns the list, e.g. BasicBlock. +// +template<typename ValueSubClass, typename ItemParentClass> +class SymbolTableListTraits : public ilist_default_traits<ValueSubClass> { + typedef ilist_traits<ValueSubClass> TraitsClass; +public: + SymbolTableListTraits() {} + + /// getListOwner - Return the object that owns this list. If this is a list + /// of instructions, it returns the BasicBlock that owns them. + ItemParentClass *getListOwner() { + size_t Offset(size_t(&((ItemParentClass*)0->*ItemParentClass:: + getSublistAccess(static_cast<ValueSubClass*>(0))))); + iplist<ValueSubClass>* Anchor(static_cast<iplist<ValueSubClass>*>(this)); + return reinterpret_cast<ItemParentClass*>(reinterpret_cast<char*>(Anchor)- + Offset); + } + + static iplist<ValueSubClass> &getList(ItemParentClass *Par) { + return Par->*(Par->getSublistAccess((ValueSubClass*)0)); + } + + static ValueSymbolTable *getSymTab(ItemParentClass *Par) { + return Par ? toPtr(Par->getValueSymbolTable()) : 0; + } + + void addNodeToList(ValueSubClass *V); + void removeNodeFromList(ValueSubClass *V); + void transferNodesFromList(ilist_traits<ValueSubClass> &L2, + ilist_iterator<ValueSubClass> first, + ilist_iterator<ValueSubClass> last); +//private: + template<typename TPtr> + void setSymTabObject(TPtr *, TPtr); + static ValueSymbolTable *toPtr(ValueSymbolTable *P) { return P; } + static ValueSymbolTable *toPtr(ValueSymbolTable &R) { return &R; } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/IR/Type.h b/include/llvm/IR/Type.h new file mode 100644 index 0000000..d89ae24 --- /dev/null +++ b/include/llvm/IR/Type.h @@ -0,0 +1,472 @@ +//===-- llvm/Type.h - Classes for handling data types -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the Type class. For more "Type" +// stuff, look in DerivedTypes.h. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_TYPE_H +#define LLVM_IR_TYPE_H + +#include "llvm/ADT/APFloat.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/ErrorHandling.h" + +namespace llvm { + +class PointerType; +class IntegerType; +class raw_ostream; +class Module; +class LLVMContext; +class LLVMContextImpl; +class StringRef; +template<class GraphType> struct GraphTraits; + +/// The instances of the Type class are immutable: once they are created, +/// they are never changed. Also note that only one instance of a particular +/// type is ever created. Thus seeing if two types are equal is a matter of +/// doing a trivial pointer comparison. To enforce that no two equal instances +/// are created, Type instances can only be created via static factory methods +/// in class Type and in derived classes. Once allocated, Types are never +/// free'd. +/// +class Type { +public: + //===--------------------------------------------------------------------===// + /// Definitions of all of the base types for the Type system. Based on this + /// value, you can cast to a class defined in DerivedTypes.h. + /// Note: If you add an element to this, you need to add an element to the + /// Type::getPrimitiveType function, or else things will break! + /// Also update LLVMTypeKind and LLVMGetTypeKind () in the C binding. + /// + enum TypeID { + // PrimitiveTypes - make sure LastPrimitiveTyID stays up to date. + VoidTyID = 0, ///< 0: type with no size + HalfTyID, ///< 1: 16-bit floating point type + FloatTyID, ///< 2: 32-bit floating point type + DoubleTyID, ///< 3: 64-bit floating point type + X86_FP80TyID, ///< 4: 80-bit floating point type (X87) + FP128TyID, ///< 5: 128-bit floating point type (112-bit mantissa) + PPC_FP128TyID, ///< 6: 128-bit floating point type (two 64-bits, PowerPC) + LabelTyID, ///< 7: Labels + MetadataTyID, ///< 8: Metadata + X86_MMXTyID, ///< 9: MMX vectors (64 bits, X86 specific) + + // Derived types... see DerivedTypes.h file. + // Make sure FirstDerivedTyID stays up to date! + IntegerTyID, ///< 10: Arbitrary bit width integers + FunctionTyID, ///< 11: Functions + StructTyID, ///< 12: Structures + ArrayTyID, ///< 13: Arrays + PointerTyID, ///< 14: Pointers + VectorTyID, ///< 15: SIMD 'packed' format, or other vector type + + NumTypeIDs, // Must remain as last defined ID + LastPrimitiveTyID = X86_MMXTyID, + FirstDerivedTyID = IntegerTyID + }; + +private: + /// Context - This refers to the LLVMContext in which this type was uniqued. + LLVMContext &Context; + + // Due to Ubuntu GCC bug 910363: + // https://bugs.launchpad.net/ubuntu/+source/gcc-4.5/+bug/910363 + // Bitpack ID and SubclassData manually. + // Note: TypeID : low 8 bit; SubclassData : high 24 bit. + uint32_t IDAndSubclassData; + +protected: + friend class LLVMContextImpl; + explicit Type(LLVMContext &C, TypeID tid) + : Context(C), IDAndSubclassData(0), + NumContainedTys(0), ContainedTys(0) { + setTypeID(tid); + } + ~Type() {} + + void setTypeID(TypeID ID) { + IDAndSubclassData = (ID & 0xFF) | (IDAndSubclassData & 0xFFFFFF00); + assert(getTypeID() == ID && "TypeID data too large for field"); + } + + unsigned getSubclassData() const { return IDAndSubclassData >> 8; } + + void setSubclassData(unsigned val) { + IDAndSubclassData = (IDAndSubclassData & 0xFF) | (val << 8); + // Ensure we don't have any accidental truncation. + assert(getSubclassData() == val && "Subclass data too large for field"); + } + + /// NumContainedTys - Keeps track of how many Type*'s there are in the + /// ContainedTys list. + unsigned NumContainedTys; + + /// ContainedTys - A pointer to the array of Types contained by this Type. + /// For example, this includes the arguments of a function type, the elements + /// of a structure, the pointee of a pointer, the element type of an array, + /// etc. This pointer may be 0 for types that don't contain other types + /// (Integer, Double, Float). + Type * const *ContainedTys; + +public: + void print(raw_ostream &O) const; + void dump() const; + + /// getContext - Return the LLVMContext in which this type was uniqued. + LLVMContext &getContext() const { return Context; } + + //===--------------------------------------------------------------------===// + // Accessors for working with types. + // + + /// getTypeID - Return the type id for the type. This will return one + /// of the TypeID enum elements defined above. + /// + TypeID getTypeID() const { return (TypeID)(IDAndSubclassData & 0xFF); } + + /// isVoidTy - Return true if this is 'void'. + bool isVoidTy() const { return getTypeID() == VoidTyID; } + + /// isHalfTy - Return true if this is 'half', a 16-bit IEEE fp type. + bool isHalfTy() const { return getTypeID() == HalfTyID; } + + /// isFloatTy - Return true if this is 'float', a 32-bit IEEE fp type. + bool isFloatTy() const { return getTypeID() == FloatTyID; } + + /// isDoubleTy - Return true if this is 'double', a 64-bit IEEE fp type. + bool isDoubleTy() const { return getTypeID() == DoubleTyID; } + + /// isX86_FP80Ty - Return true if this is x86 long double. + bool isX86_FP80Ty() const { return getTypeID() == X86_FP80TyID; } + + /// isFP128Ty - Return true if this is 'fp128'. + bool isFP128Ty() const { return getTypeID() == FP128TyID; } + + /// isPPC_FP128Ty - Return true if this is powerpc long double. + bool isPPC_FP128Ty() const { return getTypeID() == PPC_FP128TyID; } + + /// isFloatingPointTy - Return true if this is one of the six floating point + /// types + bool isFloatingPointTy() const { + return getTypeID() == HalfTyID || getTypeID() == FloatTyID || + getTypeID() == DoubleTyID || + getTypeID() == X86_FP80TyID || getTypeID() == FP128TyID || + getTypeID() == PPC_FP128TyID; + } + + const fltSemantics &getFltSemantics() const { + switch (getTypeID()) { + case HalfTyID: return APFloat::IEEEhalf; + case FloatTyID: return APFloat::IEEEsingle; + case DoubleTyID: return APFloat::IEEEdouble; + case X86_FP80TyID: return APFloat::x87DoubleExtended; + case FP128TyID: return APFloat::IEEEquad; + case PPC_FP128TyID: return APFloat::PPCDoubleDouble; + default: llvm_unreachable("Invalid floating type"); + } + } + + /// isX86_MMXTy - Return true if this is X86 MMX. + bool isX86_MMXTy() const { return getTypeID() == X86_MMXTyID; } + + /// isFPOrFPVectorTy - Return true if this is a FP type or a vector of FP. + /// + bool isFPOrFPVectorTy() const { return getScalarType()->isFloatingPointTy(); } + + /// isLabelTy - Return true if this is 'label'. + bool isLabelTy() const { return getTypeID() == LabelTyID; } + + /// isMetadataTy - Return true if this is 'metadata'. + bool isMetadataTy() const { return getTypeID() == MetadataTyID; } + + /// isIntegerTy - True if this is an instance of IntegerType. + /// + bool isIntegerTy() const { return getTypeID() == IntegerTyID; } + + /// isIntegerTy - Return true if this is an IntegerType of the given width. + bool isIntegerTy(unsigned Bitwidth) const; + + /// isIntOrIntVectorTy - Return true if this is an integer type or a vector of + /// integer types. + /// + bool isIntOrIntVectorTy() const { return getScalarType()->isIntegerTy(); } + + /// isFunctionTy - True if this is an instance of FunctionType. + /// + bool isFunctionTy() const { return getTypeID() == FunctionTyID; } + + /// isStructTy - True if this is an instance of StructType. + /// + bool isStructTy() const { return getTypeID() == StructTyID; } + + /// isArrayTy - True if this is an instance of ArrayType. + /// + bool isArrayTy() const { return getTypeID() == ArrayTyID; } + + /// isPointerTy - True if this is an instance of PointerType. + /// + bool isPointerTy() const { return getTypeID() == PointerTyID; } + + /// isPtrOrPtrVectorTy - Return true if this is a pointer type or a vector of + /// pointer types. + /// + bool isPtrOrPtrVectorTy() const { return getScalarType()->isPointerTy(); } + + /// isVectorTy - True if this is an instance of VectorType. + /// + bool isVectorTy() const { return getTypeID() == VectorTyID; } + + /// canLosslesslyBitCastTo - Return true if this type could be converted + /// with a lossless BitCast to type 'Ty'. For example, i8* to i32*. BitCasts + /// are valid for types of the same size only where no re-interpretation of + /// the bits is done. + /// @brief Determine if this type could be losslessly bitcast to Ty + bool canLosslesslyBitCastTo(Type *Ty) const; + + /// isEmptyTy - Return true if this type is empty, that is, it has no + /// elements or all its elements are empty. + bool isEmptyTy() const; + + /// Here are some useful little methods to query what type derived types are + /// Note that all other types can just compare to see if this == Type::xxxTy; + /// + bool isPrimitiveType() const { return getTypeID() <= LastPrimitiveTyID; } + bool isDerivedType() const { return getTypeID() >= FirstDerivedTyID; } + + /// isFirstClassType - Return true if the type is "first class", meaning it + /// is a valid type for a Value. + /// + bool isFirstClassType() const { + return getTypeID() != FunctionTyID && getTypeID() != VoidTyID; + } + + /// isSingleValueType - Return true if the type is a valid type for a + /// register in codegen. This includes all first-class types except struct + /// and array types. + /// + bool isSingleValueType() const { + return (getTypeID() != VoidTyID && isPrimitiveType()) || + getTypeID() == IntegerTyID || getTypeID() == PointerTyID || + getTypeID() == VectorTyID; + } + + /// isAggregateType - Return true if the type is an aggregate type. This + /// means it is valid as the first operand of an insertvalue or + /// extractvalue instruction. This includes struct and array types, but + /// does not include vector types. + /// + bool isAggregateType() const { + return getTypeID() == StructTyID || getTypeID() == ArrayTyID; + } + + /// isSized - Return true if it makes sense to take the size of this type. To + /// get the actual size for a particular target, it is reasonable to use the + /// DataLayout subsystem to do this. + /// + bool isSized() const { + // If it's a primitive, it is always sized. + if (getTypeID() == IntegerTyID || isFloatingPointTy() || + getTypeID() == PointerTyID || + getTypeID() == X86_MMXTyID) + return true; + // If it is not something that can have a size (e.g. a function or label), + // it doesn't have a size. + if (getTypeID() != StructTyID && getTypeID() != ArrayTyID && + getTypeID() != VectorTyID) + return false; + // Otherwise we have to try harder to decide. + return isSizedDerivedType(); + } + + /// getPrimitiveSizeInBits - Return the basic size of this type if it is a + /// primitive type. These are fixed by LLVM and are not target dependent. + /// This will return zero if the type does not have a size or is not a + /// primitive type. + /// + /// Note that this may not reflect the size of memory allocated for an + /// instance of the type or the number of bytes that are written when an + /// instance of the type is stored to memory. The DataLayout class provides + /// additional query functions to provide this information. + /// + unsigned getPrimitiveSizeInBits() const; + + /// getScalarSizeInBits - If this is a vector type, return the + /// getPrimitiveSizeInBits value for the element type. Otherwise return the + /// getPrimitiveSizeInBits value for this type. + unsigned getScalarSizeInBits(); + + /// getFPMantissaWidth - Return the width of the mantissa of this type. This + /// is only valid on floating point types. If the FP type does not + /// have a stable mantissa (e.g. ppc long double), this method returns -1. + int getFPMantissaWidth() const; + + /// getScalarType - If this is a vector type, return the element type, + /// otherwise return 'this'. + const Type *getScalarType() const; + Type *getScalarType(); + + //===--------------------------------------------------------------------===// + // Type Iteration support. + // + typedef Type * const *subtype_iterator; + subtype_iterator subtype_begin() const { return ContainedTys; } + subtype_iterator subtype_end() const { return &ContainedTys[NumContainedTys];} + + /// getContainedType - This method is used to implement the type iterator + /// (defined a the end of the file). For derived types, this returns the + /// types 'contained' in the derived type. + /// + Type *getContainedType(unsigned i) const { + assert(i < NumContainedTys && "Index out of range!"); + return ContainedTys[i]; + } + + /// getNumContainedTypes - Return the number of types in the derived type. + /// + unsigned getNumContainedTypes() const { return NumContainedTys; } + + //===--------------------------------------------------------------------===// + // Helper methods corresponding to subclass methods. This forces a cast to + // the specified subclass and calls its accessor. "getVectorNumElements" (for + // example) is shorthand for cast<VectorType>(Ty)->getNumElements(). This is + // only intended to cover the core methods that are frequently used, helper + // methods should not be added here. + + unsigned getIntegerBitWidth() const; + + Type *getFunctionParamType(unsigned i) const; + unsigned getFunctionNumParams() const; + bool isFunctionVarArg() const; + + StringRef getStructName() const; + unsigned getStructNumElements() const; + Type *getStructElementType(unsigned N) const; + + Type *getSequentialElementType() const; + + uint64_t getArrayNumElements() const; + Type *getArrayElementType() const { return getSequentialElementType(); } + + unsigned getVectorNumElements() const; + Type *getVectorElementType() const { return getSequentialElementType(); } + + Type *getPointerElementType() const { return getSequentialElementType(); } + + /// \brief Get the address space of this pointer or pointer vector type. + unsigned getPointerAddressSpace() const; + + //===--------------------------------------------------------------------===// + // Static members exported by the Type class itself. Useful for getting + // instances of Type. + // + + /// getPrimitiveType - Return a type based on an identifier. + static Type *getPrimitiveType(LLVMContext &C, TypeID IDNumber); + + //===--------------------------------------------------------------------===// + // These are the builtin types that are always available. + // + static Type *getVoidTy(LLVMContext &C); + static Type *getLabelTy(LLVMContext &C); + static Type *getHalfTy(LLVMContext &C); + static Type *getFloatTy(LLVMContext &C); + static Type *getDoubleTy(LLVMContext &C); + static Type *getMetadataTy(LLVMContext &C); + static Type *getX86_FP80Ty(LLVMContext &C); + static Type *getFP128Ty(LLVMContext &C); + static Type *getPPC_FP128Ty(LLVMContext &C); + static Type *getX86_MMXTy(LLVMContext &C); + static IntegerType *getIntNTy(LLVMContext &C, unsigned N); + static IntegerType *getInt1Ty(LLVMContext &C); + static IntegerType *getInt8Ty(LLVMContext &C); + static IntegerType *getInt16Ty(LLVMContext &C); + static IntegerType *getInt32Ty(LLVMContext &C); + static IntegerType *getInt64Ty(LLVMContext &C); + + //===--------------------------------------------------------------------===// + // Convenience methods for getting pointer types with one of the above builtin + // types as pointee. + // + static PointerType *getHalfPtrTy(LLVMContext &C, unsigned AS = 0); + static PointerType *getFloatPtrTy(LLVMContext &C, unsigned AS = 0); + static PointerType *getDoublePtrTy(LLVMContext &C, unsigned AS = 0); + static PointerType *getX86_FP80PtrTy(LLVMContext &C, unsigned AS = 0); + static PointerType *getFP128PtrTy(LLVMContext &C, unsigned AS = 0); + static PointerType *getPPC_FP128PtrTy(LLVMContext &C, unsigned AS = 0); + static PointerType *getX86_MMXPtrTy(LLVMContext &C, unsigned AS = 0); + static PointerType *getIntNPtrTy(LLVMContext &C, unsigned N, unsigned AS = 0); + static PointerType *getInt1PtrTy(LLVMContext &C, unsigned AS = 0); + static PointerType *getInt8PtrTy(LLVMContext &C, unsigned AS = 0); + static PointerType *getInt16PtrTy(LLVMContext &C, unsigned AS = 0); + static PointerType *getInt32PtrTy(LLVMContext &C, unsigned AS = 0); + static PointerType *getInt64PtrTy(LLVMContext &C, unsigned AS = 0); + + /// getPointerTo - Return a pointer to the current type. This is equivalent + /// to PointerType::get(Foo, AddrSpace). + PointerType *getPointerTo(unsigned AddrSpace = 0); + +private: + /// isSizedDerivedType - Derived types like structures and arrays are sized + /// iff all of the members of the type are sized as well. Since asking for + /// their size is relatively uncommon, move this operation out of line. + bool isSizedDerivedType() const; +}; + +// Printing of types. +static inline raw_ostream &operator<<(raw_ostream &OS, Type &T) { + T.print(OS); + return OS; +} + +// allow isa<PointerType>(x) to work without DerivedTypes.h included. +template <> struct isa_impl<PointerType, Type> { + static inline bool doit(const Type &Ty) { + return Ty.getTypeID() == Type::PointerTyID; + } +}; + + +//===----------------------------------------------------------------------===// +// Provide specializations of GraphTraits to be able to treat a type as a +// graph of sub types. + + +template <> struct GraphTraits<Type*> { + typedef Type NodeType; + typedef Type::subtype_iterator ChildIteratorType; + + static inline NodeType *getEntryNode(Type *T) { return T; } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->subtype_begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->subtype_end(); + } +}; + +template <> struct GraphTraits<const Type*> { + typedef const Type NodeType; + typedef Type::subtype_iterator ChildIteratorType; + + static inline NodeType *getEntryNode(NodeType *T) { return T; } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->subtype_begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->subtype_end(); + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/IR/TypeBuilder.h b/include/llvm/IR/TypeBuilder.h new file mode 100644 index 0000000..80c60a0 --- /dev/null +++ b/include/llvm/IR/TypeBuilder.h @@ -0,0 +1,399 @@ +//===---- llvm/TypeBuilder.h - Builder for LLVM types -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the TypeBuilder class, which is used as a convenient way to +// create LLVM types with a consistent and simplified interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_TYPEBUILDER_H +#define LLVM_IR_TYPEBUILDER_H + +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/LLVMContext.h" +#include <limits.h> + +namespace llvm { + +/// TypeBuilder - This provides a uniform API for looking up types +/// known at compile time. To support cross-compilation, we define a +/// series of tag types in the llvm::types namespace, like i<N>, +/// ieee_float, ppc_fp128, etc. TypeBuilder<T, false> allows T to be +/// any of these, a native C type (whose size may depend on the host +/// compiler), or a pointer, function, or struct type built out of +/// these. TypeBuilder<T, true> removes native C types from this set +/// to guarantee that its result is suitable for cross-compilation. +/// We define the primitive types, pointer types, and functions up to +/// 5 arguments here, but to use this class with your own types, +/// you'll need to specialize it. For example, say you want to call a +/// function defined externally as: +/// +/// struct MyType { +/// int32 a; +/// int32 *b; +/// void *array[1]; // Intended as a flexible array. +/// }; +/// int8 AFunction(struct MyType *value); +/// +/// You'll want to use +/// Function::Create(TypeBuilder<types::i<8>(MyType*), true>::get(), ...) +/// to declare the function, but when you first try this, your compiler will +/// complain that TypeBuilder<MyType, true>::get() doesn't exist. To fix this, +/// write: +/// +/// namespace llvm { +/// template<bool xcompile> class TypeBuilder<MyType, xcompile> { +/// public: +/// static StructType *get(LLVMContext &Context) { +/// // If you cache this result, be sure to cache it separately +/// // for each LLVMContext. +/// return StructType::get( +/// TypeBuilder<types::i<32>, xcompile>::get(Context), +/// TypeBuilder<types::i<32>*, xcompile>::get(Context), +/// TypeBuilder<types::i<8>*[], xcompile>::get(Context), +/// NULL); +/// } +/// +/// // You may find this a convenient place to put some constants +/// // to help with getelementptr. They don't have any effect on +/// // the operation of TypeBuilder. +/// enum Fields { +/// FIELD_A, +/// FIELD_B, +/// FIELD_ARRAY +/// }; +/// } +/// } // namespace llvm +/// +/// TypeBuilder cannot handle recursive types or types you only know at runtime. +/// If you try to give it a recursive type, it will deadlock, infinitely +/// recurse, or do something similarly undesirable. +template<typename T, bool cross_compilable> class TypeBuilder {}; + +// Types for use with cross-compilable TypeBuilders. These correspond +// exactly with an LLVM-native type. +namespace types { +/// i<N> corresponds to the LLVM IntegerType with N bits. +template<uint32_t num_bits> class i {}; + +// The following classes represent the LLVM floating types. +class ieee_float {}; +class ieee_double {}; +class x86_fp80 {}; +class fp128 {}; +class ppc_fp128 {}; +// X86 MMX. +class x86_mmx {}; +} // namespace types + +// LLVM doesn't have const or volatile types. +template<typename T, bool cross> class TypeBuilder<const T, cross> + : public TypeBuilder<T, cross> {}; +template<typename T, bool cross> class TypeBuilder<volatile T, cross> + : public TypeBuilder<T, cross> {}; +template<typename T, bool cross> class TypeBuilder<const volatile T, cross> + : public TypeBuilder<T, cross> {}; + +// Pointers +template<typename T, bool cross> class TypeBuilder<T*, cross> { +public: + static PointerType *get(LLVMContext &Context) { + return PointerType::getUnqual(TypeBuilder<T,cross>::get(Context)); + } +}; + +/// There is no support for references +template<typename T, bool cross> class TypeBuilder<T&, cross> {}; + +// Arrays +template<typename T, size_t N, bool cross> class TypeBuilder<T[N], cross> { +public: + static ArrayType *get(LLVMContext &Context) { + return ArrayType::get(TypeBuilder<T, cross>::get(Context), N); + } +}; +/// LLVM uses an array of length 0 to represent an unknown-length array. +template<typename T, bool cross> class TypeBuilder<T[], cross> { +public: + static ArrayType *get(LLVMContext &Context) { + return ArrayType::get(TypeBuilder<T, cross>::get(Context), 0); + } +}; + +// Define the C integral types only for TypeBuilder<T, false>. +// +// C integral types do not have a defined size. It would be nice to use the +// stdint.h-defined typedefs that do have defined sizes, but we'd run into the +// following problem: +// +// On an ILP32 machine, stdint.h might define: +// +// typedef int int32_t; +// typedef long long int64_t; +// typedef long size_t; +// +// If we defined TypeBuilder<int32_t> and TypeBuilder<int64_t>, then any use of +// TypeBuilder<size_t> would fail. We couldn't define TypeBuilder<size_t> in +// addition to the defined-size types because we'd get duplicate definitions on +// platforms where stdint.h instead defines: +// +// typedef int int32_t; +// typedef long long int64_t; +// typedef int size_t; +// +// So we define all the primitive C types and nothing else. +#define DEFINE_INTEGRAL_TYPEBUILDER(T) \ +template<> class TypeBuilder<T, false> { \ +public: \ + static IntegerType *get(LLVMContext &Context) { \ + return IntegerType::get(Context, sizeof(T) * CHAR_BIT); \ + } \ +}; \ +template<> class TypeBuilder<T, true> { \ + /* We provide a definition here so users don't accidentally */ \ + /* define these types to work. */ \ +} +DEFINE_INTEGRAL_TYPEBUILDER(char); +DEFINE_INTEGRAL_TYPEBUILDER(signed char); +DEFINE_INTEGRAL_TYPEBUILDER(unsigned char); +DEFINE_INTEGRAL_TYPEBUILDER(short); +DEFINE_INTEGRAL_TYPEBUILDER(unsigned short); +DEFINE_INTEGRAL_TYPEBUILDER(int); +DEFINE_INTEGRAL_TYPEBUILDER(unsigned int); +DEFINE_INTEGRAL_TYPEBUILDER(long); +DEFINE_INTEGRAL_TYPEBUILDER(unsigned long); +#ifdef _MSC_VER +DEFINE_INTEGRAL_TYPEBUILDER(__int64); +DEFINE_INTEGRAL_TYPEBUILDER(unsigned __int64); +#else /* _MSC_VER */ +DEFINE_INTEGRAL_TYPEBUILDER(long long); +DEFINE_INTEGRAL_TYPEBUILDER(unsigned long long); +#endif /* _MSC_VER */ +#undef DEFINE_INTEGRAL_TYPEBUILDER + +template<uint32_t num_bits, bool cross> +class TypeBuilder<types::i<num_bits>, cross> { +public: + static IntegerType *get(LLVMContext &C) { + return IntegerType::get(C, num_bits); + } +}; + +template<> class TypeBuilder<float, false> { +public: + static Type *get(LLVMContext& C) { + return Type::getFloatTy(C); + } +}; +template<> class TypeBuilder<float, true> {}; + +template<> class TypeBuilder<double, false> { +public: + static Type *get(LLVMContext& C) { + return Type::getDoubleTy(C); + } +}; +template<> class TypeBuilder<double, true> {}; + +template<bool cross> class TypeBuilder<types::ieee_float, cross> { +public: + static Type *get(LLVMContext& C) { return Type::getFloatTy(C); } +}; +template<bool cross> class TypeBuilder<types::ieee_double, cross> { +public: + static Type *get(LLVMContext& C) { return Type::getDoubleTy(C); } +}; +template<bool cross> class TypeBuilder<types::x86_fp80, cross> { +public: + static Type *get(LLVMContext& C) { return Type::getX86_FP80Ty(C); } +}; +template<bool cross> class TypeBuilder<types::fp128, cross> { +public: + static Type *get(LLVMContext& C) { return Type::getFP128Ty(C); } +}; +template<bool cross> class TypeBuilder<types::ppc_fp128, cross> { +public: + static Type *get(LLVMContext& C) { return Type::getPPC_FP128Ty(C); } +}; +template<bool cross> class TypeBuilder<types::x86_mmx, cross> { +public: + static Type *get(LLVMContext& C) { return Type::getX86_MMXTy(C); } +}; + +template<bool cross> class TypeBuilder<void, cross> { +public: + static Type *get(LLVMContext &C) { + return Type::getVoidTy(C); + } +}; + +/// void* is disallowed in LLVM types, but it occurs often enough in C code that +/// we special case it. +template<> class TypeBuilder<void*, false> + : public TypeBuilder<types::i<8>*, false> {}; +template<> class TypeBuilder<const void*, false> + : public TypeBuilder<types::i<8>*, false> {}; +template<> class TypeBuilder<volatile void*, false> + : public TypeBuilder<types::i<8>*, false> {}; +template<> class TypeBuilder<const volatile void*, false> + : public TypeBuilder<types::i<8>*, false> {}; + +template<typename R, bool cross> class TypeBuilder<R(), cross> { +public: + static FunctionType *get(LLVMContext &Context) { + return FunctionType::get(TypeBuilder<R, cross>::get(Context), false); + } +}; +template<typename R, typename A1, bool cross> class TypeBuilder<R(A1), cross> { +public: + static FunctionType *get(LLVMContext &Context) { + Type *params[] = { + TypeBuilder<A1, cross>::get(Context), + }; + return FunctionType::get(TypeBuilder<R, cross>::get(Context), + params, false); + } +}; +template<typename R, typename A1, typename A2, bool cross> +class TypeBuilder<R(A1, A2), cross> { +public: + static FunctionType *get(LLVMContext &Context) { + Type *params[] = { + TypeBuilder<A1, cross>::get(Context), + TypeBuilder<A2, cross>::get(Context), + }; + return FunctionType::get(TypeBuilder<R, cross>::get(Context), + params, false); + } +}; +template<typename R, typename A1, typename A2, typename A3, bool cross> +class TypeBuilder<R(A1, A2, A3), cross> { +public: + static FunctionType *get(LLVMContext &Context) { + Type *params[] = { + TypeBuilder<A1, cross>::get(Context), + TypeBuilder<A2, cross>::get(Context), + TypeBuilder<A3, cross>::get(Context), + }; + return FunctionType::get(TypeBuilder<R, cross>::get(Context), + params, false); + } +}; + +template<typename R, typename A1, typename A2, typename A3, typename A4, + bool cross> +class TypeBuilder<R(A1, A2, A3, A4), cross> { +public: + static FunctionType *get(LLVMContext &Context) { + Type *params[] = { + TypeBuilder<A1, cross>::get(Context), + TypeBuilder<A2, cross>::get(Context), + TypeBuilder<A3, cross>::get(Context), + TypeBuilder<A4, cross>::get(Context), + }; + return FunctionType::get(TypeBuilder<R, cross>::get(Context), + params, false); + } +}; + +template<typename R, typename A1, typename A2, typename A3, typename A4, + typename A5, bool cross> +class TypeBuilder<R(A1, A2, A3, A4, A5), cross> { +public: + static FunctionType *get(LLVMContext &Context) { + Type *params[] = { + TypeBuilder<A1, cross>::get(Context), + TypeBuilder<A2, cross>::get(Context), + TypeBuilder<A3, cross>::get(Context), + TypeBuilder<A4, cross>::get(Context), + TypeBuilder<A5, cross>::get(Context), + }; + return FunctionType::get(TypeBuilder<R, cross>::get(Context), + params, false); + } +}; + +template<typename R, bool cross> class TypeBuilder<R(...), cross> { +public: + static FunctionType *get(LLVMContext &Context) { + return FunctionType::get(TypeBuilder<R, cross>::get(Context), true); + } +}; +template<typename R, typename A1, bool cross> +class TypeBuilder<R(A1, ...), cross> { +public: + static FunctionType *get(LLVMContext &Context) { + Type *params[] = { + TypeBuilder<A1, cross>::get(Context), + }; + return FunctionType::get(TypeBuilder<R, cross>::get(Context), params, true); + } +}; +template<typename R, typename A1, typename A2, bool cross> +class TypeBuilder<R(A1, A2, ...), cross> { +public: + static FunctionType *get(LLVMContext &Context) { + Type *params[] = { + TypeBuilder<A1, cross>::get(Context), + TypeBuilder<A2, cross>::get(Context), + }; + return FunctionType::get(TypeBuilder<R, cross>::get(Context), + params, true); + } +}; +template<typename R, typename A1, typename A2, typename A3, bool cross> +class TypeBuilder<R(A1, A2, A3, ...), cross> { +public: + static FunctionType *get(LLVMContext &Context) { + Type *params[] = { + TypeBuilder<A1, cross>::get(Context), + TypeBuilder<A2, cross>::get(Context), + TypeBuilder<A3, cross>::get(Context), + }; + return FunctionType::get(TypeBuilder<R, cross>::get(Context), + params, true); + } +}; + +template<typename R, typename A1, typename A2, typename A3, typename A4, + bool cross> +class TypeBuilder<R(A1, A2, A3, A4, ...), cross> { +public: + static FunctionType *get(LLVMContext &Context) { + Type *params[] = { + TypeBuilder<A1, cross>::get(Context), + TypeBuilder<A2, cross>::get(Context), + TypeBuilder<A3, cross>::get(Context), + TypeBuilder<A4, cross>::get(Context), + }; + return FunctionType::get(TypeBuilder<R, cross>::get(Context), + params, true); + } +}; + +template<typename R, typename A1, typename A2, typename A3, typename A4, + typename A5, bool cross> +class TypeBuilder<R(A1, A2, A3, A4, A5, ...), cross> { +public: + static FunctionType *get(LLVMContext &Context) { + Type *params[] = { + TypeBuilder<A1, cross>::get(Context), + TypeBuilder<A2, cross>::get(Context), + TypeBuilder<A3, cross>::get(Context), + TypeBuilder<A4, cross>::get(Context), + TypeBuilder<A5, cross>::get(Context), + }; + return FunctionType::get(TypeBuilder<R, cross>::get(Context), + params, true); + } +}; + +} // namespace llvm + +#endif diff --git a/include/llvm/IR/TypeFinder.h b/include/llvm/IR/TypeFinder.h new file mode 100644 index 0000000..cea66a4 --- /dev/null +++ b/include/llvm/IR/TypeFinder.h @@ -0,0 +1,78 @@ +//===-- llvm/IR/TypeFinder.h - Class to find used struct types --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the TypeFinder class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_TYPEFINDER_H +#define LLVM_IR_TYPEFINDER_H + +#include "llvm/ADT/DenseSet.h" +#include <vector> + +namespace llvm { + +class MDNode; +class Module; +class StructType; +class Type; +class Value; + +/// TypeFinder - Walk over a module, identifying all of the types that are +/// used by the module. +class TypeFinder { + // To avoid walking constant expressions multiple times and other IR + // objects, we keep several helper maps. + DenseSet<const Value*> VisitedConstants; + DenseSet<Type*> VisitedTypes; + + std::vector<StructType*> StructTypes; + bool OnlyNamed; + +public: + TypeFinder() : OnlyNamed(false) {} + + void run(const Module &M, bool onlyNamed); + void clear(); + + typedef std::vector<StructType*>::iterator iterator; + typedef std::vector<StructType*>::const_iterator const_iterator; + + iterator begin() { return StructTypes.begin(); } + iterator end() { return StructTypes.end(); } + + const_iterator begin() const { return StructTypes.begin(); } + const_iterator end() const { return StructTypes.end(); } + + bool empty() const { return StructTypes.empty(); } + size_t size() const { return StructTypes.size(); } + iterator erase(iterator I, iterator E) { return StructTypes.erase(I, E); } + + StructType *&operator[](unsigned Idx) { return StructTypes[Idx]; } + +private: + /// incorporateType - This method adds the type to the list of used + /// structures if it's not in there already. + void incorporateType(Type *Ty); + + /// incorporateValue - This method is used to walk operand lists finding types + /// hiding in constant expressions and other operands that won't be walked in + /// other ways. GlobalValues, basic blocks, instructions, and inst operands + /// are all explicitly enumerated. + void incorporateValue(const Value *V); + + /// incorporateMDNode - This method is used to walk the operands of an MDNode + /// to find types hiding within. + void incorporateMDNode(const MDNode *V); +}; + +} // end llvm namespace + +#endif diff --git a/include/llvm/IR/Use.h b/include/llvm/IR/Use.h new file mode 100644 index 0000000..4bc7ce5 --- /dev/null +++ b/include/llvm/IR/Use.h @@ -0,0 +1,219 @@ +//===-- llvm/Use.h - Definition of the Use class ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This defines the Use class. The Use class represents the operand of an +// instruction or some other User instance which refers to a Value. The Use +// class keeps the "use list" of the referenced value up to date. +// +// Pointer tagging is used to efficiently find the User corresponding +// to a Use without having to store a User pointer in every Use. A +// User is preceded in memory by all the Uses corresponding to its +// operands, and the low bits of one of the fields (Prev) of the Use +// class are used to encode offsets to be able to find that User given +// a pointer to any Use. For details, see: +// +// http://www.llvm.org/docs/ProgrammersManual.html#UserLayout +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_USE_H +#define LLVM_IR_USE_H + +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/Support/Compiler.h" +#include <cstddef> +#include <iterator> + +namespace llvm { + +class Value; +class User; +class Use; +template<typename> +struct simplify_type; + +// Use** is only 4-byte aligned. +template<> +class PointerLikeTypeTraits<Use**> { +public: + static inline void *getAsVoidPointer(Use** P) { return P; } + static inline Use **getFromVoidPointer(void *P) { + return static_cast<Use**>(P); + } + enum { NumLowBitsAvailable = 2 }; +}; + +//===----------------------------------------------------------------------===// +// Use Class +//===----------------------------------------------------------------------===// + +/// Use is here to make keeping the "use" list of a Value up-to-date really +/// easy. +class Use { +public: + /// swap - provide a fast substitute to std::swap<Use> + /// that also works with less standard-compliant compilers + void swap(Use &RHS); + + // A type for the word following an array of hung-off Uses in memory, which is + // a pointer back to their User with the bottom bit set. + typedef PointerIntPair<User*, 1, unsigned> UserRef; + +private: + Use(const Use &U) LLVM_DELETED_FUNCTION; + + /// Destructor - Only for zap() + ~Use() { + if (Val) removeFromList(); + } + + enum PrevPtrTag { zeroDigitTag + , oneDigitTag + , stopTag + , fullStopTag }; + + /// Constructor + Use(PrevPtrTag tag) : Val(0) { + Prev.setInt(tag); + } + +public: + /// Normally Use will just implicitly convert to a Value* that it holds. + operator Value*() const { return Val; } + + /// If implicit conversion to Value* doesn't work, the get() method returns + /// the Value*. + Value *get() const { return Val; } + + /// getUser - This returns the User that contains this Use. For an + /// instruction operand, for example, this will return the instruction. + User *getUser() const; + + inline void set(Value *Val); + + Value *operator=(Value *RHS) { + set(RHS); + return RHS; + } + const Use &operator=(const Use &RHS) { + set(RHS.Val); + return *this; + } + + Value *operator->() { return Val; } + const Value *operator->() const { return Val; } + + Use *getNext() const { return Next; } + + + /// initTags - initialize the waymarking tags on an array of Uses, so that + /// getUser() can find the User from any of those Uses. + static Use *initTags(Use *Start, Use *Stop); + + /// zap - This is used to destroy Use operands when the number of operands of + /// a User changes. + static void zap(Use *Start, const Use *Stop, bool del = false); + +private: + const Use* getImpliedUser() const; + + Value *Val; + Use *Next; + PointerIntPair<Use**, 2, PrevPtrTag> Prev; + + void setPrev(Use **NewPrev) { + Prev.setPointer(NewPrev); + } + void addToList(Use **List) { + Next = *List; + if (Next) Next->setPrev(&Next); + setPrev(List); + *List = this; + } + void removeFromList() { + Use **StrippedPrev = Prev.getPointer(); + *StrippedPrev = Next; + if (Next) Next->setPrev(StrippedPrev); + } + + friend class Value; +}; + +// simplify_type - Allow clients to treat uses just like values when using +// casting operators. +template<> struct simplify_type<Use> { + typedef Value* SimpleType; + static SimpleType getSimplifiedValue(Use &Val) { + return Val.get(); + } +}; +template<> struct simplify_type<const Use> { + typedef /*const*/ Value* SimpleType; + static SimpleType getSimplifiedValue(const Use &Val) { + return Val.get(); + } +}; + + + +template<typename UserTy> // UserTy == 'User' or 'const User' +class value_use_iterator : public std::iterator<std::forward_iterator_tag, + UserTy*, ptrdiff_t> { + typedef std::iterator<std::forward_iterator_tag, UserTy*, ptrdiff_t> super; + typedef value_use_iterator<UserTy> _Self; + + Use *U; + explicit value_use_iterator(Use *u) : U(u) {} + friend class Value; +public: + typedef typename super::reference reference; + typedef typename super::pointer pointer; + + value_use_iterator(const _Self &I) : U(I.U) {} + value_use_iterator() {} + + bool operator==(const _Self &x) const { + return U == x.U; + } + bool operator!=(const _Self &x) const { + return !operator==(x); + } + + /// atEnd - return true if this iterator is equal to use_end() on the value. + bool atEnd() const { return U == 0; } + + // Iterator traversal: forward iteration only + _Self &operator++() { // Preincrement + assert(U && "Cannot increment end iterator!"); + U = U->getNext(); + return *this; + } + _Self operator++(int) { // Postincrement + _Self tmp = *this; ++*this; return tmp; + } + + // Retrieve a pointer to the current User. + UserTy *operator*() const { + assert(U && "Cannot dereference end iterator!"); + return U->getUser(); + } + + UserTy *operator->() const { return operator*(); } + + Use &getUse() const { return *U; } + + /// getOperandNo - Return the operand # of this use in its User. Defined in + /// User.h + /// + unsigned getOperandNo() const; +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/IR/User.h b/include/llvm/IR/User.h new file mode 100644 index 0000000..505bdeb --- /dev/null +++ b/include/llvm/IR/User.h @@ -0,0 +1,205 @@ +//===-- llvm/User.h - User class definition ---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class defines the interface that one who uses a Value must implement. +// Each instance of the Value class keeps track of what User's have handles +// to it. +// +// * Instructions are the largest class of Users. +// * Constants may be users of other constants (think arrays and stuff) +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_USER_H +#define LLVM_IR_USER_H + +#include "llvm/IR/Value.h" +#include "llvm/Support/ErrorHandling.h" + +namespace llvm { + +/// OperandTraits - Compile-time customization of +/// operand-related allocators and accessors +/// for use of the User class +template <class> +struct OperandTraits; + +class User : public Value { + User(const User &) LLVM_DELETED_FUNCTION; + void *operator new(size_t) LLVM_DELETED_FUNCTION; + template <unsigned> + friend struct HungoffOperandTraits; + virtual void anchor(); +protected: + /// OperandList - This is a pointer to the array of Uses for this User. + /// For nodes of fixed arity (e.g. a binary operator) this array will live + /// prefixed to some derived class instance. For nodes of resizable variable + /// arity (e.g. PHINodes, SwitchInst etc.), this memory will be dynamically + /// allocated and should be destroyed by the classes' virtual dtor. + Use *OperandList; + + /// NumOperands - The number of values used by this User. + /// + unsigned NumOperands; + + void *operator new(size_t s, unsigned Us); + User(Type *ty, unsigned vty, Use *OpList, unsigned NumOps) + : Value(ty, vty), OperandList(OpList), NumOperands(NumOps) {} + Use *allocHungoffUses(unsigned) const; + void dropHungoffUses() { + Use::zap(OperandList, OperandList + NumOperands, true); + OperandList = 0; + // Reset NumOperands so User::operator delete() does the right thing. + NumOperands = 0; + } +public: + ~User() { + Use::zap(OperandList, OperandList + NumOperands); + } + /// operator delete - free memory allocated for User and Use objects + void operator delete(void *Usr); + /// placement delete - required by std, but never called. + void operator delete(void*, unsigned) { + llvm_unreachable("Constructor throws?"); + } + /// placement delete - required by std, but never called. + void operator delete(void*, unsigned, bool) { + llvm_unreachable("Constructor throws?"); + } +protected: + template <int Idx, typename U> static Use &OpFrom(const U *that) { + return Idx < 0 + ? OperandTraits<U>::op_end(const_cast<U*>(that))[Idx] + : OperandTraits<U>::op_begin(const_cast<U*>(that))[Idx]; + } + template <int Idx> Use &Op() { + return OpFrom<Idx>(this); + } + template <int Idx> const Use &Op() const { + return OpFrom<Idx>(this); + } +public: + Value *getOperand(unsigned i) const { + assert(i < NumOperands && "getOperand() out of range!"); + return OperandList[i]; + } + void setOperand(unsigned i, Value *Val) { + assert(i < NumOperands && "setOperand() out of range!"); + assert((!isa<Constant>((const Value*)this) || + isa<GlobalValue>((const Value*)this)) && + "Cannot mutate a constant with setOperand!"); + OperandList[i] = Val; + } + const Use &getOperandUse(unsigned i) const { + assert(i < NumOperands && "getOperandUse() out of range!"); + return OperandList[i]; + } + Use &getOperandUse(unsigned i) { + assert(i < NumOperands && "getOperandUse() out of range!"); + return OperandList[i]; + } + + unsigned getNumOperands() const { return NumOperands; } + + // --------------------------------------------------------------------------- + // Operand Iterator interface... + // + typedef Use* op_iterator; + typedef const Use* const_op_iterator; + + inline op_iterator op_begin() { return OperandList; } + inline const_op_iterator op_begin() const { return OperandList; } + inline op_iterator op_end() { return OperandList+NumOperands; } + inline const_op_iterator op_end() const { return OperandList+NumOperands; } + + /// Convenience iterator for directly iterating over the Values in the + /// OperandList + class value_op_iterator : public std::iterator<std::forward_iterator_tag, + Value*> { + op_iterator OI; + public: + explicit value_op_iterator(Use *U) : OI(U) {} + + bool operator==(const value_op_iterator &x) const { + return OI == x.OI; + } + bool operator!=(const value_op_iterator &x) const { + return !operator==(x); + } + + /// Iterator traversal: forward iteration only + value_op_iterator &operator++() { // Preincrement + ++OI; + return *this; + } + value_op_iterator operator++(int) { // Postincrement + value_op_iterator tmp = *this; ++*this; return tmp; + } + + /// Retrieve a pointer to the current Value. + Value *operator*() const { + return *OI; + } + + Value *operator->() const { return operator*(); } + }; + + inline value_op_iterator value_op_begin() { + return value_op_iterator(op_begin()); + } + inline value_op_iterator value_op_end() { + return value_op_iterator(op_end()); + } + + // dropAllReferences() - This function is in charge of "letting go" of all + // objects that this User refers to. This allows one to + // 'delete' a whole class at a time, even though there may be circular + // references... First all references are dropped, and all use counts go to + // zero. Then everything is deleted for real. Note that no operations are + // valid on an object that has "dropped all references", except operator + // delete. + // + void dropAllReferences() { + for (op_iterator i = op_begin(), e = op_end(); i != e; ++i) + i->set(0); + } + + /// replaceUsesOfWith - Replaces all references to the "From" definition with + /// references to the "To" definition. + /// + void replaceUsesOfWith(Value *From, Value *To); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Value *V) { + return isa<Instruction>(V) || isa<Constant>(V); + } +}; + +template<> struct simplify_type<User::op_iterator> { + typedef Value* SimpleType; + static SimpleType getSimplifiedValue(User::op_iterator &Val) { + return Val->get(); + } +}; +template<> struct simplify_type<User::const_op_iterator> { + typedef /*const*/ Value* SimpleType; + static SimpleType getSimplifiedValue(User::const_op_iterator &Val) { + return Val->get(); + } +}; + +// value_use_iterator::getOperandNo - Requires the definition of the User class. +template<typename UserTy> +unsigned value_use_iterator<UserTy>::getOperandNo() const { + return U - U->getUser()->op_begin(); +} + +} // End llvm namespace + +#endif diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h new file mode 100644 index 0000000..a4f7862 --- /dev/null +++ b/include/llvm/IR/Value.h @@ -0,0 +1,411 @@ +//===-- llvm/Value.h - Definition of the Value class ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the Value class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_VALUE_H +#define LLVM_IR_VALUE_H + +#include "llvm/IR/Use.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Compiler.h" + +namespace llvm { + +class Constant; +class Argument; +class Instruction; +class BasicBlock; +class GlobalValue; +class Function; +class GlobalVariable; +class GlobalAlias; +class InlineAsm; +class ValueSymbolTable; +template<typename ValueTy> class StringMapEntry; +typedef StringMapEntry<Value*> ValueName; +class raw_ostream; +class AssemblyAnnotationWriter; +class ValueHandleBase; +class LLVMContext; +class Twine; +class MDNode; +class Type; +class StringRef; + +//===----------------------------------------------------------------------===// +// Value Class +//===----------------------------------------------------------------------===// + +/// This is a very important LLVM class. It is the base class of all values +/// computed by a program that may be used as operands to other values. Value is +/// the super class of other important classes such as Instruction and Function. +/// All Values have a Type. Type is not a subclass of Value. Some values can +/// have a name and they belong to some Module. Setting the name on the Value +/// automatically updates the module's symbol table. +/// +/// Every value has a "use list" that keeps track of which other Values are +/// using this Value. A Value can also have an arbitrary number of ValueHandle +/// objects that watch it and listen to RAUW and Destroy events. See +/// llvm/Support/ValueHandle.h for details. +/// +/// @brief LLVM Value Representation +class Value { + const unsigned char SubclassID; // Subclass identifier (for isa/dyn_cast) + unsigned char HasValueHandle : 1; // Has a ValueHandle pointing to this? +protected: + /// SubclassOptionalData - This member is similar to SubclassData, however it + /// is for holding information which may be used to aid optimization, but + /// which may be cleared to zero without affecting conservative + /// interpretation. + unsigned char SubclassOptionalData : 7; + +private: + /// SubclassData - This member is defined by this class, but is not used for + /// anything. Subclasses can use it to hold whatever state they find useful. + /// This field is initialized to zero by the ctor. + unsigned short SubclassData; + + Type *VTy; + Use *UseList; + + friend class ValueSymbolTable; // Allow ValueSymbolTable to directly mod Name. + friend class ValueHandleBase; + ValueName *Name; + + void operator=(const Value &) LLVM_DELETED_FUNCTION; + Value(const Value &) LLVM_DELETED_FUNCTION; + +protected: + /// printCustom - Value subclasses can override this to implement custom + /// printing behavior. + virtual void printCustom(raw_ostream &O) const; + + Value(Type *Ty, unsigned scid); +public: + virtual ~Value(); + + /// dump - Support for debugging, callable in GDB: V->dump() + // + void dump() const; + + /// print - Implement operator<< on Value. + /// + void print(raw_ostream &O, AssemblyAnnotationWriter *AAW = 0) const; + + /// All values are typed, get the type of this value. + /// + Type *getType() const { return VTy; } + + /// All values hold a context through their type. + LLVMContext &getContext() const; + + // All values can potentially be named. + bool hasName() const { return Name != 0 && SubclassID != MDStringVal; } + ValueName *getValueName() const { return Name; } + void setValueName(ValueName *VN) { Name = VN; } + + /// getName() - Return a constant reference to the value's name. This is cheap + /// and guaranteed to return the same reference as long as the value is not + /// modified. + StringRef getName() const; + + /// setName() - Change the name of the value, choosing a new unique name if + /// the provided name is taken. + /// + /// \param Name The new name; or "" if the value's name should be removed. + void setName(const Twine &Name); + + + /// takeName - transfer the name from V to this value, setting V's name to + /// empty. It is an error to call V->takeName(V). + void takeName(Value *V); + + /// replaceAllUsesWith - Go through the uses list for this definition and make + /// each use point to "V" instead of "this". After this completes, 'this's + /// use list is guaranteed to be empty. + /// + void replaceAllUsesWith(Value *V); + + //---------------------------------------------------------------------- + // Methods for handling the chain of uses of this Value. + // + typedef value_use_iterator<User> use_iterator; + typedef value_use_iterator<const User> const_use_iterator; + + bool use_empty() const { return UseList == 0; } + use_iterator use_begin() { return use_iterator(UseList); } + const_use_iterator use_begin() const { return const_use_iterator(UseList); } + use_iterator use_end() { return use_iterator(0); } + const_use_iterator use_end() const { return const_use_iterator(0); } + User *use_back() { return *use_begin(); } + const User *use_back() const { return *use_begin(); } + + /// hasOneUse - Return true if there is exactly one user of this value. This + /// is specialized because it is a common request and does not require + /// traversing the whole use list. + /// + bool hasOneUse() const { + const_use_iterator I = use_begin(), E = use_end(); + if (I == E) return false; + return ++I == E; + } + + /// hasNUses - Return true if this Value has exactly N users. + /// + bool hasNUses(unsigned N) const; + + /// hasNUsesOrMore - Return true if this value has N users or more. This is + /// logically equivalent to getNumUses() >= N. + /// + bool hasNUsesOrMore(unsigned N) const; + + bool isUsedInBasicBlock(const BasicBlock *BB) const; + + /// getNumUses - This method computes the number of uses of this Value. This + /// is a linear time operation. Use hasOneUse, hasNUses, or hasNUsesOrMore + /// to check for specific values. + unsigned getNumUses() const; + + /// addUse - This method should only be used by the Use class. + /// + void addUse(Use &U) { U.addToList(&UseList); } + + /// An enumeration for keeping track of the concrete subclass of Value that + /// is actually instantiated. Values of this enumeration are kept in the + /// Value classes SubclassID field. They are used for concrete type + /// identification. + enum ValueTy { + ArgumentVal, // This is an instance of Argument + BasicBlockVal, // This is an instance of BasicBlock + FunctionVal, // This is an instance of Function + GlobalAliasVal, // This is an instance of GlobalAlias + GlobalVariableVal, // This is an instance of GlobalVariable + UndefValueVal, // This is an instance of UndefValue + BlockAddressVal, // This is an instance of BlockAddress + ConstantExprVal, // This is an instance of ConstantExpr + ConstantAggregateZeroVal, // This is an instance of ConstantAggregateZero + ConstantDataArrayVal, // This is an instance of ConstantDataArray + ConstantDataVectorVal, // This is an instance of ConstantDataVector + ConstantIntVal, // This is an instance of ConstantInt + ConstantFPVal, // This is an instance of ConstantFP + ConstantArrayVal, // This is an instance of ConstantArray + ConstantStructVal, // This is an instance of ConstantStruct + ConstantVectorVal, // This is an instance of ConstantVector + ConstantPointerNullVal, // This is an instance of ConstantPointerNull + MDNodeVal, // This is an instance of MDNode + MDStringVal, // This is an instance of MDString + InlineAsmVal, // This is an instance of InlineAsm + PseudoSourceValueVal, // This is an instance of PseudoSourceValue + FixedStackPseudoSourceValueVal, // This is an instance of + // FixedStackPseudoSourceValue + InstructionVal, // This is an instance of Instruction + // Enum values starting at InstructionVal are used for Instructions; + // don't add new values here! + + // Markers: + ConstantFirstVal = FunctionVal, + ConstantLastVal = ConstantPointerNullVal + }; + + /// getValueID - Return an ID for the concrete type of this object. This is + /// used to implement the classof checks. This should not be used for any + /// other purpose, as the values may change as LLVM evolves. Also, note that + /// for instructions, the Instruction's opcode is added to InstructionVal. So + /// this means three things: + /// # there is no value with code InstructionVal (no opcode==0). + /// # there are more possible values for the value type than in ValueTy enum. + /// # the InstructionVal enumerator must be the highest valued enumerator in + /// the ValueTy enum. + unsigned getValueID() const { + return SubclassID; + } + + /// getRawSubclassOptionalData - Return the raw optional flags value + /// contained in this value. This should only be used when testing two + /// Values for equivalence. + unsigned getRawSubclassOptionalData() const { + return SubclassOptionalData; + } + + /// clearSubclassOptionalData - Clear the optional flags contained in + /// this value. + void clearSubclassOptionalData() { + SubclassOptionalData = 0; + } + + /// hasSameSubclassOptionalData - Test whether the optional flags contained + /// in this value are equal to the optional flags in the given value. + bool hasSameSubclassOptionalData(const Value *V) const { + return SubclassOptionalData == V->SubclassOptionalData; + } + + /// intersectOptionalDataWith - Clear any optional flags in this value + /// that are not also set in the given value. + void intersectOptionalDataWith(const Value *V) { + SubclassOptionalData &= V->SubclassOptionalData; + } + + /// hasValueHandle - Return true if there is a value handle associated with + /// this value. + bool hasValueHandle() const { return HasValueHandle; } + + /// stripPointerCasts - This method strips off any unneeded pointer casts and + /// all-zero GEPs from the specified value, returning the original uncasted + /// value. If this is called on a non-pointer value, it returns 'this'. + Value *stripPointerCasts(); + const Value *stripPointerCasts() const { + return const_cast<Value*>(this)->stripPointerCasts(); + } + + /// stripInBoundsConstantOffsets - This method strips off unneeded pointer casts and + /// all-constant GEPs from the specified value, returning the original + /// pointer value. If this is called on a non-pointer value, it returns + /// 'this'. + Value *stripInBoundsConstantOffsets(); + const Value *stripInBoundsConstantOffsets() const { + return const_cast<Value*>(this)->stripInBoundsConstantOffsets(); + } + + /// stripInBoundsOffsets - This method strips off unneeded pointer casts and + /// any in-bounds Offsets from the specified value, returning the original + /// pointer value. If this is called on a non-pointer value, it returns + /// 'this'. + Value *stripInBoundsOffsets(); + const Value *stripInBoundsOffsets() const { + return const_cast<Value*>(this)->stripInBoundsOffsets(); + } + + /// isDereferenceablePointer - Test if this value is always a pointer to + /// allocated and suitably aligned memory for a simple load or store. + bool isDereferenceablePointer() const; + + /// DoPHITranslation - If this value is a PHI node with CurBB as its parent, + /// return the value in the PHI node corresponding to PredBB. If not, return + /// ourself. This is useful if you want to know the value something has in a + /// predecessor block. + Value *DoPHITranslation(const BasicBlock *CurBB, const BasicBlock *PredBB); + + const Value *DoPHITranslation(const BasicBlock *CurBB, + const BasicBlock *PredBB) const{ + return const_cast<Value*>(this)->DoPHITranslation(CurBB, PredBB); + } + + /// MaximumAlignment - This is the greatest alignment value supported by + /// load, store, and alloca instructions, and global values. + static const unsigned MaximumAlignment = 1u << 29; + + /// mutateType - Mutate the type of this Value to be of the specified type. + /// Note that this is an extremely dangerous operation which can create + /// completely invalid IR very easily. It is strongly recommended that you + /// recreate IR objects with the right types instead of mutating them in + /// place. + void mutateType(Type *Ty) { + VTy = Ty; + } + +protected: + unsigned short getSubclassDataFromValue() const { return SubclassData; } + void setValueSubclassData(unsigned short D) { SubclassData = D; } +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const Value &V) { + V.print(OS); + return OS; +} + +void Use::set(Value *V) { + if (Val) removeFromList(); + Val = V; + if (V) V->addUse(*this); +} + + +// isa - Provide some specializations of isa so that we don't have to include +// the subtype header files to test to see if the value is a subclass... +// +template <> struct isa_impl<Constant, Value> { + static inline bool doit(const Value &Val) { + return Val.getValueID() >= Value::ConstantFirstVal && + Val.getValueID() <= Value::ConstantLastVal; + } +}; + +template <> struct isa_impl<Argument, Value> { + static inline bool doit (const Value &Val) { + return Val.getValueID() == Value::ArgumentVal; + } +}; + +template <> struct isa_impl<InlineAsm, Value> { + static inline bool doit(const Value &Val) { + return Val.getValueID() == Value::InlineAsmVal; + } +}; + +template <> struct isa_impl<Instruction, Value> { + static inline bool doit(const Value &Val) { + return Val.getValueID() >= Value::InstructionVal; + } +}; + +template <> struct isa_impl<BasicBlock, Value> { + static inline bool doit(const Value &Val) { + return Val.getValueID() == Value::BasicBlockVal; + } +}; + +template <> struct isa_impl<Function, Value> { + static inline bool doit(const Value &Val) { + return Val.getValueID() == Value::FunctionVal; + } +}; + +template <> struct isa_impl<GlobalVariable, Value> { + static inline bool doit(const Value &Val) { + return Val.getValueID() == Value::GlobalVariableVal; + } +}; + +template <> struct isa_impl<GlobalAlias, Value> { + static inline bool doit(const Value &Val) { + return Val.getValueID() == Value::GlobalAliasVal; + } +}; + +template <> struct isa_impl<GlobalValue, Value> { + static inline bool doit(const Value &Val) { + return isa<GlobalVariable>(Val) || isa<Function>(Val) || + isa<GlobalAlias>(Val); + } +}; + +template <> struct isa_impl<MDNode, Value> { + static inline bool doit(const Value &Val) { + return Val.getValueID() == Value::MDNodeVal; + } +}; + +// Value* is only 4-byte aligned. +template<> +class PointerLikeTypeTraits<Value*> { + typedef Value* PT; +public: + static inline void *getAsVoidPointer(PT P) { return P; } + static inline PT getFromVoidPointer(void *P) { + return static_cast<PT>(P); + } + enum { NumLowBitsAvailable = 2 }; +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/IR/ValueSymbolTable.h b/include/llvm/IR/ValueSymbolTable.h new file mode 100644 index 0000000..bf1fade --- /dev/null +++ b/include/llvm/IR/ValueSymbolTable.h @@ -0,0 +1,133 @@ +//===-- llvm/ValueSymbolTable.h - Implement a Value Symtab ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the name/Value symbol table for LLVM. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_VALUESYMBOLTABLE_H +#define LLVM_IR_VALUESYMBOLTABLE_H + +#include "llvm/ADT/StringMap.h" +#include "llvm/IR/Value.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + template<typename ValueSubClass, typename ItemParentClass> + class SymbolTableListTraits; + class BasicBlock; + class Function; + class NamedMDNode; + class Module; + class StringRef; + +/// This class provides a symbol table of name/value pairs. It is essentially +/// a std::map<std::string,Value*> but has a controlled interface provided by +/// LLVM as well as ensuring uniqueness of names. +/// +class ValueSymbolTable { + friend class Value; + friend class SymbolTableListTraits<Argument, Function>; + friend class SymbolTableListTraits<BasicBlock, Function>; + friend class SymbolTableListTraits<Instruction, BasicBlock>; + friend class SymbolTableListTraits<Function, Module>; + friend class SymbolTableListTraits<GlobalVariable, Module>; + friend class SymbolTableListTraits<GlobalAlias, Module>; +/// @name Types +/// @{ +public: + /// @brief A mapping of names to values. + typedef StringMap<Value*> ValueMap; + + /// @brief An iterator over a ValueMap. + typedef ValueMap::iterator iterator; + + /// @brief A const_iterator over a ValueMap. + typedef ValueMap::const_iterator const_iterator; + +/// @} +/// @name Constructors +/// @{ +public: + + ValueSymbolTable() : vmap(0), LastUnique(0) {} + ~ValueSymbolTable(); + +/// @} +/// @name Accessors +/// @{ +public: + + /// This method finds the value with the given \p Name in the + /// the symbol table. + /// @returns the value associated with the \p Name + /// @brief Lookup a named Value. + Value *lookup(StringRef Name) const { return vmap.lookup(Name); } + + /// @returns true iff the symbol table is empty + /// @brief Determine if the symbol table is empty + inline bool empty() const { return vmap.empty(); } + + /// @brief The number of name/type pairs is returned. + inline unsigned size() const { return unsigned(vmap.size()); } + + /// This function can be used from the debugger to display the + /// content of the symbol table while debugging. + /// @brief Print out symbol table on stderr + void dump() const; + +/// @} +/// @name Iteration +/// @{ +public: + /// @brief Get an iterator that from the beginning of the symbol table. + inline iterator begin() { return vmap.begin(); } + + /// @brief Get a const_iterator that from the beginning of the symbol table. + inline const_iterator begin() const { return vmap.begin(); } + + /// @brief Get an iterator to the end of the symbol table. + inline iterator end() { return vmap.end(); } + + /// @brief Get a const_iterator to the end of the symbol table. + inline const_iterator end() const { return vmap.end(); } + +/// @} +/// @name Mutators +/// @{ +private: + /// This method adds the provided value \p N to the symbol table. The Value + /// must have a name which is used to place the value in the symbol table. + /// If the inserted name conflicts, this renames the value. + /// @brief Add a named value to the symbol table + void reinsertValue(Value *V); + + /// createValueName - This method attempts to create a value name and insert + /// it into the symbol table with the specified name. If it conflicts, it + /// auto-renames the name and returns that instead. + ValueName *createValueName(StringRef Name, Value *V); + + /// This method removes a value from the symbol table. It leaves the + /// ValueName attached to the value, but it is no longer inserted in the + /// symtab. + void removeValueName(ValueName *V); + +/// @} +/// @name Internal Data +/// @{ +private: + ValueMap vmap; ///< The map that holds the symbol table. + mutable uint32_t LastUnique; ///< Counter for tracking unique names + +/// @} +}; + +} // End llvm namespace + +#endif |