diff options
Diffstat (limited to 'include')
206 files changed, 12227 insertions, 4366 deletions
diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h index 7774606..0bd5db3 100644 --- a/include/llvm-c/Core.h +++ b/include/llvm-c/Core.h @@ -21,9 +21,9 @@ /* Need these includes to support the LLVM 'cast' template for the C++ 'wrap' and 'unwrap' conversion functions. */ +#include "llvm/IRBuilder.h" #include "llvm/Module.h" #include "llvm/PassRegistry.h" -#include "llvm/Support/IRBuilder.h" extern "C" { #endif @@ -53,7 +53,7 @@ extern "C" { * The declared parameter names are descriptive and specify which type is * required. Additionally, each type hierarchy is documented along with the * functions that operate upon it. For more detail, refer to LLVM's C++ code. - * If in doubt, refer to Core.cpp, which performs paramter downcasts in the + * If in doubt, refer to Core.cpp, which performs parameter downcasts in the * form unwrap<RequiredType>(Param). * * Many exotic languages can interoperate with C code but have a harder time @@ -106,7 +106,7 @@ typedef struct LLVMOpaqueType *LLVMTypeRef; typedef struct LLVMOpaqueValue *LLVMValueRef; /** - * Represents a basic block of instruction in LLVM IR. + * Represents a basic block of instructions in LLVM IR. * * This models llvm::BasicBlock. */ @@ -478,6 +478,15 @@ void LLVMSetTarget(LLVMModuleRef M, const char *Triple); void LLVMDumpModule(LLVMModuleRef M); /** + * Print a representation of a module to a file. The ErrorMessage needs to be + * disposed with LLVMDisposeMessage. Returns 0 on success, 1 otherwise. + * + * @see Module::print() + */ +LLVMBool LLVMPrintModuleToFile(LLVMModuleRef M, const char *Filename, + char **ErrorMessage); + +/** * Set inline assembly for a module. * * @see Module::setModuleInlineAsm() @@ -977,7 +986,7 @@ LLVMTypeRef LLVMX86MMXType(void); * * LLVMValueRef essentially represents llvm::Value. There is a rich * hierarchy of classes within this type. Depending on the instance - * obtain, not all APIs are available. + * obtained, not all APIs are available. * * Callers can determine the type of a LLVMValueRef by calling the * LLVMIsA* family of functions (e.g. LLVMIsAArgument()). These @@ -1153,7 +1162,7 @@ LLVM_FOR_EACH_VALUE_SUBCLASS(LLVM_DECLARE_VALUE_CAST) * * Uses are obtained in an iterator fashion. First, call this function * to obtain a reference to the first use. Then, call LLVMGetNextUse() - * on that instance and all subsequently obtained instances untl + * on that instance and all subsequently obtained instances until * LLVMGetNextUse() returns NULL. * * @see llvm::Value::use_begin() @@ -2106,7 +2115,7 @@ LLVMBasicBlockRef LLVMGetInstructionParent(LLVMValueRef Inst); LLVMValueRef LLVMGetNextInstruction(LLVMValueRef Inst); /** - * Obtain the instruction that occured before this one. + * Obtain the instruction that occurred before this one. * * If the instruction is the first instruction in a basic block, NULL * will be returned. diff --git a/include/llvm-c/Disassembler.h b/include/llvm-c/Disassembler.h index a676e37..69fdc64 100644 --- a/include/llvm-c/Disassembler.h +++ b/include/llvm-c/Disassembler.h @@ -109,9 +109,9 @@ struct LLVMOpInfo1 { */ typedef const char *(*LLVMSymbolLookupCallback)(void *DisInfo, uint64_t ReferenceValue, - uint64_t *ReferenceType, - uint64_t ReferencePC, - const char **ReferenceName); + uint64_t *ReferenceType, + uint64_t ReferencePC, + const char **ReferenceName); /** * The reference types on input and output. */ diff --git a/include/llvm-c/Linker.h b/include/llvm-c/Linker.h new file mode 100644 index 0000000..9f337cf --- /dev/null +++ b/include/llvm-c/Linker.h @@ -0,0 +1,42 @@ +/*===-- llvm-c/Linker.h - Module Linker C Interface -------------*- 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 C interface to the module/file/archive linker. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_LINKER_H +#define LLVM_C_LINKER_H + +#include "llvm-c/Core.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef enum { + LLVMLinkerDestroySource = 0, /* Allow source module to be destroyed. */ + LLVMLinkerPreserveSource = 1 /* Preserve the source module. */ +} LLVMLinkerMode; + + +/* Links the source module into the destination module, taking ownership + * of the source module away from the caller. Optionally returns a + * human-readable description of any errors that occurred in linking. + * OutMessage must be disposed with LLVMDisposeMessage. The return value + * is true if an error occurred, false otherwise. */ +LLVMBool LLVMLinkModules(LLVMModuleRef Dest, LLVMModuleRef Src, + LLVMLinkerMode Mode, char **OutMessage); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/llvm-c/Target.h b/include/llvm-c/Target.h index 568e60d..8915040 100644 --- a/include/llvm-c/Target.h +++ b/include/llvm-c/Target.h @@ -56,19 +56,19 @@ typedef struct LLVMStructLayout *LLVMStructLayoutRef; /* Declare all of the available assembly printer initialization functions. */ #define LLVM_ASM_PRINTER(TargetName) \ - void LLVMInitialize##TargetName##AsmPrinter(); + void LLVMInitialize##TargetName##AsmPrinter(void); #include "llvm/Config/AsmPrinters.def" #undef LLVM_ASM_PRINTER /* Explicit undef to make SWIG happier */ /* Declare all of the available assembly parser initialization functions. */ #define LLVM_ASM_PARSER(TargetName) \ - void LLVMInitialize##TargetName##AsmParser(); + void LLVMInitialize##TargetName##AsmParser(void); #include "llvm/Config/AsmParsers.def" #undef LLVM_ASM_PARSER /* Explicit undef to make SWIG happier */ /* Declare all of the available disassembler initialization functions. */ #define LLVM_DISASSEMBLER(TargetName) \ - void LLVMInitialize##TargetName##Disassembler(); + void LLVMInitialize##TargetName##Disassembler(void); #include "llvm/Config/Disassemblers.def" #undef LLVM_DISASSEMBLER /* Explicit undef to make SWIG happier */ @@ -102,7 +102,7 @@ static inline void LLVMInitializeAllTargetMCs(void) { /** LLVMInitializeAllAsmPrinters - The main program should call this function if it wants all asm printers that LLVM is configured to support, to make them available via the TargetRegistry. */ -static inline void LLVMInitializeAllAsmPrinters() { +static inline void LLVMInitializeAllAsmPrinters(void) { #define LLVM_ASM_PRINTER(TargetName) LLVMInitialize##TargetName##AsmPrinter(); #include "llvm/Config/AsmPrinters.def" #undef LLVM_ASM_PRINTER /* Explicit undef to make SWIG happier */ @@ -111,7 +111,7 @@ static inline void LLVMInitializeAllAsmPrinters() { /** LLVMInitializeAllAsmParsers - The main program should call this function if it wants all asm parsers that LLVM is configured to support, to make them available via the TargetRegistry. */ -static inline void LLVMInitializeAllAsmParsers() { +static inline void LLVMInitializeAllAsmParsers(void) { #define LLVM_ASM_PARSER(TargetName) LLVMInitialize##TargetName##AsmParser(); #include "llvm/Config/AsmParsers.def" #undef LLVM_ASM_PARSER /* Explicit undef to make SWIG happier */ @@ -120,7 +120,7 @@ static inline void LLVMInitializeAllAsmParsers() { /** LLVMInitializeAllDisassemblers - The main program should call this function if it wants all disassemblers that LLVM is configured to support, to make them available via the TargetRegistry. */ -static inline void LLVMInitializeAllDisassemblers() { +static inline void LLVMInitializeAllDisassemblers(void) { #define LLVM_DISASSEMBLER(TargetName) \ LLVMInitialize##TargetName##Disassembler(); #include "llvm/Config/Disassemblers.def" diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h index 2b466f9..5a625a4 100644 --- a/include/llvm/ADT/APFloat.h +++ b/include/llvm/ADT/APFloat.h @@ -274,6 +274,7 @@ namespace llvm { /* C fmod, or llvm frem. */ opStatus mod(const APFloat &, roundingMode); opStatus fusedMultiplyAdd(const APFloat &, const APFloat &, roundingMode); + opStatus roundToIntegral(roundingMode); /* Sign operations. */ void changeSign(); diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h index 4101989..f30a6e3 100644 --- a/include/llvm/ADT/APInt.h +++ b/include/llvm/ADT/APInt.h @@ -16,6 +16,7 @@ #define LLVM_APINT_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/MathExtras.h" #include <cassert> #include <climits> @@ -273,6 +274,13 @@ public: initSlowCase(that); } +#if LLVM_USE_RVALUE_REFERENCES + /// @brief Move Constructor. + APInt(APInt&& that) : BitWidth(that.BitWidth), VAL(that.VAL) { + that.BitWidth = 0; + } +#endif + /// @brief Destructor. ~APInt() { if (!isSingleWord()) @@ -349,13 +357,7 @@ public: /// @brief Check if this APInt has an N-bits unsigned integer value. bool isIntN(unsigned N) const { assert(N && "N == 0 ???"); - if (N >= getBitWidth()) - return true; - - if (isSingleWord()) - return isUIntN(N, VAL); - return APInt(N, makeArrayRef(pVal, getNumWords())).zext(getBitWidth()) - == (*this); + return getActiveBits() <= N; } /// @brief Check if this APInt has an N-bits signed integer value. @@ -503,6 +505,18 @@ public: return getAllOnesValue(numBits).lshr(numBits - loBitsSet); } + /// \brief Determine if two APInts have the same value, after zero-extending + /// one of them (if needed!) to ensure that the bit-widths match. + static bool isSameValue(const APInt &I1, const APInt &I2) { + if (I1.getBitWidth() == I2.getBitWidth()) + return I1 == I2; + + if (I1.getBitWidth() > I2.getBitWidth()) + return I1 == I2.zext(I1.getBitWidth()); + + return I1.zext(I2.getBitWidth()) == I2; + } + /// \brief Overload to compute a hash_code for an APInt value. friend hash_code hash_value(const APInt &Arg); @@ -587,6 +601,21 @@ public: return AssignSlowCase(RHS); } +#if LLVM_USE_RVALUE_REFERENCES + /// @brief Move assignment operator. + APInt& operator=(APInt&& that) { + if (!isSingleWord()) + delete [] pVal; + + BitWidth = that.BitWidth; + VAL = that.VAL; + + that.BitWidth = 0; + + return *this; + } +#endif + /// The RHS value is assigned to *this. If the significant bits in RHS exceed /// the bit width, the excess bits are truncated. If the bit width is larger /// than 64, the value is zero filled in the unspecified high order bits. @@ -817,9 +846,10 @@ public: if (LHS.isNegative()) { if (RHS.isNegative()) APInt::udivrem(-LHS, -RHS, Quotient, Remainder); - else + else { APInt::udivrem(-LHS, RHS, Quotient, Remainder); - Quotient = -Quotient; + Quotient = -Quotient; + } Remainder = -Remainder; } else if (RHS.isNegative()) { APInt::udivrem(LHS, -RHS, Quotient, Remainder); @@ -1087,7 +1117,7 @@ public: else { // Set all the bits in all the words. for (unsigned i = 0; i < getNumWords(); ++i) - pVal[i] = -1ULL; + pVal[i] = -1ULL; } // Clear the unused ones clearUnusedBits(); diff --git a/include/llvm/ADT/APSInt.h b/include/llvm/ADT/APSInt.h index 54a7b60..048c65c 100644 --- a/include/llvm/ADT/APSInt.h +++ b/include/llvm/ADT/APSInt.h @@ -135,6 +135,19 @@ public: assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); return IsUnsigned ? uge(RHS) : sge(RHS); } + inline bool operator==(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return eq(RHS); + } + inline bool operator==(int64_t RHS) const { + return isSameValue(*this, APSInt(APInt(64, RHS), true)); + } + inline bool operator!=(const APSInt& RHS) const { + return !((*this) == RHS); + } + inline bool operator!=(int64_t RHS) const { + return !((*this) == RHS); + } // The remaining operators just wrap the logic of APInt, but retain the // signedness information. @@ -250,17 +263,50 @@ public: : APInt::getSignedMinValue(numBits), Unsigned); } + /// \brief Determine if two APSInts have the same value, zero- or + /// sign-extending as needed. + static bool isSameValue(const APSInt &I1, const APSInt &I2) { + if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned()) + return I1 == I2; + + // Check for a bit-width mismatch. + if (I1.getBitWidth() > I2.getBitWidth()) + return isSameValue(I1, I2.extend(I1.getBitWidth())); + else if (I2.getBitWidth() > I1.getBitWidth()) + return isSameValue(I1.extend(I2.getBitWidth()), I2); + + // We have a signedness mismatch. Turn the signed value into an unsigned + // value. + if (I1.isSigned()) { + if (I1.isNegative()) + return false; + + return APSInt(I1, true) == I2; + } + + if (I2.isNegative()) + return false; + + return I1 == APSInt(I2, true); + } + /// Profile - Used to insert APSInt objects, or objects that contain APSInt /// objects, into FoldingSets. void Profile(FoldingSetNodeID& ID) const; }; +inline bool operator==(int64_t V1, const APSInt& V2) { + return V2 == V1; +} +inline bool operator!=(int64_t V1, const APSInt& V2) { + return V2 != V1; +} + inline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) { I.print(OS, I.isSigned()); return OS; } - } // end namespace llvm #endif diff --git a/include/llvm/ADT/ArrayRef.h b/include/llvm/ADT/ArrayRef.h index f4c8e55..cf55aad 100644 --- a/include/llvm/ADT/ArrayRef.h +++ b/include/llvm/ADT/ArrayRef.h @@ -60,7 +60,7 @@ namespace llvm { : Data(begin), Length(end - begin) {} /// Construct an ArrayRef from a SmallVector. - /*implicit*/ ArrayRef(const SmallVectorImpl<T> &Vec) + /*implicit*/ ArrayRef(const SmallVectorTemplateCommon<T> &Vec) : Data(Vec.data()), Length(Vec.size()) {} /// Construct an ArrayRef from a std::vector. diff --git a/include/llvm/ADT/BitVector.h b/include/llvm/ADT/BitVector.h index 7e0b5ba..3e2e5f2 100644 --- a/include/llvm/ADT/BitVector.h +++ b/include/llvm/ADT/BitVector.h @@ -14,6 +14,7 @@ #ifndef LLVM_ADT_BITVECTOR_H #define LLVM_ADT_BITVECTOR_H +#include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include <algorithm> @@ -97,6 +98,13 @@ public: std::memcpy(Bits, RHS.Bits, Capacity * sizeof(BitWord)); } +#if LLVM_USE_RVALUE_REFERENCES + BitVector(BitVector &&RHS) + : Bits(RHS.Bits), Size(RHS.Size), Capacity(RHS.Capacity) { + RHS.Bits = 0; + } +#endif + ~BitVector() { std::free(Bits); } @@ -251,11 +259,6 @@ public: return *this; } - // No argument flip. - BitVector operator~() const { - return BitVector(*this).flip(); - } - // Indexing. reference operator[](unsigned Idx) { assert (Idx < Size && "Out-of-bounds Bit access."); @@ -272,6 +275,16 @@ public: return (*this)[Idx]; } + /// Test if any common bits are set. + bool anyCommon(const BitVector &RHS) const { + unsigned ThisWords = NumBitWords(size()); + unsigned RHSWords = NumBitWords(RHS.size()); + for (unsigned i = 0, e = std::min(ThisWords, RHSWords); i != e; ++i) + if (Bits[i] & RHS.Bits[i]) + return true; + return false; + } + // Comparison operators. bool operator==(const BitVector &RHS) const { unsigned ThisWords = NumBitWords(size()); @@ -366,6 +379,21 @@ public: return *this; } +#if LLVM_USE_RVALUE_REFERENCES + const BitVector &operator=(BitVector &&RHS) { + if (this == &RHS) return *this; + + std::free(Bits); + Bits = RHS.Bits; + Size = RHS.Size; + Capacity = RHS.Capacity; + + RHS.Bits = 0; + + return *this; + } +#endif + void swap(BitVector &RHS) { std::swap(Bits, RHS.Bits); std::swap(Size, RHS.Size); @@ -472,24 +500,6 @@ private: } }; -inline BitVector operator&(const BitVector &LHS, const BitVector &RHS) { - BitVector Result(LHS); - Result &= RHS; - return Result; -} - -inline BitVector operator|(const BitVector &LHS, const BitVector &RHS) { - BitVector Result(LHS); - Result |= RHS; - return Result; -} - -inline BitVector operator^(const BitVector &LHS, const BitVector &RHS) { - BitVector Result(LHS); - Result ^= RHS; - return Result; -} - } // End llvm namespace namespace std { diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h index 8d4a19d..65a70fb 100644 --- a/include/llvm/ADT/DenseMap.h +++ b/include/llvm/ADT/DenseMap.h @@ -14,6 +14,8 @@ #ifndef LLVM_ADT_DENSEMAP_H #define LLVM_ADT_DENSEMAP_H +#include "llvm/Support/Compiler.h" +#include "llvm/Support/AlignOf.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/PointerLikeTypeTraits.h" #include "llvm/Support/type_traits.h" @@ -23,6 +25,7 @@ #include <new> #include <utility> #include <cassert> +#include <climits> #include <cstddef> #include <cstring> @@ -33,116 +36,83 @@ template<typename KeyT, typename ValueT, bool IsConst = false> class DenseMapIterator; -template<typename KeyT, typename ValueT, - typename KeyInfoT = DenseMapInfo<KeyT> > -class DenseMap { +template<typename DerivedT, + typename KeyT, typename ValueT, typename KeyInfoT> +class DenseMapBase { +protected: typedef std::pair<KeyT, ValueT> BucketT; - unsigned NumBuckets; - BucketT *Buckets; - unsigned NumEntries; - unsigned NumTombstones; public: typedef KeyT key_type; typedef ValueT mapped_type; typedef BucketT value_type; - DenseMap(const DenseMap &other) { - NumBuckets = 0; - CopyFrom(other); - } - - explicit DenseMap(unsigned NumInitBuckets = 0) { - init(NumInitBuckets); - } - - template<typename InputIt> - DenseMap(const InputIt &I, const InputIt &E) { - init(NextPowerOf2(std::distance(I, E))); - insert(I, E); - } - - ~DenseMap() { - const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); - for (BucketT *P = Buckets, *E = Buckets+NumBuckets; P != E; ++P) { - if (!KeyInfoT::isEqual(P->first, EmptyKey) && - !KeyInfoT::isEqual(P->first, TombstoneKey)) - P->second.~ValueT(); - P->first.~KeyT(); - } -#ifndef NDEBUG - if (NumBuckets) - memset((void*)Buckets, 0x5a, sizeof(BucketT)*NumBuckets); -#endif - operator delete(Buckets); - } - typedef DenseMapIterator<KeyT, ValueT, KeyInfoT> iterator; typedef DenseMapIterator<KeyT, ValueT, KeyInfoT, true> const_iterator; inline iterator begin() { // When the map is empty, avoid the overhead of AdvancePastEmptyBuckets(). - return empty() ? end() : iterator(Buckets, Buckets+NumBuckets); + return empty() ? end() : iterator(getBuckets(), getBucketsEnd()); } inline iterator end() { - return iterator(Buckets+NumBuckets, Buckets+NumBuckets, true); + return iterator(getBucketsEnd(), getBucketsEnd(), true); } inline const_iterator begin() const { - return empty() ? end() : const_iterator(Buckets, Buckets+NumBuckets); + return empty() ? end() : const_iterator(getBuckets(), getBucketsEnd()); } inline const_iterator end() const { - return const_iterator(Buckets+NumBuckets, Buckets+NumBuckets, true); + return const_iterator(getBucketsEnd(), getBucketsEnd(), true); } - bool empty() const { return NumEntries == 0; } - unsigned size() const { return NumEntries; } + bool empty() const { return getNumEntries() == 0; } + unsigned size() const { return getNumEntries(); } /// Grow the densemap so that it has at least Size buckets. Does not shrink void resize(size_t Size) { - if (Size > NumBuckets) + if (Size > getNumBuckets()) grow(Size); } void clear() { - if (NumEntries == 0 && NumTombstones == 0) return; + if (getNumEntries() == 0 && getNumTombstones() == 0) return; // If the capacity of the array is huge, and the # elements used is small, // shrink the array. - if (NumEntries * 4 < NumBuckets && NumBuckets > 64) { + if (getNumEntries() * 4 < getNumBuckets() && getNumBuckets() > 64) { shrink_and_clear(); return; } const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); - for (BucketT *P = Buckets, *E = Buckets+NumBuckets; P != E; ++P) { + for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) { if (!KeyInfoT::isEqual(P->first, EmptyKey)) { if (!KeyInfoT::isEqual(P->first, TombstoneKey)) { P->second.~ValueT(); - --NumEntries; + decrementNumEntries(); } P->first = EmptyKey; } } - assert(NumEntries == 0 && "Node count imbalance!"); - NumTombstones = 0; + assert(getNumEntries() == 0 && "Node count imbalance!"); + setNumTombstones(0); } /// count - Return true if the specified key is in the map. bool count(const KeyT &Val) const { - BucketT *TheBucket; + const BucketT *TheBucket; return LookupBucketFor(Val, TheBucket); } iterator find(const KeyT &Val) { BucketT *TheBucket; if (LookupBucketFor(Val, TheBucket)) - return iterator(TheBucket, Buckets+NumBuckets, true); + return iterator(TheBucket, getBucketsEnd(), true); return end(); } const_iterator find(const KeyT &Val) const { - BucketT *TheBucket; + const BucketT *TheBucket; if (LookupBucketFor(Val, TheBucket)) - return const_iterator(TheBucket, Buckets+NumBuckets, true); + return const_iterator(TheBucket, getBucketsEnd(), true); return end(); } @@ -155,21 +125,21 @@ public: iterator find_as(const LookupKeyT &Val) { BucketT *TheBucket; if (LookupBucketFor(Val, TheBucket)) - return iterator(TheBucket, Buckets+NumBuckets, true); + return iterator(TheBucket, getBucketsEnd(), true); return end(); } template<class LookupKeyT> const_iterator find_as(const LookupKeyT &Val) const { - BucketT *TheBucket; + const BucketT *TheBucket; if (LookupBucketFor(Val, TheBucket)) - return const_iterator(TheBucket, Buckets+NumBuckets, true); + return const_iterator(TheBucket, getBucketsEnd(), true); return end(); } /// lookup - Return the entry for the specified key, or a default /// constructed value if no such entry exists. ValueT lookup(const KeyT &Val) const { - BucketT *TheBucket; + const BucketT *TheBucket; if (LookupBucketFor(Val, TheBucket)) return TheBucket->second; return ValueT(); @@ -181,12 +151,12 @@ public: std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) { BucketT *TheBucket; if (LookupBucketFor(KV.first, TheBucket)) - return std::make_pair(iterator(TheBucket, Buckets+NumBuckets, true), + return std::make_pair(iterator(TheBucket, getBucketsEnd(), true), false); // Already in map. // Otherwise, insert the new element. TheBucket = InsertIntoBucket(KV.first, KV.second, TheBucket); - return std::make_pair(iterator(TheBucket, Buckets+NumBuckets, true), true); + return std::make_pair(iterator(TheBucket, getBucketsEnd(), true), true); } /// insert - Range insertion of pairs. @@ -204,23 +174,16 @@ public: TheBucket->second.~ValueT(); TheBucket->first = getTombstoneKey(); - --NumEntries; - ++NumTombstones; + decrementNumEntries(); + incrementNumTombstones(); return true; } void erase(iterator I) { BucketT *TheBucket = &*I; TheBucket->second.~ValueT(); TheBucket->first = getTombstoneKey(); - --NumEntries; - ++NumTombstones; - } - - void swap(DenseMap& RHS) { - std::swap(NumBuckets, RHS.NumBuckets); - std::swap(Buckets, RHS.Buckets); - std::swap(NumEntries, RHS.NumEntries); - std::swap(NumTombstones, RHS.NumTombstones); + decrementNumEntries(); + incrementNumTombstones(); } value_type& FindAndConstruct(const KeyT &Key) { @@ -235,68 +198,211 @@ public: return FindAndConstruct(Key).second; } - DenseMap& operator=(const DenseMap& other) { - CopyFrom(other); - return *this; +#if LLVM_USE_RVALUE_REFERENCES + value_type& FindAndConstruct(KeyT &&Key) { + BucketT *TheBucket; + if (LookupBucketFor(Key, TheBucket)) + return *TheBucket; + + return *InsertIntoBucket(Key, ValueT(), TheBucket); } + ValueT &operator[](KeyT &&Key) { + return FindAndConstruct(Key).second; + } +#endif + /// isPointerIntoBucketsArray - Return true if the specified pointer points /// somewhere into the DenseMap's array of buckets (i.e. either to a key or /// value in the DenseMap). bool isPointerIntoBucketsArray(const void *Ptr) const { - return Ptr >= Buckets && Ptr < Buckets+NumBuckets; + return Ptr >= getBuckets() && Ptr < getBucketsEnd(); } /// getPointerIntoBucketsArray() - Return an opaque pointer into the buckets /// array. In conjunction with the previous method, this can be used to /// determine whether an insertion caused the DenseMap to reallocate. - const void *getPointerIntoBucketsArray() const { return Buckets; } + const void *getPointerIntoBucketsArray() const { return getBuckets(); } -private: - void CopyFrom(const DenseMap& other) { - if (NumBuckets != 0 && - (!isPodLike<KeyT>::value || !isPodLike<ValueT>::value)) { - const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); - for (BucketT *P = Buckets, *E = Buckets+NumBuckets; P != E; ++P) { - if (!KeyInfoT::isEqual(P->first, EmptyKey) && - !KeyInfoT::isEqual(P->first, TombstoneKey)) - P->second.~ValueT(); - P->first.~KeyT(); - } - } +protected: + DenseMapBase() {} - NumEntries = other.NumEntries; - NumTombstones = other.NumTombstones; + void destroyAll() { + if (getNumBuckets() == 0) // Nothing to do. + return; + + const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); + for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) { + if (!KeyInfoT::isEqual(P->first, EmptyKey) && + !KeyInfoT::isEqual(P->first, TombstoneKey)) + P->second.~ValueT(); + P->first.~KeyT(); + } - if (NumBuckets) { #ifndef NDEBUG - memset((void*)Buckets, 0x5a, sizeof(BucketT)*NumBuckets); + memset((void*)getBuckets(), 0x5a, sizeof(BucketT)*getNumBuckets()); #endif - operator delete(Buckets); - } + } - NumBuckets = other.NumBuckets; + void initEmpty() { + setNumEntries(0); + setNumTombstones(0); - if (NumBuckets == 0) { - Buckets = 0; - return; + assert((getNumBuckets() & (getNumBuckets()-1)) == 0 && + "# initial buckets must be a power of two!"); + const KeyT EmptyKey = getEmptyKey(); + for (BucketT *B = getBuckets(), *E = getBucketsEnd(); B != E; ++B) + new (&B->first) KeyT(EmptyKey); + } + + void moveFromOldBuckets(BucketT *OldBucketsBegin, BucketT *OldBucketsEnd) { + initEmpty(); + + // Insert all the old elements. + const KeyT EmptyKey = getEmptyKey(); + const KeyT TombstoneKey = getTombstoneKey(); + for (BucketT *B = OldBucketsBegin, *E = OldBucketsEnd; B != E; ++B) { + if (!KeyInfoT::isEqual(B->first, EmptyKey) && + !KeyInfoT::isEqual(B->first, TombstoneKey)) { + // Insert the key/value into the new table. + BucketT *DestBucket; + bool FoundVal = LookupBucketFor(B->first, DestBucket); + (void)FoundVal; // silence warning. + assert(!FoundVal && "Key already in new map?"); + DestBucket->first = llvm_move(B->first); + new (&DestBucket->second) ValueT(llvm_move(B->second)); + incrementNumEntries(); + + // Free the value. + B->second.~ValueT(); + } + B->first.~KeyT(); } - Buckets = static_cast<BucketT*>(operator new(sizeof(BucketT) * NumBuckets)); +#ifndef NDEBUG + if (OldBucketsBegin != OldBucketsEnd) + memset((void*)OldBucketsBegin, 0x5a, + sizeof(BucketT) * (OldBucketsEnd - OldBucketsBegin)); +#endif + } + + template <typename OtherBaseT> + void copyFrom(const DenseMapBase<OtherBaseT, KeyT, ValueT, KeyInfoT>& other) { + assert(getNumBuckets() == other.getNumBuckets()); + + setNumEntries(other.getNumEntries()); + setNumTombstones(other.getNumTombstones()); if (isPodLike<KeyT>::value && isPodLike<ValueT>::value) - memcpy(Buckets, other.Buckets, NumBuckets * sizeof(BucketT)); + memcpy(getBuckets(), other.getBuckets(), + getNumBuckets() * sizeof(BucketT)); else - for (size_t i = 0; i < NumBuckets; ++i) { - new (&Buckets[i].first) KeyT(other.Buckets[i].first); - if (!KeyInfoT::isEqual(Buckets[i].first, getEmptyKey()) && - !KeyInfoT::isEqual(Buckets[i].first, getTombstoneKey())) - new (&Buckets[i].second) ValueT(other.Buckets[i].second); + for (size_t i = 0; i < getNumBuckets(); ++i) { + new (&getBuckets()[i].first) KeyT(other.getBuckets()[i].first); + if (!KeyInfoT::isEqual(getBuckets()[i].first, getEmptyKey()) && + !KeyInfoT::isEqual(getBuckets()[i].first, getTombstoneKey())) + new (&getBuckets()[i].second) ValueT(other.getBuckets()[i].second); } } + void swap(DenseMapBase& RHS) { + std::swap(getNumEntries(), RHS.getNumEntries()); + std::swap(getNumTombstones(), RHS.getNumTombstones()); + } + + static unsigned getHashValue(const KeyT &Val) { + return KeyInfoT::getHashValue(Val); + } + template<typename LookupKeyT> + static unsigned getHashValue(const LookupKeyT &Val) { + return KeyInfoT::getHashValue(Val); + } + static const KeyT getEmptyKey() { + return KeyInfoT::getEmptyKey(); + } + static const KeyT getTombstoneKey() { + return KeyInfoT::getTombstoneKey(); + } + +private: + unsigned getNumEntries() const { + return static_cast<const DerivedT *>(this)->getNumEntries(); + } + void setNumEntries(unsigned Num) { + static_cast<DerivedT *>(this)->setNumEntries(Num); + } + void incrementNumEntries() { + setNumEntries(getNumEntries() + 1); + } + void decrementNumEntries() { + setNumEntries(getNumEntries() - 1); + } + unsigned getNumTombstones() const { + return static_cast<const DerivedT *>(this)->getNumTombstones(); + } + void setNumTombstones(unsigned Num) { + static_cast<DerivedT *>(this)->setNumTombstones(Num); + } + void incrementNumTombstones() { + setNumTombstones(getNumTombstones() + 1); + } + void decrementNumTombstones() { + setNumTombstones(getNumTombstones() - 1); + } + const BucketT *getBuckets() const { + return static_cast<const DerivedT *>(this)->getBuckets(); + } + BucketT *getBuckets() { + return static_cast<DerivedT *>(this)->getBuckets(); + } + unsigned getNumBuckets() const { + return static_cast<const DerivedT *>(this)->getNumBuckets(); + } + BucketT *getBucketsEnd() { + return getBuckets() + getNumBuckets(); + } + const BucketT *getBucketsEnd() const { + return getBuckets() + getNumBuckets(); + } + + void grow(unsigned AtLeast) { + static_cast<DerivedT *>(this)->grow(AtLeast); + } + + void shrink_and_clear() { + static_cast<DerivedT *>(this)->shrink_and_clear(); + } + + BucketT *InsertIntoBucket(const KeyT &Key, const ValueT &Value, BucketT *TheBucket) { + TheBucket = InsertIntoBucketImpl(Key, TheBucket); + + TheBucket->first = Key; + new (&TheBucket->second) ValueT(Value); + return TheBucket; + } + +#if LLVM_USE_RVALUE_REFERENCES + BucketT *InsertIntoBucket(const KeyT &Key, ValueT &&Value, + BucketT *TheBucket) { + TheBucket = InsertIntoBucketImpl(Key, TheBucket); + + TheBucket->first = Key; + new (&TheBucket->second) ValueT(std::move(Value)); + return TheBucket; + } + + BucketT *InsertIntoBucket(KeyT &&Key, ValueT &&Value, BucketT *TheBucket) { + TheBucket = InsertIntoBucketImpl(Key, TheBucket); + + TheBucket->first = std::move(Key); + new (&TheBucket->second) ValueT(std::move(Value)); + return TheBucket; + } +#endif + + BucketT *InsertIntoBucketImpl(const KeyT &Key, BucketT *TheBucket) { // If the load of the hash table is more than 3/4, or if fewer than 1/8 of // the buckets are empty (meaning that many are filled with tombstones), // grow the table. @@ -306,48 +412,38 @@ private: // probe almost the entire table until it found the empty bucket. If the // table completely filled with tombstones, no lookup would ever succeed, // causing infinite loops in lookup. - ++NumEntries; - if (NumEntries*4 >= NumBuckets*3) { + unsigned NewNumEntries = getNumEntries() + 1; + unsigned NumBuckets = getNumBuckets(); + if (NewNumEntries*4 >= NumBuckets*3) { this->grow(NumBuckets * 2); LookupBucketFor(Key, TheBucket); + NumBuckets = getNumBuckets(); } - if (NumBuckets-(NumEntries+NumTombstones) < NumBuckets/8) { + if (NumBuckets-(NewNumEntries+getNumTombstones()) <= NumBuckets/8) { this->grow(NumBuckets); LookupBucketFor(Key, TheBucket); } + // Only update the state after we've grown our bucket space appropriately + // so that when growing buckets we have self-consistent entry count. + incrementNumEntries(); + // If we are writing over a tombstone, remember this. if (!KeyInfoT::isEqual(TheBucket->first, getEmptyKey())) - --NumTombstones; + decrementNumTombstones(); - TheBucket->first = Key; - new (&TheBucket->second) ValueT(Value); return TheBucket; } - static unsigned getHashValue(const KeyT &Val) { - return KeyInfoT::getHashValue(Val); - } - template<typename LookupKeyT> - static unsigned getHashValue(const LookupKeyT &Val) { - return KeyInfoT::getHashValue(Val); - } - static const KeyT getEmptyKey() { - return KeyInfoT::getEmptyKey(); - } - static const KeyT getTombstoneKey() { - return KeyInfoT::getTombstoneKey(); - } - /// LookupBucketFor - Lookup the appropriate bucket for Val, returning it in /// FoundBucket. If the bucket contains the key and a value, this returns /// true, otherwise it returns a bucket with an empty marker or tombstone and /// returns false. template<typename LookupKeyT> - bool LookupBucketFor(const LookupKeyT &Val, BucketT *&FoundBucket) const { - unsigned BucketNo = getHashValue(Val); - unsigned ProbeAmt = 1; - BucketT *BucketsPtr = Buckets; + bool LookupBucketFor(const LookupKeyT &Val, + const BucketT *&FoundBucket) const { + const BucketT *BucketsPtr = getBuckets(); + const unsigned NumBuckets = getNumBuckets(); if (NumBuckets == 0) { FoundBucket = 0; @@ -355,15 +451,17 @@ private: } // FoundTombstone - Keep track of whether we find a tombstone while probing. - BucketT *FoundTombstone = 0; + const BucketT *FoundTombstone = 0; const KeyT EmptyKey = getEmptyKey(); const KeyT TombstoneKey = getTombstoneKey(); assert(!KeyInfoT::isEqual(Val, EmptyKey) && !KeyInfoT::isEqual(Val, TombstoneKey) && "Empty/Tombstone value shouldn't be inserted into map!"); + unsigned BucketNo = getHashValue(Val) & (NumBuckets-1); + unsigned ProbeAmt = 1; while (1) { - BucketT *ThisBucket = BucketsPtr + (BucketNo & (NumBuckets-1)); + const BucketT *ThisBucket = BucketsPtr + BucketNo; // Found Val's bucket? If so, return it. if (KeyInfoT::isEqual(Val, ThisBucket->first)) { FoundBucket = ThisBucket; @@ -388,115 +486,481 @@ private: // Otherwise, it's a hash collision or a tombstone, continue quadratic // probing. BucketNo += ProbeAmt++; + BucketNo &= (NumBuckets-1); } } - void init(unsigned InitBuckets) { - NumEntries = 0; - NumTombstones = 0; - NumBuckets = InitBuckets; + template <typename LookupKeyT> + bool LookupBucketFor(const LookupKeyT &Val, BucketT *&FoundBucket) { + const BucketT *ConstFoundBucket; + bool Result = const_cast<const DenseMapBase *>(this) + ->LookupBucketFor(Val, ConstFoundBucket); + FoundBucket = const_cast<BucketT *>(ConstFoundBucket); + return Result; + } - if (InitBuckets == 0) { - Buckets = 0; - return; +public: + /// Return the approximate size (in bytes) of the actual map. + /// This is just the raw memory used by DenseMap. + /// If entries are pointers to objects, the size of the referenced objects + /// are not included. + size_t getMemorySize() const { + return getNumBuckets() * sizeof(BucketT); + } +}; + +template<typename KeyT, typename ValueT, + typename KeyInfoT = DenseMapInfo<KeyT> > +class DenseMap + : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT>, + KeyT, ValueT, KeyInfoT> { + // Lift some types from the dependent base class into this class for + // simplicity of referring to them. + typedef DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT> BaseT; + typedef typename BaseT::BucketT BucketT; + friend class DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT>; + + BucketT *Buckets; + unsigned NumEntries; + unsigned NumTombstones; + unsigned NumBuckets; + +public: + explicit DenseMap(unsigned NumInitBuckets = 0) { + init(NumInitBuckets); + } + + DenseMap(const DenseMap &other) { + init(0); + copyFrom(other); + } + +#if LLVM_USE_RVALUE_REFERENCES + DenseMap(DenseMap &&other) { + init(0); + swap(other); + } +#endif + + template<typename InputIt> + DenseMap(const InputIt &I, const InputIt &E) { + init(NextPowerOf2(std::distance(I, E))); + this->insert(I, E); + } + + ~DenseMap() { + this->destroyAll(); + operator delete(Buckets); + } + + void swap(DenseMap& RHS) { + std::swap(Buckets, RHS.Buckets); + std::swap(NumEntries, RHS.NumEntries); + std::swap(NumTombstones, RHS.NumTombstones); + std::swap(NumBuckets, RHS.NumBuckets); + } + + DenseMap& operator=(const DenseMap& other) { + copyFrom(other); + return *this; + } + +#if LLVM_USE_RVALUE_REFERENCES + DenseMap& operator=(DenseMap &&other) { + this->destroyAll(); + operator delete(Buckets); + init(0); + swap(other); + return *this; + } +#endif + + void copyFrom(const DenseMap& other) { + this->destroyAll(); + operator delete(Buckets); + if (allocateBuckets(other.NumBuckets)) { + this->BaseT::copyFrom(other); + } else { + NumEntries = 0; + NumTombstones = 0; } + } - assert(InitBuckets && (InitBuckets & (InitBuckets-1)) == 0 && - "# initial buckets must be a power of two!"); - Buckets = static_cast<BucketT*>(operator new(sizeof(BucketT)*InitBuckets)); - // Initialize all the keys to EmptyKey. - const KeyT EmptyKey = getEmptyKey(); - for (unsigned i = 0; i != InitBuckets; ++i) - new (&Buckets[i].first) KeyT(EmptyKey); + void init(unsigned InitBuckets) { + if (allocateBuckets(InitBuckets)) { + this->BaseT::initEmpty(); + } else { + NumEntries = 0; + NumTombstones = 0; + } } void grow(unsigned AtLeast) { unsigned OldNumBuckets = NumBuckets; BucketT *OldBuckets = Buckets; - if (NumBuckets < 64) - NumBuckets = 64; + allocateBuckets(std::max<unsigned>(64, NextPowerOf2(AtLeast))); + assert(Buckets); + if (!OldBuckets) { + this->BaseT::initEmpty(); + return; + } - // Double the number of buckets. - while (NumBuckets < AtLeast) - NumBuckets <<= 1; - NumTombstones = 0; - Buckets = static_cast<BucketT*>(operator new(sizeof(BucketT)*NumBuckets)); + this->moveFromOldBuckets(OldBuckets, OldBuckets+OldNumBuckets); - // Initialize all the keys to EmptyKey. - const KeyT EmptyKey = getEmptyKey(); - for (unsigned i = 0, e = NumBuckets; i != e; ++i) - new (&Buckets[i].first) KeyT(EmptyKey); + // Free the old table. + operator delete(OldBuckets); + } - // Insert all the old elements. - const KeyT TombstoneKey = getTombstoneKey(); - for (BucketT *B = OldBuckets, *E = OldBuckets+OldNumBuckets; B != E; ++B) { - if (!KeyInfoT::isEqual(B->first, EmptyKey) && - !KeyInfoT::isEqual(B->first, TombstoneKey)) { - // Insert the key/value into the new table. - BucketT *DestBucket; - bool FoundVal = LookupBucketFor(B->first, DestBucket); - (void)FoundVal; // silence warning. - assert(!FoundVal && "Key already in new map?"); - DestBucket->first = B->first; - new (&DestBucket->second) ValueT(B->second); + void shrink_and_clear() { + unsigned OldNumEntries = NumEntries; + this->destroyAll(); - // Free the value. - B->second.~ValueT(); - } - B->first.~KeyT(); + // Reduce the number of buckets. + unsigned NewNumBuckets = 0; + if (OldNumEntries) + NewNumBuckets = std::max(64, 1 << (Log2_32_Ceil(OldNumEntries) + 1)); + if (NewNumBuckets == NumBuckets) { + this->BaseT::initEmpty(); + return; } -#ifndef NDEBUG - if (OldNumBuckets) - memset((void*)OldBuckets, 0x5a, sizeof(BucketT)*OldNumBuckets); + operator delete(Buckets); + init(NewNumBuckets); + } + +private: + unsigned getNumEntries() const { + return NumEntries; + } + void setNumEntries(unsigned Num) { + NumEntries = Num; + } + + unsigned getNumTombstones() const { + return NumTombstones; + } + void setNumTombstones(unsigned Num) { + NumTombstones = Num; + } + + BucketT *getBuckets() const { + return Buckets; + } + + unsigned getNumBuckets() const { + return NumBuckets; + } + + bool allocateBuckets(unsigned Num) { + NumBuckets = Num; + if (NumBuckets == 0) { + Buckets = 0; + return false; + } + + Buckets = static_cast<BucketT*>(operator new(sizeof(BucketT) * NumBuckets)); + return true; + } +}; + +template<typename KeyT, typename ValueT, + unsigned InlineBuckets = 4, + typename KeyInfoT = DenseMapInfo<KeyT> > +class SmallDenseMap + : public DenseMapBase<SmallDenseMap<KeyT, ValueT, InlineBuckets, KeyInfoT>, + KeyT, ValueT, KeyInfoT> { + // Lift some types from the dependent base class into this class for + // simplicity of referring to them. + typedef DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT> BaseT; + typedef typename BaseT::BucketT BucketT; + friend class DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT>; + + unsigned Small : 1; + unsigned NumEntries : 31; + unsigned NumTombstones; + + struct LargeRep { + BucketT *Buckets; + unsigned NumBuckets; + }; + + /// A "union" of an inline bucket array and the struct representing + /// a large bucket. This union will be discriminated by the 'Small' bit. + typename AlignedCharArray<BucketT[InlineBuckets], LargeRep>::union_type + storage; + +public: + explicit SmallDenseMap(unsigned NumInitBuckets = 0) { + init(NumInitBuckets); + } + + SmallDenseMap(const SmallDenseMap &other) { + init(0); + copyFrom(other); + } + +#if LLVM_USE_RVALUE_REFERENCES + SmallDenseMap(SmallDenseMap &&other) { + init(0); + swap(other); + } #endif - // Free the old table. - operator delete(OldBuckets); + + template<typename InputIt> + SmallDenseMap(const InputIt &I, const InputIt &E) { + init(NextPowerOf2(std::distance(I, E))); + this->insert(I, E); } - void shrink_and_clear() { - unsigned OldNumBuckets = NumBuckets; - BucketT *OldBuckets = Buckets; + ~SmallDenseMap() { + this->destroyAll(); + deallocateBuckets(); + } - // Reduce the number of buckets. - NumBuckets = NumEntries > 32 ? 1 << (Log2_32_Ceil(NumEntries) + 1) - : 64; - NumTombstones = 0; - Buckets = static_cast<BucketT*>(operator new(sizeof(BucketT)*NumBuckets)); + void swap(SmallDenseMap& RHS) { + unsigned TmpNumEntries = RHS.NumEntries; + RHS.NumEntries = NumEntries; + NumEntries = TmpNumEntries; + std::swap(NumTombstones, RHS.NumTombstones); - // Initialize all the keys to EmptyKey. - const KeyT EmptyKey = getEmptyKey(); - for (unsigned i = 0, e = NumBuckets; i != e; ++i) - new (&Buckets[i].first) KeyT(EmptyKey); + const KeyT EmptyKey = this->getEmptyKey(); + const KeyT TombstoneKey = this->getTombstoneKey(); + if (Small && RHS.Small) { + // If we're swapping inline bucket arrays, we have to cope with some of + // the tricky bits of DenseMap's storage system: the buckets are not + // fully initialized. Thus we swap every key, but we may have + // a one-directional move of the value. + for (unsigned i = 0, e = InlineBuckets; i != e; ++i) { + BucketT *LHSB = &getInlineBuckets()[i], + *RHSB = &RHS.getInlineBuckets()[i]; + bool hasLHSValue = (!KeyInfoT::isEqual(LHSB->first, EmptyKey) && + !KeyInfoT::isEqual(LHSB->first, TombstoneKey)); + bool hasRHSValue = (!KeyInfoT::isEqual(RHSB->first, EmptyKey) && + !KeyInfoT::isEqual(RHSB->first, TombstoneKey)); + if (hasLHSValue && hasRHSValue) { + // Swap together if we can... + std::swap(*LHSB, *RHSB); + continue; + } + // Swap separately and handle any assymetry. + std::swap(LHSB->first, RHSB->first); + if (hasLHSValue) { + new (&RHSB->second) ValueT(llvm_move(LHSB->second)); + LHSB->second.~ValueT(); + } else if (hasRHSValue) { + new (&LHSB->second) ValueT(llvm_move(RHSB->second)); + RHSB->second.~ValueT(); + } + } + return; + } + if (!Small && !RHS.Small) { + std::swap(getLargeRep()->Buckets, RHS.getLargeRep()->Buckets); + std::swap(getLargeRep()->NumBuckets, RHS.getLargeRep()->NumBuckets); + return; + } - // Free the old buckets. - const KeyT TombstoneKey = getTombstoneKey(); - for (BucketT *B = OldBuckets, *E = OldBuckets+OldNumBuckets; B != E; ++B) { - if (!KeyInfoT::isEqual(B->first, EmptyKey) && - !KeyInfoT::isEqual(B->first, TombstoneKey)) { - // Free the value. - B->second.~ValueT(); + SmallDenseMap &SmallSide = Small ? *this : RHS; + SmallDenseMap &LargeSide = Small ? RHS : *this; + + // First stash the large side's rep and move the small side across. + LargeRep TmpRep = llvm_move(*LargeSide.getLargeRep()); + LargeSide.getLargeRep()->~LargeRep(); + LargeSide.Small = true; + // This is similar to the standard move-from-old-buckets, but the bucket + // count hasn't actually rotated in this case. So we have to carefully + // move construct the keys and values into their new locations, but there + // is no need to re-hash things. + for (unsigned i = 0, e = InlineBuckets; i != e; ++i) { + BucketT *NewB = &LargeSide.getInlineBuckets()[i], + *OldB = &SmallSide.getInlineBuckets()[i]; + new (&NewB->first) KeyT(llvm_move(OldB->first)); + OldB->first.~KeyT(); + if (!KeyInfoT::isEqual(NewB->first, EmptyKey) && + !KeyInfoT::isEqual(NewB->first, TombstoneKey)) { + new (&NewB->second) ValueT(llvm_move(OldB->second)); + OldB->second.~ValueT(); } - B->first.~KeyT(); } -#ifndef NDEBUG - memset((void*)OldBuckets, 0x5a, sizeof(BucketT)*OldNumBuckets); + // The hard part of moving the small buckets across is done, just move + // the TmpRep into its new home. + SmallSide.Small = false; + new (SmallSide.getLargeRep()) LargeRep(llvm_move(TmpRep)); + } + + SmallDenseMap& operator=(const SmallDenseMap& other) { + copyFrom(other); + return *this; + } + +#if LLVM_USE_RVALUE_REFERENCES + SmallDenseMap& operator=(SmallDenseMap &&other) { + this->destroyAll(); + deallocateBuckets(); + init(0); + swap(other); + return *this; + } #endif + + void copyFrom(const SmallDenseMap& other) { + this->destroyAll(); + deallocateBuckets(); + Small = true; + if (other.getNumBuckets() > InlineBuckets) { + Small = false; + allocateBuckets(other.getNumBuckets()); + } + this->BaseT::copyFrom(other); + } + + void init(unsigned InitBuckets) { + Small = true; + if (InitBuckets > InlineBuckets) { + Small = false; + new (getLargeRep()) LargeRep(allocateBuckets(InitBuckets)); + } + this->BaseT::initEmpty(); + } + + void grow(unsigned AtLeast) { + if (AtLeast > InlineBuckets) + AtLeast = std::max<unsigned>(64, NextPowerOf2(AtLeast)); + + if (Small) { + if (AtLeast <= InlineBuckets) + return; // Nothing to do. + + // First move the inline buckets into a temporary storage. + typename AlignedCharArray<BucketT[InlineBuckets]>::union_type + TmpStorage; + BucketT *TmpBegin = reinterpret_cast<BucketT *>(TmpStorage.buffer); + BucketT *TmpEnd = TmpBegin; + + // Loop over the buckets, moving non-empty, non-tombstones into the + // temporary storage. Have the loop move the TmpEnd forward as it goes. + const KeyT EmptyKey = this->getEmptyKey(); + const KeyT TombstoneKey = this->getTombstoneKey(); + for (BucketT *P = getBuckets(), *E = P + InlineBuckets; P != E; ++P) { + if (!KeyInfoT::isEqual(P->first, EmptyKey) && + !KeyInfoT::isEqual(P->first, TombstoneKey)) { + assert(size_t(TmpEnd - TmpBegin) < InlineBuckets && + "Too many inline buckets!"); + new (&TmpEnd->first) KeyT(llvm_move(P->first)); + new (&TmpEnd->second) ValueT(llvm_move(P->second)); + ++TmpEnd; + P->second.~ValueT(); + } + P->first.~KeyT(); + } + + // Now make this map use the large rep, and move all the entries back + // into it. + Small = false; + new (getLargeRep()) LargeRep(allocateBuckets(AtLeast)); + this->moveFromOldBuckets(TmpBegin, TmpEnd); + return; + } + + LargeRep OldRep = llvm_move(*getLargeRep()); + getLargeRep()->~LargeRep(); + if (AtLeast <= InlineBuckets) { + Small = true; + } else { + new (getLargeRep()) LargeRep(allocateBuckets(AtLeast)); + } + + this->moveFromOldBuckets(OldRep.Buckets, OldRep.Buckets+OldRep.NumBuckets); + // Free the old table. - operator delete(OldBuckets); + operator delete(OldRep.Buckets); + } + + void shrink_and_clear() { + unsigned OldSize = this->size(); + this->destroyAll(); + + // Reduce the number of buckets. + unsigned NewNumBuckets = 0; + if (OldSize) { + NewNumBuckets = 1 << (Log2_32_Ceil(OldSize) + 1); + if (NewNumBuckets > InlineBuckets && NewNumBuckets < 64u) + NewNumBuckets = 64; + } + if ((Small && NewNumBuckets <= InlineBuckets) || + (!Small && NewNumBuckets == getLargeRep()->NumBuckets)) { + this->BaseT::initEmpty(); + return; + } - NumEntries = 0; + deallocateBuckets(); + init(NewNumBuckets); } - -public: - /// Return the approximate size (in bytes) of the actual map. - /// This is just the raw memory used by DenseMap. - /// If entries are pointers to objects, the size of the referenced objects - /// are not included. - size_t getMemorySize() const { - return NumBuckets * sizeof(BucketT); + +private: + unsigned getNumEntries() const { + return NumEntries; + } + void setNumEntries(unsigned Num) { + assert(Num < INT_MAX && "Cannot support more than INT_MAX entries"); + NumEntries = Num; + } + + unsigned getNumTombstones() const { + return NumTombstones; + } + void setNumTombstones(unsigned Num) { + NumTombstones = Num; + } + + const BucketT *getInlineBuckets() const { + assert(Small); + // Note that this cast does not violate aliasing rules as we assert that + // the memory's dynamic type is the small, inline bucket buffer, and the + // 'storage.buffer' static type is 'char *'. + return reinterpret_cast<const BucketT *>(storage.buffer); + } + BucketT *getInlineBuckets() { + return const_cast<BucketT *>( + const_cast<const SmallDenseMap *>(this)->getInlineBuckets()); + } + const LargeRep *getLargeRep() const { + assert(!Small); + // Note, same rule about aliasing as with getInlineBuckets. + return reinterpret_cast<const LargeRep *>(storage.buffer); + } + LargeRep *getLargeRep() { + return const_cast<LargeRep *>( + const_cast<const SmallDenseMap *>(this)->getLargeRep()); + } + + const BucketT *getBuckets() const { + return Small ? getInlineBuckets() : getLargeRep()->Buckets; + } + BucketT *getBuckets() { + return const_cast<BucketT *>( + const_cast<const SmallDenseMap *>(this)->getBuckets()); + } + unsigned getNumBuckets() const { + return Small ? InlineBuckets : getLargeRep()->NumBuckets; + } + + void deallocateBuckets() { + if (Small) + return; + + operator delete(getLargeRep()->Buckets); + getLargeRep()->~LargeRep(); + } + + LargeRep allocateBuckets(unsigned Num) { + assert(Num > InlineBuckets && "Must allocate more buckets than are inline"); + LargeRep Rep = { + static_cast<BucketT*>(operator new(sizeof(BucketT) * Num)), Num + }; + return Rep; } }; diff --git a/include/llvm/ADT/DepthFirstIterator.h b/include/llvm/ADT/DepthFirstIterator.h index dd13a2c..519b180 100644 --- a/include/llvm/ADT/DepthFirstIterator.h +++ b/include/llvm/ADT/DepthFirstIterator.h @@ -187,7 +187,7 @@ public: /// current node, counting both nodes. unsigned getPathLength() const { return VisitStack.size(); } - /// getPath - Return the n'th node in the path from the the entry node to the + /// getPath - Return the n'th node in the path from the entry node to the /// current node. NodeType *getPath(unsigned n) const { return VisitStack[n].first.getPointer(); diff --git a/include/llvm/ADT/FoldingSet.h b/include/llvm/ADT/FoldingSet.h index 7d7c777..ba415ac 100644 --- a/include/llvm/ADT/FoldingSet.h +++ b/include/llvm/ADT/FoldingSet.h @@ -518,6 +518,111 @@ public: }; //===----------------------------------------------------------------------===// +/// FoldingSetVectorIterator - This implements an iterator for +/// FoldingSetVector. It is only necessary because FoldingSetIterator provides +/// a value_type of T, while the vector in FoldingSetVector exposes +/// a value_type of T*. Fortunately, FoldingSetIterator doesn't expose very +/// much besides operator* and operator->, so we just wrap the inner vector +/// iterator and perform the extra dereference. +template <class T, class VectorIteratorT> +class FoldingSetVectorIterator { + // Provide a typedef to workaround the lack of correct injected class name + // support in older GCCs. + typedef FoldingSetVectorIterator<T, VectorIteratorT> SelfT; + + VectorIteratorT Iterator; + +public: + FoldingSetVectorIterator(VectorIteratorT I) : Iterator(I) {} + + bool operator==(const SelfT &RHS) const { + return Iterator == RHS.Iterator; + } + bool operator!=(const SelfT &RHS) const { + return Iterator != RHS.Iterator; + } + + T &operator*() const { return **Iterator; } + + T *operator->() const { return *Iterator; } + + inline SelfT &operator++() { + ++Iterator; + return *this; + } + SelfT operator++(int) { + SelfT tmp = *this; + ++*this; + return tmp; + } +}; + +//===----------------------------------------------------------------------===// +/// FoldingSetVector - This template class combines a FoldingSet and a vector +/// to provide the interface of FoldingSet but with deterministic iteration +/// order based on the insertion order. T must be a subclass of FoldingSetNode +/// and implement a Profile function. +template <class T, class VectorT = SmallVector<T*, 8> > +class FoldingSetVector { + FoldingSet<T> Set; + VectorT Vector; + +public: + explicit FoldingSetVector(unsigned Log2InitSize = 6) + : Set(Log2InitSize) { + } + + typedef FoldingSetVectorIterator<T, typename VectorT::iterator> iterator; + iterator begin() { return Vector.begin(); } + iterator end() { return Vector.end(); } + + typedef FoldingSetVectorIterator<const T, typename VectorT::const_iterator> + const_iterator; + const_iterator begin() const { return Vector.begin(); } + const_iterator end() const { return Vector.end(); } + + /// clear - Remove all nodes from the folding set. + void clear() { Set.clear(); Vector.clear(); } + + /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists, + /// return it. If not, return the insertion token that will make insertion + /// faster. + T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) { + return Set.FindNodeOrInsertPos(ID, InsertPos); + } + + /// GetOrInsertNode - If there is an existing simple Node exactly + /// equal to the specified node, return it. Otherwise, insert 'N' and + /// return it instead. + T *GetOrInsertNode(T *N) { + T *Result = Set.GetOrInsertNode(N); + if (Result == N) Vector.push_back(N); + return Result; + } + + /// InsertNode - Insert the specified node into the folding set, knowing that + /// it is not already in the folding set. InsertPos must be obtained from + /// FindNodeOrInsertPos. + void InsertNode(T *N, void *InsertPos) { + Set.InsertNode(N, InsertPos); + Vector.push_back(N); + } + + /// InsertNode - Insert the specified node into the folding set, knowing that + /// it is not already in the folding set. + void InsertNode(T *N) { + Set.InsertNode(N); + Vector.push_back(N); + } + + /// size - Returns the number of nodes in the folding set. + unsigned size() const { return Set.size(); } + + /// empty - Returns true if there are no nodes in the folding set. + bool empty() const { return Set.empty(); } +}; + +//===----------------------------------------------------------------------===// /// FoldingSetIteratorImpl - This is the common iterator support shared by all /// folding sets, which knows how to walk the folding set hash table. class FoldingSetIteratorImpl { diff --git a/include/llvm/ADT/Hashing.h b/include/llvm/ADT/Hashing.h index 53032ee..6ab0725 100644 --- a/include/llvm/ADT/Hashing.h +++ b/include/llvm/ADT/Hashing.h @@ -76,10 +76,6 @@ namespace llvm { /// using llvm::hash_value; /// llvm::hash_code code = hash_value(x); /// \endcode -/// -/// Also note that there are two numerical values which are reserved, and the -/// implementation ensures will never be produced for real hash_codes. These -/// can be used as sentinels within hashing data structures. class hash_code { size_t value; diff --git a/include/llvm/ADT/ImmutableSet.h b/include/llvm/ADT/ImmutableSet.h index 89b1648..949dc44 100644 --- a/include/llvm/ADT/ImmutableSet.h +++ b/include/llvm/ADT/ImmutableSet.h @@ -431,7 +431,7 @@ protected: // Make sure the index is not the Tombstone or Entry key of the DenseMap. static inline unsigned maskCacheIndex(unsigned I) { - return (I & ~0x02); + return (I & ~0x02); } unsigned incrementHeight(TreeTy* L, TreeTy* R) const { @@ -667,7 +667,7 @@ public: return reinterpret_cast<TreeTy*>(stack.back() & ~Flags); } - uintptr_t getVisitState() { + uintptr_t getVisitState() const { assert(!stack.empty()); return stack.back() & Flags; } diff --git a/include/llvm/ADT/IndexedMap.h b/include/llvm/ADT/IndexedMap.h index 87126ea..2ffb505 100644 --- a/include/llvm/ADT/IndexedMap.h +++ b/include/llvm/ADT/IndexedMap.h @@ -20,19 +20,14 @@ #ifndef LLVM_ADT_INDEXEDMAP_H #define LLVM_ADT_INDEXEDMAP_H +#include "llvm/ADT/STLExtras.h" #include <cassert> #include <functional> #include <vector> namespace llvm { - struct IdentityFunctor : public std::unary_function<unsigned, unsigned> { - unsigned operator()(unsigned Index) const { - return Index; - } - }; - - template <typename T, typename ToIndexT = IdentityFunctor> +template <typename T, typename ToIndexT = llvm::identity<unsigned> > class IndexedMap { typedef typename ToIndexT::argument_type IndexT; typedef std::vector<T> StorageT; diff --git a/include/llvm/ADT/IntrusiveRefCntPtr.h b/include/llvm/ADT/IntrusiveRefCntPtr.h index 3a1a3f4..a9724ee 100644 --- a/include/llvm/ADT/IntrusiveRefCntPtr.h +++ b/include/llvm/ADT/IntrusiveRefCntPtr.h @@ -21,9 +21,9 @@ #ifndef LLVM_ADT_INTRUSIVE_REF_CNT_PTR #define LLVM_ADT_INTRUSIVE_REF_CNT_PTR -#include <cassert> - #include "llvm/Support/Casting.h" +#include "llvm/Support/Compiler.h" +#include <memory> namespace llvm { @@ -34,7 +34,7 @@ namespace llvm { /// RefCountedBase - A generic base class for objects that wish to /// have their lifetimes managed using reference counts. Classes /// subclass RefCountedBase to obtain such functionality, and are -/// typically handled with IntrusivePtr "smart pointers" (see below) +/// typically handled with IntrusiveRefCntPtr "smart pointers" (see below) /// which automatically handle the management of reference counts. /// Objects that subclass RefCountedBase should not be allocated on /// the stack, as invoking "delete" (which is called when the @@ -123,25 +123,25 @@ namespace llvm { retain(); } - template <class X> - IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X>& S) - : Obj(S.getPtr()) { - retain(); +#if LLVM_USE_RVALUE_REFERENCES + IntrusiveRefCntPtr(IntrusiveRefCntPtr&& S) : Obj(S.Obj) { + S.Obj = 0; } - IntrusiveRefCntPtr& operator=(const IntrusiveRefCntPtr& S) { - replace(S.getPtr()); - return *this; + template <class X> + IntrusiveRefCntPtr(IntrusiveRefCntPtr<X>&& S) : Obj(S.getPtr()) { + S.Obj = 0; } +#endif template <class X> - IntrusiveRefCntPtr& operator=(const IntrusiveRefCntPtr<X>& S) { - replace(S.getPtr()); - return *this; + IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X>& S) + : Obj(S.getPtr()) { + retain(); } - IntrusiveRefCntPtr& operator=(T * S) { - replace(S); + IntrusiveRefCntPtr& operator=(IntrusiveRefCntPtr S) { + swap(S); return *this; } @@ -176,10 +176,6 @@ namespace llvm { private: void retain() { if (Obj) IntrusiveRefCntPtrInfo<T>::retain(Obj); } void release() { if (Obj) IntrusiveRefCntPtrInfo<T>::release(Obj); } - - void replace(T* S) { - this_type(S).swap(*this); - } }; template<class T, class U> diff --git a/include/llvm/ADT/PointerIntPair.h b/include/llvm/ADT/PointerIntPair.h index ccdcd1a..fcc758b 100644 --- a/include/llvm/ADT/PointerIntPair.h +++ b/include/llvm/ADT/PointerIntPair.h @@ -108,7 +108,14 @@ public: static PointerIntPair getFromOpaqueValue(void *V) { PointerIntPair P; P.setFromOpaqueValue(V); return P; } - + + // Allow PointerIntPairs to be created from const void * if and only if the + // pointer type could be created from a const void *. + static PointerIntPair getFromOpaqueValue(const void *V) { + (void)PtrTraits::getFromVoidPointer(V); + return getFromOpaqueValue(const_cast<void *>(V)); + } + bool operator==(const PointerIntPair &RHS) const {return Value == RHS.Value;} bool operator!=(const PointerIntPair &RHS) const {return Value != RHS.Value;} bool operator<(const PointerIntPair &RHS) const {return Value < RHS.Value;} @@ -158,6 +165,10 @@ public: getFromVoidPointer(void *P) { return PointerIntPair<PointerTy, IntBits, IntType>::getFromOpaqueValue(P); } + static inline PointerIntPair<PointerTy, IntBits, IntType> + getFromVoidPointer(const void *P) { + return PointerIntPair<PointerTy, IntBits, IntType>::getFromOpaqueValue(P); + } enum { NumLowBitsAvailable = PtrTraits::NumLowBitsAvailable - IntBits }; diff --git a/include/llvm/ADT/PointerUnion.h b/include/llvm/ADT/PointerUnion.h index 614b59c..a9e86d2 100644 --- a/include/llvm/ADT/PointerUnion.h +++ b/include/llvm/ADT/PointerUnion.h @@ -54,8 +54,8 @@ namespace llvm { static inline void *getAsVoidPointer(void *P) { return P; } static inline void *getFromVoidPointer(void *P) { return P; } enum { - PT1BitsAv = PointerLikeTypeTraits<PT1>::NumLowBitsAvailable, - PT2BitsAv = PointerLikeTypeTraits<PT2>::NumLowBitsAvailable, + PT1BitsAv = (int)(PointerLikeTypeTraits<PT1>::NumLowBitsAvailable), + PT2BitsAv = (int)(PointerLikeTypeTraits<PT2>::NumLowBitsAvailable), NumLowBitsAvailable = PT1BitsAv < PT2BitsAv ? PT1BitsAv : PT2BitsAv }; }; diff --git a/include/llvm/ADT/PostOrderIterator.h b/include/llvm/ADT/PostOrderIterator.h index 63a2b52..7f6350e 100644 --- a/include/llvm/ADT/PostOrderIterator.h +++ b/include/llvm/ADT/PostOrderIterator.h @@ -23,26 +23,65 @@ namespace llvm { -template<class SetType, bool External> // Non-external set +// The po_iterator_storage template provides access to the set of already +// visited nodes during the po_iterator's depth-first traversal. +// +// The default implementation simply contains a set of visited nodes, while +// the Extended=true version uses a reference to an external set. +// +// It is possible to prune the depth-first traversal in several ways: +// +// - When providing an external set that already contains some graph nodes, +// those nodes won't be visited again. This is useful for restarting a +// post-order traversal on a graph with nodes that aren't dominated by a +// single node. +// +// - By providing a custom SetType class, unwanted graph nodes can be excluded +// by having the insert() function return false. This could for example +// confine a CFG traversal to blocks in a specific loop. +// +// - Finally, by specializing the po_iterator_storage template itself, graph +// edges can be pruned by returning false in the insertEdge() function. This +// could be used to remove loop back-edges from the CFG seen by po_iterator. +// +// A specialized po_iterator_storage class can observe both the pre-order and +// the post-order. The insertEdge() function is called in a pre-order, while +// the finishPostorder() function is called just before the po_iterator moves +// on to the next node. + +/// Default po_iterator_storage implementation with an internal set object. +template<class SetType, bool External> class po_iterator_storage { -public: SetType Visited; -}; +public: + // Return true if edge destination should be visited. + template<typename NodeType> + bool insertEdge(NodeType *From, NodeType *To) { + return Visited.insert(To); + } -/// DFSetTraits - Allow the SetType used to record depth-first search results to -/// optionally record node postorder. -template<class SetType> -struct DFSetTraits { - static void finishPostorder( - typename SetType::iterator::value_type, SetType &) {} + // Called after all children of BB have been visited. + template<typename NodeType> + void finishPostorder(NodeType *BB) {} }; +/// Specialization of po_iterator_storage that references an external set. template<class SetType> class po_iterator_storage<SetType, true> { + SetType &Visited; public: po_iterator_storage(SetType &VSet) : Visited(VSet) {} po_iterator_storage(const po_iterator_storage &S) : Visited(S.Visited) {} - SetType &Visited; + + // Return true if edge destination should be visited, called with From = 0 for + // the root node. + // Graph edges can be pruned by specializing this function. + template<class NodeType> + bool insertEdge(NodeType *From, NodeType *To) { return Visited.insert(To); } + + // Called after all children of BB have been visited. + template<class NodeType> + void finishPostorder(NodeType *BB) {} }; template<class GraphT, @@ -64,14 +103,15 @@ class po_iterator : public std::iterator<std::forward_iterator_tag, void traverseChild() { while (VisitStack.back().second != GT::child_end(VisitStack.back().first)) { NodeType *BB = *VisitStack.back().second++; - if (this->Visited.insert(BB)) { // If the block is not visited... + if (this->insertEdge(VisitStack.back().first, BB)) { + // If the block is not visited... VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB))); } } } inline po_iterator(NodeType *BB) { - this->Visited.insert(BB); + this->insertEdge((NodeType*)0, BB); VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB))); traverseChild(); } @@ -79,7 +119,7 @@ class po_iterator : public std::iterator<std::forward_iterator_tag, inline po_iterator(NodeType *BB, SetType &S) : po_iterator_storage<SetType, ExtStorage>(S) { - if (this->Visited.insert(BB)) { + if (this->insertEdge((NodeType*)0, BB)) { VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB))); traverseChild(); } @@ -117,8 +157,7 @@ public: inline NodeType *operator->() const { return operator*(); } inline _Self& operator++() { // Preincrement - DFSetTraits<SetType>::finishPostorder(VisitStack.back().first, - this->Visited); + this->finishPostorder(VisitStack.back().first); VisitStack.pop_back(); if (!VisitStack.empty()) traverseChild(); @@ -173,14 +212,14 @@ ipo_iterator<T> ipo_end(T G){ return ipo_iterator<T>::end(G); } -//Provide global definitions of external inverse postorder iterators... +// Provide global definitions of external inverse postorder iterators... template <class T, class SetType = std::set<typename GraphTraits<T>::NodeType*> > struct ipo_ext_iterator : public ipo_iterator<T, SetType, true> { ipo_ext_iterator(const ipo_iterator<T, SetType, true> &V) : - ipo_iterator<T, SetType, true>(&V) {} + ipo_iterator<T, SetType, true>(V) {} ipo_ext_iterator(const po_iterator<Inverse<T>, SetType, true> &V) : - ipo_iterator<T, SetType, true>(&V) {} + ipo_iterator<T, SetType, true>(V) {} }; template <class T, class SetType> diff --git a/include/llvm/ADT/STLExtras.h b/include/llvm/ADT/STLExtras.h index 5da906d..aee500d 100644 --- a/include/llvm/ADT/STLExtras.h +++ b/include/llvm/ADT/STLExtras.h @@ -30,6 +30,16 @@ namespace llvm { //===----------------------------------------------------------------------===// template<class Ty> +struct identity : public std::unary_function<Ty, Ty> { + Ty &operator()(Ty &self) const { + return self; + } + const Ty &operator()(const Ty &self) const { + return self; + } +}; + +template<class Ty> struct less_ptr : public std::binary_function<Ty, Ty, bool> { bool operator()(const Ty* left, const Ty* right) const { return *left < *right; @@ -49,7 +59,7 @@ struct greater_ptr : public std::binary_function<Ty, Ty, bool> { // for_each(V.begin(), B.end(), deleter<Interval>); // template <class T> -static inline void deleter(T *Ptr) { +inline void deleter(T *Ptr) { delete Ptr; } @@ -228,7 +238,7 @@ inline size_t array_lengthof(T (&)[N]) { /// array_pod_sort_comparator - This is helper function for array_pod_sort, /// which just uses operator< on T. template<typename T> -static inline int array_pod_sort_comparator(const void *P1, const void *P2) { +inline int array_pod_sort_comparator(const void *P1, const void *P2) { if (*reinterpret_cast<const T*>(P1) < *reinterpret_cast<const T*>(P2)) return -1; if (*reinterpret_cast<const T*>(P2) < *reinterpret_cast<const T*>(P1)) @@ -239,7 +249,7 @@ static inline int array_pod_sort_comparator(const void *P1, const void *P2) { /// get_array_pad_sort_comparator - This is an internal helper function used to /// get type deduction of T right. template<typename T> -static int (*get_array_pad_sort_comparator(const T &)) +inline int (*get_array_pad_sort_comparator(const T &)) (const void*, const void*) { return array_pod_sort_comparator<T>; } @@ -260,7 +270,7 @@ static int (*get_array_pad_sort_comparator(const T &)) /// NOTE: If qsort_r were portable, we could allow a custom comparator and /// default to std::less. template<class IteratorTy> -static inline void array_pod_sort(IteratorTy Start, IteratorTy End) { +inline void array_pod_sort(IteratorTy Start, IteratorTy End) { // Don't dereference start iterator of empty sequence. if (Start == End) return; qsort(&*Start, End-Start, sizeof(*Start), @@ -268,13 +278,13 @@ static inline void array_pod_sort(IteratorTy Start, IteratorTy End) { } template<class IteratorTy> -static inline void array_pod_sort(IteratorTy Start, IteratorTy End, +inline void array_pod_sort(IteratorTy Start, IteratorTy End, int (*Compare)(const void*, const void*)) { // Don't dereference start iterator of empty sequence. if (Start == End) return; qsort(&*Start, End-Start, sizeof(*Start), Compare); } - + //===----------------------------------------------------------------------===// // Extra additions to <algorithm> //===----------------------------------------------------------------------===// diff --git a/include/llvm/ADT/SmallBitVector.h b/include/llvm/ADT/SmallBitVector.h index a3469a1..7a645e0 100644 --- a/include/llvm/ADT/SmallBitVector.h +++ b/include/llvm/ADT/SmallBitVector.h @@ -15,6 +15,7 @@ #define LLVM_ADT_SMALLBITVECTOR_H #include "llvm/ADT/BitVector.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/MathExtras.h" #include <cassert> @@ -152,6 +153,12 @@ public: switchToLarge(new BitVector(*RHS.getPointer())); } +#if LLVM_USE_RVALUE_REFERENCES + SmallBitVector(SmallBitVector &&RHS) : X(RHS.X) { + RHS.X = 1; + } +#endif + ~SmallBitVector() { if (!isSmall()) delete getPointer(); @@ -347,6 +354,19 @@ public: return (*this)[Idx]; } + /// Test if any common bits are set. + bool anyCommon(const SmallBitVector &RHS) const { + if (isSmall() && RHS.isSmall()) + return (getSmallBits() & RHS.getSmallBits()) != 0; + if (!isSmall() && !RHS.isSmall()) + return getPointer()->anyCommon(*RHS.getPointer()); + + for (unsigned i = 0, e = std::min(size(), RHS.size()); i != e; ++i) + if (test(i) && RHS.test(i)) + return true; + return false; + } + // Comparison operators. bool operator==(const SmallBitVector &RHS) const { if (size() != RHS.size()) @@ -422,9 +442,72 @@ public: return *this; } +#if LLVM_USE_RVALUE_REFERENCES + const SmallBitVector &operator=(SmallBitVector &&RHS) { + if (this != &RHS) { + clear(); + swap(RHS); + } + return *this; + } +#endif + void swap(SmallBitVector &RHS) { std::swap(X, RHS.X); } + + /// setBitsInMask - Add '1' bits from Mask to this vector. Don't resize. + /// This computes "*this |= Mask". + void setBitsInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) { + if (isSmall()) + applyMask<true, false>(Mask, MaskWords); + else + getPointer()->setBitsInMask(Mask, MaskWords); + } + + /// clearBitsInMask - Clear any bits in this vector that are set in Mask. + /// Don't resize. This computes "*this &= ~Mask". + void clearBitsInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) { + if (isSmall()) + applyMask<false, false>(Mask, MaskWords); + else + getPointer()->clearBitsInMask(Mask, MaskWords); + } + + /// setBitsNotInMask - Add a bit to this vector for every '0' bit in Mask. + /// Don't resize. This computes "*this |= ~Mask". + void setBitsNotInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) { + if (isSmall()) + applyMask<true, true>(Mask, MaskWords); + else + getPointer()->setBitsNotInMask(Mask, MaskWords); + } + + /// clearBitsNotInMask - Clear a bit in this vector for every '0' bit in Mask. + /// Don't resize. This computes "*this &= Mask". + void clearBitsNotInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) { + if (isSmall()) + applyMask<false, true>(Mask, MaskWords); + else + getPointer()->clearBitsNotInMask(Mask, MaskWords); + } + +private: + template<bool AddBits, bool InvertMask> + void applyMask(const uint32_t *Mask, unsigned MaskWords) { + assert((NumBaseBits == 64 || NumBaseBits == 32) && "Unsupported word size"); + if (NumBaseBits == 64 && MaskWords >= 2) { + uint64_t M = Mask[0] | (uint64_t(Mask[1]) << 32); + if (InvertMask) M = ~M; + if (AddBits) setSmallBits(getSmallBits() | M); + else setSmallBits(getSmallBits() & ~M); + } else { + uint32_t M = Mask[0]; + if (InvertMask) M = ~M; + if (AddBits) setSmallBits(getSmallBits() | M); + else setSmallBits(getSmallBits() & ~M); + } + } }; inline SmallBitVector diff --git a/include/llvm/ADT/SmallString.h b/include/llvm/ADT/SmallString.h index 199783b..c6f0a5b 100644 --- a/include/llvm/ADT/SmallString.h +++ b/include/llvm/ADT/SmallString.h @@ -45,7 +45,7 @@ public: /// @{ /// Assign from a repeated element - void assign(unsigned NumElts, char Elt) { + void assign(size_t NumElts, char Elt) { this->SmallVectorImpl<char>::assign(NumElts, Elt); } @@ -77,6 +77,11 @@ public: void append(in_iter S, in_iter E) { SmallVectorImpl<char>::append(S, E); } + + void append(size_t NumInputs, char Elt) { + SmallVectorImpl<char>::append(NumInputs, Elt); + } + /// Append from a StringRef void append(StringRef RHS) { diff --git a/include/llvm/ADT/SmallVector.h b/include/llvm/ADT/SmallVector.h index 0d9d0d1..9fbbbe4 100644 --- a/include/llvm/ADT/SmallVector.h +++ b/include/llvm/ADT/SmallVector.h @@ -14,6 +14,7 @@ #ifndef LLVM_ADT_SMALLVECTOR_H #define LLVM_ADT_SMALLVECTOR_H +#include "llvm/Support/Compiler.h" #include "llvm/Support/type_traits.h" #include <algorithm> #include <cassert> @@ -54,6 +55,11 @@ protected: return BeginX == static_cast<const void*>(&FirstEl); } + /// resetToSmall - Put this vector in a state of being small. + void resetToSmall() { + BeginX = EndX = CapacityX = &FirstEl; + } + /// grow_pod - This is an implementation of the grow() method which only works /// on POD-like data types and is out of line to reduce code duplication. void grow_pod(size_t MinSizeInBytes, size_t TSize); @@ -160,28 +166,84 @@ protected: } } - /// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory - /// starting with "Dest", constructing elements into it as needed. + /// move - Use move-assignment to move the range [I, E) onto the + /// objects starting with "Dest". This is just <memory>'s + /// std::move, but not all stdlibs actually provide that. + template<typename It1, typename It2> + static It2 move(It1 I, It1 E, It2 Dest) { +#if LLVM_USE_RVALUE_REFERENCES + for (; I != E; ++I, ++Dest) + *Dest = ::std::move(*I); + return Dest; +#else + return ::std::copy(I, E, Dest); +#endif + } + + /// move_backward - Use move-assignment to move the range + /// [I, E) onto the objects ending at "Dest", moving objects + /// in reverse order. This is just <algorithm>'s + /// std::move_backward, but not all stdlibs actually provide that. + template<typename It1, typename It2> + static It2 move_backward(It1 I, It1 E, It2 Dest) { +#if LLVM_USE_RVALUE_REFERENCES + while (I != E) + *--Dest = ::std::move(*--E); + return Dest; +#else + return ::std::copy_backward(I, E, Dest); +#endif + } + + /// uninitialized_move - Move the range [I, E) into the uninitialized + /// memory starting with "Dest", constructing elements as needed. + template<typename It1, typename It2> + static void uninitialized_move(It1 I, It1 E, It2 Dest) { +#if LLVM_USE_RVALUE_REFERENCES + for (; I != E; ++I, ++Dest) + ::new ((void*) &*Dest) T(::std::move(*I)); +#else + ::std::uninitialized_copy(I, E, Dest); +#endif + } + + /// uninitialized_copy - Copy the range [I, E) onto the uninitialized + /// memory starting with "Dest", constructing elements as needed. template<typename It1, typename It2> static void uninitialized_copy(It1 I, It1 E, It2 Dest) { std::uninitialized_copy(I, E, Dest); } - /// grow - double the size of the allocated memory, guaranteeing space for at - /// least one more element or MinSize if specified. + /// grow - Grow the allocated memory (without initializing new + /// elements), doubling the size of the allocated memory. + /// Guarantees space for at least one more element, or MinSize more + /// elements if specified. void grow(size_t MinSize = 0); public: void push_back(const T &Elt) { if (this->EndX < this->CapacityX) { Retry: - new (this->end()) T(Elt); + ::new ((void*) this->end()) T(Elt); this->setEnd(this->end()+1); return; } this->grow(); goto Retry; } + +#if LLVM_USE_RVALUE_REFERENCES + void push_back(T &&Elt) { + if (this->EndX < this->CapacityX) { + Retry: + ::new ((void*) this->end()) T(::std::move(Elt)); + this->setEnd(this->end()+1); + return; + } + this->grow(); + goto Retry; + } +#endif void pop_back() { this->setEnd(this->end()-1); @@ -199,8 +261,8 @@ void SmallVectorTemplateBase<T, isPodLike>::grow(size_t MinSize) { NewCapacity = MinSize; T *NewElts = static_cast<T*>(malloc(NewCapacity*sizeof(T))); - // Copy the elements over. - this->uninitialized_copy(this->begin(), this->end(), NewElts); + // Move the elements over. + this->uninitialized_move(this->begin(), this->end(), NewElts); // Destroy the original elements. destroy_range(this->begin(), this->end()); @@ -225,6 +287,29 @@ protected: // No need to do a destroy loop for POD's. static void destroy_range(T *, T *) {} + /// move - Use move-assignment to move the range [I, E) onto the + /// objects starting with "Dest". For PODs, this is just memcpy. + template<typename It1, typename It2> + static It2 move(It1 I, It1 E, It2 Dest) { + return ::std::copy(I, E, Dest); + } + + /// move_backward - Use move-assignment to move the range + /// [I, E) onto the objects ending at "Dest", moving objects + /// in reverse order. + template<typename It1, typename It2> + static It2 move_backward(It1 I, It1 E, It2 Dest) { + return ::std::copy_backward(I, E, Dest); + } + + /// uninitialized_move - Move the range [I, E) onto the uninitialized memory + /// starting with "Dest", constructing elements into it as needed. + template<typename It1, typename It2> + static void uninitialized_move(It1 I, It1 E, It2 Dest) { + // Just do a copy. + uninitialized_copy(I, E, Dest); + } + /// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory /// starting with "Dest", constructing elements into it as needed. template<typename It1, typename It2> @@ -252,7 +337,7 @@ public: void push_back(const T &Elt) { if (this->EndX < this->CapacityX) { Retry: - *this->end() = Elt; + memcpy(this->end(), &Elt, sizeof(T)); this->setEnd(this->end()+1); return; } @@ -330,7 +415,11 @@ public: } T pop_back_val() { +#if LLVM_USE_RVALUE_REFERENCES + T Result = ::std::move(this->back()); +#else T Result = this->back(); +#endif this->pop_back(); return Result; } @@ -374,36 +463,79 @@ public: } iterator erase(iterator I) { + assert(I >= this->begin() && "Iterator to erase is out of bounds."); + assert(I < this->end() && "Erasing at past-the-end iterator."); + iterator N = I; // Shift all elts down one. - std::copy(I+1, this->end(), I); + this->move(I+1, this->end(), I); // Drop the last elt. this->pop_back(); return(N); } iterator erase(iterator S, iterator E) { + assert(S >= this->begin() && "Range to erase is out of bounds."); + assert(S <= E && "Trying to erase invalid range."); + assert(E <= this->end() && "Trying to erase past the end."); + iterator N = S; // Shift all elts down. - iterator I = std::copy(E, this->end(), S); + iterator I = this->move(E, this->end(), S); // Drop the last elts. this->destroy_range(I, this->end()); this->setEnd(I); return(N); } +#if LLVM_USE_RVALUE_REFERENCES + iterator insert(iterator I, T &&Elt) { + if (I == this->end()) { // Important special case for empty vector. + this->push_back(::std::move(Elt)); + return this->end()-1; + } + + assert(I >= this->begin() && "Insertion iterator is out of bounds."); + assert(I <= this->end() && "Inserting past the end of the vector."); + + if (this->EndX < this->CapacityX) { + Retry: + ::new ((void*) this->end()) T(::std::move(this->back())); + this->setEnd(this->end()+1); + // Push everything else over. + this->move_backward(I, this->end()-1, this->end()); + + // If we just moved the element we're inserting, be sure to update + // the reference. + T *EltPtr = &Elt; + if (I <= EltPtr && EltPtr < this->EndX) + ++EltPtr; + + *I = ::std::move(*EltPtr); + return I; + } + size_t EltNo = I-this->begin(); + this->grow(); + I = this->begin()+EltNo; + goto Retry; + } +#endif + iterator insert(iterator I, const T &Elt) { if (I == this->end()) { // Important special case for empty vector. this->push_back(Elt); return this->end()-1; } + assert(I >= this->begin() && "Insertion iterator is out of bounds."); + assert(I <= this->end() && "Inserting past the end of the vector."); + if (this->EndX < this->CapacityX) { Retry: - new (this->end()) T(this->back()); + ::new ((void*) this->end()) T(this->back()); this->setEnd(this->end()+1); // Push everything else over. - std::copy_backward(I, this->end()-1, this->end()); + this->move_backward(I, this->end()-1, this->end()); // If we just moved the element we're inserting, be sure to update // the reference. @@ -421,13 +553,16 @@ public: } iterator insert(iterator I, size_type NumToInsert, const T &Elt) { + // Convert iterator to elt# to avoid invalidating iterator when we reserve() + size_t InsertElt = I - this->begin(); + if (I == this->end()) { // Important special case for empty vector. append(NumToInsert, Elt); - return this->end()-1; + return this->begin()+InsertElt; } - // Convert iterator to elt# to avoid invalidating iterator when we reserve() - size_t InsertElt = I - this->begin(); + assert(I >= this->begin() && "Insertion iterator is out of bounds."); + assert(I <= this->end() && "Inserting past the end of the vector."); // Ensure there is enough space. reserve(static_cast<unsigned>(this->size() + NumToInsert)); @@ -444,7 +579,7 @@ public: append(this->end()-NumToInsert, this->end()); // Copy the existing elements that get replaced. - std::copy_backward(I, OldEnd-NumToInsert, OldEnd); + this->move_backward(I, OldEnd-NumToInsert, OldEnd); std::fill_n(I, NumToInsert, Elt); return I; @@ -453,11 +588,11 @@ public: // Otherwise, we're inserting more elements than exist already, and we're // not inserting at the end. - // Copy over the elements that we're about to overwrite. + // Move over the elements that we're about to overwrite. T *OldEnd = this->end(); this->setEnd(this->end() + NumToInsert); size_t NumOverwritten = OldEnd-I; - this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten); + this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten); // Replace the overwritten part. std::fill_n(I, NumOverwritten, Elt); @@ -469,14 +604,18 @@ public: template<typename ItTy> iterator insert(iterator I, ItTy From, ItTy To) { + // Convert iterator to elt# to avoid invalidating iterator when we reserve() + size_t InsertElt = I - this->begin(); + if (I == this->end()) { // Important special case for empty vector. append(From, To); - return this->end()-1; + return this->begin()+InsertElt; } + assert(I >= this->begin() && "Insertion iterator is out of bounds."); + assert(I <= this->end() && "Inserting past the end of the vector."); + size_t NumToInsert = std::distance(From, To); - // Convert iterator to elt# to avoid invalidating iterator when we reserve() - size_t InsertElt = I - this->begin(); // Ensure there is enough space. reserve(static_cast<unsigned>(this->size() + NumToInsert)); @@ -493,7 +632,7 @@ public: append(this->end()-NumToInsert, this->end()); // Copy the existing elements that get replaced. - std::copy_backward(I, OldEnd-NumToInsert, OldEnd); + this->move_backward(I, OldEnd-NumToInsert, OldEnd); std::copy(From, To, I); return I; @@ -502,16 +641,16 @@ public: // Otherwise, we're inserting more elements than exist already, and we're // not inserting at the end. - // Copy over the elements that we're about to overwrite. + // Move over the elements that we're about to overwrite. T *OldEnd = this->end(); this->setEnd(this->end() + NumToInsert); size_t NumOverwritten = OldEnd-I; - this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten); + this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten); // Replace the overwritten part. - for (; NumOverwritten > 0; --NumOverwritten) { - *I = *From; - ++I; ++From; + for (T *J = I; NumOverwritten > 0; --NumOverwritten) { + *J = *From; + ++J; ++From; } // Insert the non-overwritten middle part. @@ -519,8 +658,11 @@ public: return I; } - const SmallVectorImpl - &operator=(const SmallVectorImpl &RHS); + SmallVectorImpl &operator=(const SmallVectorImpl &RHS); + +#if LLVM_USE_RVALUE_REFERENCES + SmallVectorImpl &operator=(SmallVectorImpl &&RHS); +#endif bool operator==(const SmallVectorImpl &RHS) const { if (this->size() != RHS.size()) return false; @@ -590,7 +732,7 @@ void SmallVectorImpl<T>::swap(SmallVectorImpl<T> &RHS) { } template <typename T> -const SmallVectorImpl<T> &SmallVectorImpl<T>:: +SmallVectorImpl<T> &SmallVectorImpl<T>:: operator=(const SmallVectorImpl<T> &RHS) { // Avoid self-assignment. if (this == &RHS) return *this; @@ -617,6 +759,7 @@ const SmallVectorImpl<T> &SmallVectorImpl<T>:: // If we have to grow to have enough elements, destroy the current elements. // This allows us to avoid copying them during the grow. + // FIXME: don't do this if they're efficiently moveable. if (this->capacity() < RHSSize) { // Destroy current elements. this->destroy_range(this->begin(), this->end()); @@ -637,6 +780,69 @@ const SmallVectorImpl<T> &SmallVectorImpl<T>:: return *this; } +#if LLVM_USE_RVALUE_REFERENCES +template <typename T> +SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) { + // Avoid self-assignment. + if (this == &RHS) return *this; + + // If the RHS isn't small, clear this vector and then steal its buffer. + if (!RHS.isSmall()) { + this->destroy_range(this->begin(), this->end()); + if (!this->isSmall()) free(this->begin()); + this->BeginX = RHS.BeginX; + this->EndX = RHS.EndX; + this->CapacityX = RHS.CapacityX; + RHS.resetToSmall(); + return *this; + } + + // If we already have sufficient space, assign the common elements, then + // destroy any excess. + size_t RHSSize = RHS.size(); + size_t CurSize = this->size(); + if (CurSize >= RHSSize) { + // Assign common elements. + iterator NewEnd = this->begin(); + if (RHSSize) + NewEnd = this->move(RHS.begin(), RHS.end(), NewEnd); + + // Destroy excess elements and trim the bounds. + this->destroy_range(NewEnd, this->end()); + this->setEnd(NewEnd); + + // Clear the RHS. + RHS.clear(); + + return *this; + } + + // If we have to grow to have enough elements, destroy the current elements. + // This allows us to avoid copying them during the grow. + // FIXME: this may not actually make any sense if we can efficiently move + // elements. + if (this->capacity() < RHSSize) { + // Destroy current elements. + this->destroy_range(this->begin(), this->end()); + this->setEnd(this->begin()); + CurSize = 0; + this->grow(RHSSize); + } else if (CurSize) { + // Otherwise, use assignment for the already-constructed elements. + this->move(RHS.begin(), RHS.end(), this->begin()); + } + + // Move-construct the new elements in place. + this->uninitialized_move(RHS.begin()+CurSize, RHS.end(), + this->begin()+CurSize); + + // Set end. + this->setEnd(this->begin()+RHSSize); + + RHS.clear(); + return *this; +} +#endif /// SmallVector - This is a 'vector' (really, a variable-sized array), optimized /// for the case when the array is small. It contains some number of elements @@ -692,6 +898,18 @@ public: return *this; } +#if LLVM_USE_RVALUE_REFERENCES + SmallVector(SmallVector &&RHS) : SmallVectorImpl<T>(NumTsAvailable) { + if (!RHS.empty()) + SmallVectorImpl<T>::operator=(::std::move(RHS)); + } + + const SmallVector &operator=(SmallVector &&RHS) { + SmallVectorImpl<T>::operator=(::std::move(RHS)); + return *this; + } +#endif + }; /// Specialize SmallVector at N=0. This specialization guarantees @@ -700,7 +918,8 @@ public: template <typename T> class SmallVector<T,0> : public SmallVectorImpl<T> { public: - SmallVector() : SmallVectorImpl<T>(0) {} + SmallVector() : SmallVectorImpl<T>(0) { + } explicit SmallVector(unsigned Size, const T &Value = T()) : SmallVectorImpl<T>(0) { @@ -713,13 +932,26 @@ public: } SmallVector(const SmallVector &RHS) : SmallVectorImpl<T>(0) { + if (!RHS.empty()) + SmallVectorImpl<T>::operator=(RHS); + } + + const SmallVector &operator=(const SmallVector &RHS) { SmallVectorImpl<T>::operator=(RHS); + return *this; } - SmallVector &operator=(const SmallVectorImpl<T> &RHS) { - return SmallVectorImpl<T>::operator=(RHS); +#if LLVM_USE_RVALUE_REFERENCES + SmallVector(SmallVector &&RHS) : SmallVectorImpl<T>(0) { + if (!RHS.empty()) + SmallVectorImpl<T>::operator=(::std::move(RHS)); } + const SmallVector &operator=(SmallVector &&RHS) { + SmallVectorImpl<T>::operator=(::std::move(RHS)); + return *this; + } +#endif }; template<typename T, unsigned N> diff --git a/include/llvm/ADT/SparseSet.h b/include/llvm/ADT/SparseSet.h index 923c6a5..55696333 100644 --- a/include/llvm/ADT/SparseSet.h +++ b/include/llvm/ADT/SparseSet.h @@ -21,33 +21,62 @@ #define LLVM_ADT_SPARSESET_H #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Support/DataTypes.h" #include <limits> namespace llvm { -/// SparseSetFunctor - Objects in a SparseSet are identified by small integer -/// keys. A functor object is used to compute the key of an object. The -/// functor's operator() must return an unsigned smaller than the universe. +/// SparseSetValTraits - Objects in a SparseSet are identified by keys that can +/// be uniquely converted to a small integer less than the set's universe. This +/// class allows the set to hold values that differ from the set's key type as +/// long as an index can still be derived from the value. SparseSet never +/// directly compares ValueT, only their indices, so it can map keys to +/// arbitrary values. SparseSetValTraits computes the index from the value +/// object. To compute the index from a key, SparseSet uses a separate +/// KeyFunctorT template argument. /// -/// The default functor implementation forwards to a getSparseSetKey() method -/// on the object. It is intended for sparse sets holding ad-hoc structs. +/// A simple type declaration, SparseSet<Type>, handles these cases: +/// - unsigned key, identity index, identity value +/// - unsigned key, identity index, fat value providing getSparseSetIndex() +/// +/// The type declaration SparseSet<Type, UnaryFunction> handles: +/// - unsigned key, remapped index, identity value (virtual registers) +/// - pointer key, pointer-derived index, identity value (node+ID) +/// - pointer key, pointer-derived index, fat value with getSparseSetIndex() +/// +/// Only other, unexpected cases require specializing SparseSetValTraits. +/// +/// For best results, ValueT should not require a destructor. /// template<typename ValueT> -struct SparseSetFunctor { - unsigned operator()(const ValueT &Val) { - return Val.getSparseSetKey(); +struct SparseSetValTraits { + static unsigned getValIndex(const ValueT &Val) { + return Val.getSparseSetIndex(); } }; -/// SparseSetFunctor<unsigned> - Provide a trivial identity functor for -/// SparseSet<unsigned>. +/// SparseSetValFunctor - Helper class for selecting SparseSetValTraits. The +/// generic implementation handles ValueT classes which either provide +/// getSparseSetIndex() or specialize SparseSetValTraits<>. /// -template<> struct SparseSetFunctor<unsigned> { - unsigned operator()(unsigned Val) { return Val; } +template<typename KeyT, typename ValueT, typename KeyFunctorT> +struct SparseSetValFunctor { + unsigned operator()(const ValueT &Val) const { + return SparseSetValTraits<ValueT>::getValIndex(Val); + } }; -/// SparseSet - Fast set implementation for objects that can be identified by +/// SparseSetValFunctor<KeyT, KeyT> - Helper class for the common case of +/// identity key/value sets. +template<typename KeyT, typename KeyFunctorT> +struct SparseSetValFunctor<KeyT, KeyT, KeyFunctorT> { + unsigned operator()(const KeyT &Key) const { + return KeyFunctorT()(Key); + } +}; + +/// SparseSet - Fast set implmentation for objects that can be identified by /// small unsigned keys. /// /// SparseSet allocates memory proportional to the size of the key universe, so @@ -82,18 +111,20 @@ template<> struct SparseSetFunctor<unsigned> { /// uint16_t or uint32_t. /// /// @param ValueT The type of objects in the set. +/// @param KeyFunctorT A functor that computes an unsigned index from KeyT. /// @param SparseT An unsigned integer type. See above. -/// @param KeyFunctorT A functor that computes the unsigned key of a ValueT. /// template<typename ValueT, - typename SparseT = uint8_t, - typename KeyFunctorT = SparseSetFunctor<ValueT> > + typename KeyFunctorT = llvm::identity<unsigned>, + typename SparseT = uint8_t> class SparseSet { + typedef typename KeyFunctorT::argument_type KeyT; typedef SmallVector<ValueT, 8> DenseT; DenseT Dense; SparseT *Sparse; unsigned Universe; - KeyFunctorT KeyOf; + KeyFunctorT KeyIndexOf; + SparseSetValFunctor<KeyT, ValueT, KeyFunctorT> ValIndexOf; // Disable copy construction and assignment. // This data structure is not meant to be used that way. @@ -160,21 +191,21 @@ public: Dense.clear(); } - /// find - Find an element by its key. + /// findIndex - Find an element by its index. /// - /// @param Key A valid key to find. + /// @param Idx A valid index to find. /// @returns An iterator to the element identified by key, or end(). /// - iterator find(unsigned Key) { - assert(Key < Universe && "Key out of range"); + iterator findIndex(unsigned Idx) { + assert(Idx < Universe && "Key out of range"); assert(std::numeric_limits<SparseT>::is_integer && !std::numeric_limits<SparseT>::is_signed && "SparseT must be an unsigned integer type"); const unsigned Stride = std::numeric_limits<SparseT>::max() + 1u; - for (unsigned i = Sparse[Key], e = size(); i < e; i += Stride) { - const unsigned FoundKey = KeyOf(Dense[i]); - assert(FoundKey < Universe && "Invalid key in set. Did object mutate?"); - if (Key == FoundKey) + for (unsigned i = Sparse[Idx], e = size(); i < e; i += Stride) { + const unsigned FoundIdx = ValIndexOf(Dense[i]); + assert(FoundIdx < Universe && "Invalid key in set. Did object mutate?"); + if (Idx == FoundIdx) return begin() + i; // Stride is 0 when SparseT >= unsigned. We don't need to loop. if (!Stride) @@ -183,13 +214,22 @@ public: return end(); } - const_iterator find(unsigned Key) const { - return const_cast<SparseSet*>(this)->find(Key); + /// find - Find an element by its key. + /// + /// @param Key A valid key to find. + /// @returns An iterator to the element identified by key, or end(). + /// + iterator find(const KeyT &Key) { + return findIndex(KeyIndexOf(Key)); + } + + const_iterator find(const KeyT &Key) const { + return const_cast<SparseSet*>(this)->findIndex(KeyIndexOf(Key)); } /// count - Returns true if this set contains an element identified by Key. /// - bool count(unsigned Key) const { + bool count(const KeyT &Key) const { return find(Key) != end(); } @@ -204,11 +244,11 @@ public: /// Insertion invalidates all iterators. /// std::pair<iterator, bool> insert(const ValueT &Val) { - unsigned Key = KeyOf(Val); - iterator I = find(Key); + unsigned Idx = ValIndexOf(Val); + iterator I = findIndex(Idx); if (I != end()) return std::make_pair(I, false); - Sparse[Key] = size(); + Sparse[Idx] = size(); Dense.push_back(Val); return std::make_pair(end() - 1, true); } @@ -216,7 +256,7 @@ public: /// array subscript - If an element already exists with this key, return it. /// Otherwise, automatically construct a new value from Key, insert it, /// and return the newly inserted element. - ValueT &operator[](unsigned Key) { + ValueT &operator[](const KeyT &Key) { return *insert(ValueT(Key)).first; } @@ -238,9 +278,9 @@ public: assert(unsigned(I - begin()) < size() && "Invalid iterator"); if (I != end() - 1) { *I = Dense.back(); - unsigned BackKey = KeyOf(Dense.back()); - assert(BackKey < Universe && "Invalid key in set. Did object mutate?"); - Sparse[BackKey] = I - begin(); + unsigned BackIdx = ValIndexOf(Dense.back()); + assert(BackIdx < Universe && "Invalid key in set. Did object mutate?"); + Sparse[BackIdx] = I - begin(); } // This depends on SmallVector::pop_back() not invalidating iterators. // std::vector::pop_back() doesn't give that guarantee. @@ -253,7 +293,7 @@ public: /// @param Key The key identifying the element to erase. /// @returns True when an element was erased, false if no element was found. /// - bool erase(unsigned Key) { + bool erase(const KeyT &Key) { iterator I = find(Key); if (I == end()) return false; diff --git a/include/llvm/ADT/StringRef.h b/include/llvm/ADT/StringRef.h index 76ba66e..cd84603 100644 --- a/include/llvm/ADT/StringRef.h +++ b/include/llvm/ADT/StringRef.h @@ -12,6 +12,7 @@ #include "llvm/Support/type_traits.h" +#include <algorithm> #include <cassert> #include <cstring> #include <limits> @@ -292,6 +293,16 @@ namespace llvm { /// Note: O(size() + Chars.size()) size_type find_last_of(StringRef Chars, size_t From = npos) const; + /// find_last_not_of - Find the last character in the string that is not + /// \arg C, or npos if not found. + size_type find_last_not_of(char C, size_t From = npos) const; + + /// find_last_not_of - Find the last character in the string that is not in + /// \arg Chars, or npos if not found. + /// + /// Note: O(size() + Chars.size()) + size_type find_last_not_of(StringRef Chars, size_t From = npos) const; + /// @} /// @name Helpful Algorithms /// @{ @@ -480,6 +491,24 @@ namespace llvm { return std::make_pair(slice(0, Idx), slice(Idx+1, npos)); } + /// ltrim - Return string with consecutive characters in \arg Chars starting + /// from the left removed. + StringRef ltrim(StringRef Chars = " \t\n\v\f\r") const { + return drop_front(std::min(Length, find_first_not_of(Chars))); + } + + /// rtrim - Return string with consecutive characters in \arg Chars starting + /// from the right removed. + StringRef rtrim(StringRef Chars = " \t\n\v\f\r") const { + return drop_back(Length - std::min(Length, find_last_not_of(Chars) + 1)); + } + + /// trim - Return string with consecutive characters in \arg Chars starting + /// from the left and right removed. + StringRef trim(StringRef Chars = " \t\n\v\f\r") const { + return ltrim(Chars).rtrim(Chars); + } + /// @} }; diff --git a/include/llvm/ADT/StringSwitch.h b/include/llvm/ADT/StringSwitch.h index 7480583..7fd6e279 100644 --- a/include/llvm/ADT/StringSwitch.h +++ b/include/llvm/ADT/StringSwitch.h @@ -48,8 +48,8 @@ class StringSwitch { const T *Result; public: - explicit StringSwitch(StringRef Str) - : Str(Str), Result(0) { } + explicit StringSwitch(StringRef S) + : Str(S), Result(0) { } template<unsigned N> StringSwitch& Case(const char (&S)[N], const T& Value) { diff --git a/include/llvm/ADT/TinyPtrVector.h b/include/llvm/ADT/TinyPtrVector.h index 5014517..d3d33b8 100644 --- a/include/llvm/ADT/TinyPtrVector.h +++ b/include/llvm/ADT/TinyPtrVector.h @@ -10,8 +10,11 @@ #ifndef LLVM_ADT_TINYPTRVECTOR_H #define LLVM_ADT_TINYPTRVECTOR_H -#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Compiler.h" namespace llvm { @@ -25,18 +28,78 @@ template <typename EltTy> class TinyPtrVector { public: typedef llvm::SmallVector<EltTy, 4> VecTy; + typedef typename VecTy::value_type value_type; + llvm::PointerUnion<EltTy, VecTy*> Val; - + TinyPtrVector() {} + ~TinyPtrVector() { + if (VecTy *V = Val.template dyn_cast<VecTy*>()) + delete V; + } + TinyPtrVector(const TinyPtrVector &RHS) : Val(RHS.Val) { if (VecTy *V = Val.template dyn_cast<VecTy*>()) Val = new VecTy(*V); } - ~TinyPtrVector() { - if (VecTy *V = Val.template dyn_cast<VecTy*>()) + TinyPtrVector &operator=(const TinyPtrVector &RHS) { + if (this == &RHS) + return *this; + if (RHS.empty()) { + this->clear(); + return *this; + } + + // Try to squeeze into the single slot. If it won't fit, allocate a copied + // vector. + if (Val.template is<EltTy>()) { + if (RHS.size() == 1) + Val = RHS.front(); + else + Val = new VecTy(*RHS.Val.template get<VecTy*>()); + return *this; + } + + // If we have a full vector allocated, try to re-use it. + if (RHS.Val.template is<EltTy>()) { + Val.template get<VecTy*>()->clear(); + Val.template get<VecTy*>()->push_back(RHS.front()); + } else { + *Val.template get<VecTy*>() = *RHS.Val.template get<VecTy*>(); + } + return *this; + } + +#if LLVM_USE_RVALUE_REFERENCES + TinyPtrVector(TinyPtrVector &&RHS) : Val(RHS.Val) { + RHS.Val = (EltTy)0; + } + TinyPtrVector &operator=(TinyPtrVector &&RHS) { + if (this == &RHS) + return *this; + if (RHS.empty()) { + this->clear(); + return *this; + } + + // If this vector has been allocated on the heap, re-use it if cheap. If it + // would require more copying, just delete it and we'll steal the other + // side. + if (VecTy *V = Val.template dyn_cast<VecTy*>()) { + if (RHS.Val.template is<EltTy>()) { + V->clear(); + V->push_back(RHS.front()); + return *this; + } delete V; + } + + Val = RHS.Val; + RHS.Val = (EltTy)0; + return *this; } - +#endif + // implicit conversion operator to ArrayRef. operator ArrayRef<EltTy>() const { if (Val.isNull()) @@ -45,7 +108,7 @@ public: return *Val.getAddrOfPtr1(); return *Val.template get<VecTy*>(); } - + bool empty() const { // This vector can be empty if it contains no element, or if it // contains a pointer to an empty vector. @@ -54,7 +117,7 @@ public: return Vec->empty(); return false; } - + unsigned size() const { if (empty()) return 0; @@ -62,27 +125,21 @@ public: return 1; return Val.template get<VecTy*>()->size(); } - + typedef const EltTy *const_iterator; typedef EltTy *iterator; iterator begin() { - if (empty()) - return 0; - if (Val.template is<EltTy>()) return Val.getAddrOfPtr1(); - + return Val.template get<VecTy *>()->begin(); } iterator end() { - if (empty()) - return 0; - if (Val.template is<EltTy>()) - return begin() + 1; - + return begin() + (Val.isNull() ? 0 : 1); + return Val.template get<VecTy *>()->end(); } @@ -100,38 +157,53 @@ public: assert(i == 0 && "tinyvector index out of range"); return V; } - - assert(i < Val.template get<VecTy*>()->size() && + + assert(i < Val.template get<VecTy*>()->size() && "tinyvector index out of range"); return (*Val.template get<VecTy*>())[i]; } - + EltTy front() const { assert(!empty() && "vector empty"); if (EltTy V = Val.template dyn_cast<EltTy>()) return V; return Val.template get<VecTy*>()->front(); } - + + EltTy back() const { + assert(!empty() && "vector empty"); + if (EltTy V = Val.template dyn_cast<EltTy>()) + return V; + return Val.template get<VecTy*>()->back(); + } + void push_back(EltTy NewVal) { assert(NewVal != 0 && "Can't add a null value"); - + // If we have nothing, add something. if (Val.isNull()) { Val = NewVal; return; } - + // If we have a single value, convert to a vector. if (EltTy V = Val.template dyn_cast<EltTy>()) { Val = new VecTy(); Val.template get<VecTy*>()->push_back(V); } - + // Add the new value, we know we have a vector. Val.template get<VecTy*>()->push_back(NewVal); } - + + void pop_back() { + // If we have a single value, convert to empty. + if (Val.template is<EltTy>()) + Val = (EltTy)0; + else if (VecTy *Vec = Val.template get<VecTy*>()) + Vec->pop_back(); + } + void clear() { // If we have a single value, convert to empty. if (Val.template is<EltTy>()) { @@ -144,6 +216,9 @@ public: } iterator erase(iterator I) { + assert(I >= begin() && "Iterator to erase is out of bounds."); + assert(I < end() && "Erasing at past-the-end iterator."); + // If we have a single value, convert to empty. if (Val.template is<EltTy>()) { if (I == begin()) @@ -153,12 +228,63 @@ public: // benefit to collapsing back to a pointer return Vec->erase(I); } + return end(); + } + + iterator erase(iterator S, iterator E) { + assert(S >= begin() && "Range to erase is out of bounds."); + assert(S <= E && "Trying to erase invalid range."); + assert(E <= end() && "Trying to erase past the end."); + + if (Val.template is<EltTy>()) { + if (S == begin() && S != E) + Val = (EltTy)0; + } else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) { + return Vec->erase(S, E); + } + return end(); + } - return 0; + iterator insert(iterator I, const EltTy &Elt) { + assert(I >= this->begin() && "Insertion iterator is out of bounds."); + assert(I <= this->end() && "Inserting past the end of the vector."); + if (I == end()) { + push_back(Elt); + return llvm::prior(end()); + } + assert(!Val.isNull() && "Null value with non-end insert iterator."); + if (EltTy V = Val.template dyn_cast<EltTy>()) { + assert(I == begin()); + Val = Elt; + push_back(V); + return begin(); + } + + return Val.template get<VecTy*>()->insert(I, Elt); + } + + template<typename ItTy> + iterator insert(iterator I, ItTy From, ItTy To) { + assert(I >= this->begin() && "Insertion iterator is out of bounds."); + assert(I <= this->end() && "Inserting past the end of the vector."); + if (From == To) + return I; + + // If we have a single value, convert to a vector. + ptrdiff_t Offset = I - begin(); + if (Val.isNull()) { + if (llvm::next(From) == To) { + Val = *From; + return begin(); + } + + Val = new VecTy(); + } else if (EltTy V = Val.template dyn_cast<EltTy>()) { + Val = new VecTy(); + Val.template get<VecTy*>()->push_back(V); + } + return Val.template get<VecTy*>()->insert(begin() + Offset, From, To); } - -private: - void operator=(const TinyPtrVector&); // NOT IMPLEMENTED YET. }; } // end namespace llvm diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h index f5f99d0..7f7061a 100644 --- a/include/llvm/ADT/Triple.h +++ b/include/llvm/ADT/Triple.h @@ -62,8 +62,8 @@ public: x86_64, // X86-64: amd64, x86_64 xcore, // XCore: xcore mblaze, // MBlaze: mblaze - ptx32, // PTX: ptx (32-bit) - ptx64, // PTX: ptx (64-bit) + nvptx, // NVPTX: 32-bit + nvptx64, // NVPTX: 64-bit le32, // le32: generic little-endian 32-bit CPU (PNaCl / Emscripten) amdil // amdil: amd IL }; @@ -98,7 +98,8 @@ public: Minix, RTEMS, NativeClient, - CNK // BG/P Compute-Node Kernel + CNK, // BG/P Compute-Node Kernel + Bitrig }; enum EnvironmentType { UnknownEnvironment, @@ -194,6 +195,11 @@ public: bool getMacOSXVersion(unsigned &Major, unsigned &Minor, unsigned &Micro) const; + /// getiOSVersion - Parse the version number as with getOSVersion. This should + /// only be called with IOS triples. + void getiOSVersion(unsigned &Major, unsigned &Minor, + unsigned &Micro) const; + /// @} /// @name Direct Component Access /// @{ @@ -266,7 +272,7 @@ public: /// compatibility, which handles supporting skewed version numbering schemes /// used by the "darwin" triples. unsigned isMacOSXVersionLT(unsigned Major, unsigned Minor = 0, - unsigned Micro = 0) const { + unsigned Micro = 0) const { assert(isMacOSX() && "Not an OS X triple!"); // If this is OS X, expect a sane version number. diff --git a/include/llvm/ADT/ValueMap.h b/include/llvm/ADT/ValueMap.h index 707d07d..f7e2551 100644 --- a/include/llvm/ADT/ValueMap.h +++ b/include/llvm/ADT/ValueMap.h @@ -111,20 +111,21 @@ public: /// count - Return true if the specified key is in the map. bool count(const KeyT &Val) const { - return Map.count(Wrap(Val)); + return Map.find_as(Val) != Map.end(); } iterator find(const KeyT &Val) { - return iterator(Map.find(Wrap(Val))); + return iterator(Map.find_as(Val)); } const_iterator find(const KeyT &Val) const { - return const_iterator(Map.find(Wrap(Val))); + return const_iterator(Map.find_as(Val)); } /// lookup - Return the entry for the specified key, or a default /// constructed value if no such entry exists. ValueT lookup(const KeyT &Val) const { - return Map.lookup(Wrap(Val)); + typename MapT::const_iterator I = Map.find_as(Val); + return I != Map.end() ? I->second : ValueT(); } // Inserts key,value pair into the map if the key isn't already in the map. @@ -145,7 +146,12 @@ public: bool erase(const KeyT &Val) { - return Map.erase(Wrap(Val)); + typename MapT::iterator I = Map.find_as(Val); + if (I == Map.end()) + return false; + + Map.erase(I); + return true; } void erase(iterator I) { return Map.erase(I.base()); @@ -256,9 +262,15 @@ struct DenseMapInfo<ValueMapCallbackVH<KeyT, ValueT, Config> > { static unsigned getHashValue(const VH &Val) { return PointerInfo::getHashValue(Val.Unwrap()); } + static unsigned getHashValue(const KeyT &Val) { + return PointerInfo::getHashValue(Val); + } static bool isEqual(const VH &LHS, const VH &RHS) { return LHS == RHS; } + static bool isEqual(const KeyT &LHS, const VH &RHS) { + return LHS == RHS.getValPtr(); + } }; diff --git a/include/llvm/Analysis/AliasAnalysis.h b/include/llvm/Analysis/AliasAnalysis.h index b823f71..674868a 100644 --- a/include/llvm/Analysis/AliasAnalysis.h +++ b/include/llvm/Analysis/AliasAnalysis.h @@ -50,6 +50,7 @@ class Pass; class AnalysisUsage; class MemTransferInst; class MemIntrinsic; +class DominatorTree; class AliasAnalysis { protected: @@ -462,6 +463,18 @@ public: virtual ModRefResult getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2); + /// callCapturesBefore - Return information about whether a particular call + /// site modifies or reads the specified memory location. + ModRefResult callCapturesBefore(const Instruction *I, + const AliasAnalysis::Location &MemLoc, + DominatorTree *DT); + + /// callCapturesBefore - A convenience wrapper. + ModRefResult callCapturesBefore(const Instruction *I, const Value *P, + uint64_t Size, DominatorTree *DT) { + return callCapturesBefore(I, Location(P, Size), DT); + } + //===--------------------------------------------------------------------===// /// Higher level methods for querying mod/ref information. /// diff --git a/include/llvm/Analysis/BlockFrequencyImpl.h b/include/llvm/Analysis/BlockFrequencyImpl.h index 6f2ccfb..5168ab7 100644 --- a/include/llvm/Analysis/BlockFrequencyImpl.h +++ b/include/llvm/Analysis/BlockFrequencyImpl.h @@ -217,7 +217,7 @@ class BlockFrequencyImpl { divBlockFreq(BB, BranchProbability(Numerator, EntryFreq)); } - /// doLoop - Propagate block frequency down throught the loop. + /// doLoop - Propagate block frequency down through the loop. void doLoop(BlockT *Head, BlockT *Tail) { DEBUG(dbgs() << "doLoop(" << getBlockName(Head) << ", " << getBlockName(Tail) << ")\n"); diff --git a/include/llvm/Analysis/CodeMetrics.h b/include/llvm/Analysis/CodeMetrics.h index 7116078..03c807c 100644 --- a/include/llvm/Analysis/CodeMetrics.h +++ b/include/llvm/Analysis/CodeMetrics.h @@ -16,6 +16,7 @@ #define LLVM_ANALYSIS_CODEMETRICS_H #include "llvm/ADT/DenseMap.h" +#include "llvm/Support/CallSite.h" namespace llvm { class BasicBlock; @@ -29,10 +30,11 @@ namespace llvm { /// \brief Check whether a call will lower to something small. /// - /// This tests checks whether calls to this function will lower to something + /// This tests checks whether this callsite will lower to something /// significantly cheaper than a traditional call, often a single - /// instruction. - bool callIsSmall(const Function *F); + /// instruction. Note that if isInstructionFree(CS.getInstruction()) would + /// return true, so will this function. + bool callIsSmall(ImmutableCallSite CS); /// \brief Utility to calculate the size and a few similar metrics for a set /// of basic blocks. diff --git a/include/llvm/Analysis/Dominators.h b/include/llvm/Analysis/Dominators.h index 6e8e4246..1289edd 100644 --- a/include/llvm/Analysis/Dominators.h +++ b/include/llvm/Analysis/Dominators.h @@ -152,7 +152,7 @@ EXTERN_TEMPLATE_INSTANTIATION(class DomTreeNodeBase<BasicBlock>); EXTERN_TEMPLATE_INSTANTIATION(class DomTreeNodeBase<MachineBasicBlock>); template<class NodeT> -static raw_ostream &operator<<(raw_ostream &o, +inline raw_ostream &operator<<(raw_ostream &o, const DomTreeNodeBase<NodeT> *Node) { if (Node->getBlock()) WriteAsOperand(o, Node->getBlock(), false); @@ -165,7 +165,7 @@ static raw_ostream &operator<<(raw_ostream &o, } template<class NodeT> -static void PrintDomTree(const DomTreeNodeBase<NodeT> *N, raw_ostream &o, +inline void PrintDomTree(const DomTreeNodeBase<NodeT> *N, raw_ostream &o, unsigned Lev) { o.indent(2*Lev) << "[" << Lev << "] " << N; for (typename DomTreeNodeBase<NodeT>::const_iterator I = N->begin(), @@ -705,6 +705,8 @@ DominatorTreeBase<NodeT>::properlyDominates(const NodeT *A, const NodeT *B) { EXTERN_TEMPLATE_INSTANTIATION(class DominatorTreeBase<BasicBlock>); +class BasicBlockEdge; + //===------------------------------------- /// DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to /// compute a normal dominator tree. @@ -778,6 +780,8 @@ public: bool dominates(const Instruction *Def, const Use &U) const; bool dominates(const Instruction *Def, const Instruction *User) const; bool dominates(const Instruction *Def, const BasicBlock *BB) const; + bool dominates(const BasicBlockEdge &BBE, const Use &U) const; + bool dominates(const BasicBlockEdge &BBE, const BasicBlock *BB) const; bool properlyDominates(const DomTreeNode *A, const DomTreeNode *B) const { return DT->properlyDominates(A, B); diff --git a/include/llvm/Analysis/InlineCost.h b/include/llvm/Analysis/InlineCost.h index 691c2d1..0cba135 100644 --- a/include/llvm/Analysis/InlineCost.h +++ b/include/llvm/Analysis/InlineCost.h @@ -127,10 +127,6 @@ namespace llvm { // adding a replacement API. InlineCost getInlineCost(CallSite CS, Function *Callee, int Threshold); }; - - /// callIsSmall - If a call is likely to lower to a single target instruction, - /// or is otherwise deemed small return true. - bool callIsSmall(const Function *Callee); } #endif diff --git a/include/llvm/Analysis/LoopInfo.h b/include/llvm/Analysis/LoopInfo.h index 91feaaa..eeb482d 100644 --- a/include/llvm/Analysis/LoopInfo.h +++ b/include/llvm/Analysis/LoopInfo.h @@ -46,7 +46,7 @@ namespace llvm { template<typename T> -static void RemoveFromVector(std::vector<T*> &V, T *N) { +inline void RemoveFromVector(std::vector<T*> &V, T *N) { typename std::vector<T*>::iterator I = std::find(V.begin(), V.end(), N); assert(I != V.end() && "N is not in this list!"); V.erase(I); @@ -97,6 +97,9 @@ public: BlockT *getHeader() const { return Blocks.front(); } LoopT *getParentLoop() const { return ParentLoop; } + /// setParentLoop is a raw interface for bypassing addChildLoop. + void setParentLoop(LoopT *L) { ParentLoop = L; } + /// contains - Return true if the specified loop is contained within in /// this loop. /// @@ -122,14 +125,20 @@ public: /// iterator/begin/end - Return the loops contained entirely within this loop. /// const std::vector<LoopT *> &getSubLoops() const { return SubLoops; } + std::vector<LoopT *> &getSubLoopsVector() { return SubLoops; } typedef typename std::vector<LoopT *>::const_iterator iterator; + typedef typename std::vector<LoopT *>::const_reverse_iterator + reverse_iterator; iterator begin() const { return SubLoops.begin(); } iterator end() const { return SubLoops.end(); } + reverse_iterator rbegin() const { return SubLoops.rbegin(); } + reverse_iterator rend() const { return SubLoops.rend(); } bool empty() const { return SubLoops.empty(); } /// getBlocks - Get a list of the basic blocks which make up this loop. /// const std::vector<BlockT*> &getBlocks() const { return Blocks; } + std::vector<BlockT*> &getBlocksVector() { return Blocks; } typedef typename std::vector<BlockT*>::const_iterator block_iterator; block_iterator block_begin() const { return Blocks.begin(); } block_iterator block_end() const { return Blocks.end(); } @@ -181,83 +190,26 @@ public: /// outside of the loop. These are the blocks _inside of the current loop_ /// which branch out. The returned list is always unique. /// - void getExitingBlocks(SmallVectorImpl<BlockT *> &ExitingBlocks) const { - // Sort the blocks vector so that we can use binary search to do quick - // lookups. - SmallVector<BlockT*, 128> LoopBBs(block_begin(), block_end()); - std::sort(LoopBBs.begin(), LoopBBs.end()); - - typedef GraphTraits<BlockT*> BlockTraits; - for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI) - for (typename BlockTraits::ChildIteratorType I = - BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI); - I != E; ++I) - if (!std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I)) { - // Not in current loop? It must be an exit block. - ExitingBlocks.push_back(*BI); - break; - } - } + void getExitingBlocks(SmallVectorImpl<BlockT *> &ExitingBlocks) const; /// getExitingBlock - If getExitingBlocks would return exactly one block, /// return that block. Otherwise return null. - BlockT *getExitingBlock() const { - SmallVector<BlockT*, 8> ExitingBlocks; - getExitingBlocks(ExitingBlocks); - if (ExitingBlocks.size() == 1) - return ExitingBlocks[0]; - return 0; - } + BlockT *getExitingBlock() const; /// getExitBlocks - Return all of the successor blocks of this loop. These /// are the blocks _outside of the current loop_ which are branched to. /// - void getExitBlocks(SmallVectorImpl<BlockT*> &ExitBlocks) const { - // Sort the blocks vector so that we can use binary search to do quick - // lookups. - SmallVector<BlockT*, 128> LoopBBs(block_begin(), block_end()); - std::sort(LoopBBs.begin(), LoopBBs.end()); - - typedef GraphTraits<BlockT*> BlockTraits; - for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI) - for (typename BlockTraits::ChildIteratorType I = - BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI); - I != E; ++I) - if (!std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I)) - // Not in current loop? It must be an exit block. - ExitBlocks.push_back(*I); - } + void getExitBlocks(SmallVectorImpl<BlockT*> &ExitBlocks) const; /// getExitBlock - If getExitBlocks would return exactly one block, /// return that block. Otherwise return null. - BlockT *getExitBlock() const { - SmallVector<BlockT*, 8> ExitBlocks; - getExitBlocks(ExitBlocks); - if (ExitBlocks.size() == 1) - return ExitBlocks[0]; - return 0; - } + BlockT *getExitBlock() const; /// Edge type. - typedef std::pair<BlockT*, BlockT*> Edge; + typedef std::pair<const BlockT*, const BlockT*> Edge; /// getExitEdges - Return all pairs of (_inside_block_,_outside_block_). - template <typename EdgeT> - void getExitEdges(SmallVectorImpl<EdgeT> &ExitEdges) const { - // Sort the blocks vector so that we can use binary search to do quick - // lookups. - SmallVector<BlockT*, 128> LoopBBs(block_begin(), block_end()); - array_pod_sort(LoopBBs.begin(), LoopBBs.end()); - - typedef GraphTraits<BlockT*> BlockTraits; - for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI) - for (typename BlockTraits::ChildIteratorType I = - BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI); - I != E; ++I) - if (!std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I)) - // Not in current loop? It must be an exit block. - ExitEdges.push_back(EdgeT(*BI, *I)); - } + void getExitEdges(SmallVectorImpl<Edge> &ExitEdges) const; /// getLoopPreheader - If there is a preheader for this loop, return it. A /// loop has a preheader if there is only one edge to the header of the loop @@ -266,71 +218,18 @@ public: /// /// This method returns null if there is no preheader for the loop. /// - BlockT *getLoopPreheader() const { - // Keep track of nodes outside the loop branching to the header... - BlockT *Out = getLoopPredecessor(); - if (!Out) return 0; - - // Make sure there is only one exit out of the preheader. - typedef GraphTraits<BlockT*> BlockTraits; - typename BlockTraits::ChildIteratorType SI = BlockTraits::child_begin(Out); - ++SI; - if (SI != BlockTraits::child_end(Out)) - return 0; // Multiple exits from the block, must not be a preheader. - - // The predecessor has exactly one successor, so it is a preheader. - return Out; - } + BlockT *getLoopPreheader() const; /// getLoopPredecessor - If the given loop's header has exactly one unique /// predecessor outside the loop, return it. Otherwise return null. /// This is less strict that the loop "preheader" concept, which requires /// the predecessor to have exactly one successor. /// - BlockT *getLoopPredecessor() const { - // Keep track of nodes outside the loop branching to the header... - BlockT *Out = 0; - - // Loop over the predecessors of the header node... - BlockT *Header = getHeader(); - typedef GraphTraits<BlockT*> BlockTraits; - typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits; - for (typename InvBlockTraits::ChildIteratorType PI = - InvBlockTraits::child_begin(Header), - PE = InvBlockTraits::child_end(Header); PI != PE; ++PI) { - typename InvBlockTraits::NodeType *N = *PI; - if (!contains(N)) { // If the block is not in the loop... - if (Out && Out != N) - return 0; // Multiple predecessors outside the loop - Out = N; - } - } - - // Make sure there is only one exit out of the preheader. - assert(Out && "Header of loop has no predecessors from outside loop?"); - return Out; - } + BlockT *getLoopPredecessor() const; /// getLoopLatch - If there is a single latch block for this loop, return it. /// A latch block is a block that contains a branch back to the header. - BlockT *getLoopLatch() const { - BlockT *Header = getHeader(); - typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits; - typename InvBlockTraits::ChildIteratorType PI = - InvBlockTraits::child_begin(Header); - typename InvBlockTraits::ChildIteratorType PE = - InvBlockTraits::child_end(Header); - BlockT *Latch = 0; - for (; PI != PE; ++PI) { - typename InvBlockTraits::NodeType *N = *PI; - if (contains(N)) { - if (Latch) return 0; - Latch = N; - } - } - - return Latch; - } + BlockT *getLoopLatch() const; //===--------------------------------------------------------------------===// // APIs for updating loop information after changing the CFG @@ -348,17 +247,7 @@ public: /// the OldChild entry in our children list with NewChild, and updates the /// parent pointer of OldChild to be null and the NewChild to be this loop. /// This updates the loop depth of the new child. - void replaceChildLoopWith(LoopT *OldChild, - LoopT *NewChild) { - assert(OldChild->ParentLoop == this && "This loop is already broken!"); - assert(NewChild->ParentLoop == 0 && "NewChild already has a parent!"); - typename std::vector<LoopT *>::iterator I = - std::find(SubLoops.begin(), SubLoops.end(), OldChild); - assert(I != SubLoops.end() && "OldChild not in loop!"); - *I = NewChild; - OldChild->ParentLoop = 0; - NewChild->ParentLoop = static_cast<LoopT *>(this); - } + void replaceChildLoopWith(LoopT *OldChild, LoopT *NewChild); /// addChildLoop - Add the specified loop to be a child of this loop. This /// updates the loop depth of the new child. @@ -411,121 +300,12 @@ public: } /// verifyLoop - Verify loop structure - void verifyLoop() const { -#ifndef NDEBUG - assert(!Blocks.empty() && "Loop header is missing"); - - // Setup for using a depth-first iterator to visit every block in the loop. - SmallVector<BlockT*, 8> ExitBBs; - getExitBlocks(ExitBBs); - llvm::SmallPtrSet<BlockT*, 8> VisitSet; - VisitSet.insert(ExitBBs.begin(), ExitBBs.end()); - df_ext_iterator<BlockT*, llvm::SmallPtrSet<BlockT*, 8> > - BI = df_ext_begin(getHeader(), VisitSet), - BE = df_ext_end(getHeader(), VisitSet); - - // Keep track of the number of BBs visited. - unsigned NumVisited = 0; - - // Sort the blocks vector so that we can use binary search to do quick - // lookups. - SmallVector<BlockT*, 128> LoopBBs(block_begin(), block_end()); - std::sort(LoopBBs.begin(), LoopBBs.end()); - - // Check the individual blocks. - for ( ; BI != BE; ++BI) { - BlockT *BB = *BI; - bool HasInsideLoopSuccs = false; - bool HasInsideLoopPreds = false; - SmallVector<BlockT *, 2> OutsideLoopPreds; - - typedef GraphTraits<BlockT*> BlockTraits; - for (typename BlockTraits::ChildIteratorType SI = - BlockTraits::child_begin(BB), SE = BlockTraits::child_end(BB); - SI != SE; ++SI) - if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), *SI)) { - HasInsideLoopSuccs = true; - break; - } - typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits; - for (typename InvBlockTraits::ChildIteratorType PI = - InvBlockTraits::child_begin(BB), PE = InvBlockTraits::child_end(BB); - PI != PE; ++PI) { - BlockT *N = *PI; - if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), N)) - HasInsideLoopPreds = true; - else - OutsideLoopPreds.push_back(N); - } - - if (BB == getHeader()) { - assert(!OutsideLoopPreds.empty() && "Loop is unreachable!"); - } else if (!OutsideLoopPreds.empty()) { - // A non-header loop shouldn't be reachable from outside the loop, - // though it is permitted if the predecessor is not itself actually - // reachable. - BlockT *EntryBB = BB->getParent()->begin(); - for (df_iterator<BlockT *> NI = df_begin(EntryBB), - NE = df_end(EntryBB); NI != NE; ++NI) - for (unsigned i = 0, e = OutsideLoopPreds.size(); i != e; ++i) - assert(*NI != OutsideLoopPreds[i] && - "Loop has multiple entry points!"); - } - assert(HasInsideLoopPreds && "Loop block has no in-loop predecessors!"); - assert(HasInsideLoopSuccs && "Loop block has no in-loop successors!"); - assert(BB != getHeader()->getParent()->begin() && - "Loop contains function entry block!"); - - NumVisited++; - } - - assert(NumVisited == getNumBlocks() && "Unreachable block in loop"); - - // Check the subloops. - for (iterator I = begin(), E = end(); I != E; ++I) - // Each block in each subloop should be contained within this loop. - for (block_iterator BI = (*I)->block_begin(), BE = (*I)->block_end(); - BI != BE; ++BI) { - assert(std::binary_search(LoopBBs.begin(), LoopBBs.end(), *BI) && - "Loop does not contain all the blocks of a subloop!"); - } - - // Check the parent loop pointer. - if (ParentLoop) { - assert(std::find(ParentLoop->begin(), ParentLoop->end(), this) != - ParentLoop->end() && - "Loop is not a subloop of its parent!"); - } -#endif - } + void verifyLoop() const; /// verifyLoop - Verify loop structure of this loop and all nested loops. - void verifyLoopNest(DenseSet<const LoopT*> *Loops) const { - Loops->insert(static_cast<const LoopT *>(this)); - // Verify this loop. - verifyLoop(); - // Verify the subloops. - for (iterator I = begin(), E = end(); I != E; ++I) - (*I)->verifyLoopNest(Loops); - } + void verifyLoopNest(DenseSet<const LoopT*> *Loops) const; - void print(raw_ostream &OS, unsigned Depth = 0) const { - OS.indent(Depth*2) << "Loop at depth " << getLoopDepth() - << " containing: "; - - for (unsigned i = 0; i < getBlocks().size(); ++i) { - if (i) OS << ","; - BlockT *BB = getBlocks()[i]; - WriteAsOperand(OS, BB, false); - if (BB == getHeader()) OS << "<header>"; - if (BB == getLoopLatch()) OS << "<latch>"; - if (isLoopExiting(BB)) OS << "<exiting>"; - } - OS << "\n"; - - for (iterator I = begin(), E = end(); I != E; ++I) - (*I)->print(OS, Depth+2); - } + void print(raw_ostream &OS, unsigned Depth = 0) const; protected: friend class LoopInfoBase<BlockT, LoopT>; @@ -540,6 +320,11 @@ raw_ostream& operator<<(raw_ostream &OS, const LoopBase<BlockT, LoopT> &Loop) { return OS; } +// Implementation in LoopInfoImpl.h +#ifdef __GNUC__ +__extension__ extern template class LoopBase<BasicBlock, Loop>; +#endif + class Loop : public LoopBase<BasicBlock, Loop> { public: Loop() {} @@ -650,8 +435,12 @@ public: /// function. /// typedef typename std::vector<LoopT *>::const_iterator iterator; + typedef typename std::vector<LoopT *>::const_reverse_iterator + reverse_iterator; iterator begin() const { return TopLevelLoops.begin(); } iterator end() const { return TopLevelLoops.end(); } + reverse_iterator rbegin() const { return TopLevelLoops.rbegin(); } + reverse_iterator rend() const { return TopLevelLoops.rend(); } bool empty() const { return TopLevelLoops.empty(); } /// getLoopFor - Return the inner most loop that BB lives in. If a basic @@ -744,189 +533,19 @@ public: return isNotAlreadyContainedIn(SubLoop->getParentLoop(), ParentLoop); } - void Calculate(DominatorTreeBase<BlockT> &DT) { - BlockT *RootNode = DT.getRootNode()->getBlock(); - - for (df_iterator<BlockT*> NI = df_begin(RootNode), - NE = df_end(RootNode); NI != NE; ++NI) - if (LoopT *L = ConsiderForLoop(*NI, DT)) - TopLevelLoops.push_back(L); - } - - LoopT *ConsiderForLoop(BlockT *BB, DominatorTreeBase<BlockT> &DT) { - if (BBMap.count(BB)) return 0; // Haven't processed this node? - - std::vector<BlockT *> TodoStack; - - // Scan the predecessors of BB, checking to see if BB dominates any of - // them. This identifies backedges which target this node... - typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits; - for (typename InvBlockTraits::ChildIteratorType I = - InvBlockTraits::child_begin(BB), E = InvBlockTraits::child_end(BB); - I != E; ++I) { - typename InvBlockTraits::NodeType *N = *I; - // If BB dominates its predecessor... - if (DT.dominates(BB, N) && DT.isReachableFromEntry(N)) - TodoStack.push_back(N); - } - - if (TodoStack.empty()) return 0; // No backedges to this block... - - // Create a new loop to represent this basic block... - LoopT *L = new LoopT(BB); - BBMap[BB] = L; - - while (!TodoStack.empty()) { // Process all the nodes in the loop - BlockT *X = TodoStack.back(); - TodoStack.pop_back(); - - if (!L->contains(X) && // As of yet unprocessed?? - DT.isReachableFromEntry(X)) { - // Check to see if this block already belongs to a loop. If this occurs - // then we have a case where a loop that is supposed to be a child of - // the current loop was processed before the current loop. When this - // occurs, this child loop gets added to a part of the current loop, - // making it a sibling to the current loop. We have to reparent this - // loop. - if (LoopT *SubLoop = - const_cast<LoopT *>(getLoopFor(X))) - if (SubLoop->getHeader() == X && isNotAlreadyContainedIn(SubLoop, L)){ - // Remove the subloop from its current parent... - assert(SubLoop->ParentLoop && SubLoop->ParentLoop != L); - LoopT *SLP = SubLoop->ParentLoop; // SubLoopParent - typename std::vector<LoopT *>::iterator I = - std::find(SLP->SubLoops.begin(), SLP->SubLoops.end(), SubLoop); - assert(I != SLP->SubLoops.end() &&"SubLoop not a child of parent?"); - SLP->SubLoops.erase(I); // Remove from parent... - - // Add the subloop to THIS loop... - SubLoop->ParentLoop = L; - L->SubLoops.push_back(SubLoop); - } - - // Normal case, add the block to our loop... - L->Blocks.push_back(X); - - typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits; - - // Add all of the predecessors of X to the end of the work stack... - TodoStack.insert(TodoStack.end(), InvBlockTraits::child_begin(X), - InvBlockTraits::child_end(X)); - } - } - - // If there are any loops nested within this loop, create them now! - for (typename std::vector<BlockT*>::iterator I = L->Blocks.begin(), - E = L->Blocks.end(); I != E; ++I) - if (LoopT *NewLoop = ConsiderForLoop(*I, DT)) { - L->SubLoops.push_back(NewLoop); - NewLoop->ParentLoop = L; - } - - // Add the basic blocks that comprise this loop to the BBMap so that this - // loop can be found for them. - // - for (typename std::vector<BlockT*>::iterator I = L->Blocks.begin(), - E = L->Blocks.end(); I != E; ++I) - BBMap.insert(std::make_pair(*I, L)); - - // Now that we have a list of all of the child loops of this loop, check to - // see if any of them should actually be nested inside of each other. We - // can accidentally pull loops our of their parents, so we must make sure to - // organize the loop nests correctly now. - { - std::map<BlockT *, LoopT *> ContainingLoops; - for (unsigned i = 0; i != L->SubLoops.size(); ++i) { - LoopT *Child = L->SubLoops[i]; - assert(Child->getParentLoop() == L && "Not proper child loop?"); - - if (LoopT *ContainingLoop = ContainingLoops[Child->getHeader()]) { - // If there is already a loop which contains this loop, move this loop - // into the containing loop. - MoveSiblingLoopInto(Child, ContainingLoop); - --i; // The loop got removed from the SubLoops list. - } else { - // This is currently considered to be a top-level loop. Check to see - // if any of the contained blocks are loop headers for subloops we - // have already processed. - for (unsigned b = 0, e = Child->Blocks.size(); b != e; ++b) { - LoopT *&BlockLoop = ContainingLoops[Child->Blocks[b]]; - if (BlockLoop == 0) { // Child block not processed yet... - BlockLoop = Child; - } else if (BlockLoop != Child) { - LoopT *SubLoop = BlockLoop; - // Reparent all of the blocks which used to belong to BlockLoops - for (unsigned j = 0, f = SubLoop->Blocks.size(); j != f; ++j) - ContainingLoops[SubLoop->Blocks[j]] = Child; - - // There is already a loop which contains this block, that means - // that we should reparent the loop which the block is currently - // considered to belong to to be a child of this loop. - MoveSiblingLoopInto(SubLoop, Child); - --i; // We just shrunk the SubLoops list. - } - } - } - } - } - - return L; - } - - /// MoveSiblingLoopInto - This method moves the NewChild loop to live inside - /// of the NewParent Loop, instead of being a sibling of it. - void MoveSiblingLoopInto(LoopT *NewChild, - LoopT *NewParent) { - LoopT *OldParent = NewChild->getParentLoop(); - assert(OldParent && OldParent == NewParent->getParentLoop() && - NewChild != NewParent && "Not sibling loops!"); - - // Remove NewChild from being a child of OldParent - typename std::vector<LoopT *>::iterator I = - std::find(OldParent->SubLoops.begin(), OldParent->SubLoops.end(), - NewChild); - assert(I != OldParent->SubLoops.end() && "Parent fields incorrect??"); - OldParent->SubLoops.erase(I); // Remove from parent's subloops list - NewChild->ParentLoop = 0; - - InsertLoopInto(NewChild, NewParent); - } - - /// InsertLoopInto - This inserts loop L into the specified parent loop. If - /// the parent loop contains a loop which should contain L, the loop gets - /// inserted into L instead. - void InsertLoopInto(LoopT *L, LoopT *Parent) { - BlockT *LHeader = L->getHeader(); - assert(Parent->contains(LHeader) && - "This loop should not be inserted here!"); - - // Check to see if it belongs in a child loop... - for (unsigned i = 0, e = static_cast<unsigned>(Parent->SubLoops.size()); - i != e; ++i) - if (Parent->SubLoops[i]->contains(LHeader)) { - InsertLoopInto(L, Parent->SubLoops[i]); - return; - } - - // If not, insert it here! - Parent->SubLoops.push_back(L); - L->ParentLoop = Parent; - } + /// Create the loop forest using a stable algorithm. + void Analyze(DominatorTreeBase<BlockT> &DomTree); // Debugging - void print(raw_ostream &OS) const { - for (unsigned i = 0; i < TopLevelLoops.size(); ++i) - TopLevelLoops[i]->print(OS); - #if 0 - for (DenseMap<BasicBlock*, LoopT*>::const_iterator I = BBMap.begin(), - E = BBMap.end(); I != E; ++I) - OS << "BB '" << I->first->getName() << "' level = " - << I->second->getLoopDepth() << "\n"; - #endif - } + void print(raw_ostream &OS) const; }; +// Implementation in LoopInfoImpl.h +#ifdef __GNUC__ +__extension__ extern template class LoopInfoBase<BasicBlock, Loop>; +#endif + class LoopInfo : public FunctionPass { LoopInfoBase<BasicBlock, Loop> LI; friend class LoopBase<BasicBlock, Loop>; @@ -946,8 +565,11 @@ public: /// function. /// typedef LoopInfoBase<BasicBlock, Loop>::iterator iterator; + typedef LoopInfoBase<BasicBlock, Loop>::reverse_iterator reverse_iterator; inline iterator begin() const { return LI.begin(); } inline iterator end() const { return LI.end(); } + inline reverse_iterator rbegin() const { return LI.rbegin(); } + inline reverse_iterator rend() const { return LI.rend(); } bool empty() const { return LI.empty(); } /// getLoopFor - Return the inner most loop that BB lives in. If a basic @@ -1074,27 +696,6 @@ template <> struct GraphTraits<Loop*> { } }; -template<class BlockT, class LoopT> -void -LoopBase<BlockT, LoopT>::addBasicBlockToLoop(BlockT *NewBB, - LoopInfoBase<BlockT, LoopT> &LIB) { - assert((Blocks.empty() || LIB[getHeader()] == this) && - "Incorrect LI specified for this loop!"); - assert(NewBB && "Cannot add a null basic block to the loop!"); - assert(LIB[NewBB] == 0 && "BasicBlock already in the loop!"); - - LoopT *L = static_cast<LoopT *>(this); - - // Add the loop mapping to the LoopInfo object... - LIB.BBMap[NewBB] = L; - - // Add the basic block to this loop and all parent loops... - while (L) { - L->Blocks.push_back(NewBB); - L = L->getParentLoop(); - } -} - } // End llvm namespace #endif diff --git a/include/llvm/Analysis/LoopInfoImpl.h b/include/llvm/Analysis/LoopInfoImpl.h new file mode 100644 index 0000000..c07fbf7 --- /dev/null +++ b/include/llvm/Analysis/LoopInfoImpl.h @@ -0,0 +1,570 @@ +//===- llvm/Analysis/LoopInfoImpl.h - Natural Loop Calculator ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This is the generic implementation of LoopInfo used for both Loops and +// MachineLoops. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LOOP_INFO_IMPL_H +#define LLVM_ANALYSIS_LOOP_INFO_IMPL_H + +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/ADT/PostOrderIterator.h" + +namespace llvm { + +//===----------------------------------------------------------------------===// +// APIs for simple analysis of the loop. See header notes. + +/// getExitingBlocks - Return all blocks inside the loop that have successors +/// outside of the loop. These are the blocks _inside of the current loop_ +/// which branch out. The returned list is always unique. +/// +template<class BlockT, class LoopT> +void LoopBase<BlockT, LoopT>:: +getExitingBlocks(SmallVectorImpl<BlockT *> &ExitingBlocks) const { + // Sort the blocks vector so that we can use binary search to do quick + // lookups. + SmallVector<BlockT*, 128> LoopBBs(block_begin(), block_end()); + std::sort(LoopBBs.begin(), LoopBBs.end()); + + typedef GraphTraits<BlockT*> BlockTraits; + for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI) + for (typename BlockTraits::ChildIteratorType I = + BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI); + I != E; ++I) + if (!std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I)) { + // Not in current loop? It must be an exit block. + ExitingBlocks.push_back(*BI); + break; + } +} + +/// getExitingBlock - If getExitingBlocks would return exactly one block, +/// return that block. Otherwise return null. +template<class BlockT, class LoopT> +BlockT *LoopBase<BlockT, LoopT>::getExitingBlock() const { + SmallVector<BlockT*, 8> ExitingBlocks; + getExitingBlocks(ExitingBlocks); + if (ExitingBlocks.size() == 1) + return ExitingBlocks[0]; + return 0; +} + +/// getExitBlocks - Return all of the successor blocks of this loop. These +/// are the blocks _outside of the current loop_ which are branched to. +/// +template<class BlockT, class LoopT> +void LoopBase<BlockT, LoopT>:: +getExitBlocks(SmallVectorImpl<BlockT*> &ExitBlocks) const { + // Sort the blocks vector so that we can use binary search to do quick + // lookups. + SmallVector<BlockT*, 128> LoopBBs(block_begin(), block_end()); + std::sort(LoopBBs.begin(), LoopBBs.end()); + + typedef GraphTraits<BlockT*> BlockTraits; + for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI) + for (typename BlockTraits::ChildIteratorType I = + BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI); + I != E; ++I) + if (!std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I)) + // Not in current loop? It must be an exit block. + ExitBlocks.push_back(*I); +} + +/// getExitBlock - If getExitBlocks would return exactly one block, +/// return that block. Otherwise return null. +template<class BlockT, class LoopT> +BlockT *LoopBase<BlockT, LoopT>::getExitBlock() const { + SmallVector<BlockT*, 8> ExitBlocks; + getExitBlocks(ExitBlocks); + if (ExitBlocks.size() == 1) + return ExitBlocks[0]; + return 0; +} + +/// getExitEdges - Return all pairs of (_inside_block_,_outside_block_). +template<class BlockT, class LoopT> +void LoopBase<BlockT, LoopT>:: +getExitEdges(SmallVectorImpl<Edge> &ExitEdges) const { + // Sort the blocks vector so that we can use binary search to do quick + // lookups. + SmallVector<BlockT*, 128> LoopBBs(block_begin(), block_end()); + array_pod_sort(LoopBBs.begin(), LoopBBs.end()); + + typedef GraphTraits<BlockT*> BlockTraits; + for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI) + for (typename BlockTraits::ChildIteratorType I = + BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI); + I != E; ++I) + if (!std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I)) + // Not in current loop? It must be an exit block. + ExitEdges.push_back(Edge(*BI, *I)); +} + +/// getLoopPreheader - If there is a preheader for this loop, return it. A +/// loop has a preheader if there is only one edge to the header of the loop +/// from outside of the loop. If this is the case, the block branching to the +/// header of the loop is the preheader node. +/// +/// This method returns null if there is no preheader for the loop. +/// +template<class BlockT, class LoopT> +BlockT *LoopBase<BlockT, LoopT>::getLoopPreheader() const { + // Keep track of nodes outside the loop branching to the header... + BlockT *Out = getLoopPredecessor(); + if (!Out) return 0; + + // Make sure there is only one exit out of the preheader. + typedef GraphTraits<BlockT*> BlockTraits; + typename BlockTraits::ChildIteratorType SI = BlockTraits::child_begin(Out); + ++SI; + if (SI != BlockTraits::child_end(Out)) + return 0; // Multiple exits from the block, must not be a preheader. + + // The predecessor has exactly one successor, so it is a preheader. + return Out; +} + +/// getLoopPredecessor - If the given loop's header has exactly one unique +/// predecessor outside the loop, return it. Otherwise return null. +/// This is less strict that the loop "preheader" concept, which requires +/// the predecessor to have exactly one successor. +/// +template<class BlockT, class LoopT> +BlockT *LoopBase<BlockT, LoopT>::getLoopPredecessor() const { + // Keep track of nodes outside the loop branching to the header... + BlockT *Out = 0; + + // Loop over the predecessors of the header node... + BlockT *Header = getHeader(); + typedef GraphTraits<BlockT*> BlockTraits; + typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits; + for (typename InvBlockTraits::ChildIteratorType PI = + InvBlockTraits::child_begin(Header), + PE = InvBlockTraits::child_end(Header); PI != PE; ++PI) { + typename InvBlockTraits::NodeType *N = *PI; + if (!contains(N)) { // If the block is not in the loop... + if (Out && Out != N) + return 0; // Multiple predecessors outside the loop + Out = N; + } + } + + // Make sure there is only one exit out of the preheader. + assert(Out && "Header of loop has no predecessors from outside loop?"); + return Out; +} + +/// getLoopLatch - If there is a single latch block for this loop, return it. +/// A latch block is a block that contains a branch back to the header. +template<class BlockT, class LoopT> +BlockT *LoopBase<BlockT, LoopT>::getLoopLatch() const { + BlockT *Header = getHeader(); + typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits; + typename InvBlockTraits::ChildIteratorType PI = + InvBlockTraits::child_begin(Header); + typename InvBlockTraits::ChildIteratorType PE = + InvBlockTraits::child_end(Header); + BlockT *Latch = 0; + for (; PI != PE; ++PI) { + typename InvBlockTraits::NodeType *N = *PI; + if (contains(N)) { + if (Latch) return 0; + Latch = N; + } + } + + return Latch; +} + +//===----------------------------------------------------------------------===// +// APIs for updating loop information after changing the CFG +// + +/// addBasicBlockToLoop - This method is used by other analyses to update loop +/// information. NewBB is set to be a new member of the current loop. +/// Because of this, it is added as a member of all parent loops, and is added +/// to the specified LoopInfo object as being in the current basic block. It +/// is not valid to replace the loop header with this method. +/// +template<class BlockT, class LoopT> +void LoopBase<BlockT, LoopT>:: +addBasicBlockToLoop(BlockT *NewBB, LoopInfoBase<BlockT, LoopT> &LIB) { + assert((Blocks.empty() || LIB[getHeader()] == this) && + "Incorrect LI specified for this loop!"); + assert(NewBB && "Cannot add a null basic block to the loop!"); + assert(LIB[NewBB] == 0 && "BasicBlock already in the loop!"); + + LoopT *L = static_cast<LoopT *>(this); + + // Add the loop mapping to the LoopInfo object... + LIB.BBMap[NewBB] = L; + + // Add the basic block to this loop and all parent loops... + while (L) { + L->Blocks.push_back(NewBB); + L = L->getParentLoop(); + } +} + +/// replaceChildLoopWith - This is used when splitting loops up. It replaces +/// the OldChild entry in our children list with NewChild, and updates the +/// parent pointer of OldChild to be null and the NewChild to be this loop. +/// This updates the loop depth of the new child. +template<class BlockT, class LoopT> +void LoopBase<BlockT, LoopT>:: +replaceChildLoopWith(LoopT *OldChild, LoopT *NewChild) { + assert(OldChild->ParentLoop == this && "This loop is already broken!"); + assert(NewChild->ParentLoop == 0 && "NewChild already has a parent!"); + typename std::vector<LoopT *>::iterator I = + std::find(SubLoops.begin(), SubLoops.end(), OldChild); + assert(I != SubLoops.end() && "OldChild not in loop!"); + *I = NewChild; + OldChild->ParentLoop = 0; + NewChild->ParentLoop = static_cast<LoopT *>(this); +} + +/// verifyLoop - Verify loop structure +template<class BlockT, class LoopT> +void LoopBase<BlockT, LoopT>::verifyLoop() const { +#ifndef NDEBUG + assert(!Blocks.empty() && "Loop header is missing"); + + // Setup for using a depth-first iterator to visit every block in the loop. + SmallVector<BlockT*, 8> ExitBBs; + getExitBlocks(ExitBBs); + llvm::SmallPtrSet<BlockT*, 8> VisitSet; + VisitSet.insert(ExitBBs.begin(), ExitBBs.end()); + df_ext_iterator<BlockT*, llvm::SmallPtrSet<BlockT*, 8> > + BI = df_ext_begin(getHeader(), VisitSet), + BE = df_ext_end(getHeader(), VisitSet); + + // Keep track of the number of BBs visited. + unsigned NumVisited = 0; + + // Sort the blocks vector so that we can use binary search to do quick + // lookups. + SmallVector<BlockT*, 128> LoopBBs(block_begin(), block_end()); + std::sort(LoopBBs.begin(), LoopBBs.end()); + + // Check the individual blocks. + for ( ; BI != BE; ++BI) { + BlockT *BB = *BI; + bool HasInsideLoopSuccs = false; + bool HasInsideLoopPreds = false; + SmallVector<BlockT *, 2> OutsideLoopPreds; + + typedef GraphTraits<BlockT*> BlockTraits; + for (typename BlockTraits::ChildIteratorType SI = + BlockTraits::child_begin(BB), SE = BlockTraits::child_end(BB); + SI != SE; ++SI) + if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), *SI)) { + HasInsideLoopSuccs = true; + break; + } + typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits; + for (typename InvBlockTraits::ChildIteratorType PI = + InvBlockTraits::child_begin(BB), PE = InvBlockTraits::child_end(BB); + PI != PE; ++PI) { + BlockT *N = *PI; + if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), N)) + HasInsideLoopPreds = true; + else + OutsideLoopPreds.push_back(N); + } + + if (BB == getHeader()) { + assert(!OutsideLoopPreds.empty() && "Loop is unreachable!"); + } else if (!OutsideLoopPreds.empty()) { + // A non-header loop shouldn't be reachable from outside the loop, + // though it is permitted if the predecessor is not itself actually + // reachable. + BlockT *EntryBB = BB->getParent()->begin(); + for (df_iterator<BlockT *> NI = df_begin(EntryBB), + NE = df_end(EntryBB); NI != NE; ++NI) + for (unsigned i = 0, e = OutsideLoopPreds.size(); i != e; ++i) + assert(*NI != OutsideLoopPreds[i] && + "Loop has multiple entry points!"); + } + assert(HasInsideLoopPreds && "Loop block has no in-loop predecessors!"); + assert(HasInsideLoopSuccs && "Loop block has no in-loop successors!"); + assert(BB != getHeader()->getParent()->begin() && + "Loop contains function entry block!"); + + NumVisited++; + } + + assert(NumVisited == getNumBlocks() && "Unreachable block in loop"); + + // Check the subloops. + for (iterator I = begin(), E = end(); I != E; ++I) + // Each block in each subloop should be contained within this loop. + for (block_iterator BI = (*I)->block_begin(), BE = (*I)->block_end(); + BI != BE; ++BI) { + assert(std::binary_search(LoopBBs.begin(), LoopBBs.end(), *BI) && + "Loop does not contain all the blocks of a subloop!"); + } + + // Check the parent loop pointer. + if (ParentLoop) { + assert(std::find(ParentLoop->begin(), ParentLoop->end(), this) != + ParentLoop->end() && + "Loop is not a subloop of its parent!"); + } +#endif +} + +/// verifyLoop - Verify loop structure of this loop and all nested loops. +template<class BlockT, class LoopT> +void LoopBase<BlockT, LoopT>::verifyLoopNest( + DenseSet<const LoopT*> *Loops) const { + Loops->insert(static_cast<const LoopT *>(this)); + // Verify this loop. + verifyLoop(); + // Verify the subloops. + for (iterator I = begin(), E = end(); I != E; ++I) + (*I)->verifyLoopNest(Loops); +} + +template<class BlockT, class LoopT> +void LoopBase<BlockT, LoopT>::print(raw_ostream &OS, unsigned Depth) const { + OS.indent(Depth*2) << "Loop at depth " << getLoopDepth() + << " containing: "; + + for (unsigned i = 0; i < getBlocks().size(); ++i) { + if (i) OS << ","; + BlockT *BB = getBlocks()[i]; + WriteAsOperand(OS, BB, false); + if (BB == getHeader()) OS << "<header>"; + if (BB == getLoopLatch()) OS << "<latch>"; + if (isLoopExiting(BB)) OS << "<exiting>"; + } + OS << "\n"; + + for (iterator I = begin(), E = end(); I != E; ++I) + (*I)->print(OS, Depth+2); +} + +//===----------------------------------------------------------------------===// +/// Stable LoopInfo Analysis - Build a loop tree using stable iterators so the +/// result does / not depend on use list (block predecessor) order. +/// + +/// Discover a subloop with the specified backedges such that: All blocks within +/// this loop are mapped to this loop or a subloop. And all subloops within this +/// loop have their parent loop set to this loop or a subloop. +template<class BlockT, class LoopT> +static void discoverAndMapSubloop(LoopT *L, ArrayRef<BlockT*> Backedges, + LoopInfoBase<BlockT, LoopT> *LI, + DominatorTreeBase<BlockT> &DomTree) { + typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits; + + unsigned NumBlocks = 0; + unsigned NumSubloops = 0; + + // Perform a backward CFG traversal using a worklist. + std::vector<BlockT *> ReverseCFGWorklist(Backedges.begin(), Backedges.end()); + while (!ReverseCFGWorklist.empty()) { + BlockT *PredBB = ReverseCFGWorklist.back(); + ReverseCFGWorklist.pop_back(); + + LoopT *Subloop = LI->getLoopFor(PredBB); + if (!Subloop) { + if (!DomTree.isReachableFromEntry(PredBB)) + continue; + + // This is an undiscovered block. Map it to the current loop. + LI->changeLoopFor(PredBB, L); + ++NumBlocks; + if (PredBB == L->getHeader()) + continue; + // Push all block predecessors on the worklist. + ReverseCFGWorklist.insert(ReverseCFGWorklist.end(), + InvBlockTraits::child_begin(PredBB), + InvBlockTraits::child_end(PredBB)); + } + else { + // This is a discovered block. Find its outermost discovered loop. + while (LoopT *Parent = Subloop->getParentLoop()) + Subloop = Parent; + + // If it is already discovered to be a subloop of this loop, continue. + if (Subloop == L) + continue; + + // Discover a subloop of this loop. + Subloop->setParentLoop(L); + ++NumSubloops; + NumBlocks += Subloop->getBlocks().capacity(); + PredBB = Subloop->getHeader(); + // Continue traversal along predecessors that are not loop-back edges from + // within this subloop tree itself. Note that a predecessor may directly + // reach another subloop that is not yet discovered to be a subloop of + // this loop, which we must traverse. + for (typename InvBlockTraits::ChildIteratorType PI = + InvBlockTraits::child_begin(PredBB), + PE = InvBlockTraits::child_end(PredBB); PI != PE; ++PI) { + if (LI->getLoopFor(*PI) != Subloop) + ReverseCFGWorklist.push_back(*PI); + } + } + } + L->getSubLoopsVector().reserve(NumSubloops); + L->getBlocksVector().reserve(NumBlocks); +} + +namespace { +/// Populate all loop data in a stable order during a single forward DFS. +template<class BlockT, class LoopT> +class PopulateLoopsDFS { + typedef GraphTraits<BlockT*> BlockTraits; + typedef typename BlockTraits::ChildIteratorType SuccIterTy; + + LoopInfoBase<BlockT, LoopT> *LI; + DenseSet<const BlockT *> VisitedBlocks; + std::vector<std::pair<BlockT*, SuccIterTy> > DFSStack; + +public: + PopulateLoopsDFS(LoopInfoBase<BlockT, LoopT> *li): + LI(li) {} + + void traverse(BlockT *EntryBlock); + +protected: + void insertIntoLoop(BlockT *Block); + + BlockT *dfsSource() { return DFSStack.back().first; } + SuccIterTy &dfsSucc() { return DFSStack.back().second; } + SuccIterTy dfsSuccEnd() { return BlockTraits::child_end(dfsSource()); } + + void pushBlock(BlockT *Block) { + DFSStack.push_back(std::make_pair(Block, BlockTraits::child_begin(Block))); + } +}; +} // anonymous + +/// Top-level driver for the forward DFS within the loop. +template<class BlockT, class LoopT> +void PopulateLoopsDFS<BlockT, LoopT>::traverse(BlockT *EntryBlock) { + pushBlock(EntryBlock); + VisitedBlocks.insert(EntryBlock); + while (!DFSStack.empty()) { + // Traverse the leftmost path as far as possible. + while (dfsSucc() != dfsSuccEnd()) { + BlockT *BB = *dfsSucc(); + ++dfsSucc(); + if (!VisitedBlocks.insert(BB).second) + continue; + + // Push the next DFS successor onto the stack. + pushBlock(BB); + } + // Visit the top of the stack in postorder and backtrack. + insertIntoLoop(dfsSource()); + DFSStack.pop_back(); + } +} + +/// Add a single Block to its ancestor loops in PostOrder. If the block is a +/// subloop header, add the subloop to its parent in PostOrder, then reverse the +/// Block and Subloop vectors of the now complete subloop to achieve RPO. +template<class BlockT, class LoopT> +void PopulateLoopsDFS<BlockT, LoopT>::insertIntoLoop(BlockT *Block) { + LoopT *Subloop = LI->getLoopFor(Block); + if (Subloop && Block == Subloop->getHeader()) { + // We reach this point once per subloop after processing all the blocks in + // the subloop. + if (Subloop->getParentLoop()) + Subloop->getParentLoop()->getSubLoopsVector().push_back(Subloop); + else + LI->addTopLevelLoop(Subloop); + + // For convenience, Blocks and Subloops are inserted in postorder. Reverse + // the lists, except for the loop header, which is always at the beginning. + std::reverse(Subloop->getBlocksVector().begin()+1, + Subloop->getBlocksVector().end()); + std::reverse(Subloop->getSubLoopsVector().begin(), + Subloop->getSubLoopsVector().end()); + + Subloop = Subloop->getParentLoop(); + } + for (; Subloop; Subloop = Subloop->getParentLoop()) + Subloop->getBlocksVector().push_back(Block); +} + +/// Analyze LoopInfo discovers loops during a postorder DominatorTree traversal +/// interleaved with backward CFG traversals within each subloop +/// (discoverAndMapSubloop). The backward traversal skips inner subloops, so +/// this part of the algorithm is linear in the number of CFG edges. Subloop and +/// Block vectors are then populated during a single forward CFG traversal +/// (PopulateLoopDFS). +/// +/// During the two CFG traversals each block is seen three times: +/// 1) Discovered and mapped by a reverse CFG traversal. +/// 2) Visited during a forward DFS CFG traversal. +/// 3) Reverse-inserted in the loop in postorder following forward DFS. +/// +/// The Block vectors are inclusive, so step 3 requires loop-depth number of +/// insertions per block. +template<class BlockT, class LoopT> +void LoopInfoBase<BlockT, LoopT>:: +Analyze(DominatorTreeBase<BlockT> &DomTree) { + + // Postorder traversal of the dominator tree. + DomTreeNodeBase<BlockT>* DomRoot = DomTree.getRootNode(); + for (po_iterator<DomTreeNodeBase<BlockT>*> DomIter = po_begin(DomRoot), + DomEnd = po_end(DomRoot); DomIter != DomEnd; ++DomIter) { + + BlockT *Header = DomIter->getBlock(); + SmallVector<BlockT *, 4> Backedges; + + // Check each predecessor of the potential loop header. + typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits; + for (typename InvBlockTraits::ChildIteratorType PI = + InvBlockTraits::child_begin(Header), + PE = InvBlockTraits::child_end(Header); PI != PE; ++PI) { + + BlockT *Backedge = *PI; + + // If Header dominates predBB, this is a new loop. Collect the backedges. + if (DomTree.dominates(Header, Backedge) + && DomTree.isReachableFromEntry(Backedge)) { + Backedges.push_back(Backedge); + } + } + // Perform a backward CFG traversal to discover and map blocks in this loop. + if (!Backedges.empty()) { + LoopT *L = new LoopT(Header); + discoverAndMapSubloop(L, ArrayRef<BlockT*>(Backedges), this, DomTree); + } + } + // Perform a single forward CFG traversal to populate block and subloop + // vectors for all loops. + PopulateLoopsDFS<BlockT, LoopT> DFS(this); + DFS.traverse(DomRoot->getBlock()); +} + +// Debugging +template<class BlockT, class LoopT> +void LoopInfoBase<BlockT, LoopT>::print(raw_ostream &OS) const { + for (unsigned i = 0; i < TopLevelLoops.size(); ++i) + TopLevelLoops[i]->print(OS); +#if 0 + for (DenseMap<BasicBlock*, LoopT*>::const_iterator I = BBMap.begin(), + E = BBMap.end(); I != E; ++I) + OS << "BB '" << I->first->getName() << "' level = " + << I->second->getLoopDepth() << "\n"; +#endif +} + +} // End llvm namespace + +#endif diff --git a/include/llvm/Analysis/LoopIterator.h b/include/llvm/Analysis/LoopIterator.h index 269ac80..68f25f7 100644 --- a/include/llvm/Analysis/LoopIterator.h +++ b/include/llvm/Analysis/LoopIterator.h @@ -109,6 +109,16 @@ public: } }; +/// Specialize po_iterator_storage to record postorder numbers. +template<> class po_iterator_storage<LoopBlocksTraversal, true> { + LoopBlocksTraversal &LBT; +public: + po_iterator_storage(LoopBlocksTraversal &lbs) : LBT(lbs) {} + // These functions are defined below. + bool insertEdge(BasicBlock *From, BasicBlock *To); + void finishPostorder(BasicBlock *BB); +}; + /// Traverse the blocks in a loop using a depth-first search. class LoopBlocksTraversal { public: @@ -155,31 +165,17 @@ public: DFS.PostBlocks.push_back(BB); DFS.PostNumbers[BB] = DFS.PostBlocks.size(); } - - //===---------------------------------------------------------------------- - // Implement part of the std::set interface for the purpose of driving the - // generic po_iterator. - - /// Return true if the block is outside the loop or has already been visited. - /// Sorry if this is counterintuitive. - bool count(BasicBlock *BB) const { - return !DFS.L->contains(LI->getLoopFor(BB)) || DFS.PostNumbers.count(BB); - } - - /// If this block is contained in the loop and has not been visited, return - /// true and assign a preorder number. This is a proxy for visitPreorder - /// called by POIterator. - bool insert(BasicBlock *BB) { - return visitPreorder(BB); - } }; -/// Specialize DFSetTraits to record postorder numbers. -template<> struct DFSetTraits<LoopBlocksTraversal> { - static void finishPostorder(BasicBlock *BB, LoopBlocksTraversal& LBT) { - LBT.finishPostorder(BB); - } -}; +inline bool po_iterator_storage<LoopBlocksTraversal, true>:: +insertEdge(BasicBlock *From, BasicBlock *To) { + return LBT.visitPreorder(To); +} + +inline void po_iterator_storage<LoopBlocksTraversal, true>:: +finishPostorder(BasicBlock *BB) { + LBT.finishPostorder(BB); +} } // End namespace llvm diff --git a/include/llvm/Analysis/MemoryBuiltins.h b/include/llvm/Analysis/MemoryBuiltins.h index 865d236..e674e74 100644 --- a/include/llvm/Analysis/MemoryBuiltins.h +++ b/include/llvm/Analysis/MemoryBuiltins.h @@ -15,6 +15,15 @@ #ifndef LLVM_ANALYSIS_MEMORYBUILTINS_H #define LLVM_ANALYSIS_MEMORYBUILTINS_H +#include "llvm/IRBuilder.h" +#include "llvm/Operator.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/InstVisitor.h" +#include "llvm/Support/TargetFolder.h" +#include "llvm/Support/ValueHandle.h" + namespace llvm { class CallInst; class PointerType; @@ -22,24 +31,44 @@ class TargetData; class Type; class Value; + +/// \brief Tests if a value is a call or invoke to a library function that +/// allocates or reallocates memory (either malloc, calloc, realloc, or strdup +/// like). +bool isAllocationFn(const Value *V, bool LookThroughBitCast = false); + +/// \brief Tests if a value is a call or invoke to a function that returns a +/// NoAlias pointer (including malloc/calloc/realloc/strdup-like functions). +bool isNoAliasFn(const Value *V, bool LookThroughBitCast = false); + +/// \brief Tests if a value is a call or invoke to a library function that +/// allocates uninitialized memory (such as malloc). +bool isMallocLikeFn(const Value *V, bool LookThroughBitCast = false); + +/// \brief Tests if a value is a call or invoke to a library function that +/// allocates zero-filled memory (such as calloc). +bool isCallocLikeFn(const Value *V, bool LookThroughBitCast = false); + +/// \brief Tests if a value is a call or invoke to a library function that +/// allocates memory (either malloc, calloc, or strdup like). +bool isAllocLikeFn(const Value *V, bool LookThroughBitCast = false); + +/// \brief Tests if a value is a call or invoke to a library function that +/// reallocates memory (such as realloc). +bool isReallocLikeFn(const Value *V, bool LookThroughBitCast = false); + + //===----------------------------------------------------------------------===// // malloc Call Utility Functions. // -/// isMalloc - Returns true if the value is either a malloc call or a bitcast of -/// the result of a malloc call -bool isMalloc(const Value *I); - /// extractMallocCall - Returns the corresponding CallInst if the instruction /// is a malloc call. Since CallInst::CreateMalloc() only creates calls, we /// ignore InvokeInst here. const CallInst *extractMallocCall(const Value *I); -CallInst *extractMallocCall(Value *I); - -/// extractMallocCallFromBitCast - Returns the corresponding CallInst if the -/// instruction is a bitcast of the result of a malloc call. -const CallInst *extractMallocCallFromBitCast(const Value *I); -CallInst *extractMallocCallFromBitCast(Value *I); +static inline CallInst *extractMallocCall(Value *I) { + return const_cast<CallInst*>(extractMallocCall((const Value*)I)); +} /// isArrayMalloc - Returns the corresponding CallInst if the instruction /// is a call to malloc whose array size can be determined and the array size @@ -67,7 +96,20 @@ Type *getMallocAllocatedType(const CallInst *CI); /// determined. Value *getMallocArraySize(CallInst *CI, const TargetData *TD, bool LookThroughSExt = false); - + + +//===----------------------------------------------------------------------===// +// calloc Call Utility Functions. +// + +/// extractCallocCall - Returns the corresponding CallInst if the instruction +/// is a calloc call. +const CallInst *extractCallocCall(const Value *I); +static inline CallInst *extractCallocCall(Value *I) { + return const_cast<CallInst*>(extractCallocCall((const Value*)I)); +} + + //===----------------------------------------------------------------------===// // free Call Utility Functions. // @@ -79,6 +121,131 @@ static inline CallInst *isFreeCall(Value *I) { return const_cast<CallInst*>(isFreeCall((const Value*)I)); } + +//===----------------------------------------------------------------------===// +// Utility functions to compute size of objects. +// + +/// \brief Compute the size of the object pointed by Ptr. Returns true and the +/// object size in Size if successful, and false otherwise. +/// If RoundToAlign is true, then Size is rounded up to the aligment of allocas, +/// byval arguments, and global variables. +bool getObjectSize(const Value *Ptr, uint64_t &Size, const TargetData *TD, + bool RoundToAlign = false); + + + +typedef std::pair<APInt, APInt> SizeOffsetType; + +/// \brief Evaluate the size and offset of an object ponted by a Value* +/// statically. Fails if size or offset are not known at compile time. +class ObjectSizeOffsetVisitor + : public InstVisitor<ObjectSizeOffsetVisitor, SizeOffsetType> { + + const TargetData *TD; + bool RoundToAlign; + unsigned IntTyBits; + APInt Zero; + + APInt align(APInt Size, uint64_t Align); + + SizeOffsetType unknown() { + return std::make_pair(APInt(), APInt()); + } + +public: + ObjectSizeOffsetVisitor(const TargetData *TD, LLVMContext &Context, + bool RoundToAlign = false); + + SizeOffsetType compute(Value *V); + + bool knownSize(SizeOffsetType &SizeOffset) { + return SizeOffset.first.getBitWidth() > 1; + } + + bool knownOffset(SizeOffsetType &SizeOffset) { + return SizeOffset.second.getBitWidth() > 1; + } + + bool bothKnown(SizeOffsetType &SizeOffset) { + return knownSize(SizeOffset) && knownOffset(SizeOffset); + } + + SizeOffsetType visitAllocaInst(AllocaInst &I); + SizeOffsetType visitArgument(Argument &A); + SizeOffsetType visitCallSite(CallSite CS); + SizeOffsetType visitConstantPointerNull(ConstantPointerNull&); + SizeOffsetType visitExtractElementInst(ExtractElementInst &I); + SizeOffsetType visitExtractValueInst(ExtractValueInst &I); + SizeOffsetType visitGEPOperator(GEPOperator &GEP); + SizeOffsetType visitGlobalVariable(GlobalVariable &GV); + SizeOffsetType visitIntToPtrInst(IntToPtrInst&); + SizeOffsetType visitLoadInst(LoadInst &I); + SizeOffsetType visitPHINode(PHINode&); + SizeOffsetType visitSelectInst(SelectInst &I); + SizeOffsetType visitUndefValue(UndefValue&); + SizeOffsetType visitInstruction(Instruction &I); +}; + +typedef std::pair<Value*, Value*> SizeOffsetEvalType; + + +/// \brief Evaluate the size and offset of an object ponted by a Value*. +/// May create code to compute the result at run-time. +class ObjectSizeOffsetEvaluator + : public InstVisitor<ObjectSizeOffsetEvaluator, SizeOffsetEvalType> { + + typedef IRBuilder<true, TargetFolder> BuilderTy; + typedef std::pair<WeakVH, WeakVH> WeakEvalType; + typedef DenseMap<const Value*, WeakEvalType> CacheMapTy; + typedef SmallPtrSet<const Value*, 8> PtrSetTy; + + const TargetData *TD; + LLVMContext &Context; + BuilderTy Builder; + ObjectSizeOffsetVisitor Visitor; + IntegerType *IntTy; + Value *Zero; + CacheMapTy CacheMap; + PtrSetTy SeenVals; + + SizeOffsetEvalType unknown() { + return std::make_pair((Value*)0, (Value*)0); + } + SizeOffsetEvalType compute_(Value *V); + +public: + ObjectSizeOffsetEvaluator(const TargetData *TD, LLVMContext &Context); + SizeOffsetEvalType compute(Value *V); + + bool knownSize(SizeOffsetEvalType SizeOffset) { + return SizeOffset.first; + } + + bool knownOffset(SizeOffsetEvalType SizeOffset) { + return SizeOffset.second; + } + + bool anyKnown(SizeOffsetEvalType SizeOffset) { + return knownSize(SizeOffset) || knownOffset(SizeOffset); + } + + bool bothKnown(SizeOffsetEvalType SizeOffset) { + return knownSize(SizeOffset) && knownOffset(SizeOffset); + } + + SizeOffsetEvalType visitAllocaInst(AllocaInst &I); + SizeOffsetEvalType visitCallSite(CallSite CS); + SizeOffsetEvalType visitExtractElementInst(ExtractElementInst &I); + SizeOffsetEvalType visitExtractValueInst(ExtractValueInst &I); + SizeOffsetEvalType visitGEPOperator(GEPOperator &GEP); + SizeOffsetEvalType visitIntToPtrInst(IntToPtrInst&); + SizeOffsetEvalType visitLoadInst(LoadInst &I); + SizeOffsetEvalType visitPHINode(PHINode &PHI); + SizeOffsetEvalType visitSelectInst(SelectInst &I); + SizeOffsetEvalType visitInstruction(Instruction &I); +}; + } // End llvm namespace #endif diff --git a/include/llvm/Analysis/MemoryDependenceAnalysis.h b/include/llvm/Analysis/MemoryDependenceAnalysis.h index 68ce364..7e049d6 100644 --- a/include/llvm/Analysis/MemoryDependenceAnalysis.h +++ b/include/llvm/Analysis/MemoryDependenceAnalysis.h @@ -124,11 +124,11 @@ namespace llvm { } /// isClobber - Return true if this MemDepResult represents a query that is - /// a instruction clobber dependency. + /// an instruction clobber dependency. bool isClobber() const { return Value.getInt() == Clobber; } /// isDef - Return true if this MemDepResult represents a query that is - /// a instruction definition dependency. + /// an instruction definition dependency. bool isDef() const { return Value.getInt() == Def; } /// isNonLocal - Return true if this MemDepResult represents a query that @@ -431,9 +431,6 @@ namespace llvm { void RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair P); - AliasAnalysis::ModRefResult - getModRefInfo(const Instruction *Inst, const AliasAnalysis::Location &Loc); - /// verifyRemoved - Verify that the specified instruction does not occur /// in our internal data structures. void verifyRemoved(Instruction *Inst) const; diff --git a/include/llvm/Analysis/ProfileInfoLoader.h b/include/llvm/Analysis/ProfileInfoLoader.h index 9e0c393..dcf3b38 100644 --- a/include/llvm/Analysis/ProfileInfoLoader.h +++ b/include/llvm/Analysis/ProfileInfoLoader.h @@ -28,19 +28,16 @@ class BasicBlock; class ProfileInfoLoader { const std::string &Filename; - Module &M; std::vector<std::string> CommandLines; std::vector<unsigned> FunctionCounts; std::vector<unsigned> BlockCounts; std::vector<unsigned> EdgeCounts; std::vector<unsigned> OptimalEdgeCounts; std::vector<unsigned> BBTrace; - bool Warned; public: // ProfileInfoLoader ctor - Read the specified profiling data file, exiting // the program if the file is invalid or broken. - ProfileInfoLoader(const char *ToolName, const std::string &Filename, - Module &M); + ProfileInfoLoader(const char *ToolName, const std::string &Filename); static const unsigned Uncounted; diff --git a/include/llvm/Analysis/RegionInfo.h b/include/llvm/Analysis/RegionInfo.h index b098eea..188d11c 100644 --- a/include/llvm/Analysis/RegionInfo.h +++ b/include/llvm/Analysis/RegionInfo.h @@ -473,25 +473,85 @@ public: const_iterator end() const { return children.end(); } //@} - /// @name BasicBlock Iterators + /// @name BasicBlock Node Iterators /// /// These iterators iterate over all BasicBlock RegionNodes that are - /// contained in this Region. The iterator also iterates over BasicBlocks - /// that are elements of a subregion of this Region. It is therefore called a - /// flat iterator. + /// contained in this Region. The iterator also iterates over BasicBlock + /// RegionNodes that are elements of a subregion of this Region. It is + /// therefore called a flat iterator. //@{ typedef df_iterator<RegionNode*, SmallPtrSet<RegionNode*, 8>, false, - GraphTraits<FlatIt<RegionNode*> > > block_iterator; + GraphTraits<FlatIt<RegionNode*> > > block_node_iterator; typedef df_iterator<const RegionNode*, SmallPtrSet<const RegionNode*, 8>, false, GraphTraits<FlatIt<const RegionNode*> > > - const_block_iterator; + const_block_node_iterator; + + block_node_iterator block_node_begin(); + block_node_iterator block_node_end(); + + const_block_node_iterator block_node_begin() const; + const_block_node_iterator block_node_end() const; + //@} + + /// @name BasicBlock Iterators + /// + /// These iterators iterate over all BasicBlocks that are contained in this + /// Region. The iterator also iterates over BasicBlocks that are elements of + /// a subregion of this Region. It is therefore called a flat iterator. + //@{ + template <bool IsConst> + class block_iterator_wrapper + : public df_iterator<typename conditional<IsConst, + const BasicBlock, + BasicBlock>::type*> { + typedef df_iterator<typename conditional<IsConst, + const BasicBlock, + BasicBlock>::type*> + super; + public: + typedef block_iterator_wrapper<IsConst> Self; + typedef typename super::pointer pointer; + + // Construct the begin iterator. + block_iterator_wrapper(pointer Entry, pointer Exit) : super(df_begin(Entry)) + { + // Mark the exit of the region as visited, so that the children of the + // exit and the exit itself, i.e. the block outside the region will never + // be visited. + super::Visited.insert(Exit); + } + + // Construct the end iterator. + block_iterator_wrapper() : super(df_end<pointer>((BasicBlock *)0)) {} + + /*implicit*/ block_iterator_wrapper(super I) : super(I) {} + + // FIXME: Even a const_iterator returns a non-const BasicBlock pointer. + // This was introduced for backwards compatibility, but should + // be removed as soon as all users are fixed. + BasicBlock *operator*() const { + return const_cast<BasicBlock*>(super::operator*()); + } + }; + + typedef block_iterator_wrapper<false> block_iterator; + typedef block_iterator_wrapper<true> const_block_iterator; + + block_iterator block_begin() { + return block_iterator(getEntry(), getExit()); + } - block_iterator block_begin(); - block_iterator block_end(); + block_iterator block_end() { + return block_iterator(); + } - const_block_iterator block_begin() const; - const_block_iterator block_end() const; + const_block_iterator block_begin() const { + return const_block_iterator(getEntry(), getExit()); + } + const_block_iterator block_end() const { + return const_block_iterator(); + } //@} /// @name Element Iterators diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h index 72408f7..c213ade 100644 --- a/include/llvm/Analysis/ScalarEvolution.h +++ b/include/llvm/Analysis/ScalarEvolution.h @@ -30,7 +30,7 @@ #include "llvm/Support/Allocator.h" #include "llvm/Support/ConstantRange.h" #include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" #include <map> namespace llvm { @@ -250,6 +250,9 @@ namespace llvm { /// ValueExprMapType ValueExprMap; + /// Mark predicate values currently being processed by isImpliedCond. + DenseSet<Value*> PendingLoopPredicates; + /// ExitLimit - Information about the number of loop iterations for /// which a loop exit's branch condition evaluates to the not-taken path. /// This is a temporary pair of exact and max expressions that are @@ -834,7 +837,8 @@ namespace llvm { /// bool SimplifyICmpOperands(ICmpInst::Predicate &Pred, const SCEV *&LHS, - const SCEV *&RHS); + const SCEV *&RHS, + unsigned Depth = 0); /// getLoopDisposition - Return the "disposition" of the given SCEV with /// respect to the given loop. diff --git a/include/llvm/Analysis/ScalarEvolutionExpander.h b/include/llvm/Analysis/ScalarEvolutionExpander.h index c22fc3a..3f8f149 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpander.h +++ b/include/llvm/Analysis/ScalarEvolutionExpander.h @@ -14,9 +14,9 @@ #ifndef LLVM_ANALYSIS_SCALAREVOLUTION_EXPANDER_H #define LLVM_ANALYSIS_SCALAREVOLUTION_EXPANDER_H +#include "llvm/IRBuilder.h" #include "llvm/Analysis/ScalarEvolutionExpressions.h" #include "llvm/Analysis/ScalarEvolutionNormalization.h" -#include "llvm/Support/IRBuilder.h" #include "llvm/Support/TargetFolder.h" #include "llvm/Support/ValueHandle.h" #include <set> @@ -24,6 +24,10 @@ namespace llvm { class TargetLowering; + /// Return true if the given expression is safe to expand in the sense that + /// all materialized values are safe to speculate. + bool isSafeToExpand(const SCEV *S); + /// SCEVExpander - This class uses information about analyze scalars to /// rewrite expressions in canonical form. /// diff --git a/include/llvm/Analysis/ScalarEvolutionExpressions.h b/include/llvm/Analysis/ScalarEvolutionExpressions.h index 47b3710..ded1297 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpressions.h +++ b/include/llvm/Analysis/ScalarEvolutionExpressions.h @@ -15,6 +15,7 @@ #define LLVM_ANALYSIS_SCALAREVOLUTION_EXPRESSIONS_H #include "llvm/Analysis/ScalarEvolution.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/ErrorHandling.h" namespace llvm { @@ -493,6 +494,74 @@ namespace llvm { llvm_unreachable("Invalid use of SCEVCouldNotCompute!"); } }; + + /// Visit all nodes in the expression tree using worklist traversal. + /// + /// Visitor implements: + /// // return true to follow this node. + /// bool follow(const SCEV *S); + /// // return true to terminate the search. + /// bool isDone(); + template<typename SV> + class SCEVTraversal { + SV &Visitor; + SmallVector<const SCEV *, 8> Worklist; + SmallPtrSet<const SCEV *, 8> Visited; + + void push(const SCEV *S) { + if (Visited.insert(S) && Visitor.follow(S)) + Worklist.push_back(S); + } + public: + SCEVTraversal(SV& V): Visitor(V) {} + + void visitAll(const SCEV *Root) { + push(Root); + while (!Worklist.empty() && !Visitor.isDone()) { + const SCEV *S = Worklist.pop_back_val(); + + switch (S->getSCEVType()) { + case scConstant: + case scUnknown: + break; + case scTruncate: + case scZeroExtend: + case scSignExtend: + push(cast<SCEVCastExpr>(S)->getOperand()); + break; + case scAddExpr: + case scMulExpr: + case scSMaxExpr: + case scUMaxExpr: + case scAddRecExpr: { + const SCEVNAryExpr *NAry = cast<SCEVNAryExpr>(S); + for (SCEVNAryExpr::op_iterator I = NAry->op_begin(), + E = NAry->op_end(); I != E; ++I) { + push(*I); + } + break; + } + case scUDivExpr: { + const SCEVUDivExpr *UDiv = cast<SCEVUDivExpr>(S); + push(UDiv->getLHS()); + push(UDiv->getRHS()); + break; + } + case scCouldNotCompute: + llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!"); + default: + llvm_unreachable("Unknown SCEV kind!"); + } + } + } + }; + + /// Use SCEVTraversal to visit all nodes in the givien expression tree. + template<typename SV> + void visitAll(const SCEV *Root, SV& Visitor) { + SCEVTraversal<SV> T(Visitor); + T.visitAll(Root); + } } #endif diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h index f2f9db4..e8d45f6 100644 --- a/include/llvm/Analysis/ValueTracking.h +++ b/include/llvm/Analysis/ValueTracking.h @@ -151,6 +151,14 @@ namespace llvm { return GetUnderlyingObject(const_cast<Value *>(V), TD, MaxLookup); } + /// GetUnderlyingObjects - This method is similar to GetUnderlyingObject + /// except that it can look through phi and select instructions and return + /// multiple objects. + void GetUnderlyingObjects(Value *V, + SmallVectorImpl<Value *> &Objects, + const TargetData *TD = 0, + unsigned MaxLookup = 6); + /// onlyUsedByLifetimeMarkers - Return true if the only users of this pointer /// are lifetime markers. bool onlyUsedByLifetimeMarkers(const Value *V); diff --git a/include/llvm/Attributes.h b/include/llvm/Attributes.h index 0099f17..223aa00 100644 --- a/include/llvm/Attributes.h +++ b/include/llvm/Attributes.h @@ -16,6 +16,7 @@ #define LLVM_ATTRIBUTES_H #include "llvm/Support/MathExtras.h" +#include "llvm/ADT/ArrayRef.h" #include <cassert> #include <string> @@ -45,14 +46,9 @@ class Attributes { Attributes() : Bits(0) { } explicit Attributes(uint64_t Val) : Bits(Val) { } /*implicit*/ Attributes(Attribute::AttrConst Val) : Bits(Val.v) { } - Attributes(const Attributes &Attrs) : Bits(Attrs.Bits) { } // This is a "safe bool() operator". operator const void *() const { return Bits ? this : 0; } bool isEmptyOrSingleton() const { return (Bits & (Bits - 1)) == 0; } - Attributes &operator = (const Attributes &Attrs) { - Bits = Attrs.Bits; - return *this; - } bool operator == (const Attributes &Attrs) const { return Bits == Attrs.Bits; } @@ -138,6 +134,9 @@ DECLARE_LLVM_ATTRIBUTE(NonLazyBind,1U<<31) ///< Function is called early and/or /// often, so lazy binding isn't /// worthwhile. DECLARE_LLVM_ATTRIBUTE(AddressSafety,1ULL<<32) ///< Address safety checking is on. +DECLARE_LLVM_ATTRIBUTE(IANSDialect,1ULL<<33) ///< Inline asm non-standard dialect. + /// When not set, ATT dialect assumed. + /// When set implies the Intel dialect. #undef DECLARE_LLVM_ATTRIBUTE @@ -163,14 +162,16 @@ const AttrConst FunctionOnly = {NoReturn_i | NoUnwind_i | ReadNone_i | ReadOnly_i | NoInline_i | AlwaysInline_i | OptimizeForSize_i | StackProtect_i | StackProtectReq_i | NoRedZone_i | NoImplicitFloat_i | Naked_i | InlineHint_i | StackAlignment_i | - UWTable_i | NonLazyBind_i | ReturnsTwice_i | AddressSafety_i}; + UWTable_i | NonLazyBind_i | ReturnsTwice_i | AddressSafety_i | + IANSDialect_i}; /// @brief Parameter attributes that do not apply to vararg call arguments. const AttrConst VarArgsIncompatible = {StructRet_i}; /// @brief Attributes that are mutually incompatible. -const AttrConst MutuallyIncompatible[4] = { - {ByVal_i | InReg_i | Nest_i | StructRet_i}, +const AttrConst MutuallyIncompatible[5] = { + {ByVal_i | Nest_i | StructRet_i}, + {ByVal_i | Nest_i | InReg_i }, {ZExt_i | SExt_i}, {ReadNone_i | ReadOnly_i}, {NoInline_i | AlwaysInline_i} @@ -222,6 +223,50 @@ inline unsigned getStackAlignmentFromAttrs(Attributes A) { return 1U << ((StackAlign.Raw() >> 26) - 1); } +/// This returns an integer containing an encoding of all the +/// LLVM attributes found in the given attribute bitset. Any +/// change to this encoding is a breaking change to bitcode +/// compatibility. +inline uint64_t encodeLLVMAttributesForBitcode(Attributes Attrs) { + // FIXME: It doesn't make sense to store the alignment information as an + // expanded out value, we should store it as a log2 value. However, we can't + // just change that here without breaking bitcode compatibility. If this ever + // becomes a problem in practice, we should introduce new tag numbers in the + // bitcode file and have those tags use a more efficiently encoded alignment + // field. + + // Store the alignment in the bitcode as a 16-bit raw value instead of a + // 5-bit log2 encoded value. Shift the bits above the alignment up by + // 11 bits. + + uint64_t EncodedAttrs = Attrs.Raw() & 0xffff; + if (Attrs & Attribute::Alignment) + EncodedAttrs |= (1ull << 16) << + (((Attrs & Attribute::Alignment).Raw()-1) >> 16); + EncodedAttrs |= (Attrs.Raw() & (0xfffull << 21)) << 11; + + return EncodedAttrs; +} + +/// This returns an attribute bitset containing the LLVM attributes +/// that have been decoded from the given integer. This function +/// must stay in sync with 'encodeLLVMAttributesForBitcode'. +inline Attributes decodeLLVMAttributesForBitcode(uint64_t EncodedAttrs) { + // The alignment is stored as a 16-bit raw value from bits 31--16. + // We shift the bits above 31 down by 11 bits. + + unsigned Alignment = (EncodedAttrs & (0xffffull << 16)) >> 16; + assert((!Alignment || isPowerOf2_32(Alignment)) && + "Alignment must be a power of two."); + + Attributes Attrs(EncodedAttrs & 0xffff); + if (Alignment) + Attrs |= Attribute::constructAlignmentFromInt(Alignment); + Attrs |= Attributes((EncodedAttrs & (0xfffull << 32)) >> 11); + + return Attrs; +} + /// The set of Attributes set in Attributes is converted to a /// string of equivalent mnemonics. This is, presumably, for writing out @@ -268,16 +313,8 @@ public: // Attribute List Construction and Mutation //===--------------------------------------------------------------------===// - /// get - Return a Attributes list with the specified parameter in it. - static AttrListPtr get(const AttributeWithIndex *Attr, unsigned NumAttrs); - - /// get - Return a Attribute list with the parameters specified by the - /// consecutive random access iterator range. - template <typename Iter> - static AttrListPtr get(const Iter &I, const Iter &E) { - if (I == E) return AttrListPtr(); // Empty list. - return get(&*I, static_cast<unsigned>(E-I)); - } + /// get - Return a Attributes list with the specified parameters in it. + static AttrListPtr get(ArrayRef<AttributeWithIndex> Attrs); /// addAttr - Add the specified attribute at the specified index to this /// attribute list. Since attribute lists are immutable, this diff --git a/include/llvm/Bitcode/Archive.h b/include/llvm/Bitcode/Archive.h index 86c44c7..3c75e58 100644 --- a/include/llvm/Bitcode/Archive.h +++ b/include/llvm/Bitcode/Archive.h @@ -47,14 +47,13 @@ class ArchiveMember : public ilist_node<ArchiveMember> { /// characteristics of the member. The various "is" methods below provide /// access to the flags. The flags are not user settable. enum Flags { - CompressedFlag = 1, ///< Member is a normal compressed file - SVR4SymbolTableFlag = 2, ///< Member is a SVR4 symbol table - BSD4SymbolTableFlag = 4, ///< Member is a BSD4 symbol table - LLVMSymbolTableFlag = 8, ///< Member is an LLVM symbol table - BitcodeFlag = 16, ///< Member is bitcode - HasPathFlag = 64, ///< Member has a full or partial path - HasLongFilenameFlag = 128, ///< Member uses the long filename syntax - StringTableFlag = 256 ///< Member is an ar(1) format string table + SVR4SymbolTableFlag = 1, ///< Member is a SVR4 symbol table + BSD4SymbolTableFlag = 2, ///< Member is a BSD4 symbol table + LLVMSymbolTableFlag = 4, ///< Member is an LLVM symbol table + BitcodeFlag = 8, ///< Member is bitcode + HasPathFlag = 16, ///< Member has a full or partial path + HasLongFilenameFlag = 32, ///< Member uses the long filename syntax + StringTableFlag = 64 ///< Member is an ar(1) format string table }; /// @} @@ -109,11 +108,6 @@ class ArchiveMember : public ilist_node<ArchiveMember> { /// @brief Get the data content of the archive member const char* getData() const { return data; } - /// This method determines if the member is a regular compressed file. - /// @returns true iff the archive member is a compressed regular file. - /// @brief Determine if the member is a compressed regular file. - bool isCompressed() const { return flags&CompressedFlag; } - /// @returns true iff the member is a SVR4 (non-LLVM) symbol table /// @brief Determine if this member is a SVR4 symbol table. bool isSVR4SymbolTable() const { return flags&SVR4SymbolTableFlag; } @@ -427,7 +421,6 @@ class Archive { bool writeToDisk( bool CreateSymbolTable=false, ///< Create Symbol table bool TruncateNames=false, ///< Truncate the filename to 15 chars - bool Compress=false, ///< Compress files std::string* ErrMessage=0 ///< If non-null, where error msg is set ); @@ -494,7 +487,6 @@ class Archive { std::ofstream& ARFile, ///< The file to write member onto bool CreateSymbolTable, ///< Should symbol table be created? bool TruncateNames, ///< Should names be truncated to 11 chars? - bool ShouldCompress, ///< Should the member be compressed? std::string* ErrMessage ///< If non-null, place were error msg is set ); diff --git a/include/llvm/Bitcode/ReaderWriter.h b/include/llvm/Bitcode/ReaderWriter.h index cc2b473..dd96b04 100644 --- a/include/llvm/Bitcode/ReaderWriter.h +++ b/include/llvm/Bitcode/ReaderWriter.h @@ -71,8 +71,8 @@ namespace llvm { /// isBitcodeWrapper - Return true if the given bytes are the magic bytes /// for an LLVM IR bitcode wrapper. /// - static inline bool isBitcodeWrapper(const unsigned char *BufPtr, - const unsigned char *BufEnd) { + inline bool isBitcodeWrapper(const unsigned char *BufPtr, + const unsigned char *BufEnd) { // See if you can find the hidden message in the magic bytes :-). // (Hint: it's a little-endian encoding.) return BufPtr != BufEnd && @@ -85,8 +85,8 @@ namespace llvm { /// isRawBitcode - Return true if the given bytes are the magic bytes for /// raw LLVM IR bitcode (without a wrapper). /// - static inline bool isRawBitcode(const unsigned char *BufPtr, - const unsigned char *BufEnd) { + inline bool isRawBitcode(const unsigned char *BufPtr, + const unsigned char *BufEnd) { // These bytes sort of have a hidden message, but it's not in // little-endian this time, and it's a little redundant. return BufPtr != BufEnd && @@ -99,8 +99,8 @@ namespace llvm { /// isBitcode - Return true if the given bytes are the magic bytes for /// LLVM IR bitcode, either with or without a wrapper. /// - static bool inline isBitcode(const unsigned char *BufPtr, - const unsigned char *BufEnd) { + inline bool isBitcode(const unsigned char *BufPtr, + const unsigned char *BufEnd) { return isBitcodeWrapper(BufPtr, BufEnd) || isRawBitcode(BufPtr, BufEnd); } @@ -121,9 +121,9 @@ namespace llvm { /// BC file. /// If 'VerifyBufferSize' is true, check that the buffer is large enough to /// contain the whole bitcode file. - static inline bool SkipBitcodeWrapperHeader(const unsigned char *&BufPtr, - const unsigned char *&BufEnd, - bool VerifyBufferSize) { + inline bool SkipBitcodeWrapperHeader(const unsigned char *&BufPtr, + const unsigned char *&BufEnd, + bool VerifyBufferSize) { enum { KnownHeaderSize = 4*4, // Size of header we read. OffsetField = 2*4, // Offset in bytes to Offset field. diff --git a/include/llvm/CMakeLists.txt b/include/llvm/CMakeLists.txt index de3ff86..f8cb425 100644 --- a/include/llvm/CMakeLists.txt +++ b/include/llvm/CMakeLists.txt @@ -6,8 +6,6 @@ add_custom_target(intrinsics_gen ALL DEPENDS ${llvm_builded_incs_dir}/Intrinsics.gen) set_target_properties(intrinsics_gen PROPERTIES FOLDER "Tablegenning") -set(LLVM_COMMON_DEPENDS ${LLVM_COMMON_DEPENDS} intrinsics_gen PARENT_SCOPE) - if( MSVC_IDE OR XCODE ) # Creates a dummy target containing all headers for the benefit of # Visual Studio users. diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index 56a87f1..170a528 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -354,6 +354,13 @@ namespace llvm { void EmitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset, unsigned Size) const; + /// EmitLabelReference - Emit something like ".long Label" + /// where the size in bytes of the directive is specified by Size and Label + /// specifies the label. + void EmitLabelReference(const MCSymbol *Label, unsigned Size) const { + EmitLabelPlusOffset(Label, 0, Size); + } + //===------------------------------------------------------------------===// // Dwarf Emission Helper Routines //===------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/DFAPacketizer.h b/include/llvm/CodeGen/DFAPacketizer.h index ee1ed07..2d2db78 100644 --- a/include/llvm/CodeGen/DFAPacketizer.h +++ b/include/llvm/CodeGen/DFAPacketizer.h @@ -28,6 +28,7 @@ #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/ADT/DenseMap.h" +#include <map> namespace llvm { @@ -36,7 +37,7 @@ class MachineInstr; class MachineLoopInfo; class MachineDominatorTree; class InstrItineraryData; -class ScheduleDAGInstrs; +class DefaultVLIWScheduler; class SUnit; class DFAPacketizer { @@ -77,6 +78,8 @@ public: // reserveResources - Reserve the resources occupied by a machine // instruction and change the current state to reflect that change. void reserveResources(llvm::MachineInstr *MI); + + const InstrItineraryData *getInstrItins() const { return InstrItins; } }; // VLIWPacketizerList - Implements a simple VLIW packetizer using DFA. The @@ -87,20 +90,21 @@ public: // and machine resource is marked as taken. If any dependency is found, a target // API call is made to prune the dependence. class VLIWPacketizerList { +protected: const TargetMachine &TM; const MachineFunction &MF; const TargetInstrInfo *TII; - // Encapsulate data types not exposed to the target interface. - ScheduleDAGInstrs *SchedulerImpl; + // The VLIW Scheduler. + DefaultVLIWScheduler *VLIWScheduler; -protected: // Vector of instructions assigned to the current packet. std::vector<MachineInstr*> CurrentPacketMIs; // DFA resource tracker. DFAPacketizer *ResourceTracker; - // Scheduling units. - std::vector<SUnit> SUnits; + + // Generate MI -> SU map. + std::map<MachineInstr*, SUnit*> MIToSUnit; public: VLIWPacketizerList( @@ -118,17 +122,32 @@ public: DFAPacketizer *getResourceTracker() {return ResourceTracker;} // addToPacket - Add MI to the current packet. - void addToPacket(MachineInstr *MI); + virtual MachineBasicBlock::iterator addToPacket(MachineInstr *MI) { + MachineBasicBlock::iterator MII = MI; + CurrentPacketMIs.push_back(MI); + ResourceTracker->reserveResources(MI); + return MII; + } // endPacket - End the current packet. - void endPacket(MachineBasicBlock *MBB, MachineInstr *I); + void endPacket(MachineBasicBlock *MBB, MachineInstr *MI); + + // initPacketizerState - perform initialization before packetizing + // an instruction. This function is supposed to be overrided by + // the target dependent packetizer. + virtual void initPacketizerState(void) { return; } // ignorePseudoInstruction - Ignore bundling of pseudo instructions. - bool ignorePseudoInstruction(MachineInstr *I, MachineBasicBlock *MBB); + virtual bool ignorePseudoInstruction(MachineInstr *I, + MachineBasicBlock *MBB) { + return false; + } - // isSoloInstruction - return true if instruction I must end previous - // packet. - bool isSoloInstruction(MachineInstr *I); + // isSoloInstruction - return true if instruction MI can not be packetized + // with any other instruction, which means that MI itself is a packet. + virtual bool isSoloInstruction(MachineInstr *MI) { + return true; + } // isLegalToPacketizeTogether - Is it legal to packetize SUI and SUJ // together. @@ -141,6 +160,7 @@ public: virtual bool isLegalToPruneDependencies(SUnit *SUI, SUnit *SUJ) { return false; } + }; } diff --git a/include/llvm/CodeGen/EdgeBundles.h b/include/llvm/CodeGen/EdgeBundles.h index a1d29b1..e8a4a2d 100644 --- a/include/llvm/CodeGen/EdgeBundles.h +++ b/include/llvm/CodeGen/EdgeBundles.h @@ -46,7 +46,7 @@ public: unsigned getNumBundles() const { return EC.getNumClasses(); } /// getBlocks - Return an array of blocks that are connected to Bundle. - ArrayRef<unsigned> getBlocks(unsigned Bundle) { return Blocks[Bundle]; } + ArrayRef<unsigned> getBlocks(unsigned Bundle) const { return Blocks[Bundle]; } /// getMachineFunction - Return the last machine function computed. const MachineFunction *getMachineFunction() const { return MF; } diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h index e57c8b1..7cb9695 100644 --- a/include/llvm/CodeGen/FastISel.h +++ b/include/llvm/CodeGen/FastISel.h @@ -34,6 +34,7 @@ class MachineFrameInfo; class MachineRegisterInfo; class TargetData; class TargetInstrInfo; +class TargetLibraryInfo; class TargetLowering; class TargetMachine; class TargetRegisterClass; @@ -57,6 +58,7 @@ protected: const TargetInstrInfo &TII; const TargetLowering &TLI; const TargetRegisterInfo &TRI; + const TargetLibraryInfo *LibInfo; /// The position of the last instruction for materializing constants /// for use in the current block. It resets to EmitStartPt when it @@ -144,7 +146,8 @@ public: virtual ~FastISel(); protected: - explicit FastISel(FunctionLoweringInfo &funcInfo); + explicit FastISel(FunctionLoweringInfo &funcInfo, + const TargetLibraryInfo *libInfo); /// TargetSelectInstruction - This method is called by target-independent /// code when the normal FastISel process fails to select an instruction. @@ -299,6 +302,15 @@ protected: unsigned Op1, bool Op1IsKill, uint64_t Imm); + /// FastEmitInst_rrii - Emit a MachineInstr with two register operands, + /// two immediates operands, and a result register in the given register + /// class. + unsigned FastEmitInst_rrii(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, bool Op0IsKill, + unsigned Op1, bool Op1IsKill, + uint64_t Imm1, uint64_t Imm2); + /// FastEmitInst_i - Emit a MachineInstr with a single immediate /// operand, and a result register in the given register class. unsigned FastEmitInst_i(unsigned MachineInstrOpcode, diff --git a/include/llvm/CodeGen/GCMetadata.h b/include/llvm/CodeGen/GCMetadata.h index 45469ed..20e33f7 100644 --- a/include/llvm/CodeGen/GCMetadata.h +++ b/include/llvm/CodeGen/GCMetadata.h @@ -48,18 +48,18 @@ namespace llvm { /// PointKind - The type of a collector-safe point. /// enum PointKind { - Loop, //< Instr is a loop (backwards branch). - Return, //< Instr is a return instruction. - PreCall, //< Instr is a call instruction. - PostCall //< Instr is the return address of a call. + Loop, ///< Instr is a loop (backwards branch). + Return, ///< Instr is a return instruction. + PreCall, ///< Instr is a call instruction. + PostCall ///< Instr is the return address of a call. }; } /// GCPoint - Metadata for a collector-safe point in machine code. /// struct GCPoint { - GC::PointKind Kind; //< The kind of the safe point. - MCSymbol *Label; //< A label. + GC::PointKind Kind; ///< The kind of the safe point. + MCSymbol *Label; ///< A label. DebugLoc Loc; GCPoint(GC::PointKind K, MCSymbol *L, DebugLoc DL) @@ -69,9 +69,10 @@ namespace llvm { /// GCRoot - Metadata for a pointer to an object managed by the garbage /// collector. struct GCRoot { - int Num; //< Usually a frame index. - int StackOffset; //< Offset from the stack pointer. - const Constant *Metadata;//< Metadata straight from the call to llvm.gcroot. + int Num; ///< Usually a frame index. + int StackOffset; ///< Offset from the stack pointer. + const Constant *Metadata; ///< Metadata straight from the call + ///< to llvm.gcroot. GCRoot(int N, const Constant *MD) : Num(N), StackOffset(-1), Metadata(MD) {} }; diff --git a/include/llvm/CodeGen/GCStrategy.h b/include/llvm/CodeGen/GCStrategy.h index 1cbd36a..dfc26d7 100644 --- a/include/llvm/CodeGen/GCStrategy.h +++ b/include/llvm/CodeGen/GCStrategy.h @@ -65,14 +65,14 @@ namespace llvm { list_type Functions; protected: - unsigned NeededSafePoints; //< Bitmask of required safe points. - bool CustomReadBarriers; //< Default is to insert loads. - bool CustomWriteBarriers; //< Default is to insert stores. - bool CustomRoots; //< Default is to pass through to backend. - bool CustomSafePoints; //< Default is to use NeededSafePoints - // to find safe points. - bool InitRoots; //< If set, roots are nulled during lowering. - bool UsesMetadata; //< If set, backend must emit metadata tables. + unsigned NeededSafePoints; ///< Bitmask of required safe points. + bool CustomReadBarriers; ///< Default is to insert loads. + bool CustomWriteBarriers; ///< Default is to insert stores. + bool CustomRoots; ///< Default is to pass through to backend. + bool CustomSafePoints; ///< Default is to use NeededSafePoints + ///< to find safe points. + bool InitRoots; ///< If set, roots are nulled during lowering. + bool UsesMetadata; ///< If set, backend must emit metadata tables. public: GCStrategy(); diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h index ab8ab5d..f387bd5 100644 --- a/include/llvm/CodeGen/ISDOpcodes.h +++ b/include/llvm/CodeGen/ISDOpcodes.h @@ -37,87 +37,87 @@ namespace ISD { /// and getMachineOpcode() member functions of SDNode. /// enum NodeType { - // DELETED_NODE - This is an illegal value that is used to catch - // errors. This opcode is not a legal opcode for any node. + /// DELETED_NODE - This is an illegal value that is used to catch + /// errors. This opcode is not a legal opcode for any node. DELETED_NODE, - // EntryToken - This is the marker used to indicate the start of the region. + /// EntryToken - This is the marker used to indicate the start of a region. EntryToken, - // TokenFactor - This node takes multiple tokens as input and produces a - // single token result. This is used to represent the fact that the operand - // operators are independent of each other. + /// TokenFactor - This node takes multiple tokens as input and produces a + /// single token result. This is used to represent the fact that the operand + /// operators are independent of each other. TokenFactor, - // AssertSext, AssertZext - These nodes record if a register contains a - // value that has already been zero or sign extended from a narrower type. - // These nodes take two operands. The first is the node that has already - // been extended, and the second is a value type node indicating the width - // of the extension + /// AssertSext, AssertZext - These nodes record if a register contains a + /// value that has already been zero or sign extended from a narrower type. + /// These nodes take two operands. The first is the node that has already + /// been extended, and the second is a value type node indicating the width + /// of the extension AssertSext, AssertZext, - // Various leaf nodes. + /// Various leaf nodes. BasicBlock, VALUETYPE, CONDCODE, Register, RegisterMask, Constant, ConstantFP, GlobalAddress, GlobalTLSAddress, FrameIndex, JumpTable, ConstantPool, ExternalSymbol, BlockAddress, - // The address of the GOT + /// The address of the GOT GLOBAL_OFFSET_TABLE, - // FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and - // llvm.returnaddress on the DAG. These nodes take one operand, the index - // of the frame or return address to return. An index of zero corresponds - // to the current function's frame or return address, an index of one to the - // parent's frame or return address, and so on. + /// FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and + /// llvm.returnaddress on the DAG. These nodes take one operand, the index + /// of the frame or return address to return. An index of zero corresponds + /// to the current function's frame or return address, an index of one to + /// the parent's frame or return address, and so on. FRAMEADDR, RETURNADDR, - // FRAME_TO_ARGS_OFFSET - This node represents offset from frame pointer to - // first (possible) on-stack argument. This is needed for correct stack - // adjustment during unwind. + /// FRAME_TO_ARGS_OFFSET - This node represents offset from frame pointer to + /// first (possible) on-stack argument. This is needed for correct stack + /// adjustment during unwind. FRAME_TO_ARGS_OFFSET, - // RESULT, OUTCHAIN = EXCEPTIONADDR(INCHAIN) - This node represents the - // address of the exception block on entry to an landing pad block. + /// RESULT, OUTCHAIN = EXCEPTIONADDR(INCHAIN) - This node represents the + /// address of the exception block on entry to an landing pad block. EXCEPTIONADDR, - // RESULT, OUTCHAIN = LSDAADDR(INCHAIN) - This node represents the - // address of the Language Specific Data Area for the enclosing function. + /// RESULT, OUTCHAIN = LSDAADDR(INCHAIN) - This node represents the + /// address of the Language Specific Data Area for the enclosing function. LSDAADDR, - // RESULT, OUTCHAIN = EHSELECTION(INCHAIN, EXCEPTION) - This node represents - // the selection index of the exception thrown. + /// RESULT, OUTCHAIN = EHSELECTION(INCHAIN, EXCEPTION) - This node + /// represents the selection index of the exception thrown. EHSELECTION, - // OUTCHAIN = EH_RETURN(INCHAIN, OFFSET, HANDLER) - This node represents - // 'eh_return' gcc dwarf builtin, which is used to return from - // exception. The general meaning is: adjust stack by OFFSET and pass - // execution to HANDLER. Many platform-related details also :) + /// OUTCHAIN = EH_RETURN(INCHAIN, OFFSET, HANDLER) - This node represents + /// 'eh_return' gcc dwarf builtin, which is used to return from + /// exception. The general meaning is: adjust stack by OFFSET and pass + /// execution to HANDLER. Many platform-related details also :) EH_RETURN, - // RESULT, OUTCHAIN = EH_SJLJ_SETJMP(INCHAIN, buffer) - // This corresponds to the eh.sjlj.setjmp intrinsic. - // It takes an input chain and a pointer to the jump buffer as inputs - // and returns an outchain. + /// RESULT, OUTCHAIN = EH_SJLJ_SETJMP(INCHAIN, buffer) + /// This corresponds to the eh.sjlj.setjmp intrinsic. + /// It takes an input chain and a pointer to the jump buffer as inputs + /// and returns an outchain. EH_SJLJ_SETJMP, - // OUTCHAIN = EH_SJLJ_LONGJMP(INCHAIN, buffer) - // This corresponds to the eh.sjlj.longjmp intrinsic. - // It takes an input chain and a pointer to the jump buffer as inputs - // and returns an outchain. + /// OUTCHAIN = EH_SJLJ_LONGJMP(INCHAIN, buffer) + /// This corresponds to the eh.sjlj.longjmp intrinsic. + /// It takes an input chain and a pointer to the jump buffer as inputs + /// and returns an outchain. EH_SJLJ_LONGJMP, - // TargetConstant* - Like Constant*, but the DAG does not do any folding, - // simplification, or lowering of the constant. They are used for constants - // which are known to fit in the immediate fields of their users, or for - // carrying magic numbers which are not values which need to be materialized - // in registers. + /// TargetConstant* - Like Constant*, but the DAG does not do any folding, + /// simplification, or lowering of the constant. They are used for constants + /// which are known to fit in the immediate fields of their users, or for + /// carrying magic numbers which are not values which need to be + /// materialized in registers. TargetConstant, TargetConstantFP, - // TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or - // anything else with this node, and this is valid in the target-specific - // dag, turning into a GlobalAddress operand. + /// TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or + /// anything else with this node, and this is valid in the target-specific + /// dag, turning into a GlobalAddress operand. TargetGlobalAddress, TargetGlobalTLSAddress, TargetFrameIndex, @@ -126,6 +126,11 @@ namespace ISD { TargetExternalSymbol, TargetBlockAddress, + /// TargetIndex - Like a constant pool entry, but with completely + /// target-dependent semantics. Holds target flags, a 32-bit index, and a + /// 64-bit index. Targets can use this however they like. + TargetIndex, + /// RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) /// This node represents a target intrinsic function with no side effects. /// The first operand is the ID number of the intrinsic from the @@ -148,93 +153,94 @@ namespace ISD { /// namespace. The operands to the intrinsic follow. INTRINSIC_VOID, - // CopyToReg - This node has three operands: a chain, a register number to - // set to this value, and a value. + /// CopyToReg - This node has three operands: a chain, a register number to + /// set to this value, and a value. CopyToReg, - // CopyFromReg - This node indicates that the input value is a virtual or - // physical register that is defined outside of the scope of this - // SelectionDAG. The register is available from the RegisterSDNode object. + /// CopyFromReg - This node indicates that the input value is a virtual or + /// physical register that is defined outside of the scope of this + /// SelectionDAG. The register is available from the RegisterSDNode object. CopyFromReg, - // UNDEF - An undefined node + /// UNDEF - An undefined node. UNDEF, - // EXTRACT_ELEMENT - This is used to get the lower or upper (determined by - // a Constant, which is required to be operand #1) half of the integer or - // float value specified as operand #0. This is only for use before - // legalization, for values that will be broken into multiple registers. + /// EXTRACT_ELEMENT - This is used to get the lower or upper (determined by + /// a Constant, which is required to be operand #1) half of the integer or + /// float value specified as operand #0. This is only for use before + /// legalization, for values that will be broken into multiple registers. EXTRACT_ELEMENT, - // BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways. Given - // two values of the same integer value type, this produces a value twice as - // big. Like EXTRACT_ELEMENT, this can only be used before legalization. + /// BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways. + /// Given two values of the same integer value type, this produces a value + /// twice as big. Like EXTRACT_ELEMENT, this can only be used before + /// legalization. BUILD_PAIR, - // MERGE_VALUES - This node takes multiple discrete operands and returns - // them all as its individual results. This nodes has exactly the same - // number of inputs and outputs. This node is useful for some pieces of the - // code generator that want to think about a single node with multiple - // results, not multiple nodes. + /// MERGE_VALUES - This node takes multiple discrete operands and returns + /// them all as its individual results. This nodes has exactly the same + /// number of inputs and outputs. This node is useful for some pieces of the + /// code generator that want to think about a single node with multiple + /// results, not multiple nodes. MERGE_VALUES, - // Simple integer binary arithmetic operators. + /// Simple integer binary arithmetic operators. ADD, SUB, MUL, SDIV, UDIV, SREM, UREM, - // SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing - // a signed/unsigned value of type i[2*N], and return the full value as - // two results, each of type iN. + /// SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing + /// a signed/unsigned value of type i[2*N], and return the full value as + /// two results, each of type iN. SMUL_LOHI, UMUL_LOHI, - // SDIVREM/UDIVREM - Divide two integers and produce both a quotient and - // remainder result. + /// SDIVREM/UDIVREM - Divide two integers and produce both a quotient and + /// remainder result. SDIVREM, UDIVREM, - // CARRY_FALSE - This node is used when folding other nodes, - // like ADDC/SUBC, which indicate the carry result is always false. + /// CARRY_FALSE - This node is used when folding other nodes, + /// like ADDC/SUBC, which indicate the carry result is always false. CARRY_FALSE, - // Carry-setting nodes for multiple precision addition and subtraction. - // These nodes take two operands of the same value type, and produce two - // results. The first result is the normal add or sub result, the second - // result is the carry flag result. + /// Carry-setting nodes for multiple precision addition and subtraction. + /// These nodes take two operands of the same value type, and produce two + /// results. The first result is the normal add or sub result, the second + /// result is the carry flag result. ADDC, SUBC, - // Carry-using nodes for multiple precision addition and subtraction. These - // nodes take three operands: The first two are the normal lhs and rhs to - // the add or sub, and the third is the input carry flag. These nodes - // produce two results; the normal result of the add or sub, and the output - // carry flag. These nodes both read and write a carry flag to allow them - // to them to be chained together for add and sub of arbitrarily large - // values. + /// Carry-using nodes for multiple precision addition and subtraction. These + /// nodes take three operands: The first two are the normal lhs and rhs to + /// the add or sub, and the third is the input carry flag. These nodes + /// produce two results; the normal result of the add or sub, and the output + /// carry flag. These nodes both read and write a carry flag to allow them + /// to them to be chained together for add and sub of arbitrarily large + /// values. ADDE, SUBE, - // RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition. - // These nodes take two operands: the normal LHS and RHS to the add. They - // produce two results: the normal result of the add, and a boolean that - // indicates if an overflow occurred (*not* a flag, because it may be stored - // to memory, etc.). If the type of the boolean is not i1 then the high - // bits conform to getBooleanContents. - // These nodes are generated from the llvm.[su]add.with.overflow intrinsics. + /// RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition. + /// These nodes take two operands: the normal LHS and RHS to the add. They + /// produce two results: the normal result of the add, and a boolean that + /// indicates if an overflow occurred (*not* a flag, because it may be store + /// to memory, etc.). If the type of the boolean is not i1 then the high + /// bits conform to getBooleanContents. + /// These nodes are generated from llvm.[su]add.with.overflow intrinsics. SADDO, UADDO, - // Same for subtraction + /// Same for subtraction. SSUBO, USUBO, - // Same for multiplication + /// Same for multiplication. SMULO, UMULO, - // Simple binary floating point operators. + /// Simple binary floating point operators. FADD, FSUB, FMUL, FMA, FDIV, FREM, - // FCOPYSIGN(X, Y) - Return the value of X with the sign of Y. NOTE: This - // DAG node does not require that X and Y have the same type, just that they - // are both floating point. X and the result must have the same type. - // FCOPYSIGN(f32, f64) is allowed. + /// FCOPYSIGN(X, Y) - Return the value of X with the sign of Y. NOTE: This + /// DAG node does not require that X and Y have the same type, just that the + /// are both floating point. X and the result must have the same type. + /// FCOPYSIGN(f32, f64) is allowed. FCOPYSIGN, - // INT = FGETSIGN(FP) - Return the sign bit of the specified floating point - // value as an integer 0/1 value. + /// INT = FGETSIGN(FP) - Return the sign bit of the specified floating point + /// value as an integer 0/1 value. FGETSIGN, /// BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a vector with the @@ -292,13 +298,14 @@ namespace ISD { /// than the vector element type, and is implicitly truncated to it. SCALAR_TO_VECTOR, - // MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing - // an unsigned/signed value of type i[2*N], then return the top part. + /// MULHU/MULHS - Multiply high - Multiply two integers of type iN, + /// producing an unsigned/signed value of type i[2*N], then return the top + /// part. MULHU, MULHS, /// Bitwise operators - logical and, logical or, logical xor. AND, OR, XOR, - + /// Shift and rotation operations. After legalization, the type of the /// shift amount is known to be TLI.getShiftAmountTy(). Before legalization /// the shift amount can be any type, but care must be taken to ensure it is @@ -306,7 +313,6 @@ namespace ISD { /// legalization, types like i1024 can occur and i8 doesn't have enough bits /// to represent the shift amount. By convention, DAGCombine and /// SelectionDAGBuilder forces these shift amounts to i32 for simplicity. - /// SHL, SRA, SRL, ROTL, ROTR, /// Byte Swap and Counting operators. @@ -315,67 +321,67 @@ namespace ISD { /// Bit counting operators with an undefined result for zero inputs. CTTZ_ZERO_UNDEF, CTLZ_ZERO_UNDEF, - // Select(COND, TRUEVAL, FALSEVAL). If the type of the boolean COND is not - // i1 then the high bits must conform to getBooleanContents. + /// Select(COND, TRUEVAL, FALSEVAL). If the type of the boolean COND is not + /// i1 then the high bits must conform to getBooleanContents. SELECT, - // Select with a vector condition (op #0) and two vector operands (ops #1 - // and #2), returning a vector result. All vectors have the same length. - // Much like the scalar select and setcc, each bit in the condition selects - // whether the corresponding result element is taken from op #1 or op #2. - // At first, the VSELECT condition is of vXi1 type. Later, targets may change - // the condition type in order to match the VSELECT node using a a pattern. - // The condition follows the BooleanContent format of the target. + /// Select with a vector condition (op #0) and two vector operands (ops #1 + /// and #2), returning a vector result. All vectors have the same length. + /// Much like the scalar select and setcc, each bit in the condition selects + /// whether the corresponding result element is taken from op #1 or op #2. + /// At first, the VSELECT condition is of vXi1 type. Later, targets may + /// change the condition type in order to match the VSELECT node using a + /// pattern. The condition follows the BooleanContent format of the target. VSELECT, - // Select with condition operator - This selects between a true value and - // a false value (ops #2 and #3) based on the boolean result of comparing - // the lhs and rhs (ops #0 and #1) of a conditional expression with the - // condition code in op #4, a CondCodeSDNode. + /// Select with condition operator - This selects between a true value and + /// a false value (ops #2 and #3) based on the boolean result of comparing + /// the lhs and rhs (ops #0 and #1) of a conditional expression with the + /// condition code in op #4, a CondCodeSDNode. SELECT_CC, - // SetCC operator - This evaluates to a true value iff the condition is - // true. If the result value type is not i1 then the high bits conform - // to getBooleanContents. The operands to this are the left and right - // operands to compare (ops #0, and #1) and the condition code to compare - // them with (op #2) as a CondCodeSDNode. If the operands are vector types - // then the result type must also be a vector type. + /// SetCC operator - This evaluates to a true value iff the condition is + /// true. If the result value type is not i1 then the high bits conform + /// to getBooleanContents. The operands to this are the left and right + /// operands to compare (ops #0, and #1) and the condition code to compare + /// them with (op #2) as a CondCodeSDNode. If the operands are vector types + /// then the result type must also be a vector type. SETCC, - // SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded - // integer shift operations, just like ADD/SUB_PARTS. The operation - // ordering is: - // [Lo,Hi] = op [LoLHS,HiLHS], Amt + /// SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded + /// integer shift operations, just like ADD/SUB_PARTS. The operation + /// ordering is: + /// [Lo,Hi] = op [LoLHS,HiLHS], Amt SHL_PARTS, SRA_PARTS, SRL_PARTS, - // Conversion operators. These are all single input single output - // operations. For all of these, the result type must be strictly - // wider or narrower (depending on the operation) than the source - // type. + /// Conversion operators. These are all single input single output + /// operations. For all of these, the result type must be strictly + /// wider or narrower (depending on the operation) than the source + /// type. - // SIGN_EXTEND - Used for integer types, replicating the sign bit - // into new bits. + /// SIGN_EXTEND - Used for integer types, replicating the sign bit + /// into new bits. SIGN_EXTEND, - // ZERO_EXTEND - Used for integer types, zeroing the new bits. + /// ZERO_EXTEND - Used for integer types, zeroing the new bits. ZERO_EXTEND, - // ANY_EXTEND - Used for integer types. The high bits are undefined. + /// ANY_EXTEND - Used for integer types. The high bits are undefined. ANY_EXTEND, - // TRUNCATE - Completely drop the high bits. + /// TRUNCATE - Completely drop the high bits. TRUNCATE, - // [SU]INT_TO_FP - These operators convert integers (whose interpreted sign - // depends on the first letter) to floating point. + /// [SU]INT_TO_FP - These operators convert integers (whose interpreted sign + /// depends on the first letter) to floating point. SINT_TO_FP, UINT_TO_FP, - // SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to - // sign extend a small value in a large integer register (e.g. sign - // extending the low 8 bits of a 32-bit register to fill the top 24 bits - // with the 7th bit). The size of the smaller type is indicated by the 1th - // operand, a ValueType node. + /// SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to + /// sign extend a small value in a large integer register (e.g. sign + /// extending the low 8 bits of a 32-bit register to fill the top 24 bits + /// with the 7th bit). The size of the smaller type is indicated by the 1th + /// operand, a ValueType node. SIGN_EXTEND_INREG, /// FP_TO_[US]INT - Convert a floating point value to a signed or unsigned @@ -396,12 +402,12 @@ namespace ISD { /// FP_EXTEND(FP_ROUND(X,0)) because the extra bits aren't removed. FP_ROUND, - // FLT_ROUNDS_ - Returns current rounding mode: - // -1 Undefined - // 0 Round to 0 - // 1 Round to nearest - // 2 Round to +inf - // 3 Round to -inf + /// FLT_ROUNDS_ - Returns current rounding mode: + /// -1 Undefined + /// 0 Round to 0 + /// 1 Round to nearest + /// 2 Round to +inf + /// 3 Round to -inf FLT_ROUNDS_, /// X = FP_ROUND_INREG(Y, VT) - This operator takes an FP register, and @@ -414,208 +420,211 @@ namespace ISD { /// X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type. FP_EXTEND, - // BITCAST - This operator converts between integer, vector and FP - // values, as if the value was stored to memory with one type and loaded - // from the same address with the other type (or equivalently for vector - // format conversions, etc). The source and result are required to have - // the same bit size (e.g. f32 <-> i32). This can also be used for - // int-to-int or fp-to-fp conversions, but that is a noop, deleted by - // getNode(). + /// BITCAST - This operator converts between integer, vector and FP + /// values, as if the value was stored to memory with one type and loaded + /// from the same address with the other type (or equivalently for vector + /// format conversions, etc). The source and result are required to have + /// the same bit size (e.g. f32 <-> i32). This can also be used for + /// int-to-int or fp-to-fp conversions, but that is a noop, deleted by + /// getNode(). BITCAST, - // CONVERT_RNDSAT - This operator is used to support various conversions - // between various types (float, signed, unsigned and vectors of those - // types) with rounding and saturation. NOTE: Avoid using this operator as - // most target don't support it and the operator might be removed in the - // future. It takes the following arguments: - // 0) value - // 1) dest type (type to convert to) - // 2) src type (type to convert from) - // 3) rounding imm - // 4) saturation imm - // 5) ISD::CvtCode indicating the type of conversion to do + /// CONVERT_RNDSAT - This operator is used to support various conversions + /// between various types (float, signed, unsigned and vectors of those + /// types) with rounding and saturation. NOTE: Avoid using this operator as + /// most target don't support it and the operator might be removed in the + /// future. It takes the following arguments: + /// 0) value + /// 1) dest type (type to convert to) + /// 2) src type (type to convert from) + /// 3) rounding imm + /// 4) saturation imm + /// 5) ISD::CvtCode indicating the type of conversion to do CONVERT_RNDSAT, - // FP16_TO_FP32, FP32_TO_FP16 - These operators are used to perform - // promotions and truncation for half-precision (16 bit) floating - // numbers. We need special nodes since FP16 is a storage-only type with - // special semantics of operations. + /// FP16_TO_FP32, FP32_TO_FP16 - These operators are used to perform + /// promotions and truncation for half-precision (16 bit) floating + /// numbers. We need special nodes since FP16 is a storage-only type with + /// special semantics of operations. FP16_TO_FP32, FP32_TO_FP16, - // FNEG, FABS, FSQRT, FSIN, FCOS, FPOWI, FPOW, - // FLOG, FLOG2, FLOG10, FEXP, FEXP2, - // FCEIL, FTRUNC, FRINT, FNEARBYINT, FFLOOR - Perform various unary floating - // point operations. These are inspired by libm. + /// FNEG, FABS, FSQRT, FSIN, FCOS, FPOWI, FPOW, + /// FLOG, FLOG2, FLOG10, FEXP, FEXP2, + /// FCEIL, FTRUNC, FRINT, FNEARBYINT, FFLOOR - Perform various unary + /// floating point operations. These are inspired by libm. FNEG, FABS, FSQRT, FSIN, FCOS, FPOWI, FPOW, FLOG, FLOG2, FLOG10, FEXP, FEXP2, FCEIL, FTRUNC, FRINT, FNEARBYINT, FFLOOR, - // LOAD and STORE have token chains as their first operand, then the same - // operands as an LLVM load/store instruction, then an offset node that - // is added / subtracted from the base pointer to form the address (for - // indexed memory ops). + /// LOAD and STORE have token chains as their first operand, then the same + /// operands as an LLVM load/store instruction, then an offset node that + /// is added / subtracted from the base pointer to form the address (for + /// indexed memory ops). LOAD, STORE, - // DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned - // to a specified boundary. This node always has two return values: a new - // stack pointer value and a chain. The first operand is the token chain, - // the second is the number of bytes to allocate, and the third is the - // alignment boundary. The size is guaranteed to be a multiple of the stack - // alignment, and the alignment is guaranteed to be bigger than the stack - // alignment (if required) or 0 to get standard stack alignment. + /// DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned + /// to a specified boundary. This node always has two return values: a new + /// stack pointer value and a chain. The first operand is the token chain, + /// the second is the number of bytes to allocate, and the third is the + /// alignment boundary. The size is guaranteed to be a multiple of the + /// stack alignment, and the alignment is guaranteed to be bigger than the + /// stack alignment (if required) or 0 to get standard stack alignment. DYNAMIC_STACKALLOC, - // Control flow instructions. These all have token chains. + /// Control flow instructions. These all have token chains. - // BR - Unconditional branch. The first operand is the chain - // operand, the second is the MBB to branch to. + /// BR - Unconditional branch. The first operand is the chain + /// operand, the second is the MBB to branch to. BR, - // BRIND - Indirect branch. The first operand is the chain, the second - // is the value to branch to, which must be of the same type as the target's - // pointer type. + /// BRIND - Indirect branch. The first operand is the chain, the second + /// is the value to branch to, which must be of the same type as the + /// target's pointer type. BRIND, - // BR_JT - Jumptable branch. The first operand is the chain, the second - // is the jumptable index, the last one is the jumptable entry index. + /// BR_JT - Jumptable branch. The first operand is the chain, the second + /// is the jumptable index, the last one is the jumptable entry index. BR_JT, - // BRCOND - Conditional branch. The first operand is the chain, the - // second is the condition, the third is the block to branch to if the - // condition is true. If the type of the condition is not i1, then the - // high bits must conform to getBooleanContents. + /// BRCOND - Conditional branch. The first operand is the chain, the + /// second is the condition, the third is the block to branch to if the + /// condition is true. If the type of the condition is not i1, then the + /// high bits must conform to getBooleanContents. BRCOND, - // BR_CC - Conditional branch. The behavior is like that of SELECT_CC, in - // that the condition is represented as condition code, and two nodes to - // compare, rather than as a combined SetCC node. The operands in order are - // chain, cc, lhs, rhs, block to branch to if condition is true. + /// BR_CC - Conditional branch. The behavior is like that of SELECT_CC, in + /// that the condition is represented as condition code, and two nodes to + /// compare, rather than as a combined SetCC node. The operands in order + /// are chain, cc, lhs, rhs, block to branch to if condition is true. BR_CC, - // INLINEASM - Represents an inline asm block. This node always has two - // return values: a chain and a flag result. The inputs are as follows: - // Operand #0 : Input chain. - // Operand #1 : a ExternalSymbolSDNode with a pointer to the asm string. - // Operand #2 : a MDNodeSDNode with the !srcloc metadata. - // Operand #3 : HasSideEffect, IsAlignStack bits. - // After this, it is followed by a list of operands with this format: - // ConstantSDNode: Flags that encode whether it is a mem or not, the - // of operands that follow, etc. See InlineAsm.h. - // ... however many operands ... - // Operand #last: Optional, an incoming flag. - // - // The variable width operands are required to represent target addressing - // modes as a single "operand", even though they may have multiple - // SDOperands. + /// INLINEASM - Represents an inline asm block. This node always has two + /// return values: a chain and a flag result. The inputs are as follows: + /// Operand #0 : Input chain. + /// Operand #1 : a ExternalSymbolSDNode with a pointer to the asm string. + /// Operand #2 : a MDNodeSDNode with the !srcloc metadata. + /// Operand #3 : HasSideEffect, IsAlignStack bits. + /// After this, it is followed by a list of operands with this format: + /// ConstantSDNode: Flags that encode whether it is a mem or not, the + /// of operands that follow, etc. See InlineAsm.h. + /// ... however many operands ... + /// Operand #last: Optional, an incoming flag. + /// + /// The variable width operands are required to represent target addressing + /// modes as a single "operand", even though they may have multiple + /// SDOperands. INLINEASM, - // EH_LABEL - Represents a label in mid basic block used to track - // locations needed for debug and exception handling tables. These nodes - // take a chain as input and return a chain. + /// EH_LABEL - Represents a label in mid basic block used to track + /// locations needed for debug and exception handling tables. These nodes + /// take a chain as input and return a chain. EH_LABEL, - // STACKSAVE - STACKSAVE has one operand, an input chain. It produces a - // value, the same type as the pointer type for the system, and an output - // chain. + /// STACKSAVE - STACKSAVE has one operand, an input chain. It produces a + /// value, the same type as the pointer type for the system, and an output + /// chain. STACKSAVE, - // STACKRESTORE has two operands, an input chain and a pointer to restore to - // it returns an output chain. + /// STACKRESTORE has two operands, an input chain and a pointer to restore + /// to it returns an output chain. STACKRESTORE, - // CALLSEQ_START/CALLSEQ_END - These operators mark the beginning and end of - // a call sequence, and carry arbitrary information that target might want - // to know. The first operand is a chain, the rest are specified by the - // target and not touched by the DAG optimizers. - // CALLSEQ_START..CALLSEQ_END pairs may not be nested. + /// CALLSEQ_START/CALLSEQ_END - These operators mark the beginning and end + /// of a call sequence, and carry arbitrary information that target might + /// want to know. The first operand is a chain, the rest are specified by + /// the target and not touched by the DAG optimizers. + /// CALLSEQ_START..CALLSEQ_END pairs may not be nested. CALLSEQ_START, // Beginning of a call sequence CALLSEQ_END, // End of a call sequence - // VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, - // and the alignment. It returns a pair of values: the vaarg value and a - // new chain. + /// VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, + /// and the alignment. It returns a pair of values: the vaarg value and a + /// new chain. VAARG, - // VACOPY - VACOPY has five operands: an input chain, a destination pointer, - // a source pointer, a SRCVALUE for the destination, and a SRCVALUE for the - // source. + /// VACOPY - VACOPY has 5 operands: an input chain, a destination pointer, + /// a source pointer, a SRCVALUE for the destination, and a SRCVALUE for the + /// source. VACOPY, - // VAEND, VASTART - VAEND and VASTART have three operands: an input chain, a - // pointer, and a SRCVALUE. + /// VAEND, VASTART - VAEND and VASTART have three operands: an input chain, + /// pointer, and a SRCVALUE. VAEND, VASTART, - // SRCVALUE - This is a node type that holds a Value* that is used to - // make reference to a value in the LLVM IR. + /// SRCVALUE - This is a node type that holds a Value* that is used to + /// make reference to a value in the LLVM IR. SRCVALUE, - // MDNODE_SDNODE - This is a node that holdes an MDNode*, which is used to - // reference metadata in the IR. + /// MDNODE_SDNODE - This is a node that holdes an MDNode*, which is used to + /// reference metadata in the IR. MDNODE_SDNODE, - // PCMARKER - This corresponds to the pcmarker intrinsic. + /// PCMARKER - This corresponds to the pcmarker intrinsic. PCMARKER, - // READCYCLECOUNTER - This corresponds to the readcyclecounter intrinsic. - // The only operand is a chain and a value and a chain are produced. The - // value is the contents of the architecture specific cycle counter like - // register (or other high accuracy low latency clock source) + /// READCYCLECOUNTER - This corresponds to the readcyclecounter intrinsic. + /// The only operand is a chain and a value and a chain are produced. The + /// value is the contents of the architecture specific cycle counter like + /// register (or other high accuracy low latency clock source) READCYCLECOUNTER, - // HANDLENODE node - Used as a handle for various purposes. + /// HANDLENODE node - Used as a handle for various purposes. HANDLENODE, - // INIT_TRAMPOLINE - This corresponds to the init_trampoline intrinsic. It - // takes as input a token chain, the pointer to the trampoline, the pointer - // to the nested function, the pointer to pass for the 'nest' parameter, a - // SRCVALUE for the trampoline and another for the nested function (allowing - // targets to access the original Function*). It produces a token chain as - // output. + /// INIT_TRAMPOLINE - This corresponds to the init_trampoline intrinsic. It + /// takes as input a token chain, the pointer to the trampoline, the pointer + /// to the nested function, the pointer to pass for the 'nest' parameter, a + /// SRCVALUE for the trampoline and another for the nested function + /// (allowing targets to access the original Function*). + /// It produces a token chain as output. INIT_TRAMPOLINE, - // ADJUST_TRAMPOLINE - This corresponds to the adjust_trampoline intrinsic. - // It takes a pointer to the trampoline and produces a (possibly) new - // pointer to the same trampoline with platform-specific adjustments - // applied. The pointer it returns points to an executable block of code. + /// ADJUST_TRAMPOLINE - This corresponds to the adjust_trampoline intrinsic. + /// It takes a pointer to the trampoline and produces a (possibly) new + /// pointer to the same trampoline with platform-specific adjustments + /// applied. The pointer it returns points to an executable block of code. ADJUST_TRAMPOLINE, - // TRAP - Trapping instruction + /// TRAP - Trapping instruction TRAP, - // PREFETCH - This corresponds to a prefetch intrinsic. It takes chains are - // their first operand. The other operands are the address to prefetch, - // read / write specifier, locality specifier and instruction / data cache - // specifier. + /// DEBUGTRAP - Trap intended to get the attention of a debugger. + DEBUGTRAP, + + /// PREFETCH - This corresponds to a prefetch intrinsic. The first operand + /// is the chain. The other operands are the address to prefetch, + /// read / write specifier, locality specifier and instruction / data cache + /// specifier. PREFETCH, - // OUTCHAIN = MEMBARRIER(INCHAIN, load-load, load-store, store-load, - // store-store, device) - // This corresponds to the memory.barrier intrinsic. - // it takes an input chain, 4 operands to specify the type of barrier, an - // operand specifying if the barrier applies to device and uncached memory - // and produces an output chain. + /// OUTCHAIN = MEMBARRIER(INCHAIN, load-load, load-store, store-load, + /// store-store, device) + /// This corresponds to the memory.barrier intrinsic. + /// it takes an input chain, 4 operands to specify the type of barrier, an + /// operand specifying if the barrier applies to device and uncached memory + /// and produces an output chain. MEMBARRIER, - // OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) - // This corresponds to the fence instruction. It takes an input chain, and - // two integer constants: an AtomicOrdering and a SynchronizationScope. + /// OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) + /// This corresponds to the fence instruction. It takes an input chain, and + /// two integer constants: an AtomicOrdering and a SynchronizationScope. ATOMIC_FENCE, - // Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) - // This corresponds to "load atomic" instruction. + /// Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) + /// This corresponds to "load atomic" instruction. ATOMIC_LOAD, - // OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr, val) - // This corresponds to "store atomic" instruction. + /// OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr, val) + /// This corresponds to "store atomic" instruction. ATOMIC_STORE, - // Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) - // This corresponds to the cmpxchg instruction. + /// Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) + /// This corresponds to the cmpxchg instruction. ATOMIC_CMP_SWAP, - // Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) - // Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN, ptr, amt) - // These correspond to the atomicrmw instruction. + /// Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) + /// Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN, ptr, amt) + /// These correspond to the atomicrmw instruction. ATOMIC_SWAP, ATOMIC_LOAD_ADD, ATOMIC_LOAD_SUB, @@ -790,16 +799,16 @@ namespace ISD { /// CvtCode enum - This enum defines the various converts CONVERT_RNDSAT /// supports. enum CvtCode { - CVT_FF, // Float from Float - CVT_FS, // Float from Signed - CVT_FU, // Float from Unsigned - CVT_SF, // Signed from Float - CVT_UF, // Unsigned from Float - CVT_SS, // Signed from Signed - CVT_SU, // Signed from Unsigned - CVT_US, // Unsigned from Signed - CVT_UU, // Unsigned from Unsigned - CVT_INVALID // Marker - Invalid opcode + CVT_FF, /// Float from Float + CVT_FS, /// Float from Signed + CVT_FU, /// Float from Unsigned + CVT_SF, /// Signed from Float + CVT_UF, /// Unsigned from Float + CVT_SS, /// Signed from Signed + CVT_SU, /// Signed from Unsigned + CVT_US, /// Unsigned from Signed + CVT_UU, /// Unsigned from Unsigned + CVT_INVALID /// Marker - Invalid opcode }; } // end llvm::ISD namespace diff --git a/include/llvm/CodeGen/LexicalScopes.h b/include/llvm/CodeGen/LexicalScopes.h index eb01f66c..8414c64 100644 --- a/include/llvm/CodeGen/LexicalScopes.h +++ b/include/llvm/CodeGen/LexicalScopes.h @@ -158,7 +158,10 @@ class LexicalScope { public: LexicalScope(LexicalScope *P, const MDNode *D, const MDNode *I, bool A) : Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(A), - LastInsn(0), FirstInsn(0), DFSIn(0), DFSOut(0), IndentLevel(0) { + LastInsn(0), FirstInsn(0), DFSIn(0), DFSOut(0) { +#ifndef NDEBUG + IndentLevel = 0; +#endif if (Parent) Parent->addChild(this); } @@ -241,7 +244,9 @@ private: const MachineInstr *FirstInsn; // First instruction of this scope. unsigned DFSIn, DFSOut; // In & Out Depth use to determine // scope nesting. +#ifndef NDEBUG mutable unsigned IndentLevel; // Private state for dump() +#endif }; } // end llvm namespace diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h index a6008ab..a3ce47c 100644 --- a/include/llvm/CodeGen/LiveInterval.h +++ b/include/llvm/CodeGen/LiveInterval.h @@ -40,15 +40,6 @@ namespace llvm { /// definition and use points. /// class VNInfo { - private: - enum { - HAS_PHI_KILL = 1, - IS_PHI_DEF = 1 << 1, - IS_UNUSED = 1 << 2 - }; - - unsigned char flags; - public: typedef BumpPtrAllocator Allocator; @@ -60,60 +51,30 @@ namespace llvm { /// VNInfo constructor. VNInfo(unsigned i, SlotIndex d) - : flags(0), id(i), def(d) + : id(i), def(d) { } /// VNInfo construtor, copies values from orig, except for the value number. VNInfo(unsigned i, const VNInfo &orig) - : flags(orig.flags), id(i), def(orig.def) + : id(i), def(orig.def) { } /// Copy from the parameter into this VNInfo. void copyFrom(VNInfo &src) { - flags = src.flags; def = src.def; } - /// Used for copying value number info. - unsigned getFlags() const { return flags; } - void setFlags(unsigned flags) { this->flags = flags; } - - /// Merge flags from another VNInfo - void mergeFlags(const VNInfo *VNI) { - flags = (flags | VNI->flags) & ~IS_UNUSED; - } - - /// Returns true if one or more kills are PHI nodes. - /// Obsolete, do not use! - bool hasPHIKill() const { return flags & HAS_PHI_KILL; } - /// Set the PHI kill flag on this value. - void setHasPHIKill(bool hasKill) { - if (hasKill) - flags |= HAS_PHI_KILL; - else - flags &= ~HAS_PHI_KILL; - } - /// Returns true if this value is defined by a PHI instruction (or was, /// PHI instrucions may have been eliminated). - bool isPHIDef() const { return flags & IS_PHI_DEF; } - /// Set the "phi def" flag on this value. - void setIsPHIDef(bool phiDef) { - if (phiDef) - flags |= IS_PHI_DEF; - else - flags &= ~IS_PHI_DEF; - } + /// PHI-defs begin at a block boundary, all other defs begin at register or + /// EC slots. + bool isPHIDef() const { return def.isBlock(); } /// Returns true if this value is unused. - bool isUnused() const { return flags & IS_UNUSED; } - /// Set the "is unused" flag on this value. - void setIsUnused(bool unused) { - if (unused) - flags |= IS_UNUSED; - else - flags &= ~IS_UNUSED; - } + bool isUnused() const { return !def.isValid(); } + + /// Mark this value as unused. + void markUnused() { def = SlotIndex(); } }; /// LiveRange structure - This represents a simple register range in the @@ -274,6 +235,11 @@ namespace llvm { return VNI; } + /// createDeadDef - Make sure the interval has a value defined at Def. + /// If one already exists, return it. Otherwise allocate a new value and + /// add liveness for a dead def. + VNInfo *createDeadDef(SlotIndex Def, VNInfo::Allocator &VNInfoAllocator); + /// Create a copy of the given value. The new value will be identical except /// for the Value number. VNInfo *createValueCopy(const VNInfo *orig, @@ -288,17 +254,6 @@ namespace llvm { /// unused values. void RenumberValues(LiveIntervals &lis); - /// isOnlyLROfValNo - Return true if the specified live range is the only - /// one defined by the its val#. - bool isOnlyLROfValNo(const LiveRange *LR) { - for (const_iterator I = begin(), E = end(); I != E; ++I) { - const LiveRange *Tmp = I; - if (Tmp != LR && Tmp->valno == LR->valno) - return false; - } - return true; - } - /// MergeValueNumberInto - This method is called when two value nubmers /// are found to be equivalent. This eliminates V1, replacing all /// LiveRanges with the V1 value number with the V2 value number. This can @@ -377,14 +332,6 @@ namespace llvm { return I == end() ? 0 : &*I; } - const LiveRange *getLiveRangeBefore(SlotIndex Idx) const { - return getLiveRangeContaining(Idx.getPrevSlot()); - } - - LiveRange *getLiveRangeBefore(SlotIndex Idx) { - return getLiveRangeContaining(Idx.getPrevSlot()); - } - /// getVNInfoAt - Return the VNInfo that is live at Idx, or NULL. VNInfo *getVNInfoAt(SlotIndex Idx) const { const_iterator I = FindLiveRangeContaining(Idx); @@ -411,11 +358,6 @@ namespace llvm { return I != end() && I->start <= Idx ? I : end(); } - /// findDefinedVNInfo - Find the by the specified - /// index (register interval) or defined - VNInfo *findDefinedVNInfoForRegInt(SlotIndex Idx) const; - - /// overlaps - Return true if the intersection of the two live intervals is /// not empty. bool overlaps(const LiveInterval& other) const { @@ -498,10 +440,6 @@ namespace llvm { weight = HUGE_VALF; } - /// ComputeJoinedWeight - Set the weight of a live interval after - /// Other has been merged into it. - void ComputeJoinedWeight(const LiveInterval &Other); - bool operator<(const LiveInterval& other) const { const SlotIndex &thisIndex = beginIndex(); const SlotIndex &otherIndex = other.beginIndex(); @@ -509,15 +447,27 @@ namespace llvm { (thisIndex == otherIndex && reg < other.reg)); } - void print(raw_ostream &OS, const TargetRegisterInfo *TRI = 0) const; + void print(raw_ostream &OS) const; void dump() const; + /// \brief Walk the interval and assert if any invariants fail to hold. + /// + /// Note that this is a no-op when asserts are disabled. +#ifdef NDEBUG + void verify() const {} +#else + void verify() const; +#endif + private: Ranges::iterator addRangeFrom(LiveRange LR, Ranges::iterator From); void extendIntervalEndTo(Ranges::iterator I, SlotIndex NewEnd); Ranges::iterator extendIntervalStartTo(Ranges::iterator I, SlotIndex NewStr); void markValNoForDeletion(VNInfo *V); + void mergeIntervalRanges(const LiveInterval &RHS, + VNInfo *LHSValNo = 0, + const VNInfo *RHSValNo = 0); LiveInterval& operator=(const LiveInterval& rhs); // DO NOT IMPLEMENT @@ -528,6 +478,91 @@ namespace llvm { return OS; } + /// LiveRangeQuery - Query information about a live range around a given + /// instruction. This class hides the implementation details of live ranges, + /// and it should be used as the primary interface for examining live ranges + /// around instructions. + /// + class LiveRangeQuery { + VNInfo *EarlyVal; + VNInfo *LateVal; + SlotIndex EndPoint; + bool Kill; + + public: + /// Create a LiveRangeQuery for the given live range and instruction index. + /// The sub-instruction slot of Idx doesn't matter, only the instruction it + /// refers to is considered. + LiveRangeQuery(const LiveInterval &LI, SlotIndex Idx) + : EarlyVal(0), LateVal(0), Kill(false) { + // Find the segment that enters the instruction. + LiveInterval::const_iterator I = LI.find(Idx.getBaseIndex()); + LiveInterval::const_iterator E = LI.end(); + if (I == E) + return; + // Is this an instruction live-in segment? + if (SlotIndex::isEarlierInstr(I->start, Idx)) { + EarlyVal = I->valno; + EndPoint = I->end; + // Move to the potentially live-out segment. + if (SlotIndex::isSameInstr(Idx, I->end)) { + Kill = true; + if (++I == E) + return; + } + } + // I now points to the segment that may be live-through, or defined by + // this instr. Ignore segments starting after the current instr. + if (SlotIndex::isEarlierInstr(Idx, I->start)) + return; + LateVal = I->valno; + EndPoint = I->end; + } + + /// Return the value that is live-in to the instruction. This is the value + /// that will be read by the instruction's use operands. Return NULL if no + /// value is live-in. + VNInfo *valueIn() const { + return EarlyVal; + } + + /// Return true if the live-in value is killed by this instruction. This + /// means that either the live range ends at the instruction, or it changes + /// value. + bool isKill() const { + return Kill; + } + + /// Return true if this instruction has a dead def. + bool isDeadDef() const { + return EndPoint.isDead(); + } + + /// Return the value leaving the instruction, if any. This can be a + /// live-through value, or a live def. A dead def returns NULL. + VNInfo *valueOut() const { + return isDeadDef() ? 0 : LateVal; + } + + /// Return the value defined by this instruction, if any. This includes + /// dead defs, it is the value created by the instruction's def operands. + VNInfo *valueDefined() const { + return EarlyVal == LateVal ? 0 : LateVal; + } + + /// Return the end point of the last live range segment to interact with + /// the instruction, if any. + /// + /// The end point is an invalid SlotIndex only if the live range doesn't + /// intersect the instruction at all. + /// + /// The end point may be at or past the end of the instruction's basic + /// block. That means the value was live out of the block. + SlotIndex endPoint() const { + return EndPoint; + } + }; + /// ConnectedVNInfoEqClasses - Helper class that can divide VNInfos in a /// LiveInterval into equivalence clases of connected components. A /// LiveInterval that has multiple connected components can be broken into diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index 76201c9..da521db 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -20,12 +20,13 @@ #ifndef LLVM_CODEGEN_LIVEINTERVAL_ANALYSIS_H #define LLVM_CODEGEN_LIVEINTERVAL_ANALYSIS_H +#include "llvm/Target/TargetRegisterInfo.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/LiveInterval.h" #include "llvm/CodeGen/SlotIndexes.h" #include "llvm/ADT/BitVector.h" -#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Allocator.h" @@ -35,7 +36,9 @@ namespace llvm { class AliasAnalysis; + class LiveRangeCalc; class LiveVariables; + class MachineDominatorTree; class MachineLoopInfo; class TargetRegisterInfo; class MachineRegisterInfo; @@ -44,27 +47,29 @@ namespace llvm { class VirtRegMap; class LiveIntervals : public MachineFunctionPass { - MachineFunction* mf_; - MachineRegisterInfo* mri_; - const TargetMachine* tm_; - const TargetRegisterInfo* tri_; - const TargetInstrInfo* tii_; - AliasAnalysis *aa_; - LiveVariables* lv_; - SlotIndexes* indexes_; + MachineFunction* MF; + MachineRegisterInfo* MRI; + const TargetMachine* TM; + const TargetRegisterInfo* TRI; + const TargetInstrInfo* TII; + AliasAnalysis *AA; + LiveVariables* LV; + SlotIndexes* Indexes; + MachineDominatorTree *DomTree; + LiveRangeCalc *LRCalc; /// Special pool allocator for VNInfo's (LiveInterval val#). /// VNInfo::Allocator VNInfoAllocator; - typedef DenseMap<unsigned, LiveInterval*> Reg2IntervalMap; - Reg2IntervalMap r2iMap_; + /// Live interval pointers for all the virtual registers. + IndexedMap<LiveInterval*, VirtReg2IndexFunctor> VirtRegIntervals; - /// allocatableRegs_ - A bit vector of allocatable registers. - BitVector allocatableRegs_; + /// AllocatableRegs - A bit vector of allocatable registers. + BitVector AllocatableRegs; - /// reservedRegs_ - A bit vector of reserved registers. - BitVector reservedRegs_; + /// ReservedRegs - A bit vector of reserved registers. + BitVector ReservedRegs; /// RegMaskSlots - Sorted list of instructions with register mask operands. /// Always use the 'r' slot, RegMasks are normal clobbers, not early @@ -92,83 +97,59 @@ namespace llvm { /// block. SmallVector<std::pair<unsigned, unsigned>, 8> RegMaskBlocks; + /// RegUnitIntervals - Keep a live interval for each register unit as a way + /// of tracking fixed physreg interference. + SmallVector<LiveInterval*, 0> RegUnitIntervals; + public: static char ID; // Pass identification, replacement for typeid - LiveIntervals() : MachineFunctionPass(ID) { - initializeLiveIntervalsPass(*PassRegistry::getPassRegistry()); - } + LiveIntervals(); + virtual ~LiveIntervals(); // Calculate the spill weight to assign to a single instruction. static float getSpillWeight(bool isDef, bool isUse, unsigned loopDepth); - typedef Reg2IntervalMap::iterator iterator; - typedef Reg2IntervalMap::const_iterator const_iterator; - const_iterator begin() const { return r2iMap_.begin(); } - const_iterator end() const { return r2iMap_.end(); } - iterator begin() { return r2iMap_.begin(); } - iterator end() { return r2iMap_.end(); } - unsigned getNumIntervals() const { return (unsigned)r2iMap_.size(); } - - LiveInterval &getInterval(unsigned reg) { - Reg2IntervalMap::iterator I = r2iMap_.find(reg); - assert(I != r2iMap_.end() && "Interval does not exist for register"); - return *I->second; + LiveInterval &getInterval(unsigned Reg) { + LiveInterval *LI = VirtRegIntervals[Reg]; + assert(LI && "Interval does not exist for virtual register"); + return *LI; } - const LiveInterval &getInterval(unsigned reg) const { - Reg2IntervalMap::const_iterator I = r2iMap_.find(reg); - assert(I != r2iMap_.end() && "Interval does not exist for register"); - return *I->second; + const LiveInterval &getInterval(unsigned Reg) const { + return const_cast<LiveIntervals*>(this)->getInterval(Reg); } - bool hasInterval(unsigned reg) const { - return r2iMap_.count(reg); + bool hasInterval(unsigned Reg) const { + return VirtRegIntervals.inBounds(Reg) && VirtRegIntervals[Reg]; } /// isAllocatable - is the physical register reg allocatable in the current /// function? bool isAllocatable(unsigned reg) const { - return allocatableRegs_.test(reg); + return AllocatableRegs.test(reg); } /// isReserved - is the physical register reg reserved in the current /// function bool isReserved(unsigned reg) const { - return reservedRegs_.test(reg); - } - - /// getScaledIntervalSize - get the size of an interval in "units," - /// where every function is composed of one thousand units. This - /// measure scales properly with empty index slots in the function. - double getScaledIntervalSize(LiveInterval& I) { - return (1000.0 * I.getSize()) / indexes_->getIndexesLength(); - } - - /// getFuncInstructionCount - Return the number of instructions in the - /// current function. - unsigned getFuncInstructionCount() { - return indexes_->getFunctionSize(); + return ReservedRegs.test(reg); } - /// getApproximateInstructionCount - computes an estimate of the number - /// of instructions in a given LiveInterval. - unsigned getApproximateInstructionCount(LiveInterval& I) { - double IntervalPercentage = getScaledIntervalSize(I) / 1000.0; - return (unsigned)(IntervalPercentage * indexes_->getFunctionSize()); + // Interval creation. + LiveInterval &getOrCreateInterval(unsigned Reg) { + if (!hasInterval(Reg)) { + VirtRegIntervals.grow(Reg); + VirtRegIntervals[Reg] = createInterval(Reg); + } + return getInterval(Reg); } - // Interval creation - LiveInterval &getOrCreateInterval(unsigned reg) { - Reg2IntervalMap::iterator I = r2iMap_.find(reg); - if (I == r2iMap_.end()) - I = r2iMap_.insert(std::make_pair(reg, createInterval(reg))).first; - return *I->second; + // Interval removal. + void removeInterval(unsigned Reg) { + delete VirtRegIntervals[Reg]; + VirtRegIntervals[Reg] = 0; } - /// dupInterval - Duplicate a live interval. The caller is responsible for - /// managing the allocated memory. - LiveInterval *dupInterval(LiveInterval *li); - /// addLiveRangeToEndOfBlock - Given a register and an instruction, /// adds a live range from that instruction to the end of its MBB. LiveRange addLiveRangeToEndOfBlock(unsigned reg, @@ -184,42 +165,38 @@ namespace llvm { bool shrinkToUses(LiveInterval *li, SmallVectorImpl<MachineInstr*> *dead = 0); - // Interval removal - - void removeInterval(unsigned Reg) { - DenseMap<unsigned, LiveInterval*>::iterator I = r2iMap_.find(Reg); - delete I->second; - r2iMap_.erase(I); + SlotIndexes *getSlotIndexes() const { + return Indexes; } - SlotIndexes *getSlotIndexes() const { - return indexes_; + AliasAnalysis *getAliasAnalysis() const { + return AA; } /// isNotInMIMap - returns true if the specified machine instr has been /// removed or was never entered in the map. bool isNotInMIMap(const MachineInstr* Instr) const { - return !indexes_->hasIndex(Instr); + return !Indexes->hasIndex(Instr); } /// Returns the base index of the given instruction. SlotIndex getInstructionIndex(const MachineInstr *instr) const { - return indexes_->getInstructionIndex(instr); + return Indexes->getInstructionIndex(instr); } /// Returns the instruction associated with the given index. MachineInstr* getInstructionFromIndex(SlotIndex index) const { - return indexes_->getInstructionFromIndex(index); + return Indexes->getInstructionFromIndex(index); } /// Return the first index in the given basic block. SlotIndex getMBBStartIdx(const MachineBasicBlock *mbb) const { - return indexes_->getMBBStartIdx(mbb); + return Indexes->getMBBStartIdx(mbb); } /// Return the last index in the given basic block. SlotIndex getMBBEndIdx(const MachineBasicBlock *mbb) const { - return indexes_->getMBBEndIdx(mbb); + return Indexes->getMBBEndIdx(mbb); } bool isLiveInToMBB(const LiveInterval &li, @@ -233,24 +210,24 @@ namespace llvm { } MachineBasicBlock* getMBBFromIndex(SlotIndex index) const { - return indexes_->getMBBFromIndex(index); + return Indexes->getMBBFromIndex(index); } SlotIndex InsertMachineInstrInMaps(MachineInstr *MI) { - return indexes_->insertMachineInstrInMaps(MI); + return Indexes->insertMachineInstrInMaps(MI); } void RemoveMachineInstrFromMaps(MachineInstr *MI) { - indexes_->removeMachineInstrFromMaps(MI); + Indexes->removeMachineInstrFromMaps(MI); } void ReplaceMachineInstrInMaps(MachineInstr *MI, MachineInstr *NewMI) { - indexes_->replaceMachineInstrInMaps(MI, NewMI); + Indexes->replaceMachineInstrInMaps(MI, NewMI); } bool findLiveInMBBs(SlotIndex Start, SlotIndex End, SmallVectorImpl<MachineBasicBlock*> &MBBs) const { - return indexes_->findLiveInMBBs(Start, End, MBBs); + return Indexes->findLiveInMBBs(Start, End, MBBs); } VNInfo::Allocator& getVNInfoAllocator() { return VNInfoAllocator; } @@ -264,18 +241,15 @@ namespace llvm { /// print - Implement the dump method. virtual void print(raw_ostream &O, const Module* = 0) const; - /// isReMaterializable - Returns true if every definition of MI of every - /// val# of the specified interval is re-materializable. Also returns true - /// by reference if all of the defs are load instructions. - bool isReMaterializable(const LiveInterval &li, - const SmallVectorImpl<LiveInterval*> *SpillIs, - bool &isLoad); - /// intervalIsInOneMBB - If LI is confined to a single basic block, return /// a pointer to that block. If LI is live in to or out of any block, /// return NULL. MachineBasicBlock *intervalIsInOneMBB(const LiveInterval &LI) const; + /// Returns true if VNI is killed by any PHI-def values in LI. + /// This may conservatively return true to avoid expensive computations. + bool hasPHIKill(const LiveInterval &LI, const VNInfo *VNI) const; + /// addKillFlags - Add kill flags to any instruction that kills a virtual /// register. void addKillFlags(); @@ -337,13 +311,47 @@ namespace llvm { bool checkRegMaskInterference(LiveInterval &LI, BitVector &UsableRegs); + // Register unit functions. + // + // Fixed interference occurs when MachineInstrs use physregs directly + // instead of virtual registers. This typically happens when passing + // arguments to a function call, or when instructions require operands in + // fixed registers. + // + // Each physreg has one or more register units, see MCRegisterInfo. We + // track liveness per register unit to handle aliasing registers more + // efficiently. + + /// getRegUnit - Return the live range for Unit. + /// It will be computed if it doesn't exist. + LiveInterval &getRegUnit(unsigned Unit) { + LiveInterval *LI = RegUnitIntervals[Unit]; + if (!LI) { + // Compute missing ranges on demand. + RegUnitIntervals[Unit] = LI = new LiveInterval(Unit, HUGE_VALF); + computeRegUnitInterval(LI); + } + return *LI; + } + + /// getCachedRegUnit - Return the live range for Unit if it has already + /// been computed, or NULL if it hasn't been computed yet. + LiveInterval *getCachedRegUnit(unsigned Unit) { + return RegUnitIntervals[Unit]; + } + private: /// computeIntervals - Compute live intervals. void computeIntervals(); + /// Compute live intervals for all virtual registers. + void computeVirtRegs(); + + /// Compute RegMaskSlots and RegMaskBits. + void computeRegMasks(); + /// handleRegisterDef - update intervals for a register def - /// (calls handlePhysicalRegisterDef and - /// handleVirtualRegisterDef) + /// (calls handleVirtualRegisterDef) void handleRegisterDef(MachineBasicBlock *MBB, MachineBasicBlock::iterator MI, SlotIndex MIIdx, @@ -363,43 +371,15 @@ namespace llvm { unsigned MOIdx, LiveInterval& interval); - /// handlePhysicalRegisterDef - update intervals for a physical register - /// def. - void handlePhysicalRegisterDef(MachineBasicBlock* mbb, - MachineBasicBlock::iterator mi, - SlotIndex MIIdx, MachineOperand& MO, - LiveInterval &interval); - - /// handleLiveInRegister - Create interval for a livein register. - void handleLiveInRegister(MachineBasicBlock* mbb, - SlotIndex MIIdx, - LiveInterval &interval); - - /// getReMatImplicitUse - If the remat definition MI has one (for now, we - /// only allow one) virtual register operand, then its uses are implicitly - /// using the register. Returns the virtual register. - unsigned getReMatImplicitUse(const LiveInterval &li, - MachineInstr *MI) const; - - /// isValNoAvailableAt - Return true if the val# of the specified interval - /// which reaches the given instruction also reaches the specified use - /// index. - bool isValNoAvailableAt(const LiveInterval &li, MachineInstr *MI, - SlotIndex UseIdx) const; - - /// isReMaterializable - Returns true if the definition MI of the specified - /// val# of the specified interval is re-materializable. Also returns true - /// by reference if the def is a load. - bool isReMaterializable(const LiveInterval &li, const VNInfo *ValNo, - MachineInstr *MI, - const SmallVectorImpl<LiveInterval*> *SpillIs, - bool &isLoad); - static LiveInterval* createInterval(unsigned Reg); void printInstrs(raw_ostream &O) const; void dumpInstrs() const; + void computeLiveInRegUnits(); + void computeRegUnitInterval(LiveInterval*); + void computeVirtRegInterval(LiveInterval*); + class HMEditor; }; } // End llvm namespace diff --git a/include/llvm/CodeGen/LiveRangeEdit.h b/include/llvm/CodeGen/LiveRangeEdit.h index 57a6193..def7b00 100644 --- a/include/llvm/CodeGen/LiveRangeEdit.h +++ b/include/llvm/CodeGen/LiveRangeEdit.h @@ -55,29 +55,29 @@ public: }; private: - LiveInterval &parent_; - SmallVectorImpl<LiveInterval*> &newRegs_; + LiveInterval *Parent; + SmallVectorImpl<LiveInterval*> &NewRegs; MachineRegisterInfo &MRI; LiveIntervals &LIS; VirtRegMap *VRM; const TargetInstrInfo &TII; - Delegate *const delegate_; + Delegate *const TheDelegate; - /// firstNew_ - Index of the first register added to newRegs_. - const unsigned firstNew_; + /// FirstNew - Index of the first register added to NewRegs. + const unsigned FirstNew; - /// scannedRemattable_ - true when remattable values have been identified. - bool scannedRemattable_; + /// ScannedRemattable - true when remattable values have been identified. + bool ScannedRemattable; - /// remattable_ - Values defined by remattable instructions as identified by + /// Remattable - Values defined by remattable instructions as identified by /// tii.isTriviallyReMaterializable(). - SmallPtrSet<const VNInfo*,4> remattable_; + SmallPtrSet<const VNInfo*,4> Remattable; - /// rematted_ - Values that were actually rematted, and so need to have their + /// Rematted - Values that were actually rematted, and so need to have their /// live range trimmed or entirely removed. - SmallPtrSet<const VNInfo*,4> rematted_; + SmallPtrSet<const VNInfo*,4> Rematted; - /// scanRemattable - Identify the parent_ values that may rematerialize. + /// scanRemattable - Identify the Parent values that may rematerialize. void scanRemattable(AliasAnalysis *aa); /// allUsesAvailableAt - Return true if all registers used by OrigMI at @@ -99,32 +99,35 @@ public: /// @param vrm Map of virtual registers to physical registers for this /// function. If NULL, no virtual register map updates will /// be done. This could be the case if called before Regalloc. - LiveRangeEdit(LiveInterval &parent, + LiveRangeEdit(LiveInterval *parent, SmallVectorImpl<LiveInterval*> &newRegs, MachineFunction &MF, LiveIntervals &lis, VirtRegMap *vrm, Delegate *delegate = 0) - : parent_(parent), newRegs_(newRegs), + : Parent(parent), NewRegs(newRegs), MRI(MF.getRegInfo()), LIS(lis), VRM(vrm), TII(*MF.getTarget().getInstrInfo()), - delegate_(delegate), - firstNew_(newRegs.size()), - scannedRemattable_(false) {} + TheDelegate(delegate), + FirstNew(newRegs.size()), + ScannedRemattable(false) {} - LiveInterval &getParent() const { return parent_; } - unsigned getReg() const { return parent_.reg; } + LiveInterval &getParent() const { + assert(Parent && "No parent LiveInterval"); + return *Parent; + } + unsigned getReg() const { return getParent().reg; } /// Iterator for accessing the new registers added by this edit. typedef SmallVectorImpl<LiveInterval*>::const_iterator iterator; - iterator begin() const { return newRegs_.begin()+firstNew_; } - iterator end() const { return newRegs_.end(); } - unsigned size() const { return newRegs_.size()-firstNew_; } + iterator begin() const { return NewRegs.begin()+FirstNew; } + iterator end() const { return NewRegs.end(); } + unsigned size() const { return NewRegs.size()-FirstNew; } bool empty() const { return size() == 0; } - LiveInterval *get(unsigned idx) const { return newRegs_[idx+firstNew_]; } + LiveInterval *get(unsigned idx) const { return NewRegs[idx+FirstNew]; } ArrayRef<LiveInterval*> regs() const { - return makeArrayRef(newRegs_).slice(firstNew_); + return makeArrayRef(NewRegs).slice(FirstNew); } /// createFrom - Create a new virtual register based on OldReg. @@ -174,12 +177,12 @@ public: /// markRematerialized - explicitly mark a value as rematerialized after doing /// it manually. void markRematerialized(const VNInfo *ParentVNI) { - rematted_.insert(ParentVNI); + Rematted.insert(ParentVNI); } /// didRematerialize - Return true if ParentVNI was rematerialized anywhere. bool didRematerialize(const VNInfo *ParentVNI) const { - return rematted_.count(ParentVNI); + return Rematted.count(ParentVNI); } /// eraseVirtReg - Notify the delegate that Reg is no longer in use, and try diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h index ef9c0c2..c917bd8 100644 --- a/include/llvm/CodeGen/MachineBasicBlock.h +++ b/include/llvm/CodeGen/MachineBasicBlock.h @@ -143,10 +143,7 @@ public: IterTy MII; public: - bundle_iterator(IterTy mii) : MII(mii) { - assert(!MII->isInsideBundle() && - "It's not legal to initialize bundle_iterator with a bundled MI"); - } + bundle_iterator(IterTy mii) : MII(mii) {} bundle_iterator(Ty &mi) : MII(mi) { assert(!mi.isInsideBundle() && @@ -156,7 +153,10 @@ public: assert((!mi || !mi->isInsideBundle()) && "It's not legal to initialize bundle_iterator with a bundled MI"); } - bundle_iterator(const bundle_iterator &I) : MII(I.MII) {} + // Template allows conversion from const to nonconst. + template<class OtherTy, class OtherIterTy> + bundle_iterator(const bundle_iterator<OtherTy, OtherIterTy> &I) + : MII(I.getInstrIterator()) {} bundle_iterator() : MII(0) {} Ty &operator*() const { return *MII; } @@ -173,29 +173,24 @@ public: // Increment and decrement operators... bundle_iterator &operator--() { // predecrement - Back up - do { - --MII; - } while (MII->isInsideBundle()); + do --MII; + while (MII->isInsideBundle()); return *this; } bundle_iterator &operator++() { // preincrement - Advance - do { - ++MII; - } while (MII->isInsideBundle()); + IterTy E = MII->getParent()->instr_end(); + do ++MII; + while (MII != E && MII->isInsideBundle()); return *this; } bundle_iterator operator--(int) { // postdecrement operators... bundle_iterator tmp = *this; - do { - --MII; - } while (MII->isInsideBundle()); + --*this; return tmp; } bundle_iterator operator++(int) { // postincrement operators... bundle_iterator tmp = *this; - do { - ++MII; - } while (MII->isInsideBundle()); + ++*this; return tmp; } @@ -235,42 +230,14 @@ public: reverse_instr_iterator instr_rend () { return Insts.rend(); } const_reverse_instr_iterator instr_rend () const { return Insts.rend(); } - iterator begin() { return Insts.begin(); } - const_iterator begin() const { return Insts.begin(); } - iterator end() { - instr_iterator II = instr_end(); - if (II != instr_begin()) { - while (II->isInsideBundle()) - --II; - } - return II; - } - const_iterator end() const { - const_instr_iterator II = instr_end(); - if (II != instr_begin()) { - while (II->isInsideBundle()) - --II; - } - return II; - } - reverse_iterator rbegin() { - reverse_instr_iterator II = instr_rbegin(); - if (II != instr_rend()) { - while (II->isInsideBundle()) - ++II; - } - return II; - } - const_reverse_iterator rbegin() const { - const_reverse_instr_iterator II = instr_rbegin(); - if (II != instr_rend()) { - while (II->isInsideBundle()) - ++II; - } - return II; - } - reverse_iterator rend () { return Insts.rend(); } - const_reverse_iterator rend () const { return Insts.rend(); } + iterator begin() { return instr_begin(); } + const_iterator begin() const { return instr_begin(); } + iterator end () { return instr_end(); } + const_iterator end () const { return instr_end(); } + reverse_iterator rbegin() { return instr_rbegin(); } + const_reverse_iterator rbegin() const { return instr_rbegin(); } + reverse_iterator rend () { return instr_rend(); } + const_reverse_iterator rend () const { return instr_rend(); } // Machine-CFG iterators @@ -412,6 +379,10 @@ public: /// which refer to fromMBB to refer to this. void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *fromMBB); + /// isPredecessor - Return true if the specified MBB is a predecessor of this + /// block. + bool isPredecessor(const MachineBasicBlock *MBB) const; + /// isSuccessor - Return true if the specified MBB is a successor of this /// block. bool isSuccessor(const MachineBasicBlock *MBB) const; diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h index 44402a9..8b958e4 100644 --- a/include/llvm/CodeGen/MachineFrameInfo.h +++ b/include/llvm/CodeGen/MachineFrameInfo.h @@ -359,7 +359,7 @@ public: assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && "Invalid Object Idx!"); Objects[ObjectIdx+NumFixedObjects].Alignment = Align; - MaxAlignment = std::max(MaxAlignment, Align); + ensureMaxAlignment(Align); } /// NeedsStackProtector - Returns true if the object may need stack @@ -416,9 +416,11 @@ public: /// unsigned getMaxAlignment() const { return MaxAlignment; } - /// setMaxAlignment - Set the preferred alignment. - /// - void setMaxAlignment(unsigned Align) { MaxAlignment = Align; } + /// ensureMaxAlignment - Make sure the function is at least Align bytes + /// aligned. + void ensureMaxAlignment(unsigned Align) { + if (MaxAlignment < Align) MaxAlignment = Align; + } /// AdjustsStack - Return true if this function adjusts the stack -- e.g., /// when calling another function. This is only valid during and after @@ -485,7 +487,7 @@ public: Objects.push_back(StackObject(Size, Alignment, 0, false, isSS, MayNeedSP)); int Index = (int)Objects.size() - NumFixedObjects - 1; assert(Index >= 0 && "Bad frame index!"); - MaxAlignment = std::max(MaxAlignment, Alignment); + ensureMaxAlignment(Alignment); return Index; } @@ -496,7 +498,7 @@ public: int CreateSpillStackObject(uint64_t Size, unsigned Alignment) { CreateStackObject(Size, Alignment, true, false); int Index = (int)Objects.size() - NumFixedObjects - 1; - MaxAlignment = std::max(MaxAlignment, Alignment); + ensureMaxAlignment(Alignment); return Index; } @@ -515,7 +517,7 @@ public: int CreateVariableSizedObject(unsigned Alignment) { HasVarSizedObjects = true; Objects.push_back(StackObject(0, Alignment, 0, false, false, true)); - MaxAlignment = std::max(MaxAlignment, Alignment); + ensureMaxAlignment(Alignment); return (int)Objects.size()-NumFixedObjects-1; } diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h index dda2dc7..062c750 100644 --- a/include/llvm/CodeGen/MachineFunction.h +++ b/include/llvm/CodeGen/MachineFunction.h @@ -189,8 +189,8 @@ public: /// void setAlignment(unsigned A) { Alignment = A; } - /// EnsureAlignment - Make sure the function is at least 1 << A bytes aligned. - void EnsureAlignment(unsigned A) { + /// ensureAlignment - Make sure the function is at least 1 << A bytes aligned. + void ensureAlignment(unsigned A) { if (Alignment < A) Alignment = A; } diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index 65093d7..4c5eb8b 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -635,6 +635,30 @@ public: getOperand(0).getSubReg() == getOperand(1).getSubReg(); } + /// isTransient - Return true if this is a transient instruction that is + /// either very likely to be eliminated during register allocation (such as + /// copy-like instructions), or if this instruction doesn't have an + /// execution-time cost. + bool isTransient() const { + switch(getOpcode()) { + default: return false; + // Copy-like instructions are usually eliminated during register allocation. + case TargetOpcode::PHI: + case TargetOpcode::COPY: + case TargetOpcode::INSERT_SUBREG: + case TargetOpcode::SUBREG_TO_REG: + case TargetOpcode::REG_SEQUENCE: + // Pseudo-instructions that don't produce any real output. + case TargetOpcode::IMPLICIT_DEF: + case TargetOpcode::KILL: + case TargetOpcode::PROLOG_LABEL: + case TargetOpcode::EH_LABEL: + case TargetOpcode::GC_LABEL: + case TargetOpcode::DBG_VALUE: + return true; + } + } + /// getBundleSize - Return the number of instructions inside the MI bundle. unsigned getBundleSize() const; @@ -912,12 +936,12 @@ private: /// RemoveRegOperandsFromUseLists - Unlink all of the register operands in /// this instruction from their respective use lists. This requires that the /// operands already be on their use lists. - void RemoveRegOperandsFromUseLists(); + void RemoveRegOperandsFromUseLists(MachineRegisterInfo&); /// AddRegOperandsToUseLists - Add all of the register operands in /// this instruction from their respective use lists. This requires that the /// operands not be on their use lists yet. - void AddRegOperandsToUseLists(MachineRegisterInfo &RegInfo); + void AddRegOperandsToUseLists(MachineRegisterInfo&); /// hasPropertyInBundle - Slow path for hasProperty when we're dealing with a /// bundle. diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h index 99849a6..654361f 100644 --- a/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/include/llvm/CodeGen/MachineInstrBuilder.h @@ -34,6 +34,7 @@ namespace RegState { Undef = 0x20, EarlyClobber = 0x40, Debug = 0x80, + InternalRead = 0x100, DefineNoRead = Define | Undef, ImplicitDefine = Implicit | Define, ImplicitKill = Implicit | Kill @@ -67,7 +68,8 @@ public: flags & RegState::Undef, flags & RegState::EarlyClobber, SubReg, - flags & RegState::Debug)); + flags & RegState::Debug, + flags & RegState::InternalRead)); return *this; } @@ -106,6 +108,12 @@ public: return *this; } + const MachineInstrBuilder &addTargetIndex(unsigned Idx, int64_t Offset = 0, + unsigned char TargetFlags = 0) const { + MI->addOperand(MachineOperand::CreateTargetIndex(Idx, Offset, TargetFlags)); + return *this; + } + const MachineInstrBuilder &addJumpTableIndex(unsigned Idx, unsigned char TargetFlags = 0) const { MI->addOperand(MachineOperand::CreateJTI(Idx, TargetFlags)); @@ -310,6 +318,9 @@ inline unsigned getDeadRegState(bool B) { inline unsigned getUndefRegState(bool B) { return B ? RegState::Undef : 0; } +inline unsigned getInternalReadRegState(bool B) { + return B ? RegState::InternalRead : 0; +} } // End llvm namespace diff --git a/include/llvm/CodeGen/MachineInstrBundle.h b/include/llvm/CodeGen/MachineInstrBundle.h index 0fb4969..dc5f9a6 100644 --- a/include/llvm/CodeGen/MachineInstrBundle.h +++ b/include/llvm/CodeGen/MachineInstrBundle.h @@ -43,14 +43,14 @@ bool finalizeBundles(MachineFunction &MF); /// getBundleStart - Returns the first instruction in the bundle containing MI. /// -static inline MachineInstr *getBundleStart(MachineInstr *MI) { +inline MachineInstr *getBundleStart(MachineInstr *MI) { MachineBasicBlock::instr_iterator I = MI; while (I->isInsideBundle()) --I; return I; } -static inline const MachineInstr *getBundleStart(const MachineInstr *MI) { +inline const MachineInstr *getBundleStart(const MachineInstr *MI) { MachineBasicBlock::const_instr_iterator I = MI; while (I->isInsideBundle()) --I; diff --git a/include/llvm/CodeGen/MachineJumpTableInfo.h b/include/llvm/CodeGen/MachineJumpTableInfo.h index 6bd6682..f7c4e86 100644 --- a/include/llvm/CodeGen/MachineJumpTableInfo.h +++ b/include/llvm/CodeGen/MachineJumpTableInfo.h @@ -10,9 +10,9 @@ // The MachineJumpTableInfo class keeps track of jump tables referenced by // lowered switch instructions in the MachineFunction. // -// Instructions reference the address of these jump tables through the use of -// MO_JumpTableIndex values. When emitting assembly or machine code, these -// virtual address references are converted to refer to the address of the +// Instructions reference the address of these jump tables through the use of +// MO_JumpTableIndex values. When emitting assembly or machine code, these +// virtual address references are converted to refer to the address of the // function jump tables. // //===----------------------------------------------------------------------===// @@ -34,11 +34,11 @@ class raw_ostream; struct MachineJumpTableEntry { /// MBBs - The vector of basic blocks from which to create the jump table. std::vector<MachineBasicBlock*> MBBs; - + explicit MachineJumpTableEntry(const std::vector<MachineBasicBlock*> &M) : MBBs(M) {} }; - + class MachineJumpTableInfo { public: /// JTEntryKind - This enum indicates how each entry of the jump table is @@ -57,7 +57,7 @@ public: /// with a relocation as gp-relative, e.g.: /// .gprel32 LBB123 EK_GPRel32BlockAddress, - + /// EK_LabelDifference32 - Each entry is the address of the block minus /// the address of the jump table. This is used for PIC jump tables where /// gprel32 is not supported. e.g.: @@ -80,18 +80,18 @@ private: std::vector<MachineJumpTableEntry> JumpTables; public: explicit MachineJumpTableInfo(JTEntryKind Kind): EntryKind(Kind) {} - + JTEntryKind getEntryKind() const { return EntryKind; } /// getEntrySize - Return the size of each entry in the jump table. unsigned getEntrySize(const TargetData &TD) const; /// getEntryAlignment - Return the alignment of each entry in the jump table. unsigned getEntryAlignment(const TargetData &TD) const; - + /// createJumpTableIndex - Create a new jump table. /// unsigned createJumpTableIndex(const std::vector<MachineBasicBlock*> &DestBBs); - + /// isEmpty - Return true if there are no jump tables. /// bool isEmpty() const { return JumpTables.empty(); } @@ -105,7 +105,7 @@ public: void RemoveJumpTable(unsigned Idx) { JumpTables[Idx].MBBs.clear(); } - + /// ReplaceMBBInJumpTables - If Old is the target of any jump tables, update /// the jump tables to branch to New instead. bool ReplaceMBBInJumpTables(MachineBasicBlock *Old, MachineBasicBlock *New); diff --git a/include/llvm/CodeGen/MachineLoopInfo.h b/include/llvm/CodeGen/MachineLoopInfo.h index 6dd9440..3e204be 100644 --- a/include/llvm/CodeGen/MachineLoopInfo.h +++ b/include/llvm/CodeGen/MachineLoopInfo.h @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file defines the MachineLoopInfo class that is used to identify natural +// This file defines the MachineLoopInfo class that is used to identify natural // loops and determine the loop depth of various nodes of the CFG. Note that // natural loops may actually be several loops that share the same header node. // @@ -35,6 +35,12 @@ namespace llvm { +// Implementation in LoopInfoImpl.h +#ifdef __GNUC__ +class MachineLoop; +__extension__ extern template class LoopBase<MachineBasicBlock, MachineLoop>; +#endif + class MachineLoop : public LoopBase<MachineBasicBlock, MachineLoop> { public: MachineLoop(); @@ -57,6 +63,12 @@ private: : LoopBase<MachineBasicBlock, MachineLoop>(MBB) {} }; +// Implementation in LoopInfoImpl.h +#ifdef __GNUC__ +__extension__ extern template +class LoopInfoBase<MachineBasicBlock, MachineLoop>; +#endif + class MachineLoopInfo : public MachineFunctionPass { LoopInfoBase<MachineBasicBlock, MachineLoop> LI; friend class LoopBase<MachineBasicBlock, MachineLoop>; diff --git a/include/llvm/CodeGen/MachineOperand.h b/include/llvm/CodeGen/MachineOperand.h index d244dd9..37d42b3 100644 --- a/include/llvm/CodeGen/MachineOperand.h +++ b/include/llvm/CodeGen/MachineOperand.h @@ -14,6 +14,7 @@ #ifndef LLVM_CODEGEN_MACHINEOPERAND_H #define LLVM_CODEGEN_MACHINEOPERAND_H +#include "llvm/ADT/Hashing.h" #include "llvm/Support/DataTypes.h" #include <cassert> @@ -44,6 +45,7 @@ public: MO_MachineBasicBlock, ///< MachineBasicBlock reference MO_FrameIndex, ///< Abstract Stack Frame Index MO_ConstantPoolIndex, ///< Address of indexed Constant in Constant Pool + MO_TargetIndex, ///< Target-dependent index+offset operand. MO_JumpTableIndex, ///< Address of indexed Jump Table for switch MO_ExternalSymbol, ///< Name of external global symbol MO_GlobalAddress, ///< Address of a global value @@ -148,7 +150,7 @@ private: struct { // For MO_Register. // Register number is in SmallContents.RegNo. - MachineOperand **Prev; // Access list for register. + MachineOperand *Prev; // Access list for register. See MRI. MachineOperand *Next; } Reg; @@ -214,6 +216,8 @@ public: bool isFI() const { return OpKind == MO_FrameIndex; } /// isCPI - Tests if this is a MO_ConstantPoolIndex operand. bool isCPI() const { return OpKind == MO_ConstantPoolIndex; } + /// isTargetIndex - Tests if this is a MO_TargetIndex operand. + bool isTargetIndex() const { return OpKind == MO_TargetIndex; } /// isJTI - Tests if this is a MO_JumpTableIndex operand. bool isJTI() const { return OpKind == MO_JumpTableIndex; } /// isGlobal - Tests if this is a MO_GlobalAddress operand. @@ -301,13 +305,6 @@ public: return !isUndef() && !isInternalRead() && (isUse() || getSubReg()); } - /// getNextOperandForReg - Return the next MachineOperand in the function that - /// uses or defines this register. - MachineOperand *getNextOperandForReg() const { - assert(isReg() && "This is not a register operand!"); - return Contents.Reg.Next; - } - //===--------------------------------------------------------------------===// // Mutators for Register Operands //===--------------------------------------------------------------------===// @@ -334,17 +331,9 @@ public: /// void substPhysReg(unsigned Reg, const TargetRegisterInfo&); - void setIsUse(bool Val = true) { - assert(isReg() && "Wrong MachineOperand accessor"); - assert((Val || !isDebug()) && "Marking a debug operation as def"); - IsDef = !Val; - } + void setIsUse(bool Val = true) { setIsDef(!Val); } - void setIsDef(bool Val = true) { - assert(isReg() && "Wrong MachineOperand accessor"); - assert((!Val || !isDebug()) && "Marking a debug operation as def"); - IsDef = Val; - } + void setIsDef(bool Val = true); void setImplicit(bool Val = true) { assert(isReg() && "Wrong MachineOperand accessor"); @@ -407,7 +396,7 @@ public: } int getIndex() const { - assert((isFI() || isCPI() || isJTI()) && + assert((isFI() || isCPI() || isTargetIndex() || isJTI()) && "Wrong MachineOperand accessor"); return Contents.OffsetedInfo.Val.Index; } @@ -430,8 +419,8 @@ public: /// getOffset - Return the offset from the symbol in this operand. This always /// returns 0 for ExternalSymbol operands. int64_t getOffset() const { - assert((isGlobal() || isSymbol() || isCPI() || isBlockAddress()) && - "Wrong MachineOperand accessor"); + assert((isGlobal() || isSymbol() || isCPI() || isTargetIndex() || + isBlockAddress()) && "Wrong MachineOperand accessor"); return (int64_t(Contents.OffsetedInfo.OffsetHi) << 32) | SmallContents.OffsetLo; } @@ -478,14 +467,14 @@ public: } void setOffset(int64_t Offset) { - assert((isGlobal() || isSymbol() || isCPI() || isBlockAddress()) && - "Wrong MachineOperand accessor"); + assert((isGlobal() || isSymbol() || isCPI() || isTargetIndex() || + isBlockAddress()) && "Wrong MachineOperand accessor"); SmallContents.OffsetLo = unsigned(Offset); Contents.OffsetedInfo.OffsetHi = int(Offset >> 32); } void setIndex(int Idx) { - assert((isFI() || isCPI() || isJTI()) && + assert((isFI() || isCPI() || isTargetIndex() || isJTI()) && "Wrong MachineOperand accessor"); Contents.OffsetedInfo.Val.Index = Idx; } @@ -503,6 +492,13 @@ public: /// operand. Note: This method ignores isKill and isDead properties. bool isIdenticalTo(const MachineOperand &Other) const; + /// \brief MachineOperand hash_value overload. + /// + /// Note that this includes the same information in the hash that + /// isIdenticalTo uses for comparison. It is thus suited for use in hash + /// tables which use that function for equality comparisons only. + friend hash_code hash_value(const MachineOperand &MO); + /// ChangeToImmediate - Replace this operand with a new immediate operand of /// the specified value. If an operand is known to be an immediate already, /// the setImm method should be used. @@ -542,14 +538,15 @@ public: bool isUndef = false, bool isEarlyClobber = false, unsigned SubReg = 0, - bool isDebug = false) { + bool isDebug = false, + bool isInternalRead = false) { MachineOperand Op(MachineOperand::MO_Register); Op.IsDef = isDef; Op.IsImp = isImp; Op.IsKill = isKill; Op.IsDead = isDead; Op.IsUndef = isUndef; - Op.IsInternalRead = false; + Op.IsInternalRead = isInternalRead; Op.IsEarlyClobber = isEarlyClobber; Op.IsDebug = isDebug; Op.SmallContents.RegNo = Reg; @@ -578,6 +575,14 @@ public: Op.setTargetFlags(TargetFlags); return Op; } + static MachineOperand CreateTargetIndex(unsigned Idx, int64_t Offset, + unsigned char TargetFlags = 0) { + MachineOperand Op(MachineOperand::MO_TargetIndex); + Op.setIndex(Idx); + Op.setOffset(Offset); + Op.setTargetFlags(TargetFlags); + return Op; + } static MachineOperand CreateJTI(unsigned Idx, unsigned char TargetFlags = 0) { MachineOperand Op(MachineOperand::MO_JumpTableIndex); @@ -653,15 +658,6 @@ private: assert(isReg() && "Can only add reg operand to use lists"); return Contents.Reg.Prev != 0; } - - /// AddRegOperandToRegInfo - Add this register operand to the specified - /// MachineRegisterInfo. If it is null, then the next/prev fields should be - /// explicitly nulled out. - void AddRegOperandToRegInfo(MachineRegisterInfo *RegInfo); - - /// RemoveRegOperandFromRegInfo - Remove this register operand from the - /// MachineRegisterInfo it is linked with. - void RemoveRegOperandFromRegInfo(); }; inline raw_ostream &operator<<(raw_ostream &OS, const MachineOperand& MO) { diff --git a/include/llvm/CodeGen/MachinePassRegistry.h b/include/llvm/CodeGen/MachinePassRegistry.h index c41e8e26..90ee7f4 100644 --- a/include/llvm/CodeGen/MachinePassRegistry.h +++ b/include/llvm/CodeGen/MachinePassRegistry.h @@ -26,7 +26,7 @@ namespace llvm { typedef void *(*MachinePassCtor)(); -//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// /// /// MachinePassRegistryListener - Listener to adds and removals of nodes in /// registration list. @@ -42,7 +42,7 @@ public: }; -//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// /// /// MachinePassRegistryNode - Machine pass node stored in registration list. /// @@ -55,7 +55,7 @@ private: const char *Name; // Name of function pass. const char *Description; // Description string. MachinePassCtor Ctor; // Function pass creator. - + public: MachinePassRegistryNode(const char *N, const char *D, MachinePassCtor C) @@ -72,11 +72,11 @@ public: const char *getDescription() const { return Description; } MachinePassCtor getCtor() const { return Ctor; } void setNext(MachinePassRegistryNode *N) { Next = N; } - + }; -//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// /// /// MachinePassRegistry - Track the registration of machine passes. /// @@ -88,7 +88,7 @@ private: MachinePassRegistryNode *List; // List of registry nodes. MachinePassCtor Default; // Default function pass creator. MachinePassRegistryListener* Listener;// Listener for list adds are removes. - + public: // NO CONSTRUCTOR - we don't want static constructor ordering to mess @@ -99,6 +99,7 @@ public: MachinePassRegistryNode *getList() { return List; } MachinePassCtor getDefault() { return Default; } void setDefault(MachinePassCtor C) { Default = C; } + void setDefault(StringRef Name); void setListener(MachinePassRegistryListener *L) { Listener = L; } /// Add - Adds a function pass to the registration list. @@ -126,7 +127,7 @@ public: void initialize(cl::Option &O) { cl::parser<typename RegistryClass::FunctionPassCtor>::initialize(O); - + // Add existing passes to option. for (RegistryClass *Node = RegistryClass::getList(); Node; Node = Node->getNext()) { @@ -134,7 +135,7 @@ public: (typename RegistryClass::FunctionPassCtor)Node->getCtor(), Node->getDescription()); } - + // Make sure we listen for list changes. RegistryClass::setListener(this); } diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h index 3272fbd..42a8aa4 100644 --- a/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/include/llvm/CodeGen/MachineRegisterInfo.h @@ -57,6 +57,26 @@ class MachineRegisterInfo { /// physical registers. MachineOperand **PhysRegUseDefLists; + /// getRegUseDefListHead - Return the head pointer for the register use/def + /// list for the specified virtual or physical register. + MachineOperand *&getRegUseDefListHead(unsigned RegNo) { + if (TargetRegisterInfo::isVirtualRegister(RegNo)) + return VRegInfo[RegNo].second; + return PhysRegUseDefLists[RegNo]; + } + + MachineOperand *getRegUseDefListHead(unsigned RegNo) const { + if (TargetRegisterInfo::isVirtualRegister(RegNo)) + return VRegInfo[RegNo].second; + return PhysRegUseDefLists[RegNo]; + } + + /// Get the next element in the use-def chain. + static MachineOperand *getNextOperandForReg(const MachineOperand *MO) { + assert(MO && MO->isReg() && "This is not a register operand!"); + return MO->Contents.Reg.Next; + } + /// UsedPhysRegs - This is a bit vector that is computed and set by the /// register allocator, and must be kept up to date by passes that run after /// register allocation (though most don't modify this). This is used @@ -129,12 +149,21 @@ public: // Register Info //===--------------------------------------------------------------------===// + // Strictly for use by MachineInstr.cpp. + void addRegOperandToUseList(MachineOperand *MO); + + // Strictly for use by MachineInstr.cpp. + void removeRegOperandFromUseList(MachineOperand *MO); + /// reg_begin/reg_end - Provide iteration support to walk over all definitions /// and uses of a register within the MachineFunction that corresponds to this /// MachineRegisterInfo object. template<bool Uses, bool Defs, bool SkipDebug> class defusechain_iterator; + // Make it a friend so it can access getNextOperandForReg(). + template<bool, bool, bool> friend class defusechain_iterator; + /// reg_iterator/reg_begin/reg_end - Walk all defs and uses of the specified /// register. typedef defusechain_iterator<true,true,false> reg_iterator; @@ -172,6 +201,15 @@ public: /// specified register (it may be live-in). bool def_empty(unsigned RegNo) const { return def_begin(RegNo) == def_end(); } + /// hasOneDef - Return true if there is exactly one instruction defining the + /// specified register. + bool hasOneDef(unsigned RegNo) const { + def_iterator DI = def_begin(RegNo); + if (DI == def_end()) + return false; + return ++DI == def_end(); + } + /// use_iterator/use_begin/use_end - Walk all uses of the specified register. typedef defusechain_iterator<true,false,false> use_iterator; use_iterator use_begin(unsigned RegNo) const { @@ -185,7 +223,12 @@ public: /// hasOneUse - Return true if there is exactly one instruction using the /// specified register. - bool hasOneUse(unsigned RegNo) const; + bool hasOneUse(unsigned RegNo) const { + use_iterator UI = use_begin(RegNo); + if (UI == use_end()) + return false; + return ++UI == use_end(); + } /// use_nodbg_iterator/use_nodbg_begin/use_nodbg_end - Walk all uses of the /// specified register, skipping those marked as Debug. @@ -218,25 +261,16 @@ public: /// constraints. void replaceRegWith(unsigned FromReg, unsigned ToReg); - /// getRegUseDefListHead - Return the head pointer for the register use/def - /// list for the specified virtual or physical register. - MachineOperand *&getRegUseDefListHead(unsigned RegNo) { - if (TargetRegisterInfo::isVirtualRegister(RegNo)) - return VRegInfo[RegNo].second; - return PhysRegUseDefLists[RegNo]; - } - - MachineOperand *getRegUseDefListHead(unsigned RegNo) const { - if (TargetRegisterInfo::isVirtualRegister(RegNo)) - return VRegInfo[RegNo].second; - return PhysRegUseDefLists[RegNo]; - } - /// getVRegDef - Return the machine instr that defines the specified virtual /// register or null if none is found. This assumes that the code is in SSA /// form, so there should only be one definition. MachineInstr *getVRegDef(unsigned Reg) const; + /// getUniqueVRegDef - Return the unique machine instr that defines the + /// specified virtual register or null if none is found. If there are + /// multiple definitions or no definition, return null. + MachineInstr *getUniqueVRegDef(unsigned Reg) const; + /// clearKillFlags - Iterate over all the uses of the given register and /// clear the kill flag from the MachineOperand. This function is used by /// optimization passes which extend register lifetimes and need only @@ -336,7 +370,7 @@ public: bool isPhysRegOrOverlapUsed(unsigned Reg) const { if (UsedPhysRegMask.test(Reg)) return true; - for (const uint16_t *AI = TRI->getOverlaps(Reg); *AI; ++AI) + for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) if (UsedPhysRegs.test(*AI)) return true; return false; @@ -434,10 +468,6 @@ public: const TargetRegisterInfo &TRI, const TargetInstrInfo &TII); -private: - void HandleVRegListReallocation(); - -public: /// defusechain_iterator - This class provides iterator support for machine /// operands in the function that use or define a specific register. If /// ReturnUses is true it returns uses of registers, if ReturnDefs is true it @@ -481,13 +511,22 @@ public: // Iterator traversal: forward iteration only defusechain_iterator &operator++() { // Preincrement assert(Op && "Cannot increment end iterator!"); - Op = Op->getNextOperandForReg(); - - // If this is an operand we don't care about, skip it. - while (Op && ((!ReturnUses && Op->isUse()) || - (!ReturnDefs && Op->isDef()) || - (SkipDebug && Op->isDebug()))) - Op = Op->getNextOperandForReg(); + Op = getNextOperandForReg(Op); + + // All defs come before the uses, so stop def_iterator early. + if (!ReturnUses) { + if (Op) { + if (Op->isUse()) + Op = 0; + else + assert(!Op->isDebug() && "Can't have debug defs"); + } + } else { + // If this is an operand we don't care about, skip it. + while (Op && ((!ReturnDefs && Op->isDef()) || + (SkipDebug && Op->isDebug()))) + Op = getNextOperandForReg(Op); + } return *this; } diff --git a/include/llvm/CodeGen/MachineScheduler.h b/include/llvm/CodeGen/MachineScheduler.h index e852009..8da2045 100644 --- a/include/llvm/CodeGen/MachineScheduler.h +++ b/include/llvm/CodeGen/MachineScheduler.h @@ -19,7 +19,7 @@ // createCustomMachineSched); // // Inside <Target>PassConfig: -// enablePass(MachineSchedulerID); +// enablePass(&MachineSchedulerID); // MachineSchedRegistry::setDefault(createCustomMachineSched); // //===----------------------------------------------------------------------===// @@ -35,6 +35,7 @@ class AliasAnalysis; class LiveIntervals; class MachineDominatorTree; class MachineLoopInfo; +class RegisterClassInfo; class ScheduleDAGInstrs; /// MachineSchedContext provides enough context from the MachineScheduler pass @@ -47,7 +48,10 @@ struct MachineSchedContext { AliasAnalysis *AA; LiveIntervals *LIS; - MachineSchedContext(): MF(0), MLI(0), MDT(0), PassConfig(0), AA(0), LIS(0) {} + RegisterClassInfo *RegClassInfo; + + MachineSchedContext(); + virtual ~MachineSchedContext(); }; /// MachineSchedRegistry provides a selection of available machine instruction @@ -81,6 +85,9 @@ public: static void setDefault(ScheduleDAGCtor C) { Registry.setDefault((MachinePassCtor)C); } + static void setDefault(StringRef Name) { + Registry.setDefault(Name); + } static void setListener(MachinePassRegistryListener *L) { Registry.setListener(L); } diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index e76fe99..07b3b45 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -24,6 +24,7 @@ namespace llvm { class FunctionPass; class MachineFunctionPass; class PassInfo; + class PassManagerBase; class TargetLowering; class TargetRegisterClass; class raw_ostream; @@ -31,8 +32,6 @@ namespace llvm { namespace llvm { -extern char &NoPassID; // Allow targets to choose not to run a pass. - class PassConfigImpl; /// Target-Independent Code Generator Pass Configuration Options. @@ -54,9 +53,15 @@ public: /// optimization after regalloc. static char PostRAMachineLICMID; +private: + PassManagerBase *PM; + AnalysisID StartAfter; + AnalysisID StopAfter; + bool Started; + bool Stopped; + protected: TargetMachine *TM; - PassManagerBase *PM; PassConfigImpl *Impl; // Internal data structures bool Initialized; // Flagged after all passes are configured. @@ -91,6 +96,18 @@ public: CodeGenOpt::Level getOptLevel() const { return TM->getOptLevel(); } + /// setStartStopPasses - Set the StartAfter and StopAfter passes to allow + /// running only a portion of the normal code-gen pass sequence. If the + /// Start pass ID is zero, then compilation will begin at the normal point; + /// otherwise, clear the Started flag to indicate that passes should not be + /// added until the starting pass is seen. If the Stop pass ID is zero, + /// then compilation will continue to the end. + void setStartStopPasses(AnalysisID Start, AnalysisID Stop) { + StartAfter = Start; + StopAfter = Stop; + Started = (StartAfter == 0); + } + void setDisableVerify(bool Disable) { setOpt(DisableVerify, Disable); } bool getEnableTailMerge() const { return EnableTailMerge; } @@ -98,16 +115,19 @@ public: /// Allow the target to override a specific pass without overriding the pass /// pipeline. When passes are added to the standard pipeline at the - /// point where StadardID is expected, add TargetID in its place. - void substitutePass(char &StandardID, char &TargetID); + /// point where StandardID is expected, add TargetID in its place. + void substitutePass(AnalysisID StandardID, AnalysisID TargetID); + + /// Insert InsertedPassID pass after TargetPassID pass. + void insertPass(AnalysisID TargetPassID, AnalysisID InsertedPassID); /// Allow the target to enable a specific standard pass by default. - void enablePass(char &ID) { substitutePass(ID, ID); } + void enablePass(AnalysisID PassID) { substitutePass(PassID, PassID); } /// Allow the target to disable a specific standard pass by default. - void disablePass(char &ID) { substitutePass(ID, NoPassID); } + void disablePass(AnalysisID PassID) { substitutePass(PassID, 0); } - /// Return the pass ssubtituted for StandardID by the target. + /// Return the pass substituted for StandardID by the target. /// If no substitution exists, return StandardID. AnalysisID getPassSubstitution(AnalysisID StandardID) const; @@ -118,6 +138,9 @@ public: /// transforms following machine independent optimization. virtual void addIRPasses(); + /// Add passes to lower exception handling for the code generator. + void addPassesToHandleExceptions(); + /// Add common passes that perform LLVM IR to IR transforms in preparation for /// instruction selection. virtual void addISelPrepare(); @@ -172,6 +195,18 @@ protected: /// LLVMTargetMachine provides standard regalloc passes for most targets. virtual void addOptimizedRegAlloc(FunctionPass *RegAllocPass); + /// addPreRewrite - Add passes to the optimized register allocation pipeline + /// after register allocation is complete, but before virtual registers are + /// rewritten to physical registers. + /// + /// These passes must preserve VirtRegMap and LiveIntervals, and when running + /// after RABasic or RAGreedy, they should take advantage of LiveRegMatrix. + /// When these passes run, VirtRegMap contains legal physreg assignments for + /// all virtual registers. + virtual bool addPreRewrite() { + return false; + } + /// addFinalizeRegAlloc - This method may be implemented by targets that want /// to run passes within the regalloc pipeline, immediately after the register /// allocation pass itself. These passes run as soon as virtual regisiters @@ -216,8 +251,12 @@ protected: /// /// Add a CodeGen pass at this point in the pipeline after checking overrides. - /// Return the pass that was added, or NoPassID. - AnalysisID addPass(char &ID); + /// Return the pass that was added, or zero if no pass was added. + AnalysisID addPass(AnalysisID PassID); + + /// Add a pass to the PassManager if that pass is supposed to be run, as + /// determined by the StartAfter and StopAfter options. + void addPass(Pass *P); /// addMachinePasses helper to create the target-selected or overriden /// regalloc pass. @@ -226,7 +265,7 @@ protected: /// printAndVerify - Add a pass to dump then verify the machine function, if /// those steps are enabled. /// - void printAndVerify(const char *Banner) const; + void printAndVerify(const char *Banner); }; } // namespace llvm @@ -276,6 +315,10 @@ namespace llvm { /// This pass is still in development extern char &StrongPHIEliminationID; + /// LiveIntervals - This analysis keeps track of the live ranges of virtual + /// and physical registers. + extern char &LiveIntervalsID; + /// LiveStacks pass. An analysis keeping track of the liveness of stack slots. extern char &LiveStacksID; @@ -297,6 +340,10 @@ namespace llvm { /// basic blocks. extern char &SpillPlacementID; + /// VirtRegRewriter pass. Rewrite virtual registers to physical registers as + /// assigned in VirtRegMap. + extern char &VirtRegRewriterID; + /// UnreachableMachineBlockElimination - This pass removes unreachable /// machine basic blocks. extern char &UnreachableMachineBlockElimID; @@ -342,10 +389,21 @@ namespace llvm { /// branches. extern char &BranchFolderPassID; + /// MachineFunctionPrinterPass - This pass prints out MachineInstr's. + extern char &MachineFunctionPrinterPassID; + /// TailDuplicate - Duplicate blocks with unconditional branches /// into tails of their predecessors. extern char &TailDuplicateID; + /// MachineTraceMetrics - This pass computes critical path and CPU resource + /// usage in an ensemble of traces. + extern char &MachineTraceMetricsID; + + /// EarlyIfConverter - This pass performs if-conversion on SSA form by + /// inserting cmov instructions. + extern char &EarlyIfConverterID; + /// IfConverter - This pass performs machine code if conversion. extern char &IfConverterID; diff --git a/include/llvm/CodeGen/ProcessImplicitDefs.h b/include/llvm/CodeGen/ProcessImplicitDefs.h deleted file mode 100644 index 6ab57f0..0000000 --- a/include/llvm/CodeGen/ProcessImplicitDefs.h +++ /dev/null @@ -1,51 +0,0 @@ -//===-------------- llvm/CodeGen/ProcessImplicitDefs.h ----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - - -#ifndef LLVM_CODEGEN_PROCESSIMPLICITDEFS_H -#define LLVM_CODEGEN_PROCESSIMPLICITDEFS_H - -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/ADT/SmallSet.h" - -namespace llvm { - - class MachineInstr; - class TargetInstrInfo; - class TargetRegisterInfo; - class MachineRegisterInfo; - class LiveVariables; - - /// Process IMPLICIT_DEF instructions and make sure there is one implicit_def - /// for each use. Add isUndef marker to implicit_def defs and their uses. - class ProcessImplicitDefs : public MachineFunctionPass { - const TargetInstrInfo *TII; - const TargetRegisterInfo *TRI; - MachineRegisterInfo *MRI; - LiveVariables *LV; - - bool CanTurnIntoImplicitDef(MachineInstr *MI, unsigned Reg, - unsigned OpIdx, - SmallSet<unsigned, 8> &ImpDefRegs); - - public: - static char ID; - - ProcessImplicitDefs() : MachineFunctionPass(ID) { - initializeProcessImplicitDefsPass(*PassRegistry::getPassRegistry()); - } - - virtual void getAnalysisUsage(AnalysisUsage &au) const; - - virtual bool runOnMachineFunction(MachineFunction &fn); - }; - -} - -#endif // LLVM_CODEGEN_PROCESSIMPLICITDEFS_H diff --git a/include/llvm/CodeGen/RegisterClassInfo.h b/include/llvm/CodeGen/RegisterClassInfo.h new file mode 100644 index 0000000..400e1f4 --- /dev/null +++ b/include/llvm/CodeGen/RegisterClassInfo.h @@ -0,0 +1,132 @@ +//===-- RegisterClassInfo.h - Dynamic Register Class 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 implements the RegisterClassInfo class which provides dynamic +// information about target register classes. Callee saved and reserved +// registers depends on calling conventions and other dynamic information, so +// some things cannot be determined statically. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_REGISTERCLASSINFO_H +#define LLVM_CODEGEN_REGISTERCLASSINFO_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/Target/TargetRegisterInfo.h" + +namespace llvm { + +class RegisterClassInfo { + struct RCInfo { + unsigned Tag; + unsigned NumRegs; + bool ProperSubClass; + OwningArrayPtr<unsigned> Order; + + RCInfo() : Tag(0), NumRegs(0), ProperSubClass(false) {} + operator ArrayRef<unsigned>() const { + return makeArrayRef(Order.get(), NumRegs); + } + }; + + // Brief cached information for each register class. + OwningArrayPtr<RCInfo> RegClass; + + // Tag changes whenever cached information needs to be recomputed. An RCInfo + // entry is valid when its tag matches. + unsigned Tag; + + const MachineFunction *MF; + const TargetRegisterInfo *TRI; + + // Callee saved registers of last MF. Assumed to be valid until the next + // runOnFunction() call. + const uint16_t *CalleeSaved; + + // Map register number to CalleeSaved index + 1; + SmallVector<uint8_t, 4> CSRNum; + + // Reserved registers in the current MF. + BitVector Reserved; + + // Compute all information about RC. + void compute(const TargetRegisterClass *RC) const; + + // Return an up-to-date RCInfo for RC. + const RCInfo &get(const TargetRegisterClass *RC) const { + const RCInfo &RCI = RegClass[RC->getID()]; + if (Tag != RCI.Tag) + compute(RC); + return RCI; + } + +public: + RegisterClassInfo(); + + /// runOnFunction - Prepare to answer questions about MF. This must be called + /// before any other methods are used. + void runOnMachineFunction(const MachineFunction &MF); + + /// getNumAllocatableRegs - Returns the number of actually allocatable + /// registers in RC in the current function. + unsigned getNumAllocatableRegs(const TargetRegisterClass *RC) const { + return get(RC).NumRegs; + } + + /// getOrder - Returns the preferred allocation order for RC. The order + /// contains no reserved registers, and registers that alias callee saved + /// registers come last. + ArrayRef<unsigned> getOrder(const TargetRegisterClass *RC) const { + return get(RC); + } + + /// isProperSubClass - Returns true if RC has a legal super-class with more + /// allocatable registers. + /// + /// Register classes like GR32_NOSP are not proper sub-classes because %esp + /// is not allocatable. Similarly, tGPR is not a proper sub-class in Thumb + /// mode because the GPR super-class is not legal. + bool isProperSubClass(const TargetRegisterClass *RC) const { + return get(RC).ProperSubClass; + } + + /// getLastCalleeSavedAlias - Returns the last callee saved register that + /// overlaps PhysReg, or 0 if Reg doesn't overlap a CSR. + unsigned getLastCalleeSavedAlias(unsigned PhysReg) const { + assert(TargetRegisterInfo::isPhysicalRegister(PhysReg)); + if (unsigned N = CSRNum[PhysReg]) + return CalleeSaved[N-1]; + return 0; + } + + /// isReserved - Returns true when PhysReg is a reserved register. + /// + /// Reserved registers may belong to an allocatable register class, but the + /// target has explicitly requested that they are not used. + /// + bool isReserved(unsigned PhysReg) const { + return Reserved.test(PhysReg); + } + + /// isAllocatable - Returns true when PhysReg belongs to an allocatable + /// register class and it hasn't been reserved. + /// + /// Allocatable registers may show up in the allocation order of some virtual + /// register, so a register allocator needs to track its liveness and + /// availability. + bool isAllocatable(unsigned PhysReg) const { + return TRI->isInAllocatableClass(PhysReg) && !isReserved(PhysReg); + } +}; +} // end namespace llvm + +#endif + diff --git a/include/llvm/CodeGen/RegisterPressure.h b/include/llvm/CodeGen/RegisterPressure.h new file mode 100644 index 0000000..2043155 --- /dev/null +++ b/include/llvm/CodeGen/RegisterPressure.h @@ -0,0 +1,282 @@ +//===-- RegisterPressure.h - Dynamic Register Pressure -*- 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 RegisterPressure class which can be used to track +// MachineInstr level register pressure. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_REGISTERPRESSURE_H +#define LLVM_CODEGEN_REGISTERPRESSURE_H + +#include "llvm/CodeGen/SlotIndexes.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/ADT/SparseSet.h" + +namespace llvm { + +class LiveIntervals; +class RegisterClassInfo; +class MachineInstr; + +/// Base class for register pressure results. +struct RegisterPressure { + /// Map of max reg pressure indexed by pressure set ID, not class ID. + std::vector<unsigned> MaxSetPressure; + + /// List of live in registers. + SmallVector<unsigned,8> LiveInRegs; + SmallVector<unsigned,8> LiveOutRegs; + + /// Increase register pressure for each pressure set impacted by this register + /// class. Normally called by RegPressureTracker, but may be called manually + /// to account for live through (global liveness). + void increase(const TargetRegisterClass *RC, const TargetRegisterInfo *TRI); + + /// Decrease register pressure for each pressure set impacted by this register + /// class. This is only useful to account for spilling or rematerialization. + void decrease(const TargetRegisterClass *RC, const TargetRegisterInfo *TRI); + + void dump(const TargetRegisterInfo *TRI); +}; + +/// RegisterPressure computed within a region of instructions delimited by +/// TopIdx and BottomIdx. During pressure computation, the maximum pressure per +/// register pressure set is increased. Once pressure within a region is fully +/// computed, the live-in and live-out sets are recorded. +/// +/// This is preferable to RegionPressure when LiveIntervals are available, +/// because delimiting regions by SlotIndex is more robust and convenient than +/// holding block iterators. The block contents can change without invalidating +/// the pressure result. +struct IntervalPressure : RegisterPressure { + /// Record the boundary of the region being tracked. + SlotIndex TopIdx; + SlotIndex BottomIdx; + + void reset(); + + void openTop(SlotIndex NextTop); + + void openBottom(SlotIndex PrevBottom); +}; + +/// RegisterPressure computed within a region of instructions delimited by +/// TopPos and BottomPos. This is a less precise version of IntervalPressure for +/// use when LiveIntervals are unavailable. +struct RegionPressure : RegisterPressure { + /// Record the boundary of the region being tracked. + MachineBasicBlock::const_iterator TopPos; + MachineBasicBlock::const_iterator BottomPos; + + void reset(); + + void openTop(MachineBasicBlock::const_iterator PrevTop); + + void openBottom(MachineBasicBlock::const_iterator PrevBottom); +}; + +/// An element of pressure difference that identifies the pressure set and +/// amount of increase or decrease in units of pressure. +struct PressureElement { + unsigned PSetID; + int UnitIncrease; + + PressureElement(): PSetID(~0U), UnitIncrease(0) {} + PressureElement(unsigned id, int inc): PSetID(id), UnitIncrease(inc) {} + + bool isValid() const { return PSetID != ~0U; } +}; + +/// Store the effects of a change in pressure on things that MI scheduler cares +/// about. +/// +/// Excess records the value of the largest difference in register units beyond +/// the target's pressure limits across the affected pressure sets, where +/// largest is defined as the absolute value of the difference. Negative +/// ExcessUnits indicates a reduction in pressure that had already exceeded the +/// target's limits. +/// +/// CriticalMax records the largest increase in the tracker's max pressure that +/// exceeds the critical limit for some pressure set determined by the client. +/// +/// CurrentMax records the largest increase in the tracker's max pressure that +/// exceeds the current limit for some pressure set determined by the client. +struct RegPressureDelta { + PressureElement Excess; + PressureElement CriticalMax; + PressureElement CurrentMax; + + RegPressureDelta() {} +}; + +/// Track the current register pressure at some position in the instruction +/// stream, and remember the high water mark within the region traversed. This +/// does not automatically consider live-through ranges. The client may +/// independently adjust for global liveness. +/// +/// Each RegPressureTracker only works within a MachineBasicBlock. Pressure can +/// be tracked across a larger region by storing a RegisterPressure result at +/// each block boundary and explicitly adjusting pressure to account for block +/// live-in and live-out register sets. +/// +/// RegPressureTracker holds a reference to a RegisterPressure result that it +/// computes incrementally. During downward tracking, P.BottomIdx or P.BottomPos +/// is invalid until it reaches the end of the block or closeRegion() is +/// explicitly called. Similarly, P.TopIdx is invalid during upward +/// tracking. Changing direction has the side effect of closing region, and +/// traversing past TopIdx or BottomIdx reopens it. +class RegPressureTracker { + const MachineFunction *MF; + const TargetRegisterInfo *TRI; + const RegisterClassInfo *RCI; + const MachineRegisterInfo *MRI; + const LiveIntervals *LIS; + + /// We currently only allow pressure tracking within a block. + const MachineBasicBlock *MBB; + + /// Track the max pressure within the region traversed so far. + RegisterPressure &P; + + /// Run in two modes dependending on whether constructed with IntervalPressure + /// or RegisterPressure. If requireIntervals is false, LIS are ignored. + bool RequireIntervals; + + /// Register pressure corresponds to liveness before this instruction + /// iterator. It may point to the end of the block rather than an instruction. + MachineBasicBlock::const_iterator CurrPos; + + /// Pressure map indexed by pressure set ID, not class ID. + std::vector<unsigned> CurrSetPressure; + + /// List of live registers. + SparseSet<unsigned> LivePhysRegs; + SparseSet<unsigned, VirtReg2IndexFunctor> LiveVirtRegs; + +public: + RegPressureTracker(IntervalPressure &rp) : + MF(0), TRI(0), RCI(0), LIS(0), MBB(0), P(rp), RequireIntervals(true) {} + + RegPressureTracker(RegionPressure &rp) : + MF(0), TRI(0), RCI(0), LIS(0), MBB(0), P(rp), RequireIntervals(false) {} + + void init(const MachineFunction *mf, const RegisterClassInfo *rci, + const LiveIntervals *lis, const MachineBasicBlock *mbb, + MachineBasicBlock::const_iterator pos); + + /// Force liveness of registers. Particularly useful to initialize the + /// livein/out state of the tracker before the first call to advance/recede. + void addLiveRegs(ArrayRef<unsigned> Regs); + + /// Get the MI position corresponding to this register pressure. + MachineBasicBlock::const_iterator getPos() const { return CurrPos; } + + // Reset the MI position corresponding to the register pressure. This allows + // schedulers to move instructions above the RegPressureTracker's + // CurrPos. Since the pressure is computed before CurrPos, the iterator + // position changes while pressure does not. + void setPos(MachineBasicBlock::const_iterator Pos) { CurrPos = Pos; } + + /// Recede across the previous instruction. + bool recede(); + + /// Advance across the current instruction. + bool advance(); + + /// Finalize the region boundaries and recored live ins and live outs. + void closeRegion(); + + /// Get the resulting register pressure over the traversed region. + /// This result is complete if either advance() or recede() has returned true, + /// or if closeRegion() was explicitly invoked. + RegisterPressure &getPressure() { return P; } + + /// Get the register set pressure at the current position, which may be less + /// than the pressure across the traversed region. + std::vector<unsigned> &getRegSetPressureAtPos() { return CurrSetPressure; } + + void discoverPhysLiveIn(unsigned Reg); + void discoverPhysLiveOut(unsigned Reg); + + void discoverVirtLiveIn(unsigned Reg); + void discoverVirtLiveOut(unsigned Reg); + + bool isTopClosed() const; + bool isBottomClosed() const; + + void closeTop(); + void closeBottom(); + + /// Consider the pressure increase caused by traversing this instruction + /// bottom-up. Find the pressure set with the most change beyond its pressure + /// limit based on the tracker's current pressure, and record the number of + /// excess register units of that pressure set introduced by this instruction. + void getMaxUpwardPressureDelta(const MachineInstr *MI, + RegPressureDelta &Delta, + ArrayRef<PressureElement> CriticalPSets, + ArrayRef<unsigned> MaxPressureLimit); + + /// Consider the pressure increase caused by traversing this instruction + /// top-down. Find the pressure set with the most change beyond its pressure + /// limit based on the tracker's current pressure, and record the number of + /// excess register units of that pressure set introduced by this instruction. + void getMaxDownwardPressureDelta(const MachineInstr *MI, + RegPressureDelta &Delta, + ArrayRef<PressureElement> CriticalPSets, + ArrayRef<unsigned> MaxPressureLimit); + + /// Find the pressure set with the most change beyond its pressure limit after + /// traversing this instruction either upward or downward depending on the + /// closed end of the current region. + void getMaxPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta, + ArrayRef<PressureElement> CriticalPSets, + ArrayRef<unsigned> MaxPressureLimit) { + if (isTopClosed()) + return getMaxDownwardPressureDelta(MI, Delta, CriticalPSets, + MaxPressureLimit); + + assert(isBottomClosed() && "Uninitialized pressure tracker"); + return getMaxUpwardPressureDelta(MI, Delta, CriticalPSets, + MaxPressureLimit); + } + + /// Get the pressure of each PSet after traversing this instruction bottom-up. + void getUpwardPressure(const MachineInstr *MI, + std::vector<unsigned> &PressureResult, + std::vector<unsigned> &MaxPressureResult); + + /// Get the pressure of each PSet after traversing this instruction top-down. + void getDownwardPressure(const MachineInstr *MI, + std::vector<unsigned> &PressureResult, + std::vector<unsigned> &MaxPressureResult); + + void getPressureAfterInst(const MachineInstr *MI, + std::vector<unsigned> &PressureResult, + std::vector<unsigned> &MaxPressureResult) { + if (isTopClosed()) + return getUpwardPressure(MI, PressureResult, MaxPressureResult); + + assert(isBottomClosed() && "Uninitialized pressure tracker"); + return getDownwardPressure(MI, PressureResult, MaxPressureResult); + } + +protected: + void increasePhysRegPressure(ArrayRef<unsigned> Regs); + void decreasePhysRegPressure(ArrayRef<unsigned> Regs); + + void increaseVirtRegPressure(ArrayRef<unsigned> Regs); + void decreaseVirtRegPressure(ArrayRef<unsigned> Regs); + + void bumpUpwardPressure(const MachineInstr *MI); + void bumpDownwardPressure(const MachineInstr *MI); +}; +} // end namespace llvm + +#endif diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h index f4de693..85ab47b 100644 --- a/include/llvm/CodeGen/ScheduleDAG.h +++ b/include/llvm/CodeGen/ScheduleDAG.h @@ -117,8 +117,9 @@ namespace llvm { } } - bool operator==(const SDep &Other) const { - if (Dep != Other.Dep || Latency != Other.Latency) return false; + /// Return true if the specified SDep is equivalent except for latency. + bool overlaps(const SDep &Other) const { + if (Dep != Other.Dep) return false; switch (Dep.getInt()) { case Data: case Anti: @@ -133,6 +134,10 @@ namespace llvm { llvm_unreachable("Invalid dependency kind!"); } + bool operator==(const SDep &Other) const { + return overlaps(Other) && Latency == Other.Latency; + } + bool operator!=(const SDep &Other) const { return !operator==(Other); } @@ -272,6 +277,9 @@ namespace llvm { unsigned Depth; // Node depth. unsigned Height; // Node height. public: + unsigned TopReadyCycle; // Cycle relative to start when node is ready. + unsigned BotReadyCycle; // Cycle relative to end when node is ready. + const TargetRegisterClass *CopyDstRC; // Is a special copy node if not null. const TargetRegisterClass *CopySrcRC; @@ -287,7 +295,7 @@ namespace llvm { isScheduleHigh(false), isScheduleLow(false), isCloned(false), SchedulingPref(Sched::None), isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0), - CopyDstRC(NULL), CopySrcRC(NULL) {} + TopReadyCycle(0), BotReadyCycle(0), CopyDstRC(NULL), CopySrcRC(NULL) {} /// SUnit - Construct an SUnit for post-regalloc scheduling to represent /// a MachineInstr. @@ -301,7 +309,7 @@ namespace llvm { isScheduleHigh(false), isScheduleLow(false), isCloned(false), SchedulingPref(Sched::None), isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0), - CopyDstRC(NULL), CopySrcRC(NULL) {} + TopReadyCycle(0), BotReadyCycle(0), CopyDstRC(NULL), CopySrcRC(NULL) {} /// SUnit - Construct a placeholder SUnit. SUnit() @@ -314,7 +322,7 @@ namespace llvm { isScheduleHigh(false), isScheduleLow(false), isCloned(false), SchedulingPref(Sched::None), isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0), - CopyDstRC(NULL), CopySrcRC(NULL) {} + TopReadyCycle(0), BotReadyCycle(0), CopyDstRC(NULL), CopySrcRC(NULL) {} /// setNode - Assign the representative SDNode for this SUnit. /// This may be used during pre-regalloc scheduling. @@ -552,12 +560,6 @@ namespace llvm { /// virtual void computeLatency(SUnit *SU) = 0; - /// ComputeOperandLatency - Override dependence edge latency using - /// operand use/def information - /// - virtual void computeOperandLatency(SUnit *, SUnit *, - SDep&) const { } - /// ForceUnitLatencies - Return true if all scheduling edges should be given /// a latency value of one. The default is to return false; schedulers may /// override this as needed. diff --git a/include/llvm/CodeGen/ScheduleDAGInstrs.h b/include/llvm/CodeGen/ScheduleDAGInstrs.h index 4fee108..1bde942 100644 --- a/include/llvm/CodeGen/ScheduleDAGInstrs.h +++ b/include/llvm/CodeGen/ScheduleDAGInstrs.h @@ -28,6 +28,7 @@ namespace llvm { class MachineLoopInfo; class MachineDominatorTree; class LiveIntervals; + class RegPressureTracker; /// LoopDependencies - This class analyzes loop-oriented register /// dependencies, which are used to guide scheduling decisions. @@ -35,7 +36,6 @@ namespace llvm { /// scheduled as soon as possible after the variable's last use. /// class LoopDependencies { - const MachineLoopInfo &MLI; const MachineDominatorTree &MDT; public: @@ -43,9 +43,7 @@ namespace llvm { LoopDeps; LoopDeps Deps; - LoopDependencies(const MachineLoopInfo &mli, - const MachineDominatorTree &mdt) : - MLI(mli), MDT(mdt) {} + LoopDependencies(const MachineDominatorTree &mdt) : MDT(mdt) {} /// VisitLoop - Clear out any previous state and analyze the given loop. /// @@ -105,7 +103,7 @@ namespace llvm { VReg2SUnit(unsigned reg, SUnit *su): VirtReg(reg), SU(su) {} - unsigned getSparseSetKey() const { + unsigned getSparseSetIndex() const { return TargetRegisterInfo::virtReg2Index(VirtReg); } }; @@ -160,7 +158,7 @@ namespace llvm { /// compares ValueT's, only unsigned keys. This allows the set to be cleared /// between scheduling regions in constant time as long as ValueT does not /// require a destructor. - typedef SparseSet<VReg2SUnit> VReg2SUnitMap; + typedef SparseSet<VReg2SUnit, VirtReg2IndexFunctor> VReg2SUnitMap; /// ScheduleDAGInstrs - A ScheduleDAG subclass for scheduling lists of /// MachineInstrs. @@ -229,7 +227,7 @@ namespace llvm { /// LoopDependencies LoopRegs; - /// DbgValues - Remember instruction that preceeds DBG_VALUE. + /// DbgValues - Remember instruction that precedes DBG_VALUE. /// These are generated by buildSchedGraph but persist so they can be /// referenced when emitting the final schedule. typedef std::vector<std::pair<MachineInstr *, MachineInstr *> > @@ -275,7 +273,7 @@ namespace llvm { /// buildSchedGraph - Build SUnits from the MachineBasicBlock that we are /// input. - void buildSchedGraph(AliasAnalysis *AA); + void buildSchedGraph(AliasAnalysis *AA, RegPressureTracker *RPTracker = 0); /// addSchedBarrierDeps - Add dependencies from instructions in the current /// list of instructions being scheduled to scheduling barrier. We want to @@ -290,11 +288,15 @@ namespace llvm { /// virtual void computeLatency(SUnit *SU); - /// computeOperandLatency - Override dependence edge latency using + /// computeOperandLatency - Return dependence edge latency using /// operand use/def information /// - virtual void computeOperandLatency(SUnit *Def, SUnit *Use, - SDep& dep) const; + /// FindMin may be set to get the minimum vs. expected latency. Minimum + /// latency is used for scheduling groups, while expected latency is for + /// instruction cost and critical path. + virtual unsigned computeOperandLatency(SUnit *Def, SUnit *Use, + const SDep& dep, + bool FindMin = false) const; /// schedule - Order nodes according to selected style, filling /// in the Sequence member. @@ -321,10 +323,6 @@ namespace llvm { void addPhysRegDeps(SUnit *SU, unsigned OperIdx); void addVRegDefDeps(SUnit *SU, unsigned OperIdx); void addVRegUseDeps(SUnit *SU, unsigned OperIdx); - - VReg2SUnitMap::iterator findVRegDef(unsigned VirtReg) { - return VRegDefs.find(TargetRegisterInfo::virtReg2Index(VirtReg)); - } }; /// newSUnit - Creates a new SUnit and return a ptr to it. diff --git a/include/llvm/CodeGen/ScheduleHazardRecognizer.h b/include/llvm/CodeGen/ScheduleHazardRecognizer.h index 2f53baa..9dfa344 100644 --- a/include/llvm/CodeGen/ScheduleHazardRecognizer.h +++ b/include/llvm/CodeGen/ScheduleHazardRecognizer.h @@ -46,6 +46,8 @@ public: /// atIssueLimit - Return true if no more instructions may be issued in this /// cycle. + /// + /// FIXME: remove this once MachineScheduler is the only client. virtual bool atIssueLimit() const { return false; } /// getHazardType - Return the hazard type of emitting this node. There are @@ -55,7 +57,7 @@ public: /// other instruction is available, issue it first. /// * NoopHazard: issuing this instruction would break the program. If /// some other instruction can be issued, do so, otherwise issue a noop. - virtual HazardType getHazardType(SUnit *m, int Stalls) { + virtual HazardType getHazardType(SUnit *m, int Stalls = 0) { return NoHazard; } diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index 6a7a87e..1ccfe54 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -177,6 +177,44 @@ class SelectionDAG { /// DbgInfo - Tracks dbg_value information through SDISel. SDDbgInfo *DbgInfo; +public: + /// DAGUpdateListener - Clients of various APIs that cause global effects on + /// the DAG can optionally implement this interface. This allows the clients + /// to handle the various sorts of updates that happen. + /// + /// A DAGUpdateListener automatically registers itself with DAG when it is + /// constructed, and removes itself when destroyed in RAII fashion. + struct DAGUpdateListener { + DAGUpdateListener *const Next; + SelectionDAG &DAG; + + explicit DAGUpdateListener(SelectionDAG &D) + : Next(D.UpdateListeners), DAG(D) { + DAG.UpdateListeners = this; + } + + virtual ~DAGUpdateListener() { + assert(DAG.UpdateListeners == this && + "DAGUpdateListeners must be destroyed in LIFO order"); + DAG.UpdateListeners = Next; + } + + /// NodeDeleted - The node N that was deleted and, if E is not null, an + /// equivalent node E that replaced it. + virtual void NodeDeleted(SDNode *N, SDNode *E); + + /// NodeUpdated - The node N that was updated. + virtual void NodeUpdated(SDNode *N); + }; + +private: + /// DAGUpdateListener is a friend so it can manipulate the listener stack. + friend struct DAGUpdateListener; + + /// UpdateListeners - Linked list of registered DAGUpdateListener instances. + /// This stack is maintained by DAGUpdateListener RAII. + DAGUpdateListener *UpdateListeners; + /// setGraphColorHelper - Implementation of setSubgraphColor. /// Return whether we had to truncate the search. /// @@ -384,6 +422,8 @@ public: int Offset = 0, unsigned char TargetFlags=0) { return getConstantPool(C, VT, Align, Offset, true, TargetFlags); } + SDValue getTargetIndex(int Index, EVT VT, int64_t Offset = 0, + unsigned char TargetFlags = 0); // When generating a branch to a BB, we don't in general know enough // to provide debug info for the BB at that time, so keep this one around. SDValue getBasicBlock(MachineBasicBlock *MBB); @@ -817,30 +857,14 @@ public: SDDbgValue *getDbgValue(MDNode *MDPtr, unsigned FI, uint64_t Off, DebugLoc DL, unsigned O); - /// DAGUpdateListener - Clients of various APIs that cause global effects on - /// the DAG can optionally implement this interface. This allows the clients - /// to handle the various sorts of updates that happen. - class DAGUpdateListener { - public: - virtual ~DAGUpdateListener(); - - /// NodeDeleted - The node N that was deleted and, if E is not null, an - /// equivalent node E that replaced it. - virtual void NodeDeleted(SDNode *N, SDNode *E) = 0; - - /// NodeUpdated - The node N that was updated. - virtual void NodeUpdated(SDNode *N) = 0; - }; - /// RemoveDeadNode - Remove the specified node from the system. If any of its /// operands then becomes dead, remove them as well. Inform UpdateListener /// for each node deleted. - void RemoveDeadNode(SDNode *N, DAGUpdateListener *UpdateListener = 0); + void RemoveDeadNode(SDNode *N); /// RemoveDeadNodes - This method deletes the unreachable nodes in the /// given list, and any nodes that become unreachable as a result. - void RemoveDeadNodes(SmallVectorImpl<SDNode *> &DeadNodes, - DAGUpdateListener *UpdateListener = 0); + void RemoveDeadNodes(SmallVectorImpl<SDNode *> &DeadNodes); /// ReplaceAllUsesWith - Modify anything using 'From' to use 'To' instead. /// This can cause recursive merging of nodes in the DAG. Use the first @@ -857,24 +881,19 @@ public: /// to be given new uses. These new uses of From are left in place, and /// not automatically transferred to To. /// - void ReplaceAllUsesWith(SDValue From, SDValue Op, - DAGUpdateListener *UpdateListener = 0); - void ReplaceAllUsesWith(SDNode *From, SDNode *To, - DAGUpdateListener *UpdateListener = 0); - void ReplaceAllUsesWith(SDNode *From, const SDValue *To, - DAGUpdateListener *UpdateListener = 0); + void ReplaceAllUsesWith(SDValue From, SDValue Op); + void ReplaceAllUsesWith(SDNode *From, SDNode *To); + void ReplaceAllUsesWith(SDNode *From, const SDValue *To); /// ReplaceAllUsesOfValueWith - Replace any uses of From with To, leaving /// uses of other values produced by From.Val alone. - void ReplaceAllUsesOfValueWith(SDValue From, SDValue To, - DAGUpdateListener *UpdateListener = 0); + void ReplaceAllUsesOfValueWith(SDValue From, SDValue To); /// ReplaceAllUsesOfValuesWith - Like ReplaceAllUsesOfValueWith, but /// for multiple values at once. This correctly handles the case where /// there is an overlap between the From values and the To values. void ReplaceAllUsesOfValuesWith(const SDValue *From, const SDValue *To, - unsigned Num, - DAGUpdateListener *UpdateListener = 0); + unsigned Num); /// AssignTopologicalOrder - Topological-sort the AllNodes list and a /// assign a unique node id for each node in the DAG based on their @@ -1031,7 +1050,7 @@ public: private: bool RemoveNodeFromCSEMaps(SDNode *N); - void AddModifiedNodeToCSEMaps(SDNode *N, DAGUpdateListener *UpdateListener); + void AddModifiedNodeToCSEMaps(SDNode *N); SDNode *FindModifiedNodeSlot(SDNode *N, SDValue Op, void *&InsertPos); SDNode *FindModifiedNodeSlot(SDNode *N, SDValue Op1, SDValue Op2, void *&InsertPos); diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h index ee3f231..c42f655 100644 --- a/include/llvm/CodeGen/SelectionDAGISel.h +++ b/include/llvm/CodeGen/SelectionDAGISel.h @@ -172,53 +172,22 @@ protected: /// unsigned DAGSize; - /// ISelPosition - Node iterator marking the current position of - /// instruction selection as it procedes through the topologically-sorted - /// node list. - SelectionDAG::allnodes_iterator ISelPosition; - - - /// ISelUpdater - helper class to handle updates of the - /// instruction selection graph. - class ISelUpdater : public SelectionDAG::DAGUpdateListener { - virtual void anchor(); - SelectionDAG::allnodes_iterator &ISelPosition; - public: - explicit ISelUpdater(SelectionDAG::allnodes_iterator &isp) - : ISelPosition(isp) {} - - /// NodeDeleted - Handle nodes deleted from the graph. If the - /// node being deleted is the current ISelPosition node, update - /// ISelPosition. - /// - virtual void NodeDeleted(SDNode *N, SDNode *E) { - if (ISelPosition == SelectionDAG::allnodes_iterator(N)) - ++ISelPosition; - } - - /// NodeUpdated - Ignore updates for now. - virtual void NodeUpdated(SDNode *N) {} - }; - /// ReplaceUses - replace all uses of the old node F with the use /// of the new node T. void ReplaceUses(SDValue F, SDValue T) { - ISelUpdater ISU(ISelPosition); - CurDAG->ReplaceAllUsesOfValueWith(F, T, &ISU); + CurDAG->ReplaceAllUsesOfValueWith(F, T); } /// ReplaceUses - replace all uses of the old nodes F with the use /// of the new nodes T. void ReplaceUses(const SDValue *F, const SDValue *T, unsigned Num) { - ISelUpdater ISU(ISelPosition); - CurDAG->ReplaceAllUsesOfValuesWith(F, T, Num, &ISU); + CurDAG->ReplaceAllUsesOfValuesWith(F, T, Num); } /// ReplaceUses - replace all uses of the old node F with the use /// of the new node T. void ReplaceUses(SDNode *F, SDNode *T) { - ISelUpdater ISU(ISelPosition); - CurDAG->ReplaceAllUsesWith(F, T, &ISU); + CurDAG->ReplaceAllUsesWith(F, T); } diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index f8248b8..0dfb394 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -74,6 +74,10 @@ namespace ISD { /// ISD::SCALAR_TO_VECTOR node or a BUILD_VECTOR node where only the low /// element is not an undef. bool isScalarToVector(const SDNode *N); + + /// allOperandsUndef - Return true if the node has at least one operand + /// and all operands of the specified node are ISD::UNDEF. + bool allOperandsUndef(const SDNode *N); } // end llvm:ISD namespace //===----------------------------------------------------------------------===// @@ -1339,6 +1343,29 @@ public: } }; +/// Completely target-dependent object reference. +class TargetIndexSDNode : public SDNode { + unsigned char TargetFlags; + int Index; + int64_t Offset; + friend class SelectionDAG; +public: + + TargetIndexSDNode(int Idx, EVT VT, int64_t Ofs, unsigned char TF) + : SDNode(ISD::TargetIndex, DebugLoc(), getSDVTList(VT)), + TargetFlags(TF), Index(Idx), Offset(Ofs) {} +public: + + unsigned char getTargetFlags() const { return TargetFlags; } + int getIndex() const { return Index; } + int64_t getOffset() const { return Offset; } + + static bool classof(const TargetIndexSDNode*) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::TargetIndex; + } +}; + class BasicBlockSDNode : public SDNode { MachineBasicBlock *MBB; friend class SelectionDAG; diff --git a/include/llvm/CodeGen/SlotIndexes.h b/include/llvm/CodeGen/SlotIndexes.h index 0457e43..c52599b 100644 --- a/include/llvm/CodeGen/SlotIndexes.h +++ b/include/llvm/CodeGen/SlotIndexes.h @@ -76,7 +76,6 @@ namespace llvm { /// SlotIndex - An opaque wrapper around machine indexes. class SlotIndex { friend class SlotIndexes; - friend struct DenseMapInfo<SlotIndex>; enum Slot { /// Basic block boundary. Used for live ranges entering and leaving a @@ -121,11 +120,6 @@ namespace llvm { return static_cast<Slot>(lie.getInt()); } - static inline unsigned getHashValue(const SlotIndex &v) { - void *ptrVal = v.lie.getOpaqueValue(); - return (unsigned((intptr_t)ptrVal)) ^ (unsigned((intptr_t)ptrVal) >> 9); - } - public: enum { /// The default distance between instructions as returned by distance(). @@ -133,14 +127,6 @@ namespace llvm { InstrDist = 4 * Slot_Count }; - static inline SlotIndex getEmptyKey() { - return SlotIndex(0, 1); - } - - static inline SlotIndex getTombstoneKey() { - return SlotIndex(0, 2); - } - /// Construct an invalid index. SlotIndex() : lie(0, 0) {} @@ -293,23 +279,6 @@ namespace llvm { }; - /// DenseMapInfo specialization for SlotIndex. - template <> - struct DenseMapInfo<SlotIndex> { - static inline SlotIndex getEmptyKey() { - return SlotIndex::getEmptyKey(); - } - static inline SlotIndex getTombstoneKey() { - return SlotIndex::getTombstoneKey(); - } - static inline unsigned getHashValue(const SlotIndex &v) { - return SlotIndex::getHashValue(v); - } - static inline bool isEqual(const SlotIndex &LHS, const SlotIndex &RHS) { - return (LHS == RHS); - } - }; - template <> struct isPodLike<SlotIndex> { static const bool value = true; }; @@ -344,7 +313,6 @@ namespace llvm { IndexList indexList; MachineFunction *mf; - unsigned functionSize; typedef DenseMap<const MachineInstr*, SlotIndex> Mi2IndexMap; Mi2IndexMap mi2iMap; @@ -402,19 +370,6 @@ namespace llvm { return SlotIndex(&indexList.back(), 0); } - /// Returns the distance between the highest and lowest indexes allocated - /// so far. - unsigned getIndexesLength() const { - assert(indexList.front().getIndex() == 0 && - "Initial index isn't zero?"); - return indexList.back().getIndex(); - } - - /// Returns the number of instructions in the function. - unsigned getFunctionSize() const { - return functionSize; - } - /// Returns true if the given machine instr is mapped to an index, /// otherwise returns false. bool hasIndex(const MachineInstr *instr) const { @@ -444,7 +399,7 @@ namespace llvm { } /// getIndexBefore - Returns the index of the last indexed instruction - /// before MI, or the the start index of its basic block. + /// before MI, or the start index of its basic block. /// MI is not required to have an index. SlotIndex getIndexBefore(const MachineInstr *MI) const { const MachineBasicBlock *MBB = MI->getParent(); @@ -590,7 +545,7 @@ namespace llvm { nextItr = getIndexAfter(mi).listEntry(); prevItr = prior(nextItr); } else { - // Insert mi's index immediately after the preceeding instruction. + // Insert mi's index immediately after the preceding instruction. prevItr = getIndexBefore(mi).listEntry(); nextItr = llvm::next(prevItr); } diff --git a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index 5a42136..9849e92 100644 --- a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -33,6 +33,8 @@ namespace llvm { class TargetLoweringObjectFileELF : public TargetLoweringObjectFile { + bool UseInitArray; + public: virtual ~TargetLoweringObjectFileELF() {} @@ -66,6 +68,7 @@ public: getCFIPersonalitySymbol(const GlobalValue *GV, Mangler *Mang, MachineModuleInfo *MMI) const; + void InitializeELF(bool UseInitArray_); virtual const MCSection * getStaticCtorSection(unsigned Priority = 65535) const; virtual const MCSection * diff --git a/include/llvm/CodeGen/ValueTypes.h b/include/llvm/CodeGen/ValueTypes.h index 76c2357..eb38cd3 100644 --- a/include/llvm/CodeGen/ValueTypes.h +++ b/include/llvm/CodeGen/ValueTypes.h @@ -68,34 +68,38 @@ namespace llvm { v2i32 = 22, // 2 x i32 v4i32 = 23, // 4 x i32 v8i32 = 24, // 8 x i32 - v1i64 = 25, // 1 x i64 - v2i64 = 26, // 2 x i64 - v4i64 = 27, // 4 x i64 - v8i64 = 28, // 8 x i64 - - v2f16 = 29, // 2 x f16 - v2f32 = 30, // 2 x f32 - v4f32 = 31, // 4 x f32 - v8f32 = 32, // 8 x f32 - v2f64 = 33, // 2 x f64 - v4f64 = 34, // 4 x f64 + v16i32 = 25, // 16 x i32 + v1i64 = 26, // 1 x i64 + v2i64 = 27, // 2 x i64 + v4i64 = 28, // 4 x i64 + v8i64 = 29, // 8 x i64 + v16i64 = 30, // 16 x i64 + + v2f16 = 31, // 2 x f16 + v2f32 = 32, // 2 x f32 + v4f32 = 33, // 4 x f32 + v8f32 = 34, // 8 x f32 + v2f64 = 35, // 2 x f64 + v4f64 = 36, // 4 x f64 FIRST_VECTOR_VALUETYPE = v2i8, LAST_VECTOR_VALUETYPE = v4f64, + FIRST_INTEGER_VECTOR_VALUETYPE = v2i8, + LAST_INTEGER_VECTOR_VALUETYPE = v16i64, FIRST_FP_VECTOR_VALUETYPE = v2f16, LAST_FP_VECTOR_VALUETYPE = v4f64, - x86mmx = 35, // This is an X86 MMX value + x86mmx = 37, // This is an X86 MMX value - Glue = 36, // This glues nodes together during pre-RA sched + Glue = 38, // This glues nodes together during pre-RA sched - isVoid = 37, // This has no value + isVoid = 39, // This has no value - Untyped = 38, // This value takes a register, but has + Untyped = 40, // This value takes a register, but has // unspecified type. The register class // will be determined by the opcode. - LAST_VALUETYPE = 39, // This always remains at the end of the list. + LAST_VALUETYPE = 41, // This always remains at the end of the list. // This is the current maximum for LAST_VALUETYPE. // MVT::MAX_ALLOWED_VALUETYPE is used for asserts and to size bit vectors @@ -153,15 +157,16 @@ namespace llvm { bool isFloatingPoint() const { return ((SimpleTy >= MVT::FIRST_FP_VALUETYPE && SimpleTy <= MVT::LAST_FP_VALUETYPE) || - (SimpleTy >= MVT::FIRST_FP_VECTOR_VALUETYPE && - SimpleTy <= MVT::LAST_FP_VECTOR_VALUETYPE)); + (SimpleTy >= MVT::FIRST_FP_VECTOR_VALUETYPE && + SimpleTy <= MVT::LAST_FP_VECTOR_VALUETYPE)); } /// isInteger - Return true if this is an integer, or a vector integer type. bool isInteger() const { return ((SimpleTy >= MVT::FIRST_INTEGER_VALUETYPE && SimpleTy <= MVT::LAST_INTEGER_VALUETYPE) || - (SimpleTy >= MVT::v2i8 && SimpleTy <= MVT::v8i64)); + (SimpleTy >= MVT::FIRST_INTEGER_VECTOR_VALUETYPE && + SimpleTy <= MVT::LAST_INTEGER_VECTOR_VALUETYPE)); } /// isVector - Return true if this is a vector value type. @@ -170,6 +175,37 @@ namespace llvm { SimpleTy <= MVT::LAST_VECTOR_VALUETYPE); } + /// is64BitVector - Return true if this is a 64-bit vector type. + bool is64BitVector() const { + return (SimpleTy == MVT::v8i8 || SimpleTy == MVT::v4i16 || + SimpleTy == MVT::v2i32 || SimpleTy == MVT::v1i64 || + SimpleTy == MVT::v2f32); + } + + /// is128BitVector - Return true if this is a 128-bit vector type. + bool is128BitVector() const { + return (SimpleTy == MVT::v16i8 || SimpleTy == MVT::v8i16 || + SimpleTy == MVT::v4i32 || SimpleTy == MVT::v2i64 || + SimpleTy == MVT::v4f32 || SimpleTy == MVT::v2f64); + } + + /// is256BitVector - Return true if this is a 256-bit vector type. + bool is256BitVector() const { + return (SimpleTy == MVT::v8f32 || SimpleTy == MVT::v4f64 || + SimpleTy == MVT::v32i8 || SimpleTy == MVT::v16i16 || + SimpleTy == MVT::v8i32 || SimpleTy == MVT::v4i64); + } + + /// is512BitVector - Return true if this is a 512-bit vector type. + bool is512BitVector() const { + return (SimpleTy == MVT::v8i64 || SimpleTy == MVT::v16i32); + } + + /// is1024BitVector - Return true if this is a 1024-bit vector type. + bool is1024BitVector() const { + return (SimpleTy == MVT::v16i64); + } + /// isPow2VectorType - Returns true if the given vector is a power of 2. bool isPow2VectorType() const { unsigned NElts = getVectorNumElements(); @@ -196,7 +232,7 @@ namespace llvm { MVT getVectorElementType() const { switch (SimpleTy) { default: - return (MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE); + llvm_unreachable("Not a vector MVT!"); case v2i8 : case v4i8 : case v8i8 : @@ -208,11 +244,13 @@ namespace llvm { case v16i16: return i16; case v2i32: case v4i32: - case v8i32: return i32; + case v8i32: + case v16i32: return i32; case v1i64: case v2i64: case v4i64: - case v8i64: return i64; + case v8i64: + case v16i64: return i64; case v2f16: return f16; case v2f32: case v4f32: @@ -225,10 +263,12 @@ namespace llvm { unsigned getVectorNumElements() const { switch (SimpleTy) { default: - return ~0U; + llvm_unreachable("Not a vector MVT!"); case v32i8: return 32; case v16i8: - case v16i16: return 16; + case v16i16: + case v16i32: + case v16i64:return 16; case v8i8 : case v8i16: case v8i32: @@ -295,7 +335,9 @@ namespace llvm { case v4i64: case v8f32: case v4f64: return 256; + case v16i32: case v8i64: return 512; + case v16i64:return 1024; } } @@ -368,12 +410,14 @@ namespace llvm { if (NumElements == 2) return MVT::v2i32; if (NumElements == 4) return MVT::v4i32; if (NumElements == 8) return MVT::v8i32; + if (NumElements == 16) return MVT::v16i32; break; case MVT::i64: if (NumElements == 1) return MVT::v1i64; if (NumElements == 2) return MVT::v2i64; if (NumElements == 4) return MVT::v4i64; if (NumElements == 8) return MVT::v8i64; + if (NumElements == 16) return MVT::v16i64; break; case MVT::f16: if (NumElements == 2) return MVT::v2f16; @@ -487,32 +531,27 @@ namespace llvm { /// is64BitVector - Return true if this is a 64-bit vector type. bool is64BitVector() const { - if (!isSimple()) - return isExtended64BitVector(); - - return (V == MVT::v8i8 || V==MVT::v4i16 || V==MVT::v2i32 || - V == MVT::v1i64 || V==MVT::v2f32); + return isSimple() ? V.is64BitVector() : isExtended64BitVector(); } /// is128BitVector - Return true if this is a 128-bit vector type. bool is128BitVector() const { - if (!isSimple()) - return isExtended128BitVector(); - return (V==MVT::v16i8 || V==MVT::v8i16 || V==MVT::v4i32 || - V==MVT::v2i64 || V==MVT::v4f32 || V==MVT::v2f64); + return isSimple() ? V.is128BitVector() : isExtended128BitVector(); } /// is256BitVector - Return true if this is a 256-bit vector type. - inline bool is256BitVector() const { - if (!isSimple()) - return isExtended256BitVector(); - return (V == MVT::v8f32 || V == MVT::v4f64 || V == MVT::v32i8 || - V == MVT::v16i16 || V == MVT::v8i32 || V == MVT::v4i64); + bool is256BitVector() const { + return isSimple() ? V.is256BitVector() : isExtended256BitVector(); } /// is512BitVector - Return true if this is a 512-bit vector type. - inline bool is512BitVector() const { - return isSimple() ? (V == MVT::v8i64) : isExtended512BitVector(); + bool is512BitVector() const { + return isSimple() ? V.is512BitVector() : isExtended512BitVector(); + } + + /// is1024BitVector - Return true if this is a 1024-bit vector type. + bool is1024BitVector() const { + return isSimple() ? V.is1024BitVector() : isExtended1024BitVector(); } /// isOverloaded - Return true if this is an overloaded type for TableGen. @@ -705,6 +744,7 @@ namespace llvm { bool isExtended128BitVector() const; bool isExtended256BitVector() const; bool isExtended512BitVector() const; + bool isExtended1024BitVector() const; EVT getExtendedVectorElementType() const; unsigned getExtendedVectorNumElements() const; unsigned getExtendedSizeInBits() const; diff --git a/include/llvm/CodeGen/ValueTypes.td b/include/llvm/CodeGen/ValueTypes.td index 6c22690..f4b75bd 100644 --- a/include/llvm/CodeGen/ValueTypes.td +++ b/include/llvm/CodeGen/ValueTypes.td @@ -45,22 +45,24 @@ def v16i16 : ValueType<256, 21>; // 16 x i16 vector value def v2i32 : ValueType<64 , 22>; // 2 x i32 vector value def v4i32 : ValueType<128, 23>; // 4 x i32 vector value def v8i32 : ValueType<256, 24>; // 8 x i32 vector value -def v1i64 : ValueType<64 , 25>; // 1 x i64 vector value -def v2i64 : ValueType<128, 26>; // 2 x i64 vector value -def v4i64 : ValueType<256, 27>; // 4 x i64 vector value -def v8i64 : ValueType<512, 28>; // 8 x i64 vector value +def v16i32 : ValueType<512, 25>; // 16 x i32 vector value +def v1i64 : ValueType<64 , 26>; // 1 x i64 vector value +def v2i64 : ValueType<128, 27>; // 2 x i64 vector value +def v4i64 : ValueType<256, 28>; // 4 x i64 vector value +def v8i64 : ValueType<512, 29>; // 8 x i64 vector value +def v16i64 : ValueType<1024,30>; // 16 x i64 vector value -def v2f16 : ValueType<32 , 29>; // 2 x f16 vector value -def v2f32 : ValueType<64 , 30>; // 2 x f32 vector value -def v4f32 : ValueType<128, 31>; // 4 x f32 vector value -def v8f32 : ValueType<256, 32>; // 8 x f32 vector value -def v2f64 : ValueType<128, 33>; // 2 x f64 vector value -def v4f64 : ValueType<256, 34>; // 4 x f64 vector value +def v2f16 : ValueType<32 , 31>; // 2 x f16 vector value +def v2f32 : ValueType<64 , 32>; // 2 x f32 vector value +def v4f32 : ValueType<128, 33>; // 4 x f32 vector value +def v8f32 : ValueType<256, 34>; // 8 x f32 vector value +def v2f64 : ValueType<128, 35>; // 2 x f64 vector value +def v4f64 : ValueType<256, 36>; // 4 x f64 vector value -def x86mmx : ValueType<64 , 35>; // X86 MMX value -def FlagVT : ValueType<0 , 36>; // Pre-RA sched glue -def isVoid : ValueType<0 , 37>; // Produces no value -def untyped: ValueType<8 , 38>; // Produces an untyped value +def x86mmx : ValueType<64 , 37>; // X86 MMX value +def FlagVT : ValueType<0 , 38>; // Pre-RA sched glue +def isVoid : ValueType<0 , 39>; // Produces no value +def untyped: ValueType<8 , 40>; // Produces an untyped value def MetadataVT: ValueType<0, 250>; // Metadata diff --git a/include/llvm/Config/config.h.cmake b/include/llvm/Config/config.h.cmake index 95c4d6c..b912251 100644 --- a/include/llvm/Config/config.h.cmake +++ b/include/llvm/Config/config.h.cmake @@ -14,15 +14,21 @@ /* Directories clang will search for headers */ #define C_INCLUDE_DIRS "${C_INCLUDE_DIRS}" -/* Define if CBE is enabled for printf %a output */ -#cmakedefine ENABLE_CBE_PRINTF_A ${ENABLE_CBE_PRINTF_A} +/* Default <path> to all compiler invocations for --sysroot=<path>. */ +#undef DEFAULT_SYSROOT /* Define if position independent code is enabled */ #cmakedefine ENABLE_PIC -/* Define if timestamp information (e.g., __DATE___) is allowed */ +/* Define if timestamp information (e.g., __DATE__) is allowed */ #cmakedefine ENABLE_TIMESTAMPS ${ENABLE_TIMESTAMPS} +/* Directory where gcc is installed. */ +#undef GCC_INSTALL_PREFIX + +/* Define to 1 if you have the `arc4random' function. */ +#cmakedefine HAVE_ARC4RANDOM + /* Define to 1 if you have the `argz_append' function. */ #cmakedefine HAVE_ARGZ_APPEND ${HAVE_ARGZ_APPEND} @@ -155,7 +161,7 @@ #cmakedefine HAVE_GETTIMEOFDAY ${HAVE_GETTIMEOFDAY} /* Define if the Graphviz program is available */ -#undef HAVE_GRAPHVIZ +#cmakedefine HAVE_GRAPHVIZ ${HAVE_GRAPHVIZ} /* Define if the gv program is available */ #cmakedefine HAVE_GV ${HAVE_GV} @@ -548,6 +554,9 @@ /* Has gcc/MSVC atomic intrinsics */ #cmakedefine01 LLVM_HAS_ATOMICS +/* Host triple LLVM will be executed on */ +#cmakedefine LLVM_HOSTTRIPLE "${LLVM_HOSTTRIPLE}" + /* Installation directory for include files */ #cmakedefine LLVM_INCLUDEDIR "${LLVM_INCLUDEDIR}" @@ -617,6 +626,12 @@ /* Installation prefix directory */ #cmakedefine LLVM_PREFIX "${LLVM_PREFIX}" +/* Define if we have the Intel JIT API runtime support library */ +#cmakedefine LLVM_USE_INTEL_JITEVENTS 1 + +/* Define if we have the oprofile JIT-support library */ +#cmakedefine LLVM_USE_OPROFILE 1 + /* Major version of the LLVM API */ #cmakedefine LLVM_VERSION_MAJOR ${LLVM_VERSION_MAJOR} @@ -713,10 +728,4 @@ /* Added by Kevin -- Maximum path length */ #cmakedefine MAXPATHLEN ${MAXPATHLEN} -/* Support for Intel JIT Events API is enabled */ -#cmakedefine LLVM_USE_INTEL_JITEVENTS 1 - -/* Support for OProfile JIT API is enabled */ -#cmakedefine LLVM_USE_OPROFILE 1 - #endif diff --git a/include/llvm/Config/config.h.in b/include/llvm/Config/config.h.in index 677bf2e..5a60ba5 100644 --- a/include/llvm/Config/config.h.in +++ b/include/llvm/Config/config.h.in @@ -6,6 +6,9 @@ /* Bug report URL. */ #undef BUG_REPORT_URL +/* Define if we have libxml2 */ +#undef CLANG_HAVE_LIBXML + /* Relative directory for resource files */ #undef CLANG_RESOURCE_DIR @@ -18,12 +21,15 @@ /* Define if position independent code is enabled */ #undef ENABLE_PIC -/* Define if timestamp information (e.g., __DATE___) is allowed */ +/* Define if timestamp information (e.g., __DATE__) is allowed */ #undef ENABLE_TIMESTAMPS /* Directory where gcc is installed. */ #undef GCC_INSTALL_PREFIX +/* Define to 1 if you have the `arc4random' function. */ +#undef HAVE_ARC4RANDOM + /* Define to 1 if you have the `argz_append' function. */ #undef HAVE_ARGZ_APPEND @@ -549,6 +555,9 @@ /* Has gcc/MSVC atomic intrinsics */ #undef LLVM_HAS_ATOMICS +/* Host triple LLVM will be executed on */ +#undef LLVM_HOSTTRIPLE + /* Installation directory for include files */ #undef LLVM_INCLUDEDIR diff --git a/include/llvm/Config/llvm-config.h.cmake b/include/llvm/Config/llvm-config.h.cmake index 85d28fe..3944292 100644 --- a/include/llvm/Config/llvm-config.h.cmake +++ b/include/llvm/Config/llvm-config.h.cmake @@ -40,6 +40,9 @@ /* Has gcc/MSVC atomic intrinsics */ #cmakedefine01 LLVM_HAS_ATOMICS +/* Host triple LLVM will be executed on */ +#cmakedefine LLVM_HOSTTRIPLE "${LLVM_HOSTTRIPLE}" + /* Installation directory for include files */ #cmakedefine LLVM_INCLUDEDIR "${LLVM_INCLUDEDIR}" diff --git a/include/llvm/Config/llvm-config.h.in b/include/llvm/Config/llvm-config.h.in index 973652f..9489dfe 100644 --- a/include/llvm/Config/llvm-config.h.in +++ b/include/llvm/Config/llvm-config.h.in @@ -40,6 +40,9 @@ /* Has gcc/MSVC atomic intrinsics */ #undef LLVM_HAS_ATOMICS +/* Host triple LLVM will be executed on */ +#undef LLVM_HOSTTRIPLE + /* Installation directory for include files */ #undef LLVM_INCLUDEDIR diff --git a/include/llvm/Constant.h b/include/llvm/Constant.h index 13acdc6..e0e516d 100644 --- a/include/llvm/Constant.h +++ b/include/llvm/Constant.h @@ -137,8 +137,8 @@ public: static Constant *getNullValue(Type* Ty); - /// @returns the value for an integer constant of the given type that has all - /// its bits set to true. + /// @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); diff --git a/include/llvm/Constants.h b/include/llvm/Constants.h index 0abe17d..fdd5382 100644 --- a/include/llvm/Constants.h +++ b/include/llvm/Constants.h @@ -917,6 +917,17 @@ public: 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); diff --git a/include/llvm/Analysis/DIBuilder.h b/include/llvm/DIBuilder.h index 2d109cd..2ed48a9 100644 --- a/include/llvm/Analysis/DIBuilder.h +++ b/include/llvm/DIBuilder.h @@ -1,4 +1,4 @@ -//===--- llvm/Analysis/DIBuilder.h - Debug Information Builder --*- C++ -*-===// +//===--- llvm/DIBuilder.h - Debug Information Builder -----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -127,8 +127,8 @@ namespace llvm { StringRef Name = StringRef()); /// createReferenceType - Create debugging information entry for a c++ - /// style reference. - DIType createReferenceType(DIType RTy); + /// style reference or rvalue reference type. + DIType createReferenceType(unsigned Tag, DIType RTy); /// createTypedef - Create debugging information entry for a typedef. /// @param Ty Original type. @@ -177,7 +177,7 @@ namespace llvm { /// @param OffsetInBits Member offset. /// @param Flags Flags to encode member attribute, e.g. private /// @param Ty Parent type. - /// @param PropertyName Name of the Objective C property assoicated with + /// @param PropertyName Name of the Objective C property associated with /// this ivar. /// @param GetterName Name of the Objective C property getter selector. /// @param SetterName Name of the Objective C property setter selector. @@ -218,11 +218,11 @@ namespace llvm { /// @param PropertyAttributes Objective C property attributes. /// @param Ty Type. DIObjCProperty createObjCProperty(StringRef Name, - DIFile File, unsigned LineNumber, - StringRef GetterName, - StringRef SetterName, - unsigned PropertyAttributes, - DIType Ty); + DIFile File, unsigned LineNumber, + StringRef GetterName, + StringRef SetterName, + unsigned PropertyAttributes, + DIType Ty); /// createClassType - Create debugging information entry for a class. /// @param Scope Scope in which this class is defined. @@ -329,10 +329,12 @@ namespace llvm { /// @param SizeInBits Member size. /// @param AlignInBits Member alignment. /// @param Elements Enumeration elements. + /// @param Flags Flags (e.g. forward decl) DIType createEnumerationType(DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, - uint64_t SizeInBits, - uint64_t AlignInBits, DIArray Elements); + uint64_t SizeInBits, uint64_t AlignInBits, + DIArray Elements, DIType ClassType, + unsigned Flags); /// createSubroutineType - Create subroutine type. /// @param File File in which this subroutine is defined. @@ -348,8 +350,8 @@ namespace llvm { DIType createTemporaryType(DIFile F); /// createForwardDecl - Create a temporary forward-declared type. - DIType createForwardDecl(unsigned Tag, StringRef Name, DIFile F, - unsigned Line, unsigned RuntimeLang = 0); + DIType createForwardDecl(unsigned Tag, StringRef Name, DIDescriptor Scope, + DIFile F, unsigned Line, unsigned RuntimeLang = 0); /// retainType - Retain DIType in a module even if it is not referenced /// through debug info anchors. diff --git a/include/llvm/Analysis/DebugInfo.h b/include/llvm/DebugInfo.h index 894c542..618220f 100644 --- a/include/llvm/Analysis/DebugInfo.h +++ b/include/llvm/DebugInfo.h @@ -46,8 +46,8 @@ namespace llvm { class DIObjCProperty; /// DIDescriptor - A thin wraper around MDNode to access encoded debug info. - /// This should not be stored in a container, because underly MDNode may - /// change in certain situations. + /// This should not be stored in a container, because the underlying MDNode + /// may change in certain situations. class DIDescriptor { public: enum { @@ -104,12 +104,6 @@ namespace llvm { return getUnsignedField(0) & ~LLVMDebugVersionMask; } - /// print - print descriptor. - void print(raw_ostream &OS) const; - - /// dump - print descriptor to dbgs() with a newline. - void dump() const; - bool isDerivedType() const; bool isCompositeType() const; bool isBasicType() const; @@ -130,10 +124,18 @@ namespace llvm { bool isTemplateTypeParameter() const; bool isTemplateValueParameter() const; bool isObjCProperty() const; + + /// print - print descriptor. + void print(raw_ostream &OS) const; + + /// dump - print descriptor to dbgs() with a newline. + void dump() const; }; /// DISubrange - This is used to represent ranges, for array bounds. class DISubrange : public DIDescriptor { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; public: explicit DISubrange(const MDNode *N = 0) : DIDescriptor(N) {} @@ -155,10 +157,11 @@ namespace llvm { /// DIScope - A base class for various scopes. class DIScope : public DIDescriptor { - virtual void anchor(); + protected: + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; public: explicit DIScope(const MDNode *N = 0) : DIDescriptor (N) {} - virtual ~DIScope() {} StringRef getFilename() const; StringRef getDirectory() const; @@ -166,7 +169,8 @@ namespace llvm { /// DICompileUnit - A wrapper for a compile unit. class DICompileUnit : public DIScope { - virtual void anchor(); + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; public: explicit DICompileUnit(const MDNode *N = 0) : DIScope(N) {} @@ -196,17 +200,12 @@ namespace llvm { /// Verify - Verify that a compile unit is well formed. bool Verify() const; - - /// print - print compile unit. - void print(raw_ostream &OS) const; - - /// dump - print compile unit to dbgs() with a newline. - void dump() const; }; /// DIFile - This is a wrapper for a file. class DIFile : public DIScope { - virtual void anchor(); + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const {} // FIXME: Output something? public: explicit DIFile(const MDNode *N = 0) : DIScope(N) { if (DbgNode && !isFile()) @@ -224,6 +223,8 @@ namespace llvm { /// FIXME: it seems strange that this doesn't have either a reference to the /// type/precision or a file/line pair for location info. class DIEnumerator : public DIDescriptor { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; public: explicit DIEnumerator(const MDNode *N = 0) : DIDescriptor(N) {} @@ -235,19 +236,17 @@ namespace llvm { /// FIXME: Types should be factored much better so that CV qualifiers and /// others do not require a huge and empty descriptor full of zeros. class DIType : public DIScope { - virtual void anchor(); protected: + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; // This ctor is used when the Tag has already been validated by a derived // ctor. DIType(const MDNode *N, bool, bool) : DIScope(N) {} - public: - /// Verify - Verify that a type descriptor is well formed. bool Verify() const; explicit DIType(const MDNode *N); explicit DIType() {} - virtual ~DIType() {} DIScope getContext() const { return getFieldAs<DIScope>(1); } StringRef getName() const { return getStringField(2); } @@ -314,17 +313,10 @@ namespace llvm { /// this descriptor. void replaceAllUsesWith(DIDescriptor &D); void replaceAllUsesWith(MDNode *D); - - /// print - print type. - void print(raw_ostream &OS) const; - - /// dump - print type to dbgs() with a newline. - void dump() const; }; /// DIBasicType - A basic type, like 'int' or 'float'. class DIBasicType : public DIType { - virtual void anchor(); public: explicit DIBasicType(const MDNode *N = 0) : DIType(N) {} @@ -332,18 +324,13 @@ namespace llvm { /// Verify - Verify that a basic type descriptor is well formed. bool Verify() const; - - /// print - print basic type. - void print(raw_ostream &OS) const; - - /// dump - print basic type to dbgs() with a newline. - void dump() const; }; /// DIDerivedType - A simple derived type, like a const qualified type, /// a typedef, a pointer or reference, etc. class DIDerivedType : public DIType { - virtual void anchor(); + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; protected: explicit DIDerivedType(const MDNode *N, bool, bool) : DIType(N, true, true) {} @@ -401,19 +388,14 @@ namespace llvm { /// Verify - Verify that a derived type descriptor is well formed. bool Verify() const; - - /// print - print derived type. - void print(raw_ostream &OS) const; - - /// dump - print derived type to dbgs() with a newline. - void dump() const; }; /// DICompositeType - This descriptor holds a type that can refer to multiple /// other types, like a function or struct. /// FIXME: Why is this a DIDerivedType?? class DICompositeType : public DIDerivedType { - virtual void anchor(); + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; public: explicit DICompositeType(const MDNode *N = 0) : DIDerivedType(N, true, true) { @@ -430,12 +412,6 @@ namespace llvm { /// Verify - Verify that a composite type descriptor is well formed. bool Verify() const; - - /// print - print composite type. - void print(raw_ostream &OS) const; - - /// dump - print composite type to dbgs() with a newline. - void dump() const; }; /// DITemplateTypeParameter - This is a wrapper for template type parameter. @@ -477,7 +453,8 @@ namespace llvm { /// DISubprogram - This is a wrapper for a subprogram (e.g. a function). class DISubprogram : public DIScope { - virtual void anchor(); + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; public: explicit DISubprogram(const MDNode *N = 0) : DIScope(N) {} @@ -576,12 +553,6 @@ namespace llvm { /// Verify - Verify that a subprogram descriptor is well formed. bool Verify() const; - /// print - print subprogram. - void print(raw_ostream &OS) const; - - /// dump - print subprogram to dbgs() with a newline. - void dump() const; - /// describes - Return true if this subprogram provides debugging /// information for the function F. bool describes(const Function *F); @@ -597,6 +568,8 @@ namespace llvm { /// DIGlobalVariable - This is a wrapper for a global variable. class DIGlobalVariable : public DIDescriptor { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; public: explicit DIGlobalVariable(const MDNode *N = 0) : DIDescriptor(N) {} @@ -634,17 +607,13 @@ namespace llvm { /// Verify - Verify that a global variable descriptor is well formed. bool Verify() const; - - /// print - print global variable. - void print(raw_ostream &OS) const; - - /// dump - print global variable to dbgs() with a newline. - void dump() const; }; /// DIVariable - This is a wrapper for a variable (e.g. parameter, local, /// global etc). class DIVariable : public DIDescriptor { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; public: explicit DIVariable(const MDNode *N = 0) : DIDescriptor(N) {} @@ -706,18 +675,11 @@ namespace llvm { /// information for an inlined function arguments. bool isInlinedFnArgument(const Function *CurFn); - /// print - print variable. - void print(raw_ostream &OS) const; - void printExtendedName(raw_ostream &OS) const; - - /// dump - print variable to dbgs() with a newline. - void dump() const; }; /// DILexicalBlock - This is a wrapper for a lexical block. class DILexicalBlock : public DIScope { - virtual void anchor(); public: explicit DILexicalBlock(const MDNode *N = 0) : DIScope(N) {} DIScope getContext() const { return getFieldAs<DIScope>(1); } @@ -736,7 +698,6 @@ namespace llvm { /// DILexicalBlockFile - This is a wrapper for a lexical block with /// a filename change. class DILexicalBlockFile : public DIScope { - virtual void anchor(); public: explicit DILexicalBlockFile(const MDNode *N = 0) : DIScope(N) {} DIScope getContext() const { return getScope().getContext(); } @@ -756,7 +717,6 @@ namespace llvm { /// DINameSpace - A wrapper for a C++ style name space. class DINameSpace : public DIScope { - virtual void anchor(); public: explicit DINameSpace(const MDNode *N = 0) : DIScope(N) {} DIScope getContext() const { return getFieldAs<DIScope>(1); } @@ -794,6 +754,8 @@ namespace llvm { }; class DIObjCProperty : public DIDescriptor { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; public: explicit DIObjCProperty(const MDNode *N) : DIDescriptor(N) { } @@ -830,12 +792,6 @@ namespace llvm { /// Verify - Verify that a derived type descriptor is well formed. bool Verify() const; - - /// print - print derived type. - void print(raw_ostream &OS) const; - - /// dump - print derived type to dbgs() with a newline. - void dump() const; }; /// getDISubprogram - Find subprogram that is enclosing this scope. diff --git a/include/llvm/DebugInfo/DIContext.h b/include/llvm/DebugInfo/DIContext.h index 64f80c5..cfdeb46 100644 --- a/include/llvm/DebugInfo/DIContext.h +++ b/include/llvm/DebugInfo/DIContext.h @@ -15,9 +15,9 @@ #ifndef LLVM_DEBUGINFO_DICONTEXT_H #define LLVM_DEBUGINFO_DICONTEXT_H +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" -#include <cstring> namespace llvm { @@ -25,27 +25,52 @@ class raw_ostream; /// DILineInfo - a format-neutral container for source line information. class DILineInfo { - const char *FileName; + SmallString<16> FileName; + SmallString<16> FunctionName; uint32_t Line; uint32_t Column; public: - DILineInfo() : FileName("<invalid>"), Line(0), Column(0) {} - DILineInfo(const char *fileName, uint32_t line, uint32_t column) - : FileName(fileName), Line(line), Column(column) {} + DILineInfo() + : FileName("<invalid>"), FunctionName("<invalid>"), + Line(0), Column(0) {} + DILineInfo(const SmallString<16> &fileName, + const SmallString<16> &functionName, + uint32_t line, uint32_t column) + : FileName(fileName), FunctionName(functionName), + Line(line), Column(column) {} - const char *getFileName() const { return FileName; } + const char *getFileName() { return FileName.c_str(); } + const char *getFunctionName() { return FunctionName.c_str(); } uint32_t getLine() const { return Line; } uint32_t getColumn() const { return Column; } bool operator==(const DILineInfo &RHS) const { return Line == RHS.Line && Column == RHS.Column && - std::strcmp(FileName, RHS.FileName) == 0; + FileName.equals(RHS.FileName) && + FunctionName.equals(RHS.FunctionName); } bool operator!=(const DILineInfo &RHS) const { return !(*this == RHS); } }; +/// DILineInfoSpecifier - controls which fields of DILineInfo container +/// should be filled with data. +class DILineInfoSpecifier { + const uint32_t Flags; // Or'ed flags that set the info we want to fetch. +public: + enum Specification { + FileLineInfo = 1 << 0, + AbsoluteFilePath = 1 << 1, + FunctionName = 1 << 2 + }; + // Use file/line info by default. + DILineInfoSpecifier(uint32_t flags = FileLineInfo) : Flags(flags) {} + bool needs(Specification spec) const { + return (Flags & spec) > 0; + } +}; + class DIContext { public: virtual ~DIContext(); @@ -60,7 +85,8 @@ public: virtual void dump(raw_ostream &OS) = 0; - virtual DILineInfo getLineInfoForAddress(uint64_t address) = 0; + virtual DILineInfo getLineInfoForAddress(uint64_t address, + DILineInfoSpecifier specifier = DILineInfoSpecifier()) = 0; }; } diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index e920e98..ae8b68d 100644 --- a/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -354,7 +354,7 @@ public: /// variable, possibly emitting it to memory if needed. This is used by the /// Emitter. virtual void *getOrEmitGlobalVariable(const GlobalVariable *GV) { - return getPointerToGlobal((GlobalValue*)GV); + return getPointerToGlobal((const GlobalValue *)GV); } /// Registers a listener to be called back on various events within diff --git a/include/llvm/ExecutionEngine/Interpreter.h b/include/llvm/ExecutionEngine/Interpreter.h index 7425cdb..72d97ef 100644 --- a/include/llvm/ExecutionEngine/Interpreter.h +++ b/include/llvm/ExecutionEngine/Interpreter.h @@ -23,7 +23,7 @@ extern "C" void LLVMLinkInInterpreter(); namespace { struct ForceInterpreterLinking { ForceInterpreterLinking() { - // We must reference the passes in such a way that compilers will not + // We must reference the interpreter in such a way that compilers will not // delete it all as dead code, even with whole program optimization, // yet is effectively a NO-OP. As the compiler isn't smart enough // to know that getenv() never returns -1, this will do the job. diff --git a/include/llvm/ExecutionEngine/JIT.h b/include/llvm/ExecutionEngine/JIT.h index 6013db4..b4cda1d 100644 --- a/include/llvm/ExecutionEngine/JIT.h +++ b/include/llvm/ExecutionEngine/JIT.h @@ -23,7 +23,7 @@ extern "C" void LLVMLinkInJIT(); namespace { struct ForceJITLinking { ForceJITLinking() { - // We must reference the passes in such a way that compilers will not + // We must reference JIT in such a way that compilers will not // delete it all as dead code, even with whole program optimization, // yet is effectively a NO-OP. As the compiler isn't smart enough // to know that getenv() never returns -1, this will do the job. diff --git a/include/llvm/ExecutionEngine/MCJIT.h b/include/llvm/ExecutionEngine/MCJIT.h index f956a50..ac16bdc 100644 --- a/include/llvm/ExecutionEngine/MCJIT.h +++ b/include/llvm/ExecutionEngine/MCJIT.h @@ -23,7 +23,7 @@ extern "C" void LLVMLinkInMCJIT(); namespace { struct ForceMCJITLinking { ForceMCJITLinking() { - // We must reference the passes in such a way that compilers will not + // We must reference MCJIT in such a way that compilers will not // delete it all as dead code, even with whole program optimization, // yet is effectively a NO-OP. As the compiler isn't smart enough // to know that getenv() never returns -1, this will do the job. diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h index 54c28f3..a5c9272 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyld.h +++ b/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -65,12 +65,15 @@ public: RuntimeDyld(RTDyldMemoryManager*); ~RuntimeDyld(); + /// Load an in-memory object file into the dynamic linker. bool loadObject(MemoryBuffer *InputBuffer); - // Get the address of our local copy of the symbol. This may or may not - // be the address used for relocation (clients can copy the data around - // and resolve relocatons based on where they put it). + + /// Get the address of our local copy of the symbol. This may or may not + /// be the address used for relocation (clients can copy the data around + /// and resolve relocatons based on where they put it). void *getSymbolAddress(StringRef Name); - // Resolve the relocations for all symbols we currently know about. + + /// Resolve the relocations for all symbols we currently know about. void resolveRelocations(); /// mapSectionAddress - map a section to its target address space value. diff --git a/include/llvm/Function.h b/include/llvm/Function.h index e17cd87..fdd90d1 100644 --- a/include/llvm/Function.h +++ b/include/llvm/Function.h @@ -420,8 +420,8 @@ public: void dropAllReferences(); /// hasAddressTaken - returns true if there are any uses of this function - /// other than direct calls or invokes to it. Optionally passes back the - /// offending user for diagnostic purposes. + /// 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; diff --git a/include/llvm/GlobalValue.h b/include/llvm/GlobalValue.h index 81a11a4..8b969f3 100644 --- a/include/llvm/GlobalValue.h +++ b/include/llvm/GlobalValue.h @@ -164,6 +164,12 @@ public: 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. @@ -221,6 +227,10 @@ public: 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); } diff --git a/include/llvm/GlobalVariable.h b/include/llvm/GlobalVariable.h index 034ade1..99b7a73 100644 --- a/include/llvm/GlobalVariable.h +++ b/include/llvm/GlobalVariable.h @@ -41,24 +41,35 @@ class GlobalVariable : public GlobalValue, public ilist_node<GlobalVariable> { void setParent(Module *parent); bool isConstantGlobal : 1; // Is this a global constant? - bool isThreadLocalSymbol : 1; // Is this symbol "Thread Local"? + unsigned threadLocalMode : 3; // Is this symbol "Thread Local", + // if so, what is the desired model? 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 = "", - bool ThreadLocal = false, unsigned AddressSpace = 0); + ThreadLocalMode = NotThreadLocal, unsigned AddressSpace = 0); /// 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, bool ThreadLocal = false, + const Twine &Name = "", + GlobalVariable *InsertBefore = 0, + ThreadLocalMode = NotThreadLocal, unsigned AddressSpace = 0); ~GlobalVariable() { @@ -135,8 +146,14 @@ public: void setConstant(bool Val) { isConstantGlobal = Val; } /// If the value is "Thread Local", its value isn't shared by the threads. - bool isThreadLocal() const { return isThreadLocalSymbol; } - void setThreadLocal(bool Val) { isThreadLocalSymbol = Val; } + 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); + } /// copyAttributesFrom - copy all additional attributes (those not needed to /// create a GlobalVariable) from the GlobalVariable Src to this one. diff --git a/include/llvm/Support/IRBuilder.h b/include/llvm/IRBuilder.h index ef00e8e..d5b6f47 100644 --- a/include/llvm/Support/IRBuilder.h +++ b/include/llvm/IRBuilder.h @@ -1,4 +1,4 @@ -//===---- llvm/Support/IRBuilder.h - Builder for LLVM Instrs ----*- C++ -*-===// +//===---- llvm/IRBuilder.h - Builder for LLVM Instructions ------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_IRBUILDER_H -#define LLVM_SUPPORT_IRBUILDER_H +#ifndef LLVM_IRBUILDER_H +#define LLVM_IRBUILDER_H #include "llvm/Instructions.h" #include "llvm/BasicBlock.h" @@ -411,6 +411,17 @@ public: // 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: /// CreateRetVoid - Create a 'ret void' instruction. ReturnInst *CreateRetVoid() { return Insert(ReturnInst::Create(Context)); @@ -444,15 +455,19 @@ public: /// CreateCondBr - Create a conditional 'br Cond, TrueDest, FalseDest' /// instruction. - BranchInst *CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False) { - return Insert(BranchInst::Create(True, False, Cond)); + BranchInst *CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, + MDNode *BranchWeights = 0) { + return Insert(addBranchWeights(BranchInst::Create(True, False, Cond), + BranchWeights)); } /// CreateSwitch - 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) { - return Insert(SwitchInst::Create(V, Dest, NumCases)); + SwitchInst *CreateSwitch(Value *V, BasicBlock *Dest, unsigned NumCases = 10, + MDNode *BranchWeights = 0) { + return Insert(addBranchWeights(SwitchInst::Create(V, Dest, NumCases), + BranchWeights)); } /// CreateIndirectBr - Create an indirect branch instruction with the diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index 33d2043..de97957 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -71,6 +71,7 @@ void initializeBasicCallGraphPass(PassRegistry&); void initializeBlockExtractorPassPass(PassRegistry&); void initializeBlockFrequencyInfoPass(PassRegistry&); void initializeBlockPlacementPass(PassRegistry&); +void initializeBoundsCheckingPass(PassRegistry&); void initializeBranchFolderPassPass(PassRegistry&); void initializeBranchProbabilityInfoPass(PassRegistry&); void initializeBreakCriticalEdgesPass(PassRegistry&); @@ -99,6 +100,7 @@ void initializeDomPrinterPass(PassRegistry&); void initializeDomViewerPass(PassRegistry&); void initializeDominanceFrontierPass(PassRegistry&); void initializeDominatorTreePass(PassRegistry&); +void initializeEarlyIfConverterPass(PassRegistry&); void initializeEdgeBundlesPass(PassRegistry&); void initializeEdgeProfilerPass(PassRegistry&); void initializeExpandPostRAPass(PassRegistry&); @@ -135,6 +137,7 @@ void initializeLibCallAliasAnalysisPass(PassRegistry&); void initializeLintPass(PassRegistry&); void initializeLiveDebugVariablesPass(PassRegistry&); void initializeLiveIntervalsPass(PassRegistry&); +void initializeLiveRegMatrixPass(PassRegistry&); void initializeLiveStacksPass(PassRegistry&); void initializeLiveVariablesPass(PassRegistry&); void initializeLoaderPassPass(PassRegistry&); @@ -169,6 +172,7 @@ void initializeMachineLoopRangesPass(PassRegistry&); void initializeMachineModuleInfoPass(PassRegistry&); void initializeMachineSchedulerPass(PassRegistry&); void initializeMachineSinkingPass(PassRegistry&); +void initializeMachineTraceMetricsPass(PassRegistry&); void initializeMachineVerifierPassPass(PassRegistry&); void initializeMemCpyOptPass(PassRegistry&); void initializeMemDepPrinterPass(PassRegistry&); @@ -214,7 +218,6 @@ void initializeRegionOnlyPrinterPass(PassRegistry&); void initializeRegionOnlyViewerPass(PassRegistry&); void initializeRegionPrinterPass(PassRegistry&); void initializeRegionViewerPass(PassRegistry&); -void initializeRenderMachineFunctionPass(PassRegistry&); void initializeSCCPPass(PassRegistry&); void initializeSROA_DTPass(PassRegistry&); void initializeSROA_SSAUpPass(PassRegistry&); @@ -247,10 +250,12 @@ void initializeUnreachableBlockElimPass(PassRegistry&); void initializeUnreachableMachineBlockElimPass(PassRegistry&); void initializeVerifierPass(PassRegistry&); void initializeVirtRegMapPass(PassRegistry&); +void initializeVirtRegRewriterPass(PassRegistry&); void initializeInstSimplifierPass(PassRegistry&); void initializeUnpackMachineBundlesPass(PassRegistry&); void initializeFinalizeMachineBundlesPass(PassRegistry&); void initializeBBVectorizePass(PassRegistry&); +void initializeMachineFunctionPrinterPassPass(PassRegistry&); } #endif diff --git a/include/llvm/Instruction.h b/include/llvm/Instruction.h index 9c5ac44..5512dcc 100644 --- a/include/llvm/Instruction.h +++ b/include/llvm/Instruction.h @@ -215,6 +215,27 @@ public: 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; @@ -260,6 +281,16 @@ public: /// 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 @@ -269,7 +300,7 @@ public: /// @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) const; + 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 diff --git a/include/llvm/Instructions.h b/include/llvm/Instructions.h index f6eaf04..f5187e6 100644 --- a/include/llvm/Instructions.h +++ b/include/llvm/Instructions.h @@ -20,6 +20,8 @@ #include "llvm/DerivedTypes.h" #include "llvm/Attributes.h" #include "llvm/CallingConv.h" +#include "llvm/Support/IntegersSubset.h" +#include "llvm/Support/IntegersSubsetMapping.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/ErrorHandling.h" @@ -699,7 +701,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(AtomicRMWInst, Value) // checkGEPType - Simple wrapper function to give a better assertion failure // message on bad indexes for a gep instruction. // -static inline Type *checkGEPType(Type *Ty) { +inline Type *checkGEPType(Type *Ty) { assert(Ty && "Invalid GetElementPtrInst indices for type!"); return Ty; } @@ -1265,6 +1267,11 @@ public: /// removeAttribute - removes the attribute from the list of attributes. void removeAttribute(unsigned i, Attributes attr); + /// \brief Return true if this call has the given attribute. + bool hasFnAttr(Attributes N) const { + return paramHasAttr(~0, N); + } + /// @brief Determine whether the call or the callee has the given attribute. bool paramHasAttr(unsigned i, Attributes attr) const; @@ -1274,7 +1281,7 @@ public: } /// @brief Return true if the call should not be inlined. - bool isNoInline() const { return paramHasAttr(~0, Attribute::NoInline); } + bool isNoInline() const { return hasFnAttr(Attribute::NoInline); } void setIsNoInline(bool Value = true) { if (Value) addAttribute(~0, Attribute::NoInline); else removeAttribute(~0, Attribute::NoInline); @@ -1282,7 +1289,7 @@ public: /// @brief Return true if the call can return twice bool canReturnTwice() const { - return paramHasAttr(~0, Attribute::ReturnsTwice); + return hasFnAttr(Attribute::ReturnsTwice); } void setCanReturnTwice(bool Value = true) { if (Value) addAttribute(~0, Attribute::ReturnsTwice); @@ -1291,7 +1298,7 @@ public: /// @brief Determine if the call does not access memory. bool doesNotAccessMemory() const { - return paramHasAttr(~0, Attribute::ReadNone); + return hasFnAttr(Attribute::ReadNone); } void setDoesNotAccessMemory(bool NotAccessMemory = true) { if (NotAccessMemory) addAttribute(~0, Attribute::ReadNone); @@ -1300,7 +1307,7 @@ public: /// @brief Determine if the call does not access or only reads memory. bool onlyReadsMemory() const { - return doesNotAccessMemory() || paramHasAttr(~0, Attribute::ReadOnly); + return doesNotAccessMemory() || hasFnAttr(Attribute::ReadOnly); } void setOnlyReadsMemory(bool OnlyReadsMemory = true) { if (OnlyReadsMemory) addAttribute(~0, Attribute::ReadOnly); @@ -1308,14 +1315,14 @@ public: } /// @brief Determine if the call cannot return. - bool doesNotReturn() const { return paramHasAttr(~0, Attribute::NoReturn); } + bool doesNotReturn() const { return hasFnAttr(Attribute::NoReturn); } void setDoesNotReturn(bool DoesNotReturn = true) { if (DoesNotReturn) addAttribute(~0, Attribute::NoReturn); else removeAttribute(~0, Attribute::NoReturn); } /// @brief Determine if the call cannot unwind. - bool doesNotThrow() const { return paramHasAttr(~0, Attribute::NoUnwind); } + bool doesNotThrow() const { return hasFnAttr(Attribute::NoUnwind); } void setDoesNotThrow(bool DoesNotThrow = true) { if (DoesNotThrow) addAttribute(~0, Attribute::NoUnwind); else removeAttribute(~0, Attribute::NoUnwind); @@ -2237,7 +2244,7 @@ public: /// 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 accomodate the new + /// reserveClauses - Grow the size of the operand list to accommodate the new /// number of clauses. void reserveClauses(unsigned Size) { growOperands(Size); } @@ -2440,10 +2447,31 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BranchInst, Value) class SwitchInst : public TerminatorInst { void *operator new(size_t, unsigned); // DO NOT IMPLEMENT 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(); @@ -2468,121 +2496,25 @@ 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); - template <class SwitchInstTy, class ConstantIntTy, class BasicBlockTy> - class CaseIteratorT { - protected: - - SwitchInstTy *SI; - unsigned Index; - - public: - - typedef CaseIteratorT<SwitchInstTy, ConstantIntTy, BasicBlockTy> Self; - - /// Initializes case iterator for given SwitchInst and for given - /// case number. - CaseIteratorT(SwitchInstTy *SI, unsigned CaseNum) { - this->SI = SI; - Index = 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. - ConstantIntTy *getCaseValue() { - assert(Index < SI->getNumCases() && "Index out the number of cases."); - return reinterpret_cast<ConstantIntTy*>(SI->getOperand(2 + Index*2)); - } - - /// 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; - 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 ++. - assert((Index == 0 || Index-1 <= SI->getNumCases()) && - "Index out the number of cases."); - --Index; - 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; - } - }; - - typedef CaseIteratorT<const SwitchInst, const ConstantInt, const BasicBlock> - ConstCaseIt; - - class CaseIt : public CaseIteratorT<SwitchInst, ConstantInt, BasicBlock> { - - typedef CaseIteratorT<SwitchInst, ConstantInt, BasicBlock> ParentTy; - - public: - - CaseIt(const ParentTy& Src) : ParentTy(Src) {} - CaseIt(SwitchInst *SI, unsigned CaseNum) : ParentTy(SI, CaseNum) {} - - /// Sets the new value for current case. - void setValue(ConstantInt *V) { - assert(Index < SI->getNumCases() && "Index out the number of cases."); - SI->setOperand(2 + Index*2, reinterpret_cast<Value*>(V)); - } - - /// Sets the new successor for current case. - void setSuccessor(BasicBlock *S) { - SI->setSuccessor(getSuccessorIndex(), S); - } - }; - static SwitchInst *Create(Value *Value, BasicBlock *Default, unsigned NumCases, Instruction *InsertBefore = 0) { return new SwitchInst(Value, Default, NumCases, InsertBefore); @@ -2618,23 +2550,23 @@ public: /// Returns a read/write iterator that points to the first /// case in SwitchInst. CaseIt case_begin() { - return CaseIt(this, 0); + 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); + 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()); + 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()); + return ConstCaseIt(this, getNumCases(), TheSubsets.end()); } /// Returns an iterator that points to the default case. /// Note: this iterator allows to resolve successor only. Attempt @@ -2642,10 +2574,10 @@ public: /// Also note, that increment and decrement also causes an assertion and /// makes iterator invalid. CaseIt case_default() { - return CaseIt(this, DefaultPseudoIndex); + return CaseIt(this, DefaultPseudoIndex, TheSubsets.end()); } ConstCaseIt case_default() const { - return ConstCaseIt(this, DefaultPseudoIndex); + return ConstCaseIt(this, DefaultPseudoIndex, TheSubsets.end()); } /// findCaseValue - Search all of the case values for the specified constant. @@ -2654,13 +2586,13 @@ public: /// 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.getCaseValue() == C) + 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.getCaseValue() == C) + if (i.getCaseValueEx().isSatisfies(IntItem::fromConstantInt(C))) return i; return case_default(); } @@ -2681,10 +2613,17 @@ public: } /// 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 @@ -2692,7 +2631,7 @@ public: /// Note: /// This action invalidates iterators for all cases following the one removed, /// including the case_end() iterator. - void removeCase(CaseIt i); + void removeCase(CaseIt& i); unsigned getNumSuccessors() const { return getNumOperands()/2; } BasicBlock *getSuccessor(unsigned idx) const { @@ -2703,8 +2642,193 @@ public: 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 long 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 != -1UL) + --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 SwitchInst *) { return true; } static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::Switch; @@ -2905,6 +3029,11 @@ public: /// removeAttribute - removes the attribute from the list of attributes. void removeAttribute(unsigned i, Attributes attr); + /// \brief Return true if this call has the given attribute. + bool hasFnAttr(Attributes N) const { + return paramHasAttr(~0, N); + } + /// @brief Determine whether the call or the callee has the given attribute. bool paramHasAttr(unsigned i, Attributes attr) const; @@ -2914,7 +3043,7 @@ public: } /// @brief Return true if the call should not be inlined. - bool isNoInline() const { return paramHasAttr(~0, Attribute::NoInline); } + bool isNoInline() const { return hasFnAttr(Attribute::NoInline); } void setIsNoInline(bool Value = true) { if (Value) addAttribute(~0, Attribute::NoInline); else removeAttribute(~0, Attribute::NoInline); @@ -2922,7 +3051,7 @@ public: /// @brief Determine if the call does not access memory. bool doesNotAccessMemory() const { - return paramHasAttr(~0, Attribute::ReadNone); + return hasFnAttr(Attribute::ReadNone); } void setDoesNotAccessMemory(bool NotAccessMemory = true) { if (NotAccessMemory) addAttribute(~0, Attribute::ReadNone); @@ -2931,7 +3060,7 @@ public: /// @brief Determine if the call does not access or only reads memory. bool onlyReadsMemory() const { - return doesNotAccessMemory() || paramHasAttr(~0, Attribute::ReadOnly); + return doesNotAccessMemory() || hasFnAttr(Attribute::ReadOnly); } void setOnlyReadsMemory(bool OnlyReadsMemory = true) { if (OnlyReadsMemory) addAttribute(~0, Attribute::ReadOnly); @@ -2939,14 +3068,14 @@ public: } /// @brief Determine if the call cannot return. - bool doesNotReturn() const { return paramHasAttr(~0, Attribute::NoReturn); } + bool doesNotReturn() const { return hasFnAttr(Attribute::NoReturn); } void setDoesNotReturn(bool DoesNotReturn = true) { if (DoesNotReturn) addAttribute(~0, Attribute::NoReturn); else removeAttribute(~0, Attribute::NoReturn); } /// @brief Determine if the call cannot unwind. - bool doesNotThrow() const { return paramHasAttr(~0, Attribute::NoUnwind); } + bool doesNotThrow() const { return hasFnAttr(Attribute::NoUnwind); } void setDoesNotThrow(bool DoesNotThrow = true) { if (DoesNotThrow) addAttribute(~0, Attribute::NoUnwind); else removeAttribute(~0, Attribute::NoUnwind); diff --git a/include/llvm/Intrinsics.h b/include/llvm/Intrinsics.h index 3703825..c350388 100644 --- a/include/llvm/Intrinsics.h +++ b/include/llvm/Intrinsics.h @@ -74,6 +74,53 @@ namespace Intrinsic { /// 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, 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 diff --git a/include/llvm/Intrinsics.td b/include/llvm/Intrinsics.td index 069f907..d1a0fee 100644 --- a/include/llvm/Intrinsics.td +++ b/include/llvm/Intrinsics.td @@ -55,6 +55,8 @@ class NoCapture<int argNo> : IntrinsicProperty { int ArgNo = argNo; } +def IntrNoReturn : IntrinsicProperty; + //===----------------------------------------------------------------------===// // Types used by intrinsics. //===----------------------------------------------------------------------===// @@ -63,11 +65,15 @@ class LLVMType<ValueType vt> { ValueType VT = vt; } -class LLVMPointerType<LLVMType elty> +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; @@ -127,9 +133,12 @@ def llvm_v16i16_ty : LLVMType<v16i16>; // 16 x i16 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 @@ -155,10 +164,11 @@ def llvm_vararg_ty : LLVMType<isVoid>; // this means vararg here // 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 = ""> { + string name = ""> : SDPatternOperator { string LLVMName = name; string TargetPrefix = ""; // Set to a prefix for target-specific intrinsics. list<LLVMType> RetTypes = ret_types; @@ -253,12 +263,18 @@ let Properties = [IntrReadMem] in { 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>]>; } 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. @@ -297,7 +313,7 @@ let Properties = [IntrNoMem] in { let Properties = [IntrNoMem] in { def int_dbg_declare : Intrinsic<[], [llvm_metadata_ty, llvm_metadata_ty]>; - def int_dbg_value : Intrinsic<[], + def int_dbg_value : Intrinsic<[], [llvm_metadata_ty, llvm_i64_ty, llvm_metadata_ty]>; } @@ -396,8 +412,13 @@ def int_invariant_end : Intrinsic<[], // def int_flt_rounds : Intrinsic<[llvm_i32_ty]>, GCCBuiltin<"__builtin_flt_rounds">; -def int_trap : Intrinsic<[]>, +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 { @@ -439,5 +460,6 @@ include "llvm/IntrinsicsX86.td" include "llvm/IntrinsicsARM.td" include "llvm/IntrinsicsCellSPU.td" include "llvm/IntrinsicsXCore.td" -include "llvm/IntrinsicsPTX.td" include "llvm/IntrinsicsHexagon.td" +include "llvm/IntrinsicsNVVM.td" +include "llvm/IntrinsicsMips.td" diff --git a/include/llvm/IntrinsicsHexagon.td b/include/llvm/IntrinsicsHexagon.td index eb5dc8f..efd04f3 100644 --- a/include/llvm/IntrinsicsHexagon.td +++ b/include/llvm/IntrinsicsHexagon.td @@ -225,6 +225,22 @@ class Hexagon_qi_didi_Intrinsic<string 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> // @@ -406,3266 +422,4456 @@ class Hexagon_di_didisisi_Intrinsic<string GCCIntSuffix> 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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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_usi_sisi_Intrinsic<"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_usi_sisi_Intrinsic<"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_usi_sisi_Intrinsic<"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_usi_sisi_Intrinsic<"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_usi_sisi_Intrinsic<"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_usi_sisi_Intrinsic<"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_usi_sisi_Intrinsic<"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_usi_sisi_Intrinsic<"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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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_udi_sisi_Intrinsic<"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_udi_sisi_Intrinsic<"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_udi_sisi_Intrinsic<"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_udi_sisi_Intrinsic<"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_udi_sisi_Intrinsic<"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_udi_sisi_Intrinsic<"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_udi_sisi_Intrinsic<"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_udi_sisi_Intrinsic<"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">; +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">; +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">; +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">; +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">; +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">; +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_udi_sisi_Intrinsic<"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">; +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">; +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">; +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_usi_sisi_Intrinsic<"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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; -def int_hexagon_A2_addh_l16_lh : -Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.addh.l16.lh">; -def int_hexagon_A2_addh_l16_hh : -Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.addh.l16.hh">; +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">; +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">; -def int_hexagon_A2_addh_l16_sat_lh : -Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.addh.l16.sat.lh">; -def int_hexagon_A2_addh_l16_sat_hh : -Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.addh.l16.sat.hh">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_max">; // // BUILTIN_INFO(HEXAGON.A2_maxu,USI_ftype_SISI,2) // def int_hexagon_A2_maxu : -Hexagon_usi_sisi_Intrinsic<"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">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A2_min">; // // BUILTIN_INFO(HEXAGON.A2_minu,USI_ftype_SISI,2) // def int_hexagon_A2_minu : -Hexagon_usi_sisi_Intrinsic<"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">; +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_maxp">; // // BUILTIN_INFO(HEXAGON.A2_maxup,UDI_ftype_DIDI,2) // def int_hexagon_A2_maxup : -Hexagon_udi_didi_Intrinsic<"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">; +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_minp">; // // BUILTIN_INFO(HEXAGON.A2_minup,UDI_ftype_DIDI,2) // def int_hexagon_A2_minup : -Hexagon_udi_didi_Intrinsic<"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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +Hexagon_di_didi_Intrinsic<"HEXAGON_A2_vnavghr">; // -// BUILTIN_INFO(HEXAGON.A2_vminh,DI_ftype_DIDI,2) +// BUILTIN_INFO(HEXAGON.A4_round_ri,SI_ftype_SISI,2) // -def int_hexagon_A2_vminh : -Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vminh">; +def int_hexagon_A4_round_ri : +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_round_ri">; // -// BUILTIN_INFO(HEXAGON.A2_vmaxh,DI_ftype_DIDI,2) +// BUILTIN_INFO(HEXAGON.A4_round_rr,SI_ftype_SISI,2) // -def int_hexagon_A2_vmaxh : -Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vmaxh">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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">; +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_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">; - -// -// 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(HEXAGON.A4_orn,SI_ftype_SISI,2) -// -def int_hexagon_A4_orn : -Hexagon_si_sisi_Intrinsic<"HEXAGON.A4.orn">; -// -// 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,DI_ftype_DIDI,2) -// -def int_hexagon_A4_ornp : -Hexagon_di_didi_Intrinsic<"HEXAGON.A4.ornp">; -// -// BUILTIN_INFO(HEXAGON.A4_andn,DI_ftype_DIDI,2) -// -def int_hexagon_A4_andnp : -Hexagon_di_didi_Intrinsic<"HEXAGON.A4.andnp">; -// -// BUILTIN_INFO(HEXAGON.A4_combineir,DI_ftype_sisi,2) -// -def int_hexagon_A4_combineir : -Hexagon_di_sisi_Intrinsic<"HEXAGON.A4.combineir">; -// -// BUILTIN_INFO(HEXAGON.A4_combineir,DI_ftype_sisi,2) -// -def int_hexagon_A4_combineri : -Hexagon_di_sisi_Intrinsic<"HEXAGON.A4.combineri">; -// -// 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_cmpneqi,QI_ftype_SISI,2) -// -def int_hexagon_C4_cmpneqi : -Hexagon_qi_sisi_Intrinsic<"HEXAGON.C4.cmpneqi">; -// -// 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_cmpltei,QI_ftype_SISI,2) -// -def int_hexagon_C4_cmpltei : -Hexagon_qi_sisi_Intrinsic<"HEXAGON.C4.cmpltei">; -// -// BUILTIN_INFO(HEXAGON.C4_cmplteu,QI_ftype_SISI,2) -// -def int_hexagon_C4_cmplteu : -Hexagon_qi_sisi_Intrinsic<"HEXAGON.C4.cmplteu">; -// -// BUILTIN_INFO(HEXAGON.C4_cmplteui,QI_ftype_SISI,2) -// -def int_hexagon_C4_cmplteui : -Hexagon_qi_sisi_Intrinsic<"HEXAGON.C4.cmplteui">; -// -// BUILTIN_INFO(HEXAGON.A4_rcmpneq,SI_ftype_SISI,2) -// -def int_hexagon_A4_rcmpneq : -Hexagon_si_sisi_Intrinsic<"HEXAGON.A4.rcmpneq">; -// -// 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_rcmpeqi,SI_ftype_SISI,2) -// -def int_hexagon_A4_rcmpeqi : -Hexagon_si_sisi_Intrinsic<"HEXAGON.A4.rcmpeqi">; -// -// 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.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_and,QI_ftype_QIQIQI,3) -// -def int_hexagon_C4_and_and : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON.C4.and_and">; -// -// 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_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_andn,QI_ftype_QIQIQI,3) -// -def int_hexagon_C4_or_andn : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON.C4.or_andn">; -// -// 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_orn,QI_ftype_QIQIQI,3) -// -def int_hexagon_C4_or_orn : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON.C4.or_orn">; -// -// 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.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.S4_andnp,DI_ftype_DIDI,2) -// -def int_hexagon_S4_andnp : -Hexagon_di_didi_Intrinsic<"HEXAGON.S4.andnp">; +Hexagon_si_si_Intrinsic<"HEXAGON_S2_ct1">; // -// BUILTIN_INFO(HEXAGON.S4_ornp,DI_ftype_DIDI,2) +// BUILTIN_INFO(HEXAGON.S2_ct0p,SI_ftype_DI,1) // -def int_hexagon_S4_ornp : -Hexagon_di_didi_Intrinsic<"HEXAGON.S4.ornp">; +def int_hexagon_S2_ct0p : +Hexagon_si_di_Intrinsic<"HEXAGON_S2_ct0p">; // -// 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.M4_and_and,SI_ftype_SISISI,3) -// -def int_hexagon_M4_and_and : -Hexagon_si_sisisi_Intrinsic<"HEXAGON.M4.and_and">; +// BUILTIN_INFO(HEXAGON.S2_ct1p,SI_ftype_DI,1) // -// BUILTIN_INFO(HEXAGON.M4_and_andn,SI_ftype_SISISI,3) +def int_hexagon_S2_ct1p : +Hexagon_si_di_Intrinsic<"HEXAGON_S2_ct1p">; // -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_xor_and,SI_ftype_SISISI,3) -// -def int_hexagon_M4_xor_or : -Hexagon_si_sisisi_Intrinsic<"HEXAGON.M4.xor_or">; -// -// BUILTIN_INFO(HEXAGON.M4_xor_or,SI_ftype_SISISI,3) -// -def int_hexagon_M4_xor_and : -Hexagon_si_sisisi_Intrinsic<"HEXAGON.M4.xor_and">; -// -// 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.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_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.M4_or_andn,SI_ftype_SISISI,3) -// -def int_hexagon_M4_or_andn : -Hexagon_si_sisisi_Intrinsic<"HEXAGON.M4.or_andn">; -// -// 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.A4_modwrapu,SI_ftype_SISI,2) -// -def int_hexagon_A4_modwrapu : -Hexagon_si_sisi_Intrinsic<"HEXAGON.A4.modwrapu">; -// -// 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_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) +// BUILTIN_INFO(HEXAGON.S2_interleave,DI_ftype_DI,1) // -def int_hexagon_A4_round_ri_sat : -Hexagon_si_sisi_Intrinsic<"HEXAGON.A4.round_ri_sat">; +def int_hexagon_S2_interleave : +Hexagon_di_di_Intrinsic<"HEXAGON_S2_interleave">; // -// BUILTIN_INFO(HEXAGON.A4_round_rr_sat,SI_ftype_SISI,2) +// BUILTIN_INFO(HEXAGON.S2_deinterleave,DI_ftype_DI,1) // -def int_hexagon_A4_round_rr_sat : -Hexagon_si_sisi_Intrinsic<"HEXAGON.A4.round_rr_sat">; +def int_hexagon_S2_deinterleave : +Hexagon_di_di_Intrinsic<"HEXAGON_S2_deinterleave">; diff --git a/include/llvm/IntrinsicsMips.td b/include/llvm/IntrinsicsMips.td new file mode 100644 index 0000000..4375ac2 --- /dev/null +++ b/include/llvm/IntrinsicsMips.td @@ -0,0 +1,264 @@ +//===- 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_q31_ty: LLVMType<i32>; + +let TargetPrefix = "mips" in { // All intrinsics start with "llvm.mips.". + +//===----------------------------------------------------------------------===// +// 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]>; +} diff --git a/include/llvm/IntrinsicsNVVM.td b/include/llvm/IntrinsicsNVVM.td new file mode 100644 index 0000000..1853c99 --- /dev/null +++ b/include/llvm/IntrinsicsNVVM.td @@ -0,0 +1,952 @@ +//===- 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">; + + +// 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, NoCapture<0>], + "llvm.nvvm.ptr.local.to.gen">; +def int_nvvm_ptr_shared_to_gen: Intrinsic<[llvm_anyptr_ty], + [llvm_anyptr_ty], [IntrNoMem, NoCapture<0>], + "llvm.nvvm.ptr.shared.to.gen">; +def int_nvvm_ptr_global_to_gen: Intrinsic<[llvm_anyptr_ty], + [llvm_anyptr_ty], [IntrNoMem, NoCapture<0>], + "llvm.nvvm.ptr.global.to.gen">; +def int_nvvm_ptr_constant_to_gen: Intrinsic<[llvm_anyptr_ty], + [llvm_anyptr_ty], [IntrNoMem, NoCapture<0>], + "llvm.nvvm.ptr.constant.to.gen">; + +def int_nvvm_ptr_gen_to_global: Intrinsic<[llvm_anyptr_ty], + [llvm_anyptr_ty], [IntrNoMem, NoCapture<0>], + "llvm.nvvm.ptr.gen.to.global">; +def int_nvvm_ptr_gen_to_shared: Intrinsic<[llvm_anyptr_ty], + [llvm_anyptr_ty], [IntrNoMem, NoCapture<0>], + "llvm.nvvm.ptr.gen.to.shared">; +def int_nvvm_ptr_gen_to_local: Intrinsic<[llvm_anyptr_ty], + [llvm_anyptr_ty], [IntrNoMem, NoCapture<0>], + "llvm.nvvm.ptr.gen.to.local">; +def int_nvvm_ptr_gen_to_constant: Intrinsic<[llvm_anyptr_ty], + [llvm_anyptr_ty], [IntrNoMem, NoCapture<0>], + "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, NoCapture<0>], + "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/IntrinsicsPTX.td b/include/llvm/IntrinsicsPTX.td deleted file mode 100644 index 28379c9..0000000 --- a/include/llvm/IntrinsicsPTX.td +++ /dev/null @@ -1,92 +0,0 @@ -//===- IntrinsicsPTX.td - Defines PTX 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 PTX-specific intrinsics. -// -//===----------------------------------------------------------------------===// - -let TargetPrefix = "ptx" in { - 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">; - -let TargetPrefix = "ptx" in - def int_ptx_bar_sync : Intrinsic<[], [llvm_i32_ty], []>, - GCCBuiltin<"__builtin_ptx_bar_sync">; diff --git a/include/llvm/IntrinsicsX86.td b/include/llvm/IntrinsicsX86.td index cb7b3ea..e8039f2 100644 --- a/include/llvm/IntrinsicsX86.td +++ b/include/llvm/IntrinsicsX86.td @@ -819,6 +819,13 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [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">, @@ -1005,6 +1012,28 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". } //===----------------------------------------------------------------------===// +// 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 @@ -1272,16 +1301,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[], [llvm_ptr_ty, llvm_v32i8_ty], []>; } -// Cacheability support ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx_movnt_dq_256 : GCCBuiltin<"__builtin_ia32_movntdq256">, - Intrinsic<[], [llvm_ptr_ty, llvm_v4i64_ty], []>; - def int_x86_avx_movnt_pd_256 : GCCBuiltin<"__builtin_ia32_movntpd256">, - Intrinsic<[], [llvm_ptr_ty, llvm_v4f64_ty], []>; - def int_x86_avx_movnt_ps_256 : GCCBuiltin<"__builtin_ia32_movntps256">, - Intrinsic<[], [llvm_ptr_ty, llvm_v8f32_ty], []>; -} - // Conditional load ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx_maskload_pd : GCCBuiltin<"__builtin_ia32_maskloadpd">, @@ -1725,6 +1744,75 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [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">, @@ -1740,137 +1828,137 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". } //===----------------------------------------------------------------------===// -// FMA4 +// FMA3 and FMA4 let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_fma4_vfmadd_ss : GCCBuiltin<"__builtin_ia32_vfmaddss">, + 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_fma4_vfmadd_sd : GCCBuiltin<"__builtin_ia32_vfmaddsd">, + 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_fma4_vfmadd_ps : GCCBuiltin<"__builtin_ia32_vfmaddps">, + 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_fma4_vfmadd_pd : GCCBuiltin<"__builtin_ia32_vfmaddpd">, + 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_fma4_vfmadd_ps_256 : GCCBuiltin<"__builtin_ia32_vfmaddps256">, + 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_fma4_vfmadd_pd_256 : GCCBuiltin<"__builtin_ia32_vfmaddpd256">, + 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_fma4_vfmsub_ss : GCCBuiltin<"__builtin_ia32_vfmsubss">, + 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_fma4_vfmsub_sd : GCCBuiltin<"__builtin_ia32_vfmsubsd">, + 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_fma4_vfmsub_ps : GCCBuiltin<"__builtin_ia32_vfmsubps">, + 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_fma4_vfmsub_pd : GCCBuiltin<"__builtin_ia32_vfmsubpd">, + 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_fma4_vfmsub_ps_256 : GCCBuiltin<"__builtin_ia32_vfmsubps256">, + 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_fma4_vfmsub_pd_256 : GCCBuiltin<"__builtin_ia32_vfmsubpd256">, + 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_fma4_vfnmadd_ss : GCCBuiltin<"__builtin_ia32_vfnmaddss">, + 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_fma4_vfnmadd_sd : GCCBuiltin<"__builtin_ia32_vfnmaddsd">, + 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_fma4_vfnmadd_ps : GCCBuiltin<"__builtin_ia32_vfnmaddps">, + 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_fma4_vfnmadd_pd : GCCBuiltin<"__builtin_ia32_vfnmaddpd">, + 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_fma4_vfnmadd_ps_256 : GCCBuiltin<"__builtin_ia32_vfnmaddps256">, + 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_fma4_vfnmadd_pd_256 : GCCBuiltin<"__builtin_ia32_vfnmaddpd256">, + 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_fma4_vfnmsub_ss : GCCBuiltin<"__builtin_ia32_vfnmsubss">, + 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_fma4_vfnmsub_sd : GCCBuiltin<"__builtin_ia32_vfnmsubsd">, + 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_fma4_vfnmsub_ps : GCCBuiltin<"__builtin_ia32_vfnmsubps">, + 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_fma4_vfnmsub_pd : GCCBuiltin<"__builtin_ia32_vfnmsubpd">, + 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_fma4_vfnmsub_ps_256 : GCCBuiltin<"__builtin_ia32_vfnmsubps256">, + 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_fma4_vfnmsub_pd_256 : GCCBuiltin<"__builtin_ia32_vfnmsubpd256">, + 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_fma4_vfmaddsub_ps : GCCBuiltin<"__builtin_ia32_vfmaddsubps">, + 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_fma4_vfmaddsub_pd : GCCBuiltin<"__builtin_ia32_vfmaddsubpd">, + 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_fma4_vfmaddsub_ps_256 : + 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_fma4_vfmaddsub_pd_256 : + 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_fma4_vfmsubadd_ps : GCCBuiltin<"__builtin_ia32_vfmsubaddps">, + 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_fma4_vfmsubadd_pd : GCCBuiltin<"__builtin_ia32_vfmsubaddpd">, + 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_fma4_vfmsubadd_ps_256 : + 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_fma4_vfmsubadd_pd_256 : + def int_x86_fma_vfmsubadd_pd_256 : GCCBuiltin<"__builtin_ia32_vfmsubaddpd256">, Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], @@ -1901,26 +1989,19 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_xop_vfrcz_pd : - GCCBuiltin<"__builtin_ia32_vfrczpd">, + 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">, + 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, llvm_v2f64_ty], - [IntrNoMem]>; - def int_x86_xop_vfrcz_ss : - GCCBuiltin<"__builtin_ia32_vfrczss">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], - [IntrNoMem]>; - def int_x86_xop_vfrcz_pd_256 : - GCCBuiltin<"__builtin_ia32_vfrczpd256">, + 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">, + 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], @@ -1931,262 +2012,32 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; - def int_x86_xop_vpcomeqb : - GCCBuiltin<"__builtin_ia32_vpcomeqb">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomeqw : - GCCBuiltin<"__builtin_ia32_vpcomeqw">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomeqd : - GCCBuiltin<"__builtin_ia32_vpcomeqd">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomeqq : - GCCBuiltin<"__builtin_ia32_vpcomeqq">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomequb : - GCCBuiltin<"__builtin_ia32_vpcomequb">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomequd : - GCCBuiltin<"__builtin_ia32_vpcomequd">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomequq : - GCCBuiltin<"__builtin_ia32_vpcomequq">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomequw : - GCCBuiltin<"__builtin_ia32_vpcomequw">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomfalseb : - GCCBuiltin<"__builtin_ia32_vpcomfalseb">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomfalsed : - GCCBuiltin<"__builtin_ia32_vpcomfalsed">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomfalseq : - GCCBuiltin<"__builtin_ia32_vpcomfalseq">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomfalseub : - GCCBuiltin<"__builtin_ia32_vpcomfalseub">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomfalseud : - GCCBuiltin<"__builtin_ia32_vpcomfalseud">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomfalseuq : - GCCBuiltin<"__builtin_ia32_vpcomfalseuq">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomfalseuw : - GCCBuiltin<"__builtin_ia32_vpcomfalseuw">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomfalsew : - GCCBuiltin<"__builtin_ia32_vpcomfalsew">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomgeb : - GCCBuiltin<"__builtin_ia32_vpcomgeb">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomged : - GCCBuiltin<"__builtin_ia32_vpcomged">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomgeq : - GCCBuiltin<"__builtin_ia32_vpcomgeq">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomgeub : - GCCBuiltin<"__builtin_ia32_vpcomgeub">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomgeud : - GCCBuiltin<"__builtin_ia32_vpcomgeud">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomgeuq : - GCCBuiltin<"__builtin_ia32_vpcomgeuq">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomgeuw : - GCCBuiltin<"__builtin_ia32_vpcomgeuw">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomgew : - GCCBuiltin<"__builtin_ia32_vpcomgew">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomgtb : - GCCBuiltin<"__builtin_ia32_vpcomgtb">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomgtd : - GCCBuiltin<"__builtin_ia32_vpcomgtd">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomgtq : - GCCBuiltin<"__builtin_ia32_vpcomgtq">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomgtub : - GCCBuiltin<"__builtin_ia32_vpcomgtub">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomgtud : - GCCBuiltin<"__builtin_ia32_vpcomgtud">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomgtuq : - GCCBuiltin<"__builtin_ia32_vpcomgtuq">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomgtuw : - GCCBuiltin<"__builtin_ia32_vpcomgtuw">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomgtw : - GCCBuiltin<"__builtin_ia32_vpcomgtw">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomleb : - GCCBuiltin<"__builtin_ia32_vpcomleb">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomled : - GCCBuiltin<"__builtin_ia32_vpcomled">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomleq : - GCCBuiltin<"__builtin_ia32_vpcomleq">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomleub : - GCCBuiltin<"__builtin_ia32_vpcomleub">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomleud : - GCCBuiltin<"__builtin_ia32_vpcomleud">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomleuq : - GCCBuiltin<"__builtin_ia32_vpcomleuq">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomleuw : - GCCBuiltin<"__builtin_ia32_vpcomleuw">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomlew : - GCCBuiltin<"__builtin_ia32_vpcomlew">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomltb : - GCCBuiltin<"__builtin_ia32_vpcomltb">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomltd : - GCCBuiltin<"__builtin_ia32_vpcomltd">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomltq : - GCCBuiltin<"__builtin_ia32_vpcomltq">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomltub : - GCCBuiltin<"__builtin_ia32_vpcomltub">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomltud : - GCCBuiltin<"__builtin_ia32_vpcomltud">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomltuq : - GCCBuiltin<"__builtin_ia32_vpcomltuq">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomltuw : - GCCBuiltin<"__builtin_ia32_vpcomltuw">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomltw : - GCCBuiltin<"__builtin_ia32_vpcomltw">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomneb : - GCCBuiltin<"__builtin_ia32_vpcomneb">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomned : - GCCBuiltin<"__builtin_ia32_vpcomned">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomneq : - GCCBuiltin<"__builtin_ia32_vpcomneq">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomneub : - GCCBuiltin<"__builtin_ia32_vpcomneub">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomneud : - GCCBuiltin<"__builtin_ia32_vpcomneud">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomneuq : - GCCBuiltin<"__builtin_ia32_vpcomneuq">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomneuw : - GCCBuiltin<"__builtin_ia32_vpcomneuw">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomnew : - GCCBuiltin<"__builtin_ia32_vpcomnew">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomtrueb : - GCCBuiltin<"__builtin_ia32_vpcomtrueb">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomtrued : - GCCBuiltin<"__builtin_ia32_vpcomtrued">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomtrueq : - GCCBuiltin<"__builtin_ia32_vpcomtrueq">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomtrueub : - GCCBuiltin<"__builtin_ia32_vpcomtrueub">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomtrueud : - GCCBuiltin<"__builtin_ia32_vpcomtrueud">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomtrueuq : - GCCBuiltin<"__builtin_ia32_vpcomtrueuq">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomtrueuw : - GCCBuiltin<"__builtin_ia32_vpcomtrueuw">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; - def int_x86_xop_vpcomtruew : - GCCBuiltin<"__builtin_ia32_vpcomtruew">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_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]>; @@ -2297,22 +2148,32 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; - def int_x86_xop_vprotb : - GCCBuiltin<"__builtin_ia32_vprotb">, + + 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">, + 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">, + 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">, + 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], @@ -2675,3 +2536,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v8i16_ty], [llvm_v8f32_ty, llvm_i32_ty], [IntrNoMem]>; } + +//===----------------------------------------------------------------------===// +// RDRAND intrinsics. Return a 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], [], []>; +} diff --git a/include/llvm/LinkAllPasses.h b/include/llvm/LinkAllPasses.h index 2258d45..697c94c 100644 --- a/include/llvm/LinkAllPasses.h +++ b/include/llvm/LinkAllPasses.h @@ -55,6 +55,7 @@ namespace { (void) llvm::createScalarEvolutionAliasAnalysisPass(); (void) llvm::createTypeBasedAliasAnalysisPass(); (void) llvm::createBlockPlacementPass(); + (void) llvm::createBoundsCheckingPass(); (void) llvm::createBreakCriticalEdgesPass(); (void) llvm::createCFGSimplificationPass(); (void) llvm::createConstantMergePass(); diff --git a/include/llvm/MC/EDInstInfo.h b/include/llvm/MC/EDInstInfo.h index 0b9d3f6..5b02467 100644 --- a/include/llvm/MC/EDInstInfo.h +++ b/include/llvm/MC/EDInstInfo.h @@ -12,7 +12,7 @@ #include "llvm/Support/DataTypes.h" namespace llvm { - + #define EDIS_MAX_OPERANDS 13 #define EDIS_MAX_SYNTAXES 2 @@ -23,7 +23,7 @@ struct EDInstInfo { uint8_t operandFlags[EDIS_MAX_OPERANDS]; const signed char operandOrders[EDIS_MAX_SYNTAXES][EDIS_MAX_OPERANDS]; }; - + } // namespace llvm #endif diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h index 0f67c99..9f5230b 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -147,6 +147,11 @@ namespace llvm { // FIXME: Make this a more general encoding setting? bool AllowUTF8; + /// UseDataRegionDirectives - This is true if data region markers should + /// be printed as ".data_region/.end_data_region" directives. If false, + /// use "$d/$a" labels instead. + bool UseDataRegionDirectives; + //===--- Data Emission Directives -------------------------------------===// /// ZeroDirective - this should be set to the directive used to get some @@ -172,18 +177,6 @@ namespace llvm { const char *Data32bitsDirective; // Defaults to "\t.long\t" const char *Data64bitsDirective; // Defaults to "\t.quad\t" - /// [Data|Code]Begin - These magic labels are used to marked a region as - /// data or code, and are used to provide additional information for - /// correct disassembly on targets that like to mix data and code within - /// a segment. These labels will be implicitly suffixed by the streamer - /// to give them unique names. - const char *DataBegin; // Defaults to "$d." - const char *CodeBegin; // Defaults to "$a." - const char *JT8Begin; // Defaults to "$a." - const char *JT16Begin; // Defaults to "$a." - const char *JT32Begin; // Defaults to "$a." - bool SupportsDataRegions; - /// GPRel64Directive - if non-null, a directive that is used to emit a word /// which should be relocated as a 64-bit GP-relative offset, e.g. .gpdword /// on Mips. @@ -322,26 +315,14 @@ namespace llvm { /// DwarfSectionOffsetDirective - Special section offset directive. const char* DwarfSectionOffsetDirective; // Defaults to NULL - /// DwarfRequiresRelocationForSectionOffset - True if we need to produce a - /// relocation when we want a section offset in dwarf. - bool DwarfRequiresRelocationForSectionOffset; // Defaults to true; - - /// DwarfUsesLabelOffsetDifference - True if Dwarf2 output can - /// use EmitLabelOffsetDifference. - bool DwarfUsesLabelOffsetForRanges; - - /// DwarfUsesRelocationsForStringPool - True if this Dwarf output must use - /// relocations to refer to entries in the string pool. - bool DwarfUsesRelocationsForStringPool; + /// DwarfUsesRelocationsAcrossSections - True if Dwarf2 output generally + /// uses relocations for references to other .debug_* sections. + bool DwarfUsesRelocationsAcrossSections; /// DwarfRegNumForCFI - True if dwarf register numbers are printed /// instead of symbolic register names in .cfi_* directives. bool DwarfRegNumForCFI; // Defaults to false; - //===--- CBE Asm Translation Table -----------------------------------===// - - const char *const *AsmTransCBE; // Defaults to empty - //===--- Prologue State ----------------------------------------------===// std::vector<MachineMove> InitialFrameState; @@ -388,14 +369,6 @@ namespace llvm { const char *getGPRel64Directive() const { return GPRel64Directive; } const char *getGPRel32Directive() const { return GPRel32Directive; } - /// [Code|Data]Begin label name accessors. - const char *getCodeBeginLabelName() const { return CodeBegin; } - const char *getDataBeginLabelName() const { return DataBegin; } - const char *getJumpTable8BeginLabelName() const { return JT8Begin; } - const char *getJumpTable16BeginLabelName() const { return JT16Begin; } - const char *getJumpTable32BeginLabelName() const { return JT32Begin; } - bool getSupportsDataRegions() const { return SupportsDataRegions; } - /// getNonexecutableStackSection - Targets can implement this method to /// specify a section to switch to if the translation unit doesn't have any /// trampolines that require an executable stack. @@ -492,6 +465,9 @@ namespace llvm { bool doesAllowUTF8() const { return AllowUTF8; } + bool doesSupportDataRegionDirectives() const { + return UseDataRegionDirectives; + } const char *getZeroDirective() const { return ZeroDirective; } @@ -565,21 +541,12 @@ namespace llvm { const char *getDwarfSectionOffsetDirective() const { return DwarfSectionOffsetDirective; } - bool doesDwarfRequireRelocationForSectionOffset() const { - return DwarfRequiresRelocationForSectionOffset; - } - bool doesDwarfUseLabelOffsetForRanges() const { - return DwarfUsesLabelOffsetForRanges; - } - bool doesDwarfUseRelocationsForStringPool() const { - return DwarfUsesRelocationsForStringPool; + bool doesDwarfUseRelocationsAcrossSections() const { + return DwarfUsesRelocationsAcrossSections; } bool useDwarfRegNumForCFI() const { return DwarfRegNumForCFI; } - const char *const *getAsmCBE() const { - return AsmTransCBE; - } void addInitialFrameState(MCSymbol *label, const MachineLocation &D, const MachineLocation &S) { diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index d139173..b7b2d66 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -130,7 +130,7 @@ public: void addFixup(MCFixup Fixup) { // Enforce invariant that fixups are in offset order. - assert((Fixups.empty() || Fixup.getOffset() > Fixups.back().getOffset()) && + assert((Fixups.empty() || Fixup.getOffset() >= Fixups.back().getOffset()) && "Fixups must be added in order!"); Fixups.push_back(Fixup); } @@ -651,6 +651,16 @@ struct IndirectSymbolData { MCSectionData *SectionData; }; +// FIXME: Ditto this. Purely so the Streamer and the ObjectWriter can talk +// to one another. +struct DataRegionData { + // This enum should be kept in sync w/ the mach-o definition in + // llvm/Object/MachOFormat.h. + enum KindTy { Data = 1, JumpTable8, JumpTable16, JumpTable32 } Kind; + MCSymbol *Start; + MCSymbol *End; +}; + class MCAssembler { friend class MCAsmLayout; @@ -668,6 +678,10 @@ public: const_indirect_symbol_iterator; typedef std::vector<IndirectSymbolData>::iterator indirect_symbol_iterator; + typedef std::vector<DataRegionData>::const_iterator + const_data_region_iterator; + typedef std::vector<DataRegionData>::iterator data_region_iterator; + private: MCAssembler(const MCAssembler&); // DO NOT IMPLEMENT void operator=(const MCAssembler&); // DO NOT IMPLEMENT @@ -698,6 +712,7 @@ private: std::vector<IndirectSymbolData> IndirectSymbols; + std::vector<DataRegionData> DataRegions; /// The set of function symbols for which a .thumb_func directive has /// been seen. // @@ -884,6 +899,33 @@ public: size_t indirect_symbol_size() const { return IndirectSymbols.size(); } /// @} + /// @name Data Region List Access + /// @{ + + // FIXME: This is a total hack, this should not be here. Once things are + // factored so that the streamer has direct access to the .o writer, it can + // disappear. + std::vector<DataRegionData> &getDataRegions() { + return DataRegions; + } + + data_region_iterator data_region_begin() { + return DataRegions.begin(); + } + const_data_region_iterator data_region_begin() const { + return DataRegions.begin(); + } + + data_region_iterator data_region_end() { + return DataRegions.end(); + } + const_data_region_iterator data_region_end() const { + return DataRegions.end(); + } + + size_t data_region_size() const { return DataRegions.size(); } + + /// @} /// @name Backend Data Access /// @{ diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h index b586319..59545d3 100644 --- a/include/llvm/MC/MCContext.h +++ b/include/llvm/MC/MCContext.h @@ -161,6 +161,10 @@ namespace llvm { /// with a unique but unspecified name. MCSymbol *CreateTempSymbol(); + /// getUniqueSymbolID() - Return a unique identifier for use in constructing + /// symbol names. + unsigned getUniqueSymbolID() { return NextUniqueID++; } + /// CreateDirectionalLocalSymbol - Create the definition of a directional /// local symbol for numbered label (used for "1:" definitions). MCSymbol *CreateDirectionalLocalSymbol(int64_t LocalLabelVal); diff --git a/include/llvm/MC/MCDirectives.h b/include/llvm/MC/MCDirectives.h index 9180d1b..0461766 100644 --- a/include/llvm/MC/MCDirectives.h +++ b/include/llvm/MC/MCDirectives.h @@ -52,6 +52,14 @@ enum MCAssemblerFlag { MCAF_Code64 ///< .code64 (X86) }; +enum MCDataRegionType { + MCDR_DataRegion, ///< .data_region + MCDR_DataRegionJT8, ///< .data_region jt8 + MCDR_DataRegionJT16, ///< .data_region jt16 + MCDR_DataRegionJT32, ///< .data_region jt32 + MCDR_DataRegionEnd ///< .end_data_region +}; + } // end namespace llvm #endif diff --git a/include/llvm/MC/MCDisassembler.h b/include/llvm/MC/MCDisassembler.h index 4b5fbec..53a9ce0 100644 --- a/include/llvm/MC/MCDisassembler.h +++ b/include/llvm/MC/MCDisassembler.h @@ -13,13 +13,13 @@ #include "llvm-c/Disassembler.h" namespace llvm { - + class MCInst; class MCSubtargetInfo; class MemoryObject; class raw_ostream; class MCContext; - + struct EDInstInfo; /// MCDisassembler - Superclass for all disassemblers. Consumes a memory region @@ -58,12 +58,12 @@ public: MCDisassembler(const MCSubtargetInfo &STI) : GetOpInfo(0), SymbolLookUp(0), DisInfo(0), Ctx(0), STI(STI), CommentStream(0) {} - + virtual ~MCDisassembler(); - + /// getInstruction - Returns the disassembly of a single instruction. /// - /// @param instr - An MCInst to populate with the contents of the + /// @param instr - An MCInst to populate with the contents of the /// instruction. /// @param size - A value to populate with the size of the instruction, or /// the number of bytes consumed while attempting to decode @@ -74,7 +74,7 @@ public: /// @param vStream - The stream to print warnings and diagnostic messages on. /// @param cStream - The stream to print comments and annotations on. /// @return - MCDisassembler::Success if the instruction is valid, - /// MCDisassembler::SoftFail if the instruction was + /// MCDisassembler::SoftFail if the instruction was /// disassemblable but invalid, /// MCDisassembler::Fail if the instruction was invalid. virtual DecodeStatus getInstruction(MCInst& instr, diff --git a/include/llvm/MC/MCELFObjectWriter.h b/include/llvm/MC/MCELFObjectWriter.h index f153cb0..abbe188 100644 --- a/include/llvm/MC/MCELFObjectWriter.h +++ b/include/llvm/MC/MCELFObjectWriter.h @@ -54,11 +54,13 @@ class MCELFObjectTargetWriter { const uint16_t EMachine; const unsigned HasRelocationAddend : 1; const unsigned Is64Bit : 1; + const unsigned IsN64 : 1; protected: MCELFObjectTargetWriter(bool Is64Bit_, uint8_t OSABI_, - uint16_t EMachine_, bool HasRelocationAddend_); + uint16_t EMachine_, bool HasRelocationAddend, + bool IsN64=false); public: static uint8_t getOSABI(Triple::OSType OSType) { @@ -95,7 +97,47 @@ public: uint16_t getEMachine() { return EMachine; } bool hasRelocationAddend() { return HasRelocationAddend; } bool is64Bit() const { return Is64Bit; } + bool isN64() const { return IsN64; } /// @} + + // Instead of changing everyone's API we pack the N64 Type fields + // into the existing 32 bit data unsigned. +#define R_TYPE_SHIFT 0 +#define R_TYPE_MASK 0xffffff00 +#define R_TYPE2_SHIFT 8 +#define R_TYPE2_MASK 0xffff00ff +#define R_TYPE3_SHIFT 16 +#define R_TYPE3_MASK 0xff00ffff +#define R_SSYM_SHIFT 24 +#define R_SSYM_MASK 0x00ffffff + + // N64 relocation type accessors + unsigned getRType(uint32_t Type) const { + return (unsigned)((Type >> R_TYPE_SHIFT) & 0xff); + } + unsigned getRType2(uint32_t Type) const { + return (unsigned)((Type >> R_TYPE2_SHIFT) & 0xff); + } + unsigned getRType3(uint32_t Type) const { + return (unsigned)((Type >> R_TYPE3_SHIFT) & 0xff); + } + unsigned getRSsym(uint32_t Type) const { + return (unsigned)((Type >> R_SSYM_SHIFT) & 0xff); + } + + // N64 relocation type setting + unsigned setRType(unsigned Value, unsigned Type) const { + return ((Type & R_TYPE_MASK) | ((Value & 0xff) << R_TYPE_SHIFT)); + } + unsigned setRType2(unsigned Value, unsigned Type) const { + return (Type & R_TYPE2_MASK) | ((Value & 0xff) << R_TYPE2_SHIFT); + } + unsigned setRType3(unsigned Value, unsigned Type) const { + return (Type & R_TYPE3_MASK) | ((Value & 0xff) << R_TYPE3_SHIFT); + } + unsigned setRSsym(unsigned Value, unsigned Type) const { + return (Type & R_SSYM_MASK) | ((Value & 0xff) << R_SSYM_SHIFT); + } }; /// \brief Construct a new ELF writer instance. diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index ff33641..aa62eb2 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -176,6 +176,8 @@ public: VK_PPC_DARWIN_LO16, // lo16(symbol) VK_PPC_GAS_HA16, // symbol@ha VK_PPC_GAS_LO16, // symbol@l + VK_PPC_TPREL16_HA, // symbol@tprel@ha + VK_PPC_TPREL16_LO, // symbol@tprel@l VK_Mips_GPREL, VK_Mips_GOT_CALL, @@ -194,7 +196,9 @@ public: VK_Mips_GPOFF_LO, VK_Mips_GOT_DISP, VK_Mips_GOT_PAGE, - VK_Mips_GOT_OFST + VK_Mips_GOT_OFST, + VK_Mips_HIGHER, + VK_Mips_HIGHEST }; private: diff --git a/include/llvm/MC/MCFixupKindInfo.h b/include/llvm/MC/MCFixupKindInfo.h index 1961687..6979ad5 100644 --- a/include/llvm/MC/MCFixupKindInfo.h +++ b/include/llvm/MC/MCFixupKindInfo.h @@ -18,7 +18,7 @@ struct MCFixupKindInfo { /// Is this fixup kind PCrelative? This is used by the assembler backend to /// evaluate fixup values in a target independent manner when possible. FKF_IsPCRel = (1 << 0), - + /// Should this fixup kind force a 4-byte aligned effective PC value? FKF_IsAlignedDownTo32Bits = (1 << 1) }; diff --git a/include/llvm/MC/MCInstrItineraries.h b/include/llvm/MC/MCInstrItineraries.h index e942892..65d1559 100644 --- a/include/llvm/MC/MCInstrItineraries.h +++ b/include/llvm/MC/MCInstrItineraries.h @@ -16,6 +16,7 @@ #ifndef LLVM_MC_MCINSTRITINERARIES_H #define LLVM_MC_MCINSTRITINERARIES_H +#include "llvm/MC/MCSchedule.h" #include <algorithm> namespace llvm { @@ -95,7 +96,7 @@ struct InstrStage { /// operands are read and written. /// struct InstrItinerary { - unsigned NumMicroOps; ///< # of micro-ops, 0 means it's variable + int NumMicroOps; ///< # of micro-ops, -1 means it's variable unsigned FirstStage; ///< Index of first stage in itinerary unsigned LastStage; ///< Index of last + 1 stage in itinerary unsigned FirstOperandCycle; ///< Index of first operand rd/wr @@ -109,21 +110,22 @@ struct InstrItinerary { /// class InstrItineraryData { public: + const MCSchedModel *SchedModel; ///< Basic machine properties. const InstrStage *Stages; ///< Array of stages selected const unsigned *OperandCycles; ///< Array of operand cycles selected const unsigned *Forwardings; ///< Array of pipeline forwarding pathes const InstrItinerary *Itineraries; ///< Array of itineraries selected - unsigned IssueWidth; ///< Max issue per cycle. 0=Unknown. /// Ctors. /// - InstrItineraryData() : Stages(0), OperandCycles(0), Forwardings(0), - Itineraries(0), IssueWidth(0) {} + InstrItineraryData() : SchedModel(&MCSchedModel::DefaultSchedModel), + Stages(0), OperandCycles(0), + Forwardings(0), Itineraries(0) {} - InstrItineraryData(const InstrStage *S, const unsigned *OS, - const unsigned *F, const InstrItinerary *I) - : Stages(S), OperandCycles(OS), Forwardings(F), Itineraries(I), - IssueWidth(0) {} + InstrItineraryData(const MCSchedModel *SM, const InstrStage *S, + const unsigned *OS, const unsigned *F) + : SchedModel(SM), Stages(S), OperandCycles(OS), Forwardings(F), + Itineraries(SchedModel->InstrItineraries) {} /// isEmpty - Returns true if there are no itineraries. /// @@ -155,15 +157,17 @@ public: /// class. The latency is the maximum completion time for any stage /// in the itinerary. /// + /// InstrStages override the itinerary's MinLatency property. In fact, if the + /// stage latencies, which may be zero, are less than MinLatency, + /// getStageLatency returns a value less than MinLatency. + /// + /// If no stages exist, MinLatency is used. If MinLatency is invalid (<0), + /// then it defaults to one cycle. unsigned getStageLatency(unsigned ItinClassIndx) const { // If the target doesn't provide itinerary information, use a simple - // non-zero default value for all instructions. Some target's provide a - // dummy (Generic) itinerary which should be handled as if it's itinerary is - // empty. We identify this by looking for a reference to stage zero (invalid - // stage). This is different from beginStage == endState != 0, which could - // be used for zero-latency pseudo ops. - if (isEmpty() || Itineraries[ItinClassIndx].FirstStage == 0) - return 1; + // non-zero default value for all instructions. + if (isEmpty()) + return SchedModel->MinLatency < 0 ? 1 : SchedModel->MinLatency; // Calculate the maximum completion time for any stage. unsigned Latency = 0, StartCycle = 0; @@ -238,16 +242,16 @@ public: return UseCycle; } - /// isMicroCoded - Return true if the instructions in the given class decode - /// to more than one micro-ops. - bool isMicroCoded(unsigned ItinClassIndx) const { + /// getNumMicroOps - Return the number of micro-ops that the given class + /// decodes to. Return -1 for classes that require dynamic lookup via + /// TargetInstrInfo. + int getNumMicroOps(unsigned ItinClassIndx) const { if (isEmpty()) - return false; - return Itineraries[ItinClassIndx].NumMicroOps != 1; + return 1; + return Itineraries[ItinClassIndx].NumMicroOps; } }; - } // End llvm namespace #endif diff --git a/include/llvm/MC/MCMachObjectWriter.h b/include/llvm/MC/MCMachObjectWriter.h index 9bb598f..949d907 100644 --- a/include/llvm/MC/MCMachObjectWriter.h +++ b/include/llvm/MC/MCMachObjectWriter.h @@ -179,6 +179,9 @@ public: void WriteNlist(MachSymbolData &MSD, const MCAsmLayout &Layout); + void WriteLinkeditLoadCommand(uint32_t Type, uint32_t DataOffset, + uint32_t DataSize); + // FIXME: We really need to improve the relocation validation. Basically, we // want to implement a separate computation which evaluates the relocation // entry as the linker would, and verifies that the resultant fixup value is diff --git a/include/llvm/MC/MCObjectFileInfo.h b/include/llvm/MC/MCObjectFileInfo.h index aea4b41..74e2263 100644 --- a/include/llvm/MC/MCObjectFileInfo.h +++ b/include/llvm/MC/MCObjectFileInfo.h @@ -22,17 +22,17 @@ namespace llvm { class StringRef; class Triple; -class MCObjectFileInfo { +class MCObjectFileInfo { protected: /// CommDirectiveSupportsAlignment - True if .comm supports alignment. This /// is a hack for as long as we support 10.4 Tiger, whose assembler doesn't /// support alignment on comm. bool CommDirectiveSupportsAlignment; - + /// SupportsWeakEmptyEHFrame - True if target object file supports a /// weak_definition of constant 0 for an omitted EH frame. bool SupportsWeakOmittedEHFrame; - + /// IsFunctionEHFrameSymbolPrivate - This flag is set to true if the /// "EH_frame" symbol for EH information should be an assembler temporary (aka /// private linkage, aka an L or .L label) or false if it should be a normal @@ -53,20 +53,20 @@ protected: /// TextSection - Section directive for standard text. /// const MCSection *TextSection; - + /// DataSection - Section directive for standard data. /// const MCSection *DataSection; - + /// BSSSection - Section that is default initialized to zero. const MCSection *BSSSection; - + /// ReadOnlySection - Section that is readonly and can contain arbitrary /// initialized data. Targets are not required to have a readonly section. /// If they don't, various bits of code will fall back to using the data /// section for constants. const MCSection *ReadOnlySection; - + /// StaticCtorSection - This section contains the static constructor pointer /// list. const MCSection *StaticCtorSection; @@ -74,7 +74,7 @@ protected: /// StaticDtorSection - This section contains the static destructor pointer /// list. const MCSection *StaticDtorSection; - + /// LSDASection - If exception handling is supported by the target, this is /// the section the Language Specific Data Area information is emitted to. const MCSection *LSDASection; @@ -109,7 +109,7 @@ protected: // Extra TLS Variable Data section. If the target needs to put additional // information for a TLS variable, it'll go here. const MCSection *TLSExtraDataSection; - + /// TLSDataSection - Section directive for Thread Local data. /// ELF, MachO and COFF. const MCSection *TLSDataSection; // Defaults to ".tdata". @@ -141,11 +141,11 @@ protected: /// Contains the source code name of the variable, visibility and a pointer /// to the initial value (.tdata or .tbss). const MCSection *TLSTLVSection; // Defaults to ".tlv". - + /// TLSThreadInitSection - Section for thread local data initialization /// functions. const MCSection *TLSThreadInitSection; // Defaults to ".thread_init_func". - + const MCSection *CStringSection; const MCSection *UStringSection; const MCSection *TextCoalSection; @@ -169,7 +169,7 @@ protected: public: void InitMCObjectFileInfo(StringRef TT, Reloc::Model RM, CodeModel::Model CM, MCContext &ctx); - + bool isFunctionEHFrameSymbolPrivate() const { return IsFunctionEHFrameSymbolPrivate; } diff --git a/include/llvm/MC/MCObjectWriter.h b/include/llvm/MC/MCObjectWriter.h index 6e44e6ce..9591a00 100644 --- a/include/llvm/MC/MCObjectWriter.h +++ b/include/llvm/MC/MCObjectWriter.h @@ -182,11 +182,6 @@ public: /// @} - /// Utility function to encode a SLEB128 value. - static void EncodeSLEB128(int64_t Value, raw_ostream &OS); - /// Utility function to encode a ULEB128 value. - static void EncodeULEB128(uint64_t Value, raw_ostream &OS, - unsigned Padding = 0); }; } // End llvm namespace diff --git a/include/llvm/MC/MCRegisterInfo.h b/include/llvm/MC/MCRegisterInfo.h index 27acf2f..46a9d71 100644 --- a/include/llvm/MC/MCRegisterInfo.h +++ b/include/llvm/MC/MCRegisterInfo.h @@ -106,10 +106,18 @@ public: /// of AX. /// struct MCRegisterDesc { - const char *Name; // Printable name for the reg (for debugging) - uint32_t Overlaps; // Overlapping registers, described above - uint32_t SubRegs; // Sub-register set, described above - uint32_t SuperRegs; // Super-register set, described above + uint32_t Name; // Printable name for the reg (for debugging) + uint32_t Overlaps; // Overlapping registers, described above + uint32_t SubRegs; // Sub-register set, described above + uint32_t SuperRegs; // Super-register set, described above + + // Offset into MCRI::SubRegIndices of a list of sub-register indices for each + // sub-register in SubRegs. + uint32_t SubRegIndices; + + // RegUnits - Points to the list of register units. The low 4 bits holds the + // Scale, the high bits hold an offset into DiffLists. See MCRegUnitIterator. + uint32_t RegUnits; }; /// MCRegisterInfo base class - We assume that the target defines a static @@ -142,10 +150,15 @@ private: unsigned RAReg; // Return address register const MCRegisterClass *Classes; // Pointer to the regclass array unsigned NumClasses; // Number of entries in the array - const uint16_t *RegLists; // Pointer to the reglists array + unsigned NumRegUnits; // Number of regunits. + const uint16_t (*RegUnitRoots)[2]; // Pointer to regunit root table. + const uint16_t *DiffLists; // Pointer to the difflists array + const char *RegStrings; // Pointer to the string table. const uint16_t *SubRegIndices; // Pointer to the subreg lookup // array. unsigned NumSubRegIndices; // Number of subreg indices. + const uint16_t *RegEncodingTable; // Pointer to array of register + // encodings. unsigned L2DwarfRegsSize; unsigned EHL2DwarfRegsSize; @@ -158,21 +171,83 @@ private: DenseMap<unsigned, int> L2SEHRegs; // LLVM to SEH regs mapping public: + /// DiffListIterator - Base iterator class that can traverse the + /// differentially encoded register and regunit lists in DiffLists. + /// Don't use this class directly, use one of the specialized sub-classes + /// defined below. + class DiffListIterator { + uint16_t Val; + const uint16_t *List; + + protected: + /// Create an invalid iterator. Call init() to point to something useful. + DiffListIterator() : Val(0), List(0) {} + + /// init - Point the iterator to InitVal, decoding subsequent values from + /// DiffList. The iterator will initially point to InitVal, sub-classes are + /// responsible for skipping the seed value if it is not part of the list. + void init(uint16_t InitVal, const uint16_t *DiffList) { + Val = InitVal; + List = DiffList; + } + + /// advance - Move to the next list position, return the applied + /// differential. This function does not detect the end of the list, that + /// is the caller's responsibility (by checking for a 0 return value). + unsigned advance() { + assert(isValid() && "Cannot move off the end of the list."); + uint16_t D = *List++; + Val += D; + return D; + } + + public: + + /// isValid - returns true if this iterator is not yet at the end. + bool isValid() const { return List; } + + /// Dereference the iterator to get the value at the current position. + unsigned operator*() const { return Val; } + + /// Pre-increment to move to the next position. + void operator++() { + // The end of the list is encoded as a 0 differential. + if (!advance()) + List = 0; + } + }; + + // These iterators are allowed to sub-class DiffListIterator and access + // internal list pointers. + friend class MCSubRegIterator; + friend class MCSuperRegIterator; + friend class MCRegAliasIterator; + friend class MCRegUnitIterator; + friend class MCRegUnitRootIterator; + /// InitMCRegisterInfo - Initialize MCRegisterInfo, called by TableGen /// auto-generated routines. *DO NOT USE*. void InitMCRegisterInfo(const MCRegisterDesc *D, unsigned NR, unsigned RA, const MCRegisterClass *C, unsigned NC, - const uint16_t *RL, + const uint16_t (*RURoots)[2], + unsigned NRU, + const uint16_t *DL, + const char *Strings, const uint16_t *SubIndices, - unsigned NumIndices) { + unsigned NumIndices, + const uint16_t *RET) { Desc = D; NumRegs = NR; RAReg = RA; Classes = C; - RegLists = RL; + DiffLists = DL; + RegStrings = Strings; NumClasses = NC; + RegUnitRoots = RURoots; + NumRegUnits = NRU; SubRegIndices = SubIndices; NumSubRegIndices = NumIndices; + RegEncodingTable = RET; } /// mapLLVMRegsToDwarfRegs - Used to initialize LLVM register to Dwarf @@ -231,73 +306,25 @@ public: return operator[](RegNo); } - /// getAliasSet - Return the set of registers aliased by the specified - /// register, or a null list of there are none. The list returned is zero - /// terminated. - /// - const uint16_t *getAliasSet(unsigned RegNo) const { - // The Overlaps set always begins with Reg itself. - return RegLists + get(RegNo).Overlaps + 1; - } - - /// getOverlaps - Return a list of registers that overlap Reg, including - /// itself. This is the same as the alias set except Reg is included in the - /// list. - /// These are exactly the registers in { x | regsOverlap(x, Reg) }. - /// - const uint16_t *getOverlaps(unsigned RegNo) const { - return RegLists + get(RegNo).Overlaps; - } - - /// getSubRegisters - Return the list of registers that are sub-registers of - /// the specified register, or a null list of there are none. The list - /// returned is zero terminated and sorted according to super-sub register - /// relations. e.g. X86::RAX's sub-register list is EAX, AX, AL, AH. - /// - const uint16_t *getSubRegisters(unsigned RegNo) const { - return RegLists + get(RegNo).SubRegs; - } - /// getSubReg - Returns the physical register number of sub-register "Index" /// for physical register RegNo. Return zero if the sub-register does not /// exist. - unsigned getSubReg(unsigned Reg, unsigned Idx) const { - return *(SubRegIndices + (Reg - 1) * NumSubRegIndices + Idx - 1); - } + unsigned getSubReg(unsigned Reg, unsigned Idx) const; /// getMatchingSuperReg - Return a super-register of the specified register /// Reg so its sub-register of index SubIdx is Reg. unsigned getMatchingSuperReg(unsigned Reg, unsigned SubIdx, - const MCRegisterClass *RC) const { - for (const uint16_t *SRs = getSuperRegisters(Reg); unsigned SR = *SRs;++SRs) - if (Reg == getSubReg(SR, SubIdx) && RC->contains(SR)) - return SR; - return 0; - } + const MCRegisterClass *RC) const; /// getSubRegIndex - For a given register pair, return the sub-register index /// if the second register is a sub-register of the first. Return zero /// otherwise. - unsigned getSubRegIndex(unsigned RegNo, unsigned SubRegNo) const { - for (unsigned I = 1; I <= NumSubRegIndices; ++I) - if (getSubReg(RegNo, I) == SubRegNo) - return I; - return 0; - } - - /// getSuperRegisters - Return the list of registers that are super-registers - /// of the specified register, or a null list of there are none. The list - /// returned is zero terminated and sorted according to super-sub register - /// relations. e.g. X86::AL's super-register list is AX, EAX, RAX. - /// - const uint16_t *getSuperRegisters(unsigned RegNo) const { - return RegLists + get(RegNo).SuperRegs; - } + unsigned getSubRegIndex(unsigned RegNo, unsigned SubRegNo) const; /// getName - Return the human-readable symbolic target-specific name for the /// specified physical register. const char *getName(unsigned RegNo) const { - return get(RegNo).Name; + return RegStrings + get(RegNo).Name; } /// getNumRegs - Return the number of registers this target has (useful for @@ -306,40 +333,26 @@ public: return NumRegs; } + /// getNumRegUnits - Return the number of (native) register units in the + /// target. Register units are numbered from 0 to getNumRegUnits() - 1. They + /// can be accessed through MCRegUnitIterator defined below. + unsigned getNumRegUnits() const { + return NumRegUnits; + } + /// getDwarfRegNum - Map a target register to an equivalent dwarf register /// number. Returns -1 if there is no equivalent value. The second /// parameter allows targets to use different numberings for EH info and /// debugging info. - int getDwarfRegNum(unsigned RegNum, bool isEH) const { - const DwarfLLVMRegPair *M = isEH ? EHL2DwarfRegs : L2DwarfRegs; - unsigned Size = isEH ? EHL2DwarfRegsSize : L2DwarfRegsSize; - - DwarfLLVMRegPair Key = { RegNum, 0 }; - const DwarfLLVMRegPair *I = std::lower_bound(M, M+Size, Key); - if (I == M+Size || I->FromReg != RegNum) - return -1; - return I->ToReg; - } + int getDwarfRegNum(unsigned RegNum, bool isEH) const; /// getLLVMRegNum - Map a dwarf register back to a target register. /// - int getLLVMRegNum(unsigned RegNum, bool isEH) const { - const DwarfLLVMRegPair *M = isEH ? EHDwarf2LRegs : Dwarf2LRegs; - unsigned Size = isEH ? EHDwarf2LRegsSize : Dwarf2LRegsSize; - - DwarfLLVMRegPair Key = { RegNum, 0 }; - const DwarfLLVMRegPair *I = std::lower_bound(M, M+Size, Key); - assert(I != M+Size && I->FromReg == RegNum && "Invalid RegNum"); - return I->ToReg; - } + int getLLVMRegNum(unsigned RegNum, bool isEH) const; /// getSEHRegNum - Map a target register to an equivalent SEH register /// number. Returns LLVM register number if there is no equivalent value. - int getSEHRegNum(unsigned RegNum) const { - const DenseMap<unsigned, int>::const_iterator I = L2SEHRegs.find(RegNum); - if (I == L2SEHRegs.end()) return (int)RegNum; - return I->second; - } + int getSEHRegNum(unsigned RegNum) const; regclass_iterator regclass_begin() const { return Classes; } regclass_iterator regclass_end() const { return Classes+NumClasses; } @@ -354,6 +367,128 @@ public: assert(i < getNumRegClasses() && "Register Class ID out of range"); return Classes[i]; } + + /// getEncodingValue - Returns the encoding for RegNo + uint16_t getEncodingValue(unsigned RegNo) const { + assert(RegNo < NumRegs && + "Attempting to get encoding for invalid register number!"); + return RegEncodingTable[RegNo]; + } + +}; + +//===----------------------------------------------------------------------===// +// Register List Iterators +//===----------------------------------------------------------------------===// + +// MCRegisterInfo provides lists of super-registers, sub-registers, and +// aliasing registers. Use these iterator classes to traverse the lists. + +/// MCSubRegIterator enumerates all sub-registers of Reg. +class MCSubRegIterator : public MCRegisterInfo::DiffListIterator { +public: + MCSubRegIterator(unsigned Reg, const MCRegisterInfo *MCRI) { + init(Reg, MCRI->DiffLists + MCRI->get(Reg).SubRegs); + ++*this; + } +}; + +/// MCSuperRegIterator enumerates all super-registers of Reg. +class MCSuperRegIterator : public MCRegisterInfo::DiffListIterator { +public: + MCSuperRegIterator(unsigned Reg, const MCRegisterInfo *MCRI) { + init(Reg, MCRI->DiffLists + MCRI->get(Reg).SuperRegs); + ++*this; + } +}; + +/// MCRegAliasIterator enumerates all registers aliasing Reg. +/// If IncludeSelf is set, Reg itself is included in the list. +class MCRegAliasIterator : public MCRegisterInfo::DiffListIterator { +public: + MCRegAliasIterator(unsigned Reg, const MCRegisterInfo *MCRI, + bool IncludeSelf) { + init(Reg, MCRI->DiffLists + MCRI->get(Reg).Overlaps); + // Initially, the iterator points to Reg itself. + if (!IncludeSelf) + ++*this; + } +}; + +//===----------------------------------------------------------------------===// +// Register Units +//===----------------------------------------------------------------------===// + +// Register units are used to compute register aliasing. Every register has at +// least one register unit, but it can have more. Two registers overlap if and +// only if they have a common register unit. +// +// A target with a complicated sub-register structure will typically have many +// fewer register units than actual registers. MCRI::getNumRegUnits() returns +// the number of register units in the target. + +// MCRegUnitIterator enumerates a list of register units for Reg. The list is +// in ascending numerical order. +class MCRegUnitIterator : public MCRegisterInfo::DiffListIterator { +public: + /// MCRegUnitIterator - Create an iterator that traverses the register units + /// in Reg. + MCRegUnitIterator(unsigned Reg, const MCRegisterInfo *MCRI) { + // Decode the RegUnits MCRegisterDesc field. + unsigned RU = MCRI->get(Reg).RegUnits; + unsigned Scale = RU & 15; + unsigned Offset = RU >> 4; + + // Initialize the iterator to Reg * Scale, and the List pointer to + // DiffLists + Offset. + init(Reg * Scale, MCRI->DiffLists + Offset); + + // That may not be a valid unit, we need to advance by one to get the real + // unit number. The first differential can be 0 which would normally + // terminate the list, but since we know every register has at least one + // unit, we can allow a 0 differential here. + advance(); + } +}; + +// Each register unit has one or two root registers. The complete set of +// registers containing a register unit is the union of the roots and their +// super-registers. All registers aliasing Unit can be visited like this: +// +// for (MCRegUnitRootIterator RI(Unit, MCRI); RI.isValid(); ++RI) { +// unsigned Root = *RI; +// visit(Root); +// for (MCSuperRegIterator SI(Root, MCRI); SI.isValid(); ++SI) +// visit(*SI); +// } + +/// MCRegUnitRootIterator enumerates the root registers of a register unit. +class MCRegUnitRootIterator { + uint16_t Reg0; + uint16_t Reg1; +public: + MCRegUnitRootIterator(unsigned RegUnit, const MCRegisterInfo *MCRI) { + assert(RegUnit < MCRI->getNumRegUnits() && "Invalid register unit"); + Reg0 = MCRI->RegUnitRoots[RegUnit][0]; + Reg1 = MCRI->RegUnitRoots[RegUnit][1]; + } + + /// Dereference to get the current root register. + unsigned operator*() const { + return Reg0; + } + + /// isValid - Check if the iterator is at the end of the list. + bool isValid() const { + return Reg0; + } + + /// Preincrement to move to the next root register. + void operator++() { + assert(isValid() && "Cannot move off the end of the list."); + Reg0 = Reg1; + Reg1 = 0; + } }; } // End llvm namespace diff --git a/include/llvm/MC/MCSchedule.h b/include/llvm/MC/MCSchedule.h new file mode 100644 index 0000000..3b1cdf1 --- /dev/null +++ b/include/llvm/MC/MCSchedule.h @@ -0,0 +1,114 @@ +//===-- llvm/MC/MCSchedule.h - Scheduling -----------------------*- 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 classes used to describe a subtarget's machine model +// for scheduling and other instruction cost heuristics. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCSCHEDMODEL_H +#define LLVM_MC_MCSCHEDMODEL_H + +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +struct InstrItinerary; + +/// Machine model for scheduling, bundling, and heuristics. +/// +/// The machine model directly provides basic information about the +/// microarchitecture to the scheduler in the form of properties. It also +/// optionally refers to scheduler resources tables and itinerary +/// tables. Scheduler resources tables model the latency and cost for each +/// instruction type. Itinerary tables are an independant mechanism that +/// provides a detailed reservation table describing each cycle of instruction +/// execution. Subtargets may define any or all of the above categories of data +/// depending on the type of CPU and selected scheduler. +class MCSchedModel { +public: + static MCSchedModel DefaultSchedModel; // For unknown processors. + + // IssueWidth is the maximum number of instructions that may be scheduled in + // the same per-cycle group. + unsigned IssueWidth; + static const unsigned DefaultIssueWidth = 1; + + // MinLatency is the minimum latency between a register write + // followed by a data dependent read. This determines which + // instructions may be scheduled in the same per-cycle group. This + // is distinct from *expected* latency, which determines the likely + // critical path but does not guarantee a pipeline + // hazard. MinLatency can always be overridden by the number of + // InstrStage cycles. + // + // (-1) Standard in-order processor. + // Use InstrItinerary OperandCycles as MinLatency. + // If no OperandCycles exist, then use the cycle of the last InstrStage. + // + // (0) Out-of-order processor, or in-order with bundled dependencies. + // RAW dependencies may be dispatched in the same cycle. + // Optional InstrItinerary OperandCycles provides expected latency. + // + // (>0) In-order processor with variable latencies. + // Use the greater of this value or the cycle of the last InstrStage. + // Optional InstrItinerary OperandCycles provides expected latency. + // TODO: can't yet specify both min and expected latency per operand. + int MinLatency; + static const unsigned DefaultMinLatency = -1; + + // LoadLatency is the expected latency of load instructions. + // + // If MinLatency >= 0, this may be overriden for individual load opcodes by + // InstrItinerary OperandCycles. + unsigned LoadLatency; + static const unsigned DefaultLoadLatency = 4; + + // HighLatency is the expected latency of "very high latency" operations. + // See TargetInstrInfo::isHighLatencyDef(). + // By default, this is set to an arbitrarily high number of cycles + // likely to have some impact on scheduling heuristics. + // If MinLatency >= 0, this may be overriden by InstrItinData OperandCycles. + unsigned HighLatency; + static const unsigned DefaultHighLatency = 10; + + // MispredictPenalty is the typical number of extra cycles the processor + // takes to recover from a branch misprediction. + unsigned MispredictPenalty; + static const unsigned DefaultMispredictPenalty = 10; + +private: + // TODO: Add a reference to proc resource types and sched resource tables. + + // Instruction itinerary tables used by InstrItineraryData. + friend class InstrItineraryData; + const InstrItinerary *InstrItineraries; + +public: + // Default's must be specified as static const literals so that tablegenerated + // target code can use it in static initializers. The defaults need to be + // initialized in this default ctor because some clients directly instantiate + // MCSchedModel instead of using a generated itinerary. + MCSchedModel(): IssueWidth(DefaultIssueWidth), + MinLatency(DefaultMinLatency), + LoadLatency(DefaultLoadLatency), + HighLatency(DefaultHighLatency), + MispredictPenalty(DefaultMispredictPenalty), + InstrItineraries(0) {} + + // Table-gen driven ctor. + MCSchedModel(unsigned iw, int ml, unsigned ll, unsigned hl, unsigned mp, + const InstrItinerary *ii): + IssueWidth(iw), MinLatency(ml), LoadLatency(ll), HighLatency(hl), + MispredictPenalty(mp), InstrItineraries(ii){} +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 2595600..e8c3e59 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -69,22 +69,7 @@ namespace llvm { SmallVector<std::pair<const MCSection *, const MCSection *>, 4> SectionStack; - unsigned UniqueCodeBeginSuffix; - unsigned UniqueDataBeginSuffix; - protected: - /// Indicator of whether the previous data-or-code indicator was for - /// code or not. Used to determine when we need to emit a new indicator. - enum DataType { - Data, - Code, - JumpTable8, - JumpTable16, - JumpTable32 - }; - DataType RegionIndicator; - - MCStreamer(MCContext &Ctx); const MCExpr *BuildSymbolDiff(MCContext &Context, const MCSymbol *A, @@ -241,47 +226,15 @@ namespace llvm { /// used in an assignment. virtual void EmitLabel(MCSymbol *Symbol); - /// EmitDataRegion - Emit a label that marks the beginning of a data - /// region. - /// On ELF targets, this corresponds to an assembler statement such as: - /// $d.1: - virtual void EmitDataRegion(); - - /// EmitJumpTable8Region - Emit a label that marks the beginning of a - /// jump table composed of 8-bit offsets. - /// On ELF targets, this corresponds to an assembler statement such as: - /// $d.1: - virtual void EmitJumpTable8Region(); - - /// EmitJumpTable16Region - Emit a label that marks the beginning of a - /// jump table composed of 16-bit offsets. - /// On ELF targets, this corresponds to an assembler statement such as: - /// $d.1: - virtual void EmitJumpTable16Region(); - - /// EmitJumpTable32Region - Emit a label that marks the beginning of a - /// jump table composed of 32-bit offsets. - /// On ELF targets, this corresponds to an assembler statement such as: - /// $d.1: - virtual void EmitJumpTable32Region(); - - /// EmitCodeRegion - Emit a label that marks the beginning of a code - /// region. - /// On ELF targets, this corresponds to an assembler statement such as: - /// $a.1: - virtual void EmitCodeRegion(); - - /// ForceCodeRegion - Forcibly sets the current region mode to code. Used - /// at function entry points. - void ForceCodeRegion() { RegionIndicator = Code; } - - virtual void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol); - /// EmitAssemblerFlag - Note in the output the specified @p Flag + /// EmitAssemblerFlag - Note in the output the specified @p Flag. virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) = 0; + /// EmitDataRegion - Note in the output the specified region @p Kind. + virtual void EmitDataRegion(MCDataRegionType Kind) {} + /// EmitThumbFunc - Note in the output that the specified @p Func is /// a Thumb mode function (ARM target only). virtual void EmitThumbFunc(MCSymbol *Func) = 0; @@ -373,7 +326,7 @@ namespace llvm { /// @param ByteAlignment - The alignment of the zerofill symbol if /// non-zero. This must be a power of 2 on some targets. virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, - unsigned Size = 0,unsigned ByteAlignment = 0) = 0; + uint64_t Size = 0,unsigned ByteAlignment = 0) = 0; /// EmitTBSSSymbol - Emit a thread local bss (.tbss) symbol. /// diff --git a/include/llvm/MC/MCSubtargetInfo.h b/include/llvm/MC/MCSubtargetInfo.h index 3b53f20..31d632d 100644 --- a/include/llvm/MC/MCSubtargetInfo.h +++ b/include/llvm/MC/MCSubtargetInfo.h @@ -30,10 +30,10 @@ class MCSubtargetInfo { std::string TargetTriple; // Target triple const SubtargetFeatureKV *ProcFeatures; // Processor feature list const SubtargetFeatureKV *ProcDesc; // Processor descriptions - const SubtargetInfoKV *ProcItins; // Scheduling itineraries - const InstrStage *Stages; // Instruction stages - const unsigned *OperandCycles; // Operand cycles - const unsigned *ForwardingPathes; // Forwarding pathes + const SubtargetInfoKV *ProcSchedModel; // Scheduler machine model + const InstrStage *Stages; // Instruction itinerary stages + const unsigned *OperandCycles; // Itinerary operand cycles + const unsigned *ForwardingPaths; // Forwarding paths unsigned NumFeatures; // Number of processor features unsigned NumProcs; // Number of processors uint64_t FeatureBits; // Feature bits for current CPU + FS @@ -42,7 +42,8 @@ public: void InitMCSubtargetInfo(StringRef TT, StringRef CPU, StringRef FS, const SubtargetFeatureKV *PF, const SubtargetFeatureKV *PD, - const SubtargetInfoKV *PI, const InstrStage *IS, + const SubtargetInfoKV *ProcSched, + const InstrStage *IS, const unsigned *OC, const unsigned *FP, unsigned NF, unsigned NP); @@ -69,6 +70,10 @@ public: /// bits. This version will also change all implied bits. uint64_t ToggleFeature(StringRef FS); + /// getSchedModelForCPU - Get the machine model of a CPU. + /// + MCSchedModel *getSchedModelForCPU(StringRef CPU) const; + /// getInstrItineraryForCPU - Get scheduling itinerary of a CPU. /// InstrItineraryData getInstrItineraryForCPU(StringRef CPU) const; diff --git a/include/llvm/MC/MCTargetAsmLexer.h b/include/llvm/MC/MCTargetAsmLexer.h index acb3d4d..f5c8c09 100644 --- a/include/llvm/MC/MCTargetAsmLexer.h +++ b/include/llvm/MC/MCTargetAsmLexer.h @@ -14,72 +14,72 @@ namespace llvm { class Target; - + /// MCTargetAsmLexer - Generic interface to target specific assembly lexers. class MCTargetAsmLexer { /// The current token AsmToken CurTok; - + /// The location and description of the current error SMLoc ErrLoc; std::string Err; - + MCTargetAsmLexer(const MCTargetAsmLexer &); // DO NOT IMPLEMENT void operator=(const MCTargetAsmLexer &); // DO NOT IMPLEMENT protected: // Can only create subclasses. MCTargetAsmLexer(const Target &); - + virtual AsmToken LexToken() = 0; - + void SetError(const SMLoc &errLoc, const std::string &err) { ErrLoc = errLoc; Err = err; } - + /// TheTarget - The Target that this machine was created for. const Target &TheTarget; MCAsmLexer *Lexer; - + public: virtual ~MCTargetAsmLexer(); - + const Target &getTarget() const { return TheTarget; } - + /// InstallLexer - Set the lexer to get tokens from lower-level lexer \arg L. void InstallLexer(MCAsmLexer &L) { Lexer = &L; } - + MCAsmLexer *getLexer() { return Lexer; } - + /// Lex - Consume the next token from the input stream and return it. const AsmToken &Lex() { return CurTok = LexToken(); } - + /// getTok - Get the current (last) lexed token. const AsmToken &getTok() { return CurTok; } - + /// getErrLoc - Get the current error location const SMLoc &getErrLoc() { return ErrLoc; } - + /// getErr - Get the current error string const std::string &getErr() { return Err; } - + /// getKind - Get the kind of current token. AsmToken::TokenKind getKind() const { return CurTok.getKind(); } - + /// is - Check if the current token has kind \arg K. bool is(AsmToken::TokenKind K) const { return CurTok.is(K); } - + /// isNot - Check if the current token has kind \arg K. bool isNot(AsmToken::TokenKind K) const { return CurTok.isNot(K); } }; diff --git a/include/llvm/MC/MCTargetAsmParser.h b/include/llvm/MC/MCTargetAsmParser.h index 4e3fd0d..929a204 100644 --- a/include/llvm/MC/MCTargetAsmParser.h +++ b/include/llvm/MC/MCTargetAsmParser.h @@ -79,6 +79,19 @@ public: /// \param DirectiveID - the identifier token of the directive. virtual bool ParseDirective(AsmToken DirectiveID) = 0; + /// MatchInstruction - Recognize a series of operands of a parsed instruction + /// as an actual MCInst. This returns false on success and returns true on + /// failure to match. + /// + /// On failure, the target parser is responsible for emitting a diagnostic + /// explaining the match failure. + virtual bool + MatchInstruction(SMLoc IDLoc, + SmallVectorImpl<MCParsedAsmOperand*> &Operands, + SmallVectorImpl<MCInst> &MCInsts) { + return true; + } + /// MatchAndEmitInstruction - Recognize a series of operands of a parsed /// instruction as an actual MCInst and emit it to the specified MCStreamer. /// This returns false on success and returns true on failure to match. diff --git a/include/llvm/MC/MachineLocation.h b/include/llvm/MC/MachineLocation.h index 8ddfdbc..5caad33 100644 --- a/include/llvm/MC/MachineLocation.h +++ b/include/llvm/MC/MachineLocation.h @@ -11,7 +11,7 @@ // from a base address plus an offset. Register indirection can be specified by // using an offset of zero. // -// The MachineMove class is used to represent abstract move operations in the +// The MachineMove class is used to represent abstract move operations in the // prolog/epilog of a compiled function. A collection of these objects can be // used by a debug consumer to track the location of values when unwinding stack // frames. @@ -23,7 +23,7 @@ namespace llvm { class MCSymbol; - + class MachineLocation { private: bool IsRegister; // True if location is a register. @@ -46,7 +46,7 @@ public: return IsRegister == Other.IsRegister && Register == Other.Register && Offset == Other.Offset; } - + // Accessors bool isReg() const { return IsRegister; } unsigned getReg() const { return Register; } @@ -77,7 +77,7 @@ private: /// Label - Symbol for post-instruction address when result of move takes /// effect. MCSymbol *Label; - + // Move to & from location. MachineLocation Destination, Source; public: @@ -86,7 +86,7 @@ public: MachineMove(MCSymbol *label, const MachineLocation &D, const MachineLocation &S) : Label(label), Destination(D), Source(S) {} - + // Accessors MCSymbol *getLabel() const { return Label; } const MachineLocation &getDestination() const { return Destination; } diff --git a/include/llvm/MC/SubtargetFeature.h b/include/llvm/MC/SubtargetFeature.h index 1a7dc92..507d882 100644 --- a/include/llvm/MC/SubtargetFeature.h +++ b/include/llvm/MC/SubtargetFeature.h @@ -25,7 +25,7 @@ namespace llvm { class raw_ostream; class StringRef; - + //===----------------------------------------------------------------------===// /// /// SubtargetFeatureKV - Used to provide key value pairs for feature and @@ -36,13 +36,13 @@ struct SubtargetFeatureKV { const char *Desc; // Help descriptor uint64_t Value; // K-V integer value uint64_t Implies; // K-V bit mask - + // Compare routine for std binary search bool operator<(const SubtargetFeatureKV &S) const { return strcmp(Key, S.Key) < 0; } }; - + //===----------------------------------------------------------------------===// /// /// SubtargetInfoKV - Used to provide key value pairs for CPU and arbitrary @@ -51,16 +51,16 @@ struct SubtargetFeatureKV { struct SubtargetInfoKV { const char *Key; // K-V key string void *Value; // K-V pointer value - + // Compare routine for std binary search bool operator<(const SubtargetInfoKV &S) const { return strcmp(Key, S.Key) < 0; } }; - + //===----------------------------------------------------------------------===// /// -/// SubtargetFeatures - Manages the enabling and disabling of subtarget +/// SubtargetFeatures - Manages the enabling and disabling of subtarget /// specific features. Features are encoded as a string of the form /// "cpu,+attr1,+attr2,-attr3,...,+attrN" /// A comma separates each feature from the next (all lowercase.) @@ -81,27 +81,27 @@ public: /// Adding Features. void AddFeature(const StringRef String, bool IsEnabled = true); - + /// ToggleFeature - Toggle a feature and returns the newly updated feature /// bits. uint64_t ToggleFeature(uint64_t Bits, const StringRef String, const SubtargetFeatureKV *FeatureTable, size_t FeatureTableSize); - + /// Get feature bits of a CPU. uint64_t getFeatureBits(const StringRef CPU, const SubtargetFeatureKV *CPUTable, size_t CPUTableSize, const SubtargetFeatureKV *FeatureTable, size_t FeatureTableSize); - + /// Get scheduling itinerary of a CPU. void *getItinerary(const StringRef CPU, const SubtargetInfoKV *Table, size_t TableSize); - + /// Print feature string. void print(raw_ostream &OS) const; - + // Dump feature info. void dump() const; diff --git a/include/llvm/Support/MDBuilder.h b/include/llvm/MDBuilder.h index 40f028a..2aa48b0 100644 --- a/include/llvm/Support/MDBuilder.h +++ b/include/llvm/MDBuilder.h @@ -1,4 +1,4 @@ -//===---- llvm/Support/MDBuilder.h - Builder for LLVM metadata --*- C++ -*-===// +//===---- llvm/MDBuilder.h - Builder for LLVM metadata ----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_MDBUILDER_H -#define LLVM_SUPPORT_MDBUILDER_H +#ifndef LLVM_MDBUILDER_H +#define LLVM_MDBUILDER_H #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" @@ -49,6 +49,29 @@ namespace llvm { 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. diff --git a/include/llvm/Metadata.h b/include/llvm/Metadata.h index 7357986..b40549b 100644 --- a/include/llvm/Metadata.h +++ b/include/llvm/Metadata.h @@ -165,6 +165,11 @@ public: 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(); diff --git a/include/llvm/Module.h b/include/llvm/Module.h index b9c9881..e6303ac 100644 --- a/include/llvm/Module.h +++ b/include/llvm/Module.h @@ -301,10 +301,6 @@ public: typedef DenseMap<StructType*, unsigned, DenseMapInfo<StructType*> > NumeredTypesMapTy; - /// findUsedStructTypes - Walk the entire module and find all of the - /// struct types that are in use, returning them in a vector. - void findUsedStructTypes(std::vector<StructType*> &StructTypes) const; - /// getTypeByName - Return the type with the specified name, or null if there /// is none by that name. StructType *getTypeByName(StringRef Name) const; @@ -497,6 +493,13 @@ public: 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. diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h index 77a08d5..befe812 100644 --- a/include/llvm/Object/Binary.h +++ b/include/llvm/Object/Binary.h @@ -90,7 +90,7 @@ public: /// @brief Create a Binary from Source, autodetecting the file type. /// -/// @param Source The data to create the Binary from. Ownership is transfered +/// @param Source The data to create the Binary from. Ownership is transferred /// to Result if successful. If an error is returned, Source is destroyed /// by createBinary before returning. /// @param Result A pointer to the resulting Binary if no error occured. diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index 68b5ca1..967420e 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -168,6 +168,10 @@ public: virtual section_iterator begin_sections() const; virtual section_iterator end_sections() const; + const coff_section *getCOFFSection(section_iterator &It) const; + const coff_symbol *getCOFFSymbol(symbol_iterator &It) const; + const coff_relocation *getCOFFRelocation(relocation_iterator &It) const; + virtual uint8_t getBytesInAddress() const; virtual StringRef getFileFormatName() const; virtual unsigned getArch() const; @@ -184,6 +188,8 @@ public: return ec; } error_code getSymbolName(const coff_symbol *symbol, StringRef &Res) const; + ArrayRef<uint8_t> getSymbolAuxData(const coff_symbol *symbol) const; + error_code getSectionName(const coff_section *Sec, StringRef &Res) const; error_code getSectionContents(const coff_section *Sec, ArrayRef<uint8_t> &Res) const; diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index e493f5b..7698441 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -217,7 +217,7 @@ struct Elf_Verdef_Impl { } }; -/// Elf_Verdaux: This is the structure of auxilary data in the SHT_GNU_verdef +/// Elf_Verdaux: This is the structure of auxiliary data in the SHT_GNU_verdef /// section (.gnu.version_d). This structure is identical for ELF32 and ELF64. template<support::endianness target_endianness, bool is64Bits> struct Elf_Verdaux_Impl { @@ -505,9 +505,6 @@ private: const Elf_Rela *getRela(DataRefImpl Rela) const; const char *getString(uint32_t section, uint32_t offset) const; const char *getString(const Elf_Shdr *section, uint32_t offset) const; - error_code getSymbolName(const Elf_Shdr *section, - const Elf_Sym *Symb, - StringRef &Res) const; error_code getSymbolVersion(const Elf_Shdr *section, const Elf_Sym *Symb, StringRef &Version, @@ -519,6 +516,11 @@ protected: void validateSymbol(DataRefImpl Symb) const; public: + error_code getSymbolName(const Elf_Shdr *section, + const Elf_Sym *Symb, + StringRef &Res) const; + error_code getSectionName(const Elf_Shdr *section, + StringRef &Res) const; const Elf_Dyn *getDyn(DataRefImpl DynData) const; error_code getSymbolVersion(SymbolRef Symb, StringRef &Version, bool &IsDefault) const; @@ -597,11 +599,15 @@ public: virtual StringRef getObjectType() const { return "ELF"; } virtual unsigned getArch() const; virtual StringRef getLoadName() const; + virtual error_code getSectionContents(const Elf_Shdr *sec, + StringRef &Res) const; uint64_t getNumSections() const; uint64_t getStringTableIndex() const; ELF::Elf64_Word getSymbolTableIndex(const Elf_Sym *symb) const; const Elf_Shdr *getSection(const Elf_Sym *symb) const; + const Elf_Shdr *getElfSection(section_iterator &It) const; + const Elf_Sym *getElfSymbol(symbol_iterator &It) const; // Methods for type inquiry through isa, cast, and dyn_cast bool isDyldType() const { return isDyldELFObject; } @@ -783,6 +789,21 @@ ELFObjectFile<target_endianness, is64Bits> } template<support::endianness target_endianness, bool is64Bits> +const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr * +ELFObjectFile<target_endianness, is64Bits> + ::getElfSection(section_iterator &It) const { + llvm::object::DataRefImpl ShdrRef = It->getRawDataRefImpl(); + return reinterpret_cast<const Elf_Shdr *>(ShdrRef.p); +} + +template<support::endianness target_endianness, bool is64Bits> +const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Sym * +ELFObjectFile<target_endianness, is64Bits> + ::getElfSymbol(symbol_iterator &It) const { + return getSymbol(It->getRawDataRefImpl()); +} + +template<support::endianness target_endianness, bool is64Bits> error_code ELFObjectFile<target_endianness, is64Bits> ::getSymbolFileOffset(DataRefImpl Symb, uint64_t &Result) const { @@ -1060,6 +1081,15 @@ error_code ELFObjectFile<target_endianness, is64Bits> template<support::endianness target_endianness, bool is64Bits> error_code ELFObjectFile<target_endianness, is64Bits> + ::getSectionContents(const Elf_Shdr *Sec, + StringRef &Result) const { + const char *start = (const char*)base() + Sec->sh_offset; + Result = StringRef(start, Sec->sh_size); + return object_error::success; +} + +template<support::endianness target_endianness, bool is64Bits> +error_code ELFObjectFile<target_endianness, is64Bits> ::getSectionAlignment(DataRefImpl Sec, uint64_t &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); @@ -1414,6 +1444,98 @@ error_code ELFObjectFile<target_endianness, is64Bits> res = "Unknown"; } break; + case ELF::EM_HEXAGON: + switch (type) { + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_NONE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B22_PCREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B15_PCREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B7_PCREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_8); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GPREL16_0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GPREL16_1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GPREL16_2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GPREL16_3); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_HL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B13_PCREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B9_PCREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B32_PCREL_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_32_6_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B22_PCREL_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B15_PCREL_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B13_PCREL_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B9_PCREL_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B7_PCREL_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_16_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_12_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_11_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_10_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_9_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_8_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_7_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_6_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_32_PCREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_COPY); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GLOB_DAT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_JMP_SLOT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_RELATIVE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_PLT_B22_PCREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPMOD_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_PLT_B22_PCREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_6_PCREL_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_32_6_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_16_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_11_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_32_6_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_16_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_11_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_32_6_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_16_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_11_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_32_6_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_16_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_11_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_32_6_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_16_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_32_6_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_16_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_11_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_32_6_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_16_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_11_X); + default: + res = "Unknown"; + } + break; default: res = "Unknown"; } @@ -1489,6 +1611,9 @@ error_code ELFObjectFile<target_endianness, is64Bits> res = "Unknown"; } break; + case ELF::EM_HEXAGON: + res = symname; + break; default: res = "Unknown"; } @@ -1888,6 +2013,8 @@ StringRef ELFObjectFile<target_endianness, is64Bits> return "ELF32-x86-64"; case ELF::EM_ARM: return "ELF32-arm"; + case ELF::EM_HEXAGON: + return "ELF32-hexagon"; default: return "ELF32-unknown"; } @@ -1915,6 +2042,8 @@ unsigned ELFObjectFile<target_endianness, is64Bits>::getArch() const { return Triple::x86_64; case ELF::EM_ARM: return Triple::arm; + case ELF::EM_HEXAGON: + return Triple::hexagon; default: return Triple::UnknownArch; } @@ -2054,6 +2183,14 @@ error_code ELFObjectFile<target_endianness, is64Bits> template<support::endianness target_endianness, bool is64Bits> error_code ELFObjectFile<target_endianness, is64Bits> + ::getSectionName(const Elf_Shdr *section, + StringRef &Result) const { + Result = StringRef(getString(dot_shstrtab_sec, section->sh_name)); + return object_error::success; +} + +template<support::endianness target_endianness, bool is64Bits> +error_code ELFObjectFile<target_endianness, is64Bits> ::getSymbolVersion(const Elf_Shdr *section, const Elf_Sym *symb, StringRef &Version, diff --git a/include/llvm/Object/MachOFormat.h b/include/llvm/Object/MachOFormat.h index 089cde9..f30d431 100644 --- a/include/llvm/Object/MachOFormat.h +++ b/include/llvm/Object/MachOFormat.h @@ -97,7 +97,8 @@ namespace macho { DysymtabLoadCommandSize = 80, Nlist32Size = 12, Nlist64Size = 16, - RelocationInfoSize = 8 + RelocationInfoSize = 8, + LinkeditLoadCommandSize = 16 }; /// \brief Constants for header magic field. @@ -140,7 +141,8 @@ namespace macho { LCT_UUID = 0x1b, LCT_CodeSignature = 0x1d, LCT_SegmentSplitInfo = 0x1e, - LCT_FunctionStarts = 0x26 + LCT_FunctionStarts = 0x26, + LCT_DataInCode = 0x29 }; /// \brief Load command structure. @@ -280,6 +282,18 @@ namespace macho { }; /// @} + /// @name Data-in-code Table Entry + /// @{ + + // See <mach-o/loader.h>. + enum DataRegionType { Data = 1, JumpTable8, JumpTable16, JumpTable32 }; + struct DataInCodeTableEntry { + uint32_t Offset; /* from mach_header to start of data region */ + uint16_t Length; /* number of bytes in data region */ + uint16_t Kind; /* a DataRegionType value */ + }; + + /// @} /// @name Indirect Symbol Table /// @{ diff --git a/include/llvm/Object/MachOObject.h b/include/llvm/Object/MachOObject.h index 0560402..86f150a 100644 --- a/include/llvm/Object/MachOObject.h +++ b/include/llvm/Object/MachOObject.h @@ -174,6 +174,9 @@ public: void ReadSymbol64TableEntry( uint64_t SymbolTableOffset, unsigned Index, InMemoryStruct<macho::Symbol64TableEntry> &Res) const; + void ReadDataInCodeTableEntry( + uint64_t TableOffset, unsigned Index, + InMemoryStruct<macho::DataInCodeTableEntry> &Res) const; void ReadULEB128s(uint64_t Index, SmallVectorImpl<uint64_t> &Out) const; /// @} diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index 4dd7fb5..2ec656b 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -76,13 +76,13 @@ public: } }; -static bool operator ==(const DataRefImpl &a, const DataRefImpl &b) { +inline bool operator ==(const DataRefImpl &a, const DataRefImpl &b) { // Check bitwise identical. This is the only legal way to compare a union w/o // knowing which member is in use. return std::memcmp(&a, &b, sizeof(DataRefImpl)) == 0; } -static bool operator <(const DataRefImpl &a, const DataRefImpl &b) { +inline bool operator <(const DataRefImpl &a, const DataRefImpl &b) { // Check bitwise identical. This is the only legal way to compare a union w/o // knowing which member is in use. return std::memcmp(&a, &b, sizeof(DataRefImpl)) < 0; @@ -126,6 +126,8 @@ public: /// /// This is for display purposes only. error_code getValueString(SmallVectorImpl<char> &Result) const; + + DataRefImpl getRawDataRefImpl() const; }; typedef content_iterator<RelocationRef> relocation_iterator; @@ -570,6 +572,11 @@ inline error_code RelocationRef::getValueString(SmallVectorImpl<char> &Result) inline error_code RelocationRef::getHidden(bool &Result) const { return OwningObject->getRelocationHidden(RelocationPimpl, Result); } + +inline DataRefImpl RelocationRef::getRawDataRefImpl() const { + return RelocationPimpl; +} + // Inline function definitions. inline LibraryRef::LibraryRef(DataRefImpl LibraryP, const ObjectFile *Owner) : LibraryPimpl(LibraryP) diff --git a/include/llvm/PassManagers.h b/include/llvm/PassManagers.h index fa29f50..0af5853 100644 --- a/include/llvm/PassManagers.h +++ b/include/llvm/PassManagers.h @@ -15,6 +15,7 @@ #define LLVM_PASSMANAGERS_H #include "llvm/Pass.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/DenseMap.h" @@ -184,7 +185,7 @@ public: void schedulePass(Pass *P); /// Set pass P as the last user of the given analysis passes. - void setLastUser(const SmallVectorImpl<Pass *> &AnalysisPasses, Pass *P); + void setLastUser(ArrayRef<Pass*> AnalysisPasses, Pass *P); /// Collect passes whose last user is P void collectLastUses(SmallVectorImpl<Pass *> &LastUses, Pass *P); diff --git a/include/llvm/Support/AlignOf.h b/include/llvm/Support/AlignOf.h index cebfa79..85607c8 100644 --- a/include/llvm/Support/AlignOf.h +++ b/include/llvm/Support/AlignOf.h @@ -15,6 +15,9 @@ #ifndef LLVM_SUPPORT_ALIGNOF_H #define LLVM_SUPPORT_ALIGNOF_H +#include "llvm/Support/Compiler.h" +#include <cstddef> + namespace llvm { template <typename T> @@ -54,7 +57,94 @@ struct AlignOf { /// class besides some cosmetic cleanliness. Example usage: /// alignOf<int>() returns the alignment of an int. template <typename T> -static inline unsigned alignOf() { return AlignOf<T>::Alignment; } +inline unsigned alignOf() { return AlignOf<T>::Alignment; } + + +/// \brief Helper for building an aligned character array type. +/// +/// This template is used to explicitly build up a collection of aligned +/// character types. We have to build these up using a macro and explicit +/// specialization to cope with old versions of MSVC and GCC where only an +/// integer literal can be used to specify an alignment constraint. Once built +/// up here, we can then begin to indirect between these using normal C++ +/// template parameters. +template <size_t Alignment> struct AlignedCharArrayImpl {}; +template <> struct AlignedCharArrayImpl<0> { + typedef char type; +}; +#if __has_feature(cxx_alignas) +#define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \ + template <> struct AlignedCharArrayImpl<x> { \ + typedef char alignas(x) type; \ + } +#elif defined(__clang__) || defined(__GNUC__) +#define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \ + template <> struct AlignedCharArrayImpl<x> { \ + typedef char type __attribute__((aligned(x))); \ + } +#elif defined(_MSC_VER) +#define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \ + template <> struct AlignedCharArrayImpl<x> { \ + typedef __declspec(align(x)) char type; \ + } +#else +# error No supported align as directive. +#endif + +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1); +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2); +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4); +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8); +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16); +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32); +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64); +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128); +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(512); +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1024); +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2048); +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4096); +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8192); +// Any larger and MSVC complains. +#undef LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT + +/// \brief This class template exposes a typedef for type containing a suitable +/// aligned character array to hold elements of any of up to four types. +/// +/// These types may be arrays, structs, or any other types. The goal is to +/// produce a union type containing a character array which, when used, forms +/// storage suitable to placement new any of these types over. Support for more +/// than four types can be added at the cost of more boiler plate. +template <typename T1, + typename T2 = char, typename T3 = char, typename T4 = char> +class AlignedCharArray { + class AlignerImpl { + T1 t1; T2 t2; T3 t3; T4 t4; + + AlignerImpl(); // Never defined or instantiated. + }; + union SizerImpl { + char arr1[sizeof(T1)], arr2[sizeof(T2)], arr3[sizeof(T3)], arr4[sizeof(T4)]; + }; + +public: + // Sadly, Clang and GCC both fail to align a character array properly even + // with an explicit alignment attribute. To work around this, we union + // the character array that will actually be used with a struct that contains + // a single aligned character member. Tests seem to indicate that both Clang + // and GCC will properly register the alignment of a struct containing an + // aligned member, and this alignment should carry over to the character + // array in the union. + union union_type { + // This is the only member of the union which should be used by clients: + char buffer[sizeof(SizerImpl)]; + + // This member of the union only exists to force the alignment. + struct { + typename llvm::AlignedCharArrayImpl<AlignOf<AlignerImpl>::Alignment>::type + nonce_inner_member; + } nonce_member; + }; +}; } // end namespace llvm #endif diff --git a/include/llvm/Support/COFF.h b/include/llvm/Support/COFF.h index 88c60ba..6c2ee08 100644 --- a/include/llvm/Support/COFF.h +++ b/include/llvm/Support/COFF.h @@ -50,6 +50,8 @@ namespace COFF { }; enum MachineTypes { + MT_Invalid = -1, + IMAGE_FILE_MACHINE_UNKNOWN = 0x0, IMAGE_FILE_MACHINE_AM33 = 0x13, IMAGE_FILE_MACHINE_AMD64 = 0x8664, @@ -74,6 +76,8 @@ namespace COFF { }; enum Characteristics { + C_Invalid = 0, + /// The file does not contain base relocations and must be loaded at its /// preferred base. If this cannot be done, the loader will error. IMAGE_FILE_RELOCS_STRIPPED = 0x0001, @@ -114,9 +118,9 @@ namespace COFF { struct symbol { char Name[NameSize]; uint32_t Value; + uint16_t SectionNumber; uint16_t Type; uint8_t StorageClass; - uint16_t SectionNumber; uint8_t NumberOfAuxSymbols; }; @@ -138,6 +142,8 @@ namespace COFF { /// Storage class tells where and what the symbol represents enum SymbolStorageClass { + SSC_Invalid = -1, + IMAGE_SYM_CLASS_END_OF_FUNCTION = -1, ///< Physical end of function IMAGE_SYM_CLASS_NULL = 0, ///< No symbol IMAGE_SYM_CLASS_AUTOMATIC = 1, ///< Stack variable @@ -214,6 +220,8 @@ namespace COFF { }; enum SectionCharacteristics { + SC_Invalid = -1, + IMAGE_SCN_TYPE_NO_PAD = 0x00000008, IMAGE_SCN_CNT_CODE = 0x00000020, IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040, diff --git a/include/llvm/Support/CallSite.h b/include/llvm/Support/CallSite.h index 20634ed..c23bb6a 100644 --- a/include/llvm/Support/CallSite.h +++ b/include/llvm/Support/CallSite.h @@ -184,6 +184,11 @@ public: CALLSITE_DELEGATE_SETTER(setAttributes(PAL)); } + /// \brief Return true if this function has the given attribute. + bool hasFnAttr(Attributes N) const { + CALLSITE_DELEGATE_GETTER(hasFnAttr(N)); + } + /// paramHasAttr - whether the call or the callee has the given attribute. bool paramHasAttr(uint16_t i, Attributes attr) const { CALLSITE_DELEGATE_GETTER(paramHasAttr(i, attr)); diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h index c212d2d..ae1570d 100644 --- a/include/llvm/Support/CommandLine.h +++ b/include/llvm/Support/CommandLine.h @@ -217,11 +217,11 @@ public: void setMiscFlag(enum MiscFlags M) { Misc |= M; } void setPosition(unsigned pos) { Position = pos; } protected: - explicit Option(enum NumOccurrencesFlag Occurrences, + explicit Option(enum NumOccurrencesFlag OccurrencesFlag, enum OptionHidden Hidden) - : NumOccurrences(0), Occurrences(Occurrences), HiddenFlag(Hidden), - Formatting(NormalFormatting), Position(0), - AdditionalVals(0), NextRegistered(0), + : NumOccurrences(0), Occurrences(OccurrencesFlag), Value(0), + HiddenFlag(Hidden), Formatting(NormalFormatting), Misc(0), + Position(0), AdditionalVals(0), NextRegistered(0), ArgStr(""), HelpStr(""), ValueStr("") { } diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h index d0b186e..f654f32 100644 --- a/include/llvm/Support/Compiler.h +++ b/include/llvm/Support/Compiler.h @@ -19,6 +19,25 @@ # define __has_feature(x) 0 #endif +/// LLVM_HAS_RVALUE_REFERENCES - Does the compiler provide r-value references? +/// This implies that <utility> provides the one-argument std::move; it +/// does not imply the existence of any other C++ library features. +#if (__has_feature(cxx_rvalue_references) \ + || defined(__GXX_EXPERIMENTAL_CXX0X__) \ + || _MSC_VER >= 1600) +#define LLVM_USE_RVALUE_REFERENCES 1 +#else +#define LLVM_USE_RVALUE_REFERENCES 0 +#endif + +/// llvm_move - Expands to ::std::move if the compiler supports +/// r-value references; otherwise, expands to the argument. +#if LLVM_USE_RVALUE_REFERENCES +#define llvm_move(value) (::std::move(value)) +#else +#define llvm_move(value) (value) +#endif + /// LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked /// into a shared library, then the class should be private to the library and /// not accessible from outside it. Can also be used to mark variables and @@ -102,7 +121,7 @@ // 3.4 supported this but is buggy in various cases and produces unimplemented // errors, just use it in GCC 4.0 and later. #if __GNUC__ > 3 -#define LLVM_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline)) +#define LLVM_ATTRIBUTE_ALWAYS_INLINE inline __attribute__((always_inline)) #elif defined(_MSC_VER) #define LLVM_ATTRIBUTE_ALWAYS_INLINE __forceinline #else diff --git a/include/llvm/Support/ConstantRange.h b/include/llvm/Support/ConstantRange.h index ced3a2c..90dd69f 100644 --- a/include/llvm/Support/ConstantRange.h +++ b/include/llvm/Support/ConstantRange.h @@ -155,6 +155,10 @@ public: /// constant range. ConstantRange subtract(const APInt &CI) const; + /// \brief Subtract the specified range from this range (aka relative + /// complement of the sets). + ConstantRange difference(const ConstantRange &CR) const; + /// intersectWith - Return the range that results from the intersection of /// this range with another range. The resultant range is guaranteed to /// include all elements contained in both input ranges, and to have the diff --git a/include/llvm/Support/DataTypes.h.cmake b/include/llvm/Support/DataTypes.h.cmake index a3a6489..7484abd 100644 --- a/include/llvm/Support/DataTypes.h.cmake +++ b/include/llvm/Support/DataTypes.h.cmake @@ -79,18 +79,6 @@ typedef u_int64_t uint64_t; #endif #endif -#ifdef _OpenBSD_ -#define INT8_MAX 127 -#define INT8_MIN -128 -#define UINT8_MAX 255 -#define INT16_MAX 32767 -#define INT16_MIN -32768 -#define UINT16_MAX 65535 -#define INT32_MAX 2147483647 -#define INT32_MIN -2147483648 -#define UINT32_MAX 4294967295U -#endif - #else /* _MSC_VER */ /* Visual C++ doesn't provide standard integer headers, but it does provide built-in data types. */ diff --git a/include/llvm/Support/DataTypes.h.in b/include/llvm/Support/DataTypes.h.in index b492bb1..b9fb48a 100644 --- a/include/llvm/Support/DataTypes.h.in +++ b/include/llvm/Support/DataTypes.h.in @@ -79,18 +79,6 @@ typedef u_int64_t uint64_t; #endif #endif -#ifdef _OpenBSD_ -#define INT8_MAX 127 -#define INT8_MIN -128 -#define UINT8_MAX 255 -#define INT16_MAX 32767 -#define INT16_MIN -32768 -#define UINT16_MAX 65535 -#define INT32_MAX 2147483647 -#define INT32_MIN -2147483648 -#define UINT32_MAX 4294967295U -#endif - #else /* _MSC_VER */ /* Visual C++ doesn't provide standard integer headers, but it does provide built-in data types. */ diff --git a/include/llvm/Support/Debug.h b/include/llvm/Support/Debug.h index e723272..896fe84 100644 --- a/include/llvm/Support/Debug.h +++ b/include/llvm/Support/Debug.h @@ -19,7 +19,7 @@ // foo class. // // When compiling without assertions, the -debug-* options and all code in -// DEBUG() statements disappears, so it does not effect the runtime of the code. +// DEBUG() statements disappears, so it does not affect the runtime of the code. // //===----------------------------------------------------------------------===// @@ -49,11 +49,11 @@ extern bool DebugFlag; /// bool isCurrentDebugType(const char *Type); -/// SetCurrentDebugType - Set the current debug type, as if the -debug-only=X +/// setCurrentDebugType - Set the current debug type, as if the -debug-only=X /// option were specified. Note that DebugFlag also needs to be set to true for /// debug output to be produced. /// -void SetCurrentDebugType(const char *Type); +void setCurrentDebugType(const char *Type); /// DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug /// information. In the '-debug' option is specified on the commandline, and if @@ -70,7 +70,7 @@ void SetCurrentDebugType(const char *Type); #else #define isCurrentDebugType(X) (false) -#define SetCurrentDebugType(X) +#define setCurrentDebugType(X) #define DEBUG_WITH_TYPE(TYPE, X) do { } while (0) #endif diff --git a/include/llvm/Support/DebugLoc.h b/include/llvm/Support/DebugLoc.h index 2ee9f87..0498075 100644 --- a/include/llvm/Support/DebugLoc.h +++ b/include/llvm/Support/DebugLoc.h @@ -15,9 +15,8 @@ #ifndef LLVM_SUPPORT_DEBUGLOC_H #define LLVM_SUPPORT_DEBUGLOC_H -#include "llvm/ADT/DenseMapInfo.h" - namespace llvm { + template <typename T> struct DenseMapInfo; class MDNode; class LLVMContext; @@ -103,10 +102,10 @@ namespace llvm { template <> struct DenseMapInfo<DebugLoc> { - static DebugLoc getEmptyKey(); - static DebugLoc getTombstoneKey(); + static DebugLoc getEmptyKey() { return DebugLoc::getEmptyKey(); } + static DebugLoc getTombstoneKey() { return DebugLoc::getTombstoneKey(); } static unsigned getHashValue(const DebugLoc &Key); - static bool isEqual(const DebugLoc &LHS, const DebugLoc &RHS); + static bool isEqual(DebugLoc LHS, DebugLoc RHS) { return LHS == RHS; } }; } // end namespace llvm diff --git a/include/llvm/Support/ELF.h b/include/llvm/Support/ELF.h index 04953b6..f7ae60f 100644 --- a/include/llvm/Support/ELF.h +++ b/include/llvm/Support/ELF.h @@ -248,7 +248,7 @@ enum { EM_CYPRESS_M8C = 161, // Cypress M8C microprocessor EM_R32C = 162, // Renesas R32C series microprocessors EM_TRIMEDIA = 163, // NXP Semiconductors TriMedia architecture family - EM_QDSP6 = 164, // QUALCOMM DSP6 Processor + EM_HEXAGON = 164, // Qualcomm Hexagon processor EM_8051 = 165, // Intel 8051 and variants EM_STXP7X = 166, // STMicroelectronics STxP7x family of configurable // and extensible RISC processors @@ -674,6 +674,97 @@ enum { R_MIPS_NUM = 218 }; +// ELF Relocation types for Hexagon +// Release 5 ABI - Document: 80-V9418-3 Rev. J +enum { + R_HEX_NONE = 0, + R_HEX_B22_PCREL = 1, + R_HEX_B15_PCREL = 2, + R_HEX_B7_PCREL = 3, + R_HEX_LO16 = 4, + R_HEX_HI16 = 5, + R_HEX_32 = 6, + R_HEX_16 = 7, + R_HEX_8 = 8, + R_HEX_GPREL16_0 = 9, + R_HEX_GPREL16_1 = 10, + R_HEX_GPREL16_2 = 11, + R_HEX_GPREL16_3 = 12, + R_HEX_HL16 = 13, + R_HEX_B13_PCREL = 14, + R_HEX_B9_PCREL = 15, + R_HEX_B32_PCREL_X = 16, + R_HEX_32_6_X = 17, + R_HEX_B22_PCREL_X = 18, + R_HEX_B15_PCREL_X = 19, + R_HEX_B13_PCREL_X = 20, + R_HEX_B9_PCREL_X = 21, + R_HEX_B7_PCREL_X = 22, + R_HEX_16_X = 23, + R_HEX_12_X = 24, + R_HEX_11_X = 25, + R_HEX_10_X = 26, + R_HEX_9_X = 27, + R_HEX_8_X = 28, + R_HEX_7_X = 29, + R_HEX_6_X = 30, + R_HEX_32_PCREL = 31, + R_HEX_COPY = 32, + R_HEX_GLOB_DAT = 33, + R_HEX_JMP_SLOT = 34, + R_HEX_RELATIVE = 35, + R_HEX_PLT_B22_PCREL = 36, + R_HEX_GOTREL_LO16 = 37, + R_HEX_GOTREL_HI16 = 38, + R_HEX_GOTREL_32 = 39, + R_HEX_GOT_LO16 = 40, + R_HEX_GOT_HI16 = 41, + R_HEX_GOT_32 = 42, + R_HEX_GOT_16 = 43, + R_HEX_DTPMOD_32 = 44, + R_HEX_DTPREL_LO16 = 45, + R_HEX_DTPREL_HI16 = 46, + R_HEX_DTPREL_32 = 47, + R_HEX_DTPREL_16 = 48, + R_HEX_GD_PLT_B22_PCREL = 49, + R_HEX_GD_GOT_LO16 = 50, + R_HEX_GD_GOT_HI16 = 51, + R_HEX_GD_GOT_32 = 52, + R_HEX_GD_GOT_16 = 53, + R_HEX_IE_LO16 = 54, + R_HEX_IE_HI16 = 55, + R_HEX_IE_32 = 56, + R_HEX_IE_GOT_LO16 = 57, + R_HEX_IE_GOT_HI16 = 58, + R_HEX_IE_GOT_32 = 59, + R_HEX_IE_GOT_16 = 60, + R_HEX_TPREL_LO16 = 61, + R_HEX_TPREL_HI16 = 62, + R_HEX_TPREL_32 = 63, + R_HEX_TPREL_16 = 64, + R_HEX_6_PCREL_X = 65, + R_HEX_GOTREL_32_6_X = 66, + R_HEX_GOTREL_16_X = 67, + R_HEX_GOTREL_11_X = 68, + R_HEX_GOT_32_6_X = 69, + R_HEX_GOT_16_X = 70, + R_HEX_GOT_11_X = 71, + R_HEX_DTPREL_32_6_X = 72, + R_HEX_DTPREL_16_X = 73, + R_HEX_DTPREL_11_X = 74, + R_HEX_GD_GOT_32_6_X = 75, + R_HEX_GD_GOT_16_X = 76, + R_HEX_GD_GOT_11_X = 77, + R_HEX_IE_32_6_X = 78, + R_HEX_IE_16_X = 79, + R_HEX_IE_GOT_32_6_X = 80, + R_HEX_IE_GOT_16_X = 81, + R_HEX_IE_GOT_11_X = 82, + R_HEX_TPREL_32_6_X = 83, + R_HEX_TPREL_16_X = 84, + R_HEX_TPREL_11_X = 85 +}; + // Section header. struct Elf32_Shdr { Elf32_Word sh_name; // Section name (index into string table) @@ -736,6 +827,8 @@ enum { SHT_GROUP = 17, // Section group. SHT_SYMTAB_SHNDX = 18, // Indices for SHN_XINDEX entries. SHT_LOOS = 0x60000000, // Lowest operating system-specific type. + SHT_GNU_ATTRIBUTES= 0x6ffffff5, // Object attributes. + SHT_GNU_HASH = 0x6ffffff6, // GNU-style hash table. SHT_GNU_verdef = 0x6ffffffd, // GNU version definitions. SHT_GNU_verneed = 0x6ffffffe, // GNU version references. SHT_GNU_versym = 0x6fffffff, // GNU symbol versions table. @@ -1017,6 +1110,9 @@ enum { PT_SUNW_EH_FRAME = 0x6474e550, PT_SUNW_UNWIND = 0x6464e550, + PT_GNU_STACK = 0x6474e551, // Indicates stack executability. + PT_GNU_RELRO = 0x6474e552, // Read-only after relocation. + PT_HIOS = 0x6fffffff, // Highest operating system-specific pt entry type. PT_LOPROC = 0x70000000, // Lowest processor-specific program hdr entry type. PT_HIPROC = 0x7fffffff // Highest processor-specific program hdr entry type. @@ -1095,7 +1191,16 @@ enum { DT_LOOS = 0x60000000, // Start of environment specific tags. DT_HIOS = 0x6FFFFFFF, // End of environment specific tags. DT_LOPROC = 0x70000000, // Start of processor specific tags. - DT_HIPROC = 0x7FFFFFFF // End of processor specific tags. + DT_HIPROC = 0x7FFFFFFF, // End of processor specific tags. + + DT_RELACOUNT = 0x6FFFFFF9, // ELF32_Rela count. + DT_RELCOUNT = 0x6FFFFFFA, // ELF32_Rel count. + + DT_FLAGS_1 = 0X6FFFFFFB, // Flags_1. + DT_VERDEF = 0X6FFFFFFC, // The address of the version definition table. + DT_VERDEFNUM = 0X6FFFFFFD, // The number of entries in DT_VERDEF. + DT_VERNEED = 0X6FFFFFFE, // The address of the version Dependency table. + DT_VERNEEDNUM = 0X6FFFFFFF // The number of entries in DT_VERNEED. }; // DT_FLAGS values. @@ -1107,6 +1212,27 @@ enum { DF_STATIC_TLS = 0x10 // Reject attempts to load dynamically. }; +// State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1 entry. +enum { + DF_1_NOW = 0x00000001, // Set RTLD_NOW for this object. + DF_1_GLOBAL = 0x00000002, // Set RTLD_GLOBAL for this object. + DF_1_GROUP = 0x00000004, // Set RTLD_GROUP for this object. + DF_1_NODELETE = 0x00000008, // Set RTLD_NODELETE for this object. + DF_1_LOADFLTR = 0x00000010, // Trigger filtee loading at runtime. + DF_1_INITFIRST = 0x00000020, // Set RTLD_INITFIRST for this object. + DF_1_NOOPEN = 0x00000040, // Set RTLD_NOOPEN for this object. + DF_1_ORIGIN = 0x00000080, // $ORIGIN must be handled. + DF_1_DIRECT = 0x00000100, // Direct binding enabled. + DF_1_TRANS = 0x00000200, + DF_1_INTERPOSE = 0x00000400, // Object is used to interpose. + DF_1_NODEFLIB = 0x00000800, // Ignore default lib search path. + DF_1_NODUMP = 0x00001000, // Object can't be dldump'ed. + DF_1_CONFALT = 0x00002000, // Configuration alternative created. + DF_1_ENDFILTEE = 0x00004000, // Filtee terminates filters search. + DF_1_DISPRELDNE = 0x00008000, // Disp reloc applied at build time. + DF_1_DISPRELPND = 0x00010000 // Disp reloc applied at run-time. +}; + // ElfXX_VerDef structure version (GNU versioning) enum { VER_DEF_NONE = 0, diff --git a/include/llvm/Support/Endian.h b/include/llvm/Support/Endian.h index 733ab75..8d5649d 100644 --- a/include/llvm/Support/Endian.h +++ b/include/llvm/Support/Endian.h @@ -49,7 +49,7 @@ struct alignment_access_helper<value_type, unaligned> namespace endian { template<typename value_type, alignment align> - static value_type read_le(const void *memory) { + inline value_type read_le(const void *memory) { value_type t = reinterpret_cast<const detail::alignment_access_helper <value_type, align> *>(memory)->val; @@ -59,7 +59,7 @@ namespace endian { } template<typename value_type, alignment align> - static void write_le(void *memory, value_type value) { + inline void write_le(void *memory, value_type value) { if (sys::isBigEndianHost()) value = sys::SwapByteOrder(value); reinterpret_cast<detail::alignment_access_helper<value_type, align> *> @@ -67,7 +67,7 @@ namespace endian { } template<typename value_type, alignment align> - static value_type read_be(const void *memory) { + inline value_type read_be(const void *memory) { value_type t = reinterpret_cast<const detail::alignment_access_helper <value_type, align> *>(memory)->val; @@ -77,7 +77,7 @@ namespace endian { } template<typename value_type, alignment align> - static void write_be(void *memory, value_type value) { + inline void write_be(void *memory, value_type value) { if (sys::isLittleEndianHost()) value = sys::SwapByteOrder(value); reinterpret_cast<detail::alignment_access_helper<value_type, align> *> diff --git a/include/llvm/Support/FileOutputBuffer.h b/include/llvm/Support/FileOutputBuffer.h new file mode 100644 index 0000000..0f07164 --- /dev/null +++ b/include/llvm/Support/FileOutputBuffer.h @@ -0,0 +1,97 @@ +//=== FileOutputBuffer.h - File Output Buffer -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Utility for creating a in-memory buffer that will be written to a file. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_FILEOUTPUTBUFFER_H +#define LLVM_SUPPORT_FILEOUTPUTBUFFER_H + +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class error_code; +template<class T> class OwningPtr; + +/// FileOutputBuffer - This interface provides simple way to create an in-memory +/// buffer which will be written to a file. During the lifetime of these +/// objects, the content or existence of the specified file is undefined. That +/// is, creating an OutputBuffer for a file may immediately remove the file. +/// If the FileOutputBuffer is committed, the target file's content will become +/// the buffer content at the time of the commit. If the FileOutputBuffer is +/// not committed, the file will be deleted in the FileOutputBuffer destructor. +class FileOutputBuffer { +public: + + enum { + F_executable = 1 /// set the 'x' bit on the resulting file + }; + + /// Factory method to create an OutputBuffer object which manages a read/write + /// buffer of the specified size. When committed, the buffer will be written + /// to the file at the specified path. + static error_code create(StringRef FilePath, size_t Size, + OwningPtr<FileOutputBuffer> &Result, + unsigned Flags=0); + + + /// Returns a pointer to the start of the buffer. + uint8_t *getBufferStart() const { + return BufferStart; + } + + /// Returns a pointer to the end of the buffer. + uint8_t *getBufferEnd() const { + return BufferEnd; + } + + /// Returns size of the buffer. + size_t getBufferSize() const { + return BufferEnd - BufferStart; + } + + /// Returns path where file will show up if buffer is committed. + StringRef getPath() const { + return FinalPath; + } + + /// Flushes the content of the buffer to its file and deallocates the + /// buffer. If commit() is not called before this object's destructor + /// is called, the file is deleted in the destructor. The optional parameter + /// is used if it turns out you want the file size to be smaller than + /// initially requested. + error_code commit(int64_t NewSmallerSize = -1); + + /// If this object was previously committed, the destructor just deletes + /// this object. If this object was not committed, the destructor + /// deallocates the buffer and the target file is never written. + ~FileOutputBuffer(); + + +protected: + FileOutputBuffer(const FileOutputBuffer &); // DO NOT IMPLEMENT + FileOutputBuffer &operator=(const FileOutputBuffer &); // DO NOT IMPLEMENT + FileOutputBuffer(uint8_t *Start, uint8_t *End, + StringRef Path, StringRef TempPath); + + uint8_t *BufferStart; + uint8_t *BufferEnd; + SmallString<128> FinalPath; + SmallString<128> TempPath; +}; + + + +} // end namespace llvm + +#endif diff --git a/include/llvm/Support/FileSystem.h b/include/llvm/Support/FileSystem.h index e6f9926..e0353f9 100644 --- a/include/llvm/Support/FileSystem.h +++ b/include/llvm/Support/FileSystem.h @@ -94,13 +94,62 @@ struct space_info { uint64_t available; }; + +enum perms { + no_perms = 0, + owner_read = 0400, + owner_write = 0200, + owner_exe = 0100, + owner_all = owner_read | owner_write | owner_exe, + group_read = 040, + group_write = 020, + group_exe = 010, + group_all = group_read | group_write | group_exe, + others_read = 04, + others_write = 02, + others_exe = 01, + others_all = others_read | others_write | others_exe, + all_all = owner_all | group_all | others_all, + set_uid_on_exe = 04000, + set_gid_on_exe = 02000, + sticky_bit = 01000, + perms_mask = all_all | set_uid_on_exe | set_gid_on_exe | sticky_bit, + perms_not_known = 0xFFFF, + add_perms = 0x1000, + remove_perms = 0x2000, + symlink_perms = 0x4000 +}; + +// Helper functions so that you can use & and | to manipulate perms bits: +inline perms operator|(perms l , perms r) { + return static_cast<perms>( + static_cast<unsigned short>(l) | static_cast<unsigned short>(r)); +} +inline perms operator&(perms l , perms r) { + return static_cast<perms>( + static_cast<unsigned short>(l) & static_cast<unsigned short>(r)); +} +inline perms &operator|=(perms &l, perms r) { + l = l | r; + return l; +} +inline perms &operator&=(perms &l, perms r) { + l = l & r; + return l; +} +inline perms operator~(perms x) { + return static_cast<perms>(~static_cast<unsigned short>(x)); +} + + + /// file_status - Represents the result of a call to stat and friends. It has /// a platform specific member to store the result. class file_status { #if defined(LLVM_ON_UNIX) - dev_t st_dev; - ino_t st_ino; + dev_t fs_st_dev; + ino_t fs_st_ino; #elif defined (LLVM_ON_WIN32) uint32_t LastWriteTimeHigh; uint32_t LastWriteTimeLow; @@ -113,12 +162,19 @@ class file_status friend bool equivalent(file_status A, file_status B); friend error_code status(const Twine &path, file_status &result); file_type Type; + perms Perms; public: - explicit file_status(file_type v=file_type::status_error) - : Type(v) {} + explicit file_status(file_type v=file_type::status_error, + perms prms=perms_not_known) + : Type(v), Perms(prms) {} + // getters file_type type() const { return Type; } + perms permissions() const { return Perms; } + + // setters void type(file_type v) { Type = v; } + void permissions(perms p) { Perms = p; } }; /// file_magic - An "enum class" enumeration of file types based on magic (the first @@ -309,6 +365,13 @@ bool equivalent(file_status A, file_status B); /// platform specific error_code. error_code equivalent(const Twine &A, const Twine &B, bool &result); +/// @brief Simpler version of equivalent for clients that don't need to +/// differentiate between an error and false. +inline bool equivalent(const Twine &A, const Twine &B) { + bool result; + return !equivalent(A, B, result) && result; +} + /// @brief Get file size. /// /// @param path Input path. @@ -388,6 +451,13 @@ error_code is_symlink(const Twine &path, bool &result); /// platform specific error_code. error_code status(const Twine &path, file_status &result); +/// @brief Modifies permission bits on a file +/// +/// @param path Input path. +/// @results errc::success if permissions have been changed, otherwise a +/// platform specific error_code. +error_code permissions(const Twine &path, perms prms); + /// @brief Is status available? /// /// @param path Input path. @@ -422,8 +492,8 @@ error_code status_known(const Twine &path, bool &result); /// @results errc::success if result_{fd,path} have been successfully set, /// otherwise a platform specific error_code. error_code unique_file(const Twine &model, int &result_fd, - SmallVectorImpl<char> &result_path, - bool makeAbsolute = true); + SmallVectorImpl<char> &result_path, + bool makeAbsolute = true, unsigned mode = 0600); /// @brief Canonicalize path. /// @@ -506,6 +576,33 @@ error_code FindLibrary(const Twine &short_name, SmallVectorImpl<char> &result); error_code GetMainExecutable(const char *argv0, void *MainAddr, SmallVectorImpl<char> &result); + +/// @brief Memory maps the contents of a file +/// +/// @param path Path to file to map. +/// @param file_offset Byte offset in file where mapping should begin. +/// @param size_t Byte length of range of the file to map. +/// @param map_writable If true, the file will be mapped in r/w such +/// that changes to the mapped buffer will be flushed back +/// to the file. If false, the file will be mapped read-only +/// and the buffer will be read-only. +/// @param result Set to the start address of the mapped buffer. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code map_file_pages(const Twine &path, off_t file_offset, size_t size, + bool map_writable, void *&result); + + +/// @brief Memory unmaps the contents of a file +/// +/// @param base Pointer to the start of the buffer. +/// @param size Byte length of the range to unmmap. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code unmap_file_pages(void *base, size_t size); + + + /// @} /// @name Iterators /// @{ diff --git a/include/llvm/Support/GCOV.h b/include/llvm/Support/GCOV.h index 49cd87f..19e1ce8 100644 --- a/include/llvm/Support/GCOV.h +++ b/include/llvm/Support/GCOV.h @@ -63,8 +63,8 @@ public: bool readFunctionTag() { StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); if (Tag.empty() || - Tag[0] != '\0' || Tag[1] != '\0' || - Tag[2] != '\0' || Tag[3] != '\1') { + Tag[0] != '\0' || Tag[1] != '\0' || + Tag[2] != '\0' || Tag[3] != '\1') { return false; } Cursor += 4; @@ -76,8 +76,8 @@ public: bool readBlockTag() { StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); if (Tag.empty() || - Tag[0] != '\0' || Tag[1] != '\0' || - Tag[2] != '\x41' || Tag[3] != '\x01') { + Tag[0] != '\0' || Tag[1] != '\0' || + Tag[2] != '\x41' || Tag[3] != '\x01') { return false; } Cursor += 4; @@ -89,8 +89,8 @@ public: bool readEdgeTag() { StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); if (Tag.empty() || - Tag[0] != '\0' || Tag[1] != '\0' || - Tag[2] != '\x43' || Tag[3] != '\x01') { + Tag[0] != '\0' || Tag[1] != '\0' || + Tag[2] != '\x43' || Tag[3] != '\x01') { return false; } Cursor += 4; @@ -102,8 +102,8 @@ public: bool readLineTag() { StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); if (Tag.empty() || - Tag[0] != '\0' || Tag[1] != '\0' || - Tag[2] != '\x45' || Tag[3] != '\x01') { + Tag[0] != '\0' || Tag[1] != '\0' || + Tag[2] != '\x45' || Tag[3] != '\x01') { return false; } Cursor += 4; @@ -115,8 +115,8 @@ public: bool readArcTag() { StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); if (Tag.empty() || - Tag[0] != '\0' || Tag[1] != '\0' || - Tag[2] != '\xa1' || Tag[3] != '\1') { + Tag[0] != '\0' || Tag[1] != '\0' || + Tag[2] != '\xa1' || Tag[3] != '\1') { return false; } Cursor += 4; diff --git a/include/llvm/Support/GraphWriter.h b/include/llvm/Support/GraphWriter.h index ae32da5..f178b0c 100644 --- a/include/llvm/Support/GraphWriter.h +++ b/include/llvm/Support/GraphWriter.h @@ -172,7 +172,7 @@ public: // If we should include the address of the node in the label, do so now. if (DTraits.hasNodeAddressLabel(Node, G)) - O << "|" << (void*)Node; + O << "|" << static_cast<const void*>(Node); } std::string edgeSourceLabels; @@ -192,7 +192,7 @@ public: // If we should include the address of the node in the label, do so now. if (DTraits.hasNodeAddressLabel(Node, G)) - O << "|" << (void*)Node; + O << "|" << static_cast<const void*>(Node); } if (DTraits.hasEdgeDestLabels()) { diff --git a/include/llvm/Support/InstVisitor.h b/include/llvm/Support/InstVisitor.h index 52de8f6..109b3cf 100644 --- a/include/llvm/Support/InstVisitor.h +++ b/include/llvm/Support/InstVisitor.h @@ -13,6 +13,8 @@ #include "llvm/Function.h" #include "llvm/Instructions.h" +#include "llvm/Intrinsics.h" +#include "llvm/IntrinsicInst.h" #include "llvm/Module.h" #include "llvm/Support/CallSite.h" #include "llvm/Support/ErrorHandling.h" @@ -145,14 +147,17 @@ public: // visitMul to proxy to visitBinaryOperator for instance in case the user does // not need this generality. // - // The one problem case we have to handle here though is that the PHINode - // class and opcode name are the exact same. Because of this, we cannot - // define visitPHINode (the inst version) to forward to visitPHINode (the - // generic version) without multiply defined symbols and recursion. To handle - // this, we do not autoexpand "Other" instructions, we do it manually. - // + // These functions can also implement fan-out, when a single opcode and + // instruction have multiple more specific Instruction subclasses. The Call + // instruction currently supports this. We implement that by redirecting that + // instruction to a special delegation helper. #define HANDLE_INST(NUM, OPCODE, CLASS) \ - RetTy visit##OPCODE(CLASS &I) { DELEGATE(CLASS); } + RetTy visit##OPCODE(CLASS &I) { \ + if (NUM == Instruction::Call) \ + return delegateCallInst(I); \ + else \ + DELEGATE(CLASS); \ + } #include "llvm/Instruction.def" // Specific Instruction type classes... note that all of the casts are @@ -195,6 +200,17 @@ public: RetTy visitInsertValueInst(InsertValueInst &I) { DELEGATE(Instruction); } RetTy visitLandingPadInst(LandingPadInst &I) { DELEGATE(Instruction); } + // Handle the special instrinsic instruction classes. + RetTy visitDbgDeclareInst(DbgDeclareInst &I) { DELEGATE(DbgInfoIntrinsic);} + RetTy visitDbgValueInst(DbgValueInst &I) { DELEGATE(DbgInfoIntrinsic);} + RetTy visitDbgInfoIntrinsic(DbgInfoIntrinsic &I) { DELEGATE(IntrinsicInst); } + RetTy visitMemSetInst(MemSetInst &I) { DELEGATE(MemIntrinsic); } + RetTy visitMemCpyInst(MemCpyInst &I) { DELEGATE(MemTransferInst); } + RetTy visitMemMoveInst(MemMoveInst &I) { DELEGATE(MemTransferInst); } + RetTy visitMemTransferInst(MemTransferInst &I) { DELEGATE(MemIntrinsic); } + RetTy visitMemIntrinsic(MemIntrinsic &I) { DELEGATE(IntrinsicInst); } + RetTy visitIntrinsicInst(IntrinsicInst &I) { DELEGATE(CallInst); } + // Call and Invoke are slightly different as they delegate first through // a generic CallSite visitor. RetTy visitCallInst(CallInst &I) { @@ -234,6 +250,29 @@ public: // Note that you MUST override this function if your return type is not void. // void visitInstruction(Instruction &I) {} // Ignore unhandled instructions + +private: + // Special helper function to delegate to CallInst subclass visitors. + RetTy delegateCallInst(CallInst &I) { + if (const Function *F = I.getCalledFunction()) { + switch ((Intrinsic::ID)F->getIntrinsicID()) { + default: DELEGATE(IntrinsicInst); + case Intrinsic::dbg_declare: DELEGATE(DbgDeclareInst); + case Intrinsic::dbg_value: DELEGATE(DbgValueInst); + case Intrinsic::memcpy: DELEGATE(MemCpyInst); + case Intrinsic::memmove: DELEGATE(MemMoveInst); + case Intrinsic::memset: DELEGATE(MemSetInst); + case Intrinsic::not_intrinsic: break; + } + } + DELEGATE(CallInst); + } + + // An overload that will never actually be called, it is used only from dead + // code in the dispatching from opcodes to instruction subclasses. + RetTy delegateCallInst(Instruction &I) { + llvm_unreachable("delegateCallInst called for non-CallInst"); + } }; #undef DELEGATE diff --git a/include/llvm/Support/IntegersSubset.h b/include/llvm/Support/IntegersSubset.h new file mode 100644 index 0000000..bb9e769 --- /dev/null +++ b/include/llvm/Support/IntegersSubset.h @@ -0,0 +1,541 @@ +//===-- llvm/IntegersSubset.h - The subset of integers ----------*- 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 class that implements constant set of ranges: +/// [<Low0,High0>,...,<LowN,HighN>]. Initially, this class was created for +/// SwitchInst and was used for case value representation that may contain +/// multiple ranges for a single successor. +// +//===----------------------------------------------------------------------===// + +#ifndef CONSTANTRANGESSET_H_ +#define CONSTANTRANGESSET_H_ + +#include <list> + +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/LLVMContext.h" + +namespace llvm { + + // The IntItem is a wrapper for APInt. + // 1. It determines sign of integer, it allows to use + // comparison operators >,<,>=,<=, and as result we got shorter and cleaner + // constructions. + // 2. It helps to implement PR1255 (case ranges) as a series of small patches. + // 3. Currently we can interpret IntItem both as ConstantInt and as APInt. + // It allows to provide SwitchInst methods that works with ConstantInt for + // non-updated passes. And it allows to use APInt interface for new methods. + // 4. IntItem can be easily replaced with APInt. + + // The set of macros that allows to propagate APInt operators to the IntItem. + +#define INT_ITEM_DEFINE_COMPARISON(op,func) \ + bool operator op (const APInt& RHS) const { \ + return getAPIntValue().func(RHS); \ + } + +#define INT_ITEM_DEFINE_UNARY_OP(op) \ + IntItem operator op () const { \ + APInt res = op(getAPIntValue()); \ + Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \ + return IntItem(cast<ConstantInt>(NewVal)); \ + } + +#define INT_ITEM_DEFINE_BINARY_OP(op) \ + IntItem operator op (const APInt& RHS) const { \ + APInt res = getAPIntValue() op RHS; \ + Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \ + return IntItem(cast<ConstantInt>(NewVal)); \ + } + +#define INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(op) \ + IntItem& operator op (const APInt& RHS) {\ + APInt res = getAPIntValue();\ + res op RHS; \ + Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \ + ConstantIntVal = cast<ConstantInt>(NewVal); \ + return *this; \ + } + +#define INT_ITEM_DEFINE_PREINCDEC(op) \ + IntItem& operator op () { \ + APInt res = getAPIntValue(); \ + op(res); \ + Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \ + ConstantIntVal = cast<ConstantInt>(NewVal); \ + return *this; \ + } + +#define INT_ITEM_DEFINE_POSTINCDEC(op) \ + IntItem& operator op (int) { \ + APInt res = getAPIntValue();\ + op(res); \ + Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \ + OldConstantIntVal = ConstantIntVal; \ + ConstantIntVal = cast<ConstantInt>(NewVal); \ + return IntItem(OldConstantIntVal); \ + } + +#define INT_ITEM_DEFINE_OP_STANDARD_INT(RetTy, op, IntTy) \ + RetTy operator op (IntTy RHS) const { \ + return (*this) op APInt(getAPIntValue().getBitWidth(), RHS); \ + } + +class IntItem { + ConstantInt *ConstantIntVal; + const APInt* APIntVal; + IntItem(const ConstantInt *V) : + ConstantIntVal(const_cast<ConstantInt*>(V)), + APIntVal(&ConstantIntVal->getValue()){} + const APInt& getAPIntValue() const { + return *APIntVal; + } +public: + + IntItem() {} + + operator const APInt&() const { + return getAPIntValue(); + } + + // Propagate APInt operators. + // Note, that + // /,/=,>>,>>= are not implemented in APInt. + // <<= is implemented for unsigned RHS, but not implemented for APInt RHS. + + INT_ITEM_DEFINE_COMPARISON(<, ult) + INT_ITEM_DEFINE_COMPARISON(>, ugt) + INT_ITEM_DEFINE_COMPARISON(<=, ule) + INT_ITEM_DEFINE_COMPARISON(>=, uge) + + INT_ITEM_DEFINE_COMPARISON(==, eq) + INT_ITEM_DEFINE_OP_STANDARD_INT(bool,==,uint64_t) + + INT_ITEM_DEFINE_COMPARISON(!=, ne) + INT_ITEM_DEFINE_OP_STANDARD_INT(bool,!=,uint64_t) + + INT_ITEM_DEFINE_BINARY_OP(*) + INT_ITEM_DEFINE_BINARY_OP(+) + INT_ITEM_DEFINE_OP_STANDARD_INT(IntItem,+,uint64_t) + INT_ITEM_DEFINE_BINARY_OP(-) + INT_ITEM_DEFINE_OP_STANDARD_INT(IntItem,-,uint64_t) + INT_ITEM_DEFINE_BINARY_OP(<<) + INT_ITEM_DEFINE_OP_STANDARD_INT(IntItem,<<,unsigned) + INT_ITEM_DEFINE_BINARY_OP(&) + INT_ITEM_DEFINE_BINARY_OP(^) + INT_ITEM_DEFINE_BINARY_OP(|) + + INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(*=) + INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(+=) + INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(-=) + INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(&=) + INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(^=) + INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(|=) + + // Special case for <<= + IntItem& operator <<= (unsigned RHS) { + APInt res = getAPIntValue(); + res <<= RHS; + Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); + ConstantIntVal = cast<ConstantInt>(NewVal); + return *this; + } + + INT_ITEM_DEFINE_UNARY_OP(-) + INT_ITEM_DEFINE_UNARY_OP(~) + + INT_ITEM_DEFINE_PREINCDEC(++) + INT_ITEM_DEFINE_PREINCDEC(--) + + // The set of workarounds, since currently we use ConstantInt implemented + // integer. + + static IntItem fromConstantInt(const ConstantInt *V) { + return IntItem(V); + } + static IntItem fromType(Type* Ty, const APInt& V) { + ConstantInt *C = cast<ConstantInt>(ConstantInt::get(Ty, V)); + return fromConstantInt(C); + } + static IntItem withImplLikeThis(const IntItem& LikeThis, const APInt& V) { + ConstantInt *C = cast<ConstantInt>(ConstantInt::get( + LikeThis.ConstantIntVal->getContext(), V)); + return fromConstantInt(C); + } + ConstantInt *toConstantInt() const { + return ConstantIntVal; + } +}; + +template<class IntType> +class IntRange { +protected: + IntType Low; + IntType High; + bool IsEmpty : 1; + bool IsSingleNumber : 1; + +public: + typedef IntRange<IntType> self; + typedef std::pair<self, self> SubRes; + + IntRange() : IsEmpty(true) {} + IntRange(const self &RHS) : + Low(RHS.Low), High(RHS.High), + IsEmpty(RHS.IsEmpty), IsSingleNumber(RHS.IsSingleNumber) {} + IntRange(const IntType &C) : + Low(C), High(C), IsEmpty(false), IsSingleNumber(true) {} + + IntRange(const IntType &L, const IntType &H) : Low(L), High(H), + IsEmpty(false), IsSingleNumber(Low == High) {} + + bool isEmpty() const { return IsEmpty; } + bool isSingleNumber() const { return IsSingleNumber; } + + const IntType& getLow() const { + assert(!IsEmpty && "Range is empty."); + return Low; + } + const IntType& getHigh() const { + assert(!IsEmpty && "Range is empty."); + return High; + } + + bool operator<(const self &RHS) const { + assert(!IsEmpty && "Left range is empty."); + assert(!RHS.IsEmpty && "Right range is empty."); + if (Low == RHS.Low) { + if (High > RHS.High) + return true; + return false; + } + if (Low < RHS.Low) + return true; + return false; + } + + bool operator==(const self &RHS) const { + assert(!IsEmpty && "Left range is empty."); + assert(!RHS.IsEmpty && "Right range is empty."); + return Low == RHS.Low && High == RHS.High; + } + + bool operator!=(const self &RHS) const { + return !operator ==(RHS); + } + + static bool LessBySize(const self &LHS, const self &RHS) { + return (LHS.High - LHS.Low) < (RHS.High - RHS.Low); + } + + bool isInRange(const IntType &IntVal) const { + assert(!IsEmpty && "Range is empty."); + return IntVal >= Low && IntVal <= High; + } + + SubRes sub(const self &RHS) const { + SubRes Res; + + // RHS is either more global and includes this range or + // if it doesn't intersected with this range. + if (!isInRange(RHS.Low) && !isInRange(RHS.High)) { + + // If RHS more global (it is enough to check + // only one border in this case. + if (RHS.isInRange(Low)) + return std::make_pair(self(Low, High), self()); + + return Res; + } + + if (Low < RHS.Low) { + Res.first.Low = Low; + IntType NewHigh = RHS.Low; + --NewHigh; + Res.first.High = NewHigh; + } + if (High > RHS.High) { + IntType NewLow = RHS.High; + ++NewLow; + Res.second.Low = NewLow; + Res.second.High = High; + } + return Res; + } + }; + +//===----------------------------------------------------------------------===// +/// IntegersSubsetGeneric - class that implements the subset of integers. It +/// consists from ranges and single numbers. +template <class IntTy> +class IntegersSubsetGeneric { +public: + // Use Chris Lattner idea, that was initially described here: + // http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20120213/136954.html + // In short, for more compact memory consumption we can store flat + // numbers collection, and define range as pair of indices. + // In that case we can safe some memory on 32 bit machines. + typedef std::vector<IntTy> FlatCollectionTy; + typedef std::pair<IntTy*, IntTy*> RangeLinkTy; + typedef std::vector<RangeLinkTy> RangeLinksTy; + typedef typename RangeLinksTy::const_iterator RangeLinksConstIt; + + typedef IntegersSubsetGeneric<IntTy> self; + +protected: + + FlatCollectionTy FlatCollection; + RangeLinksTy RangeLinks; + + bool IsSingleNumber; + bool IsSingleNumbersOnly; + +public: + + template<class RangesCollectionTy> + explicit IntegersSubsetGeneric(const RangesCollectionTy& Links) { + assert(Links.size() && "Empty ranges are not allowed."); + + // In case of big set of single numbers consumes additional RAM space, + // but allows to avoid additional reallocation. + FlatCollection.reserve(Links.size() * 2); + RangeLinks.reserve(Links.size()); + IsSingleNumbersOnly = true; + for (typename RangesCollectionTy::const_iterator i = Links.begin(), + e = Links.end(); i != e; ++i) { + RangeLinkTy RangeLink; + FlatCollection.push_back(i->getLow()); + RangeLink.first = &FlatCollection.back(); + if (i->getLow() != i->getHigh()) { + FlatCollection.push_back(i->getHigh()); + IsSingleNumbersOnly = false; + } + RangeLink.second = &FlatCollection.back(); + RangeLinks.push_back(RangeLink); + } + IsSingleNumber = IsSingleNumbersOnly && RangeLinks.size() == 1; + } + + IntegersSubsetGeneric(const self& RHS) { + *this = RHS; + } + + self& operator=(const self& RHS) { + FlatCollection.clear(); + RangeLinks.clear(); + FlatCollection.reserve(RHS.RangeLinks.size() * 2); + RangeLinks.reserve(RHS.RangeLinks.size()); + for (RangeLinksConstIt i = RHS.RangeLinks.begin(), e = RHS.RangeLinks.end(); + i != e; ++i) { + RangeLinkTy RangeLink; + FlatCollection.push_back(*(i->first)); + RangeLink.first = &FlatCollection.back(); + if (i->first != i->second) + FlatCollection.push_back(*(i->second)); + RangeLink.second = &FlatCollection.back(); + RangeLinks.push_back(RangeLink); + } + IsSingleNumber = RHS.IsSingleNumber; + IsSingleNumbersOnly = RHS.IsSingleNumbersOnly; + return *this; + } + + typedef IntRange<IntTy> Range; + + /// Checks is the given constant satisfies this case. Returns + /// true if it equals to one of contained values or belongs to the one of + /// contained ranges. + bool isSatisfies(const IntTy &CheckingVal) const { + if (IsSingleNumber) + return FlatCollection.front() == CheckingVal; + if (IsSingleNumbersOnly) + return std::find(FlatCollection.begin(), + FlatCollection.end(), + CheckingVal) != FlatCollection.end(); + + for (unsigned i = 0, e = getNumItems(); i < e; ++i) { + if (RangeLinks[i].first == RangeLinks[i].second) { + if (*RangeLinks[i].first == CheckingVal) + return true; + } else if (*RangeLinks[i].first <= CheckingVal && + *RangeLinks[i].second >= CheckingVal) + return true; + } + return false; + } + + /// Returns set's item with given index. + Range getItem(unsigned idx) const { + const RangeLinkTy &Link = RangeLinks[idx]; + if (Link.first != Link.second) + return Range(*Link.first, *Link.second); + else + return Range(*Link.first); + } + + /// Return number of items (ranges) stored in set. + unsigned getNumItems() const { + return RangeLinks.size(); + } + + /// Returns true if whole subset contains single element. + bool isSingleNumber() const { + return IsSingleNumber; + } + + /// Returns true if whole subset contains only single numbers, no ranges. + bool isSingleNumbersOnly() const { + return IsSingleNumbersOnly; + } + + /// Does the same like getItem(idx).isSingleNumber(), but + /// works faster, since we avoid creation of temporary range object. + bool isSingleNumber(unsigned idx) const { + return RangeLinks[idx].first == RangeLinks[idx].second; + } + + /// Returns set the size, that equals number of all values + sizes of all + /// ranges. + /// Ranges set is considered as flat numbers collection. + /// E.g.: for range [<0>, <1>, <4,8>] the size will 7; + /// for range [<0>, <1>, <5>] the size will 3 + unsigned getSize() const { + APInt sz(((const APInt&)getItem(0).getLow()).getBitWidth(), 0); + for (unsigned i = 0, e = getNumItems(); i != e; ++i) { + const APInt &Low = getItem(i).getLow(); + const APInt &High = getItem(i).getHigh(); + APInt S = High - Low + 1; + sz += S; + } + return sz.getZExtValue(); + } + + /// Allows to access single value even if it belongs to some range. + /// Ranges set is considered as flat numbers collection. + /// [<1>, <4,8>] is considered as [1,4,5,6,7,8] + /// For range [<1>, <4,8>] getSingleValue(3) returns 6. + APInt getSingleValue(unsigned idx) const { + APInt sz(((const APInt&)getItem(0).getLow()).getBitWidth(), 0); + for (unsigned i = 0, e = getNumItems(); i != e; ++i) { + const APInt &Low = getItem(i).getLow(); + const APInt &High = getItem(i).getHigh(); + APInt S = High - Low + 1; + APInt oldSz = sz; + sz += S; + if (sz.ugt(idx)) { + APInt Res = Low; + APInt Offset(oldSz.getBitWidth(), idx); + Offset -= oldSz; + Res += Offset; + return Res; + } + } + assert(0 && "Index exceeds high border."); + return sz; + } + + /// Does the same as getSingleValue, but works only if subset contains + /// single numbers only. + const IntTy& getSingleNumber(unsigned idx) const { + assert(IsSingleNumbersOnly && "This method works properly if subset " + "contains single numbers only."); + return FlatCollection[idx]; + } +}; + +//===----------------------------------------------------------------------===// +/// IntegersSubset - currently is extension of IntegersSubsetGeneric +/// that also supports conversion to/from Constant* object. +class IntegersSubset : public IntegersSubsetGeneric<IntItem> { + + typedef IntegersSubsetGeneric<IntItem> ParentTy; + + Constant *Holder; + + static unsigned getNumItemsFromConstant(Constant *C) { + return cast<ArrayType>(C->getType())->getNumElements(); + } + + static Range getItemFromConstant(Constant *C, unsigned idx) { + const Constant *CV = C->getAggregateElement(idx); + + unsigned NumEls = cast<VectorType>(CV->getType())->getNumElements(); + switch (NumEls) { + case 1: + return Range(IntItem::fromConstantInt( + cast<ConstantInt>(CV->getAggregateElement(0U))), + IntItem::fromConstantInt(cast<ConstantInt>( + cast<ConstantInt>(CV->getAggregateElement(0U))))); + case 2: + return Range(IntItem::fromConstantInt( + cast<ConstantInt>(CV->getAggregateElement(0U))), + IntItem::fromConstantInt( + cast<ConstantInt>(CV->getAggregateElement(1)))); + default: + assert(0 && "Only pairs and single numbers are allowed here."); + return Range(); + } + } + + std::vector<Range> rangesFromConstant(Constant *C) { + unsigned NumItems = getNumItemsFromConstant(C); + std::vector<Range> r; + r.reserve(NumItems); + for (unsigned i = 0, e = NumItems; i != e; ++i) + r.push_back(getItemFromConstant(C, i)); + return r; + } + +public: + + explicit IntegersSubset(Constant *C) : ParentTy(rangesFromConstant(C)), + Holder(C) {} + + IntegersSubset(const IntegersSubset& RHS) : + ParentTy(*(const ParentTy *)&RHS), // FIXME: tweak for msvc. + Holder(RHS.Holder) {} + + template<class RangesCollectionTy> + explicit IntegersSubset(const RangesCollectionTy& Src) : ParentTy(Src) { + std::vector<Constant*> Elts; + Elts.reserve(Src.size()); + for (typename RangesCollectionTy::const_iterator i = Src.begin(), + e = Src.end(); i != e; ++i) { + const Range &R = *i; + std::vector<Constant*> r; + if (R.isSingleNumber()) { + r.reserve(2); + // FIXME: Since currently we have ConstantInt based numbers + // use hack-conversion of IntItem to ConstantInt + r.push_back(R.getLow().toConstantInt()); + r.push_back(R.getHigh().toConstantInt()); + } else { + r.reserve(1); + r.push_back(R.getLow().toConstantInt()); + } + Constant *CV = ConstantVector::get(r); + Elts.push_back(CV); + } + ArrayType *ArrTy = + ArrayType::get(Elts.front()->getType(), (uint64_t)Elts.size()); + Holder = ConstantArray::get(ArrTy, Elts); + } + + operator Constant*() { return Holder; } + operator const Constant*() const { return Holder; } + Constant *operator->() { return Holder; } + const Constant *operator->() const { return Holder; } +}; + +} + +#endif /* CONSTANTRANGESSET_H_ */ diff --git a/include/llvm/Support/IntegersSubsetMapping.h b/include/llvm/Support/IntegersSubsetMapping.h new file mode 100644 index 0000000..cab18dc --- /dev/null +++ b/include/llvm/Support/IntegersSubsetMapping.h @@ -0,0 +1,580 @@ +//===- IntegersSubsetMapping.h - Mapping subset ==> Successor ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// @file +/// IntegersSubsetMapping is mapping from A to B, where +/// Items in A is subsets of integers, +/// Items in B some pointers (Successors). +/// If user which to add another subset for successor that is already +/// exists in mapping, IntegersSubsetMapping merges existing subset with +/// added one. +// +//===----------------------------------------------------------------------===// + +#ifndef CRSBUILDER_H_ +#define CRSBUILDER_H_ + +#include "llvm/Support/IntegersSubset.h" +#include <list> +#include <map> +#include <vector> + +namespace llvm { + +template <class SuccessorClass, + class IntegersSubsetTy = IntegersSubset, + class IntTy = IntItem> +class IntegersSubsetMapping { + // FIXME: To much similar iterators typedefs, similar names. + // - Rename RangeIterator to the cluster iterator. + // - Remove unused "add" methods. + // - Class contents needs cleaning. +public: + + typedef IntRange<IntTy> RangeTy; + + struct RangeEx : public RangeTy { + RangeEx() : Weight(1) {} + RangeEx(const RangeTy &R) : RangeTy(R), Weight(1) {} + RangeEx(const IntTy &C) : RangeTy(C), Weight(1) {} + RangeEx(const IntTy &L, const IntTy &H) : RangeTy(L, H), Weight(1) {} + RangeEx(const IntTy &L, const IntTy &H, unsigned W) : + RangeTy(L, H), Weight(W) {} + unsigned Weight; + }; + + typedef std::pair<RangeEx, SuccessorClass*> Cluster; + + typedef std::list<RangeTy> RangesCollection; + typedef typename RangesCollection::iterator RangesCollectionIt; + typedef typename RangesCollection::const_iterator RangesCollectionConstIt; + typedef IntegersSubsetMapping<SuccessorClass, IntegersSubsetTy, IntTy> self; + +protected: + + typedef std::list<Cluster> CaseItems; + typedef typename CaseItems::iterator CaseItemIt; + typedef typename CaseItems::const_iterator CaseItemConstIt; + + // TODO: Change unclean CRS prefixes to SubsetMap for example. + typedef std::map<SuccessorClass*, RangesCollection > CRSMap; + typedef typename CRSMap::iterator CRSMapIt; + + struct ClustersCmp { + bool operator()(const Cluster &C1, const Cluster &C2) { + return C1.first < C2.first; + } + }; + + CaseItems Items; + bool Sorted; + + bool isIntersected(CaseItemIt& LItem, CaseItemIt& RItem) { + return LItem->first.getHigh() >= RItem->first.getLow(); + } + + bool isJoinable(CaseItemIt& LItem, CaseItemIt& RItem) { + if (LItem->second != RItem->second) { + assert(!isIntersected(LItem, RItem) && + "Intersected items with different successors!"); + return false; + } + APInt RLow = RItem->first.getLow(); + if (RLow != APInt::getNullValue(RLow.getBitWidth())) + --RLow; + return LItem->first.getHigh() >= RLow; + } + + void sort() { + if (!Sorted) { + std::vector<Cluster> clustersVector; + clustersVector.reserve(Items.size()); + clustersVector.insert(clustersVector.begin(), Items.begin(), Items.end()); + std::sort(clustersVector.begin(), clustersVector.end(), ClustersCmp()); + Items.clear(); + Items.insert(Items.begin(), clustersVector.begin(), clustersVector.end()); + Sorted = true; + } + } + + enum DiffProcessState { + L_OPENED, + INTERSECT_OPENED, + R_OPENED, + ALL_IS_CLOSED + }; + + class DiffStateMachine { + + DiffProcessState State; + IntTy OpenPt; + SuccessorClass *CurrentLSuccessor; + SuccessorClass *CurrentRSuccessor; + + self *LeftMapping; + self *IntersectionMapping; + self *RightMapping; + + public: + + typedef + IntegersSubsetMapping<SuccessorClass, IntegersSubsetTy, IntTy> MappingTy; + + DiffStateMachine(MappingTy *L, + MappingTy *Intersection, + MappingTy *R) : + State(ALL_IS_CLOSED), + LeftMapping(L), + IntersectionMapping(Intersection), + RightMapping(R) + {} + + void onLOpen(const IntTy &Pt, SuccessorClass *S) { + switch (State) { + case R_OPENED: + if (Pt > OpenPt/*Don't add empty ranges.*/ && RightMapping) + RightMapping->add(OpenPt, Pt-1, CurrentRSuccessor); + State = INTERSECT_OPENED; + break; + case ALL_IS_CLOSED: + State = L_OPENED; + break; + default: + assert(0 && "Got unexpected point."); + break; + } + CurrentLSuccessor = S; + OpenPt = Pt; + } + + void onLClose(const IntTy &Pt) { + switch (State) { + case L_OPENED: + assert(Pt >= OpenPt && + "Subset is not sorted or contains overlapped ranges"); + if (LeftMapping) + LeftMapping->add(OpenPt, Pt, CurrentLSuccessor); + State = ALL_IS_CLOSED; + break; + case INTERSECT_OPENED: + if (IntersectionMapping) + IntersectionMapping->add(OpenPt, Pt, CurrentLSuccessor); + OpenPt = Pt + 1; + State = R_OPENED; + break; + default: + assert(0 && "Got unexpected point."); + break; + } + } + + void onROpen(const IntTy &Pt, SuccessorClass *S) { + switch (State) { + case L_OPENED: + if (Pt > OpenPt && LeftMapping) + LeftMapping->add(OpenPt, Pt-1, CurrentLSuccessor); + State = INTERSECT_OPENED; + break; + case ALL_IS_CLOSED: + State = R_OPENED; + break; + default: + assert(0 && "Got unexpected point."); + break; + } + CurrentRSuccessor = S; + OpenPt = Pt; + } + + void onRClose(const IntTy &Pt) { + switch (State) { + case R_OPENED: + assert(Pt >= OpenPt && + "Subset is not sorted or contains overlapped ranges"); + if (RightMapping) + RightMapping->add(OpenPt, Pt, CurrentRSuccessor); + State = ALL_IS_CLOSED; + break; + case INTERSECT_OPENED: + if (IntersectionMapping) + IntersectionMapping->add(OpenPt, Pt, CurrentLSuccessor); + OpenPt = Pt + 1; + State = L_OPENED; + break; + default: + assert(0 && "Got unexpected point."); + break; + } + } + + void onLROpen(const IntTy &Pt, + SuccessorClass *LS, + SuccessorClass *RS) { + switch (State) { + case ALL_IS_CLOSED: + State = INTERSECT_OPENED; + break; + default: + assert(0 && "Got unexpected point."); + break; + } + CurrentLSuccessor = LS; + CurrentRSuccessor = RS; + OpenPt = Pt; + } + + void onLRClose(const IntTy &Pt) { + switch (State) { + case INTERSECT_OPENED: + if (IntersectionMapping) + IntersectionMapping->add(OpenPt, Pt, CurrentLSuccessor); + State = ALL_IS_CLOSED; + break; + default: + assert(0 && "Got unexpected point."); + break; + } + } + + bool isLOpened() { return State == L_OPENED; } + bool isROpened() { return State == R_OPENED; } + }; + +public: + + // Don't public CaseItems itself. Don't allow edit the Items directly. + // Just present the user way to iterate over the internal collection + // sharing iterator, begin() and end(). Editing should be controlled by + // factory. + typedef CaseItemIt RangeIterator; + + typedef std::pair<SuccessorClass*, IntegersSubsetTy> Case; + typedef std::list<Case> Cases; + typedef typename Cases::iterator CasesIt; + + IntegersSubsetMapping() { + Sorted = false; + } + + bool verify() { + RangeIterator DummyErrItem; + return verify(DummyErrItem); + } + + bool verify(RangeIterator& errItem) { + if (Items.empty()) + return true; + sort(); + for (CaseItemIt j = Items.begin(), i = j++, e = Items.end(); + j != e; i = j++) { + if (isIntersected(i, j) && i->second != j->second) { + errItem = j; + return false; + } + } + return true; + } + + bool isOverlapped(self &RHS) { + if (Items.empty() || RHS.empty()) + return true; + + for (CaseItemIt L = Items.begin(), R = RHS.Items.begin(), + el = Items.end(), er = RHS.Items.end(); L != el && R != er;) { + + const RangeTy &LRange = L->first; + const RangeTy &RRange = R->first; + + if (LRange.getLow() > RRange.getLow()) { + if (RRange.isSingleNumber() || LRange.getLow() > RRange.getHigh()) + ++R; + else + return true; + } else if (LRange.getLow() < RRange.getLow()) { + if (LRange.isSingleNumber() || LRange.getHigh() < RRange.getLow()) + ++L; + else + return true; + } else // iRange.getLow() == jRange.getLow() + return true; + } + return false; + } + + + void optimize() { + if (Items.size() < 2) + return; + sort(); + CaseItems OldItems = Items; + Items.clear(); + const IntTy *Low = &OldItems.begin()->first.getLow(); + const IntTy *High = &OldItems.begin()->first.getHigh(); + unsigned Weight = 1; + SuccessorClass *Successor = OldItems.begin()->second; + for (CaseItemIt j = OldItems.begin(), i = j++, e = OldItems.end(); + j != e; i = j++) { + if (isJoinable(i, j)) { + const IntTy *CurHigh = &j->first.getHigh(); + ++Weight; + if (*CurHigh > *High) + High = CurHigh; + } else { + RangeEx R(*Low, *High, Weight); + add(R, Successor); + Low = &j->first.getLow(); + High = &j->first.getHigh(); + Weight = 1; + Successor = j->second; + } + } + RangeEx R(*Low, *High, Weight); + add(R, Successor); + // We recollected the Items, but we kept it sorted. + Sorted = true; + } + + /// Adds a constant value. + void add(const IntTy &C, SuccessorClass *S = 0) { + RangeTy R(C); + add(R, S); + } + + /// Adds a range. + void add(const IntTy &Low, const IntTy &High, SuccessorClass *S = 0) { + RangeTy R(Low, High); + add(R, S); + } + void add(const RangeTy &R, SuccessorClass *S = 0) { + RangeEx REx = R; + add(REx, S); + } + void add(const RangeEx &R, SuccessorClass *S = 0) { + Items.push_back(std::make_pair(R, S)); + Sorted = false; + } + + /// Adds all ranges and values from given ranges set to the current + /// mapping. + void add(const IntegersSubsetTy &CRS, SuccessorClass *S = 0) { + for (unsigned i = 0, e = CRS.getNumItems(); i < e; ++i) { + RangeTy R = CRS.getItem(i); + add(R, S); + } + } + + void add(self& RHS) { + Items.insert(Items.end(), RHS.Items.begin(), RHS.Items.end()); + } + + void add(self& RHS, SuccessorClass *S) { + for (CaseItemIt i = RHS.Items.begin(), e = RHS.Items.end(); i != e; ++i) + add(i->first, S); + } + + void add(const RangesCollection& RHS, SuccessorClass *S = 0) { + for (RangesCollectionConstIt i = RHS.begin(), e = RHS.end(); i != e; ++i) + add(*i, S); + } + + /// Removes items from set. + void removeItem(RangeIterator i) { Items.erase(i); } + + /// Moves whole case from current mapping to the NewMapping object. + void detachCase(self& NewMapping, SuccessorClass *Succ) { + for (CaseItemIt i = Items.begin(); i != Items.end();) + if (i->second == Succ) { + NewMapping.add(i->first, i->second); + Items.erase(i++); + } else + ++i; + } + + /// Removes all clusters for given successor. + void removeCase(SuccessorClass *Succ) { + for (CaseItemIt i = Items.begin(); i != Items.end();) + if (i->second == Succ) { + Items.erase(i++); + } else + ++i; + } + + /// Find successor that satisfies given value. + SuccessorClass *findSuccessor(const IntTy& Val) { + for (CaseItemIt i = Items.begin(); i != Items.end(); ++i) { + if (i->first.isInRange(Val)) + return i->second; + } + return 0; + } + + /// Calculates the difference between this mapping and RHS. + /// THIS without RHS is placed into LExclude, + /// RHS without THIS is placed into RExclude, + /// THIS intersect RHS is placed into Intersection. + void diff(self *LExclude, self *Intersection, self *RExclude, + const self& RHS) { + + DiffStateMachine Machine(LExclude, Intersection, RExclude); + + CaseItemConstIt L = Items.begin(), R = RHS.Items.begin(); + while (L != Items.end() && R != RHS.Items.end()) { + const Cluster &LCluster = *L; + const RangeEx &LRange = LCluster.first; + const Cluster &RCluster = *R; + const RangeEx &RRange = RCluster.first; + + if (LRange.getHigh() < RRange.getLow()) { + Machine.onLOpen(LRange.getLow(), LCluster.second); + Machine.onLClose(LRange.getHigh()); + ++L; + continue; + } + + if (LRange.getLow() > RRange.getHigh()) { + Machine.onROpen(RRange.getLow(), RCluster.second); + Machine.onRClose(RRange.getHigh()); + ++R; + continue; + } + + if (LRange.getLow() < RRange.getLow()) { + // May be opened in previous iteration. + if (!Machine.isLOpened()) + Machine.onLOpen(LRange.getLow(), LCluster.second); + Machine.onROpen(RRange.getLow(), RCluster.second); + } + else if (RRange.getLow() < LRange.getLow()) { + if (!Machine.isROpened()) + Machine.onROpen(RRange.getLow(), RCluster.second); + Machine.onLOpen(LRange.getLow(), LCluster.second); + } + else + Machine.onLROpen(LRange.getLow(), LCluster.second, RCluster.second); + + if (LRange.getHigh() < RRange.getHigh()) { + Machine.onLClose(LRange.getHigh()); + ++L; + while(L != Items.end() && L->first.getHigh() < RRange.getHigh()) { + Machine.onLOpen(L->first.getLow(), L->second); + Machine.onLClose(L->first.getHigh()); + ++L; + } + } + else if (RRange.getHigh() < LRange.getHigh()) { + Machine.onRClose(RRange.getHigh()); + ++R; + while(R != RHS.Items.end() && R->first.getHigh() < LRange.getHigh()) { + Machine.onROpen(R->first.getLow(), R->second); + Machine.onRClose(R->first.getHigh()); + ++R; + } + } + else { + Machine.onLRClose(LRange.getHigh()); + ++L; + ++R; + } + } + + if (L != Items.end()) { + if (Machine.isLOpened()) { + Machine.onLClose(L->first.getHigh()); + ++L; + } + if (LExclude) + while (L != Items.end()) { + LExclude->add(L->first, L->second); + ++L; + } + } else if (R != RHS.Items.end()) { + if (Machine.isROpened()) { + Machine.onRClose(R->first.getHigh()); + ++R; + } + if (RExclude) + while (R != RHS.Items.end()) { + RExclude->add(R->first, R->second); + ++R; + } + } + } + + /// Builds the finalized case objects. + void getCases(Cases& TheCases, bool PreventMerging = false) { + //FIXME: PreventMerging is a temporary parameter. + //Currently a set of passes is still knows nothing about + //switches with case ranges, and if these passes meet switch + //with complex case that crashs the application. + if (PreventMerging) { + for (RangeIterator i = this->begin(); i != this->end(); ++i) { + RangesCollection SingleRange; + SingleRange.push_back(i->first); + TheCases.push_back(std::make_pair(i->second, + IntegersSubsetTy(SingleRange))); + } + return; + } + CRSMap TheCRSMap; + for (RangeIterator i = this->begin(); i != this->end(); ++i) + TheCRSMap[i->second].push_back(i->first); + for (CRSMapIt i = TheCRSMap.begin(), e = TheCRSMap.end(); i != e; ++i) + TheCases.push_back(std::make_pair(i->first, IntegersSubsetTy(i->second))); + } + + /// Builds the finalized case objects ignoring successor values, as though + /// all ranges belongs to the same successor. + IntegersSubsetTy getCase() { + RangesCollection Ranges; + for (RangeIterator i = this->begin(); i != this->end(); ++i) + Ranges.push_back(i->first); + return IntegersSubsetTy(Ranges); + } + + /// Returns pointer to value of case if it is single-numbered or 0 + /// in another case. + const IntTy* getCaseSingleNumber(SuccessorClass *Succ) { + const IntTy* Res = 0; + for (CaseItemIt i = Items.begin(); i != Items.end(); ++i) + if (i->second == Succ) { + if (!i->first.isSingleNumber()) + return 0; + if (Res) + return 0; + else + Res = &(i->first.getLow()); + } + return Res; + } + + /// Returns true if there is no ranges and values inside. + bool empty() const { return Items.empty(); } + + void clear() { + Items.clear(); + // Don't reset Sorted flag: + // 1. For empty mapping it matters nothing. + // 2. After first item will added Sorted flag will cleared. + } + + // Returns number of clusters + unsigned size() const { + return Items.size(); + } + + RangeIterator begin() { return Items.begin(); } + RangeIterator end() { return Items.end(); } +}; + +class BasicBlock; +typedef IntegersSubsetMapping<BasicBlock> IntegersSubsetToBB; + +} + +#endif /* CRSBUILDER_H_ */ diff --git a/include/llvm/Support/LEB128.h b/include/llvm/Support/LEB128.h new file mode 100644 index 0000000..00c7eea --- /dev/null +++ b/include/llvm/Support/LEB128.h @@ -0,0 +1,58 @@ +//===- llvm/Support/LEB128.h - [SU]LEB128 utility functions -----*- 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 some utility functions for encoding SLEB128 and +// ULEB128 values. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_LEB128_H +#define LLVM_SYSTEM_LEB128_H + +#include <llvm/Support/raw_ostream.h> + +namespace llvm { + +/// Utility function to encode a SLEB128 value. +static inline void encodeSLEB128(int64_t Value, raw_ostream &OS) { + bool More; + do { + uint8_t Byte = Value & 0x7f; + // NOTE: this assumes that this signed shift is an arithmetic right shift. + Value >>= 7; + More = !((((Value == 0 ) && ((Byte & 0x40) == 0)) || + ((Value == -1) && ((Byte & 0x40) != 0)))); + if (More) + Byte |= 0x80; // Mark this byte that that more bytes will follow. + OS << char(Byte); + } while (More); +} + +/// Utility function to encode a ULEB128 value. +static inline void encodeULEB128(uint64_t Value, raw_ostream &OS, + unsigned Padding = 0) { + do { + uint8_t Byte = Value & 0x7f; + Value >>= 7; + if (Value != 0 || Padding != 0) + Byte |= 0x80; // Mark this byte that that more bytes will follow. + OS << char(Byte); + } while (Value != 0); + + // Pad with 0x80 and emit a null byte at the end. + if (Padding != 0) { + for (; Padding != 1; --Padding) + OS << '\x80'; + OS << '\x00'; + } +} + +} // namespace llvm + +#endif // LLVM_SYSTEM_LEB128_H diff --git a/include/llvm/Support/MachO.h b/include/llvm/Support/MachO.h index 44a7a79..7f28c3f 100644 --- a/include/llvm/Support/MachO.h +++ b/include/llvm/Support/MachO.h @@ -174,50 +174,50 @@ namespace llvm { RebaseTypePointer = 1u, // REBASE_TYPE_POINTER RebaseTypeTextAbsolute32 = 2u, // REBASE_TYPE_TEXT_ABSOLUTE32 - RebaseTypeTextPCRelative32 = 3u, // REBASE_TYPE_TEXT_PCREL32 + RebaseTypeTextPCRelative32 = 3u, // REBASE_TYPE_TEXT_PCREL32 RebaseOpcodeMask = 0xF0u, // REBASE_OPCODE_MASK RebaseImmediateMask = 0x0Fu, // REBASE_IMMEDIATE_MASK RebaseOpcodeDone = 0x00u, // REBASE_OPCODE_DONE RebaseOpcodeSetTypeImmediate = 0x10u, // REBASE_OPCODE_SET_TYPE_IMM - RebaseOpcodeSetSegmentAndOffsetULEB = 0x20u, // REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB + RebaseOpcodeSetSegmentAndOffsetULEB = 0x20u, // REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB RebaseOpcodeAddAddressULEB = 0x30u, // REBASE_OPCODE_ADD_ADDR_ULEB - RebaseOpcodeAddAddressImmediateScaled = 0x40u, // REBASE_OPCODE_ADD_ADDR_IMM_SCALED - RebaseOpcodeDoRebaseImmediateTimes = 0x50u, // REBASE_OPCODE_DO_REBASE_IMM_TIMES + RebaseOpcodeAddAddressImmediateScaled = 0x40u, // REBASE_OPCODE_ADD_ADDR_IMM_SCALED + RebaseOpcodeDoRebaseImmediateTimes = 0x50u, // REBASE_OPCODE_DO_REBASE_IMM_TIMES RebaseOpcodeDoRebaseULEBTimes = 0x60u, // REBASE_OPCODE_DO_REBASE_ULEB_TIMES RebaseOpcodeDoRebaseAddAddressULEB = 0x70u, // REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB RebaseOpcodeDoRebaseULEBTimesSkippingULEB = 0x80u, // REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB BindTypePointer = 1u, // BIND_TYPE_POINTER - BindTypeTextAbsolute32 = 2u, // BIND_TYPE_TEXT_ABSOLUTE32 - BindTypeTextPCRelative32 = 3u, // BIND_TYPE_TEXT_PCREL32 + BindTypeTextAbsolute32 = 2u, // BIND_TYPE_TEXT_ABSOLUTE32 + BindTypeTextPCRelative32 = 3u, // BIND_TYPE_TEXT_PCREL32 BindSpecialDylibSelf = 0u, // BIND_SPECIAL_DYLIB_SELF BindSpecialDylibMainExecutable = -1u, // BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE BindSpecialDylibFlatLookup = -2u, // BIND_SPECIAL_DYLIB_FLAT_LOOKUP BindSymbolFlagsWeakImport = 0x1u, // BIND_SYMBOL_FLAGS_WEAK_IMPORT - BindSymbolFlagsNonWeakDefinition = 0x8u, // BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION + BindSymbolFlagsNonWeakDefinition = 0x8u, // BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION BindOpcodeMask = 0xF0u, // BIND_OPCODE_MASK BindImmediateMask = 0x0Fu, // BIND_IMMEDIATE_MASK BindOpcodeDone = 0x00u, // BIND_OPCODE_DONE BindOpcodeSetDylibOrdinalImmediate = 0x10u, // BIND_OPCODE_SET_DYLIB_ORDINAL_IMM BindOpcodeSetDylibOrdinalULEB = 0x20u, // BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB - BindOpcodeSetDylibSpecialImmediate = 0x30u, // BIND_OPCODE_SET_DYLIB_SPECIAL_IMM - BindOpcodeSetSymbolTrailingFlagsImmediate = 0x40u, // BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM - BindOpcodeSetTypeImmediate = 0x50u, // BIND_OPCODE_SET_TYPE_IMM + BindOpcodeSetDylibSpecialImmediate = 0x30u, // BIND_OPCODE_SET_DYLIB_SPECIAL_IMM + BindOpcodeSetSymbolTrailingFlagsImmediate = 0x40u, // BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM + BindOpcodeSetTypeImmediate = 0x50u, // BIND_OPCODE_SET_TYPE_IMM BindOpcodeSetAppendSLEB = 0x60u, // BIND_OPCODE_SET_ADDEND_SLEB BindOpcodeSetSegmentAndOffsetULEB = 0x70u, // BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB BindOpcodeAddAddressULEB = 0x80u, // BIND_OPCODE_ADD_ADDR_ULEB BindOpcodeDoBind = 0x90u, // BIND_OPCODE_DO_BIND - BindOpcodeDoBindAddAddressULEB = 0xA0u, // BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB - BindOpcodeDoBindAddAddressImmediateScaled = 0xB0u, // BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED + BindOpcodeDoBindAddAddressULEB = 0xA0u, // BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB + BindOpcodeDoBindAddAddressImmediateScaled = 0xB0u, // BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED BindOpcodeDoBindULEBTimesSkippingULEB = 0xC0u, // BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB ExportSymbolFlagsKindMask = 0x03u, // EXPORT_SYMBOL_FLAGS_KIND_MASK - ExportSymbolFlagsKindRegular = 0x00u, // EXPORT_SYMBOL_FLAGS_KIND_REGULAR + ExportSymbolFlagsKindRegular = 0x00u, // EXPORT_SYMBOL_FLAGS_KIND_REGULAR ExportSymbolFlagsKindThreadLocal = 0x01u, // EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL ExportSymbolFlagsWeakDefinition = 0x04u, // EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION ExportSymbolFlagsIndirectDefinition = 0x08u, // EXPORT_SYMBOL_FLAGS_INDIRECT_DEFINITION @@ -227,7 +227,7 @@ namespace llvm { // Constant masks for the "n_type" field in llvm::MachO::nlist and // llvm::MachO::nlist_64 NlistMaskStab = 0xe0, // N_STAB - NlistMaskPrivateExternal = 0x10, // N_PEXT + NlistMaskPrivateExternal = 0x10, // N_PEXT NlistMaskType = 0x0e, // N_TYPE NlistMaskExternal = 0x01, // N_EXT @@ -249,35 +249,35 @@ namespace llvm { // Constant values for the "n_type" field in llvm::MachO::nlist and // llvm::MachO::nlist_64 when "(n_type & NlistMaskStab) != 0" - StabGlobalSymbol = 0x20u, // N_GSYM - StabFunctionName = 0x22u, // N_FNAME - StabFunction = 0x24u, // N_FUN - StabStaticSymbol = 0x26u, // N_STSYM - StabLocalCommon = 0x28u, // N_LCSYM + StabGlobalSymbol = 0x20u, // N_GSYM + StabFunctionName = 0x22u, // N_FNAME + StabFunction = 0x24u, // N_FUN + StabStaticSymbol = 0x26u, // N_STSYM + StabLocalCommon = 0x28u, // N_LCSYM StabBeginSymbol = 0x2Eu, // N_BNSYM - StabSourceFileOptions = 0x3Cu, // N_OPT - StabRegisterSymbol = 0x40u, // N_RSYM - StabSourceLine = 0x44u, // N_SLINE + StabSourceFileOptions = 0x3Cu, // N_OPT + StabRegisterSymbol = 0x40u, // N_RSYM + StabSourceLine = 0x44u, // N_SLINE StabEndSymbol = 0x4Eu, // N_ENSYM - StabStructureType = 0x60u, // N_SSYM - StabSourceFileName = 0x64u, // N_SO - StabObjectFileName = 0x66u, // N_OSO - StabLocalSymbol = 0x80u, // N_LSYM - StabBeginIncludeFileName = 0x82u, // N_BINCL - StabIncludeFileName = 0x84u, // N_SOL + StabStructureType = 0x60u, // N_SSYM + StabSourceFileName = 0x64u, // N_SO + StabObjectFileName = 0x66u, // N_OSO + StabLocalSymbol = 0x80u, // N_LSYM + StabBeginIncludeFileName = 0x82u, // N_BINCL + StabIncludeFileName = 0x84u, // N_SOL StabCompilerParameters = 0x86u, // N_PARAMS StabCompilerVersion = 0x88u, // N_VERSION StabCompilerOptLevel = 0x8Au, // N_OLEVEL - StabParameter = 0xA0u, // N_PSYM - StabEndIncludeFile = 0xA2u, // N_EINCL - StabAlternateEntry = 0xA4u, // N_ENTRY - StabLeftBracket = 0xC0u, // N_LBRAC - StabDeletedIncludeFile = 0xC2u, // N_EXCL - StabRightBracket = 0xE0u, // N_RBRAC - StabBeginCommon = 0xE2u, // N_BCOMM - StabEndCommon = 0xE4u, // N_ECOMM - StabEndCommonLocal = 0xE8u, // N_ECOML - StabLength = 0xFEu // N_LENG + StabParameter = 0xA0u, // N_PSYM + StabEndIncludeFile = 0xA2u, // N_EINCL + StabAlternateEntry = 0xA4u, // N_ENTRY + StabLeftBracket = 0xC0u, // N_LBRAC + StabDeletedIncludeFile = 0xC2u, // N_EXCL + StabRightBracket = 0xE0u, // N_RBRAC + StabBeginCommon = 0xE2u, // N_BCOMM + StabEndCommon = 0xE4u, // N_ECOMM + StabEndCommonLocal = 0xE8u, // N_ECOML + StabLength = 0xFEu // N_LENG }; @@ -490,12 +490,12 @@ namespace llvm { uint32_t nextrel; uint32_t locreloff; uint32_t nlocrel; - }; + }; struct dylib_table_of_contents { uint32_t symbol_index; uint32_t module_index; - }; + }; struct dylib_module { uint32_t module_name; @@ -511,7 +511,7 @@ namespace llvm { uint32_t ninit_nterm; uint32_t objc_module_info_addr; uint32_t objc_module_info_size; - }; + }; struct dylib_module_64 { uint32_t module_name; diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h index d085c94..4005161 100644 --- a/include/llvm/Support/MathExtras.h +++ b/include/llvm/Support/MathExtras.h @@ -414,14 +414,14 @@ int IsInf(double d); /// MinAlign - A and B are either alignments or offsets. Return the minimum /// alignment that may be assumed after adding the two together. -static inline uint64_t MinAlign(uint64_t A, uint64_t B) { +inline uint64_t MinAlign(uint64_t A, uint64_t B) { // The largest power of 2 that divides both A and B. return (A | B) & -(A | B); } /// NextPowerOf2 - Returns the next power of two (in 64-bits) /// that is strictly greater than A. Returns zero on overflow. -static inline uint64_t NextPowerOf2(uint64_t A) { +inline uint64_t NextPowerOf2(uint64_t A) { A |= (A >> 1); A |= (A >> 2); A |= (A >> 4); diff --git a/include/llvm/Support/PathV2.h b/include/llvm/Support/PathV2.h index 6d38c95..8d79709 100644 --- a/include/llvm/Support/PathV2.h +++ b/include/llvm/Support/PathV2.h @@ -47,9 +47,9 @@ namespace path { /// C:\foo\bar => C:,/,foo,bar /// class const_iterator { - StringRef Path; //< The entire path. - StringRef Component; //< The current component. Not necessarily in Path. - size_t Position; //< The iterators current position within Path. + StringRef Path; ///< The entire path. + StringRef Component; ///< The current component. Not necessarily in Path. + size_t Position; ///< The iterators current position within Path. // An end iterator has Position = Path.size() + 1. friend const_iterator begin(StringRef path); diff --git a/include/llvm/Support/Process.h b/include/llvm/Support/Process.h index d796b79..088897c 100644 --- a/include/llvm/Support/Process.h +++ b/include/llvm/Support/Process.h @@ -1,4 +1,4 @@ -//===- llvm/Support/Process.h ------------------------------------*- C++ -*-===// +//===- llvm/Support/Process.h -----------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -97,6 +97,10 @@ namespace sys { /// the user rather than being put on a pipe or stored in a file. static bool FileDescriptorIsDisplayed(int fd); + /// This function determines if the given file descriptor is displayd and + /// supports colors. + static bool FileDescriptorHasColors(int fd); + /// This function determines the number of columns in the window /// if standard output is connected to a "tty" or "console" /// window. If standard output is not connected to a tty or @@ -142,6 +146,10 @@ namespace sys { /// Resets the terminals colors, or returns an escape sequence to do so. static const char *ResetColor(); + + /// Get the result of a process wide random number generator. The + /// generator will be automatically seeded in non-deterministic fashion. + static unsigned GetRandomNumber(); /// @} }; } diff --git a/include/llvm/Support/SMLoc.h b/include/llvm/Support/SMLoc.h index d48bfcc..1bf810b 100644 --- a/include/llvm/Support/SMLoc.h +++ b/include/llvm/Support/SMLoc.h @@ -24,7 +24,6 @@ class SMLoc { const char *Ptr; public: SMLoc() : Ptr(0) {} - SMLoc(const SMLoc &RHS) : Ptr(RHS.Ptr) {} bool isValid() const { return Ptr != 0; } @@ -48,7 +47,7 @@ public: SMLoc Start, End; SMRange() {} - SMRange(SMLoc Start, SMLoc End) : Start(Start), End(End) { + SMRange(SMLoc St, SMLoc En) : Start(St), End(En) { assert(Start.isValid() == End.isValid() && "Start and end should either both be valid or both be invalid!"); } diff --git a/include/llvm/Support/SourceMgr.h b/include/llvm/Support/SourceMgr.h index 76967db..8949a3a 100644 --- a/include/llvm/Support/SourceMgr.h +++ b/include/llvm/Support/SourceMgr.h @@ -123,7 +123,14 @@ public: /// FindLineNumber - Find the line number for the specified location in the /// specified file. This is not a fast method. - unsigned FindLineNumber(SMLoc Loc, int BufferID = -1) const; + unsigned FindLineNumber(SMLoc Loc, int BufferID = -1) const { + return getLineAndColumn(Loc, BufferID).first; + } + + /// getLineAndColumn - Find the line and column number for the specified + /// location in the specified file. This is not a fast method. + std::pair<unsigned, unsigned> + getLineAndColumn(SMLoc Loc, int BufferID = -1) const; /// PrintMessage - Emit a message about the specified location with the /// specified string. @@ -169,9 +176,9 @@ public: SMDiagnostic() : SM(0), LineNo(0), ColumnNo(0), Kind(SourceMgr::DK_Error) {} // Diagnostic with no location (e.g. file not found, command line arg error). - SMDiagnostic(const std::string &filename, SourceMgr::DiagKind Kind, + SMDiagnostic(const std::string &filename, SourceMgr::DiagKind Knd, const std::string &Msg) - : SM(0), Filename(filename), LineNo(-1), ColumnNo(-1), Kind(Kind), + : SM(0), Filename(filename), LineNo(-1), ColumnNo(-1), Kind(Knd), Message(Msg) {} // Diagnostic with a location. diff --git a/include/llvm/Support/TargetRegistry.h b/include/llvm/Support/TargetRegistry.h index 8808130..c0be8f1 100644 --- a/include/llvm/Support/TargetRegistry.h +++ b/include/llvm/Support/TargetRegistry.h @@ -108,6 +108,7 @@ namespace llvm { const MCRegisterInfo &MRI, const MCSubtargetInfo &STI); typedef MCCodeEmitter *(*MCCodeEmitterCtorTy)(const MCInstrInfo &II, + const MCRegisterInfo &MRI, const MCSubtargetInfo &STI, MCContext &Ctx); typedef MCStreamer *(*MCObjectStreamerCtorTy)(const Target &T, @@ -405,11 +406,12 @@ namespace llvm { /// createMCCodeEmitter - Create a target specific code emitter. MCCodeEmitter *createMCCodeEmitter(const MCInstrInfo &II, + const MCRegisterInfo &MRI, const MCSubtargetInfo &STI, MCContext &Ctx) const { if (!MCCodeEmitterCtorFn) return 0; - return MCCodeEmitterCtorFn(II, STI, Ctx); + return MCCodeEmitterCtorFn(II, MRI, STI, Ctx); } /// createMCObjectStreamer - Create a target specific MCStreamer. @@ -510,6 +512,21 @@ namespace llvm { static const Target *lookupTarget(const std::string &Triple, std::string &Error); + /// lookupTarget - Lookup a target based on an architecture name + /// and a target triple. If the architecture name is non-empty, + /// then the lookup is done by architecture. Otherwise, the target + /// triple is used. + /// + /// \param ArchName - The architecture to use for finding a target. + /// \param TheTriple - The triple to use for finding a target. The + /// triple is updated with canonical architecture name if a lookup + /// by architecture is done. + /// \param Error - On failure, an error string describing why no target was + /// found. + static const Target *lookupTarget(const std::string &ArchName, + Triple &TheTriple, + std::string &Error); + /// getClosestTargetForJIT - Pick the best target that is compatible with /// the current host. If no close target can be found, this returns null /// and sets the Error string to a reason. @@ -1129,6 +1146,7 @@ namespace llvm { private: static MCCodeEmitter *Allocator(const MCInstrInfo &II, + const MCRegisterInfo &MRI, const MCSubtargetInfo &STI, MCContext &Ctx) { return new MCCodeEmitterImpl(); diff --git a/include/llvm/Support/ThreadLocal.h b/include/llvm/Support/ThreadLocal.h index 15350a7..62ec90a 100644 --- a/include/llvm/Support/ThreadLocal.h +++ b/include/llvm/Support/ThreadLocal.h @@ -15,6 +15,7 @@ #define LLVM_SYSTEM_THREAD_LOCAL_H #include "llvm/Support/Threading.h" +#include "llvm/Support/DataTypes.h" #include <cassert> namespace llvm { @@ -22,7 +23,15 @@ namespace llvm { // ThreadLocalImpl - Common base class of all ThreadLocal instantiations. // YOU SHOULD NEVER USE THIS DIRECTLY. class ThreadLocalImpl { - void* data; + typedef uint64_t ThreadLocalDataTy; + /// \brief Platform-specific thread local data. + /// + /// This is embedded in the class and we avoid malloc'ing/free'ing it, + /// to make this class more safe for use along with CrashRecoveryContext. + union { + char data[sizeof(ThreadLocalDataTy)]; + ThreadLocalDataTy align_data; + }; public: ThreadLocalImpl(); virtual ~ThreadLocalImpl(); diff --git a/include/llvm/Support/ValueHandle.h b/include/llvm/Support/ValueHandle.h index b7210b2..61e21b8 100644 --- a/include/llvm/Support/ValueHandle.h +++ b/include/llvm/Support/ValueHandle.h @@ -110,11 +110,12 @@ protected: V != DenseMapInfo<Value *>::getTombstoneKey(); } -private: +public: // Callbacks made from Value. static void ValueIsDeleted(Value *V); static void ValueIsRAUWd(Value *Old, Value *New); +private: // Internal implementation details. ValueHandleBase **getPrevPtr() const { return PrevPair.getPointer(); } HandleBaseKind getKind() const { return PrevPair.getInt(); } @@ -367,7 +368,7 @@ protected: CallbackVH(const CallbackVH &RHS) : ValueHandleBase(Callback, RHS) {} - virtual ~CallbackVH(); + virtual ~CallbackVH() {} void setValPtr(Value *P) { ValueHandleBase::operator=(P); @@ -389,15 +390,13 @@ public: /// /// All implementations must remove the reference from this object to the /// Value that's being destroyed. - virtual void deleted() { - setValPtr(NULL); - } + virtual void deleted(); /// Called when this->getValPtr()->replaceAllUsesWith(new_value) is called, /// _before_ any of the uses have actually been replaced. If WeakVH were /// implemented as a CallbackVH, it would use this method to call /// setValPtr(new_value). AssertingVH would do nothing in this method. - virtual void allUsesReplacedWith(Value *) {} + virtual void allUsesReplacedWith(Value *); }; // Specialize simplify_type to allow CallbackVH to participate in diff --git a/include/llvm/Support/YAMLParser.h b/include/llvm/Support/YAMLParser.h index 47206b3..98910eb 100644 --- a/include/llvm/Support/YAMLParser.h +++ b/include/llvm/Support/YAMLParser.h @@ -130,7 +130,7 @@ public: void setError(const Twine &Message, Token &Location) const; bool failed() const; - virtual void skip() {}; + virtual void skip() {} unsigned int getType() const { return TypeID; } static inline bool classof(const Node *) { return true; } @@ -336,7 +336,7 @@ public: enum MappingType { MT_Block, MT_Flow, - MT_Inline //< An inline mapping node is used for "[key: value]". + MT_Inline ///< An inline mapping node is used for "[key: value]". }; MappingNode(OwningPtr<Document> &D, StringRef Anchor, MappingType MT) @@ -513,37 +513,44 @@ private: /// @brief Iterator abstraction for Documents over a Stream. class document_iterator { public: - document_iterator() : Doc(NullDoc) {} - document_iterator(OwningPtr<Document> &D) : Doc(D) {} + document_iterator() : Doc(0) {} + document_iterator(OwningPtr<Document> &D) : Doc(&D) {} bool operator ==(const document_iterator &Other) { - return Doc == Other.Doc; + if (isAtEnd() || Other.isAtEnd()) + return isAtEnd() && Other.isAtEnd(); + + return *Doc == *Other.Doc; } bool operator !=(const document_iterator &Other) { return !(*this == Other); } document_iterator operator ++() { - if (!Doc->skip()) { - Doc.reset(0); + assert(Doc != 0 && "incrementing iterator past the end."); + if (!(*Doc)->skip()) { + Doc->reset(0); } else { - Stream &S = Doc->stream; - Doc.reset(new Document(S)); + Stream &S = (*Doc)->stream; + Doc->reset(new Document(S)); } return *this; } Document &operator *() { - return *Doc; + return *Doc->get(); } OwningPtr<Document> &operator ->() { - return Doc; + return *Doc; } private: - static OwningPtr<Document> NullDoc; - OwningPtr<Document> &Doc; + bool isAtEnd() const { + return Doc == 0 || *Doc == 0; + } + + OwningPtr<Document> *Doc; }; } diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h index 6c5d478..5de749a 100644 --- a/include/llvm/Support/raw_ostream.h +++ b/include/llvm/Support/raw_ostream.h @@ -230,6 +230,9 @@ public: /// rather than being put on a pipe or stored in a file. virtual bool is_displayed() const { return false; } + /// This function determines if this stream is displayed and supports colors. + virtual bool has_colors() const { return is_displayed(); } + //===--------------------------------------------------------------------===// // Subclass Interface //===--------------------------------------------------------------------===// @@ -386,10 +389,12 @@ public: virtual bool is_displayed() const; + virtual bool has_colors() const; + /// has_error - Return the value of the flag in this raw_fd_ostream indicating /// whether an output error has been encountered. /// This doesn't implicitly flush any pending output. Also, it doesn't - /// guarantee to detect all errors unless the the stream has been closed. + /// guarantee to detect all errors unless the stream has been closed. bool has_error() const { return Error; } diff --git a/include/llvm/Support/type_traits.h b/include/llvm/Support/type_traits.h index a3a551f..7b97547 100644 --- a/include/llvm/Support/type_traits.h +++ b/include/llvm/Support/type_traits.h @@ -21,6 +21,11 @@ #include <cstddef> #include <utility> +#ifndef __has_feature +#define LLVM_DEFINED_HAS_FEATURE +#define __has_feature(x) 0 +#endif + // This is actually the conforming implementation which works with abstract // classes. However, enough compilers have trouble with it that most will use // the one in boost/type_traits/object_traits.hpp. This implementation actually @@ -58,9 +63,15 @@ struct is_class /// type can be copied around with memcpy instead of running ctors etc. template <typename T> struct isPodLike { +#if __has_feature(is_trivially_copyable) + // If the compiler supports the is_trivially_copyable trait use it, as it + // matches the definition of isPodLike closely. + static const bool value = __is_trivially_copyable(T); +#else // If we don't know anything else, we can (at least) assume that all non-class // types are PODs. static const bool value = !is_class<T>::value; +#endif }; // std::pair's are pod-like if their elements are. @@ -202,4 +213,8 @@ struct conditional<false, T, F> { typedef F type; }; } +#ifdef LLVM_DEFINED_HAS_FEATURE +#undef __has_feature +#endif + #endif diff --git a/include/llvm/TableGen/Record.h b/include/llvm/TableGen/Record.h index 3aea1ae..a8256b7 100644 --- a/include/llvm/TableGen/Record.h +++ b/include/llvm/TableGen/Record.h @@ -1558,12 +1558,14 @@ public: return I == Defs.end() ? 0 : I->second; } void addClass(Record *R) { - assert(getClass(R->getNameInitAsString()) == 0 && "Class already exists!"); - Classes.insert(std::make_pair(R->getNameInitAsString(), R)); + bool Ins = Classes.insert(std::make_pair(R->getName(), R)).second; + (void)Ins; + assert(Ins && "Class already exists"); } void addDef(Record *R) { - assert(getDef(R->getNameInitAsString()) == 0 && "Def already exists!"); - Defs.insert(std::make_pair(R->getNameInitAsString(), R)); + bool Ins = Defs.insert(std::make_pair(R->getName(), R)).second; + (void)Ins; + assert(Ins && "Record already exists"); } /// removeClass - Remove, but do not delete, the specified record. diff --git a/include/llvm/TableGen/StringMatcher.h b/include/llvm/TableGen/StringMatcher.h new file mode 100644 index 0000000..1dadc76 --- /dev/null +++ b/include/llvm/TableGen/StringMatcher.h @@ -0,0 +1,54 @@ +//===- StringMatcher.h - Generate a matcher for input strings ---*- 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 StringMatcher class. +// +//===----------------------------------------------------------------------===// + +#ifndef STRINGMATCHER_H +#define STRINGMATCHER_H + +#include <vector> +#include <string> +#include <utility> +#include "llvm/ADT/StringRef.h" + +namespace llvm { + class raw_ostream; + +/// StringMatcher - Given a list of strings and code to execute when they match, +/// output a simple switch tree to classify the input string. +/// +/// If a match is found, the code in Vals[i].second is executed; control must +/// not exit this code fragment. If nothing matches, execution falls through. +/// +class StringMatcher { +public: + typedef std::pair<std::string, std::string> StringPair; +private: + StringRef StrVariableName; + const std::vector<StringPair> &Matches; + raw_ostream &OS; + +public: + StringMatcher(StringRef strVariableName, + const std::vector<StringPair> &matches, raw_ostream &os) + : StrVariableName(strVariableName), Matches(matches), OS(os) {} + + void Emit(unsigned Indent = 0) const; + + +private: + bool EmitStringMatcherForChar(const std::vector<const StringPair*> &Matches, + unsigned CharNo, unsigned IndentCount) const; +}; + +} // end llvm namespace. + +#endif diff --git a/include/llvm/TableGen/TableGenBackend.h b/include/llvm/TableGen/TableGenBackend.h index 3ebcd92..bedf7fb 100644 --- a/include/llvm/TableGen/TableGenBackend.h +++ b/include/llvm/TableGen/TableGenBackend.h @@ -1,4 +1,4 @@ -//===- llvm/TableGen/TableGenBackend.h - Backend base class -----*- C++ -*-===// +//===- llvm/TableGen/TableGenBackend.h - Backend utilities ------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,36 +7,22 @@ // //===----------------------------------------------------------------------===// // -// The TableGenBackend class is provided as a common interface for all TableGen -// backends. It provides useful services and an standardized interface. +// Useful utilities for TableGen backends. // //===----------------------------------------------------------------------===// #ifndef LLVM_TABLEGEN_TABLEGENBACKEND_H #define LLVM_TABLEGEN_TABLEGENBACKEND_H -#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/StringRef.h" namespace llvm { -class Record; -class RecordKeeper; +class raw_ostream; -struct TableGenBackend { - virtual void anchor(); - virtual ~TableGenBackend() {} - - // run - All TableGen backends should implement the run method, which should - // be the main entry point. - virtual void run(raw_ostream &OS) = 0; - - -public: // Useful helper routines... - /// EmitSourceFileHeader - Output a LLVM style file header to the specified - /// ostream. - void EmitSourceFileHeader(StringRef Desc, raw_ostream &OS) const; - -}; +/// emitSourceFileHeader - Output a LLVM style file header to the specified +/// raw_ostream. +void emitSourceFileHeader(StringRef Desc, raw_ostream &OS); } // End llvm namespace diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index fa1ec55..24be2b1 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -64,18 +64,6 @@ class Register<string n, list<string> altNames = []> { // register. list<RegAltNameIndex> RegAltNameIndices = []; - // CompositeIndices - Specify subreg indices that don't correspond directly to - // a register in SubRegs and are not inherited. The following formats are - // supported: - // - // (a) Identity - Reg:a == Reg - // (a b) Alias - Reg:a == Reg:b - // (a b,c) Composite - Reg:a == (Reg:b):c - // - // This can be used to disambiguate a sub-sub-register that exists in more - // than one subregister and other weird stuff. - list<dag> CompositeIndices = []; - // DwarfNumbers - Numbers used internally by gcc/gdb to identify the register. // These values can be determined by locating the <target>.h file in the // directory llvmgcc/gcc/config/<target>/ and looking for REGISTER_NAMES. The @@ -96,6 +84,9 @@ class Register<string n, list<string> altNames = []> { // x86 register AX is covered by its sub-registers AL and AH, but EAX is not // covered by its sub-register AX. bit CoveredBySubRegs = 0; + + // HWEncoding - The target specific hardware encoding for this register. + bits<16> HWEncoding = 0; } // RegisterWithSubRegs - This can be used to define instances of Register which @@ -108,13 +99,20 @@ class RegisterWithSubRegs<string n, list<Register> subregs> : Register<n> { let SubRegs = subregs; } +// DAGOperand - An empty base class that unifies RegisterClass's and other forms +// of Operand's that are legal as type qualifiers in DAG patterns. This should +// only ever be used for defining multiclasses that are polymorphic over both +// RegisterClass's and other Operand's. +class DAGOperand { } + // RegisterClass - Now that all of the registers are defined, and aliases // between registers are defined, specify which registers belong to which // register classes. This also defines the default allocation order of // registers by register allocators. // class RegisterClass<string namespace, list<ValueType> regTypes, int alignment, - dag regList, RegAltNameIndex idx = NoRegAltName> { + dag regList, RegAltNameIndex idx = NoRegAltName> + : DAGOperand { string Namespace = namespace; // RegType - Specify the list ValueType of the registers in this register @@ -151,10 +149,6 @@ class RegisterClass<string namespace, list<ValueType> regTypes, int alignment, // a valid alternate name for the given index. RegAltNameIndex altNameIndex = idx; - // SubRegClasses - Specify the register class of subregisters as a list of - // dags: (RegClass SubRegIndex, SubRegindex, ...) - list<dag> SubRegClasses = []; - // isAllocatable - Specify that the register class can be used for virtual // registers and register allocation. Some register classes are only used to // model instruction operand constraints, and should have isAllocatable = 0. @@ -192,7 +186,8 @@ class RegisterClass<string namespace, list<ValueType> regTypes, int alignment, // also in the second set. // // (sequence "R%u", 0, 15) -> [R0, R1, ..., R15]. Generate a sequence of -// numbered registers. +// numbered registers. Takes an optional 4th operand which is a stride to use +// when generating the sequence. // // (shl GPR, 4) - Remove the first N elements. // @@ -245,9 +240,6 @@ class RegisterTuples<list<SubRegIndex> Indices, list<dag> Regs> { // SubRegIndices - N SubRegIndex instances. This provides the names of the // sub-registers in the synthesized super-registers. list<SubRegIndex> SubRegIndices = Indices; - - // Compose sub-register indices like in a normal Register. - list<dag> CompositeIndices = []; } @@ -402,6 +394,13 @@ class Instruction { string AsmMatchConverter = ""; + /// TwoOperandAliasConstraint - Enable TableGen to auto-generate a + /// two-operand matcher inst-alias for a three operand instruction. + /// For example, the arm instruction "add r3, r3, r5" can be written + /// as "add r3, r5". The constraint is of the same form as a tied-operand + /// constraint. For example, "$Rn = $Rd". + string TwoOperandAliasConstraint = ""; + ///@} } @@ -431,6 +430,10 @@ class Predicate<string cond> { /// e.g. "ModeThumb,FeatureThumb2" is translated to /// "(Bits & ModeThumb) != 0 && (Bits & FeatureThumb2) != 0". string AssemblerCondString = ""; + + /// PredicateName - User-level name to use for the predicate. Mainly for use + /// in diagnostics such as missing feature errors in the asm matcher. + string PredicateName = ""; } /// NoHonorSignDependentRounding - This predicate is true if support for @@ -512,6 +515,11 @@ class AsmOperandClass { /// to immediates or registers and are very instruction specific (as flags to /// set in a processor register, coprocessor number, ...). string ParserMethod = ?; + + // The diagnostic type to present when referencing this operand in a + // match failure error message. By default, use a generic "invalid operand" + // diagnostic. The target AsmParser maps these codes to text. + string DiagnosticType = ""; } def ImmAsmOperand : AsmOperandClass { @@ -521,7 +529,7 @@ def ImmAsmOperand : AsmOperandClass { /// Operand Types - These provide the built-in operand types that may be used /// by a target. Targets can optionally provide their own operand types as /// needed, though this should not be needed for RISC targets. -class Operand<ValueType ty> { +class Operand<ValueType ty> : DAGOperand { ValueType Type = ty; string PrintMethod = "printOperand"; string EncoderMethod = ""; @@ -541,7 +549,8 @@ class Operand<ValueType ty> { AsmOperandClass ParserMatchClass = ImmAsmOperand; } -class RegisterOperand<RegisterClass regclass, string pm = "printOperand"> { +class RegisterOperand<RegisterClass regclass, string pm = "printOperand"> + : DAGOperand { // RegClass - The register class of the operand. RegisterClass RegClass = regclass; // PrintMethod - The target method to call to print register operands of @@ -729,7 +738,7 @@ class AsmParser { def DefaultAsmParser : AsmParser; //===----------------------------------------------------------------------===// -// AsmParserVariant - Subtargets can have multiple different assembly parsers +// AsmParserVariant - Subtargets can have multiple different assembly parsers // (e.g. AT&T vs Intel syntax on X86 for example). This class can be // implemented by targets to describe such variants. // @@ -754,9 +763,10 @@ def DefaultAsmParserVariant : AsmParserVariant; /// AssemblerPredicate - This is a Predicate that can be used when the assembler /// matches instructions and aliases. -class AssemblerPredicate<string cond> { +class AssemblerPredicate<string cond, string name = ""> { bit AssemblerMatcherPredicate = 1; string AssemblerCondString = cond; + string PredicateName = name; } /// TokenAlias - This class allows targets to define assembler token @@ -861,7 +871,7 @@ class Target { // AssemblyParsers - The AsmParser instances available for this target. list<AsmParser> AssemblyParsers = [DefaultAsmParser]; - /// AssemblyParserVariants - The AsmParserVariant instances available for + /// AssemblyParserVariants - The AsmParserVariant instances available for /// this target. list<AsmParserVariant> AssemblyParserVariants = [DefaultAsmParserVariant]; @@ -909,6 +919,10 @@ class Processor<string n, ProcessorItineraries pi, list<SubtargetFeature> f> { // string Name = n; + // SchedModel - The machine model for scheduling and instruction cost. + // + SchedMachineModel SchedModel = NoSchedModel; + // ProcItin - The scheduling information for the target processor. // ProcessorItineraries ProcItin = pi; @@ -917,6 +931,14 @@ class Processor<string n, ProcessorItineraries pi, list<SubtargetFeature> f> { list<SubtargetFeature> Features = f; } +// ProcessorModel allows subtargets to specify the more general +// SchedMachineModel instead if a ProcessorItinerary. Subtargets will +// gradually move to this newer form. +class ProcessorModel<string n, SchedMachineModel m, list<SubtargetFeature> f> + : Processor<n, NoItineraries, f> { + let SchedModel = m; +} + //===----------------------------------------------------------------------===// // Pull in the common support for calling conventions. // diff --git a/include/llvm/Target/TargetCallingConv.h b/include/llvm/Target/TargetCallingConv.h index a6251e7..f8cebef 100644 --- a/include/llvm/Target/TargetCallingConv.h +++ b/include/llvm/Target/TargetCallingConv.h @@ -36,16 +36,16 @@ namespace ISD { static const uint64_t ByValOffs = 4; static const uint64_t Nest = 1ULL<<5; ///< Nested fn static chain static const uint64_t NestOffs = 5; - static const uint64_t ByValAlign = 0xFULL << 6; //< Struct alignment + static const uint64_t ByValAlign = 0xFULL << 6; ///< Struct alignment static const uint64_t ByValAlignOffs = 6; static const uint64_t Split = 1ULL << 10; static const uint64_t SplitOffs = 10; static const uint64_t OrigAlign = 0x1FULL<<27; static const uint64_t OrigAlignOffs = 27; - static const uint64_t ByValSize = 0xffffffffULL << 32; //< Struct size + static const uint64_t ByValSize = 0xffffffffULL << 32; ///< Struct size static const uint64_t ByValSizeOffs = 32; - static const uint64_t One = 1ULL; //< 1 of this type, for shifts + static const uint64_t One = 1ULL; ///< 1 of this type, for shifts uint64_t Flags; public: diff --git a/include/llvm/Target/TargetData.h b/include/llvm/Target/TargetData.h index d116f39..4f94ab7 100644 --- a/include/llvm/Target/TargetData.h +++ b/include/llvm/Target/TargetData.h @@ -53,10 +53,10 @@ enum AlignTypeEnum { /// @note The unusual order of elements in the structure attempts to reduce /// padding and make the structure slightly more cache friendly. struct TargetAlignElem { - AlignTypeEnum AlignType : 8; //< Alignment type (AlignTypeEnum) - unsigned ABIAlign; //< ABI alignment for this type/bitw - unsigned PrefAlign; //< Pref. alignment for this type/bitw - uint32_t TypeBitWidth; //< Type bit width + AlignTypeEnum AlignType : 8; ///< Alignment type (AlignTypeEnum) + unsigned ABIAlign; ///< ABI alignment for this type/bitw + unsigned PrefAlign; ///< Pref. alignment for this type/bitw + uint32_t TypeBitWidth; ///< Type bit width /// Initializer static TargetAlignElem get(AlignTypeEnum align_type, unsigned abi_align, diff --git a/include/llvm/Target/TargetELFWriterInfo.h b/include/llvm/Target/TargetELFWriterInfo.h index 114295e..5e48629 100644 --- a/include/llvm/Target/TargetELFWriterInfo.h +++ b/include/llvm/Target/TargetELFWriterInfo.h @@ -43,7 +43,8 @@ namespace llvm { EM_ARM = 40, // ARM EM_ALPHA = 41, // DEC Alpha EM_SPARCV9 = 43, // SPARC V9 - EM_X86_64 = 62 // AMD64 + EM_X86_64 = 62, // AMD64 + EM_HEXAGON = 164 // Qualcomm Hexagon }; // ELF File classes diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index d1e380c..a18b030 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -14,6 +14,7 @@ #ifndef LLVM_TARGET_TARGETINSTRINFO_H #define LLVM_TARGET_TARGETINSTRINFO_H +#include "llvm/ADT/SmallSet.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/CodeGen/DFAPacketizer.h" #include "llvm/CodeGen/MachineFunction.h" @@ -27,6 +28,7 @@ class MachineMemOperand; class MachineRegisterInfo; class MDNode; class MCInst; +class MCSchedModel; class SDNode; class ScheduleHazardRecognizer; class SelectionDAG; @@ -57,7 +59,8 @@ public: /// class constraint for OpNum, or NULL. const TargetRegisterClass *getRegClass(const MCInstrDesc &TID, unsigned OpNum, - const TargetRegisterInfo *TRI) const; + const TargetRegisterInfo *TRI, + const MachineFunction &MF) const; /// isTriviallyReMaterializable - Return true if the instruction is trivially /// rematerializable, meaning it has no side effects and requires no operands @@ -185,14 +188,6 @@ public: const MachineInstr *Orig, const TargetRegisterInfo &TRI) const = 0; - /// scheduleTwoAddrSource - Schedule the copy / re-mat of the source of the - /// two-addrss instruction inserted by two-address pass. - virtual void scheduleTwoAddrSource(MachineInstr *SrcMI, - MachineInstr *UseMI, - const TargetRegisterInfo &TRI) const { - // Do nothing. - } - /// duplicate - Create a duplicate of the Orig instruction in MF. This is like /// MachineFunction::CloneMachineInstr(), but the target may update operands /// that are required to be unique. @@ -319,7 +314,7 @@ public: /// being executed is given by Probability, and Confidence is a measure /// of our confidence that it will be properly predicted. virtual - bool isProfitableToIfCvt(MachineBasicBlock &MBB, unsigned NumCyles, + bool isProfitableToIfCvt(MachineBasicBlock &MBB, unsigned NumCycles, unsigned ExtraPredCycles, const BranchProbability &Probability) const { return false; @@ -347,7 +342,7 @@ public: /// Probability, and Confidence is a measure of our confidence that it /// will be properly predicted. virtual bool - isProfitableToDupForIfCvt(MachineBasicBlock &MBB, unsigned NumCyles, + isProfitableToDupForIfCvt(MachineBasicBlock &MBB, unsigned NumCycles, const BranchProbability &Probability) const { return false; } @@ -368,6 +363,56 @@ public: return false; } + /// canInsertSelect - Return true if it is possible to insert a select + /// instruction that chooses between TrueReg and FalseReg based on the + /// condition code in Cond. + /// + /// When successful, also return the latency in cycles from TrueReg, + /// FalseReg, and Cond to the destination register. The Cond latency should + /// compensate for a conditional branch being removed. For example, if a + /// conditional branch has a 3 cycle latency from the condition code read, + /// and a cmov instruction has a 2 cycle latency from the condition code + /// read, CondCycles should be returned as -1. + /// + /// @param MBB Block where select instruction would be inserted. + /// @param Cond Condition returned by AnalyzeBranch. + /// @param TrueReg Virtual register to select when Cond is true. + /// @param FalseReg Virtual register to select when Cond is false. + /// @param CondCycles Latency from Cond+Branch to select output. + /// @param TrueCycles Latency from TrueReg to select output. + /// @param FalseCycles Latency from FalseReg to select output. + virtual bool canInsertSelect(const MachineBasicBlock &MBB, + const SmallVectorImpl<MachineOperand> &Cond, + unsigned TrueReg, unsigned FalseReg, + int &CondCycles, + int &TrueCycles, int &FalseCycles) const { + return false; + } + + /// insertSelect - Insert a select instruction into MBB before I that will + /// copy TrueReg to DstReg when Cond is true, and FalseReg to DstReg when + /// Cond is false. + /// + /// This function can only be called after canInsertSelect() returned true. + /// The condition in Cond comes from AnalyzeBranch, and it can be assumed + /// that the same flags or registers required by Cond are available at the + /// insertion point. + /// + /// @param MBB Block where select instruction should be inserted. + /// @param I Insertion point. + /// @param DL Source location for debugging. + /// @param DstReg Virtual register to be defined by select instruction. + /// @param Cond Condition as computed by AnalyzeBranch. + /// @param TrueReg Virtual register to copy when Cond is true. + /// @param FalseReg Virtual register to copy when Cons is false. + virtual void insertSelect(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, DebugLoc DL, + unsigned DstReg, + const SmallVectorImpl<MachineOperand> &Cond, + unsigned TrueReg, unsigned FalseReg) const { + llvm_unreachable("Target didn't implement TargetInstrInfo::insertSelect!"); + } + /// copyPhysReg - Emit instructions to copy a pair of physical registers. virtual void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, DebugLoc DL, @@ -608,6 +653,13 @@ public: CreateTargetHazardRecognizer(const TargetMachine *TM, const ScheduleDAG *DAG) const = 0; + /// CreateTargetMIHazardRecognizer - Allocate and return a hazard recognizer + /// to use for this target when scheduling the machine instructions before + /// register allocation. + virtual ScheduleHazardRecognizer* + CreateTargetMIHazardRecognizer(const InstrItineraryData*, + const ScheduleDAG *DAG) const = 0; + /// CreateTargetPostRAHazardRecognizer - Allocate and return a hazard /// recognizer to use for this target when scheduling the machine instructions /// after register allocation. @@ -615,23 +667,40 @@ public: CreateTargetPostRAHazardRecognizer(const InstrItineraryData*, const ScheduleDAG *DAG) const = 0; - /// AnalyzeCompare - For a comparison instruction, return the source register - /// in SrcReg and the value it compares against in CmpValue. Return true if - /// the comparison instruction can be analyzed. - virtual bool AnalyzeCompare(const MachineInstr *MI, - unsigned &SrcReg, int &Mask, int &Value) const { + /// analyzeCompare - For a comparison instruction, return the source registers + /// in SrcReg and SrcReg2 if having two register operands, and the value it + /// compares against in CmpValue. Return true if the comparison instruction + /// can be analyzed. + virtual bool analyzeCompare(const MachineInstr *MI, + unsigned &SrcReg, unsigned &SrcReg2, + int &Mask, int &Value) const { return false; } - /// OptimizeCompareInstr - See if the comparison instruction can be converted + /// optimizeCompareInstr - See if the comparison instruction can be converted /// into something more efficient. E.g., on ARM most instructions can set the /// flags register, obviating the need for a separate CMP. - virtual bool OptimizeCompareInstr(MachineInstr *CmpInstr, - unsigned SrcReg, int Mask, int Value, + virtual bool optimizeCompareInstr(MachineInstr *CmpInstr, + unsigned SrcReg, unsigned SrcReg2, + int Mask, int Value, const MachineRegisterInfo *MRI) const { return false; } + /// optimizeLoadInstr - Try to remove the load by folding it to a register + /// operand at the use. We fold the load instructions if and only if the + /// def and use are in the same BB. We only look at one load and see + /// whether it can be folded into MI. FoldAsLoadDefReg is the virtual register + /// defined by the load we are trying to fold. DefMI returns the machine + /// instruction that defines FoldAsLoadDefReg, and the function returns + /// the machine instruction generated due to folding. + virtual MachineInstr* optimizeLoadInstr(MachineInstr *MI, + const MachineRegisterInfo *MRI, + unsigned &FoldAsLoadDefReg, + MachineInstr *&DefMI) const { + return 0; + } + /// FoldImmediate - 'Reg' is known to be defined by a move immediate /// instruction, try to fold the immediate into the use instruction. virtual bool FoldImmediate(MachineInstr *UseMI, MachineInstr *DefMI, @@ -640,9 +709,11 @@ public: } /// getNumMicroOps - Return the number of u-operations the given machine - /// instruction will be decoded to on the target cpu. + /// instruction will be decoded to on the target cpu. The itinerary's + /// IssueWidth is the number of microops that can be dispatched each + /// cycle. An instruction with zero microops takes no dispatch resources. virtual unsigned getNumMicroOps(const InstrItineraryData *ItinData, - const MachineInstr *MI) const; + const MachineInstr *MI) const = 0; /// isZeroCost - Return true for pseudo instructions that don't consume any /// machine resources in their current form. These are common cases that the @@ -652,18 +723,45 @@ public: return Opcode <= TargetOpcode::COPY; } + virtual int getOperandLatency(const InstrItineraryData *ItinData, + SDNode *DefNode, unsigned DefIdx, + SDNode *UseNode, unsigned UseIdx) const = 0; + /// getOperandLatency - Compute and return the use operand latency of a given /// pair of def and use. /// In most cases, the static scheduling itinerary was enough to determine the /// operand latency. But it may not be possible for instructions with variable /// number of defs / uses. + /// + /// This is a raw interface to the itinerary that may be directly overriden by + /// a target. Use computeOperandLatency to get the best estimate of latency. virtual int getOperandLatency(const InstrItineraryData *ItinData, - const MachineInstr *DefMI, unsigned DefIdx, - const MachineInstr *UseMI, unsigned UseIdx) const; - - virtual int getOperandLatency(const InstrItineraryData *ItinData, - SDNode *DefNode, unsigned DefIdx, - SDNode *UseNode, unsigned UseIdx) const = 0; + const MachineInstr *DefMI, unsigned DefIdx, + const MachineInstr *UseMI, + unsigned UseIdx) const = 0; + + /// computeOperandLatency - Compute and return the latency of the given data + /// dependent def and use when the operand indices are already known. + /// + /// FindMin may be set to get the minimum vs. expected latency. + unsigned computeOperandLatency(const InstrItineraryData *ItinData, + const MachineInstr *DefMI, unsigned DefIdx, + const MachineInstr *UseMI, unsigned UseIdx, + bool FindMin = false) const; + + /// computeOperandLatency - Compute and return the latency of the given data + /// dependent def and use. DefMI must be a valid def. UseMI may be NULL for + /// an unknown use. If the subtarget allows, this may or may not need to call + /// getOperandLatency(). + /// + /// FindMin may be set to get the minimum vs. expected latency. Minimum + /// latency is used for scheduling groups, while expected latency is for + /// instruction cost and critical path. + unsigned computeOperandLatency(const InstrItineraryData *ItinData, + const TargetRegisterInfo *TRI, + const MachineInstr *DefMI, + const MachineInstr *UseMI, + unsigned Reg, bool FindMin) const; /// getOutputLatency - Compute and return the output dependency latency of a /// a given pair of defs which both target the same register. This is usually @@ -677,13 +775,17 @@ public: /// getInstrLatency - Compute the instruction latency of a given instruction. /// If the instruction has higher cost when predicated, it's returned via /// PredCost. - virtual int getInstrLatency(const InstrItineraryData *ItinData, - const MachineInstr *MI, - unsigned *PredCost = 0) const; + virtual unsigned getInstrLatency(const InstrItineraryData *ItinData, + const MachineInstr *MI, + unsigned *PredCost = 0) const = 0; virtual int getInstrLatency(const InstrItineraryData *ItinData, SDNode *Node) const = 0; + /// Return the default expected latency for a def based on it's opcode. + unsigned defaultDefLatency(const MCSchedModel *SchedModel, + const MachineInstr *DefMI) const; + /// isHighLatencyDef - Return true if this opcode has high latency to its /// result. virtual bool isHighLatencyDef(int opc) const { return false; } @@ -705,7 +807,7 @@ public: /// if the target considered it 'low'. virtual bool hasLowDefLatency(const InstrItineraryData *ItinData, - const MachineInstr *DefMI, unsigned DefIdx) const; + const MachineInstr *DefMI, unsigned DefIdx) const = 0; /// verifyInstruction - Perform target specific instruction verification. virtual @@ -862,20 +964,40 @@ public: virtual bool isSchedulingBoundary(const MachineInstr *MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const; - using TargetInstrInfo::getOperandLatency; + virtual int getOperandLatency(const InstrItineraryData *ItinData, SDNode *DefNode, unsigned DefIdx, SDNode *UseNode, unsigned UseIdx) const; - using TargetInstrInfo::getInstrLatency; + virtual int getInstrLatency(const InstrItineraryData *ItinData, SDNode *Node) const; + virtual unsigned getNumMicroOps(const InstrItineraryData *ItinData, + const MachineInstr *MI) const; + + virtual unsigned getInstrLatency(const InstrItineraryData *ItinData, + const MachineInstr *MI, + unsigned *PredCost = 0) const; + + virtual + bool hasLowDefLatency(const InstrItineraryData *ItinData, + const MachineInstr *DefMI, unsigned DefIdx) const; + + virtual int getOperandLatency(const InstrItineraryData *ItinData, + const MachineInstr *DefMI, unsigned DefIdx, + const MachineInstr *UseMI, + unsigned UseIdx) const; + bool usePreRAHazardRecognizer() const; virtual ScheduleHazardRecognizer * CreateTargetHazardRecognizer(const TargetMachine*, const ScheduleDAG*) const; virtual ScheduleHazardRecognizer * + CreateTargetMIHazardRecognizer(const InstrItineraryData*, + const ScheduleDAG*) const; + + virtual ScheduleHazardRecognizer * CreateTargetPostRAHazardRecognizer(const InstrItineraryData*, const ScheduleDAG*) const; }; diff --git a/include/llvm/Target/TargetItinerary.td b/include/llvm/Target/TargetItinerary.td new file mode 100644 index 0000000..cc74006 --- /dev/null +++ b/include/llvm/Target/TargetItinerary.td @@ -0,0 +1,136 @@ +//===- TargetItinerary.td - Target Itinierary Description --*- 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 the target-independent scheduling interfaces +// which should be implemented by each target that uses instruction +// itineraries for scheduling. Itineraries are details reservation +// tables for each instruction class. They are most appropriate for +// in-order machine with complicated scheduling or bundling constraints. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Processor functional unit - These values represent the function units +// available across all chip sets for the target. Eg., IntUnit, FPUnit, ... +// These may be independent values for each chip set or may be shared across +// all chip sets of the target. Each functional unit is treated as a resource +// during scheduling and has an affect instruction order based on availability +// during a time interval. +// +class FuncUnit; + +//===----------------------------------------------------------------------===// +// Pipeline bypass / forwarding - These values specifies the symbolic names of +// pipeline bypasses which can be used to forward results of instructions +// that are forwarded to uses. +class Bypass; +def NoBypass : Bypass; + +class ReservationKind<bits<1> val> { + int Value = val; +} + +def Required : ReservationKind<0>; +def Reserved : ReservationKind<1>; + +//===----------------------------------------------------------------------===// +// Instruction stage - These values represent a non-pipelined step in +// the execution of an instruction. Cycles represents the number of +// discrete time slots needed to complete the stage. Units represent +// the choice of functional units that can be used to complete the +// stage. Eg. IntUnit1, IntUnit2. NextCycles indicates how many +// cycles should elapse from the start of this stage to the start of +// the next stage in the itinerary. For example: +// +// A stage is specified in one of two ways: +// +// InstrStage<1, [FU_x, FU_y]> - TimeInc defaults to Cycles +// InstrStage<1, [FU_x, FU_y], 0> - TimeInc explicit +// + +class InstrStage<int cycles, list<FuncUnit> units, + int timeinc = -1, + ReservationKind kind = Required> { + int Cycles = cycles; // length of stage in machine cycles + list<FuncUnit> Units = units; // choice of functional units + int TimeInc = timeinc; // cycles till start of next stage + int Kind = kind.Value; // kind of FU reservation +} + +//===----------------------------------------------------------------------===// +// Instruction itinerary - An itinerary represents a sequential series of steps +// required to complete an instruction. Itineraries are represented as lists of +// instruction stages. +// + +//===----------------------------------------------------------------------===// +// Instruction itinerary classes - These values represent 'named' instruction +// itinerary. Using named itineraries simplifies managing groups of +// instructions across chip sets. An instruction uses the same itinerary class +// across all chip sets. Thus a new chip set can be added without modifying +// instruction information. +// +class InstrItinClass; +def NoItinerary : InstrItinClass; + +//===----------------------------------------------------------------------===// +// Instruction itinerary data - These values provide a runtime map of an +// instruction itinerary class (name) to its itinerary data. +// +// NumMicroOps represents the number of micro-operations that each instruction +// in the class are decoded to. If the number is zero, then it means the +// instruction can decode into variable number of micro-ops and it must be +// determined dynamically. This directly relates to the itineraries +// global IssueWidth property, which constrains the number of microops +// that can issue per cycle. +// +// OperandCycles are optional "cycle counts". They specify the cycle after +// instruction issue the values which correspond to specific operand indices +// are defined or read. Bypasses are optional "pipeline forwarding pathes", if +// a def by an instruction is available on a specific bypass and the use can +// read from the same bypass, then the operand use latency is reduced by one. +// +// InstrItinData<IIC_iLoad_i , [InstrStage<1, [A9_Pipe1]>, +// InstrStage<1, [A9_AGU]>], +// [3, 1], [A9_LdBypass]>, +// InstrItinData<IIC_iMVNr , [InstrStage<1, [A9_Pipe0, A9_Pipe1]>], +// [1, 1], [NoBypass, A9_LdBypass]>, +// +// In this example, the instruction of IIC_iLoadi reads its input on cycle 1 +// (after issue) and the result of the load is available on cycle 3. The result +// is available via forwarding path A9_LdBypass. If it's used by the first +// source operand of instructions of IIC_iMVNr class, then the operand latency +// is reduced by 1. +class InstrItinData<InstrItinClass Class, list<InstrStage> stages, + list<int> operandcycles = [], + list<Bypass> bypasses = [], int uops = 1> { + InstrItinClass TheClass = Class; + int NumMicroOps = uops; + list<InstrStage> Stages = stages; + list<int> OperandCycles = operandcycles; + list<Bypass> Bypasses = bypasses; +} + +//===----------------------------------------------------------------------===// +// Processor itineraries - These values represent the set of all itinerary +// classes for a given chip set. +// +// Set property values to -1 to use the default. +// See InstrItineraryProps for comments and defaults. +class ProcessorItineraries<list<FuncUnit> fu, list<Bypass> bp, + list<InstrItinData> iid> { + list<FuncUnit> FU = fu; + list<Bypass> BP = bp; + list<InstrItinData> IID = iid; +} + +// NoItineraries - A marker that can be used by processors without schedule +// info. Subtargets using NoItineraries can bypass the scheduler's +// expensive HazardRecognizer because no reservation table is needed. +def NoItineraries : ProcessorItineraries<[], [], []>; diff --git a/include/llvm/Target/TargetLibraryInfo.h b/include/llvm/Target/TargetLibraryInfo.h index c8cacf2..ea2874f 100644 --- a/include/llvm/Target/TargetLibraryInfo.h +++ b/include/llvm/Target/TargetLibraryInfo.h @@ -18,36 +18,47 @@ namespace llvm { namespace LibFunc { enum Func { + /// int __cxa_atexit(void (*f)(void *), void *p, void *d); + cxa_atexit, + /// void __cxa_guard_abort(guard_t *guard); + /// guard_t is int64_t in Itanium ABI or int32_t on ARM eabi. + cxa_guard_abort, + /// int __cxa_guard_acquire(guard_t *guard); + cxa_guard_acquire, + /// void __cxa_guard_release(guard_t *guard); + cxa_guard_release, + /// void *__memcpy_chk(void *s1, const void *s2, size_t n, size_t s1size); + memcpy_chk, /// double acos(double x); acos, - /// long double acosl(long double x); - acosl, /// float acosf(float x); acosf, + /// long double acosl(long double x); + acosl, /// double asin(double x); asin, - /// long double asinl(long double x); - asinl, /// float asinf(float x); asinf, + /// long double asinl(long double x); + asinl, /// double atan(double x); atan, - /// long double atanl(long double x); - atanl, - /// float atanf(float x); - atanf, /// double atan2(double y, double x); atan2, - /// long double atan2l(long double y, long double x); - atan2l, /// float atan2f(float y, float x); atan2f, + /// long double atan2l(long double y, long double x); + atan2l, + /// float atanf(float x); + atanf, + /// long double atanl(long double x); + atanl, /// double ceil(double x); ceil, - /// long double ceill(long double x); - ceill, /// float ceilf(float x); ceilf, + /// long double ceill(long double x); + ceill, /// double copysign(double x, double y); copysign, /// float copysignf(float x, float y); @@ -56,54 +67,56 @@ namespace llvm { copysignl, /// double cos(double x); cos, - /// long double cosl(long double x); - cosl, /// float cosf(float x); cosf, /// double cosh(double x); cosh, - /// long double coshl(long double x); - coshl, /// float coshf(float x); coshf, + /// long double coshl(long double x); + coshl, + /// long double cosl(long double x); + cosl, /// double exp(double x); exp, - /// long double expl(long double x); - expl, - /// float expf(float x); - expf, /// double exp2(double x); exp2, - /// long double exp2l(long double x); - exp2l, /// float exp2f(float x); exp2f, + /// long double exp2l(long double x); + exp2l, + /// float expf(float x); + expf, + /// long double expl(long double x); + expl, /// double expm1(double x); expm1, - /// long double expm1l(long double x); - expm1l, /// float expm1f(float x); expm1f, + /// long double expm1l(long double x); + expm1l, /// double fabs(double x); fabs, - /// long double fabsl(long double x); - fabsl, /// float fabsf(float x); fabsf, + /// long double fabsl(long double x); + fabsl, + /// int fiprintf(FILE *stream, const char *format, ...); + fiprintf, /// double floor(double x); floor, - /// long double floorl(long double x); - floorl, /// float floorf(float x); floorf, - /// int fiprintf(FILE *stream, const char *format, ...); - fiprintf, + /// long double floorl(long double x); + floorl, /// double fmod(double x, double y); fmod, - /// long double fmodl(long double x, long double y); - fmodl, /// float fmodf(float x, float y); fmodf, + /// long double fmodl(long double x, long double y); + fmodl, + /// int fputc(int c, FILE *stream); + fputc, /// int fputs(const char *s, FILE *stream); fputs, /// size_t fwrite(const void *ptr, size_t size, size_t nitems, @@ -113,28 +126,32 @@ namespace llvm { iprintf, /// double log(double x); log, - /// long double logl(long double x); - logl, - /// float logf(float x); - logf, - /// double log2(double x); - log2, - /// double long double log2l(long double x); - log2l, - /// float log2f(float x); - log2f, /// double log10(double x); log10, - /// long double log10l(long double x); - log10l, /// float log10f(float x); log10f, + /// long double log10l(long double x); + log10l, /// double log1p(double x); log1p, - /// long double log1pl(long double x); - log1pl, /// float log1pf(float x); log1pf, + /// long double log1pl(long double x); + log1pl, + /// double log2(double x); + log2, + /// float log2f(float x); + log2f, + /// double long double log2l(long double x); + log2l, + /// float logf(float x); + logf, + /// long double logl(long double x); + logl, + /// void *memchr(const void *s, int c, size_t n); + memchr, + /// int memcmp(const void *s1, const void *s2, size_t n); + memcmp, /// void *memcpy(void *s1, const void *s2, size_t n); memcpy, /// void *memmove(void *s1, const void *s2, size_t n); @@ -155,6 +172,10 @@ namespace llvm { powf, /// long double powl(long double x, long double y); powl, + /// int putchar(int c); + putchar, + /// int puts(const char *s); + puts, /// double rint(double x); rint, /// float rintf(float x); @@ -169,51 +190,58 @@ namespace llvm { roundl, /// double sin(double x); sin, - /// long double sinl(long double x); - sinl, /// float sinf(float x); sinf, /// double sinh(double x); sinh, - /// long double sinhl(long double x); - sinhl, /// float sinhf(float x); sinhf, + /// long double sinhl(long double x); + sinhl, + /// long double sinl(long double x); + sinl, /// int siprintf(char *str, const char *format, ...); siprintf, /// double sqrt(double x); sqrt, - /// long double sqrtl(long double x); - sqrtl, /// float sqrtf(float x); sqrtf, + /// long double sqrtl(long double x); + sqrtl, + /// char *strcat(char *s1, const char *s2); + strcat, + /// char *strchr(const char *s, int c); + strchr, + /// char *strcpy(char *s1, const char *s2); + strcpy, + /// size_t strlen(const char *s); + strlen, + /// char *strncat(char *s1, const char *s2, size_t n); + strncat, + /// int strncmp(const char *s1, const char *s2, size_t n); + strncmp, + /// char *strncpy(char *s1, const char *s2, size_t n); + strncpy, + /// size_t strnlen(const char *s, size_t maxlen); + strnlen, /// double tan(double x); tan, - /// long double tanl(long double x); - tanl, /// float tanf(float x); tanf, /// double tanh(double x); tanh, - /// long double tanhl(long double x); - tanhl, /// float tanhf(float x); tanhf, + /// long double tanhl(long double x); + tanhl, + /// long double tanl(long double x); + tanl, /// double trunc(double x); trunc, /// float truncf(float x); truncf, /// long double truncl(long double x); truncl, - /// int __cxa_atexit(void (*f)(void *), void *p, void *d); - cxa_atexit, - /// void __cxa_guard_abort(guard_t *guard); - /// guard_t is int64_t in Itanium ABI or int32_t on ARM eabi. - cxa_guard_abort, - /// int __cxa_guard_acquire(guard_t *guard); - cxa_guard_acquire, - /// void __cxa_guard_release(guard_t *guard); - cxa_guard_release, NumLibFuncs }; @@ -247,12 +275,41 @@ public: TargetLibraryInfo(const Triple &T); explicit TargetLibraryInfo(const TargetLibraryInfo &TLI); + /// getLibFunc - Search for a particular function name. If it is one of the + /// known library functions, return true and set F to the corresponding value. + bool getLibFunc(StringRef funcName, LibFunc::Func &F) const; + /// has - This function is used by optimizations that want to match on or form /// a given library function. bool has(LibFunc::Func F) const { return getState(F) != Unavailable; } + /// hasOptimizedCodeGen - Return true if the function is both available as + /// a builtin and a candidate for optimized code generation. + bool hasOptimizedCodeGen(LibFunc::Func F) const { + if (getState(F) == Unavailable) + return false; + switch (F) { + default: break; + case LibFunc::copysign: case LibFunc::copysignf: case LibFunc::copysignl: + case LibFunc::fabs: case LibFunc::fabsf: case LibFunc::fabsl: + case LibFunc::sin: case LibFunc::sinf: case LibFunc::sinl: + case LibFunc::cos: case LibFunc::cosf: case LibFunc::cosl: + case LibFunc::sqrt: case LibFunc::sqrtf: case LibFunc::sqrtl: + case LibFunc::floor: case LibFunc::floorf: case LibFunc::floorl: + case LibFunc::nearbyint: case LibFunc::nearbyintf: case LibFunc::nearbyintl: + case LibFunc::ceil: case LibFunc::ceilf: case LibFunc::ceill: + case LibFunc::rint: case LibFunc::rintf: case LibFunc::rintl: + case LibFunc::trunc: case LibFunc::truncf: case LibFunc::truncl: + case LibFunc::log2: case LibFunc::log2f: case LibFunc::log2l: + case LibFunc::exp2: case LibFunc::exp2f: case LibFunc::exp2l: + case LibFunc::memcmp: + return true; + } + return false; + } + StringRef getName(LibFunc::Func F) const { AvailabilityState State = getState(F); if (State == Unavailable) diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index 720c9df..acf0419 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -25,6 +25,7 @@ #include "llvm/CallingConv.h" #include "llvm/InlineAsm.h" #include "llvm/Attributes.h" +#include "llvm/Support/CallSite.h" #include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/CodeGen/RuntimeLibcalls.h" #include "llvm/Support/DebugLoc.h" @@ -50,6 +51,7 @@ namespace llvm { template<typename T> class SmallVectorImpl; class TargetData; class TargetRegisterClass; + class TargetLibraryInfo; class TargetLoweringObjectFile; class Value; @@ -150,6 +152,12 @@ public: /// that should be avoided. bool isJumpExpensive() const { return JumpIsExpensive; } + /// isPredictableSelectExpensive - Return true if selects are only cheaper + /// than branches if the branch is unlikely to be predicted right. + bool isPredictableSelectExpensive() const { + return predictableSelectIsExpensive; + } + /// getSetCCResultType - Return the ValueType of the result of SETCC /// operations. Also used to obtain the target's preferred type for /// the condition operand of SELECT and BRCOND nodes. In the case of @@ -358,7 +366,9 @@ public: /// for it. LegalizeAction getOperationAction(unsigned Op, EVT VT) const { if (VT.isExtended()) return Expand; - assert(Op < array_lengthof(OpActions[0]) && "Table isn't big enough!"); + // If a target-specific SDNode requires legalization, require the target + // to provide custom legalization for it. + if (Op > array_lengthof(OpActions[0])) return Custom; unsigned I = (unsigned) VT.getSimpleVT().SimpleTy; return (LegalizeAction)OpActions[I][Op]; } @@ -670,6 +680,12 @@ public: return UseUnderscoreLongJmp; } + /// supportJumpTables - return whether the target can generate code for + /// jump tables. + bool supportJumpTables() const { + return SupportJumpTables; + } + /// getStackPointerRegisterToSaveRestore - If a physical register, this /// specifies the register that llvm.savestack/llvm.restorestack should save /// and restore. @@ -984,6 +1000,12 @@ protected: UseUnderscoreLongJmp = Val; } + /// setSupportJumpTables - Indicate whether the target can generate code for + /// jump tables. + void setSupportJumpTables(bool Val) { + SupportJumpTables = Val; + } + /// setStackPointerRegisterToSaveRestore - If set to a physical register, this /// specifies the register that llvm.savestack/llvm.restorestack should save /// and restore. @@ -1169,7 +1191,7 @@ protected: ShouldFoldAtomicFences = fold; } - /// setInsertFencesForAtomic - Set if the the DAG builder should + /// setInsertFencesForAtomic - Set if the DAG builder should /// automatically insert fences and reduce the order of atomic memory /// operations to Monotonic. void setInsertFencesForAtomic(bool fence) { @@ -1197,11 +1219,6 @@ public: llvm_unreachable("Not Implemented"); } - /// LowerCallTo - This function lowers an abstract call to a function into an - /// actual call. This returns a pair of operands. The first element is the - /// return value for the function (if RetTy is not VoidTy). The second - /// element is the outgoing token chain. It calls LowerCall to do the actual - /// lowering. struct ArgListEntry { SDValue Node; Type* Ty; @@ -1217,13 +1234,72 @@ public: isSRet(false), isNest(false), isByVal(false), Alignment(0) { } }; typedef std::vector<ArgListEntry> ArgListTy; - std::pair<SDValue, SDValue> - LowerCallTo(SDValue Chain, Type *RetTy, bool RetSExt, bool RetZExt, - bool isVarArg, bool isInreg, unsigned NumFixedArgs, - CallingConv::ID CallConv, bool isTailCall, - bool doesNotRet, bool isReturnValueUsed, - SDValue Callee, ArgListTy &Args, - SelectionDAG &DAG, DebugLoc dl) const; + + /// CallLoweringInfo - This structure contains all information that is + /// necessary for lowering calls. It is passed to TLI::LowerCallTo when the + /// SelectionDAG builder needs to lower a call, and targets will see this + /// struct in their LowerCall implementation. + struct CallLoweringInfo { + SDValue Chain; + Type *RetTy; + bool RetSExt : 1; + bool RetZExt : 1; + bool IsVarArg : 1; + bool IsInReg : 1; + bool DoesNotReturn : 1; + bool IsReturnValueUsed : 1; + + // IsTailCall should be modified by implementations of + // TargetLowering::LowerCall that perform tail call conversions. + bool IsTailCall; + + unsigned NumFixedArgs; + CallingConv::ID CallConv; + SDValue Callee; + ArgListTy &Args; + SelectionDAG &DAG; + DebugLoc DL; + ImmutableCallSite *CS; + SmallVector<ISD::OutputArg, 32> Outs; + SmallVector<SDValue, 32> OutVals; + SmallVector<ISD::InputArg, 32> Ins; + + + /// CallLoweringInfo - Constructs a call lowering context based on the + /// ImmutableCallSite \p cs. + CallLoweringInfo(SDValue chain, Type *retTy, + FunctionType *FTy, bool isTailCall, SDValue callee, + ArgListTy &args, SelectionDAG &dag, DebugLoc dl, + ImmutableCallSite &cs) + : Chain(chain), RetTy(retTy), RetSExt(cs.paramHasAttr(0, Attribute::SExt)), + RetZExt(cs.paramHasAttr(0, Attribute::ZExt)), IsVarArg(FTy->isVarArg()), + IsInReg(cs.paramHasAttr(0, Attribute::InReg)), + DoesNotReturn(cs.doesNotReturn()), + IsReturnValueUsed(!cs.getInstruction()->use_empty()), + IsTailCall(isTailCall), NumFixedArgs(FTy->getNumParams()), + CallConv(cs.getCallingConv()), Callee(callee), Args(args), DAG(dag), + DL(dl), CS(&cs) {} + + /// CallLoweringInfo - Constructs a call lowering context based on the + /// provided call information. + CallLoweringInfo(SDValue chain, Type *retTy, bool retSExt, bool retZExt, + bool isVarArg, bool isInReg, unsigned numFixedArgs, + CallingConv::ID callConv, bool isTailCall, + bool doesNotReturn, bool isReturnValueUsed, SDValue callee, + ArgListTy &args, SelectionDAG &dag, DebugLoc dl) + : Chain(chain), RetTy(retTy), RetSExt(retSExt), RetZExt(retZExt), + IsVarArg(isVarArg), IsInReg(isInReg), DoesNotReturn(doesNotReturn), + IsReturnValueUsed(isReturnValueUsed), IsTailCall(isTailCall), + NumFixedArgs(numFixedArgs), CallConv(callConv), Callee(callee), + Args(args), DAG(dag), DL(dl), CS(NULL) {} + }; + + /// LowerCallTo - This function lowers an abstract call to a function into an + /// actual call. This returns a pair of operands. The first element is the + /// return value for the function (if RetTy is not VoidTy). The second + /// element is the outgoing token chain. It calls LowerCall to do the actual + /// lowering. + std::pair<SDValue, SDValue> LowerCallTo(CallLoweringInfo &CLI) const; /// LowerCall - This hook must be implemented to lower calls into the /// the specified DAG. The outgoing arguments to the call are described @@ -1232,13 +1308,7 @@ public: /// InVals array with legal-type return values from the call, and return /// the resulting token chain value. virtual SDValue - LowerCall(SDValue /*Chain*/, SDValue /*Callee*/, - CallingConv::ID /*CallConv*/, bool /*isVarArg*/, - bool /*doesNotRet*/, bool &/*isTailCall*/, - const SmallVectorImpl<ISD::OutputArg> &/*Outs*/, - const SmallVectorImpl<SDValue> &/*OutVals*/, - const SmallVectorImpl<ISD::InputArg> &/*Ins*/, - DebugLoc /*dl*/, SelectionDAG &/*DAG*/, + LowerCall(CallLoweringInfo &/*CLI*/, SmallVectorImpl<SDValue> &/*InVals*/) const { llvm_unreachable("Not Implemented"); } @@ -1251,7 +1321,7 @@ public: /// registers. If false is returned, an sret-demotion is performed. /// virtual bool CanLowerReturn(CallingConv::ID /*CallConv*/, - MachineFunction &/*MF*/, bool /*isVarArg*/, + MachineFunction &/*MF*/, bool /*isVarArg*/, const SmallVectorImpl<ISD::OutputArg> &/*Outs*/, LLVMContext &/*Context*/) const { @@ -1346,7 +1416,8 @@ public: /// createFastISel - This method returns a target specific FastISel object, /// or null if the target does not support "fast" ISel. - virtual FastISel *createFastISel(FunctionLoweringInfo &) const { + virtual FastISel *createFastISel(FunctionLoweringInfo &, + const TargetLibraryInfo *) const { return 0; } @@ -1602,6 +1673,14 @@ public: return false; } + /// isFMAFasterThanMulAndAdd - Return true if an FMA operation is faster than + /// a pair of mul and add instructions. fmuladd intrinsics will be expanded to + /// FMAs when this method returns true (and FMAs are legal), otherwise fmuladd + /// is expanded to mul + add. + virtual bool isFMAFasterThanMulAndAdd(EVT) const { + return false; + } + /// isNarrowingProfitable - Return true if it's profitable to narrow /// operations of type VT1 to VT2. e.g. on x86, it's profitable to narrow /// from i32 to i8 but not from i32 to i16. @@ -1665,13 +1744,6 @@ private: const TargetData *TD; const TargetLoweringObjectFile &TLOF; - /// We are in the process of implementing a new TypeLegalization action - /// which is the promotion of vector elements. This feature is under - /// development. Until this feature is complete, it is only enabled using a - /// flag. We pass this flag using a member because of circular dep issues. - /// This member will be removed with the flag once we complete the transition. - bool mayPromoteElements; - /// PointerTy - The type to use for pointers, usually i32 or i64. /// MVT PointerTy; @@ -1708,6 +1780,10 @@ private: /// llvm.longjmp. Defaults to false. bool UseUnderscoreLongJmp; + /// SupportJumpTables - Whether the target can generate code for jumptables. + /// If it's not true, then each jumptable must be lowered into if-then-else's. + bool SupportJumpTables; + /// BooleanContents - Information about the contents of the high-bits in /// boolean values held in a type wider than i1. See getBooleanContents. BooleanContent BooleanContents; @@ -1875,9 +1951,8 @@ private: if (NumElts == 1) return LegalizeKind(TypeScalarizeVector, EltVT); - // If we allow the promotion of vector elements using a flag, - // then try to widen vector elements until a legal type is found. - if (mayPromoteElements && EltVT.isInteger()) { + // Try to widen vector elements until a legal type is found. + if (EltVT.isInteger()) { // Vectors with a number of elements that is not a power of two are always // widened, for example <3 x float> -> <4 x float>. if (!VT.isPow2VectorType()) { @@ -2028,14 +2103,14 @@ protected: /// optimization. bool benefitFromCodePlacementOpt; + /// predictableSelectIsExpensive - Tells the code generator that select is + /// more expensive than a branch if the branch is usually predicted right. + bool predictableSelectIsExpensive; + private: /// isLegalRC - Return true if the value types that can be represented by the /// specified register class are all legal. bool isLegalRC(const TargetRegisterClass *RC) const; - - /// hasLegalSuperRegRegClasses - Return true if the specified register class - /// has one or more super-reg register classes that are legal. - bool hasLegalSuperRegRegClasses(const TargetRegisterClass *RC) const; }; /// GetReturnInfo - Given an LLVM IR type and return type attributes, @@ -2043,8 +2118,7 @@ private: /// the offsets, if the return value is being lowered to memory. void GetReturnInfo(Type* ReturnType, Attributes attr, SmallVectorImpl<ISD::OutputArg> &Outs, - const TargetLowering &TLI, - SmallVectorImpl<uint64_t> *Offsets = 0); + const TargetLowering &TLI); } // end llvm namespace diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h index 1a05604..e4bf32b 100644 --- a/include/llvm/Target/TargetMachine.h +++ b/include/llvm/Target/TargetMachine.h @@ -14,6 +14,7 @@ #ifndef LLVM_TARGET_TARGETMACHINE_H #define LLVM_TARGET_TARGETMACHINE_H +#include "llvm/Pass.h" #include "llvm/Support/CodeGen.h" #include "llvm/Target/TargetOptions.h" #include "llvm/ADT/StringRef.h" @@ -247,7 +248,9 @@ public: virtual bool addPassesToEmitFile(PassManagerBase &, formatted_raw_ostream &, CodeGenFileType, - bool /*DisableVerify*/ = true) { + bool /*DisableVerify*/ = true, + AnalysisID StartAfter = 0, + AnalysisID StopAfter = 0) { return true; } @@ -297,7 +300,9 @@ public: virtual bool addPassesToEmitFile(PassManagerBase &PM, formatted_raw_ostream &Out, CodeGenFileType FileType, - bool DisableVerify = true); + bool DisableVerify = true, + AnalysisID StartAfter = 0, + AnalysisID StopAfter = 0); /// addPassesToEmitMachineCode - Add passes to the specified pass manager to /// get machine code emitted. This uses a JITCodeEmitter object to handle diff --git a/include/llvm/Target/TargetOptions.h b/include/llvm/Target/TargetOptions.h index 12a2757..d1a07d1 100644 --- a/include/llvm/Target/TargetOptions.h +++ b/include/llvm/Target/TargetOptions.h @@ -30,20 +30,28 @@ namespace llvm { }; } + namespace FPOpFusion { + enum FPOpFusionMode { + Fast, // Enable fusion of FP ops wherever it's profitable. + Standard, // Only allow fusion of 'blessed' ops (currently just fmuladd). + Strict // Never fuse FP-ops. + }; + } + class TargetOptions { public: TargetOptions() : PrintMachineCode(false), NoFramePointerElim(false), NoFramePointerElimNonLeaf(false), LessPreciseFPMADOption(false), - NoExcessFPPrecision(false), UnsafeFPMath(false), NoInfsFPMath(false), + UnsafeFPMath(false), NoInfsFPMath(false), NoNaNsFPMath(false), HonorSignDependentRoundingFPMathOption(false), UseSoftFloat(false), NoZerosInBSS(false), JITExceptionHandling(false), JITEmitDebugInfo(false), JITEmitDebugInfoToDisk(false), GuaranteedTailCallOpt(false), DisableTailCalls(false), - StackAlignmentOverride(0), RealignStack(true), - DisableJumpTables(false), EnableFastISel(false), + StackAlignmentOverride(0), RealignStack(true), EnableFastISel(false), PositionIndependentExecutable(false), EnableSegmentedStacks(false), - TrapFuncName(""), FloatABIType(FloatABI::Default) + UseInitArray(false), TrapFuncName(""), FloatABIType(FloatABI::Default), + AllowFPOpFusion(FPOpFusion::Standard) {} /// PrintMachineCode - This flag is enabled when the -print-machineinstrs @@ -74,14 +82,6 @@ namespace llvm { unsigned LessPreciseFPMADOption : 1; bool LessPreciseFPMAD() const; - /// NoExcessFPPrecision - This flag is enabled when the - /// -disable-excess-fp-precision flag is specified on the command line. - /// When this flag is off (the default), the code generator is allowed to - /// produce results that are "more precise" than IEEE allows. This includes - /// use of FMA-like operations and use of the X86 FP registers without - /// rounding all over the place. - unsigned NoExcessFPPrecision : 1; - /// UnsafeFPMath - This flag is enabled when the /// -enable-unsafe-fp-math flag is specified on the command line. When /// this flag is off (the default), the code generator is not allowed to @@ -155,10 +155,6 @@ namespace llvm { /// automatically realigned, if needed. unsigned RealignStack : 1; - /// DisableJumpTables - This flag indicates jump tables should not be - /// generated. - unsigned DisableJumpTables : 1; - /// EnableFastISel - This flag enables fast-path instruction selection /// which trades away generated code quality in favor of reducing /// compile time. @@ -172,6 +168,10 @@ namespace llvm { unsigned EnableSegmentedStacks : 1; + /// UseInitArray - Use .init_array instead of .ctors for static + /// constructors. + unsigned UseInitArray : 1; + /// getTrapFunctionName - If this returns a non-empty string, this means /// isel should lower Intrinsic::trap to a call to the specified function /// name instead of an ISD::TRAP node. @@ -185,6 +185,25 @@ namespace llvm { /// Such a combination is unfortunately popular (e.g. arm-apple-darwin). /// Hard presumes that the normal FP ABI is used. FloatABI::ABIType FloatABIType; + + /// AllowFPOpFusion - This flag is set by the -fuse-fp-ops=xxx option. + /// This controls the creation of fused FP ops that store intermediate + /// results in higher precision than IEEE allows (E.g. FMAs). + /// + /// Fast mode - allows formation of fused FP ops whenever they're + /// profitable. + /// Standard mode - allow fusion only for 'blessed' FP ops. At present the + /// only blessed op is the fmuladd intrinsic. In the future more blessed ops + /// may be added. + /// Strict mode - allow fusion only if/when it can be proven that the excess + /// precision won't effect the result. + /// + /// Note: This option only controls formation of fused ops by the optimizers. + /// Fused operations that are explicitly specified (e.g. FMA via the + /// llvm.fma.* intrinsic) will always be honored, regardless of the value of + /// this option. + FPOpFusion::FPOpFusionMode AllowFPOpFusion; + }; } // End llvm namespace diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index 6ddd364..df4d900 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -42,9 +42,9 @@ public: // Instance variables filled by tablegen, do not use! const MCRegisterClass *MC; const vt_iterator VTs; - const unsigned *SubClassMask; + const uint32_t *SubClassMask; + const uint16_t *SuperRegIndices; const sc_iterator SuperClasses; - const sc_iterator SuperRegClasses; ArrayRef<uint16_t> (*OrderFunc)(const MachineFunction&); /// getID() - Return the register class ID number. @@ -119,18 +119,6 @@ public: return I; } - /// superregclasses_begin / superregclasses_end - Loop over all of - /// the superreg register classes of this register class. - sc_iterator superregclasses_begin() const { - return SuperRegClasses; - } - - sc_iterator superregclasses_end() const { - sc_iterator I = SuperRegClasses; - while (*I != NULL) ++I; - return I; - } - /// hasSubClass - return true if the specified TargetRegisterClass /// is a proper sub-class of this TargetRegisterClass. bool hasSubClass(const TargetRegisterClass *RC) const { @@ -163,6 +151,18 @@ public: return SubClassMask; } + /// getSuperRegIndices - Returns a 0-terminated list of sub-register indices + /// that project some super-register class into this register class. The list + /// has an entry for each Idx such that: + /// + /// There exists SuperRC where: + /// For all Reg in SuperRC: + /// this->contains(Reg:Idx) + /// + const uint16_t *getSuperRegIndices() const { + return SuperRegIndices; + } + /// getSuperClasses - Returns a NULL terminated list of super-classes. The /// classes are ordered by ID which is also a topological ordering from large /// to small classes. The list does NOT include the current class. @@ -301,6 +301,11 @@ public: const TargetRegisterClass * getMinimalPhysRegClass(unsigned Reg, EVT VT = MVT::Other) const; + /// getAllocatableClass - Return the maximal subclass of the given register + /// class that is alloctable, or NULL. + const TargetRegisterClass * + getAllocatableClass(const TargetRegisterClass *RC) const; + /// getAllocatableSet - Returns a bitset indexed by register number /// indicating if a register is allocatable or not. If a register class is /// specified, returns the subset for the class. @@ -332,9 +337,23 @@ public: if (regA == regB) return true; if (isVirtualRegister(regA) || isVirtualRegister(regB)) return false; - for (const uint16_t *regList = getOverlaps(regA)+1; *regList; ++regList) { - if (*regList == regB) return true; - } + + // Regunits are numerically ordered. Find a common unit. + MCRegUnitIterator RUA(regA, this); + MCRegUnitIterator RUB(regB, this); + do { + if (*RUA == *RUB) return true; + if (*RUA < *RUB) ++RUA; + else ++RUB; + } while (RUA.isValid() && RUB.isValid()); + return false; + } + + /// hasRegUnit - Returns true if Reg contains RegUnit. + bool hasRegUnit(unsigned Reg, unsigned RegUnit) const { + for (MCRegUnitIterator Units(Reg, this); Units.isValid(); ++Units) + if (*Units == RegUnit) + return true; return false; } @@ -346,10 +365,10 @@ public: /// isSuperRegister - Returns true if regB is a super-register of regA. /// - bool isSuperRegister(unsigned regA, unsigned regB) const { - for (const uint16_t *regList = getSuperRegisters(regA); *regList;++regList){ - if (*regList == regB) return true; - } + bool isSuperRegister(unsigned RegA, unsigned RegB) const { + for (MCSuperRegIterator I(RegA, this); I.isValid(); ++I) + if (*I == RegB) + return true; return false; } @@ -416,7 +435,7 @@ public: /// TableGen will synthesize missing A sub-classes. virtual const TargetRegisterClass * getMatchingSuperRegClass(const TargetRegisterClass *A, - const TargetRegisterClass *B, unsigned Idx) const =0; + const TargetRegisterClass *B, unsigned Idx) const; /// getSubClassWithSubReg - Returns the largest legal sub-class of RC that /// supports the sub-register index Idx. @@ -431,7 +450,10 @@ public: /// /// TableGen will synthesize missing RC sub-classes. virtual const TargetRegisterClass * - getSubClassWithSubReg(const TargetRegisterClass *RC, unsigned Idx) const =0; + getSubClassWithSubReg(const TargetRegisterClass *RC, unsigned Idx) const { + assert(Idx == 0 && "Target has no sub-registers"); + return RC; + } /// composeSubRegIndices - Return the subregister index you get from composing /// two subregister indices. @@ -450,6 +472,34 @@ public: return b; } + /// getCommonSuperRegClass - Find a common super-register class if it exists. + /// + /// Find a register class, SuperRC and two sub-register indices, PreA and + /// PreB, such that: + /// + /// 1. PreA + SubA == PreB + SubB (using composeSubRegIndices()), and + /// + /// 2. For all Reg in SuperRC: Reg:PreA in RCA and Reg:PreB in RCB, and + /// + /// 3. SuperRC->getSize() >= max(RCA->getSize(), RCB->getSize()). + /// + /// SuperRC will be chosen such that no super-class of SuperRC satisfies the + /// requirements, and there is no register class with a smaller spill size + /// that satisfies the requirements. + /// + /// SubA and SubB must not be 0. Use getMatchingSuperRegClass() instead. + /// + /// Either of the PreA and PreB sub-register indices may be returned as 0. In + /// that case, the returned register class will be a sub-class of the + /// corresponding argument register class. + /// + /// The function returns NULL if no register class can be found. + /// + const TargetRegisterClass* + getCommonSuperRegClass(const TargetRegisterClass *RCA, unsigned SubA, + const TargetRegisterClass *RCB, unsigned SubB, + unsigned &PreA, unsigned &PreB) const; + //===--------------------------------------------------------------------===// // Register Class Information // @@ -479,7 +529,8 @@ public: /// getPointerRegClass - Returns a TargetRegisterClass used for pointer /// values. If a target supports multiple different pointer register classes, /// kind specifies which one is indicated. - virtual const TargetRegisterClass *getPointerRegClass(unsigned Kind=0) const { + virtual const TargetRegisterClass * + getPointerRegClass(const MachineFunction &MF, unsigned Kind=0) const { llvm_unreachable("Target didn't implement getPointerRegClass!"); } @@ -515,13 +566,16 @@ public: return 0; } - /// Get the weight in units of pressure for this register class. +// Get the weight in units of pressure for this register class. virtual const RegClassWeight &getRegClassWeight( const TargetRegisterClass *RC) const = 0; /// Get the number of dimensions of register pressure. virtual unsigned getNumRegPressureSets() const = 0; + /// Get the name of this register unit pressure set. + virtual const char *getRegPressureSetName(unsigned Idx) const = 0; + /// Get the register unit pressure limit for this dimension. /// This limit must be adjusted dynamically for reserved registers. virtual unsigned getRegPressureSetLimit(unsigned Idx) const = 0; @@ -609,6 +663,12 @@ public: return false; } + /// trackLivenessAfterRegAlloc - returns true if the live-ins should be tracked + /// after register allocation. + virtual bool trackLivenessAfterRegAlloc(const MachineFunction &MF) const { + return false; + } + /// needsStackRealignment - true if storage within the function requires the /// stack pointer to be aligned more than the normal calling convention calls /// for. @@ -708,6 +768,62 @@ public: }; +//===----------------------------------------------------------------------===// +// SuperRegClassIterator +//===----------------------------------------------------------------------===// +// +// Iterate over the possible super-registers for a given register class. The +// iterator will visit a list of pairs (Idx, Mask) corresponding to the +// possible classes of super-registers. +// +// Each bit mask will have at least one set bit, and each set bit in Mask +// corresponds to a SuperRC such that: +// +// For all Reg in SuperRC: Reg:Idx is in RC. +// +// The iterator can include (O, RC->getSubClassMask()) as the first entry which +// also satisfies the above requirement, assuming Reg:0 == Reg. +// +class SuperRegClassIterator { + const unsigned RCMaskWords; + unsigned SubReg; + const uint16_t *Idx; + const uint32_t *Mask; + +public: + /// Create a SuperRegClassIterator that visits all the super-register classes + /// of RC. When IncludeSelf is set, also include the (0, sub-classes) entry. + SuperRegClassIterator(const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI, + bool IncludeSelf = false) + : RCMaskWords((TRI->getNumRegClasses() + 31) / 32), + SubReg(0), + Idx(RC->getSuperRegIndices()), + Mask(RC->getSubClassMask()) { + if (!IncludeSelf) + ++*this; + } + + /// Returns true if this iterator is still pointing at a valid entry. + bool isValid() const { return Idx; } + + /// Returns the current sub-register index. + unsigned getSubReg() const { return SubReg; } + + /// Returns the bit mask if register classes that getSubReg() projects into + /// RC. + const uint32_t *getMask() const { return Mask; } + + /// Advance iterator to the next entry. + void operator++() { + assert(isValid() && "Cannot move iterator past end."); + Mask += RCMaskWords; + SubReg = *Idx++; + if (!SubReg) + Idx = 0; + } +}; + // This is useful when building IndexedMaps keyed on virtual registers struct VirtReg2IndexFunctor : public std::unary_function<unsigned, unsigned> { unsigned operator()(unsigned Reg) const { @@ -742,6 +858,29 @@ static inline raw_ostream &operator<<(raw_ostream &OS, const PrintReg &PR) { return OS; } +/// PrintRegUnit - Helper class for printing register units on a raw_ostream. +/// +/// Register units are named after their root registers: +/// +/// AL - Single root. +/// FP0~ST7 - Dual roots. +/// +/// Usage: OS << PrintRegUnit(Unit, TRI) << '\n'; +/// +class PrintRegUnit { + const TargetRegisterInfo *TRI; + unsigned Unit; +public: + PrintRegUnit(unsigned unit, const TargetRegisterInfo *tri) + : TRI(tri), Unit(unit) {} + void print(raw_ostream&) const; +}; + +static inline raw_ostream &operator<<(raw_ostream &OS, const PrintRegUnit &PR) { + PR.print(OS); + return OS; +} + } // End llvm namespace #endif diff --git a/include/llvm/Target/TargetSchedule.td b/include/llvm/Target/TargetSchedule.td index 97ea82a..4dc488d 100644 --- a/include/llvm/Target/TargetSchedule.td +++ b/include/llvm/Target/TargetSchedule.td @@ -1,10 +1,10 @@ //===- TargetSchedule.td - Target Independent Scheduling ---*- 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 the target-independent scheduling interfaces which should @@ -12,119 +12,30 @@ // //===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// -// Processor functional unit - These values represent the function units -// available across all chip sets for the target. Eg., IntUnit, FPUnit, ... -// These may be independent values for each chip set or may be shared across -// all chip sets of the target. Each functional unit is treated as a resource -// during scheduling and has an affect instruction order based on availability -// during a time interval. -// -class FuncUnit; - -//===----------------------------------------------------------------------===// -// Pipeline bypass / forwarding - These values specifies the symbolic names of -// pipeline bypasses which can be used to forward results of instructions -// that are forwarded to uses. -class Bypass; -def NoBypass : Bypass; - -class ReservationKind<bits<1> val> { - int Value = val; -} - -def Required : ReservationKind<0>; -def Reserved : ReservationKind<1>; +include "llvm/Target/TargetItinerary.td" -//===----------------------------------------------------------------------===// -// Instruction stage - These values represent a non-pipelined step in -// the execution of an instruction. Cycles represents the number of -// discrete time slots needed to complete the stage. Units represent -// the choice of functional units that can be used to complete the -// stage. Eg. IntUnit1, IntUnit2. NextCycles indicates how many -// cycles should elapse from the start of this stage to the start of -// the next stage in the itinerary. For example: -// -// A stage is specified in one of two ways: -// -// InstrStage<1, [FU_x, FU_y]> - TimeInc defaults to Cycles -// InstrStage<1, [FU_x, FU_y], 0> - TimeInc explicit +// The SchedMachineModel is defined by subtargets for three categories of data: +// 1) Basic properties for coarse grained instruction cost model. +// 2) Scheduler Read/Write resources for simple per-opcode cost model. +// 3) Instruction itineraties for detailed reservation tables. // +// Default values for basic properties are defined in MCSchedModel. "-1" +// indicates that the property is not overriden by the target description. +class SchedMachineModel { + int IssueWidth = -1; // Max instructions that may be scheduled per cycle. + int MinLatency = -1; // Determines which instrucions are allowed in a group. + // (-1) inorder (0) ooo, (1): inorder +var latencies. + int LoadLatency = -1; // Cycles for loads to access the cache. + int HighLatency = -1; // Approximation of cycles for "high latency" ops. + int MispredictPenalty = -1; // Extra cycles for a mispredicted branch. -class InstrStage<int cycles, list<FuncUnit> units, - int timeinc = -1, - ReservationKind kind = Required> { - int Cycles = cycles; // length of stage in machine cycles - list<FuncUnit> Units = units; // choice of functional units - int TimeInc = timeinc; // cycles till start of next stage - int Kind = kind.Value; // kind of FU reservation -} + ProcessorItineraries Itineraries = NoItineraries; -//===----------------------------------------------------------------------===// -// Instruction itinerary - An itinerary represents a sequential series of steps -// required to complete an instruction. Itineraries are represented as lists of -// instruction stages. -// - -//===----------------------------------------------------------------------===// -// Instruction itinerary classes - These values represent 'named' instruction -// itinerary. Using named itineraries simplifies managing groups of -// instructions across chip sets. An instruction uses the same itinerary class -// across all chip sets. Thus a new chip set can be added without modifying -// instruction information. -// -// NumMicroOps represents the number of micro-operations that each instruction -// in the class are decoded to. If the number is zero, then it means the -// instruction can decode into variable number of micro-ops and it must be -// determined dynamically. -// -class InstrItinClass<int ops = 1> { - int NumMicroOps = ops; + bit NoModel = 0; // Special tag to indicate missing machine model. } -def NoItinerary : InstrItinClass; -//===----------------------------------------------------------------------===// -// Instruction itinerary data - These values provide a runtime map of an -// instruction itinerary class (name) to its itinerary data. -// -// OperandCycles are optional "cycle counts". They specify the cycle after -// instruction issue the values which correspond to specific operand indices -// are defined or read. Bypasses are optional "pipeline forwarding pathes", if -// a def by an instruction is available on a specific bypass and the use can -// read from the same bypass, then the operand use latency is reduced by one. -// -// InstrItinData<IIC_iLoad_i , [InstrStage<1, [A9_Pipe1]>, -// InstrStage<1, [A9_AGU]>], -// [3, 1], [A9_LdBypass]>, -// InstrItinData<IIC_iMVNr , [InstrStage<1, [A9_Pipe0, A9_Pipe1]>], -// [1, 1], [NoBypass, A9_LdBypass]>, -// -// In this example, the instruction of IIC_iLoadi reads its input on cycle 1 -// (after issue) and the result of the load is available on cycle 3. The result -// is available via forwarding path A9_LdBypass. If it's used by the first -// source operand of instructions of IIC_iMVNr class, then the operand latency -// is reduced by 1. -class InstrItinData<InstrItinClass Class, list<InstrStage> stages, - list<int> operandcycles = [], - list<Bypass> bypasses = []> { - InstrItinClass TheClass = Class; - list<InstrStage> Stages = stages; - list<int> OperandCycles = operandcycles; - list<Bypass> Bypasses = bypasses; -} - -//===----------------------------------------------------------------------===// -// Processor itineraries - These values represent the set of all itinerary -// classes for a given chip set. -// -class ProcessorItineraries<list<FuncUnit> fu, list<Bypass> bp, - list<InstrItinData> iid> { - list<FuncUnit> FU = fu; - list<Bypass> BP = bp; - list<InstrItinData> IID = iid; +def NoSchedModel : SchedMachineModel { + let NoModel = 1; } -// NoItineraries - A marker that can be used by processors without schedule -// info. -def NoItineraries : ProcessorItineraries<[], [], []>; - +// TODO: Define classes for processor and scheduler resources. diff --git a/include/llvm/Target/TargetSelectionDAG.td b/include/llvm/Target/TargetSelectionDAG.td index f55cf0e..3f81c06 100644 --- a/include/llvm/Target/TargetSelectionDAG.td +++ b/include/llvm/Target/TargetSelectionDAG.td @@ -404,11 +404,16 @@ def brind : SDNode<"ISD::BRIND" , SDTBrind, [SDNPHasChain]>; def br : SDNode<"ISD::BR" , SDTBr, [SDNPHasChain]>; def trap : SDNode<"ISD::TRAP" , SDTNone, [SDNPHasChain, SDNPSideEffect]>; +def debugtrap : SDNode<"ISD::DEBUGTRAP" , SDTNone, + [SDNPHasChain, SDNPSideEffect]>; def prefetch : SDNode<"ISD::PREFETCH" , SDTPrefetch, [SDNPHasChain, SDNPMayLoad, SDNPMayStore, SDNPMemOperand]>; +def readcyclecounter : SDNode<"ISD::READCYCLECOUNTER", SDTIntLeaf, + [SDNPHasChain, SDNPSideEffect]>; + def membarrier : SDNode<"ISD::MEMBARRIER" , SDTMemBarrier, [SDNPHasChain, SDNPSideEffect]>; @@ -593,6 +598,13 @@ def not : PatFrag<(ops node:$in), (xor node:$in, -1)>; def vnot : PatFrag<(ops node:$in), (xor node:$in, immAllOnesV)>; def ineg : PatFrag<(ops node:$in), (sub 0, node:$in)>; +// null_frag - The null pattern operator is used in multiclass instantiations +// which accept an SDPatternOperator for use in matching patterns for internal +// definitions. When expanding a pattern, if the null fragment is referenced +// in the expansion, the pattern is discarded and it is as-if '[]' had been +// specified. This allows multiclasses to have the isel patterns be optional. +def null_frag : SDPatternOperator; + // load fragments. def unindexedload : PatFrag<(ops node:$ptr), (ld node:$ptr), [{ return cast<LoadSDNode>(N)->getAddressingMode() == ISD::UNINDEXED; diff --git a/include/llvm/Transforms/Instrumentation.h b/include/llvm/Transforms/Instrumentation.h index bbf3a69..4b0c448 100644 --- a/include/llvm/Transforms/Instrumentation.h +++ b/include/llvm/Transforms/Instrumentation.h @@ -38,6 +38,13 @@ ModulePass *createAddressSanitizerPass(); // Insert ThreadSanitizer (race detection) instrumentation FunctionPass *createThreadSanitizerPass(); + +// BoundsChecking - This pass instruments the code to perform run-time bounds +// checking on loads, stores, and other memory intrinsics. +// Penalty is the maximum run-time that is acceptable for the user. +// +FunctionPass *createBoundsCheckingPass(unsigned Penalty = 5); + } // End llvm namespace #endif diff --git a/include/llvm/Transforms/Scalar.h b/include/llvm/Transforms/Scalar.h index 7f055d4..3dce6fe 100644 --- a/include/llvm/Transforms/Scalar.h +++ b/include/llvm/Transforms/Scalar.h @@ -74,7 +74,10 @@ FunctionPass *createAggressiveDCEPass(); // if possible. // FunctionPass *createScalarReplAggregatesPass(signed Threshold = -1, - bool UseDomTree = true); + bool UseDomTree = true, + signed StructMemberThreshold = -1, + signed ArrayElementThreshold = -1, + signed ScalarLoadThreshold = -1); //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils/BasicBlockUtils.h b/include/llvm/Transforms/Utils/BasicBlockUtils.h index 2f9dc54..8a939cc 100644 --- a/include/llvm/Transforms/Utils/BasicBlockUtils.h +++ b/include/llvm/Transforms/Utils/BasicBlockUtils.h @@ -202,10 +202,6 @@ void SplitLandingPadPredecessors(BasicBlock *OrigBB,ArrayRef<BasicBlock*> Preds, ReturnInst *FoldReturnIntoUncondBranch(ReturnInst *RI, BasicBlock *BB, BasicBlock *Pred); -/// GetFirstDebugLocInBasicBlock - Return first valid DebugLoc entry in a -/// given basic block. -DebugLoc GetFirstDebugLocInBasicBlock(const BasicBlock *BB); - } // End llvm namespace #endif diff --git a/include/llvm/Transforms/Utils/BuildLibCalls.h b/include/llvm/Transforms/Utils/BuildLibCalls.h index 17cd58eb..a6e41f0 100644 --- a/include/llvm/Transforms/Utils/BuildLibCalls.h +++ b/include/llvm/Transforms/Utils/BuildLibCalls.h @@ -15,7 +15,7 @@ #ifndef TRANSFORMS_UTILS_BUILDLIBCALLS_H #define TRANSFORMS_UTILS_BUILDLIBCALLS_H -#include "llvm/Support/IRBuilder.h" +#include "llvm/IRBuilder.h" namespace llvm { class Value; @@ -28,41 +28,52 @@ namespace llvm { /// EmitStrLen - Emit a call to the strlen function to the builder, for the /// specified pointer. Ptr is required to be some pointer type, and the /// return value has 'intptr_t' type. - Value *EmitStrLen(Value *Ptr, IRBuilder<> &B, const TargetData *TD); + Value *EmitStrLen(Value *Ptr, IRBuilder<> &B, const TargetData *TD, + const TargetLibraryInfo *TLI); + + /// EmitStrNLen - Emit a call to the strnlen function to the builder, for the + /// specified pointer. Ptr is required to be some pointer type, MaxLen must + /// be of size_t type, and the return value has 'intptr_t' type. + Value *EmitStrNLen(Value *Ptr, Value *MaxLen, IRBuilder<> &B, + const TargetData *TD, const TargetLibraryInfo *TLI); /// EmitStrChr - Emit a call to the strchr function to the builder, for the /// specified pointer and character. Ptr is required to be some pointer type, /// and the return value has 'i8*' type. - Value *EmitStrChr(Value *Ptr, char C, IRBuilder<> &B, const TargetData *TD); + Value *EmitStrChr(Value *Ptr, char C, IRBuilder<> &B, const TargetData *TD, + const TargetLibraryInfo *TLI); /// EmitStrNCmp - Emit a call to the strncmp function to the builder. Value *EmitStrNCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B, - const TargetData *TD); + const TargetData *TD, const TargetLibraryInfo *TLI); /// EmitStrCpy - Emit a call to the strcpy function to the builder, for the /// specified pointer arguments. Value *EmitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B, - const TargetData *TD, StringRef Name = "strcpy"); + const TargetData *TD, const TargetLibraryInfo *TLI, + StringRef Name = "strcpy"); /// EmitStrNCpy - Emit a call to the strncpy function to the builder, for the /// specified pointer arguments and length. Value *EmitStrNCpy(Value *Dst, Value *Src, Value *Len, IRBuilder<> &B, - const TargetData *TD, StringRef Name = "strncpy"); + const TargetData *TD, const TargetLibraryInfo *TLI, + StringRef Name = "strncpy"); /// EmitMemCpyChk - Emit a call to the __memcpy_chk function to the builder. /// This expects that the Len and ObjSize have type 'intptr_t' and Dst/Src /// are pointers. Value *EmitMemCpyChk(Value *Dst, Value *Src, Value *Len, Value *ObjSize, - IRBuilder<> &B, const TargetData *TD); + IRBuilder<> &B, const TargetData *TD, + const TargetLibraryInfo *TLI); /// EmitMemChr - Emit a call to the memchr function. This assumes that Ptr is /// a pointer, Val is an i32 value, and Len is an 'intptr_t' value. Value *EmitMemChr(Value *Ptr, Value *Val, Value *Len, IRBuilder<> &B, - const TargetData *TD); + const TargetData *TD, const TargetLibraryInfo *TLI); /// EmitMemCmp - Emit a call to the memcmp function. Value *EmitMemCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B, - const TargetData *TD); + const TargetData *TD, const TargetLibraryInfo *TLI); /// EmitUnaryFloatFnCall - Emit a call to the unary function named 'Name' /// (e.g. 'floor'). This function is known to take a single of type matching @@ -74,26 +85,28 @@ namespace llvm { /// EmitPutChar - Emit a call to the putchar function. This assumes that Char /// is an integer. - Value *EmitPutChar(Value *Char, IRBuilder<> &B, const TargetData *TD); + Value *EmitPutChar(Value *Char, IRBuilder<> &B, const TargetData *TD, + const TargetLibraryInfo *TLI); /// EmitPutS - Emit a call to the puts function. This assumes that Str is /// some pointer. - void EmitPutS(Value *Str, IRBuilder<> &B, const TargetData *TD); + Value *EmitPutS(Value *Str, IRBuilder<> &B, const TargetData *TD, + const TargetLibraryInfo *TLI); /// EmitFPutC - Emit a call to the fputc function. This assumes that Char is /// an i32, and File is a pointer to FILE. - void EmitFPutC(Value *Char, Value *File, IRBuilder<> &B, - const TargetData *TD); + Value *EmitFPutC(Value *Char, Value *File, IRBuilder<> &B, + const TargetData *TD, const TargetLibraryInfo *TLI); /// EmitFPutS - Emit a call to the puts function. Str is required to be a /// pointer and File is a pointer to FILE. - void EmitFPutS(Value *Str, Value *File, IRBuilder<> &B, const TargetData *TD, - const TargetLibraryInfo *TLI); + Value *EmitFPutS(Value *Str, Value *File, IRBuilder<> &B, const TargetData *TD, + const TargetLibraryInfo *TLI); /// EmitFWrite - Emit a call to the fwrite function. This assumes that Ptr is /// a pointer, Size is an 'intptr_t', and File is a pointer to FILE. - void EmitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilder<> &B, - const TargetData *TD, const TargetLibraryInfo *TLI); + Value *EmitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilder<> &B, + const TargetData *TD, const TargetLibraryInfo *TLI); /// SimplifyFortifiedLibCalls - Helper class for folding checked library /// calls (e.g. __strcpy_chk) into their unchecked counterparts. @@ -105,7 +118,7 @@ namespace llvm { bool isString) const = 0; public: virtual ~SimplifyFortifiedLibCalls(); - bool fold(CallInst *CI, const TargetData *TD); + bool fold(CallInst *CI, const TargetData *TD, const TargetLibraryInfo *TLI); }; } diff --git a/include/llvm/Transforms/Utils/CodeExtractor.h b/include/llvm/Transforms/Utils/CodeExtractor.h new file mode 100644 index 0000000..1122678 --- /dev/null +++ b/include/llvm/Transforms/Utils/CodeExtractor.h @@ -0,0 +1,127 @@ +//===-- Transform/Utils/CodeExtractor.h - Code extraction util --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// A utility to support extracting code from one function into its own +// stand-alone function. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_CODE_EXTRACTOR_H +#define LLVM_TRANSFORMS_UTILS_CODE_EXTRACTOR_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SetVector.h" + +namespace llvm { + class BasicBlock; + class DominatorTree; + class Function; + class Loop; + class Module; + class RegionNode; + class Type; + class Value; + + /// \brief Utility class for extracting code into a new function. + /// + /// This utility provides a simple interface for extracting some sequence of + /// code into its own function, replacing it with a call to that function. It + /// also provides various methods to query about the nature and result of + /// such a transformation. + /// + /// The rough algorithm used is: + /// 1) Find both the inputs and outputs for the extracted region. + /// 2) Pass the inputs as arguments, remapping them within the extracted + /// function to arguments. + /// 3) Add allocas for any scalar outputs, adding all of the outputs' allocas + /// as arguments, and inserting stores to the arguments for any scalars. + class CodeExtractor { + typedef SetVector<Value *> ValueSet; + + // Various bits of state computed on construction. + DominatorTree *const DT; + const bool AggregateArgs; + + // Bits of intermediate state computed at various phases of extraction. + SetVector<BasicBlock *> Blocks; + unsigned NumExitBlocks; + Type *RetTy; + + public: + /// \brief Create a code extractor for a single basic block. + /// + /// In this formation, we don't require a dominator tree. The given basic + /// block is set up for extraction. + CodeExtractor(BasicBlock *BB, bool AggregateArgs = false); + + /// \brief Create a code extractor for a sequence of blocks. + /// + /// Given a sequence of basic blocks where the first block in the sequence + /// dominates the rest, prepare a code extractor object for pulling this + /// sequence out into its new function. When a DominatorTree is also given, + /// extra checking and transformations are enabled. + CodeExtractor(ArrayRef<BasicBlock *> BBs, DominatorTree *DT = 0, + bool AggregateArgs = false); + + /// \brief Create a code extractor for a loop body. + /// + /// Behaves just like the generic code sequence constructor, but uses the + /// block sequence of the loop. + CodeExtractor(DominatorTree &DT, Loop &L, bool AggregateArgs = false); + + /// \brief Create a code extractor for a region node. + /// + /// Behaves just like the generic code sequence constructor, but uses the + /// block sequence of the region node passed in. + CodeExtractor(DominatorTree &DT, const RegionNode &RN, + bool AggregateArgs = false); + + /// \brief Perform the extraction, returning the new function. + /// + /// Returns zero when called on a CodeExtractor instance where isEligible + /// returns false. + Function *extractCodeRegion(); + + /// \brief Test whether this code extractor is eligible. + /// + /// Based on the blocks used when constructing the code extractor, + /// determine whether it is eligible for extraction. + bool isEligible() const { return !Blocks.empty(); } + + /// \brief Compute the set of input values and output values for the code. + /// + /// These can be used either when performing the extraction or to evaluate + /// the expected size of a call to the extracted function. Note that this + /// work cannot be cached between the two as once we decide to extract + /// a code sequence, that sequence is modified, including changing these + /// sets, before extraction occurs. These modifications won't have any + /// significant impact on the cost however. + void findInputsOutputs(ValueSet &Inputs, ValueSet &Outputs) const; + + private: + void severSplitPHINodes(BasicBlock *&Header); + void splitReturnBlocks(); + + Function *constructFunction(const ValueSet &inputs, + const ValueSet &outputs, + BasicBlock *header, + BasicBlock *newRootNode, BasicBlock *newHeader, + Function *oldFunction, Module *M); + + void moveCodeToFunction(Function *newFunction); + + void emitCallAndSwitchStatement(Function *newFunction, + BasicBlock *newHeader, + ValueSet &inputs, + ValueSet &outputs); + + }; +} + +#endif diff --git a/include/llvm/Transforms/Utils/FunctionUtils.h b/include/llvm/Transforms/Utils/FunctionUtils.h deleted file mode 100644 index 8d71e43..0000000 --- a/include/llvm/Transforms/Utils/FunctionUtils.h +++ /dev/null @@ -1,45 +0,0 @@ -//===-- Transform/Utils/FunctionUtils.h - Function Utils --------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This family of transformations manipulate LLVM functions. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TRANSFORMS_UTILS_FUNCTION_H -#define LLVM_TRANSFORMS_UTILS_FUNCTION_H - -#include "llvm/ADT/ArrayRef.h" -#include <vector> - -namespace llvm { - class BasicBlock; - class DominatorTree; - class Function; - class Loop; - - /// ExtractCodeRegion - Rip out a sequence of basic blocks into a new - /// function. - /// - Function* ExtractCodeRegion(DominatorTree& DT, - ArrayRef<BasicBlock*> code, - bool AggregateArgs = false); - - /// ExtractLoop - Rip out a natural loop into a new function. - /// - Function* ExtractLoop(DominatorTree& DT, Loop *L, - bool AggregateArgs = false); - - /// ExtractBasicBlock - Rip out a basic block (and the associated landing pad) - /// into a new function. - /// - Function* ExtractBasicBlock(ArrayRef<BasicBlock*> BBs, - bool AggregateArgs = false); -} - -#endif diff --git a/include/llvm/Transforms/Utils/Local.h b/include/llvm/Transforms/Utils/Local.h index 7f99dbc..495eab7 100644 --- a/include/llvm/Transforms/Utils/Local.h +++ b/include/llvm/Transforms/Utils/Local.h @@ -15,6 +15,11 @@ #ifndef LLVM_TRANSFORMS_UTILS_LOCAL_H #define LLVM_TRANSFORMS_UTILS_LOCAL_H +#include "llvm/IRBuilder.h" +#include "llvm/Operator.h" +#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/Target/TargetData.h" + namespace llvm { class User; @@ -160,6 +165,65 @@ static inline unsigned getKnownAlignment(Value *V, const TargetData *TD = 0) { return getOrEnforceKnownAlignment(V, 0, TD); } +/// EmitGEPOffset - Given a getelementptr instruction/constantexpr, emit the +/// code necessary to compute the offset from the base pointer (without adding +/// in the base pointer). Return the result as a signed integer of intptr size. +/// When NoAssumptions is true, no assumptions about index computation not +/// overflowing is made. +template<typename IRBuilderTy> +Value *EmitGEPOffset(IRBuilderTy *Builder, const TargetData &TD, User *GEP, + bool NoAssumptions = false) { + gep_type_iterator GTI = gep_type_begin(GEP); + Type *IntPtrTy = TD.getIntPtrType(GEP->getContext()); + Value *Result = Constant::getNullValue(IntPtrTy); + + // If the GEP is inbounds, we know that none of the addressing operations will + // overflow in an unsigned sense. + bool isInBounds = cast<GEPOperator>(GEP)->isInBounds() && !NoAssumptions; + + // Build a mask for high order bits. + unsigned IntPtrWidth = TD.getPointerSizeInBits(); + uint64_t PtrSizeMask = ~0ULL >> (64-IntPtrWidth); + + for (User::op_iterator i = GEP->op_begin() + 1, e = GEP->op_end(); i != e; + ++i, ++GTI) { + Value *Op = *i; + uint64_t Size = TD.getTypeAllocSize(GTI.getIndexedType()) & PtrSizeMask; + if (ConstantInt *OpC = dyn_cast<ConstantInt>(Op)) { + if (OpC->isZero()) continue; + + // Handle a struct index, which adds its field offset to the pointer. + if (StructType *STy = dyn_cast<StructType>(*GTI)) { + Size = TD.getStructLayout(STy)->getElementOffset(OpC->getZExtValue()); + + if (Size) + Result = Builder->CreateAdd(Result, ConstantInt::get(IntPtrTy, Size), + GEP->getName()+".offs"); + continue; + } + + Constant *Scale = ConstantInt::get(IntPtrTy, Size); + Constant *OC = ConstantExpr::getIntegerCast(OpC, IntPtrTy, true /*SExt*/); + Scale = ConstantExpr::getMul(OC, Scale, isInBounds/*NUW*/); + // Emit an add instruction. + Result = Builder->CreateAdd(Result, Scale, GEP->getName()+".offs"); + continue; + } + // Convert to correct type. + if (Op->getType() != IntPtrTy) + Op = Builder->CreateIntCast(Op, IntPtrTy, true, Op->getName()+".c"); + if (Size != 1) { + // We'll let instcombine(mul) convert this to a shl if possible. + Op = Builder->CreateMul(Op, ConstantInt::get(IntPtrTy, Size), + GEP->getName()+".idx", isInBounds /*NUW*/); + } + + // Emit an add instruction. + Result = Builder->CreateAdd(Op, Result, GEP->getName()+".offs"); + } + return Result; +} + ///===---------------------------------------------------------------------===// /// Dbg Intrinsic utilities /// diff --git a/include/llvm/Transforms/Utils/PromoteMemToReg.h b/include/llvm/Transforms/Utils/PromoteMemToReg.h index 98d51a2..0bb6ec6 100644 --- a/include/llvm/Transforms/Utils/PromoteMemToReg.h +++ b/include/llvm/Transforms/Utils/PromoteMemToReg.h @@ -21,7 +21,6 @@ namespace llvm { class AllocaInst; class DominatorTree; -class DominanceFrontier; class AliasSetTracker; /// isAllocaPromotable - Return true if this alloca is legal for promotion. diff --git a/include/llvm/Transforms/Vectorize.h b/include/llvm/Transforms/Vectorize.h index 652916c..1e49a9c 100644 --- a/include/llvm/Transforms/Vectorize.h +++ b/include/llvm/Transforms/Vectorize.h @@ -28,6 +28,9 @@ struct VectorizeConfig { /// @brief The size of the native vector registers. unsigned VectorBits; + /// @brief Vectorize boolean values. + bool VectorizeBools; + /// @brief Vectorize integer values. bool VectorizeInts; @@ -49,6 +52,9 @@ struct VectorizeConfig { /// @brief Vectorize select instructions. bool VectorizeSelect; + /// @brief Vectorize comparison instructions. + bool VectorizeCmp; + /// @brief Vectorize getelementptr instructions. bool VectorizeGEP; @@ -80,6 +86,9 @@ struct VectorizeConfig { /// @brief The maximum number of pairing iterations. unsigned MaxIter; + /// @brief Don't try to form odd-length vectors. + bool Pow2LenOnly; + /// @brief Don't boost the chain-depth contribution of loads and stores. bool NoMemOpBoost; diff --git a/include/llvm/Support/TypeBuilder.h b/include/llvm/TypeBuilder.h index c756069..0b56479 100644 --- a/include/llvm/Support/TypeBuilder.h +++ b/include/llvm/TypeBuilder.h @@ -1,4 +1,4 @@ -//===---- llvm/Support/TypeBuilder.h - Builder for LLVM types ---*- C++ -*-===// +//===---- llvm/TypeBuilder.h - Builder for LLVM types -----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_TYPEBUILDER_H -#define LLVM_SUPPORT_TYPEBUILDER_H +#ifndef LLVM_TYPEBUILDER_H +#define LLVM_TYPEBUILDER_H #include "llvm/DerivedTypes.h" #include "llvm/LLVMContext.h" diff --git a/include/llvm/TypeFinder.h b/include/llvm/TypeFinder.h new file mode 100644 index 0000000..5d80705 --- /dev/null +++ b/include/llvm/TypeFinder.h @@ -0,0 +1,78 @@ +//===-- llvm/TypeFinder.h - Class for finding 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_TYPEFINDER_H +#define LLVM_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/User.h b/include/llvm/User.h index c52f32f..5d5460c 100644 --- a/include/llvm/User.h +++ b/include/llvm/User.h @@ -7,11 +7,11 @@ // //===----------------------------------------------------------------------===// // -// This class defines the interface that one who 'use's a Value must implement. +// 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 User's. +// * Instructions are the largest class of Users. // * Constants may be users of other constants (think arrays and stuff) // //===----------------------------------------------------------------------===// |