diff options
Diffstat (limited to 'llvm/include')
55 files changed, 723 insertions, 350 deletions
diff --git a/llvm/include/llvm/ADT/Bitfields.h b/llvm/include/llvm/ADT/Bitfields.h index 1fbc41c..be9546e 100644 --- a/llvm/include/llvm/ADT/Bitfields.h +++ b/llvm/include/llvm/ADT/Bitfields.h @@ -100,8 +100,8 @@ template <typename Bitfield, typename StorageType> struct Impl { using IntegerType = typename Bitfield::IntegerType; static constexpr size_t StorageBits = sizeof(StorageType) * CHAR_BIT; - static_assert(Bitfield::FirstBit <= StorageBits, "Data must fit in mask"); - static_assert(Bitfield::LastBit <= StorageBits, "Data must fit in mask"); + static_assert(Bitfield::FirstBit < StorageBits, "Data must fit in mask"); + static_assert(Bitfield::LastBit < StorageBits, "Data must fit in mask"); static constexpr StorageType LowMask = maskTrailingOnes<StorageType>(Bitfield::Bits); static constexpr StorageType Mask = LowMask << Bitfield::Shift; diff --git a/llvm/include/llvm/ADT/ConcurrentHashtable.h b/llvm/include/llvm/ADT/ConcurrentHashtable.h index 6a943c5..0cc03cf 100644 --- a/llvm/include/llvm/ADT/ConcurrentHashtable.h +++ b/llvm/include/llvm/ADT/ConcurrentHashtable.h @@ -177,7 +177,7 @@ public: #if LLVM_ENABLE_THREADS // Lock bucket. - CurBucket.Guard.lock(); + std::scoped_lock<std::mutex> Lock(CurBucket.Guard); #endif HashesPtr BucketHashes = CurBucket.Hashes; @@ -195,11 +195,6 @@ public: CurBucket.NumberOfEntries++; RehashBucket(CurBucket); - -#if LLVM_ENABLE_THREADS - CurBucket.Guard.unlock(); -#endif - return {NewData, true}; } @@ -208,10 +203,6 @@ public: KeyDataTy *EntryData = BucketEntries[CurEntryIdx]; if (Info::isEqual(Info::getKey(*EntryData), NewValue)) { // Already existed entry matched with inserted data is found. -#if LLVM_ENABLE_THREADS - CurBucket.Guard.unlock(); -#endif - return {EntryData, false}; } } diff --git a/llvm/include/llvm/ADT/DenseMap.h b/llvm/include/llvm/ADT/DenseMap.h index 25b5262..22ef7ed 100644 --- a/llvm/include/llvm/ADT/DenseMap.h +++ b/llvm/include/llvm/ADT/DenseMap.h @@ -130,13 +130,13 @@ public: return; } - const KeyT EmptyKey = getEmptyKey(); + const KeyT EmptyKey = KeyInfoT::getEmptyKey(); if constexpr (std::is_trivially_destructible_v<ValueT>) { // Use a simpler loop when values don't need destruction. for (BucketT &B : buckets()) B.getFirst() = EmptyKey; } else { - const KeyT TombstoneKey = getTombstoneKey(); + const KeyT TombstoneKey = KeyInfoT::getTombstoneKey(); unsigned NumEntries = getNumEntries(); for (BucketT &B : buckets()) { if (!KeyInfoT::isEqual(B.getFirst(), EmptyKey)) { @@ -154,6 +154,17 @@ public: setNumTombstones(0); } + void shrink_and_clear() { + auto [Reallocate, NewNumBuckets] = derived().planShrinkAndClear(); + destroyAll(); + if (!Reallocate) { + initEmpty(); + return; + } + derived().deallocateBuckets(); + derived().init(NewNumBuckets); + } + /// Return true if the specified key is in the map, false otherwise. [[nodiscard]] bool contains(const_arg_type_t<KeyT> Val) const { return doFind(Val) != nullptr; @@ -314,7 +325,7 @@ public: return false; // not in map. TheBucket->getSecond().~ValueT(); - TheBucket->getFirst() = getTombstoneKey(); + TheBucket->getFirst() = KeyInfoT::getTombstoneKey(); decrementNumEntries(); incrementNumTombstones(); return true; @@ -322,7 +333,7 @@ public: void erase(iterator I) { BucketT *TheBucket = &*I; TheBucket->getSecond().~ValueT(); - TheBucket->getFirst() = getTombstoneKey(); + TheBucket->getFirst() = KeyInfoT::getTombstoneKey(); decrementNumEntries(); incrementNumTombstones(); } @@ -353,10 +364,17 @@ protected: DenseMapBase() = default; void destroyAll() { + // No need to iterate through the buckets if both KeyT and ValueT are + // trivially destructible. + if constexpr (std::is_trivially_destructible_v<KeyT> && + std::is_trivially_destructible_v<ValueT>) + return; + if (getNumBuckets() == 0) // Nothing to do. return; - const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); + const KeyT EmptyKey = KeyInfoT::getEmptyKey(); + const KeyT TombstoneKey = KeyInfoT::getTombstoneKey(); for (BucketT &B : buckets()) { if (!KeyInfoT::isEqual(B.getFirst(), EmptyKey) && !KeyInfoT::isEqual(B.getFirst(), TombstoneKey)) @@ -366,12 +384,14 @@ protected: } void initEmpty() { + static_assert(std::is_base_of_v<DenseMapBase, DerivedT>, + "Must pass the derived type to this template!"); setNumEntries(0); setNumTombstones(0); assert((getNumBuckets() & (getNumBuckets() - 1)) == 0 && "# initial buckets must be a power of two!"); - const KeyT EmptyKey = getEmptyKey(); + const KeyT EmptyKey = KeyInfoT::getEmptyKey(); for (BucketT &B : buckets()) ::new (&B.getFirst()) KeyT(EmptyKey); } @@ -391,8 +411,8 @@ protected: initEmpty(); // Insert all the old elements. - const KeyT EmptyKey = getEmptyKey(); - const KeyT TombstoneKey = getTombstoneKey(); + const KeyT EmptyKey = KeyInfoT::getEmptyKey(); + const KeyT TombstoneKey = KeyInfoT::getTombstoneKey(); for (BucketT &B : OldBuckets) { if (!KeyInfoT::isEqual(B.getFirst(), EmptyKey) && !KeyInfoT::isEqual(B.getFirst(), TombstoneKey)) { @@ -412,9 +432,16 @@ protected: } } - template <typename OtherBaseT> - void copyFrom( - const DenseMapBase<OtherBaseT, KeyT, ValueT, KeyInfoT, BucketT> &other) { + void copyFrom(const DerivedT &other) { + this->destroyAll(); + derived().deallocateBuckets(); + setNumEntries(0); + setNumTombstones(0); + if (!derived().allocateBuckets(other.getNumBuckets())) { + // The bucket list is empty. No work to do. + return; + } + assert(&other != this); assert(getNumBuckets() == other.getNumBuckets()); @@ -429,8 +456,8 @@ protected: memcpy(reinterpret_cast<void *>(Buckets), OtherBuckets, NumBuckets * sizeof(BucketT)); } else { - const KeyT EmptyKey = getEmptyKey(); - const KeyT TombstoneKey = getTombstoneKey(); + const KeyT EmptyKey = KeyInfoT::getEmptyKey(); + const KeyT TombstoneKey = KeyInfoT::getTombstoneKey(); for (size_t I = 0; I < NumBuckets; ++I) { ::new (&Buckets[I].getFirst()) KeyT(OtherBuckets[I].getFirst()); if (!KeyInfoT::isEqual(Buckets[I].getFirst(), EmptyKey) && @@ -440,19 +467,6 @@ protected: } } - template <typename LookupKeyT> - static unsigned getHashValue(const LookupKeyT &Val) { - return KeyInfoT::getHashValue(Val); - } - - static const KeyT getEmptyKey() { - static_assert(std::is_base_of_v<DenseMapBase, DerivedT>, - "Must pass the derived type to this template!"); - return KeyInfoT::getEmptyKey(); - } - - static const KeyT getTombstoneKey() { return KeyInfoT::getTombstoneKey(); } - private: DerivedT &derived() { return *static_cast<DerivedT *>(this); } const DerivedT &derived() const { @@ -526,8 +540,6 @@ private: void grow(unsigned AtLeast) { derived().grow(AtLeast); } - void shrink_and_clear() { derived().shrink_and_clear(); } - template <typename LookupKeyT> BucketT *findBucketForInsertion(const LookupKeyT &Lookup, BucketT *TheBucket) { @@ -560,7 +572,7 @@ private: incrementNumEntries(); // If we are writing over a tombstone, remember this. - const KeyT EmptyKey = getEmptyKey(); + const KeyT EmptyKey = KeyInfoT::getEmptyKey(); if (!KeyInfoT::isEqual(TheBucket->getFirst(), EmptyKey)) decrementNumTombstones(); @@ -574,8 +586,8 @@ private: if (NumBuckets == 0) return nullptr; - const KeyT EmptyKey = getEmptyKey(); - unsigned BucketNo = getHashValue(Val) & (NumBuckets - 1); + const KeyT EmptyKey = KeyInfoT::getEmptyKey(); + unsigned BucketNo = KeyInfoT::getHashValue(Val) & (NumBuckets - 1); unsigned ProbeAmt = 1; while (true) { const BucketT *Bucket = BucketsPtr + BucketNo; @@ -612,13 +624,13 @@ private: // FoundTombstone - Keep track of whether we find a tombstone while probing. BucketT *FoundTombstone = nullptr; - const KeyT EmptyKey = getEmptyKey(); - const KeyT TombstoneKey = getTombstoneKey(); + const KeyT EmptyKey = KeyInfoT::getEmptyKey(); + const KeyT TombstoneKey = KeyInfoT::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 BucketNo = KeyInfoT::getHashValue(Val) & (NumBuckets - 1); unsigned ProbeAmt = 1; while (true) { BucketT *ThisBucket = BucketsPtr + BucketNo; @@ -719,7 +731,7 @@ public: DenseMap(const DenseMap &other) : BaseT() { init(0); - copyFrom(other); + this->copyFrom(other); } DenseMap(DenseMap &&other) : BaseT() { @@ -755,7 +767,7 @@ public: DenseMap &operator=(const DenseMap &other) { if (&other != this) - copyFrom(other); + this->copyFrom(other); return *this; } @@ -767,56 +779,6 @@ public: return *this; } - void copyFrom(const DenseMap &other) { - this->destroyAll(); - deallocateBuckets(); - if (allocateBuckets(other.NumBuckets)) { - this->BaseT::copyFrom(other); - } else { - NumEntries = 0; - NumTombstones = 0; - } - } - - void grow(unsigned AtLeast) { - unsigned OldNumBuckets = NumBuckets; - BucketT *OldBuckets = Buckets; - - allocateBuckets(std::max<unsigned>( - 64, static_cast<unsigned>(NextPowerOf2(AtLeast - 1)))); - assert(Buckets); - if (!OldBuckets) { - this->BaseT::initEmpty(); - return; - } - - this->moveFromOldBuckets( - llvm::make_range(OldBuckets, OldBuckets + OldNumBuckets)); - - // Free the old table. - deallocate_buffer(OldBuckets, sizeof(BucketT) * OldNumBuckets, - alignof(BucketT)); - } - - void shrink_and_clear() { - unsigned OldNumBuckets = NumBuckets; - unsigned OldNumEntries = NumEntries; - this->destroyAll(); - - // 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; - } - - deallocate_buffer(Buckets, sizeof(BucketT) * OldNumBuckets, - alignof(BucketT)); - init(NewNumBuckets); - } - private: unsigned getNumEntries() const { return NumEntries; } @@ -855,6 +817,38 @@ private: NumTombstones = 0; } } + + void grow(unsigned AtLeast) { + unsigned OldNumBuckets = NumBuckets; + BucketT *OldBuckets = Buckets; + + allocateBuckets(std::max<unsigned>( + 64, static_cast<unsigned>(NextPowerOf2(AtLeast - 1)))); + assert(Buckets); + if (!OldBuckets) { + this->BaseT::initEmpty(); + return; + } + + this->moveFromOldBuckets( + llvm::make_range(OldBuckets, OldBuckets + OldNumBuckets)); + + // Free the old table. + deallocate_buffer(OldBuckets, sizeof(BucketT) * OldNumBuckets, + alignof(BucketT)); + } + + // Plan how to shrink the bucket table. Return: + // - {false, 0} to reuse the existing bucket table + // - {true, N} to reallocate a bucket table with N entries + std::pair<bool, unsigned> planShrinkAndClear() const { + unsigned NewNumBuckets = 0; + if (NumEntries) + NewNumBuckets = std::max(64u, 1u << (Log2_32_Ceil(NumEntries) + 1)); + if (NewNumBuckets == NumBuckets) + return {false, 0}; // Reuse. + return {true, NewNumBuckets}; // Reallocate. + } }; template <typename KeyT, typename ValueT, unsigned InlineBuckets = 4, @@ -896,7 +890,7 @@ public: SmallDenseMap(const SmallDenseMap &other) : BaseT() { init(0); - copyFrom(other); + this->copyFrom(other); } SmallDenseMap(SmallDenseMap &&other) : BaseT() { @@ -928,8 +922,8 @@ public: NumEntries = TmpNumEntries; std::swap(NumTombstones, RHS.NumTombstones); - const KeyT EmptyKey = this->getEmptyKey(); - const KeyT TombstoneKey = this->getTombstoneKey(); + const KeyT EmptyKey = KeyInfoT::getEmptyKey(); + const KeyT TombstoneKey = KeyInfoT::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 @@ -995,7 +989,7 @@ public: SmallDenseMap &operator=(const SmallDenseMap &other) { if (&other != this) - copyFrom(other); + this->copyFrom(other); return *this; } @@ -1007,86 +1001,6 @@ public: return *this; } - void copyFrom(const SmallDenseMap &other) { - this->destroyAll(); - deallocateBuckets(); - allocateBuckets(other.getNumBuckets()); - this->BaseT::copyFrom(other); - } - - void init(unsigned InitNumEntries) { - auto InitBuckets = BaseT::getMinBucketToReserveForEntries(InitNumEntries); - allocateBuckets(InitBuckets); - this->BaseT::initEmpty(); - } - - void grow(unsigned AtLeast) { - if (AtLeast > InlineBuckets) - AtLeast = std::max<unsigned>(64, NextPowerOf2(AtLeast - 1)); - - if (Small) { - // First move the inline buckets into a temporary storage. - AlignedCharArrayUnion<BucketT[InlineBuckets]> TmpStorage; - BucketT *TmpBegin = reinterpret_cast<BucketT *>(&TmpStorage); - 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 &B : inlineBuckets()) { - if (!KeyInfoT::isEqual(B.getFirst(), EmptyKey) && - !KeyInfoT::isEqual(B.getFirst(), TombstoneKey)) { - assert(size_t(TmpEnd - TmpBegin) < InlineBuckets && - "Too many inline buckets!"); - ::new (&TmpEnd->getFirst()) KeyT(std::move(B.getFirst())); - ::new (&TmpEnd->getSecond()) ValueT(std::move(B.getSecond())); - ++TmpEnd; - B.getSecond().~ValueT(); - } - B.getFirst().~KeyT(); - } - - // AtLeast == InlineBuckets can happen if there are many tombstones, - // and grow() is used to remove them. Usually we always switch to the - // large rep here. - allocateBuckets(AtLeast); - this->moveFromOldBuckets(llvm::make_range(TmpBegin, TmpEnd)); - return; - } - - LargeRep OldRep = std::move(*getLargeRep()); - getLargeRep()->~LargeRep(); - allocateBuckets(AtLeast); - - this->moveFromOldBuckets(OldRep.buckets()); - - // Free the old table. - deallocate_buffer(OldRep.Buckets, sizeof(BucketT) * OldRep.NumBuckets, - alignof(BucketT)); - } - - 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; - } - - deallocateBuckets(); - init(NewNumBuckets); - } - private: unsigned getNumEntries() const { return NumEntries; } @@ -1152,7 +1066,7 @@ private: getLargeRep()->~LargeRep(); } - void allocateBuckets(unsigned Num) { + bool allocateBuckets(unsigned Num) { if (Num <= InlineBuckets) { Small = true; } else { @@ -1161,6 +1075,76 @@ private: allocate_buffer(sizeof(BucketT) * Num, alignof(BucketT))); new (getLargeRep()) LargeRep{NewBuckets, Num}; } + return true; + } + + void init(unsigned InitNumEntries) { + auto InitBuckets = BaseT::getMinBucketToReserveForEntries(InitNumEntries); + allocateBuckets(InitBuckets); + this->BaseT::initEmpty(); + } + + void grow(unsigned AtLeast) { + if (AtLeast > InlineBuckets) + AtLeast = std::max<unsigned>(64, NextPowerOf2(AtLeast - 1)); + + if (Small) { + // First move the inline buckets into a temporary storage. + AlignedCharArrayUnion<BucketT[InlineBuckets]> TmpStorage; + BucketT *TmpBegin = reinterpret_cast<BucketT *>(&TmpStorage); + 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 = KeyInfoT::getEmptyKey(); + const KeyT TombstoneKey = KeyInfoT::getTombstoneKey(); + for (BucketT &B : inlineBuckets()) { + if (!KeyInfoT::isEqual(B.getFirst(), EmptyKey) && + !KeyInfoT::isEqual(B.getFirst(), TombstoneKey)) { + assert(size_t(TmpEnd - TmpBegin) < InlineBuckets && + "Too many inline buckets!"); + ::new (&TmpEnd->getFirst()) KeyT(std::move(B.getFirst())); + ::new (&TmpEnd->getSecond()) ValueT(std::move(B.getSecond())); + ++TmpEnd; + B.getSecond().~ValueT(); + } + B.getFirst().~KeyT(); + } + + // AtLeast == InlineBuckets can happen if there are many tombstones, + // and grow() is used to remove them. Usually we always switch to the + // large rep here. + allocateBuckets(AtLeast); + this->moveFromOldBuckets(llvm::make_range(TmpBegin, TmpEnd)); + return; + } + + LargeRep OldRep = std::move(*getLargeRep()); + getLargeRep()->~LargeRep(); + allocateBuckets(AtLeast); + + this->moveFromOldBuckets(OldRep.buckets()); + + // Free the old table. + deallocate_buffer(OldRep.Buckets, sizeof(BucketT) * OldRep.NumBuckets, + alignof(BucketT)); + } + + // Plan how to shrink the bucket table. Return: + // - {false, 0} to reuse the existing bucket table + // - {true, N} to reallocate a bucket table with N entries + std::pair<bool, unsigned> planShrinkAndClear() const { + unsigned NewNumBuckets = 0; + if (!this->empty()) { + NewNumBuckets = 1u << (Log2_32_Ceil(this->size()) + 1); + if (NewNumBuckets > InlineBuckets) + NewNumBuckets = std::max(64u, NewNumBuckets); + } + bool Reuse = Small ? NewNumBuckets <= InlineBuckets + : NewNumBuckets == getLargeRep()->NumBuckets; + if (Reuse) + return {false, 0}; // Reuse. + return {true, NewNumBuckets}; // Reallocate. } }; diff --git a/llvm/include/llvm/ADT/IndexedMap.h b/llvm/include/llvm/ADT/IndexedMap.h index 55935a7..02193c7 100644 --- a/llvm/include/llvm/ADT/IndexedMap.h +++ b/llvm/include/llvm/ADT/IndexedMap.h @@ -43,40 +43,40 @@ class IndexedMap { // is trivially copyable. using StorageT = SmallVector<T, 0>; - StorageT storage_; - T nullVal_ = T(); - ToIndexT toIndex_; + StorageT Storage; + T NullVal = T(); + ToIndexT ToIndex; public: IndexedMap() = default; - explicit IndexedMap(const T &val) : nullVal_(val) {} + explicit IndexedMap(const T &Val) : NullVal(Val) {} - typename StorageT::reference operator[](IndexT n) { - assert(toIndex_(n) < storage_.size() && "index out of bounds!"); - return storage_[toIndex_(n)]; + typename StorageT::reference operator[](IndexT N) { + assert(ToIndex(N) < Storage.size() && "index out of bounds!"); + return Storage[ToIndex(N)]; } - typename StorageT::const_reference operator[](IndexT n) const { - assert(toIndex_(n) < storage_.size() && "index out of bounds!"); - return storage_[toIndex_(n)]; + typename StorageT::const_reference operator[](IndexT N) const { + assert(ToIndex(N) < Storage.size() && "index out of bounds!"); + return Storage[ToIndex(N)]; } - void reserve(typename StorageT::size_type s) { storage_.reserve(s); } + void reserve(typename StorageT::size_type S) { Storage.reserve(S); } - void resize(typename StorageT::size_type s) { storage_.resize(s, nullVal_); } + void resize(typename StorageT::size_type S) { Storage.resize(S, NullVal); } - void clear() { storage_.clear(); } + void clear() { Storage.clear(); } - void grow(IndexT n) { - unsigned NewSize = toIndex_(n) + 1; - if (NewSize > storage_.size()) + void grow(IndexT N) { + unsigned NewSize = ToIndex(N) + 1; + if (NewSize > Storage.size()) resize(NewSize); } - bool inBounds(IndexT n) const { return toIndex_(n) < storage_.size(); } + bool inBounds(IndexT N) const { return ToIndex(N) < Storage.size(); } - typename StorageT::size_type size() const { return storage_.size(); } + typename StorageT::size_type size() const { return Storage.size(); } }; } // namespace llvm diff --git a/llvm/include/llvm/ADT/RadixTree.h b/llvm/include/llvm/ADT/RadixTree.h new file mode 100644 index 0000000..9e2ab97 --- /dev/null +++ b/llvm/include/llvm/ADT/RadixTree.h @@ -0,0 +1,350 @@ +//===-- llvm/ADT/RadixTree.h - Radix Tree implementation --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +//===----------------------------------------------------------------------===// +// +// This file implements a Radix Tree. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_RADIXTREE_H +#define LLVM_ADT_RADIXTREE_H + +#include "llvm/ADT/ADL.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/iterator.h" +#include "llvm/ADT/iterator_range.h" +#include <cassert> +#include <cstddef> +#include <iterator> +#include <list> +#include <utility> +#include <vector> + +namespace llvm { + +/// \brief A Radix Tree implementation. +/// +/// A Radix Tree (also known as a compact prefix tree or radix trie) is a +/// data structure that stores a dynamic set or associative array where keys +/// are strings and values are associated with these keys. Unlike a regular +/// trie, the edges of a radix tree can be labeled with sequences of characters +/// as well as single characters. This makes radix trees more efficient for +/// storing sparse data sets, where many nodes in a regular trie would have +/// only one child. +/// +/// This implementation supports arbitrary key types that can be iterated over +/// (e.g., `std::string`, `std::vector<char>`, `ArrayRef<char>`). The key type +/// must provide `begin()` and `end()` for iteration. +/// +/// The tree stores `std::pair<const KeyType, T>` as its value type. +/// +/// Example usage: +/// \code +/// llvm::RadixTree<StringRef, int> Tree; +/// Tree.emplace("apple", 1); +/// Tree.emplace("grapefruit", 2); +/// Tree.emplace("grape", 3); +/// +/// // Find prefixes +/// for (const auto &[Key, Value] : Tree.find_prefixes("grapefruit juice")) { +/// // pair will be {"grape", 3} +/// // pair will be {"grapefruit", 2} +/// llvm::outs() << Key << ": " << Value << "\n"; +/// } +/// +/// // Iterate over all elements +/// for (const auto &[Key, Value] : Tree) +/// llvm::outs() << Key << ": " << Value << "\n"; +/// \endcode +/// +/// \note +/// The `RadixTree` takes ownership of the `KeyType` and `T` objects +/// inserted into it. When an element is removed or the tree is destroyed, +/// these objects will be destructed. +/// However, if `KeyType` is a reference-like type, e.g., StringRef or range, +/// the user must guarantee that the referenced data has a lifetime longer than +/// the tree. +template <typename KeyType, typename T> class RadixTree { +public: + using key_type = KeyType; + using mapped_type = T; + using value_type = std::pair<const KeyType, mapped_type>; + +private: + using KeyConstIteratorType = + decltype(adl_begin(std::declval<const key_type &>())); + using KeyConstIteratorRangeType = iterator_range<KeyConstIteratorType>; + using KeyValueType = + remove_cvref_t<decltype(*adl_begin(std::declval<key_type &>()))>; + using ContainerType = std::list<value_type>; + + /// Represents an internal node in the Radix Tree. + struct Node { + KeyConstIteratorRangeType Key{KeyConstIteratorType{}, + KeyConstIteratorType{}}; + std::vector<Node> Children; + + /// An iterator to the value associated with this node. + /// + /// If this node does not have a value (i.e., it's an internal node that + /// only serves as a path to other values), this iterator will be equal + /// to default constructed `ContainerType::iterator()`. + typename ContainerType::iterator Value; + + /// The first character of the Key. Used for fast child lookup. + KeyValueType KeyFront; + + Node() = default; + Node(const KeyConstIteratorRangeType &Key) + : Key(Key), KeyFront(*Key.begin()) { + assert(!Key.empty()); + } + + Node(Node &&) = default; + Node &operator=(Node &&) = default; + + Node(const Node &) = delete; + Node &operator=(const Node &) = delete; + + const Node *findChild(const KeyConstIteratorRangeType &Key) const { + if (Key.empty()) + return nullptr; + for (const Node &Child : Children) { + assert(!Child.Key.empty()); // Only root can be empty. + if (Child.KeyFront == *Key.begin()) + return &Child; + } + return nullptr; + } + + Node *findChild(const KeyConstIteratorRangeType &Query) { + const Node *This = this; + return const_cast<Node *>(This->findChild(Query)); + } + + size_t countNodes() const { + size_t R = 1; + for (const Node &C : Children) + R += C.countNodes(); + return R; + } + + /// + /// Splits the current node into two. + /// + /// This function is used when a new key needs to be inserted that shares + /// a common prefix with the current node's key, but then diverges. + /// The current `Key` is truncated to the common prefix, and a new child + /// node is created for the remainder of the original node's `Key`. + /// + /// \param SplitPoint An iterator pointing to the character in the current + /// `Key` where the split should occur. + void split(KeyConstIteratorType SplitPoint) { + Node Child(make_range(SplitPoint, Key.end())); + Key = make_range(Key.begin(), SplitPoint); + + Children.swap(Child.Children); + std::swap(Value, Child.Value); + + Children.emplace_back(std::move(Child)); + } + }; + + /// Root always corresponds to the empty key, which is the shortest possible + /// prefix for everything. + Node Root; + ContainerType KeyValuePairs; + + /// Finds or creates a new tail or leaf node corresponding to the `Key`. + Node &findOrCreate(KeyConstIteratorRangeType Key) { + Node *Curr = &Root; + if (Key.empty()) + return *Curr; + + for (;;) { + auto [I1, I2] = llvm::mismatch(Key, Curr->Key); + Key = make_range(I1, Key.end()); + + if (I2 != Curr->Key.end()) { + // Match is partial. Either query is too short, or there is mismatching + // character. Split either way, and put new node in between of the + // current and its children. + Curr->split(I2); + + // Split was caused by mismatch, so `findChild` would fail. + break; + } + + Node *Child = Curr->findChild(Key); + if (!Child) + break; + + // Move to child with the same first character. + Curr = Child; + } + + if (Key.empty()) { + // The current node completely matches the key, return it. + return *Curr; + } + + // `Key` is a suffix of original `Key` unmatched by path from the `Root` to + // the `Curr`, and we have no candidate in the children to match more. + // Create a new one. + return Curr->Children.emplace_back(Key); + } + + /// + /// An iterator for traversing prefixes search results. + /// + /// This iterator is used by `find_prefixes` to traverse the tree and find + /// elements that are prefixes to the given key. It's a forward iterator. + /// + /// \tparam MappedType The type of the value pointed to by the iterator. + /// This will be `value_type` for non-const iterators + /// and `const value_type` for const iterators. + template <typename MappedType> + class IteratorImpl + : public iterator_facade_base<IteratorImpl<MappedType>, + std::forward_iterator_tag, MappedType> { + const Node *Curr = nullptr; + KeyConstIteratorRangeType Query{KeyConstIteratorType{}, + KeyConstIteratorType{}}; + + void findNextValid() { + while (Curr && Curr->Value == typename ContainerType::iterator()) + advance(); + } + + void advance() { + assert(Curr); + if (Query.empty()) { + Curr = nullptr; + return; + } + + Curr = Curr->findChild(Query); + if (!Curr) { + Curr = nullptr; + return; + } + + auto [I1, I2] = llvm::mismatch(Query, Curr->Key); + if (I2 != Curr->Key.end()) { + Curr = nullptr; + return; + } + Query = make_range(I1, Query.end()); + } + + friend class RadixTree; + IteratorImpl(const Node *C, const KeyConstIteratorRangeType &Q) + : Curr(C), Query(Q) { + findNextValid(); + } + + public: + IteratorImpl() = default; + + MappedType &operator*() const { return *Curr->Value; } + + IteratorImpl &operator++() { + advance(); + findNextValid(); + return *this; + } + + bool operator==(const IteratorImpl &Other) const { + return Curr == Other.Curr; + } + }; + +public: + RadixTree() = default; + RadixTree(RadixTree &&) = default; + RadixTree &operator=(RadixTree &&) = default; + + using prefix_iterator = IteratorImpl<value_type>; + using const_prefix_iterator = IteratorImpl<const value_type>; + + using iterator = typename ContainerType::iterator; + using const_iterator = typename ContainerType::const_iterator; + + /// Returns true if the tree is empty. + bool empty() const { return KeyValuePairs.empty(); } + + /// Returns the number of elements in the tree. + size_t size() const { return KeyValuePairs.size(); } + + /// Returns the number of nodes in the tree. + /// + /// This function counts all internal nodes in the tree. It can be useful for + /// understanding the memory footprint or complexity of the tree structure. + size_t countNodes() const { return Root.countNodes(); } + + /// Returns an iterator to the first element. + iterator begin() { return KeyValuePairs.begin(); } + const_iterator begin() const { return KeyValuePairs.begin(); } + + /// Returns an iterator to the end of the tree. + iterator end() { return KeyValuePairs.end(); } + const_iterator end() const { return KeyValuePairs.end(); } + + /// Constructs and inserts a new element into the tree. + /// + /// This function constructs an element in place within the tree. If an + /// element with the same key already exists, the insertion fails and the + /// function returns an iterator to the existing element along with `false`. + /// Otherwise, the new element is inserted and the function returns an + /// iterator to the new element along with `true`. + /// + /// \param Key The key of the element to construct. + /// \param Args Arguments to forward to the constructor of the mapped_type. + /// \return A pair consisting of an iterator to the inserted element (or to + /// the element that prevented insertion) and a boolean value + /// indicating whether the insertion took place. + template <typename... Ts> + std::pair<iterator, bool> emplace(key_type &&Key, Ts &&...Args) { + // We want to make new `Node` to refer key in the container, not the one + // from the argument. + // FIXME: Determine that we need a new node, before expanding + // `KeyValuePairs`. + const value_type &NewValue = KeyValuePairs.emplace_front( + std::move(Key), T(std::forward<Ts>(Args)...)); + Node &Node = findOrCreate(NewValue.first); + bool HasValue = Node.Value != typename ContainerType::iterator(); + if (!HasValue) + Node.Value = KeyValuePairs.begin(); + else + KeyValuePairs.pop_front(); + return {Node.Value, !HasValue}; + } + + /// + /// Finds all elements whose keys are prefixes of the given `Key`. + /// + /// This function returns an iterator range over all elements in the tree + /// whose keys are prefixes of the provided `Key`. For example, if the tree + /// contains "abcde", "abc", "abcdefgh", and `Key` is "abcde", this function + /// would return iterators to "abcde" and "abc". + /// + /// \param Key The key to search for prefixes of. + /// \return An `iterator_range` of `const_prefix_iterator`s, allowing + /// iteration over the found prefix elements. + /// \note The returned iterators reference the `Key` provided by the caller. + /// The caller must ensure that `Key` remains valid for the lifetime + /// of the iterators. + iterator_range<const_prefix_iterator> + find_prefixes(const key_type &Key) const { + return iterator_range<const_prefix_iterator>{ + const_prefix_iterator(&Root, KeyConstIteratorRangeType(Key)), + const_prefix_iterator{}}; + } +}; + +} // namespace llvm + +#endif // LLVM_ADT_RADIXTREE_H diff --git a/llvm/include/llvm/ADT/STLForwardCompat.h b/llvm/include/llvm/ADT/STLForwardCompat.h index 9c81981..e02694f 100644 --- a/llvm/include/llvm/ADT/STLForwardCompat.h +++ b/llvm/include/llvm/ADT/STLForwardCompat.h @@ -125,7 +125,7 @@ struct detector<std::void_t<Op<Args...>>, Op, Args...> { template <template <class...> class Op, class... Args> using is_detected = typename detail::detector<void, Op, Args...>::value_t; -struct identity_cxx20 // NOLINT(readability-identifier-naming) +struct identity // NOLINT(readability-identifier-naming) { using is_transparent = void; diff --git a/llvm/include/llvm/ADT/ScopedHashTable.h b/llvm/include/llvm/ADT/ScopedHashTable.h index 78d4df7..97d1546 100644 --- a/llvm/include/llvm/ADT/ScopedHashTable.h +++ b/llvm/include/llvm/ADT/ScopedHashTable.h @@ -151,8 +151,8 @@ class ScopedHashTable : detail::AllocatorHolder<AllocatorTy> { using AllocTy = detail::AllocatorHolder<AllocatorTy>; public: - /// ScopeTy - This is a helpful typedef that allows clients to get easy access - /// to the name of the scope for this hash table. + /// ScopeTy - A type alias for easy access to the name of the scope for this + /// hash table. using ScopeTy = ScopedHashTableScope<K, V, KInfo, AllocatorTy>; using size_type = unsigned; diff --git a/llvm/include/llvm/ADT/SparseMultiSet.h b/llvm/include/llvm/ADT/SparseMultiSet.h index 5e4e170..59de4cf 100644 --- a/llvm/include/llvm/ADT/SparseMultiSet.h +++ b/llvm/include/llvm/ADT/SparseMultiSet.h @@ -82,7 +82,7 @@ namespace llvm { /// @tparam SparseT An unsigned integer type. See above. /// template <typename ValueT, typename KeyT = unsigned, - typename KeyFunctorT = identity_cxx20, typename SparseT = uint8_t> + typename KeyFunctorT = identity, typename SparseT = uint8_t> class SparseMultiSet { static_assert(std::is_unsigned_v<SparseT>, "SparseT must be an unsigned integer type"); diff --git a/llvm/include/llvm/ADT/SparseSet.h b/llvm/include/llvm/ADT/SparseSet.h index 4697de09..41fd501 100644 --- a/llvm/include/llvm/ADT/SparseSet.h +++ b/llvm/include/llvm/ADT/SparseSet.h @@ -59,24 +59,20 @@ template <typename ValueT> struct SparseSetValTraits { } }; -/// SparseSetValFunctor - Helper class for selecting SparseSetValTraits. The -/// generic implementation handles ValueT classes which either provide -/// getSparseSetIndex() or specialize SparseSetValTraits<>. +/// SparseSetValFunctor - Helper class for getting a value's index. /// +/// In the generic case, this is done via SparseSetValTraits. When the value +/// type is the same as the key type, the KeyFunctor is used directly. template <typename KeyT, typename ValueT, typename KeyFunctorT> struct SparseSetValFunctor { unsigned operator()(const ValueT &Val) const { - return SparseSetValTraits<ValueT>::getValIndex(Val); + if constexpr (std::is_same_v<KeyT, ValueT>) + return KeyFunctorT()(Val); + else + return SparseSetValTraits<ValueT>::getValIndex(Val); } }; -/// 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 implementation for objects that can be identified by /// small unsigned keys. /// @@ -117,7 +113,7 @@ struct SparseSetValFunctor<KeyT, KeyT, KeyFunctorT> { /// @tparam SparseT An unsigned integer type. See above. /// template <typename ValueT, typename KeyT = unsigned, - typename KeyFunctorT = identity_cxx20, typename SparseT = uint8_t> + typename KeyFunctorT = identity, typename SparseT = uint8_t> class SparseSet { static_assert(std::is_unsigned_v<SparseT>, "SparseT must be an unsigned integer type"); diff --git a/llvm/include/llvm/ADT/StringSwitch.h b/llvm/include/llvm/ADT/StringSwitch.h index 2262b11..98685de 100644 --- a/llvm/include/llvm/ADT/StringSwitch.h +++ b/llvm/include/llvm/ADT/StringSwitch.h @@ -93,6 +93,7 @@ public: return CasesImpl({S0, S1}, Value); } + [[deprecated("Pass cases in std::initializer_list instead")]] StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, T Value) { return CasesImpl({S0, S1, S2}, Value); @@ -176,6 +177,7 @@ public: return CasesLowerImpl({S0, S1}, Value); } + [[deprecated("Pass cases in std::initializer_list instead")]] StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2, T Value) { return CasesLowerImpl({S0, S1, S2}, Value); diff --git a/llvm/include/llvm/Analysis/InstSimplifyFolder.h b/llvm/include/llvm/Analysis/InstSimplifyFolder.h index 58793ed..2832beb 100644 --- a/llvm/include/llvm/Analysis/InstSimplifyFolder.h +++ b/llvm/include/llvm/Analysis/InstSimplifyFolder.h @@ -120,7 +120,7 @@ public: } Value *FoldBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS, Type *Ty, - Instruction *FMFSource) const override { + Instruction *FMFSource = nullptr) const override { return simplifyBinaryIntrinsic(ID, Ty, LHS, RHS, SQ, dyn_cast_if_present<CallBase>(FMFSource)); } diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h index 93aff35..b0601eb 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h @@ -276,7 +276,6 @@ public: SmallVector<Register> &Ops) const; /// Replace \p MI with a build_vector. - bool matchCombineShuffleToBuildVector(MachineInstr &MI) const; void applyCombineShuffleToBuildVector(MachineInstr &MI) const; /// Try to combine G_SHUFFLE_VECTOR into G_CONCAT_VECTORS. @@ -295,8 +294,6 @@ public: /// Replace \p MI with a concat_vectors with \p Ops. void applyCombineShuffleVector(MachineInstr &MI, const ArrayRef<Register> Ops) const; - bool matchShuffleToExtract(MachineInstr &MI) const; - void applyShuffleToExtract(MachineInstr &MI) const; /// Optimize memcpy intrinsics et al, e.g. constant len calls. /// /p MaxLen if non-zero specifies the max length of a mem libcall to inline. diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h index c0e426c..a458cbd 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h @@ -497,6 +497,7 @@ public: LLVM_ABI LegalizeResult lowerMinMax(MachineInstr &MI); LLVM_ABI LegalizeResult lowerFCopySign(MachineInstr &MI); LLVM_ABI LegalizeResult lowerFMinNumMaxNum(MachineInstr &MI); + LLVM_ABI LegalizeResult lowerFMinimumMaximum(MachineInstr &MI); LLVM_ABI LegalizeResult lowerFMad(MachineInstr &MI); LLVM_ABI LegalizeResult lowerIntrinsicRound(MachineInstr &MI); LLVM_ABI LegalizeResult lowerFFloor(MachineInstr &MI); diff --git a/llvm/include/llvm/CodeGen/Passes.h b/llvm/include/llvm/CodeGen/Passes.h index 9fddd47..a852555 100644 --- a/llvm/include/llvm/CodeGen/Passes.h +++ b/llvm/include/llvm/CodeGen/Passes.h @@ -610,14 +610,6 @@ LLVM_ABI ModulePass *createCheckDebugMachineModulePass(); /// caller saved registers with stack slots. LLVM_ABI extern char &FixupStatepointCallerSavedID; -/// The pass transforms load/store <256 x i32> to AMX load/store intrinsics -/// or split the data to two <128 x i32>. -LLVM_ABI FunctionPass *createX86LowerAMXTypePass(); - -/// The pass transforms amx intrinsics to scalar operation if the function has -/// optnone attribute or it is O0. -LLVM_ABI FunctionPass *createX86LowerAMXIntrinsicsPass(); - /// When learning an eviction policy, extract score(reward) information, /// otherwise this does nothing LLVM_ABI FunctionPass *createRegAllocScoringPass(); diff --git a/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h b/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h index 26d7080..ab0d7e3 100644 --- a/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h +++ b/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h @@ -89,7 +89,7 @@ namespace llvm { /// allocated once for the pass. It can be cleared in constant time and reused /// without any frees. using RegUnit2SUnitsMap = - SparseMultiSet<PhysRegSUOper, unsigned, identity_cxx20, uint16_t>; + SparseMultiSet<PhysRegSUOper, unsigned, identity, uint16_t>; /// Track local uses of virtual registers. These uses are gathered by the DAG /// builder and may be consulted by the scheduler to avoid iterating an entire diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h index 64a7563..d6ed3a8 100644 --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -2127,7 +2127,7 @@ public: /// performs validation and error handling, returns the function. Otherwise, /// returns nullptr. Must be previously inserted by insertSSPDeclarations. /// Should be used only when getIRStackGuard returns nullptr. - virtual Function *getSSPStackGuardCheck(const Module &M) const; + Function *getSSPStackGuardCheck(const Module &M) const; protected: Value *getDefaultSafeStackPointerLocation(IRBuilderBase &IRB, @@ -3576,6 +3576,10 @@ public: return nullptr; } + const RTLIB::RuntimeLibcallsInfo &getRuntimeLibcallsInfo() const { + return Libcalls; + } + void setLibcallImpl(RTLIB::Libcall Call, RTLIB::LibcallImpl Impl) { Libcalls.setLibcallImpl(Call, Impl); } @@ -3813,10 +3817,6 @@ private: /// The list of libcalls that the target will use. RTLIB::RuntimeLibcallsInfo Libcalls; - /// The ISD::CondCode that should be used to test the result of each of the - /// comparison libcall against zero. - ISD::CondCode CmpLibcallCCs[RTLIB::UNKNOWN_LIBCALL]; - /// The bits of IndexedModeActions used to store the legalisation actions /// We store the data as | ML | MS | L | S | each taking 4 bits. enum IndexedModeActionsBits { diff --git a/llvm/include/llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h b/llvm/include/llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h index 3a36863..5a46207 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h +++ b/llvm/include/llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h @@ -34,7 +34,7 @@ class LLVM_ABI AppendingTypeTableBuilder : public TypeCollection { public: explicit AppendingTypeTableBuilder(BumpPtrAllocator &Storage); - ~AppendingTypeTableBuilder(); + ~AppendingTypeTableBuilder() override; // TypeCollection overrides std::optional<TypeIndex> getFirst() override; diff --git a/llvm/include/llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h b/llvm/include/llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h index a587b3e..93e1c99 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h +++ b/llvm/include/llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h @@ -47,7 +47,7 @@ class LLVM_ABI GlobalTypeTableBuilder : public TypeCollection { public: explicit GlobalTypeTableBuilder(BumpPtrAllocator &Storage); - ~GlobalTypeTableBuilder(); + ~GlobalTypeTableBuilder() override; // TypeCollection overrides std::optional<TypeIndex> getFirst() override; diff --git a/llvm/include/llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h b/llvm/include/llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h index 7302784..b9b2669 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h +++ b/llvm/include/llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h @@ -43,7 +43,7 @@ class LLVM_ABI MergingTypeTableBuilder : public TypeCollection { public: explicit MergingTypeTableBuilder(BumpPtrAllocator &Storage); - ~MergingTypeTableBuilder(); + ~MergingTypeTableBuilder() override; // TypeCollection overrides std::optional<TypeIndex> getFirst() override; diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h index 547d92c..451c438 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h @@ -102,9 +102,7 @@ public: using attr_iterator_range = iterator_range<AttributeSpecVector::const_iterator>; - attr_iterator_range attributes() const { - return attr_iterator_range(AttributeSpecs.begin(), AttributeSpecs.end()); - } + attr_iterator_range attributes() const { return AttributeSpecs; } dwarf::Form getFormByIndex(uint32_t idx) const { assert(idx < AttributeSpecs.size()); diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h index 6518991..c1d9be7 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h @@ -226,9 +226,7 @@ public: /// DWARF Frame entries accessors iterator begin() const { return Entries.begin(); } iterator end() const { return Entries.end(); } - iterator_range<iterator> entries() const { - return iterator_range<iterator>(Entries.begin(), Entries.end()); - } + iterator_range<iterator> entries() const { return Entries; } uint64_t getEHFrameAddress() const { return EHFrameAddress; } }; diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h index 964ff8e..7f9bf12 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -563,7 +563,7 @@ public: die_iterator_range dies() { extractDIEsIfNeeded(false); - return die_iterator_range(DieArray.begin(), DieArray.end()); + return DieArray; } virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts) = 0; diff --git a/llvm/include/llvm/DebugInfo/GSYM/GsymContext.h b/llvm/include/llvm/DebugInfo/GSYM/GsymContext.h index 07d599c..e3e9b2b 100644 --- a/llvm/include/llvm/DebugInfo/GSYM/GsymContext.h +++ b/llvm/include/llvm/DebugInfo/GSYM/GsymContext.h @@ -30,7 +30,7 @@ class GsymReader; class GsymContext : public DIContext { public: GsymContext(std::unique_ptr<GsymReader> Reader); - ~GsymContext(); + ~GsymContext() override; GsymContext(GsymContext &) = delete; GsymContext &operator=(GsymContext &) = delete; diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h index 0e7be45..34bace8 100644 --- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h +++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h @@ -143,7 +143,7 @@ public: VirtualityCode(0) {} LVElement(const LVElement &) = delete; LVElement &operator=(const LVElement &) = delete; - virtual ~LVElement() = default; + ~LVElement() override = default; LVSubclassID getSubclassID() const { return SubclassID; } diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVLine.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVLine.h index 3618ce7..dd17f76 100644 --- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVLine.h +++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVLine.h @@ -53,7 +53,7 @@ public: } LVLine(const LVLine &) = delete; LVLine &operator=(const LVLine &) = delete; - virtual ~LVLine() = default; + ~LVLine() override = default; static bool classof(const LVElement *Element) { return Element->getSubclassID() == LVSubclassID::LV_LINE; @@ -117,7 +117,7 @@ public: LVLineDebug() : LVLine() { setIsLineDebug(); } LVLineDebug(const LVLineDebug &) = delete; LVLineDebug &operator=(const LVLineDebug &) = delete; - ~LVLineDebug() = default; + ~LVLineDebug() override = default; // Additional line information. It includes attributes that describes // states in the machine instructions (basic block, end prologue, etc). @@ -142,7 +142,7 @@ public: LVLineAssembler() : LVLine() { setIsLineAssembler(); } LVLineAssembler(const LVLineAssembler &) = delete; LVLineAssembler &operator=(const LVLineAssembler &) = delete; - ~LVLineAssembler() = default; + ~LVLineAssembler() override = default; // Print blanks as the line number. std::string noLineAsString(bool ShowZero) const override { diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVLocation.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVLocation.h index 0718e33..090af54 100644 --- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVLocation.h +++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVLocation.h @@ -100,7 +100,7 @@ public: LVLocation() : LVObject() { setIsLocation(); } LVLocation(const LVLocation &) = delete; LVLocation &operator=(const LVLocation &) = delete; - virtual ~LVLocation() = default; + ~LVLocation() override = default; PROPERTY(Property, IsAddressRange); PROPERTY(Property, IsBaseClassOffset); @@ -171,7 +171,7 @@ public: LVLocationSymbol() : LVLocation() {} LVLocationSymbol(const LVLocationSymbol &) = delete; LVLocationSymbol &operator=(const LVLocationSymbol &) = delete; - ~LVLocationSymbol() = default; + ~LVLocationSymbol() override = default; void addObject(LVAddress LowPC, LVAddress HighPC, LVUnsigned SectionOffset, uint64_t LocDescOffset) override; diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h index b5c8333..4fa6a9a 100644 --- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h +++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h @@ -62,7 +62,7 @@ public: LVRange() : LVObject(), RangesTree(Allocator) {} LVRange(const LVRange &) = delete; LVRange &operator=(const LVRange &) = delete; - ~LVRange() = default; + ~LVRange() override = default; void addEntry(LVScope *Scope, LVAddress LowerAddress, LVAddress UpperAddress); void addEntry(LVScope *Scope); diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h index f4f3516..2e2619c 100644 --- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h +++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h @@ -153,7 +153,7 @@ public: } LVScope(const LVScope &) = delete; LVScope &operator=(const LVScope &) = delete; - virtual ~LVScope() = default; + ~LVScope() override = default; static bool classof(const LVElement *Element) { return Element->getSubclassID() == LVSubclassID::LV_SCOPE; @@ -349,7 +349,7 @@ public: LVScopeAggregate() : LVScope() {} LVScopeAggregate(const LVScopeAggregate &) = delete; LVScopeAggregate &operator=(const LVScopeAggregate &) = delete; - ~LVScopeAggregate() = default; + ~LVScopeAggregate() override = default; // DW_AT_specification, DW_AT_abstract_origin. LVScope *getReference() const override { return Reference; } @@ -387,7 +387,7 @@ public: } LVScopeAlias(const LVScopeAlias &) = delete; LVScopeAlias &operator=(const LVScopeAlias &) = delete; - ~LVScopeAlias() = default; + ~LVScopeAlias() override = default; // Returns true if current scope is logically equal to the given 'Scope'. bool equals(const LVScope *Scope) const override; @@ -401,7 +401,7 @@ public: LVScopeArray() : LVScope() { setIsArray(); } LVScopeArray(const LVScopeArray &) = delete; LVScopeArray &operator=(const LVScopeArray &) = delete; - ~LVScopeArray() = default; + ~LVScopeArray() override = default; void resolveExtra() override; @@ -513,7 +513,7 @@ public: } LVScopeCompileUnit(const LVScopeCompileUnit &) = delete; LVScopeCompileUnit &operator=(const LVScopeCompileUnit &) = delete; - ~LVScopeCompileUnit() = default; + ~LVScopeCompileUnit() override = default; LVScope *getCompileUnitParent() const override { return static_cast<LVScope *>(const_cast<LVScopeCompileUnit *>(this)); @@ -643,7 +643,7 @@ public: LVScopeEnumeration() : LVScope() { setIsEnumeration(); } LVScopeEnumeration(const LVScopeEnumeration &) = delete; LVScopeEnumeration &operator=(const LVScopeEnumeration &) = delete; - ~LVScopeEnumeration() = default; + ~LVScopeEnumeration() override = default; // Returns true if current scope is logically equal to the given 'Scope'. bool equals(const LVScope *Scope) const override; @@ -658,7 +658,7 @@ public: LVScopeFormalPack() : LVScope() { setIsTemplatePack(); } LVScopeFormalPack(const LVScopeFormalPack &) = delete; LVScopeFormalPack &operator=(const LVScopeFormalPack &) = delete; - ~LVScopeFormalPack() = default; + ~LVScopeFormalPack() override = default; // Returns true if current scope is logically equal to the given 'Scope'. bool equals(const LVScope *Scope) const override; @@ -676,7 +676,7 @@ public: LVScopeFunction() : LVScope() {} LVScopeFunction(const LVScopeFunction &) = delete; LVScopeFunction &operator=(const LVScopeFunction &) = delete; - virtual ~LVScopeFunction() = default; + ~LVScopeFunction() override = default; // DW_AT_specification, DW_AT_abstract_origin. LVScope *getReference() const override { return Reference; } @@ -728,7 +728,7 @@ public: LVScopeFunctionInlined() : LVScopeFunction() { setIsInlinedFunction(); } LVScopeFunctionInlined(const LVScopeFunctionInlined &) = delete; LVScopeFunctionInlined &operator=(const LVScopeFunctionInlined &) = delete; - ~LVScopeFunctionInlined() = default; + ~LVScopeFunctionInlined() override = default; uint32_t getDiscriminator() const override { return Discriminator; } void setDiscriminator(uint32_t Value) override { @@ -767,7 +767,7 @@ public: LVScopeFunctionType() : LVScopeFunction() { setIsFunctionType(); } LVScopeFunctionType(const LVScopeFunctionType &) = delete; LVScopeFunctionType &operator=(const LVScopeFunctionType &) = delete; - ~LVScopeFunctionType() = default; + ~LVScopeFunctionType() override = default; void resolveExtra() override; }; @@ -781,7 +781,7 @@ public: } LVScopeModule(const LVScopeModule &) = delete; LVScopeModule &operator=(const LVScopeModule &) = delete; - ~LVScopeModule() = default; + ~LVScopeModule() override = default; // Returns true if current scope is logically equal to the given 'Scope'. bool equals(const LVScope *Scope) const override; @@ -797,7 +797,7 @@ public: LVScopeNamespace() : LVScope() { setIsNamespace(); } LVScopeNamespace(const LVScopeNamespace &) = delete; LVScopeNamespace &operator=(const LVScopeNamespace &) = delete; - ~LVScopeNamespace() = default; + ~LVScopeNamespace() override = default; // Access DW_AT_extension reference. LVScope *getReference() const override { return Reference; } @@ -827,7 +827,7 @@ public: LVScopeRoot() : LVScope() { setIsRoot(); } LVScopeRoot(const LVScopeRoot &) = delete; LVScopeRoot &operator=(const LVScopeRoot &) = delete; - ~LVScopeRoot() = default; + ~LVScopeRoot() override = default; StringRef getFileFormatName() const { return getStringPool().getString(FileFormatNameIndex); @@ -859,7 +859,7 @@ public: LVScopeTemplatePack() : LVScope() { setIsTemplatePack(); } LVScopeTemplatePack(const LVScopeTemplatePack &) = delete; LVScopeTemplatePack &operator=(const LVScopeTemplatePack &) = delete; - ~LVScopeTemplatePack() = default; + ~LVScopeTemplatePack() override = default; // Returns true if current scope is logically equal to the given 'Scope'. bool equals(const LVScope *Scope) const override; diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVSymbol.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVSymbol.h index ec9017e..c5314fc 100644 --- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVSymbol.h +++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVSymbol.h @@ -74,7 +74,7 @@ public: } LVSymbol(const LVSymbol &) = delete; LVSymbol &operator=(const LVSymbol &) = delete; - ~LVSymbol() = default; + ~LVSymbol() override = default; static bool classof(const LVElement *Element) { return Element->getSubclassID() == LVSubclassID::LV_SYMBOL; diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVType.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVType.h index 59e6a92..af4abcf 100644 --- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVType.h +++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVType.h @@ -67,7 +67,7 @@ public: LVType() : LVElement(LVSubclassID::LV_TYPE) { setIsType(); } LVType(const LVType &) = delete; LVType &operator=(const LVType &) = delete; - virtual ~LVType() = default; + ~LVType() override = default; static bool classof(const LVElement *Element) { return Element->getSubclassID() == LVSubclassID::LV_TYPE; @@ -157,7 +157,7 @@ public: } LVTypeDefinition(const LVTypeDefinition &) = delete; LVTypeDefinition &operator=(const LVTypeDefinition &) = delete; - ~LVTypeDefinition() = default; + ~LVTypeDefinition() override = default; // Return the underlying type for a type definition. LVElement *getUnderlyingType() override; @@ -183,7 +183,7 @@ public: } LVTypeEnumerator(const LVTypeEnumerator &) = delete; LVTypeEnumerator &operator=(const LVTypeEnumerator &) = delete; - ~LVTypeEnumerator() = default; + ~LVTypeEnumerator() override = default; // Process the values for a DW_TAG_enumerator. StringRef getValue() const override { @@ -206,7 +206,7 @@ public: LVTypeImport() : LVType() { setIncludeInPrint(); } LVTypeImport(const LVTypeImport &) = delete; LVTypeImport &operator=(const LVTypeImport &) = delete; - ~LVTypeImport() = default; + ~LVTypeImport() override = default; // Returns true if current type is logically equal to the given 'Type'. bool equals(const LVType *Type) const override; @@ -223,7 +223,7 @@ public: LVTypeParam(); LVTypeParam(const LVTypeParam &) = delete; LVTypeParam &operator=(const LVTypeParam &) = delete; - ~LVTypeParam() = default; + ~LVTypeParam() override = default; // Template parameter value. StringRef getValue() const override { @@ -256,7 +256,7 @@ public: } LVTypeSubrange(const LVTypeSubrange &) = delete; LVTypeSubrange &operator=(const LVTypeSubrange &) = delete; - ~LVTypeSubrange() = default; + ~LVTypeSubrange() override = default; int64_t getCount() const override { return getIsSubrangeCount() ? LowerBound : 0; diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVBinaryReader.h b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVBinaryReader.h index 2cf4a8e..cc8dda2 100644 --- a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVBinaryReader.h +++ b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVBinaryReader.h @@ -192,7 +192,7 @@ public: : LVReader(Filename, FileFormatName, W, BinaryType) {} LVBinaryReader(const LVBinaryReader &) = delete; LVBinaryReader &operator=(const LVBinaryReader &) = delete; - virtual ~LVBinaryReader() = default; + ~LVBinaryReader() override = default; void addInlineeLines(LVScope *Scope, LVLines &Lines) { CUInlineeLines.emplace(Scope, std::make_unique<LVLines>(std::move(Lines))); diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h index 4dd7c96..9f6fd553 100644 --- a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h +++ b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h @@ -200,7 +200,7 @@ public: Input(&Pdb), ExePath(ExePath), LogicalVisitor(this, W, Input) {} LVCodeViewReader(const LVCodeViewReader &) = delete; LVCodeViewReader &operator=(const LVCodeViewReader &) = delete; - ~LVCodeViewReader() = default; + ~LVCodeViewReader() override = default; void getLinkageName(const llvm::object::coff_section *CoffSection, uint32_t RelocOffset, uint32_t Offset, diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVDWARFReader.h b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVDWARFReader.h index 2abc18b..1cf2914 100644 --- a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVDWARFReader.h +++ b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVDWARFReader.h @@ -123,7 +123,7 @@ public: Obj(Obj) {} LVDWARFReader(const LVDWARFReader &) = delete; LVDWARFReader &operator=(const LVDWARFReader &) = delete; - ~LVDWARFReader() = default; + ~LVDWARFReader() override = default; LVAddress getCUBaseAddress() const { return CUBaseAddress; } void setCUBaseAddress(LVAddress Address) { CUBaseAddress = Address; } diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h index b21cd09..c0b3151 100644 --- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h +++ b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h @@ -20,7 +20,7 @@ namespace pdb { class LLVM_ABI PDBSymbolTypeBuiltin : public PDBSymbol { DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::BuiltinType) public: - ~PDBSymbolTypeBuiltin(); + ~PDBSymbolTypeBuiltin() override; void dump(PDBSymDumper &Dumper) const override; FORWARD_SYMBOL_METHOD(getBuiltinType) diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Core.h b/llvm/include/llvm/ExecutionEngine/Orc/Core.h index f05febf..24a0cb7 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/Core.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/Core.h @@ -1768,7 +1768,7 @@ private: // FIXME: We should be able to derive FailedSymsForQuery from each query once // we fix how the detach operation works. struct EmitQueries { - JITDylib::AsynchronousSymbolQuerySet Updated; + JITDylib::AsynchronousSymbolQuerySet Completed; JITDylib::AsynchronousSymbolQuerySet Failed; DenseMap<AsynchronousSymbolQuery *, std::shared_ptr<SymbolDependenceMap>> FailedSymsForQuery; diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h b/llvm/include/llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h index 4a32113b..6adaa8a 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h @@ -34,7 +34,7 @@ using ExecutorAddrDiff = uint64_t; class ExecutorAddr { public: /// A wrap/unwrap function that leaves pointers unmodified. - using rawPtr = llvm::identity_cxx20; + using rawPtr = llvm::identity; #if __has_feature(ptrauth_calls) template <typename T> class PtrauthSignDefault { diff --git a/llvm/include/llvm/IR/DebugInfo.h b/llvm/include/llvm/IR/DebugInfo.h index 220e4c1..33e6df0 100644 --- a/llvm/include/llvm/IR/DebugInfo.h +++ b/llvm/include/llvm/IR/DebugInfo.h @@ -140,25 +140,17 @@ public: using type_iterator = SmallVectorImpl<DIType *>::const_iterator; using scope_iterator = SmallVectorImpl<DIScope *>::const_iterator; - iterator_range<compile_unit_iterator> compile_units() const { - return make_range(CUs.begin(), CUs.end()); - } + iterator_range<compile_unit_iterator> compile_units() const { return CUs; } - iterator_range<subprogram_iterator> subprograms() const { - return make_range(SPs.begin(), SPs.end()); - } + iterator_range<subprogram_iterator> subprograms() const { return SPs; } iterator_range<global_variable_expression_iterator> global_variables() const { - return make_range(GVs.begin(), GVs.end()); + return GVs; } - iterator_range<type_iterator> types() const { - return make_range(TYs.begin(), TYs.end()); - } + iterator_range<type_iterator> types() const { return TYs; } - iterator_range<scope_iterator> scopes() const { - return make_range(Scopes.begin(), Scopes.end()); - } + iterator_range<scope_iterator> scopes() const { return Scopes; } unsigned compile_unit_count() const { return CUs.size(); } unsigned global_variable_count() const { return GVs.size(); } diff --git a/llvm/include/llvm/IR/IntrinsicsHexagon.td b/llvm/include/llvm/IR/IntrinsicsHexagon.td index 67b873d..20ba51a 100644 --- a/llvm/include/llvm/IR/IntrinsicsHexagon.td +++ b/llvm/include/llvm/IR/IntrinsicsHexagon.td @@ -447,3 +447,15 @@ def int_hexagon_instrprof_custom include "llvm/IR/IntrinsicsHexagonDep.td" + +class Hexagon__ptri32i32v64i16_Intrinsic<string GCCIntSuffix, + list<IntrinsicProperty> intr_properties = [IntrNoMem]> + : Hexagon_Intrinsic<GCCIntSuffix, + [], [llvm_ptr_ty,llvm_i32_ty,llvm_i32_ty,llvm_v64i16_ty], + intr_properties>; + +def int_hexagon_V6_vgather_vscattermh : +Hexagon__ptri32i32v64i16_Intrinsic<"HEXAGON_V6_vgather_vscattermh", [IntrArgMemOnly]>; + +def int_hexagon_V6_vgather_vscattermh_128B : +Hexagon__ptri32i32v32i32_Intrinsic<"HEXAGON_V6_vgather_vscattermh_128B", [IntrArgMemOnly]>; diff --git a/llvm/include/llvm/IR/IntrinsicsHexagonDep.td b/llvm/include/llvm/IR/IntrinsicsHexagonDep.td index 0cd6008..fe95377 100644 --- a/llvm/include/llvm/IR/IntrinsicsHexagonDep.td +++ b/llvm/include/llvm/IR/IntrinsicsHexagonDep.td @@ -6832,3 +6832,17 @@ Hexagon_v32i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vsub_hf_f8">; def int_hexagon_V6_vsub_hf_f8_128B : Hexagon_v64i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsub_hf_f8_128B">; + +// V81 HVX Instructions. + +def int_hexagon_V6_vsub_hf_mix : +Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vsub_hf_mix">; + +def int_hexagon_V6_vsub_hf_mix_128B : +Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsub_hf_mix_128B">; + +def int_hexagon_V6_vsub_sf_mix : +Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vsub_sf_mix">; + +def int_hexagon_V6_vsub_sf_mix_128B : +Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsub_sf_mix_128B">; diff --git a/llvm/include/llvm/IR/IntrinsicsRISCVXsf.td b/llvm/include/llvm/IR/IntrinsicsRISCVXsf.td index 4a0272c..b1bb24e 100644 --- a/llvm/include/llvm/IR/IntrinsicsRISCVXsf.td +++ b/llvm/include/llvm/IR/IntrinsicsRISCVXsf.td @@ -162,6 +162,10 @@ let TargetPrefix = "riscv" in { defm "" : RISCVSFCustomVC_XVV<["x", "i", "v", "f"]>; defm "" : RISCVSFCustomVC_XVW<["x", "i", "v", "f"]>; + // XSfvfexp* and XSfvfexpa* + defm sf_vfexp : RISCVUnaryAA; + defm sf_vfexpa : RISCVUnaryAA; + // XSfvqmaccdod def int_riscv_sf_vqmaccu_2x8x2 : RISCVSFCustomVMACC; def int_riscv_sf_vqmacc_2x8x2 : RISCVSFCustomVMACC; diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h index 99f70b1..e3ec7e1 100644 --- a/llvm/include/llvm/IR/PatternMatch.h +++ b/llvm/include/llvm/IR/PatternMatch.h @@ -198,6 +198,26 @@ struct constantexpr_match { /// expression. inline constantexpr_match m_ConstantExpr() { return constantexpr_match(); } +template <typename SubPattern_t> struct Splat_match { + SubPattern_t SubPattern; + Splat_match(const SubPattern_t &SP) : SubPattern(SP) {} + + template <typename OpTy> bool match(OpTy *V) const { + if (auto *C = dyn_cast<Constant>(V)) { + auto *Splat = C->getSplatValue(); + return Splat ? SubPattern.match(Splat) : false; + } + // TODO: Extend to other cases (e.g. shufflevectors). + return false; + } +}; + +/// Match a constant splat. TODO: Extend this to non-constant splats. +template <typename T> +inline Splat_match<T> m_ConstantSplat(const T &SubPattern) { + return SubPattern; +} + /// Match an arbitrary basic block value and ignore it. inline class_match<BasicBlock> m_BasicBlock() { return class_match<BasicBlock>(); @@ -2925,6 +2945,12 @@ inline typename m_Intrinsic_Ty<Opnd0>::Ty m_VecReverse(const Opnd0 &Op0) { return m_Intrinsic<Intrinsic::vector_reverse>(Op0); } +template <typename Opnd0, typename Opnd1, typename Opnd2> +inline typename m_Intrinsic_Ty<Opnd0, Opnd1, Opnd2>::Ty +m_VectorInsert(const Opnd0 &Op0, const Opnd1 &Op1, const Opnd2 &Op2) { + return m_Intrinsic<Intrinsic::vector_insert>(Op0, Op1, Op2); +} + //===----------------------------------------------------------------------===// // Matchers for two-operands operators with the operators in either order // diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td index 3dc9055..ec16995 100644 --- a/llvm/include/llvm/IR/RuntimeLibcalls.td +++ b/llvm/include/llvm/IR/RuntimeLibcalls.td @@ -32,6 +32,15 @@ def isWindowsMSVCEnvironment : RuntimeLibcallPredicate< def isNotOSLinuxAndNotOSOpenBSD : RuntimeLibcallPredicate< [{!TT.isOSLinux() && !TT.isOSOpenBSD()}]>; +def isNotOSAIXAndNotOSOpenBSD : RuntimeLibcallPredicate< + [{!TT.isOSAIX() && !TT.isOSOpenBSD()}]>; + +// OpenBSD uses __guard_local. AIX uses __ssp_canary_word, MSVC/Windows +// Itanium uses __security_cookie +def hasStackChkFail : RuntimeLibcallPredicate< + [{ !TT.isOSOpenBSD() && !TT.isWindowsMSVCEnvironment() && + !TT.isWindowsItaniumEnvironment()}]>; + def isWindowsMSVCOrItaniumEnvironment : RuntimeLibcallPredicate< [{TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment()}]>; @@ -1241,9 +1250,9 @@ defvar LibmHasLdexpF80 = LibcallImpls<(add ldexpl_f80), isNotOSWindowsOrIsCygwin defvar LibmHasFrexpF128 = LibcallImpls<(add frexpl_f128), isNotOSWindowsOrIsCygwinMinGW>; defvar LibmHasLdexpF128 = LibcallImpls<(add ldexpl_f128), isNotOSWindowsOrIsCygwinMinGW>; -defvar has__stack_chk_fail = LibcallImpls<(add __stack_chk_fail), isNotOSOpenBSD>; +defvar has__stack_chk_fail = LibcallImpls<(add __stack_chk_fail), hasStackChkFail>; defvar has__stack_chk_guard = - LibcallImpls<(add __stack_chk_guard), isNotOSOpenBSD>; + LibcallImpls<(add __stack_chk_guard), hasStackChkFail>; defvar has__stack_smash_handler = LibcallImpls<(add __stack_smash_handler), isOSOpenBSD>; defvar has___guard_local = LibcallImpls<(add __guard_local), isOSOpenBSD>; @@ -1396,8 +1405,8 @@ defvar ExceptionModelCallsArm64EC = (add def WindowsARM64ECSystemLibrary : SystemRuntimeLibrary<isWindowsArm64EC, (add WinArm64ECDefaultRuntimeLibcallImpls, - arm64ec___stack_chk_fail, - __stack_chk_guard, + AvailableIf<arm64ec___stack_chk_fail, hasStackChkFail>, + AvailableIf<__stack_chk_guard, hasStackChkFail>, LibcallImpls<(add __security_check_cookie_arm64ec, __security_cookie), isWindowsMSVCEnvironment>, @@ -2318,11 +2327,11 @@ def PPCSystemLibrary LibmHasSinCosPPCF128, AvailableIf<memcpy, isNotAIX>, LibcallImpls<(add Int128RTLibcalls), isPPC64>, - has__stack_chk_fail, has__stack_smash_handler, has___guard_local, AvailableIf<__ssp_canary_word, isAIX>, - AvailableIf<__stack_chk_guard, isNotAIX>)>; + AvailableIf<__stack_chk_fail, isNotOSOpenBSD>, + AvailableIf<__stack_chk_guard, isNotOSAIXAndNotOSOpenBSD>)>; //===----------------------------------------------------------------------===// // RISCV Runtime Libcalls diff --git a/llvm/include/llvm/LTO/LTO.h b/llvm/include/llvm/LTO/LTO.h index a837cdd..3a4dc5a 100644 --- a/llvm/include/llvm/LTO/LTO.h +++ b/llvm/include/llvm/LTO/LTO.h @@ -462,6 +462,19 @@ private: ModuleMapType ModuleMap; // The bitcode modules to compile, if specified by the LTO Config. std::optional<ModuleMapType> ModulesToCompile; + + void setPrevailingModuleForGUID(GlobalValue::GUID GUID, StringRef Module) { + PrevailingModuleForGUID[GUID] = Module; + } + bool isPrevailingModuleForGUID(GlobalValue::GUID GUID, + StringRef Module) const { + auto It = PrevailingModuleForGUID.find(GUID); + return It != PrevailingModuleForGUID.end() && It->second == Module; + } + + private: + // Make this private so all accesses must go through above accessor methods + // to avoid inadvertently creating new entries on lookups. DenseMap<GlobalValue::GUID, StringRef> PrevailingModuleForGUID; } ThinLTO; diff --git a/llvm/include/llvm/Object/DXContainer.h b/llvm/include/llvm/Object/DXContainer.h index 5a5a4db..c5888b8 100644 --- a/llvm/include/llvm/Object/DXContainer.h +++ b/llvm/include/llvm/Object/DXContainer.h @@ -245,10 +245,10 @@ public: uint32_t getStaticSamplersOffset() const { return StaticSamplersOffset; } uint32_t getNumRootParameters() const { return ParametersHeaders.size(); } llvm::iterator_range<param_header_iterator> param_headers() const { - return llvm::make_range(ParametersHeaders.begin(), ParametersHeaders.end()); + return ParametersHeaders; } llvm::iterator_range<samplers_iterator> samplers() const { - return llvm::make_range(StaticSamplers.begin(), StaticSamplers.end()); + return StaticSamplers; } uint32_t getFlags() const { return Flags; } diff --git a/llvm/include/llvm/Object/MachO.h b/llvm/include/llvm/Object/MachO.h index 3f4a21d..01e7c6b 100644 --- a/llvm/include/llvm/Object/MachO.h +++ b/llvm/include/llvm/Object/MachO.h @@ -121,9 +121,7 @@ private: NodeList Stack; bool Done = false; - iterator_range<node_iterator> nodes() const { - return make_range(Stack.begin(), Stack.end()); - } + iterator_range<node_iterator> nodes() const { return Stack; } }; using export_iterator = content_iterator<ExportEntry>; diff --git a/llvm/include/llvm/Remarks/RemarkLinker.h b/llvm/include/llvm/Remarks/RemarkLinker.h index 67208f4..2d98f2d 100644 --- a/llvm/include/llvm/Remarks/RemarkLinker.h +++ b/llvm/include/llvm/Remarks/RemarkLinker.h @@ -101,9 +101,7 @@ public: /// for (const Remark &R : RL.remarks() { [...] } using iterator = pointee_iterator<decltype(Remarks)::const_iterator>; - iterator_range<iterator> remarks() const { - return {Remarks.begin(), Remarks.end()}; - } + iterator_range<iterator> remarks() const { return Remarks; } }; /// Returns a buffer with the contents of the remarks section depending on the diff --git a/llvm/include/llvm/Support/DataExtractor.h b/llvm/include/llvm/Support/DataExtractor.h index 3792f53..f1710b9 100644 --- a/llvm/include/llvm/Support/DataExtractor.h +++ b/llvm/include/llvm/Support/DataExtractor.h @@ -19,12 +19,8 @@ namespace llvm { /// An auxiliary type to facilitate extraction of 3-byte entities. struct Uint24 { uint8_t Bytes[3]; - Uint24(uint8_t U) { - Bytes[0] = Bytes[1] = Bytes[2] = U; - } - Uint24(uint8_t U0, uint8_t U1, uint8_t U2) { - Bytes[0] = U0; Bytes[1] = U1; Bytes[2] = U2; - } + Uint24(uint8_t U) : Bytes{U, U, U} {} + Uint24(uint8_t U0, uint8_t U1, uint8_t U2) : Bytes{U0, U1, U2} {} uint32_t getAsUint32(bool IsLittleEndian) const { int LoIx = IsLittleEndian ? 0 : 2; return Bytes[LoIx] + (Bytes[1] << 8) + (Bytes[2-LoIx] << 16); diff --git a/llvm/include/llvm/Support/Recycler.h b/llvm/include/llvm/Support/Recycler.h index b51c586..6502a70 100644 --- a/llvm/include/llvm/Support/Recycler.h +++ b/llvm/include/llvm/Support/Recycler.h @@ -19,6 +19,7 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include <cassert> +#include <type_traits> namespace llvm { @@ -72,19 +73,19 @@ public: /// deleted; calling clear is one way to ensure this. template<class AllocatorType> void clear(AllocatorType &Allocator) { - while (FreeList) { - T *t = reinterpret_cast<T *>(pop_val()); - Allocator.Deallocate(t, Size, Align); + if constexpr (std::is_same_v<std::decay_t<AllocatorType>, + BumpPtrAllocator>) { + // For BumpPtrAllocator, Deallocate is a no-op, so just drop the free + // list. + FreeList = nullptr; + } else { + while (FreeList) { + T *t = reinterpret_cast<T *>(pop_val()); + Allocator.Deallocate(t, Size, Align); + } } } - /// Special case for BumpPtrAllocator which has an empty Deallocate() - /// function. - /// - /// There is no need to traverse the free list, pulling all the objects into - /// cache. - void clear(BumpPtrAllocator &) { FreeList = nullptr; } - template<class SubClass, class AllocatorType> SubClass *Allocate(AllocatorType &Allocator) { static_assert(alignof(SubClass) <= Align, diff --git a/llvm/include/llvm/Support/SpecialCaseList.h b/llvm/include/llvm/Support/SpecialCaseList.h index ead7655..860f73c 100644 --- a/llvm/include/llvm/Support/SpecialCaseList.h +++ b/llvm/include/llvm/Support/SpecialCaseList.h @@ -13,7 +13,10 @@ #define LLVM_SUPPORT_SPECIALCASELIST_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/RadixTree.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/GlobPattern.h" @@ -162,6 +165,11 @@ private: }; std::vector<GlobMatcher::Glob> Globs; + + RadixTree<iterator_range<StringRef::const_iterator>, + RadixTree<iterator_range<StringRef::const_reverse_iterator>, + SmallVector<const GlobMatcher::Glob *, 1>>> + PrefixSuffixToGlob; }; /// Represents a set of patterns and their line numbers diff --git a/llvm/include/llvm/Support/Timer.h b/llvm/include/llvm/Support/Timer.h index 6a44758..527d67f 100644 --- a/llvm/include/llvm/Support/Timer.h +++ b/llvm/include/llvm/Support/Timer.h @@ -209,6 +209,7 @@ class TimerGroup { std::string Description; Timer *FirstTimer = nullptr; ///< First timer in the group. std::vector<PrintRecord> TimersToPrint; + bool PrintOnExit; TimerGroup **Prev; ///< Pointer to Next field of previous timergroup in list. TimerGroup *Next; ///< Pointer to next timergroup in list. @@ -217,13 +218,15 @@ class TimerGroup { friend class TimerGlobals; explicit TimerGroup(StringRef Name, StringRef Description, - sys::SmartMutex<true> &lock); + sys::SmartMutex<true> &lock, bool PrintOnExit); public: - LLVM_ABI explicit TimerGroup(StringRef Name, StringRef Description); + LLVM_ABI explicit TimerGroup(StringRef Name, StringRef Description, + bool PrintOnExit = true); LLVM_ABI explicit TimerGroup(StringRef Name, StringRef Description, - const StringMap<TimeRecord> &Records); + const StringMap<TimeRecord> &Records, + bool PrintOnExit = true); LLVM_ABI ~TimerGroup(); diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td index 3d21f52..47d5d68 100644 --- a/llvm/include/llvm/Target/GlobalISel/Combine.td +++ b/llvm/include/llvm/Target/GlobalISel/Combine.td @@ -484,13 +484,6 @@ def propagate_undef_shuffle_mask: GICombineRule< [{ return Helper.matchUndefShuffleVectorMask(*${root}); }]), (apply [{ Helper.replaceInstWithUndef(*${root}); }])>; -// Replace a G_SHUFFLE_VECTOR with a G_EXTRACT_VECTOR_ELT. -def shuffle_to_extract: GICombineRule< - (defs root:$root), - (match (wip_match_opcode G_SHUFFLE_VECTOR):$root, - [{ return Helper.matchShuffleToExtract(*${root}); }]), - (apply [{ Helper.applyShuffleToExtract(*${root}); }])>; - // Replace an insert/extract element of an out of bounds index with undef. def insert_extract_vec_elt_out_of_bounds : GICombineRule< (defs root:$root), @@ -1674,8 +1667,7 @@ def combine_shuffle_concat : GICombineRule< // Combines shuffles of vector into build_vector def combine_shuffle_vector_to_build_vector : GICombineRule< (defs root:$root), - (match (G_SHUFFLE_VECTOR $dst, $src1, $src2, $mask):$root, - [{ return Helper.matchCombineShuffleToBuildVector(*${root}); }]), + (match (G_SHUFFLE_VECTOR $dst, $src1, $src2, $mask):$root), (apply [{ Helper.applyCombineShuffleToBuildVector(*${root}); }])>; def insert_vector_element_idx_undef : GICombineRule< diff --git a/llvm/include/llvm/TargetParser/AArch64TargetParser.h b/llvm/include/llvm/TargetParser/AArch64TargetParser.h index 8e83b046..7e68ad2 100644 --- a/llvm/include/llvm/TargetParser/AArch64TargetParser.h +++ b/llvm/include/llvm/TargetParser/AArch64TargetParser.h @@ -115,9 +115,9 @@ struct ArchInfo { // Defines the following partial order, indicating when an architecture is // a superset of another: // - // v9.6a > v9.5a > v9.4a > v9.3a > v9.2a > v9.1a > v9a; - // v v v v v - // v8.9a > v8.8a > v8.7a > v8.6a > v8.5a > v8.4a > ... > v8a; + // v9.7a > v9.6a > v9.5a > v9.4a > v9.3a > v9.2a > v9.1a > v9a; + // v v v v v + // v8.9a > v8.8a > v8.7a > v8.6a > v8.5a > ... > v8a; // // v8r has no relation to anything. This is used to determine which // features to enable for a given architecture. See diff --git a/llvm/include/llvm/TargetParser/ARMTargetParser.def b/llvm/include/llvm/TargetParser/ARMTargetParser.def index ff53aa1..0ada2e7 100644 --- a/llvm/include/llvm/TargetParser/ARMTargetParser.def +++ b/llvm/include/llvm/TargetParser/ARMTargetParser.def @@ -187,6 +187,11 @@ ARM_ARCH("armv9.6-a", ARMV9_6A, "9.6-A", "+v9.6a", ARMBuildAttrs::CPUArch::v9_A, (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_CRC | ARM::AEK_RAS | ARM::AEK_DOTPROD | ARM::AEK_BF16 | ARM::AEK_I8MM)) +ARM_ARCH("armv9.7-a", ARMV9_7A, "9.7-A", "+v9.7a", ARMBuildAttrs::CPUArch::v9_A, + FK_NEON_FP_ARMV8, + (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM | + ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_CRC | ARM::AEK_RAS | + ARM::AEK_DOTPROD | ARM::AEK_BF16 | ARM::AEK_I8MM)) ARM_ARCH("armv8-r", ARMV8R, "8-R", "+v8r", ARMBuildAttrs::CPUArch::v8_R, FK_FPV5_SP_D16, (ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM | diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h index 5e43444..0e82dd2 100644 --- a/llvm/include/llvm/TargetParser/Triple.h +++ b/llvm/include/llvm/TargetParser/Triple.h @@ -115,6 +115,7 @@ public: enum SubArchType { NoSubArch, + ARMSubArch_v9_7a, ARMSubArch_v9_6a, ARMSubArch_v9_5a, ARMSubArch_v9_4a, diff --git a/llvm/include/llvm/TextAPI/SymbolSet.h b/llvm/include/llvm/TextAPI/SymbolSet.h index 22f4124..c97d7a1 100644 --- a/llvm/include/llvm/TextAPI/SymbolSet.h +++ b/llvm/include/llvm/TextAPI/SymbolSet.h @@ -139,18 +139,14 @@ public: iterator_range<const_filtered_symbol_iterator>; // Range that contains all symbols. - const_symbol_range symbols() const { - return {Symbols.begin(), Symbols.end()}; - } + const_symbol_range symbols() const { return Symbols; } // Range that contains all defined and exported symbols. const_filtered_symbol_range exports() const { std::function<bool(const Symbol *)> fn = [](const Symbol *Symbol) { return !Symbol->isUndefined() && !Symbol->isReexported(); }; - return make_filter_range( - make_range<const_symbol_iterator>({Symbols.begin()}, {Symbols.end()}), - fn); + return make_filter_range(symbols(), fn); } // Range that contains all reexported symbols. @@ -158,9 +154,7 @@ public: std::function<bool(const Symbol *)> fn = [](const Symbol *Symbol) { return Symbol->isReexported(); }; - return make_filter_range( - make_range<const_symbol_iterator>({Symbols.begin()}, {Symbols.end()}), - fn); + return make_filter_range(symbols(), fn); } // Range that contains all undefined and exported symbols. @@ -168,9 +162,7 @@ public: std::function<bool(const Symbol *)> fn = [](const Symbol *Symbol) { return Symbol->isUndefined(); }; - return make_filter_range( - make_range<const_symbol_iterator>({Symbols.begin()}, {Symbols.end()}), - fn); + return make_filter_range(symbols(), fn); } LLVM_ABI bool operator==(const SymbolSet &O) const; |
