Merge llvm, clang, lld, lldb, compiler-rt and libc++ r303291, and update

build glue.
This commit is contained in:
Dimitry Andric 2017-05-18 18:33:33 +00:00
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/clang500-import/; revision=318477
141 changed files with 2065 additions and 1879 deletions

View File

@ -104,7 +104,7 @@ __floatdidf(di_int a)
}
#endif
#if defined(__AEABI__)
#if defined(__ARM_EABI__)
AEABI_RTABI double __aeabi_l2d(di_int a) {
return __floatdidf(a);
}

View File

@ -64,14 +64,23 @@ struct forward_iterator_tag : public input_iterator_tag {};
struct bidirectional_iterator_tag : public forward_iterator_tag {};
struct random_access_iterator_tag : public bidirectional_iterator_tag {};
// 27.4.3, iterator operations
// extension: second argument not conforming to C++03
template <class InputIterator>
void advance(InputIterator& i,
template <class InputIterator> // constexpr in C++17
constexpr void advance(InputIterator& i,
typename iterator_traits<InputIterator>::difference_type n);
template <class InputIterator>
typename iterator_traits<InputIterator>::difference_type
distance(InputIterator first, InputIterator last);
template <class InputIterator> // constexpr in C++17
constexpr typename iterator_traits<InputIterator>::difference_type
distance(InputIterator first, InputIterator last);
template <class InputIterator> // constexpr in C++17
constexpr InputIterator next(InputIterator x,
typename iterator_traits<InputIterator>::difference_type n = 1);
template <class BidirectionalIterator> // constexpr in C++17
constexpr BidirectionalIterator prev(BidirectionalIterator x,
typename iterator_traits<BidirectionalIterator>::difference_type n = 1);
template <class Iterator>
class reverse_iterator
@ -529,7 +538,7 @@ struct _LIBCPP_TEMPLATE_VIS iterator
};
template <class _InputIter>
inline _LIBCPP_INLINE_VISIBILITY
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
void __advance(_InputIter& __i,
typename iterator_traits<_InputIter>::difference_type __n, input_iterator_tag)
{
@ -538,7 +547,7 @@ void __advance(_InputIter& __i,
}
template <class _BiDirIter>
inline _LIBCPP_INLINE_VISIBILITY
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
void __advance(_BiDirIter& __i,
typename iterator_traits<_BiDirIter>::difference_type __n, bidirectional_iterator_tag)
{
@ -551,7 +560,7 @@ void __advance(_BiDirIter& __i,
}
template <class _RandIter>
inline _LIBCPP_INLINE_VISIBILITY
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
void __advance(_RandIter& __i,
typename iterator_traits<_RandIter>::difference_type __n, random_access_iterator_tag)
{
@ -559,7 +568,7 @@ void __advance(_RandIter& __i,
}
template <class _InputIter>
inline _LIBCPP_INLINE_VISIBILITY
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
void advance(_InputIter& __i,
typename iterator_traits<_InputIter>::difference_type __n)
{
@ -567,7 +576,7 @@ void advance(_InputIter& __i,
}
template <class _InputIter>
inline _LIBCPP_INLINE_VISIBILITY
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
typename iterator_traits<_InputIter>::difference_type
__distance(_InputIter __first, _InputIter __last, input_iterator_tag)
{
@ -578,7 +587,7 @@ __distance(_InputIter __first, _InputIter __last, input_iterator_tag)
}
template <class _RandIter>
inline _LIBCPP_INLINE_VISIBILITY
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
typename iterator_traits<_RandIter>::difference_type
__distance(_RandIter __first, _RandIter __last, random_access_iterator_tag)
{
@ -586,7 +595,7 @@ __distance(_RandIter __first, _RandIter __last, random_access_iterator_tag)
}
template <class _InputIter>
inline _LIBCPP_INLINE_VISIBILITY
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
typename iterator_traits<_InputIter>::difference_type
distance(_InputIter __first, _InputIter __last)
{
@ -594,7 +603,7 @@ distance(_InputIter __first, _InputIter __last)
}
template <class _InputIter>
inline _LIBCPP_INLINE_VISIBILITY
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
_InputIter
next(_InputIter __x,
typename iterator_traits<_InputIter>::difference_type __n = 1,
@ -605,7 +614,7 @@ next(_InputIter __x,
}
template <class _BidiretionalIter>
inline _LIBCPP_INLINE_VISIBILITY
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
_BidiretionalIter
prev(_BidiretionalIter __x,
typename iterator_traits<_BidiretionalIter>::difference_type __n = 1,

View File

@ -599,8 +599,8 @@ private:
public:
_LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {}
_LIBCPP_INLINE_VISIBILITY optional(const optional&) = default;
_LIBCPP_INLINE_VISIBILITY optional(optional&&) = default;
_LIBCPP_INLINE_VISIBILITY constexpr optional(const optional&) = default;
_LIBCPP_INLINE_VISIBILITY constexpr optional(optional&&) = default;
_LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {}
template <class... _Args, class = enable_if_t<

View File

@ -1067,9 +1067,7 @@ class LLVM_NODISCARD APInt {
/// \returns the bit value at bitPosition
bool operator[](unsigned bitPosition) const {
assert(bitPosition < getBitWidth() && "Bit position out of bounds!");
return (maskBit(bitPosition) &
(isSingleWord() ? U.VAL : U.pVal[whichWord(bitPosition)])) !=
0;
return (maskBit(bitPosition) & getWord(bitPosition)) != 0;
}
/// @}

View File

@ -15,6 +15,7 @@
#define LLVM_ADT_BITVECTOR_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/MathExtras.h"
#include <algorithm>
#include <cassert>
@ -26,6 +27,50 @@
namespace llvm {
/// ForwardIterator for the bits that are set.
/// Iterators get invalidated when resize / reserve is called.
template <typename BitVectorT> class const_set_bits_iterator_impl {
const BitVectorT &Parent;
int Current = 0;
void advance() {
assert(Current != -1 && "Trying to advance past end.");
Current = Parent.find_next(Current);
}
public:
const_set_bits_iterator_impl(const BitVectorT &Parent, int Current)
: Parent(Parent), Current(Current) {}
explicit const_set_bits_iterator_impl(const BitVectorT &Parent)
: const_set_bits_iterator_impl(Parent, Parent.find_first()) {}
const_set_bits_iterator_impl(const const_set_bits_iterator_impl &) = default;
const_set_bits_iterator_impl operator++(int) {
auto Prev = *this;
advance();
return Prev;
}
const_set_bits_iterator_impl &operator++() {
advance();
return *this;
}
unsigned operator*() const { return Current; }
bool operator==(const const_set_bits_iterator_impl &Other) const {
assert(&Parent == &Other.Parent &&
"Comparing iterators from different BitVectors");
return Current == Other.Current;
}
bool operator!=(const const_set_bits_iterator_impl &Other) const {
assert(&Parent == &Other.Parent &&
"Comparing iterators from different BitVectors");
return Current != Other.Current;
}
};
class BitVector {
typedef unsigned long BitWord;
@ -73,6 +118,18 @@ class BitVector {
}
};
typedef const_set_bits_iterator_impl<BitVector> const_set_bits_iterator;
typedef const_set_bits_iterator set_iterator;
const_set_bits_iterator set_bits_begin() const {
return const_set_bits_iterator(*this);
}
const_set_bits_iterator set_bits_end() const {
return const_set_bits_iterator(*this, -1);
}
iterator_range<const_set_bits_iterator> set_bits() const {
return make_range(set_bits_begin(), set_bits_end());
}
/// BitVector default ctor - Creates an empty bitvector.
BitVector() : Size(0) {}
@ -146,138 +203,164 @@ class BitVector {
return !any();
}
/// find_first - Returns the index of the first set bit, -1 if none
/// of the bits are set.
int find_first() const {
for (unsigned i = 0; i < NumBitWords(size()); ++i)
if (Bits[i] != 0)
return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
/// find_first_in - Returns the index of the first set bit in the range
/// [Begin, End). Returns -1 if all bits in the range are unset.
int find_first_in(unsigned Begin, unsigned End) const {
assert(Begin <= End && End <= Size);
if (Begin == End)
return -1;
unsigned FirstWord = Begin / BITWORD_SIZE;
unsigned LastWord = (End - 1) / BITWORD_SIZE;
// Check subsequent words.
for (unsigned i = FirstWord; i <= LastWord; ++i) {
BitWord Copy = Bits[i];
if (i == FirstWord) {
unsigned FirstBit = Begin % BITWORD_SIZE;
Copy &= maskTrailingZeros<BitWord>(FirstBit);
}
if (i == LastWord) {
unsigned LastBit = (End - 1) % BITWORD_SIZE;
Copy &= maskTrailingOnes<BitWord>(LastBit + 1);
}
if (Copy != 0)
return i * BITWORD_SIZE + countTrailingZeros(Copy);
}
return -1;
}
/// find_last_in - Returns the index of the last set bit in the range
/// [Begin, End). Returns -1 if all bits in the range are unset.
int find_last_in(unsigned Begin, unsigned End) const {
assert(Begin <= End && End <= Size);
if (Begin == End)
return -1;
unsigned LastWord = (End - 1) / BITWORD_SIZE;
unsigned FirstWord = Begin / BITWORD_SIZE;
for (unsigned i = LastWord + 1; i >= FirstWord + 1; --i) {
unsigned CurrentWord = i - 1;
BitWord Copy = Bits[CurrentWord];
if (CurrentWord == LastWord) {
unsigned LastBit = (End - 1) % BITWORD_SIZE;
Copy &= maskTrailingOnes<BitWord>(LastBit + 1);
}
if (CurrentWord == FirstWord) {
unsigned FirstBit = Begin % BITWORD_SIZE;
Copy &= maskTrailingZeros<BitWord>(FirstBit);
}
if (Copy != 0)
return (CurrentWord + 1) * BITWORD_SIZE - countLeadingZeros(Copy) - 1;
}
return -1;
}
/// find_first_unset_in - Returns the index of the first unset bit in the
/// range [Begin, End). Returns -1 if all bits in the range are set.
int find_first_unset_in(unsigned Begin, unsigned End) const {
assert(Begin <= End && End <= Size);
if (Begin == End)
return -1;
unsigned FirstWord = Begin / BITWORD_SIZE;
unsigned LastWord = (End - 1) / BITWORD_SIZE;
// Check subsequent words.
for (unsigned i = FirstWord; i <= LastWord; ++i) {
BitWord Copy = Bits[i];
if (i == FirstWord) {
unsigned FirstBit = Begin % BITWORD_SIZE;
Copy |= maskTrailingOnes<BitWord>(FirstBit);
}
if (i == LastWord) {
unsigned LastBit = (End - 1) % BITWORD_SIZE;
Copy |= maskTrailingZeros<BitWord>(LastBit + 1);
}
if (Copy != ~0UL) {
unsigned Result = i * BITWORD_SIZE + countTrailingOnes(Copy);
return Result < size() ? Result : -1;
}
}
return -1;
}
/// find_last_unset_in - Returns the index of the last unset bit in the
/// range [Begin, End). Returns -1 if all bits in the range are set.
int find_last_unset_in(unsigned Begin, unsigned End) const {
assert(Begin <= End && End <= Size);
if (Begin == End)
return -1;
unsigned LastWord = (End - 1) / BITWORD_SIZE;
unsigned FirstWord = Begin / BITWORD_SIZE;
for (unsigned i = LastWord + 1; i >= FirstWord + 1; --i) {
unsigned CurrentWord = i - 1;
BitWord Copy = Bits[CurrentWord];
if (CurrentWord == LastWord) {
unsigned LastBit = (End - 1) % BITWORD_SIZE;
Copy |= maskTrailingZeros<BitWord>(LastBit + 1);
}
if (CurrentWord == FirstWord) {
unsigned FirstBit = Begin % BITWORD_SIZE;
Copy |= maskTrailingOnes<BitWord>(FirstBit);
}
if (Copy != ~0UL) {
unsigned Result =
(CurrentWord + 1) * BITWORD_SIZE - countLeadingOnes(Copy) - 1;
return Result < Size ? Result : -1;
}
}
return -1;
}
/// find_first - Returns the index of the first set bit, -1 if none
/// of the bits are set.
int find_first() const { return find_first_in(0, Size); }
/// find_last - Returns the index of the last set bit, -1 if none of the bits
/// are set.
int find_last() const {
if (Size == 0)
return -1;
unsigned N = NumBitWords(size());
assert(N > 0);
unsigned i = N - 1;
while (i > 0 && Bits[i] == BitWord(0))
--i;
return int((i + 1) * BITWORD_SIZE - countLeadingZeros(Bits[i])) - 1;
}
/// find_first_unset - Returns the index of the first unset bit, -1 if all
/// of the bits are set.
int find_first_unset() const {
for (unsigned i = 0; i < NumBitWords(size()); ++i)
if (Bits[i] != ~0UL) {
unsigned Result = i * BITWORD_SIZE + countTrailingOnes(Bits[i]);
return Result < size() ? Result : -1;
}
return -1;
}
/// find_last_unset - Returns the index of the last unset bit, -1 if all of
/// the bits are set.
int find_last_unset() const {
if (Size == 0)
return -1;
const unsigned N = NumBitWords(size());
assert(N > 0);
unsigned i = N - 1;
BitWord W = Bits[i];
// The last word in the BitVector has some unused bits, so we need to set
// them all to 1 first. Set them all to 1 so they don't get treated as
// valid unset bits.
unsigned UnusedCount = BITWORD_SIZE - size() % BITWORD_SIZE;
W |= maskLeadingOnes<BitWord>(UnusedCount);
while (W == ~BitWord(0) && --i > 0)
W = Bits[i];
return int((i + 1) * BITWORD_SIZE - countLeadingOnes(W)) - 1;
}
int find_last() const { return find_last_in(0, Size); }
/// find_next - Returns the index of the next set bit following the
/// "Prev" bit. Returns -1 if the next set bit is not found.
int find_next(unsigned Prev) const {
++Prev;
if (Prev >= Size)
return -1;
int find_next(unsigned Prev) const { return find_first_in(Prev + 1, Size); }
unsigned WordPos = Prev / BITWORD_SIZE;
unsigned BitPos = Prev % BITWORD_SIZE;
BitWord Copy = Bits[WordPos];
// Mask off previous bits.
Copy &= maskTrailingZeros<BitWord>(BitPos);
/// find_prev - Returns the index of the first set bit that precedes the
/// the bit at \p PriorTo. Returns -1 if all previous bits are unset.
int find_prev(unsigned PriorTo) const { return find_last_in(0, PriorTo); }
if (Copy != 0)
return WordPos * BITWORD_SIZE + countTrailingZeros(Copy);
// Check subsequent words.
for (unsigned i = WordPos+1; i < NumBitWords(size()); ++i)
if (Bits[i] != 0)
return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
return -1;
}
/// find_first_unset - Returns the index of the first unset bit, -1 if all
/// of the bits are set.
int find_first_unset() const { return find_first_unset_in(0, Size); }
/// find_next_unset - Returns the index of the next unset bit following the
/// "Prev" bit. Returns -1 if all remaining bits are set.
int find_next_unset(unsigned Prev) const {
++Prev;
if (Prev >= Size)
return -1;
unsigned WordPos = Prev / BITWORD_SIZE;
unsigned BitPos = Prev % BITWORD_SIZE;
BitWord Copy = Bits[WordPos];
// Mask in previous bits.
BitWord Mask = (1 << BitPos) - 1;
Copy |= Mask;
if (Copy != ~0UL)
return next_unset_in_word(WordPos, Copy);
// Check subsequent words.
for (unsigned i = WordPos + 1; i < NumBitWords(size()); ++i)
if (Bits[i] != ~0UL)
return next_unset_in_word(i, Bits[i]);
return -1;
return find_first_unset_in(Prev + 1, Size);
}
/// find_prev - Returns the index of the first set bit that precedes the
/// the bit at \p PriorTo. Returns -1 if all previous bits are unset.
int find_prev(unsigned PriorTo) const {
if (PriorTo == 0)
return -1;
/// find_last_unset - Returns the index of the last unset bit, -1 if all of
/// the bits are set.
int find_last_unset() const { return find_last_unset_in(0, Size); }
--PriorTo;
unsigned WordPos = PriorTo / BITWORD_SIZE;
unsigned BitPos = PriorTo % BITWORD_SIZE;
BitWord Copy = Bits[WordPos];
// Mask off next bits.
Copy &= maskTrailingOnes<BitWord>(BitPos + 1);
if (Copy != 0)
return (WordPos + 1) * BITWORD_SIZE - countLeadingZeros(Copy) - 1;
// Check previous words.
for (unsigned i = 1; i <= WordPos; ++i) {
unsigned Index = WordPos - i;
if (Bits[Index] == 0)
continue;
return (Index + 1) * BITWORD_SIZE - countLeadingZeros(Bits[Index]) - 1;
}
return -1;
/// find_prev_unset - Returns the index of the first unset bit that precedes
/// the bit at \p PriorTo. Returns -1 if all previous bits are set.
int find_prev_unset(unsigned PriorTo) {
return find_last_unset_in(0, PriorTo);
}
/// clear - Removes all bits from the bitvector. Does not change capacity.

View File

@ -96,24 +96,14 @@ template <class GraphT,
class po_iterator
: public std::iterator<std::forward_iterator_tag, typename GT::NodeRef>,
public po_iterator_storage<SetType, ExtStorage> {
typedef std::iterator<std::forward_iterator_tag, typename GT::NodeRef> super;
typedef typename GT::NodeRef NodeRef;
typedef typename GT::ChildIteratorType ChildItTy;
using super = std::iterator<std::forward_iterator_tag, typename GT::NodeRef>;
using NodeRef = typename GT::NodeRef;
using ChildItTy = typename GT::ChildIteratorType;
// VisitStack - Used to maintain the ordering. Top = current block
// First element is basic block pointer, second is the 'next child' to visit
std::vector<std::pair<NodeRef, ChildItTy>> VisitStack;
void traverseChild() {
while (VisitStack.back().second != GT::child_end(VisitStack.back().first)) {
NodeRef BB = *VisitStack.back().second++;
if (this->insertEdge(Optional<NodeRef>(VisitStack.back().first), BB)) {
// If the block is not visited...
VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB)));
}
}
}
po_iterator(NodeRef BB) {
this->insertEdge(Optional<NodeRef>(), BB);
VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB)));
@ -134,8 +124,18 @@ class po_iterator
: po_iterator_storage<SetType, ExtStorage>(S) {
} // End is when stack is empty.
void traverseChild() {
while (VisitStack.back().second != GT::child_end(VisitStack.back().first)) {
NodeRef BB = *VisitStack.back().second++;
if (this->insertEdge(Optional<NodeRef>(VisitStack.back().first), BB)) {
// If the block is not visited...
VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB)));
}
}
}
public:
typedef typename super::pointer pointer;
using pointer = typename super::pointer;
// Provide static "constructors"...
static po_iterator begin(GraphT G) {
@ -286,7 +286,8 @@ inverse_post_order_ext(const T &G, SetType &S) {
template<class GraphT, class GT = GraphTraits<GraphT>>
class ReversePostOrderTraversal {
typedef typename GT::NodeRef NodeRef;
using NodeRef = typename GT::NodeRef;
std::vector<NodeRef> Blocks; // Block list in normal PO order
void Initialize(NodeRef BB) {
@ -294,7 +295,7 @@ class ReversePostOrderTraversal {
}
public:
typedef typename std::vector<NodeRef>::reverse_iterator rpo_iterator;
using rpo_iterator = typename std::vector<NodeRef>::reverse_iterator;
ReversePostOrderTraversal(GraphT G) { Initialize(GT::getEntryNode(G)); }

View File

@ -17,13 +17,14 @@
#define LLVM_ADT_PRIORITYWORKLIST_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Sequence.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Compiler.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <iterator>
#include <type_traits>
#include <vector>
namespace llvm {
@ -55,11 +56,11 @@ template <typename T, typename VectorT = std::vector<T>,
typename MapT = DenseMap<T, ptrdiff_t>>
class PriorityWorklist {
public:
typedef T value_type;
typedef T key_type;
typedef T& reference;
typedef const T& const_reference;
typedef typename MapT::size_type size_type;
using value_type = T;
using key_type = T;
using reference = T&;
using const_reference = const T&;
using size_type = typename MapT::size_type;
/// Construct an empty PriorityWorklist
PriorityWorklist() = default;

View File

@ -1,4 +1,4 @@
//===---- ADT/SCCIterator.h - Strongly Connected Comp. Iter. ----*- C++ -*-===//
//===- ADT/SCCIterator.h - Strongly Connected Comp. Iter. -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -43,10 +43,10 @@ template <class GraphT, class GT = GraphTraits<GraphT>>
class scc_iterator : public iterator_facade_base<
scc_iterator<GraphT, GT>, std::forward_iterator_tag,
const std::vector<typename GT::NodeRef>, ptrdiff_t> {
typedef typename GT::NodeRef NodeRef;
typedef typename GT::ChildIteratorType ChildItTy;
typedef std::vector<NodeRef> SccTy;
typedef typename scc_iterator::reference reference;
using NodeRef = typename GT::NodeRef;
using ChildItTy = typename GT::ChildIteratorType;
using SccTy = std::vector<NodeRef>;
using reference = typename scc_iterator::reference;
/// Element of VisitStack during DFS.
struct StackElement {

View File

@ -13,27 +13,31 @@
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_ADT_SEQ_H
#define LLVM_ADT_SEQ_H
#ifndef LLVM_ADT_SEQUENCE_H
#define LLVM_ADT_SEQUENCE_H
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
#include <algorithm>
#include <iterator>
#include <utility>
namespace llvm {
namespace detail {
template <typename ValueT>
class value_sequence_iterator
: public iterator_facade_base<value_sequence_iterator<ValueT>,
std::random_access_iterator_tag,
const ValueT> {
typedef typename value_sequence_iterator::iterator_facade_base BaseT;
using BaseT = typename value_sequence_iterator::iterator_facade_base;
ValueT Value;
public:
typedef typename BaseT::difference_type difference_type;
typedef typename BaseT::reference reference;
using difference_type = typename BaseT::difference_type;
using reference = typename BaseT::reference;
value_sequence_iterator() = default;
value_sequence_iterator(const value_sequence_iterator &) = default;
@ -65,7 +69,8 @@ class value_sequence_iterator
reference operator*() const { return Value; }
};
} // End detail namespace.
} // end namespace detail
template <typename ValueT>
iterator_range<detail::value_sequence_iterator<ValueT>> seq(ValueT Begin,
@ -74,6 +79,6 @@ iterator_range<detail::value_sequence_iterator<ValueT>> seq(ValueT Begin,
detail::value_sequence_iterator<ValueT>(End));
}
}
} // end namespace llvm
#endif
#endif // LLVM_ADT_SEQUENCE_H

View File

@ -40,17 +40,17 @@ template <typename T, typename Vector = std::vector<T>,
typename Set = DenseSet<T>>
class SetVector {
public:
typedef T value_type;
typedef T key_type;
typedef T& reference;
typedef const T& const_reference;
typedef Set set_type;
typedef Vector vector_type;
typedef typename vector_type::const_iterator iterator;
typedef typename vector_type::const_iterator const_iterator;
typedef typename vector_type::const_reverse_iterator reverse_iterator;
typedef typename vector_type::const_reverse_iterator const_reverse_iterator;
typedef typename vector_type::size_type size_type;
using value_type = T;
using key_type = T;
using reference = T&;
using const_reference = const T&;
using set_type = Set;
using vector_type = Vector;
using iterator = typename vector_type::const_iterator;
using const_iterator = typename vector_type::const_iterator;
using reverse_iterator = typename vector_type::const_reverse_iterator;
using const_reverse_iterator = typename vector_type::const_reverse_iterator;
using size_type = typename vector_type::size_type;
/// \brief Construct an empty SetVector
SetVector() = default;

View File

@ -134,6 +134,19 @@ class SmallBitVector {
}
public:
typedef const_set_bits_iterator_impl<SmallBitVector> const_set_bits_iterator;
typedef const_set_bits_iterator set_iterator;
const_set_bits_iterator set_bits_begin() const {
return const_set_bits_iterator(*this);
}
const_set_bits_iterator set_bits_end() const {
return const_set_bits_iterator(*this, -1);
}
iterator_range<const_set_bits_iterator> set_bits() const {
return make_range(set_bits_begin(), set_bits_end());
}
/// Creates an empty bitvector.
SmallBitVector() : X(1) {}

View File

@ -27,15 +27,13 @@
#include <iterator>
#include <utility>
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
namespace llvm {
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
template <class T = void> struct ReverseIterate { static bool value; };
template <class T> bool ReverseIterate<T>::value = false;
}
#endif
namespace llvm {
/// SmallPtrSetImplBase - This is the common code shared among all the
/// SmallPtrSet<>'s, which is almost everything. SmallPtrSet has two modes, one
/// for small and one for large sets.
@ -92,7 +90,7 @@ class SmallPtrSetImplBase {
}
public:
typedef unsigned size_type;
using size_type = unsigned;
SmallPtrSetImplBase &operator=(const SmallPtrSetImplBase &) = delete;
@ -273,14 +271,14 @@ class SmallPtrSetIteratorImpl {
/// SmallPtrSetIterator - This implements a const_iterator for SmallPtrSet.
template<typename PtrTy>
class SmallPtrSetIterator : public SmallPtrSetIteratorImpl {
typedef PointerLikeTypeTraits<PtrTy> PtrTraits;
using PtrTraits = PointerLikeTypeTraits<PtrTy>;
public:
typedef PtrTy value_type;
typedef PtrTy reference;
typedef PtrTy pointer;
typedef std::ptrdiff_t difference_type;
typedef std::forward_iterator_tag iterator_category;
using value_type = PtrTy;
using reference = PtrTy;
using pointer = PtrTy;
using difference_type = std::ptrdiff_t;
using iterator_category = std::forward_iterator_tag;
explicit SmallPtrSetIterator(const void *const *BP, const void *const *E)
: SmallPtrSetIteratorImpl(BP, E) {}
@ -351,8 +349,8 @@ struct RoundUpToPowerOfTwo {
template <typename PtrType>
class SmallPtrSetImpl : public SmallPtrSetImplBase {
using ConstPtrType = typename add_const_past_pointer<PtrType>::type;
typedef PointerLikeTypeTraits<PtrType> PtrTraits;
typedef PointerLikeTypeTraits<ConstPtrType> ConstPtrTraits;
using PtrTraits = PointerLikeTypeTraits<PtrType>;
using ConstPtrTraits = PointerLikeTypeTraits<ConstPtrType>;
protected:
// Constructors that forward to the base.
@ -365,8 +363,8 @@ class SmallPtrSetImpl : public SmallPtrSetImplBase {
: SmallPtrSetImplBase(SmallStorage, SmallSize) {}
public:
typedef SmallPtrSetIterator<PtrType> iterator;
typedef SmallPtrSetIterator<PtrType> const_iterator;
using iterator = SmallPtrSetIterator<PtrType>;
using const_iterator = SmallPtrSetIterator<PtrType>;
SmallPtrSetImpl(const SmallPtrSetImpl &) = delete;
@ -431,7 +429,7 @@ class SmallPtrSet : public SmallPtrSetImpl<PtrType> {
// DenseSet<> instead if you expect many elements in the set.
static_assert(SmallSize <= 32, "SmallSize should be small");
typedef SmallPtrSetImpl<PtrType> BaseT;
using BaseT = SmallPtrSetImpl<PtrType>;
// Make sure that SmallSize is a power of two, round up if not.
enum { SmallSizePowTwo = RoundUpToPowerOfTwo<SmallSize>::Val };

View File

@ -71,7 +71,7 @@ class SmallVectorTemplateCommon : public SmallVectorBase {
// Allocate raw space for N elements of type T. If T has a ctor or dtor, we
// don't want it to be automatically run, so we need to represent the space as
// something else. Use an array of char of sufficient alignment.
typedef AlignedCharArrayUnion<T> U;
using U = AlignedCharArrayUnion<T>;
U FirstEl;
// Space after 'FirstEl' is clobbered, do not add any instance vars after it.
@ -96,19 +96,19 @@ class SmallVectorTemplateCommon : public SmallVectorBase {
void setEnd(T *P) { this->EndX = P; }
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T value_type;
typedef T *iterator;
typedef const T *const_iterator;
using size_type = size_t;
using difference_type = ptrdiff_t;
using value_type = T;
using iterator = T *;
using const_iterator = const T *;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
using reverse_iterator = std::reverse_iterator<iterator>;
typedef T &reference;
typedef const T &const_reference;
typedef T *pointer;
typedef const T *const_pointer;
using reference = T &;
using const_reference = const T &;
using pointer = T *;
using const_pointer = const T *;
// forward iterator creation methods.
LLVM_ATTRIBUTE_ALWAYS_INLINE
@ -319,12 +319,12 @@ class SmallVectorTemplateBase<T, true> : public SmallVectorTemplateCommon<T> {
/// reduce code duplication based on the SmallVector 'N' template parameter.
template <typename T>
class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
typedef SmallVectorTemplateBase<T, isPodLike<T>::value > SuperClass;
using SuperClass = SmallVectorTemplateBase<T, isPodLike<T>::value>;
public:
typedef typename SuperClass::iterator iterator;
typedef typename SuperClass::const_iterator const_iterator;
typedef typename SuperClass::size_type size_type;
using iterator = typename SuperClass::iterator;
using const_iterator = typename SuperClass::const_iterator;
using size_type = typename SuperClass::size_type;
protected:
// Default ctor - Initialize to empty.
@ -845,8 +845,7 @@ class SmallVector : public SmallVectorImpl<T> {
SmallVectorStorage<T, N> Storage;
public:
SmallVector() : SmallVectorImpl<T>(N) {
}
SmallVector() : SmallVectorImpl<T>(N) {}
explicit SmallVector(size_t Size, const T &Value = T())
: SmallVectorImpl<T>(N) {
@ -883,16 +882,16 @@ class SmallVector : public SmallVectorImpl<T> {
SmallVectorImpl<T>::operator=(::std::move(RHS));
}
const SmallVector &operator=(SmallVector &&RHS) {
SmallVectorImpl<T>::operator=(::std::move(RHS));
return *this;
}
SmallVector(SmallVectorImpl<T> &&RHS) : SmallVectorImpl<T>(N) {
if (!RHS.empty())
SmallVectorImpl<T>::operator=(::std::move(RHS));
}
const SmallVector &operator=(SmallVector &&RHS) {
SmallVectorImpl<T>::operator=(::std::move(RHS));
return *this;
}
const SmallVector &operator=(SmallVectorImpl<T> &&RHS) {
SmallVectorImpl<T>::operator=(::std::move(RHS));
return *this;

View File

@ -1,4 +1,4 @@
//===- llvm/ADT/SparseBitVector.h - Efficient Sparse BitVector -*- C++ -*- ===//
//===- llvm/ADT/SparseBitVector.h - Efficient Sparse BitVector --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -41,8 +41,8 @@ namespace llvm {
template <unsigned ElementSize = 128> struct SparseBitVectorElement {
public:
typedef unsigned long BitWord;
typedef unsigned size_type;
using BitWord = unsigned long;
using size_type = unsigned;
enum {
BITWORD_SIZE = sizeof(BitWord) * CHAR_BIT,
BITWORDS_PER_ELEMENT = (ElementSize + BITWORD_SIZE - 1) / BITWORD_SIZE,
@ -100,7 +100,7 @@ template <unsigned ElementSize = 128> struct SparseBitVectorElement {
Bits[Idx / BITWORD_SIZE] |= 1L << (Idx % BITWORD_SIZE);
}
bool test_and_set (unsigned Idx) {
bool test_and_set(unsigned Idx) {
bool old = test(Idx);
if (!old) {
set(Idx);
@ -254,9 +254,9 @@ template <unsigned ElementSize = 128> struct SparseBitVectorElement {
template <unsigned ElementSize = 128>
class SparseBitVector {
typedef std::list<SparseBitVectorElement<ElementSize>> ElementList;
typedef typename ElementList::iterator ElementListIter;
typedef typename ElementList::const_iterator ElementListConstIter;
using ElementList = std::list<SparseBitVectorElement<ElementSize>>;
using ElementListIter = typename ElementList::iterator;
using ElementListConstIter = typename ElementList::const_iterator;
enum {
BITWORD_SIZE = SparseBitVectorElement<ElementSize>::BITWORD_SIZE
};
@ -421,14 +421,12 @@ class SparseBitVector {
};
public:
typedef SparseBitVectorIterator iterator;
using iterator = SparseBitVectorIterator;
SparseBitVector() {
CurrElementIter = Elements.begin();
}
~SparseBitVector() = default;
// SparseBitVector copy ctor.
SparseBitVector(const SparseBitVector &RHS) {
ElementListConstIter ElementIter = RHS.Elements.begin();
@ -440,6 +438,8 @@ class SparseBitVector {
CurrElementIter = Elements.begin ();
}
~SparseBitVector() = default;
// Clear.
void clear() {
Elements.clear();

View File

@ -1,4 +1,4 @@
//===--- llvm/ADT/SparseMultiSet.h - Sparse multiset ------------*- C++ -*-===//
//===- llvm/ADT/SparseMultiSet.h - Sparse multiset --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -101,7 +101,7 @@ class SparseMultiSet {
unsigned Prev;
unsigned Next;
SMSNode(ValueT D, unsigned P, unsigned N) : Data(D), Prev(P), Next(N) { }
SMSNode(ValueT D, unsigned P, unsigned N) : Data(D), Prev(P), Next(N) {}
/// List tails have invalid Nexts.
bool isTail() const {
@ -118,8 +118,8 @@ class SparseMultiSet {
bool isValid() const { return Prev != INVALID; }
};
typedef typename KeyFunctorT::argument_type KeyT;
typedef SmallVector<SMSNode, 8> DenseT;
using KeyT = typename KeyFunctorT::argument_type;
using DenseT = SmallVector<SMSNode, 8>;
DenseT Dense;
SparseT *Sparse = nullptr;
unsigned Universe = 0;
@ -183,12 +183,12 @@ class SparseMultiSet {
}
public:
typedef ValueT value_type;
typedef ValueT &reference;
typedef const ValueT &const_reference;
typedef ValueT *pointer;
typedef const ValueT *const_pointer;
typedef unsigned size_type;
using value_type = ValueT;
using reference = ValueT &;
using const_reference = const ValueT &;
using pointer = ValueT *;
using const_pointer = const ValueT *;
using size_type = unsigned;
SparseMultiSet() = default;
SparseMultiSet(const SparseMultiSet &) = delete;
@ -227,7 +227,7 @@ class SparseMultiSet {
unsigned SparseIdx;
iterator_base(SMSPtrTy P, unsigned I, unsigned SI)
: SMS(P), Idx(I), SparseIdx(SI) { }
: SMS(P), Idx(I), SparseIdx(SI) {}
/// Whether our iterator has fallen outside our dense vector.
bool isEnd() const {
@ -248,11 +248,11 @@ class SparseMultiSet {
void setNext(unsigned N) { SMS->Dense[Idx].Next = N; }
public:
typedef std::iterator<std::bidirectional_iterator_tag, ValueT> super;
typedef typename super::value_type value_type;
typedef typename super::difference_type difference_type;
typedef typename super::pointer pointer;
typedef typename super::reference reference;
using super = std::iterator<std::bidirectional_iterator_tag, ValueT>;
using value_type = typename super::value_type;
using difference_type = typename super::difference_type;
using pointer = typename super::pointer;
using reference = typename super::reference;
reference operator*() const {
assert(isKeyed() && SMS->sparseIndex(SMS->Dense[Idx].Data) == SparseIdx &&
@ -308,11 +308,12 @@ class SparseMultiSet {
return I;
}
};
typedef iterator_base<SparseMultiSet *> iterator;
typedef iterator_base<const SparseMultiSet *> const_iterator;
using iterator = iterator_base<SparseMultiSet *>;
using const_iterator = iterator_base<const SparseMultiSet *>;
// Convenience types
typedef std::pair<iterator, iterator> RangePair;
using RangePair = std::pair<iterator, iterator>;
/// Returns an iterator past this container. Note that such an iterator cannot
/// be decremented, but will compare equal to other end iterators.

View File

@ -1,4 +1,4 @@
//===--- llvm/ADT/SparseSet.h - Sparse set ----------------------*- C++ -*-===//
//===- llvm/ADT/SparseSet.h - Sparse set ------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -125,9 +125,9 @@ class SparseSet {
!std::numeric_limits<SparseT>::is_signed,
"SparseT must be an unsigned integer type");
typedef typename KeyFunctorT::argument_type KeyT;
typedef SmallVector<ValueT, 8> DenseT;
typedef unsigned size_type;
using KeyT = typename KeyFunctorT::argument_type;
using DenseT = SmallVector<ValueT, 8>;
using size_type = unsigned;
DenseT Dense;
SparseT *Sparse = nullptr;
unsigned Universe = 0;
@ -135,11 +135,11 @@ class SparseSet {
SparseSetValFunctor<KeyT, ValueT, KeyFunctorT> ValIndexOf;
public:
typedef ValueT value_type;
typedef ValueT &reference;
typedef const ValueT &const_reference;
typedef ValueT *pointer;
typedef const ValueT *const_pointer;
using value_type = ValueT;
using reference = ValueT &;
using const_reference = const ValueT &;
using pointer = ValueT *;
using const_pointer = const ValueT *;
SparseSet() = default;
SparseSet(const SparseSet &) = delete;
@ -168,8 +168,8 @@ class SparseSet {
}
// Import trivial vector stuff from DenseT.
typedef typename DenseT::iterator iterator;
typedef typename DenseT::const_iterator const_iterator;
using iterator = typename DenseT::iterator;
using const_iterator = typename DenseT::const_iterator;
const_iterator begin() const { return Dense.begin(); }
const_iterator end() const { return Dense.end(); }

View File

@ -1,4 +1,4 @@
//===-- llvm/ADT/StringExtras.h - Useful string functions -------*- C++ -*-===//
//===- llvm/ADT/StringExtras.h - Useful string functions --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -15,12 +15,18 @@
#define LLVM_ADT_STRINGEXTRAS_H
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DataTypes.h"
#include <iterator>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <string>
#include <utility>
namespace llvm {
class raw_ostream;
template<typename T> class SmallVectorImpl;
class raw_ostream;
/// hexdigit - Return the hexadecimal character for the
/// given number \p X (which should be less than 16).
@ -128,7 +134,6 @@ static inline std::string utostr(uint64_t X, bool isNeg = false) {
return std::string(BufPtr, std::end(Buffer));
}
static inline std::string itostr(int64_t X) {
if (X < 0)
return utostr(static_cast<uint64_t>(-X), true);
@ -261,13 +266,14 @@ template <typename A1, typename... Args>
inline size_t join_items_size(const A1 &A, Args &&... Items) {
return join_one_item_size(A) + join_items_size(std::forward<Args>(Items)...);
}
}
} // end namespace detail
/// Joins the strings in the range [Begin, End), adding Separator between
/// the elements.
template <typename IteratorT>
inline std::string join(IteratorT Begin, IteratorT End, StringRef Separator) {
typedef typename std::iterator_traits<IteratorT>::iterator_category tag;
using tag = typename std::iterator_traits<IteratorT>::iterator_category;
return detail::join_impl(Begin, End, Separator, tag());
}
@ -295,6 +301,6 @@ inline std::string join_items(Sep Separator, Args &&... Items) {
return Result;
}
} // End llvm namespace
} // end namespace llvm
#endif
#endif // LLVM_ADT_STRINGEXTRAS_H

View File

@ -1,4 +1,4 @@
//===--- StringMap.h - String Hash table map interface ----------*- C++ -*-===//
//===- StringMap.h - String Hash table map interface ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -16,25 +16,23 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <initializer_list>
#include <new>
#include <iterator>
#include <utility>
namespace llvm {
template<typename ValueT>
class StringMapConstIterator;
template<typename ValueT>
class StringMapIterator;
template <typename ValueT> class StringMapKeyIterator;
template<typename ValueTy>
class StringMapEntry;
template<typename ValueTy> class StringMapConstIterator;
template<typename ValueTy> class StringMapIterator;
template<typename ValueTy> class StringMapKeyIterator;
/// StringMapEntryBase - Shared base class of StringMapEntry instances.
class StringMapEntryBase {
@ -53,17 +51,15 @@ class StringMapImpl {
// Array of NumBuckets pointers to entries, null pointers are holes.
// TheTable[NumBuckets] contains a sentinel value for easy iteration. Followed
// by an array of the actual hash values as unsigned integers.
StringMapEntryBase **TheTable;
unsigned NumBuckets;
unsigned NumItems;
unsigned NumTombstones;
StringMapEntryBase **TheTable = nullptr;
unsigned NumBuckets = 0;
unsigned NumItems = 0;
unsigned NumTombstones = 0;
unsigned ItemSize;
protected:
explicit StringMapImpl(unsigned itemSize)
: TheTable(nullptr),
// Initialize the map with zero buckets to allocation.
NumBuckets(0), NumItems(0), NumTombstones(0), ItemSize(itemSize) {}
: ItemSize(itemSize) {}
StringMapImpl(StringMapImpl &&RHS)
: TheTable(RHS.TheTable), NumBuckets(RHS.NumBuckets),
NumItems(RHS.NumItems), NumTombstones(RHS.NumTombstones),
@ -225,9 +221,10 @@ class StringMap : public StringMapImpl {
AllocatorTy Allocator;
public:
typedef StringMapEntry<ValueTy> MapEntryTy;
using MapEntryTy = StringMapEntry<ValueTy>;
StringMap() : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) {}
explicit StringMap(unsigned InitialSize)
: StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))) {}
@ -248,12 +245,6 @@ class StringMap : public StringMapImpl {
StringMap(StringMap &&RHS)
: StringMapImpl(std::move(RHS)), Allocator(std::move(RHS.Allocator)) {}
StringMap &operator=(StringMap RHS) {
StringMapImpl::swap(RHS);
std::swap(Allocator, RHS.Allocator);
return *this;
}
StringMap(const StringMap &RHS) :
StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))),
Allocator(RHS.Allocator) {
@ -289,16 +280,37 @@ class StringMap : public StringMapImpl {
// not worthwhile.
}
StringMap &operator=(StringMap RHS) {
StringMapImpl::swap(RHS);
std::swap(Allocator, RHS.Allocator);
return *this;
}
~StringMap() {
// Delete all the elements in the map, but don't reset the elements
// to default values. This is a copy of clear(), but avoids unnecessary
// work not required in the destructor.
if (!empty()) {
for (unsigned I = 0, E = NumBuckets; I != E; ++I) {
StringMapEntryBase *Bucket = TheTable[I];
if (Bucket && Bucket != getTombstoneVal()) {
static_cast<MapEntryTy*>(Bucket)->Destroy(Allocator);
}
}
}
free(TheTable);
}
AllocatorTy &getAllocator() { return Allocator; }
const AllocatorTy &getAllocator() const { return Allocator; }
typedef const char* key_type;
typedef ValueTy mapped_type;
typedef StringMapEntry<ValueTy> value_type;
typedef size_t size_type;
using key_type = const char*;
using mapped_type = ValueTy;
using value_type = StringMapEntry<ValueTy>;
using size_type = size_t;
typedef StringMapConstIterator<ValueTy> const_iterator;
typedef StringMapIterator<ValueTy> iterator;
using const_iterator = StringMapConstIterator<ValueTy>;
using iterator = StringMapIterator<ValueTy>;
iterator begin() {
return iterator(TheTable, NumBuckets == 0);
@ -313,7 +325,7 @@ class StringMap : public StringMapImpl {
return const_iterator(TheTable+NumBuckets, true);
}
llvm::iterator_range<StringMapKeyIterator<ValueTy>> keys() const {
iterator_range<StringMapKeyIterator<ValueTy>> keys() const {
return make_range(StringMapKeyIterator<ValueTy>(begin()),
StringMapKeyIterator<ValueTy>(end()));
}
@ -433,21 +445,6 @@ class StringMap : public StringMapImpl {
erase(I);
return true;
}
~StringMap() {
// Delete all the elements in the map, but don't reset the elements
// to default values. This is a copy of clear(), but avoids unnecessary
// work not required in the destructor.
if (!empty()) {
for (unsigned I = 0, E = NumBuckets; I != E; ++I) {
StringMapEntryBase *Bucket = TheTable[I];
if (Bucket && Bucket != getTombstoneVal()) {
static_cast<MapEntryTy*>(Bucket)->Destroy(Allocator);
}
}
}
free(TheTable);
}
};
template <typename DerivedTy, typename ValueTy>
@ -542,7 +539,6 @@ class StringMapKeyIterator
public:
StringMapKeyIterator() = default;
explicit StringMapKeyIterator(StringMapConstIterator<ValueTy> Iter)
: base(std::move(Iter)) {}

View File

@ -1,4 +1,4 @@
//===--- StringRef.h - Constant String Reference Wrapper --------*- C++ -*-===//
//===- StringRef.h - Constant String Reference Wrapper ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -15,16 +15,18 @@
#include "llvm/Support/Compiler.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstring>
#include <limits>
#include <type_traits>
#include <string>
#include <utility>
namespace llvm {
template <typename T>
class SmallVectorImpl;
class APInt;
class hash_code;
template <typename T> class SmallVectorImpl;
class StringRef;
/// Helper functions for StringRef::getAsInteger.
@ -46,10 +48,11 @@ namespace llvm {
/// general safe to store a StringRef.
class StringRef {
public:
typedef const char *iterator;
typedef const char *const_iterator;
static const size_t npos = ~size_t(0);
typedef size_t size_type;
using iterator = const char *;
using const_iterator = const char *;
using size_type = size_t;
private:
/// The start of the string, in an external buffer.
@ -906,6 +909,7 @@ namespace llvm {
// StringRefs can be treated like a POD type.
template <typename T> struct isPodLike;
template <> struct isPodLike<StringRef> { static const bool value = true; };
}
#endif
} // end namespace llvm
#endif // LLVM_ADT_STRINGREF_H

View File

@ -1,4 +1,4 @@
//===--- StringSet.h - The LLVM Compiler Driver -----------------*- C++ -*-===//
//===- StringSet.h - The LLVM Compiler Driver -------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -15,13 +15,19 @@
#define LLVM_ADT_STRINGSET_H
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
#include <cassert>
#include <initializer_list>
#include <utility>
namespace llvm {
/// StringSet - A wrapper for StringMap that provides set-like functionality.
template <class AllocatorTy = llvm::MallocAllocator>
class StringSet : public llvm::StringMap<char, AllocatorTy> {
typedef llvm::StringMap<char, AllocatorTy> base;
template <class AllocatorTy = MallocAllocator>
class StringSet : public StringMap<char, AllocatorTy> {
using base = StringMap<char, AllocatorTy>;
public:
StringSet() = default;
StringSet(std::initializer_list<StringRef> S) {
@ -40,6 +46,7 @@ namespace llvm {
base::insert(std::make_pair(*It, '\0'));
}
};
}
} // end namespace llvm
#endif // LLVM_ADT_STRINGSET_H

View File

@ -30,9 +30,9 @@ namespace llvm {
template <typename EltTy>
class TinyPtrVector {
public:
typedef SmallVector<EltTy, 4> VecTy;
typedef typename VecTy::value_type value_type;
typedef PointerUnion<EltTy, VecTy *> PtrUnion;
using VecTy = SmallVector<EltTy, 4>;
using value_type = typename VecTy::value_type;
using PtrUnion = PointerUnion<EltTy, VecTy *>;
private:
PtrUnion Val;
@ -167,10 +167,10 @@ class TinyPtrVector {
return Val.template get<VecTy*>()->size();
}
typedef EltTy *iterator;
typedef const EltTy *const_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
using iterator = EltTy *;
using const_iterator = const EltTy *;
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
iterator begin() {
if (Val.template is<EltTy>())

View File

@ -1,4 +1,4 @@
//===-- llvm/ADT/UniqueVector.h ---------------------------------*- C++ -*-===//
//===- llvm/ADT/UniqueVector.h ----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -24,16 +24,15 @@ namespace llvm {
/// Entries can be fetched using operator[] with the entry ID.
template<class T> class UniqueVector {
public:
typedef typename std::vector<T> VectorType;
typedef typename VectorType::iterator iterator;
typedef typename VectorType::const_iterator const_iterator;
using VectorType = typename std::vector<T>;
using iterator = typename VectorType::iterator;
using const_iterator = typename VectorType::const_iterator;
private:
// Map - Used to handle the correspondence of entry to ID.
std::map<T, unsigned> Map;
// Vector - ID ordered vector of entries. Entries can be indexed by ID - 1.
//
VectorType Vector;
public:
@ -68,7 +67,6 @@ template<class T> class UniqueVector {
}
/// operator[] - Returns a reference to the entry with the specified ID.
///
const T &operator[](unsigned ID) const {
assert(ID-1 < size() && "ID is 0 or out of range!");
return Vector[ID - 1];
@ -87,21 +85,18 @@ template<class T> class UniqueVector {
const_iterator end() const { return Vector.end(); }
/// size - Returns the number of entries in the vector.
///
size_t size() const { return Vector.size(); }
/// empty - Returns true if the vector is empty.
///
bool empty() const { return Vector.empty(); }
/// reset - Clears all the entries.
///
void reset() {
Map.clear();
Vector.resize(0, 0);
}
};
} // End of namespace llvm
} // end namespace llvm
#endif // LLVM_ADT_UNIQUEVECTOR_H

View File

@ -55,6 +55,21 @@ class ProfileSummaryInfo {
ProfileSummaryInfo(ProfileSummaryInfo &&Arg)
: M(Arg.M), Summary(std::move(Arg.Summary)) {}
/// \brief Returns true if profile summary is available.
bool hasProfileSummary() { return computeSummary(); }
/// \brief Returns true if module \c M has sample profile.
bool hasSampleProfile() {
return hasProfileSummary() &&
Summary->getKind() == ProfileSummary::PSK_Sample;
}
/// \brief Returns true if module \c M has instrumentation profile.
bool hasInstrumentationProfile() {
return hasProfileSummary() &&
Summary->getKind() == ProfileSummary::PSK_Instr;
}
/// Handle the invalidation of this information.
///
/// When used as a result of \c ProfileSummaryAnalysis this method will be

View File

@ -28,7 +28,7 @@ class CVTypeVisitor {
Error visitTypeRecord(CVType &Record, TypeIndex Index);
Error visitTypeRecord(CVType &Record);
Error visitMemberRecord(CVMemberRecord &Record);
Error visitMemberRecord(CVMemberRecord Record);
/// Visits the type records in Data. Sets the error flag on parse failures.
Error visitTypeStream(const CVTypeArray &Types);
@ -47,6 +47,36 @@ class CVTypeVisitor {
TinyPtrVector<TypeServerHandler *> Handlers;
};
enum VisitorDataSource {
VDS_BytesPresent, // The record bytes are passed into the the visitation
// function. The algorithm should first deserialize them
// before passing them on through the pipeline.
VDS_BytesExternal // The record bytes are not present, and it is the
// responsibility of the visitor callback interface to
// supply the bytes.
};
Error visitTypeRecord(CVType &Record, TypeIndex Index,
TypeVisitorCallbacks &Callbacks,
VisitorDataSource Source = VDS_BytesPresent,
TypeServerHandler *TS = nullptr);
Error visitTypeRecord(CVType &Record, TypeVisitorCallbacks &Callbacks,
VisitorDataSource Source = VDS_BytesPresent,
TypeServerHandler *TS = nullptr);
Error visitMemberRecord(CVMemberRecord Record, TypeVisitorCallbacks &Callbacks,
VisitorDataSource Source = VDS_BytesPresent);
Error visitMemberRecord(TypeLeafKind Kind, ArrayRef<uint8_t> Record,
TypeVisitorCallbacks &Callbacks);
Error visitMemberRecordStream(ArrayRef<uint8_t> FieldList,
TypeVisitorCallbacks &Callbacks);
Error visitTypeStream(const CVTypeArray &Types, TypeVisitorCallbacks &Callbacks,
TypeServerHandler *TS = nullptr);
Error visitTypeStream(CVTypeRange Types, TypeVisitorCallbacks &Callbacks,
TypeServerHandler *TS = nullptr);
} // end namespace codeview
} // end namespace llvm

View File

@ -11,13 +11,10 @@
#define LLVM_DEBUGINFO_CODEVIEW_RANDOMACCESSTYPEVISITOR_H
#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
#include "llvm/Support/Error.h"
namespace llvm {
@ -73,18 +70,6 @@ class RandomAccessTypeVisitor {
/// The database visitor which adds new records to the database.
TypeDatabaseVisitor DatabaseVisitor;
/// The deserializer which deserializes new records.
TypeDeserializer Deserializer;
/// The visitation callback pipeline to use. By default this contains a
/// deserializer and a type database visitor. But the callback specified
/// in the constructor is also added.
TypeVisitorCallbackPipeline Pipeline;
/// The visitor used to visit the internal pipeline for deserialization and
/// database maintenance.
CVTypeVisitor InternalVisitor;
/// A vector mapping type indices to type offset. For every record that has
/// been visited, contains the absolute offset of that record in the record
/// array.

View File

@ -31,10 +31,10 @@ struct DWARFAttribute {
dwarf::Attribute Attr;
/// The form and value for this attribute.
DWARFFormValue Value;
DWARFAttribute(uint32_t O, dwarf::Attribute A = dwarf::Attribute(0),
dwarf::Form F = dwarf::Form(0)) : Attr(A), Value(F) {}
bool isValid() const {
return Offset != 0 && Attr != dwarf::Attribute(0);
}

View File

@ -22,19 +22,19 @@ class raw_ostream;
class DWARFDebugArangeSet {
public:
struct Header {
// The total length of the entries for that set, not including the length
// field itself.
/// The total length of the entries for that set, not including the length
/// field itself.
uint32_t Length;
// The offset from the beginning of the .debug_info section of the
// compilation unit entry referenced by the table.
/// The offset from the beginning of the .debug_info section of the
/// compilation unit entry referenced by the table.
uint32_t CuOffset;
// The DWARF version number.
/// The DWARF version number.
uint16_t Version;
// The size in bytes of an address on the target architecture. For segmented
// addressing, this is the size of the offset portion of the address.
/// The size in bytes of an address on the target architecture. For segmented
/// addressing, this is the size of the offset portion of the address.
uint8_t AddrSize;
// The size in bytes of a segment descriptor on the target architecture.
// If the target system uses a flat address space, this value is 0.
/// The size in bytes of a segment descriptor on the target architecture.
/// If the target system uses a flat address space, this value is 0.
uint8_t SegSize;
};

View File

@ -28,7 +28,7 @@ class DWARFDebugAranges {
void clear();
void extract(DataExtractor DebugArangesData);
// Call appendRange multiple times and then call construct.
/// Call appendRange multiple times and then call construct.
void appendRange(uint32_t CUOffset, uint64_t LowPC, uint64_t HighPC);
void construct();
@ -58,9 +58,9 @@ class DWARFDebugAranges {
return LowPC < other.LowPC;
}
uint64_t LowPC; // Start of address range.
uint32_t Length; // End of address range (not including this address).
uint32_t CUOffset; // Offset of the compile unit or die.
uint64_t LowPC; /// Start of address range.
uint32_t Length; /// End of address range (not including this address).
uint32_t CUOffset; /// Offset of the compile unit or die.
};
struct RangeEndpoint {

View File

@ -33,31 +33,31 @@ typedef std::vector<DWARFAddressRange> DWARFAddressRangesVector;
class DWARFDebugRangeList {
public:
struct RangeListEntry {
// A beginning address offset. This address offset has the size of an
// address and is relative to the applicable base address of the
// compilation unit referencing this range list. It marks the beginning
// of an address range.
/// A beginning address offset. This address offset has the size of an
/// address and is relative to the applicable base address of the
/// compilation unit referencing this range list. It marks the beginning
/// of an address range.
uint64_t StartAddress;
// An ending address offset. This address offset again has the size of
// an address and is relative to the applicable base address of the
// compilation unit referencing this range list. It marks the first
// address past the end of the address range. The ending address must
// be greater than or equal to the beginning address.
/// An ending address offset. This address offset again has the size of
/// an address and is relative to the applicable base address of the
/// compilation unit referencing this range list. It marks the first
/// address past the end of the address range. The ending address must
/// be greater than or equal to the beginning address.
uint64_t EndAddress;
// The end of any given range list is marked by an end of list entry,
// which consists of a 0 for the beginning address offset
// and a 0 for the ending address offset.
/// The end of any given range list is marked by an end of list entry,
/// which consists of a 0 for the beginning address offset
/// and a 0 for the ending address offset.
bool isEndOfListEntry() const {
return (StartAddress == 0) && (EndAddress == 0);
}
// A base address selection entry consists of:
// 1. The value of the largest representable address offset
// (for example, 0xffffffff when the size of an address is 32 bits).
// 2. An address, which defines the appropriate base address for
// use in interpreting the beginning and ending address offsets of
// subsequent entries of the location list.
/// A base address selection entry consists of:
/// 1. The value of the largest representable address offset
/// (for example, 0xffffffff when the size of an address is 32 bits).
/// 2. An address, which defines the appropriate base address for
/// use in interpreting the beginning and ending address offsets of
/// subsequent entries of the location list.
bool isBaseAddressSelectionEntry(uint8_t AddressSize) const {
assert(AddressSize == 4 || AddressSize == 8);
if (AddressSize == 4)
@ -68,7 +68,7 @@ class DWARFDebugRangeList {
};
private:
// Offset in .debug_ranges section.
/// Offset in .debug_ranges section.
uint32_t Offset;
uint8_t AddressSize;
std::vector<RangeListEntry> Entries;

View File

@ -24,10 +24,10 @@
#include <iterator>
namespace llvm {
class DWARFUnit;
class raw_ostream;
//===----------------------------------------------------------------------===//
/// Utility class that carries the DWARF compile/type unit and the debug info
/// entry in an object.
@ -47,7 +47,7 @@ class DWARFDie {
public:
DWARFDie() = default;
DWARFDie(DWARFUnit *Unit, const DWARFDebugInfoEntry * D) : U(Unit), Die(D) {}
bool isValid() const { return U && Die; }
explicit operator bool() const { return isValid(); }
const DWARFDebugInfoEntry *getDebugInfoEntry() const { return Die; }
@ -68,7 +68,7 @@ class DWARFDie {
assert(isValid() && "must check validity prior to calling");
return Die->getOffset();
}
dwarf::Tag getTag() const {
auto AbbrevDecl = getAbbreviationDeclarationPtr();
if (AbbrevDecl)
@ -80,7 +80,7 @@ class DWARFDie {
assert(isValid() && "must check validity prior to calling");
return Die->hasChildren();
}
/// Returns true for a valid DIE that terminates a sibling chain.
bool isNULL() const {
return getAbbreviationDeclarationPtr() == nullptr;
@ -97,13 +97,13 @@ class DWARFDie {
/// \returns a valid DWARFDie instance if this object has a parent or an
/// invalid DWARFDie instance if it doesn't.
DWARFDie getParent() const;
/// Get the sibling of this DIE object.
///
/// \returns a valid DWARFDie instance if this object has a sibling or an
/// invalid DWARFDie instance if it doesn't.
DWARFDie getSibling() const;
/// Get the first child of this DIE object.
///
/// \returns a valid DWARFDie instance if this object has children or an
@ -113,7 +113,7 @@ class DWARFDie {
return DWARFDie(U, Die + 1);
return DWARFDie();
}
/// Dump the DIE and all of its attributes to the supplied stream.
///
/// \param OS the stream to use for output.
@ -121,7 +121,7 @@ class DWARFDie {
/// children.
/// \param indent the number of characters to indent each line that is output.
void dump(raw_ostream &OS, unsigned recurseDepth, unsigned indent = 0) const;
/// Extract the specified attribute from this DIE.
///
/// Extract an attribute value from this DIE only. This call doesn't look
@ -132,7 +132,7 @@ class DWARFDie {
/// \returns an optional DWARFFormValue that will have the form value if the
/// attribute was successfully extracted.
Optional<DWARFFormValue> find(dwarf::Attribute Attr) const;
/// Extract the first value of any attribute in Attrs from this DIE.
///
/// Extract the first attribute that matches from this DIE only. This call
@ -180,7 +180,7 @@ class DWARFDie {
///
/// \returns anm optional absolute section offset value for the attribute.
Optional<uint64_t> getRangesBaseAttribute() const;
/// Get the DW_AT_high_pc attribute value as an address.
///
/// In DWARF version 4 and later the high PC can be encoded as an offset from
@ -196,7 +196,7 @@ class DWARFDie {
/// Retrieves DW_AT_low_pc and DW_AT_high_pc from CU.
/// Returns true if both attributes are present.
bool getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC) const;
/// Get the address ranges for this DIE.
///
/// Get the hi/low PC range if both attributes are available or exrtracts the
@ -208,7 +208,7 @@ class DWARFDie {
/// \returns a address range vector that might be empty if no address range
/// information is available.
DWARFAddressRangesVector getAddressRanges() const;
/// Get all address ranges for any DW_TAG_subprogram DIEs in this DIE or any
/// of its children.
///
@ -218,19 +218,19 @@ class DWARFDie {
///
/// \param Ranges the addres range vector to fill in.
void collectChildrenAddressRanges(DWARFAddressRangesVector &Ranges) const;
bool addressRangeContainsAddress(const uint64_t Address) const;
/// If a DIE represents a subprogram (or inlined subroutine), returns its
/// mangled name (or short name, if mangled is missing). This name may be
/// fetched from specification or abstract origin for this subprogram.
/// Returns null if no name is found.
const char *getSubroutineName(DINameKind Kind) const;
/// Return the DIE name resolving DW_AT_sepcification or DW_AT_abstract_origin
/// references if necessary. Returns null if no name is found.
const char *getName(DINameKind Kind) const;
/// Returns the declaration line (start line) for a DIE, assuming it specifies
/// a subprogram. This may be fetched from specification or abstract origin
/// for this subprogram by resolving DW_AT_sepcification or
@ -251,21 +251,21 @@ class DWARFDie {
/// there is no DW_AT_GNU_discriminator attribute in this DIE.
void getCallerFrame(uint32_t &CallFile, uint32_t &CallLine,
uint32_t &CallColumn, uint32_t &CallDiscriminator) const;
class attribute_iterator;
/// Get an iterator range to all attributes in the current DIE only.
///
/// \returns an iterator range for the attributes of the current DIE.
iterator_range<attribute_iterator> attributes() const;
class iterator;
iterator begin() const;
iterator end() const;
iterator_range<iterator> children() const;
};
class DWARFDie::attribute_iterator :
public iterator_facade_base<attribute_iterator, std::forward_iterator_tag,
const DWARFAttribute> {
@ -275,7 +275,7 @@ class DWARFDie::attribute_iterator :
DWARFAttribute AttrValue;
/// The attribute index within the abbreviation declaration in Die.
uint32_t Index;
/// Update the attribute index and attempt to read the attribute value. If the
/// attribute is able to be read, update AttrValue and the Index member
/// variable. If the attribute value is not able to be read, an appropriate

View File

@ -49,9 +49,9 @@ class DWARFFormValue {
const uint8_t *data = nullptr;
};
dwarf::Form Form; // Form for this value.
ValueType Value; // Contains all data for the form.
const DWARFUnit *U = nullptr; // Remember the DWARFUnit at extract time.
dwarf::Form Form; /// Form for this value.
ValueType Value; /// Contains all data for the form.
const DWARFUnit *U = nullptr; /// Remember the DWARFUnit at extract time.
public:
DWARFFormValue(dwarf::Form F = dwarf::Form(0)) : Form(F) {}
@ -72,11 +72,14 @@ class DWARFFormValue {
const DWARFUnit *getUnit() const { return U; }
void dump(raw_ostream &OS) const;
/// \brief extracts a value in data at offset *offset_ptr.
/// Extracts a value in \p Data at offset \p *OffsetPtr.
///
/// The passed DWARFUnit is allowed to be nullptr, in which
/// case no relocation processing will be performed and some
/// kind of forms that depend on Unit information are disallowed.
/// \param Data The DataExtractor to use.
/// \param OffsetPtr The offset within DataExtractor where the data starts.
/// \param U The optional DWARFUnit supplying information for some forms.
/// \returns whether the extraction succeeded.
bool extractValue(const DataExtractor &Data, uint32_t *OffsetPtr,
const DWARFUnit *U);

View File

@ -29,25 +29,25 @@ class DWARFGdbIndex {
uint32_t ConstantPoolOffset;
struct CompUnitEntry {
uint64_t Offset; // Offset of a CU in the .debug_info section.
uint64_t Length; // Length of that CU.
uint64_t Offset; /// Offset of a CU in the .debug_info section.
uint64_t Length; /// Length of that CU.
};
SmallVector<CompUnitEntry, 0> CuList;
struct AddressEntry {
uint64_t LowAddress; // The low address.
uint64_t HighAddress; // The high address.
uint32_t CuIndex; // The CU index.
uint64_t LowAddress; /// The low address.
uint64_t HighAddress; /// The high address.
uint32_t CuIndex; /// The CU index.
};
SmallVector<AddressEntry, 0> AddressArea;
struct SymTableEntry {
uint32_t NameOffset; // Offset of the symbol's name in the constant pool.
uint32_t VecOffset; // Offset of the CU vector in the constant pool.
uint32_t NameOffset; /// Offset of the symbol's name in the constant pool.
uint32_t VecOffset; /// Offset of the CU vector in the constant pool.
};
SmallVector<SymTableEntry, 0> SymbolTable;
// Each value is CU index + attributes.
/// Each value is CU index + attributes.
SmallVector<std::pair<uint32_t, SmallVector<uint32_t, 0>>, 0>
ConstantPoolVectors;

View File

@ -17,15 +17,14 @@
namespace llvm {
struct RelocAddrEntry {
uint8_t Width;
int64_t Value;
};
// In place of applying the relocations to the data we've read from disk we use
// a separate mapping table to the side and checking that at locations in the
// dwarf where we expect relocated values. This adds a bit of complexity to the
// dwarf parsing/extraction at the benefit of not allocating memory for the
// entire size of the debug info sections.
/// In place of applying the relocations to the data we've read from disk we use
/// a separate mapping table to the side and checking that at locations in the
/// dwarf where we expect relocated values. This adds a bit of complexity to the
/// dwarf parsing/extraction at the benefit of not allocating memory for the
/// entire size of the debug info sections.
typedef DenseMap<uint64_t, RelocAddrEntry> RelocAddrMap;
} // end namespace llvm

View File

@ -111,7 +111,7 @@ class DWARFUnitSection final : public SmallVector<std::unique_ptr<UnitType>, 1>,
class DWARFUnit {
DWARFContext &Context;
// Section containing this DWARFUnit.
/// Section containing this DWARFUnit.
const DWARFSection &InfoSection;
const DWARFDebugAbbrev *Abbrev;
@ -133,12 +133,12 @@ class DWARFUnit {
uint8_t UnitType;
uint8_t AddrSize;
uint64_t BaseAddr;
// The compile unit debug information entry items.
/// The compile unit debug information entry items.
std::vector<DWARFDebugInfoEntry> DieArray;
// Map from range's start address to end address and corresponding DIE.
// IntervalMap does not support range removal, as a result, we use the
// std::map::upper_bound for address range lookup.
/// Map from range's start address to end address and corresponding DIE.
/// IntervalMap does not support range removal, as a result, we use the
/// std::map::upper_bound for address range lookup.
std::map<uint64_t, std::pair<uint64_t, DWARFDie>> AddrDieMap;
typedef iterator_range<std::vector<DWARFDebugInfoEntry>::iterator>
die_iterator_range;
@ -189,7 +189,7 @@ class DWARFUnit {
AddrOffsetSectionBase = Base;
}
// Recursively update address to Die map.
/// Recursively update address to Die map.
void updateAddressDieMap(DWARFDie Die);
void setRangesSection(const DWARFSection *RS, uint32_t Base) {

View File

@ -51,6 +51,7 @@ class TpiStream {
HashTable &getHashAdjusters();
codeview::CVTypeRange types(bool *HadError) const;
const codeview::CVTypeArray &typeArray() const { return TypeRecords; }
Error commit();

View File

@ -1132,4 +1132,6 @@ def int_ppc_tsuspend : GCCBuiltin<"__builtin_tsuspend">,
def int_ppc_ttest : GCCBuiltin<"__builtin_ttest">,
Intrinsic<[llvm_i64_ty], [], []>;
def int_ppc_cfence : Intrinsic<[], [llvm_anyint_ty], []>;
}

View File

@ -62,6 +62,7 @@ def : GINodeEquiv<G_FMUL, fmul>;
def : GINodeEquiv<G_FDIV, fdiv>;
def : GINodeEquiv<G_FREM, frem>;
def : GINodeEquiv<G_FPOW, fpow>;
def : GINodeEquiv<G_INTRINSIC, intrinsic_wo_chain>;
def : GINodeEquiv<G_BR, br>;
// Specifies the GlobalISel equivalents for SelectionDAG's ComplexPattern.

View File

@ -2984,7 +2984,7 @@ bool DependenceInfo::propagate(const SCEV *&Src, const SCEV *&Dst,
SmallVectorImpl<Constraint> &Constraints,
bool &Consistent) {
bool Result = false;
for (int LI = Loops.find_first(); LI >= 0; LI = Loops.find_next(LI)) {
for (unsigned LI : Loops.set_bits()) {
DEBUG(dbgs() << "\t Constraint[" << LI << "] is");
DEBUG(Constraints[LI].dump(dbgs()));
if (Constraints[LI].isDistance())
@ -3266,7 +3266,7 @@ bool DependenceInfo::tryDelinearize(Instruction *Src, Instruction *Dst,
// For debugging purposes, dump a small bit vector to dbgs().
static void dumpSmallBitVector(SmallBitVector &BV) {
dbgs() << "{";
for (int VI = BV.find_first(); VI >= 0; VI = BV.find_next(VI)) {
for (unsigned VI : BV.set_bits()) {
dbgs() << VI;
if (BV.find_next(VI) >= 0)
dbgs() << ' ';
@ -3506,7 +3506,7 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst,
NewConstraint.setAny(SE);
// test separable subscripts
for (int SI = Separable.find_first(); SI >= 0; SI = Separable.find_next(SI)) {
for (unsigned SI : Separable.set_bits()) {
DEBUG(dbgs() << "testing subscript " << SI);
switch (Pair[SI].Classification) {
case Subscript::ZIV:
@ -3545,14 +3545,14 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst,
SmallVector<Constraint, 4> Constraints(MaxLevels + 1);
for (unsigned II = 0; II <= MaxLevels; ++II)
Constraints[II].setAny(SE);
for (int SI = Coupled.find_first(); SI >= 0; SI = Coupled.find_next(SI)) {
for (unsigned SI : Coupled.set_bits()) {
DEBUG(dbgs() << "testing subscript group " << SI << " { ");
SmallBitVector Group(Pair[SI].Group);
SmallBitVector Sivs(Pairs);
SmallBitVector Mivs(Pairs);
SmallBitVector ConstrainedLevels(MaxLevels + 1);
SmallVector<Subscript *, 4> PairsInGroup;
for (int SJ = Group.find_first(); SJ >= 0; SJ = Group.find_next(SJ)) {
for (unsigned SJ : Group.set_bits()) {
DEBUG(dbgs() << SJ << " ");
if (Pair[SJ].Classification == Subscript::SIV)
Sivs.set(SJ);
@ -3564,7 +3564,7 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst,
DEBUG(dbgs() << "}\n");
while (Sivs.any()) {
bool Changed = false;
for (int SJ = Sivs.find_first(); SJ >= 0; SJ = Sivs.find_next(SJ)) {
for (unsigned SJ : Sivs.set_bits()) {
DEBUG(dbgs() << "testing subscript " << SJ << ", SIV\n");
// SJ is an SIV subscript that's part of the current coupled group
unsigned Level;
@ -3588,7 +3588,7 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst,
DEBUG(dbgs() << " propagating\n");
DEBUG(dbgs() << "\tMivs = ");
DEBUG(dumpSmallBitVector(Mivs));
for (int SJ = Mivs.find_first(); SJ >= 0; SJ = Mivs.find_next(SJ)) {
for (unsigned SJ : Mivs.set_bits()) {
// SJ is an MIV subscript that's part of the current coupled group
DEBUG(dbgs() << "\tSJ = " << SJ << "\n");
if (propagate(Pair[SJ].Src, Pair[SJ].Dst, Pair[SJ].Loops,
@ -3622,7 +3622,7 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst,
}
// test & propagate remaining RDIVs
for (int SJ = Mivs.find_first(); SJ >= 0; SJ = Mivs.find_next(SJ)) {
for (unsigned SJ : Mivs.set_bits()) {
if (Pair[SJ].Classification == Subscript::RDIV) {
DEBUG(dbgs() << "RDIV test\n");
if (testRDIV(Pair[SJ].Src, Pair[SJ].Dst, Result))
@ -3635,7 +3635,7 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst,
// test remaining MIVs
// This code is temporary.
// Better to somehow test all remaining subscripts simultaneously.
for (int SJ = Mivs.find_first(); SJ >= 0; SJ = Mivs.find_next(SJ)) {
for (unsigned SJ : Mivs.set_bits()) {
if (Pair[SJ].Classification == Subscript::MIV) {
DEBUG(dbgs() << "MIV test\n");
if (testMIV(Pair[SJ].Src, Pair[SJ].Dst, Pair[SJ].Loops, Result))
@ -3647,9 +3647,8 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst,
// update Result.DV from constraint vector
DEBUG(dbgs() << " updating\n");
for (int SJ = ConstrainedLevels.find_first(); SJ >= 0;
SJ = ConstrainedLevels.find_next(SJ)) {
if (SJ > (int)CommonLevels)
for (unsigned SJ : ConstrainedLevels.set_bits()) {
if (SJ > CommonLevels)
break;
updateDirection(Result.DV[SJ - 1], Constraints[SJ]);
if (Result.DV[SJ - 1].Direction == Dependence::DVEntry::NONE)
@ -3859,7 +3858,7 @@ const SCEV *DependenceInfo::getSplitIteration(const Dependence &Dep,
NewConstraint.setAny(SE);
// test separable subscripts
for (int SI = Separable.find_first(); SI >= 0; SI = Separable.find_next(SI)) {
for (unsigned SI : Separable.set_bits()) {
switch (Pair[SI].Classification) {
case Subscript::SIV: {
unsigned Level;
@ -3886,12 +3885,12 @@ const SCEV *DependenceInfo::getSplitIteration(const Dependence &Dep,
SmallVector<Constraint, 4> Constraints(MaxLevels + 1);
for (unsigned II = 0; II <= MaxLevels; ++II)
Constraints[II].setAny(SE);
for (int SI = Coupled.find_first(); SI >= 0; SI = Coupled.find_next(SI)) {
for (unsigned SI : Coupled.set_bits()) {
SmallBitVector Group(Pair[SI].Group);
SmallBitVector Sivs(Pairs);
SmallBitVector Mivs(Pairs);
SmallBitVector ConstrainedLevels(MaxLevels + 1);
for (int SJ = Group.find_first(); SJ >= 0; SJ = Group.find_next(SJ)) {
for (unsigned SJ : Group.set_bits()) {
if (Pair[SJ].Classification == Subscript::SIV)
Sivs.set(SJ);
else
@ -3899,7 +3898,7 @@ const SCEV *DependenceInfo::getSplitIteration(const Dependence &Dep,
}
while (Sivs.any()) {
bool Changed = false;
for (int SJ = Sivs.find_first(); SJ >= 0; SJ = Sivs.find_next(SJ)) {
for (unsigned SJ : Sivs.set_bits()) {
// SJ is an SIV subscript that's part of the current coupled group
unsigned Level;
const SCEV *SplitIter = nullptr;
@ -3914,7 +3913,7 @@ const SCEV *DependenceInfo::getSplitIteration(const Dependence &Dep,
}
if (Changed) {
// propagate, possibly creating new SIVs and ZIVs
for (int SJ = Mivs.find_first(); SJ >= 0; SJ = Mivs.find_next(SJ)) {
for (unsigned SJ : Mivs.set_bits()) {
// SJ is an MIV subscript that's part of the current coupled group
if (propagate(Pair[SJ].Src, Pair[SJ].Dst,
Pair[SJ].Loops, Constraints, Result.Consistent)) {

View File

@ -669,21 +669,33 @@ void CallAnalyzer::updateThreshold(CallSite CS, Function &Callee) {
Threshold = MaxIfValid(Threshold, Params.HintThreshold);
if (PSI) {
BlockFrequencyInfo *CallerBFI = GetBFI ? &((*GetBFI)(*Caller)) : nullptr;
if (PSI->isHotCallSite(CS, CallerBFI)) {
DEBUG(dbgs() << "Hot callsite.\n");
Threshold = Params.HotCallSiteThreshold.getValue();
} else if (PSI->isFunctionEntryHot(&Callee)) {
DEBUG(dbgs() << "Hot callee.\n");
// If callsite hotness can not be determined, we may still know
// that the callee is hot and treat it as a weaker hint for threshold
// increase.
Threshold = MaxIfValid(Threshold, Params.HintThreshold);
} else if (PSI->isColdCallSite(CS, CallerBFI)) {
DEBUG(dbgs() << "Cold callsite.\n");
Threshold = MinIfValid(Threshold, Params.ColdCallSiteThreshold);
} else if (PSI->isFunctionEntryCold(&Callee)) {
DEBUG(dbgs() << "Cold callee.\n");
Threshold = MinIfValid(Threshold, Params.ColdThreshold);
// FIXME: After switching to the new passmanager, simplify the logic below
// by checking only the callsite hotness/coldness. The check for CallerBFI
// exists only because we do not have BFI available with the old PM.
//
// Use callee's hotness information only if we have no way of determining
// callsite's hotness information. Callsite hotness can be determined if
// sample profile is used (which adds hotness metadata to calls) or if
// caller's BlockFrequencyInfo is available.
if (CallerBFI || PSI->hasSampleProfile()) {
if (PSI->isHotCallSite(CS, CallerBFI)) {
DEBUG(dbgs() << "Hot callsite.\n");
Threshold = Params.HotCallSiteThreshold.getValue();
} else if (PSI->isColdCallSite(CS, CallerBFI)) {
DEBUG(dbgs() << "Cold callsite.\n");
Threshold = MinIfValid(Threshold, Params.ColdCallSiteThreshold);
}
} else {
if (PSI->isFunctionEntryHot(&Callee)) {
DEBUG(dbgs() << "Hot callee.\n");
// If callsite hotness can not be determined, we may still know
// that the callee is hot and treat it as a weaker hint for threshold
// increase.
Threshold = MaxIfValid(Threshold, Params.HintThreshold);
} else if (PSI->isFunctionEntryCold(&Callee)) {
DEBUG(dbgs() << "Cold callee.\n");
Threshold = MinIfValid(Threshold, Params.ColdThreshold);
}
}
}
}

View File

@ -1752,6 +1752,24 @@ static Value *SimplifyAndInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
(A == Op0 || B == Op0))
return Op0;
// A mask that only clears known zeros of a shifted value is a no-op.
Value *X;
const APInt *Mask;
const APInt *ShAmt;
if (match(Op1, m_APInt(Mask))) {
// If all bits in the inverted and shifted mask are clear:
// and (shl X, ShAmt), Mask --> shl X, ShAmt
if (match(Op0, m_Shl(m_Value(X), m_APInt(ShAmt))) &&
(~(*Mask)).lshr(*ShAmt).isNullValue())
return Op0;
// If all bits in the inverted and shifted mask are clear:
// and (lshr X, ShAmt), Mask --> lshr X, ShAmt
if (match(Op0, m_LShr(m_Value(X), m_APInt(ShAmt))) &&
(~(*Mask)).shl(*ShAmt).isNullValue())
return Op0;
}
// A & (-A) = A if A is a power of two or zero.
if (match(Op0, m_Neg(m_Specific(Op1))) ||
match(Op1, m_Neg(m_Specific(Op0)))) {

View File

@ -75,7 +75,7 @@ ProfileSummaryInfo::getProfileCount(const Instruction *Inst,
return None;
assert((isa<CallInst>(Inst) || isa<InvokeInst>(Inst)) &&
"We can only get profile count for call/invoke instruction.");
if (computeSummary() && Summary->getKind() == ProfileSummary::PSK_Sample) {
if (hasSampleProfile()) {
// In sample PGO mode, check if there is a profile metadata on the
// instruction. If it is present, determine hotness solely based on that,
// since the sampled entry count may not be accurate.

View File

@ -629,19 +629,19 @@ static int CompareSCEVComplexity(
const SCEVAddRecExpr *LA = cast<SCEVAddRecExpr>(LHS);
const SCEVAddRecExpr *RA = cast<SCEVAddRecExpr>(RHS);
// If there is a dominance relationship between the loops, sort by the
// dominance. Otherwise, sort by depth. We require such order in getAddExpr.
// There is always a dominance between two recs that are used by one SCEV,
// so we can safely sort recs by loop header dominance. We require such
// order in getAddExpr.
const Loop *LLoop = LA->getLoop(), *RLoop = RA->getLoop();
if (LLoop != RLoop) {
const BasicBlock *LHead = LLoop->getHeader(), *RHead = RLoop->getHeader();
assert(LHead != RHead && "Two loops share the same header?");
if (DT.dominates(LHead, RHead))
return 1;
else if (DT.dominates(RHead, LHead))
return -1;
unsigned LDepth = LLoop->getLoopDepth(), RDepth = RLoop->getLoopDepth();
if (LDepth != RDepth)
return (int)LDepth - (int)RDepth;
else
assert(DT.dominates(RHead, LHead) &&
"No dominance between recurrences used by one SCEV?");
return -1;
}
// Addrec complexity grows with operand count.
@ -2512,22 +2512,23 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
SmallVector<const SCEV *, 4> AddRecOps(AddRec->op_begin(),
AddRec->op_end());
for (; OtherIdx != Ops.size() && isa<SCEVAddRecExpr>(Ops[OtherIdx]);
++OtherIdx)
if (const auto *OtherAddRec = dyn_cast<SCEVAddRecExpr>(Ops[OtherIdx]))
if (OtherAddRec->getLoop() == AddRecLoop) {
for (unsigned i = 0, e = OtherAddRec->getNumOperands();
i != e; ++i) {
if (i >= AddRecOps.size()) {
AddRecOps.append(OtherAddRec->op_begin()+i,
OtherAddRec->op_end());
break;
}
SmallVector<const SCEV *, 2> TwoOps = {
AddRecOps[i], OtherAddRec->getOperand(i)};
AddRecOps[i] = getAddExpr(TwoOps, SCEV::FlagAnyWrap, Depth + 1);
++OtherIdx) {
const auto *OtherAddRec = cast<SCEVAddRecExpr>(Ops[OtherIdx]);
if (OtherAddRec->getLoop() == AddRecLoop) {
for (unsigned i = 0, e = OtherAddRec->getNumOperands();
i != e; ++i) {
if (i >= AddRecOps.size()) {
AddRecOps.append(OtherAddRec->op_begin()+i,
OtherAddRec->op_end());
break;
}
Ops.erase(Ops.begin() + OtherIdx); --OtherIdx;
SmallVector<const SCEV *, 2> TwoOps = {
AddRecOps[i], OtherAddRec->getOperand(i)};
AddRecOps[i] = getAddExpr(TwoOps, SCEV::FlagAnyWrap, Depth + 1);
}
Ops.erase(Ops.begin() + OtherIdx); --OtherIdx;
}
}
// Step size has changed, so we cannot guarantee no self-wraparound.
Ops[Idx] = getAddRecExpr(AddRecOps, AddRecLoop, SCEV::FlagAnyWrap);
return getAddExpr(Ops, SCEV::FlagAnyWrap, Depth + 1);

View File

@ -128,8 +128,7 @@ AggressiveAntiDepBreaker::AggressiveAntiDepBreaker(
}
DEBUG(dbgs() << "AntiDep Critical-Path Registers:");
DEBUG(for (int r = CriticalPathSet.find_first(); r != -1;
r = CriticalPathSet.find_next(r))
DEBUG(for (unsigned r : CriticalPathSet.set_bits())
dbgs() << " " << TRI->getName(r));
DEBUG(dbgs() << '\n');
}
@ -571,7 +570,7 @@ bool AggressiveAntiDepBreaker::FindSuitableFreeRegisters(
DEBUG({
dbgs() << " ::";
for (int r = BV.find_first(); r != -1; r = BV.find_next(r))
for (unsigned r : BV.set_bits())
dbgs() << " " << TRI->getName(r);
dbgs() << "\n";
});

View File

@ -501,7 +501,7 @@ void CodeViewDebug::emitTypeInformation() {
Error E = Reader.readArray(Types, Reader.getLength());
if (!E) {
TypeVisitorCallbacks C;
E = CVTypeVisitor(C).visitTypeStream(Types);
E = codeview::visitTypeStream(Types, C);
}
if (E) {
logAllUnhandledErrors(std::move(E), errs(), "error: ");

View File

@ -209,8 +209,7 @@ void llvm::calculateDbgValueHistory(const MachineFunction *MF,
} else if (MO.isRegMask()) {
// If this is a register mask operand, clobber all debug values in
// non-CSRs.
for (int I = ChangingRegs.find_first(); I != -1;
I = ChangingRegs.find_next(I)) {
for (unsigned I : ChangingRegs.set_bits()) {
// Don't consider SP to be clobbered by register masks.
if (unsigned(I) != SP && TRI->isPhysicalRegister(I) &&
MO.clobbersPhysReg(I)) {

View File

@ -1129,6 +1129,11 @@ void IRTranslator::finalizeFunction() {
ValToVReg.clear();
FrameIndices.clear();
MachinePreds.clear();
// MachineIRBuilder::DebugLoc can outlive the DILocation it holds. Clear it
// to avoid accessing freed memory (in runOnMachineFunction) and to avoid
// destroying it twice (in ~IRTranslator() and ~LLVMContext())
EntryBuilder = MachineIRBuilder();
CurBuilder = MachineIRBuilder();
}
bool IRTranslator::runOnMachineFunction(MachineFunction &CurMF) {

View File

@ -760,7 +760,7 @@ MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) {
const MachineFrameInfo &MFI = MF->getFrameInfo();
BitVector PR = MFI.getPristineRegs(*MF);
for (int I = PR.find_first(); I>0; I = PR.find_next(I)) {
for (unsigned I : PR.set_bits()) {
for (MCSubRegIterator SubRegs(I, TRI, /*IncludeSelf=*/true);
SubRegs.isValid(); ++SubRegs)
regsLive.insert(*SubRegs);

View File

@ -285,8 +285,7 @@ class RAGreedy : public MachineFunctionPass,
// Set B[i] = C for every live bundle where B[i] was NoCand.
unsigned getBundles(SmallVectorImpl<unsigned> &B, unsigned C) {
unsigned Count = 0;
for (int i = LiveBundles.find_first(); i >= 0;
i = LiveBundles.find_next(i))
for (unsigned i : LiveBundles.set_bits())
if (B[i] == NoCand) {
B[i] = C;
Count++;
@ -1162,9 +1161,8 @@ bool RAGreedy::calcCompactRegion(GlobalSplitCandidate &Cand) {
}
DEBUG({
for (int i = Cand.LiveBundles.find_first(); i>=0;
i = Cand.LiveBundles.find_next(i))
dbgs() << " EB#" << i;
for (int i : Cand.LiveBundles.set_bits())
dbgs() << " EB#" << i;
dbgs() << ".\n";
});
return true;
@ -1482,8 +1480,7 @@ unsigned RAGreedy::calculateRegionSplitCost(LiveInterval &VirtReg,
DEBUG({
dbgs() << ", total = "; MBFI->printBlockFreq(dbgs(), Cost)
<< " with bundles";
for (int i = Cand.LiveBundles.find_first(); i>=0;
i = Cand.LiveBundles.find_next(i))
for (int i : Cand.LiveBundles.set_bits())
dbgs() << " EB#" << i;
dbgs() << ".\n";
});

View File

@ -13087,14 +13087,28 @@ SDValue DAGCombiner::visitSTORE(SDNode *N) {
}
}
// If this is a store followed by a store with the same value to the same
// location, then the store is dead/noop.
if (StoreSDNode *ST1 = dyn_cast<StoreSDNode>(Chain)) {
if (ST1->getBasePtr() == Ptr && ST->getMemoryVT() == ST1->getMemoryVT() &&
ST1->getValue() == Value && ST->isUnindexed() && !ST->isVolatile() &&
ST1->isUnindexed() && !ST1->isVolatile()) {
// The store is dead, remove it.
return Chain;
if (ST->isUnindexed() && !ST->isVolatile() && ST1->isUnindexed() &&
!ST1->isVolatile() && ST1->getBasePtr() == Ptr &&
ST->getMemoryVT() == ST1->getMemoryVT()) {
// If this is a store followed by a store with the same value to the same
// location, then the store is dead/noop.
if (ST1->getValue() == Value) {
// The store is dead, remove it.
return Chain;
}
// If this is a store who's preceeding store to the same location
// and no one other node is chained to that store we can effectively
// drop the store. Do not remove stores to undef as they may be used as
// data sinks.
if (OptLevel != CodeGenOpt::None && ST1->hasOneUse() &&
!ST1->getBasePtr().isUndef()) {
// ST1 is fully overwritten and can be elided. Combine with it's chain
// value.
CombineTo(ST1, ST1->getChain());
return SDValue();
}
}
}

View File

@ -310,7 +310,7 @@ void SpillPlacement::addLinks(ArrayRef<unsigned> Links) {
bool SpillPlacement::scanActiveBundles() {
RecentPositive.clear();
for (int n = ActiveNodes->find_first(); n>=0; n = ActiveNodes->find_next(n)) {
for (unsigned n : ActiveNodes->set_bits()) {
update(n);
// A node that must spill, or a node without any links is not going to
// change its value ever again, so exclude it from iterations.
@ -365,7 +365,7 @@ SpillPlacement::finish() {
// Write preferences back to ActiveNodes.
bool Perfect = true;
for (int n = ActiveNodes->find_first(); n>=0; n = ActiveNodes->find_next(n))
for (unsigned n : ActiveNodes->set_bits())
if (!nodes[n].preferReg()) {
ActiveNodes->reset(n);
Perfect = false;

View File

@ -703,12 +703,10 @@ void StackColoring::calculateLiveIntervals(unsigned NumSlots) {
// Create the interval of the blocks that we previously found to be 'alive'.
BlockLifetimeInfo &MBBLiveness = BlockLiveness[&MBB];
for (int pos = MBBLiveness.LiveIn.find_first(); pos != -1;
pos = MBBLiveness.LiveIn.find_next(pos)) {
for (unsigned pos : MBBLiveness.LiveIn.set_bits()) {
Starts[pos] = Indexes->getMBBStartIdx(&MBB);
}
for (int pos = MBBLiveness.LiveOut.find_first(); pos != -1;
pos = MBBLiveness.LiveOut.find_next(pos)) {
for (unsigned pos : MBBLiveness.LiveOut.set_bits()) {
Finishes[pos] = Indexes->getMBBEndIdx(&MBB);
}

View File

@ -1312,7 +1312,7 @@ TargetLoweringBase::findRepresentativeClass(const TargetRegisterInfo *TRI,
// Find the first legal register class with the largest spill size.
const TargetRegisterClass *BestRC = RC;
for (int i = SuperRegRC.find_first(); i >= 0; i = SuperRegRC.find_next(i)) {
for (unsigned i : SuperRegRC.set_bits()) {
const TargetRegisterClass *SuperRC = TRI->getRegClass(i);
// We want the largest possible spill size.
if (TRI->getSpillSize(*SuperRC) <= TRI->getSpillSize(*BestRC))

View File

@ -564,6 +564,14 @@ void TargetPassConfig::addISelPrepare() {
addPass(createVerifierPass());
}
/// -regalloc=... command line option.
static FunctionPass *useDefaultRegisterAllocator() { return nullptr; }
static cl::opt<RegisterRegAlloc::FunctionPassCtor, false,
RegisterPassParser<RegisterRegAlloc> >
RegAlloc("regalloc",
cl::init(&useDefaultRegisterAllocator),
cl::desc("Register allocator to use"));
/// Add the complete set of target-independent postISel code generator passes.
///
/// This can be read as the standard order of major LLVM CodeGen stages. Stages
@ -625,8 +633,12 @@ void TargetPassConfig::addMachinePasses() {
// including phi elimination and scheduling.
if (getOptimizeRegAlloc())
addOptimizedRegAlloc(createRegAllocPass(true));
else
else {
if (RegAlloc != &useDefaultRegisterAllocator &&
RegAlloc != &createFastRegisterAllocator)
report_fatal_error("Must use fast (default) register allocator for unoptimized regalloc.");
addFastRegAlloc(createRegAllocPass(false));
}
// Run post-ra passes.
addPostRegAlloc();
@ -759,19 +771,12 @@ MachinePassRegistry RegisterRegAlloc::Registry;
/// A dummy default pass factory indicates whether the register allocator is
/// overridden on the command line.
static llvm::once_flag InitializeDefaultRegisterAllocatorFlag;
static FunctionPass *useDefaultRegisterAllocator() { return nullptr; }
static RegisterRegAlloc
defaultRegAlloc("default",
"pick register allocator based on -O option",
useDefaultRegisterAllocator);
/// -regalloc=... command line option.
static cl::opt<RegisterRegAlloc::FunctionPassCtor, false,
RegisterPassParser<RegisterRegAlloc> >
RegAlloc("regalloc",
cl::init(&useDefaultRegisterAllocator),
cl::desc("Register allocator to use"));
static void initializeDefaultRegisterAllocatorOnce() {
RegisterRegAlloc::FunctionPassCtor Ctor = RegisterRegAlloc::getDefault();
@ -781,7 +786,6 @@ static void initializeDefaultRegisterAllocatorOnce() {
}
}
/// Instantiate the default register allocator pass for this target for either
/// the optimized or unoptimized allocation path. This will be added to the pass
/// manager by addFastRegAlloc in the unoptimized case or addOptimizedRegAlloc

View File

@ -50,8 +50,7 @@ bool TargetRegisterInfo::checkAllSuperRegsMarked(const BitVector &RegisterSet,
ArrayRef<MCPhysReg> Exceptions) const {
// Check that all super registers of reserved regs are reserved as well.
BitVector Checked(getNumRegs());
for (int Reg = RegisterSet.find_first(); Reg>=0;
Reg = RegisterSet.find_next(Reg)) {
for (unsigned Reg : RegisterSet.set_bits()) {
if (Checked[Reg])
continue;
for (MCSuperRegIterator SR(Reg, this); SR.isValid(); ++SR) {

View File

@ -11,7 +11,6 @@
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
#include "llvm/Support/BinaryByteStream.h"
@ -21,38 +20,23 @@ using namespace llvm::codeview;
Error CVTypeDumper::dump(const CVType &Record, TypeVisitorCallbacks &Dumper) {
TypeDatabaseVisitor DBV(TypeDB);
TypeDeserializer Deserializer;
TypeVisitorCallbackPipeline Pipeline;
Pipeline.addCallbackToPipeline(Deserializer);
Pipeline.addCallbackToPipeline(DBV);
Pipeline.addCallbackToPipeline(Dumper);
CVTypeVisitor Visitor(Pipeline);
if (Handler)
Visitor.addTypeServerHandler(*Handler);
CVType RecordCopy = Record;
if (auto EC = Visitor.visitTypeRecord(RecordCopy))
return EC;
return Error::success();
return codeview::visitTypeRecord(RecordCopy, Pipeline, VDS_BytesPresent,
Handler);
}
Error CVTypeDumper::dump(const CVTypeArray &Types,
TypeVisitorCallbacks &Dumper) {
TypeDatabaseVisitor DBV(TypeDB);
TypeDeserializer Deserializer;
TypeVisitorCallbackPipeline Pipeline;
Pipeline.addCallbackToPipeline(Deserializer);
Pipeline.addCallbackToPipeline(DBV);
Pipeline.addCallbackToPipeline(Dumper);
CVTypeVisitor Visitor(Pipeline);
if (Handler)
Visitor.addTypeServerHandler(*Handler);
if (auto EC = Visitor.visitTypeStream(Types))
return EC;
return Error::success();
return codeview::visitTypeStream(Types, Pipeline, Handler);
}
Error CVTypeDumper::dump(ArrayRef<uint8_t> Data, TypeVisitorCallbacks &Dumper) {

View File

@ -59,13 +59,8 @@ static Expected<TypeServer2Record> deserializeTypeServerRecord(CVType &Record) {
};
TypeServer2Record R(TypeRecordKind::TypeServer2);
TypeDeserializer Deserializer;
StealTypeServerVisitor Thief(R);
TypeVisitorCallbackPipeline Pipeline;
Pipeline.addCallbackToPipeline(Deserializer);
Pipeline.addCallbackToPipeline(Thief);
CVTypeVisitor Visitor(Pipeline);
if (auto EC = Visitor.visitTypeRecord(Record))
if (auto EC = visitTypeRecord(Record, Thief))
return std::move(EC);
return R;
@ -178,7 +173,7 @@ static Error visitMemberRecord(CVMemberRecord &Record,
return Error::success();
}
Error CVTypeVisitor::visitMemberRecord(CVMemberRecord &Record) {
Error CVTypeVisitor::visitMemberRecord(CVMemberRecord Record) {
return ::visitMemberRecord(Record, Callbacks);
}
@ -224,3 +219,93 @@ Error CVTypeVisitor::visitFieldListMemberStream(ArrayRef<uint8_t> Data) {
BinaryStreamReader SR(S);
return visitFieldListMemberStream(SR);
}
namespace {
struct FieldListVisitHelper {
FieldListVisitHelper(TypeVisitorCallbacks &Callbacks, ArrayRef<uint8_t> Data,
VisitorDataSource Source)
: Stream(Data, llvm::support::little), Reader(Stream),
Deserializer(Reader),
Visitor((Source == VDS_BytesPresent) ? Pipeline : Callbacks) {
if (Source == VDS_BytesPresent) {
Pipeline.addCallbackToPipeline(Deserializer);
Pipeline.addCallbackToPipeline(Callbacks);
}
}
BinaryByteStream Stream;
BinaryStreamReader Reader;
FieldListDeserializer Deserializer;
TypeVisitorCallbackPipeline Pipeline;
CVTypeVisitor Visitor;
};
struct VisitHelper {
VisitHelper(TypeVisitorCallbacks &Callbacks, VisitorDataSource Source,
TypeServerHandler *TS)
: Visitor((Source == VDS_BytesPresent) ? Pipeline : Callbacks) {
if (TS)
Visitor.addTypeServerHandler(*TS);
if (Source == VDS_BytesPresent) {
Pipeline.addCallbackToPipeline(Deserializer);
Pipeline.addCallbackToPipeline(Callbacks);
}
}
TypeDeserializer Deserializer;
TypeVisitorCallbackPipeline Pipeline;
CVTypeVisitor Visitor;
};
}
Error llvm::codeview::visitTypeRecord(CVType &Record, TypeIndex Index,
TypeVisitorCallbacks &Callbacks,
VisitorDataSource Source,
TypeServerHandler *TS) {
VisitHelper Helper(Callbacks, Source, TS);
return Helper.Visitor.visitTypeRecord(Record, Index);
}
Error llvm::codeview::visitTypeRecord(CVType &Record,
TypeVisitorCallbacks &Callbacks,
VisitorDataSource Source,
TypeServerHandler *TS) {
VisitHelper Helper(Callbacks, Source, TS);
return Helper.Visitor.visitTypeRecord(Record);
}
Error llvm::codeview::visitMemberRecordStream(ArrayRef<uint8_t> FieldList,
TypeVisitorCallbacks &Callbacks) {
CVTypeVisitor Visitor(Callbacks);
return Visitor.visitFieldListMemberStream(FieldList);
}
Error llvm::codeview::visitMemberRecord(CVMemberRecord Record,
TypeVisitorCallbacks &Callbacks,
VisitorDataSource Source) {
FieldListVisitHelper Helper(Callbacks, Record.Data, Source);
return Helper.Visitor.visitMemberRecord(Record);
}
Error llvm::codeview::visitMemberRecord(TypeLeafKind Kind,
ArrayRef<uint8_t> Record,
TypeVisitorCallbacks &Callbacks) {
CVMemberRecord R;
R.Data = Record;
R.Kind = Kind;
return visitMemberRecord(R, Callbacks, VDS_BytesPresent);
}
Error llvm::codeview::visitTypeStream(const CVTypeArray &Types,
TypeVisitorCallbacks &Callbacks,
TypeServerHandler *TS) {
VisitHelper Helper(Callbacks, VDS_BytesPresent, TS);
return Helper.Visitor.visitTypeStream(Types);
}
Error llvm::codeview::visitTypeStream(CVTypeRange Types,
TypeVisitorCallbacks &Callbacks,
TypeServerHandler *TS) {
VisitHelper Helper(Callbacks, VDS_BytesPresent, TS);
return Helper.Visitor.visitTypeStream(Types);
}

View File

@ -9,6 +9,7 @@
#include "llvm/DebugInfo/CodeView/RandomAccessTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
#include "llvm/DebugInfo/CodeView/TypeServerHandler.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
@ -20,9 +21,7 @@ RandomAccessTypeVisitor::RandomAccessTypeVisitor(
const CVTypeArray &Types, uint32_t NumRecords,
PartialOffsetArray PartialOffsets)
: Database(NumRecords), Types(Types), DatabaseVisitor(Database),
InternalVisitor(Pipeline), PartialOffsets(PartialOffsets) {
Pipeline.addCallbackToPipeline(Deserializer);
Pipeline.addCallbackToPipeline(DatabaseVisitor);
PartialOffsets(PartialOffsets) {
KnownOffsets.resize(Database.capacity());
}
@ -38,8 +37,7 @@ Error RandomAccessTypeVisitor::visitTypeIndex(TypeIndex TI,
assert(Database.contains(TI));
auto &Record = Database.getTypeRecord(TI);
CVTypeVisitor V(Callbacks);
return V.visitTypeRecord(Record, TI);
return codeview::visitTypeRecord(Record, TI, Callbacks);
}
Error RandomAccessTypeVisitor::visitRangeForType(TypeIndex TI) {
@ -78,7 +76,7 @@ Error RandomAccessTypeVisitor::visitRange(TypeIndex Begin, uint32_t BeginOffset,
while (Begin != End) {
assert(!Database.contains(Begin));
if (auto EC = InternalVisitor.visitTypeRecord(*RI, Begin))
if (auto EC = codeview::visitTypeRecord(*RI, Begin, DatabaseVisitor))
return EC;
KnownOffsets[Begin.toArrayIndex()] = BeginOffset;

View File

@ -216,8 +216,7 @@ Error TypeDumpVisitor::visitMemberEnd(CVMemberRecord &Record) {
Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
FieldListRecord &FieldList) {
CVTypeVisitor Visitor(*this);
if (auto EC = Visitor.visitFieldListMemberStream(FieldList.Data))
if (auto EC = codeview::visitMemberRecordStream(FieldList.Data, *this))
return EC;
return Error::success();

View File

@ -361,8 +361,7 @@ Error TypeStreamMerger::visitKnownRecord(CVType &, FieldListRecord &R) {
// Visit the members inside the field list.
HadUntranslatedMember = false;
FieldListBuilder.begin();
CVTypeVisitor Visitor(*this);
if (auto EC = Visitor.visitFieldListMemberStream(R.Data))
if (auto EC = codeview::visitMemberRecordStream(R.Data, *this))
return EC;
// Write the record if we translated all field list members.
@ -440,18 +439,9 @@ Error TypeStreamMerger::visitUnknownType(CVType &Rec) {
Error TypeStreamMerger::mergeStream(const CVTypeArray &Types) {
assert(IndexMap.empty());
TypeVisitorCallbackPipeline Pipeline;
LastError = Error::success();
TypeDeserializer Deserializer;
Pipeline.addCallbackToPipeline(Deserializer);
Pipeline.addCallbackToPipeline(*this);
CVTypeVisitor Visitor(Pipeline);
if (Handler)
Visitor.addTypeServerHandler(*Handler);
if (auto EC = Visitor.visitTypeStream(Types))
if (auto EC = codeview::visitTypeStream(Types, *this, Handler))
return EC;
// If we found bad indices but no other errors, try doing another pass and see
@ -466,7 +456,8 @@ Error TypeStreamMerger::mergeStream(const CVTypeArray &Types) {
IsSecondPass = true;
NumBadIndices = 0;
CurIndex = TypeIndex(TypeIndex::FirstNonSimpleIndex);
if (auto EC = Visitor.visitTypeStream(Types))
if (auto EC = codeview::visitTypeStream(Types, *this, Handler))
return EC;
assert(NumBadIndices <= BadIndicesRemaining &&

View File

@ -1086,49 +1086,32 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
continue;
}
if (Section.relocation_begin() == Section.relocation_end())
continue;
std::map<SymbolRef, uint64_t> AddrCache;
if (Section.relocation_begin() != Section.relocation_end()) {
uint64_t SectionSize = RelocatedSection->getSize();
for (const RelocationRef &Reloc : Section.relocations()) {
// FIXME: it's not clear how to correctly handle scattered
// relocations.
if (isRelocScattered(Obj, Reloc))
continue;
for (const RelocationRef &Reloc : Section.relocations()) {
// FIXME: it's not clear how to correctly handle scattered
// relocations.
if (isRelocScattered(Obj, Reloc))
continue;
Expected<uint64_t> SymAddrOrErr =
getSymbolAddress(Obj, Reloc, L, AddrCache);
if (!SymAddrOrErr) {
errs() << toString(SymAddrOrErr.takeError()) << '\n';
continue;
}
object::RelocVisitor V(Obj);
object::RelocToApply R(V.visit(Reloc.getType(), Reloc, *SymAddrOrErr));
if (V.error()) {
SmallString<32> Name;
Reloc.getTypeName(Name);
errs() << "error: failed to compute relocation: "
<< Name << "\n";
continue;
}
uint64_t Address = Reloc.getOffset();
if (Address + R.Width > SectionSize) {
errs() << "error: " << R.Width << "-byte relocation starting "
<< Address << " bytes into section " << name << " which is "
<< SectionSize << " bytes long.\n";
continue;
}
if (R.Width > 8) {
errs() << "error: can't handle a relocation of more than 8 bytes at "
"a time.\n";
continue;
}
DEBUG(dbgs() << "Writing " << format("%p", R.Value)
<< " at " << format("%p", Address)
<< " with width " << format("%d", R.Width)
<< "\n");
Map->insert({Address, {(uint8_t)R.Width, R.Value}});
Expected<uint64_t> SymAddrOrErr =
getSymbolAddress(Obj, Reloc, L, AddrCache);
if (!SymAddrOrErr) {
errs() << toString(SymAddrOrErr.takeError()) << '\n';
continue;
}
object::RelocVisitor V(Obj);
object::RelocToApply R(V.visit(Reloc.getType(), Reloc, *SymAddrOrErr));
if (V.error()) {
SmallString<32> Name;
Reloc.getTypeName(Name);
errs() << "error: failed to compute relocation: " << Name << "\n";
continue;
}
Map->insert({Reloc.getOffset(), {R.Value}});
}
}
}

View File

@ -55,9 +55,8 @@ PDBTypeServerHandler::handleInternal(PDBFile &File,
auto ExpectedTpi = File.getPDBTpiStream();
if (!ExpectedTpi)
return ExpectedTpi.takeError();
CVTypeVisitor Visitor(Callbacks);
if (auto EC = Visitor.visitTypeStream(ExpectedTpi->types(nullptr)))
if (auto EC = codeview::visitTypeStream(ExpectedTpi->typeArray(), Callbacks))
return std::move(EC);
return true;

View File

@ -705,7 +705,7 @@ RuntimeDyldImpl::emitSection(const ObjectFile &Obj,
unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL;
unsigned PaddingSize = 0;
unsigned StubBufSize = 0;
bool IsRequired = isRequiredForExecution(Section) || ProcessAllSections;
bool IsRequired = isRequiredForExecution(Section);
bool IsVirtual = Section.isVirtual();
bool IsZeroInit = isZeroInit(Section);
bool IsReadOnly = isReadOnlyData(Section);
@ -745,8 +745,8 @@ RuntimeDyldImpl::emitSection(const ObjectFile &Obj,
Alignment = std::max(Alignment, getStubAlignment());
// Some sections, such as debug info, don't need to be loaded for execution.
// Leave those where they are.
if (IsRequired) {
// Process those only if explicitly requested.
if (IsRequired || ProcessAllSections) {
Allocate = DataSize + PaddingSize + StubBufSize;
if (!Allocate)
Allocate = 1;
@ -790,6 +790,10 @@ RuntimeDyldImpl::emitSection(const ObjectFile &Obj,
Sections.push_back(
SectionEntry(Name, Addr, DataSize, Allocate, (uintptr_t)pData));
// Debug info sections are linked as if their load address was zero
if (!IsRequired)
Sections.back().setLoadAddress(0);
if (Checker)
Checker->registerSection(Obj.getFileName(), SectionID);

View File

@ -78,6 +78,9 @@ static bool gCrashRecoveryEnabled = false;
static ManagedStatic<sys::ThreadLocal<const CrashRecoveryContext>>
tlIsRecoveringFromCrash;
static void installExceptionOrSignalHandlers();
static void uninstallExceptionOrSignalHandlers();
CrashRecoveryContextCleanup::~CrashRecoveryContextCleanup() {}
CrashRecoveryContext::~CrashRecoveryContext() {
@ -113,6 +116,23 @@ CrashRecoveryContext *CrashRecoveryContext::GetCurrent() {
return CRCI->CRC;
}
void CrashRecoveryContext::Enable() {
sys::ScopedLock L(*gCrashRecoveryContextMutex);
// FIXME: Shouldn't this be a refcount or something?
if (gCrashRecoveryEnabled)
return;
gCrashRecoveryEnabled = true;
installExceptionOrSignalHandlers();
}
void CrashRecoveryContext::Disable() {
sys::ScopedLock L(*gCrashRecoveryContextMutex);
if (!gCrashRecoveryEnabled)
return;
gCrashRecoveryEnabled = false;
uninstallExceptionOrSignalHandlers();
}
void CrashRecoveryContext::registerCleanup(CrashRecoveryContextCleanup *cleanup)
{
if (!cleanup)
@ -140,30 +160,70 @@ CrashRecoveryContext::unregisterCleanup(CrashRecoveryContextCleanup *cleanup) {
delete cleanup;
}
#ifdef LLVM_ON_WIN32
#if defined(_MSC_VER)
// If _MSC_VER is defined, we must have SEH. Use it if it's available. It's way
// better than VEH. Vectored exception handling catches all exceptions happening
// on the thread with installed exception handlers, so it can interfere with
// internal exception handling of other libraries on that thread. SEH works
// exactly as you would expect normal exception handling to work: it only
// catches exceptions if they would bubble out from the stack frame with __try /
// __except.
#include "Windows/WindowsSupport.h"
static void installExceptionOrSignalHandlers() {}
static void uninstallExceptionOrSignalHandlers() {}
// On Windows, we can make use of vectored exception handling to
// catch most crashing situations. Note that this does mean
// we will be alerted of exceptions *before* structured exception
// handling has the opportunity to catch it. But that isn't likely
// to cause problems because nowhere in the project is SEH being
// used.
bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) {
if (!gCrashRecoveryEnabled) {
Fn();
return true;
}
bool Result = true;
__try {
Fn();
} __except (1) { // Catch any exception.
Result = false;
}
return Result;
}
#else // !_MSC_VER
#if defined(LLVM_ON_WIN32)
// This is a non-MSVC compiler, probably mingw gcc or clang without
// -fms-extensions. Use vectored exception handling (VEH).
//
// Vectored exception handling is built on top of SEH, and so it
// works on a per-thread basis.
// On Windows, we can make use of vectored exception handling to catch most
// crashing situations. Note that this does mean we will be alerted of
// exceptions *before* structured exception handling has the opportunity to
// catch it. Unfortunately, this causes problems in practice with other code
// running on threads with LLVM crash recovery contexts, so we would like to
// eventually move away from VEH.
//
// Vectored works on a per-thread basis, which is an advantage over
// SetUnhandledExceptionFilter. SetUnhandledExceptionFilter also doesn't have
// any native support for chaining exception handlers, but VEH allows more than
// one.
//
// The vectored exception handler functionality was added in Windows
// XP, so if support for older versions of Windows is required,
// it will have to be added.
//
// If we want to support as far back as Win2k, we could use the
// SetUnhandledExceptionFilter API, but there's a risk of that
// being entirely overwritten (it's not a chain).
#include "Windows/WindowsSupport.h"
static LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo)
{
// DBG_PRINTEXCEPTION_WIDE_C is not properly defined on all supported
// compilers and platforms, so we define it manually.
constexpr ULONG DbgPrintExceptionWideC = 0x4001000AL;
switch (ExceptionInfo->ExceptionRecord->ExceptionCode)
{
case DBG_PRINTEXCEPTION_C:
case DbgPrintExceptionWideC:
case 0x406D1388: // set debugger thread name
return EXCEPTION_CONTINUE_EXECUTION;
}
// Lookup the current thread local recovery object.
const CrashRecoveryContextImpl *CRCI = CurrentContext->get();
@ -192,14 +252,7 @@ static LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo)
// non-NULL, valid VEH handles, or NULL.
static sys::ThreadLocal<const void> sCurrentExceptionHandle;
void CrashRecoveryContext::Enable() {
sys::ScopedLock L(*gCrashRecoveryContextMutex);
if (gCrashRecoveryEnabled)
return;
gCrashRecoveryEnabled = true;
static void installExceptionOrSignalHandlers() {
// We can set up vectored exception handling now. We will install our
// handler as the front of the list, though there's no assurances that
// it will remain at the front (another call could install itself before
@ -208,14 +261,7 @@ void CrashRecoveryContext::Enable() {
sCurrentExceptionHandle.set(handle);
}
void CrashRecoveryContext::Disable() {
sys::ScopedLock L(*gCrashRecoveryContextMutex);
if (!gCrashRecoveryEnabled)
return;
gCrashRecoveryEnabled = false;
static void uninstallExceptionOrSignalHandlers() {
PVOID currentHandle = const_cast<PVOID>(sCurrentExceptionHandle.get());
if (currentHandle) {
// Now we can remove the vectored exception handler from the chain
@ -226,7 +272,7 @@ void CrashRecoveryContext::Disable() {
}
}
#else
#else // !LLVM_ON_WIN32
// Generic POSIX implementation.
//
@ -278,14 +324,7 @@ static void CrashRecoverySignalHandler(int Signal) {
const_cast<CrashRecoveryContextImpl*>(CRCI)->HandleCrash();
}
void CrashRecoveryContext::Enable() {
sys::ScopedLock L(*gCrashRecoveryContextMutex);
if (gCrashRecoveryEnabled)
return;
gCrashRecoveryEnabled = true;
static void installExceptionOrSignalHandlers() {
// Setup the signal handler.
struct sigaction Handler;
Handler.sa_handler = CrashRecoverySignalHandler;
@ -297,20 +336,13 @@ void CrashRecoveryContext::Enable() {
}
}
void CrashRecoveryContext::Disable() {
sys::ScopedLock L(*gCrashRecoveryContextMutex);
if (!gCrashRecoveryEnabled)
return;
gCrashRecoveryEnabled = false;
static void uninstallExceptionOrSignalHandlers() {
// Restore the previous signal handlers.
for (unsigned i = 0; i != NumSignals; ++i)
sigaction(Signals[i], &PrevActions[i], nullptr);
}
#endif
#endif // !LLVM_ON_WIN32
bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) {
// If crash recovery is disabled, do nothing.
@ -328,6 +360,8 @@ bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) {
return true;
}
#endif // !_MSC_VER
void CrashRecoveryContext::HandleCrash() {
CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *) Impl;
assert(CRCI && "Crash recovery context never initialized!");

View File

@ -103,16 +103,13 @@
#define STATVFS_F_FLAG(vfs) (vfs).f_flags
#endif
#if defined(__FreeBSD__) || defined(__NetBSD__)
#include <sys/sysctl.h>
#endif
using namespace llvm;
namespace llvm {
namespace sys {
namespace fs {
#if defined(__Bitrig__) || defined(__OpenBSD__) || defined(__minix) || \
#if defined(__FreeBSD__) || defined (__NetBSD__) || defined(__Bitrig__) || \
defined(__OpenBSD__) || defined(__minix) || defined(__FreeBSD_kernel__) || \
defined(__linux__) || defined(__CYGWIN__) || defined(__DragonFly__) || \
defined(_AIX)
static int
@ -167,7 +164,7 @@ getprogpath(char ret[PATH_MAX], const char *bin)
free(pv);
return nullptr;
}
#endif // Bitrig || OpenBSD || minix || linux || CYGWIN || DragonFly || AIX
#endif // __FreeBSD__ || __NetBSD__ || __FreeBSD_kernel__
/// GetMainExecutable - Return the path to the main executable, given the
/// value of argv[0] from program startup.
@ -183,24 +180,9 @@ std::string getMainExecutable(const char *argv0, void *MainAddr) {
if (realpath(exe_path, link_path))
return link_path;
}
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__)
int mib[4];
mib[0] = CTL_KERN;
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PATHNAME;
mib[3] = -1;
#else
mib[1] = KERN_PROC_ARGS;
mib[2] = -1;
mib[3] = KERN_PROC_PATHNAME;
#endif
char exe_path[PATH_MAX];
size_t cb = sizeof(exe_path);
if (sysctl(mib, 4, exe_path, &cb, NULL, 0) == 0)
return exe_path;
#elif defined(__Bitrig__) || defined(__OpenBSD__) || defined(__minix) || \
defined(__DragonFly__) || defined(_AIX)
#elif defined(__FreeBSD__) || defined (__NetBSD__) || defined(__Bitrig__) || \
defined(__OpenBSD__) || defined(__minix) || defined(__DragonFly__) || \
defined(__FreeBSD_kernel__) || defined(_AIX)
char exe_path[PATH_MAX];
if (getprogpath(exe_path, argv0) != NULL)

View File

@ -1158,8 +1158,7 @@ void AArch64FrameLowering::determineCalleeSaves(MachineFunction &MF,
}
DEBUG(dbgs() << "*** determineCalleeSaves\nUsed CSRs:";
for (int Reg = SavedRegs.find_first(); Reg != -1;
Reg = SavedRegs.find_next(Reg))
for (unsigned Reg : SavedRegs.set_bits())
dbgs() << ' ' << PrintReg(Reg, RegInfo);
dbgs() << "\n";);

View File

@ -553,7 +553,6 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
setTargetDAGCombine(ISD::INTRINSIC_VOID);
setTargetDAGCombine(ISD::INTRINSIC_W_CHAIN);
setTargetDAGCombine(ISD::INSERT_VECTOR_ELT);
setTargetDAGCombine(ISD::EXTRACT_VECTOR_ELT);
MaxStoresPerMemset = MaxStoresPerMemsetOptSize = 8;
MaxStoresPerMemcpy = MaxStoresPerMemcpyOptSize = 4;
@ -659,6 +658,19 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
setOperationAction(ISD::MUL, MVT::v4i32, Custom);
setOperationAction(ISD::MUL, MVT::v2i64, Custom);
// Vector reductions
for (MVT VT : MVT::integer_valuetypes()) {
setOperationAction(ISD::VECREDUCE_ADD, VT, Custom);
setOperationAction(ISD::VECREDUCE_SMAX, VT, Custom);
setOperationAction(ISD::VECREDUCE_SMIN, VT, Custom);
setOperationAction(ISD::VECREDUCE_UMAX, VT, Custom);
setOperationAction(ISD::VECREDUCE_UMIN, VT, Custom);
}
for (MVT VT : MVT::fp_valuetypes()) {
setOperationAction(ISD::VECREDUCE_FMAX, VT, Custom);
setOperationAction(ISD::VECREDUCE_FMIN, VT, Custom);
}
setOperationAction(ISD::ANY_EXTEND, MVT::v4i32, Legal);
setTruncStoreAction(MVT::v2i32, MVT::v2i16, Expand);
// Likewise, narrowing and extending vector loads/stores aren't handled
@ -2606,6 +2618,14 @@ SDValue AArch64TargetLowering::LowerOperation(SDValue Op,
return LowerMUL(Op, DAG);
case ISD::INTRINSIC_WO_CHAIN:
return LowerINTRINSIC_WO_CHAIN(Op, DAG);
case ISD::VECREDUCE_ADD:
case ISD::VECREDUCE_SMAX:
case ISD::VECREDUCE_SMIN:
case ISD::VECREDUCE_UMAX:
case ISD::VECREDUCE_UMIN:
case ISD::VECREDUCE_FMAX:
case ISD::VECREDUCE_FMIN:
return LowerVECREDUCE(Op, DAG);
}
}
@ -7128,6 +7148,47 @@ SDValue AArch64TargetLowering::LowerVSETCC(SDValue Op,
return Cmp;
}
static SDValue getReductionSDNode(unsigned Op, SDLoc DL, SDValue ScalarOp,
SelectionDAG &DAG) {
SDValue VecOp = ScalarOp.getOperand(0);
auto Rdx = DAG.getNode(Op, DL, VecOp.getSimpleValueType(), VecOp);
return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, ScalarOp.getValueType(), Rdx,
DAG.getConstant(0, DL, MVT::i64));
}
SDValue AArch64TargetLowering::LowerVECREDUCE(SDValue Op,
SelectionDAG &DAG) const {
SDLoc dl(Op);
switch (Op.getOpcode()) {
case ISD::VECREDUCE_ADD:
return getReductionSDNode(AArch64ISD::UADDV, dl, Op, DAG);
case ISD::VECREDUCE_SMAX:
return getReductionSDNode(AArch64ISD::SMAXV, dl, Op, DAG);
case ISD::VECREDUCE_SMIN:
return getReductionSDNode(AArch64ISD::SMINV, dl, Op, DAG);
case ISD::VECREDUCE_UMAX:
return getReductionSDNode(AArch64ISD::UMAXV, dl, Op, DAG);
case ISD::VECREDUCE_UMIN:
return getReductionSDNode(AArch64ISD::UMINV, dl, Op, DAG);
case ISD::VECREDUCE_FMAX: {
assert(Op->getFlags().hasNoNaNs() && "fmax vector reduction needs NoNaN flag");
return DAG.getNode(
ISD::INTRINSIC_WO_CHAIN, dl, Op.getValueType(),
DAG.getConstant(Intrinsic::aarch64_neon_fmaxnmv, dl, MVT::i32),
Op.getOperand(0));
}
case ISD::VECREDUCE_FMIN: {
assert(Op->getFlags().hasNoNaNs() && "fmin vector reduction needs NoNaN flag");
return DAG.getNode(
ISD::INTRINSIC_WO_CHAIN, dl, Op.getValueType(),
DAG.getConstant(Intrinsic::aarch64_neon_fminnmv, dl, MVT::i32),
Op.getOperand(0));
}
default:
llvm_unreachable("Unhandled reduction");
}
}
/// getTgtMemIntrinsic - Represent NEON load and store intrinsics as
/// MemIntrinsicNodes. The associated MachineMemOperands record the alignment
/// specified in the intrinsic calls.
@ -9490,266 +9551,6 @@ static SDValue performSTORECombine(SDNode *N,
return SDValue();
}
/// This function handles the log2-shuffle pattern produced by the
/// LoopVectorizer for the across vector reduction. It consists of
/// log2(NumVectorElements) steps and, in each step, 2^(s) elements
/// are reduced, where s is an induction variable from 0 to
/// log2(NumVectorElements).
static SDValue tryMatchAcrossLaneShuffleForReduction(SDNode *N, SDValue OpV,
unsigned Op,
SelectionDAG &DAG) {
EVT VTy = OpV->getOperand(0).getValueType();
if (!VTy.isVector())
return SDValue();
int NumVecElts = VTy.getVectorNumElements();
if (Op == ISD::FMAXNUM || Op == ISD::FMINNUM) {
if (NumVecElts != 4)
return SDValue();
} else {
if (NumVecElts != 4 && NumVecElts != 8 && NumVecElts != 16)
return SDValue();
}
int NumExpectedSteps = APInt(8, NumVecElts).logBase2();
SDValue PreOp = OpV;
// Iterate over each step of the across vector reduction.
for (int CurStep = 0; CurStep != NumExpectedSteps; ++CurStep) {
SDValue CurOp = PreOp.getOperand(0);
SDValue Shuffle = PreOp.getOperand(1);
if (Shuffle.getOpcode() != ISD::VECTOR_SHUFFLE) {
// Try to swap the 1st and 2nd operand as add and min/max instructions
// are commutative.
CurOp = PreOp.getOperand(1);
Shuffle = PreOp.getOperand(0);
if (Shuffle.getOpcode() != ISD::VECTOR_SHUFFLE)
return SDValue();
}
// Check if the input vector is fed by the operator we want to handle,
// except the last step; the very first input vector is not necessarily
// the same operator we are handling.
if (CurOp.getOpcode() != Op && (CurStep != (NumExpectedSteps - 1)))
return SDValue();
// Check if it forms one step of the across vector reduction.
// E.g.,
// %cur = add %1, %0
// %shuffle = vector_shuffle %cur, <2, 3, u, u>
// %pre = add %cur, %shuffle
if (Shuffle.getOperand(0) != CurOp)
return SDValue();
int NumMaskElts = 1 << CurStep;
ArrayRef<int> Mask = cast<ShuffleVectorSDNode>(Shuffle)->getMask();
// Check mask values in each step.
// We expect the shuffle mask in each step follows a specific pattern
// denoted here by the <M, U> form, where M is a sequence of integers
// starting from NumMaskElts, increasing by 1, and the number integers
// in M should be NumMaskElts. U is a sequence of UNDEFs and the number
// of undef in U should be NumVecElts - NumMaskElts.
// E.g., for <8 x i16>, mask values in each step should be :
// step 0 : <1,u,u,u,u,u,u,u>
// step 1 : <2,3,u,u,u,u,u,u>
// step 2 : <4,5,6,7,u,u,u,u>
for (int i = 0; i < NumVecElts; ++i)
if ((i < NumMaskElts && Mask[i] != (NumMaskElts + i)) ||
(i >= NumMaskElts && !(Mask[i] < 0)))
return SDValue();
PreOp = CurOp;
}
unsigned Opcode;
bool IsIntrinsic = false;
switch (Op) {
default:
llvm_unreachable("Unexpected operator for across vector reduction");
case ISD::ADD:
Opcode = AArch64ISD::UADDV;
break;
case ISD::SMAX:
Opcode = AArch64ISD::SMAXV;
break;
case ISD::UMAX:
Opcode = AArch64ISD::UMAXV;
break;
case ISD::SMIN:
Opcode = AArch64ISD::SMINV;
break;
case ISD::UMIN:
Opcode = AArch64ISD::UMINV;
break;
case ISD::FMAXNUM:
Opcode = Intrinsic::aarch64_neon_fmaxnmv;
IsIntrinsic = true;
break;
case ISD::FMINNUM:
Opcode = Intrinsic::aarch64_neon_fminnmv;
IsIntrinsic = true;
break;
}
SDLoc DL(N);
return IsIntrinsic
? DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, N->getValueType(0),
DAG.getConstant(Opcode, DL, MVT::i32), PreOp)
: DAG.getNode(
ISD::EXTRACT_VECTOR_ELT, DL, N->getValueType(0),
DAG.getNode(Opcode, DL, PreOp.getSimpleValueType(), PreOp),
DAG.getConstant(0, DL, MVT::i64));
}
/// Target-specific DAG combine for the across vector min/max reductions.
/// This function specifically handles the final clean-up step of the vector
/// min/max reductions produced by the LoopVectorizer. It is the log2-shuffle
/// pattern, which narrows down and finds the final min/max value from all
/// elements of the vector.
/// For example, for a <16 x i8> vector :
/// svn0 = vector_shuffle %0, undef<8,9,10,11,12,13,14,15,u,u,u,u,u,u,u,u>
/// %smax0 = smax %arr, svn0
/// %svn1 = vector_shuffle %smax0, undef<4,5,6,7,u,u,u,u,u,u,u,u,u,u,u,u>
/// %smax1 = smax %smax0, %svn1
/// %svn2 = vector_shuffle %smax1, undef<2,3,u,u,u,u,u,u,u,u,u,u,u,u,u,u>
/// %smax2 = smax %smax1, svn2
/// %svn3 = vector_shuffle %smax2, undef<1,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u>
/// %sc = setcc %smax2, %svn3, gt
/// %n0 = extract_vector_elt %sc, #0
/// %n1 = extract_vector_elt %smax2, #0
/// %n2 = extract_vector_elt $smax2, #1
/// %result = select %n0, %n1, n2
/// becomes :
/// %1 = smaxv %0
/// %result = extract_vector_elt %1, 0
static SDValue
performAcrossLaneMinMaxReductionCombine(SDNode *N, SelectionDAG &DAG,
const AArch64Subtarget *Subtarget) {
if (!Subtarget->hasNEON())
return SDValue();
SDValue N0 = N->getOperand(0);
SDValue IfTrue = N->getOperand(1);
SDValue IfFalse = N->getOperand(2);
// Check if the SELECT merges up the final result of the min/max
// from a vector.
if (N0.getOpcode() != ISD::EXTRACT_VECTOR_ELT ||
IfTrue.getOpcode() != ISD::EXTRACT_VECTOR_ELT ||
IfFalse.getOpcode() != ISD::EXTRACT_VECTOR_ELT)
return SDValue();
// Expect N0 is fed by SETCC.
SDValue SetCC = N0.getOperand(0);
EVT SetCCVT = SetCC.getValueType();
if (SetCC.getOpcode() != ISD::SETCC || !SetCCVT.isVector() ||
SetCCVT.getVectorElementType() != MVT::i1)
return SDValue();
SDValue VectorOp = SetCC.getOperand(0);
unsigned Op = VectorOp->getOpcode();
// Check if the input vector is fed by the operator we want to handle.
if (Op != ISD::SMAX && Op != ISD::UMAX && Op != ISD::SMIN &&
Op != ISD::UMIN && Op != ISD::FMAXNUM && Op != ISD::FMINNUM)
return SDValue();
EVT VTy = VectorOp.getValueType();
if (!VTy.isVector())
return SDValue();
if (VTy.getSizeInBits() < 64)
return SDValue();
EVT EltTy = VTy.getVectorElementType();
if (Op == ISD::FMAXNUM || Op == ISD::FMINNUM) {
if (EltTy != MVT::f32)
return SDValue();
} else {
if (EltTy != MVT::i32 && EltTy != MVT::i16 && EltTy != MVT::i8)
return SDValue();
}
// Check if extracting from the same vector.
// For example,
// %sc = setcc %vector, %svn1, gt
// %n0 = extract_vector_elt %sc, #0
// %n1 = extract_vector_elt %vector, #0
// %n2 = extract_vector_elt $vector, #1
if (!(VectorOp == IfTrue->getOperand(0) &&
VectorOp == IfFalse->getOperand(0)))
return SDValue();
// Check if the condition code is matched with the operator type.
ISD::CondCode CC = cast<CondCodeSDNode>(SetCC->getOperand(2))->get();
if ((Op == ISD::SMAX && CC != ISD::SETGT && CC != ISD::SETGE) ||
(Op == ISD::UMAX && CC != ISD::SETUGT && CC != ISD::SETUGE) ||
(Op == ISD::SMIN && CC != ISD::SETLT && CC != ISD::SETLE) ||
(Op == ISD::UMIN && CC != ISD::SETULT && CC != ISD::SETULE) ||
(Op == ISD::FMAXNUM && CC != ISD::SETOGT && CC != ISD::SETOGE &&
CC != ISD::SETUGT && CC != ISD::SETUGE && CC != ISD::SETGT &&
CC != ISD::SETGE) ||
(Op == ISD::FMINNUM && CC != ISD::SETOLT && CC != ISD::SETOLE &&
CC != ISD::SETULT && CC != ISD::SETULE && CC != ISD::SETLT &&
CC != ISD::SETLE))
return SDValue();
// Expect to check only lane 0 from the vector SETCC.
if (!isNullConstant(N0.getOperand(1)))
return SDValue();
// Expect to extract the true value from lane 0.
if (!isNullConstant(IfTrue.getOperand(1)))
return SDValue();
// Expect to extract the false value from lane 1.
if (!isOneConstant(IfFalse.getOperand(1)))
return SDValue();
return tryMatchAcrossLaneShuffleForReduction(N, SetCC, Op, DAG);
}
/// Target-specific DAG combine for the across vector add reduction.
/// This function specifically handles the final clean-up step of the vector
/// add reduction produced by the LoopVectorizer. It is the log2-shuffle
/// pattern, which adds all elements of a vector together.
/// For example, for a <4 x i32> vector :
/// %1 = vector_shuffle %0, <2,3,u,u>
/// %2 = add %0, %1
/// %3 = vector_shuffle %2, <1,u,u,u>
/// %4 = add %2, %3
/// %result = extract_vector_elt %4, 0
/// becomes :
/// %0 = uaddv %0
/// %result = extract_vector_elt %0, 0
static SDValue
performAcrossLaneAddReductionCombine(SDNode *N, SelectionDAG &DAG,
const AArch64Subtarget *Subtarget) {
if (!Subtarget->hasNEON())
return SDValue();
SDValue N0 = N->getOperand(0);
SDValue N1 = N->getOperand(1);
// Check if the input vector is fed by the ADD.
if (N0->getOpcode() != ISD::ADD)
return SDValue();
// The vector extract idx must constant zero because we only expect the final
// result of the reduction is placed in lane 0.
if (!isNullConstant(N1))
return SDValue();
EVT VTy = N0.getValueType();
if (!VTy.isVector())
return SDValue();
EVT EltTy = VTy.getVectorElementType();
if (EltTy != MVT::i32 && EltTy != MVT::i16 && EltTy != MVT::i8)
return SDValue();
if (VTy.getSizeInBits() < 64)
return SDValue();
return tryMatchAcrossLaneShuffleForReduction(N, N0, ISD::ADD, DAG);
}
/// Target-specific DAG combine function for NEON load/store intrinsics
/// to merge base address updates.
@ -10428,12 +10229,8 @@ SDValue AArch64TargetLowering::PerformDAGCombine(SDNode *N,
return performBitcastCombine(N, DCI, DAG);
case ISD::CONCAT_VECTORS:
return performConcatVectorsCombine(N, DCI, DAG);
case ISD::SELECT: {
SDValue RV = performSelectCombine(N, DCI);
if (!RV.getNode())
RV = performAcrossLaneMinMaxReductionCombine(N, DAG, Subtarget);
return RV;
}
case ISD::SELECT:
return performSelectCombine(N, DCI);
case ISD::VSELECT:
return performVSelectCombine(N, DCI.DAG);
case ISD::LOAD:
@ -10455,8 +10252,6 @@ SDValue AArch64TargetLowering::PerformDAGCombine(SDNode *N,
return performNVCASTCombine(N);
case ISD::INSERT_VECTOR_ELT:
return performPostLD1Combine(N, DCI, true);
case ISD::EXTRACT_VECTOR_ELT:
return performAcrossLaneAddReductionCombine(N, DAG, Subtarget);
case ISD::INTRINSIC_VOID:
case ISD::INTRINSIC_W_CHAIN:
switch (cast<ConstantSDNode>(N->getOperand(1))->getZExtValue()) {
@ -10676,6 +10471,14 @@ void AArch64TargetLowering::ReplaceNodeResults(
case ISD::BITCAST:
ReplaceBITCASTResults(N, Results, DAG);
return;
case ISD::VECREDUCE_ADD:
case ISD::VECREDUCE_SMAX:
case ISD::VECREDUCE_SMIN:
case ISD::VECREDUCE_UMAX:
case ISD::VECREDUCE_UMIN:
Results.push_back(LowerVECREDUCE(SDValue(N, 0), DAG));
return;
case AArch64ISD::SADDV:
ReplaceReductionResults(N, Results, DAG, ISD::ADD, AArch64ISD::SADDV);
return;

View File

@ -568,6 +568,7 @@ class AArch64TargetLowering : public TargetLowering {
SDValue LowerVectorOR(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerFSINCOS(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerVECREDUCE(SDValue Op, SelectionDAG &DAG) const;
SDValue BuildSDIVPow2(SDNode *N, const APInt &Divisor, SelectionDAG &DAG,
std::vector<SDNode *> *Created) const override;

View File

@ -769,3 +769,28 @@ unsigned AArch64TTIImpl::getMinPrefetchStride() {
unsigned AArch64TTIImpl::getMaxPrefetchIterationsAhead() {
return ST->getMaxPrefetchIterationsAhead();
}
bool AArch64TTIImpl::useReductionIntrinsic(unsigned Opcode, Type *Ty,
TTI::ReductionFlags Flags) const {
assert(isa<VectorType>(Ty) && "Expected Ty to be a vector type");
unsigned ScalarBits = Ty->getScalarSizeInBits();
switch (Opcode) {
case Instruction::FAdd:
case Instruction::FMul:
case Instruction::And:
case Instruction::Or:
case Instruction::Xor:
case Instruction::Mul:
return false;
case Instruction::Add:
return ScalarBits * Ty->getVectorNumElements() >= 128;
case Instruction::ICmp:
return (ScalarBits < 64) &&
(ScalarBits * Ty->getVectorNumElements() >= 128);
case Instruction::FCmp:
return Flags.NoNaN;
default:
llvm_unreachable("Unhandled reduction opcode");
}
return false;
}

View File

@ -145,6 +145,9 @@ class AArch64TTIImpl : public BasicTTIImplBase<AArch64TTIImpl> {
bool shouldExpandReduction(const IntrinsicInst *II) const {
return false;
}
bool useReductionIntrinsic(unsigned Opcode, Type *Ty,
TTI::ReductionFlags Flags) const;
/// @}
};

View File

@ -1707,10 +1707,38 @@ bool AMDGPUDAGToDAGISel::SelectVOP3PMods(SDValue In, SDValue &Src,
// FIXME: Look for on separate components
if (Src.getOpcode() == ISD::FNEG) {
Mods |= (SISrcMods::NEG | SISrcMods::NEG_HI);
Mods ^= (SISrcMods::NEG | SISrcMods::NEG_HI);
Src = Src.getOperand(0);
}
if (Src.getOpcode() == ISD::BUILD_VECTOR) {
unsigned VecMods = Mods;
SDValue Lo = Src.getOperand(0);
SDValue Hi = Src.getOperand(1);
if (Lo.getOpcode() == ISD::FNEG) {
Lo = Lo.getOperand(0);
Mods ^= SISrcMods::NEG;
}
if (Hi.getOpcode() == ISD::FNEG) {
Hi = Hi.getOperand(0);
Mods ^= SISrcMods::NEG_HI;
}
if (Lo == Hi && !isInlineImmediate(Lo.getNode())) {
// Really a scalar input. Just select from the low half of the register to
// avoid packing.
Src = Lo;
SrcMods = CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
return true;
}
Mods = VecMods;
}
// Packed instructions do not have abs modifiers.
// FIXME: Handle abs/neg of individual components.

View File

@ -289,6 +289,10 @@ class AMDGPUSubtarget : public AMDGPUGenSubtargetInfo {
return getGeneration() >= GFX9;
}
bool hasMin3Max3_16() const {
return getGeneration() >= GFX9;
}
bool hasCARRY() const {
return (getGeneration() >= EVERGREEN);
}

View File

@ -4491,7 +4491,8 @@ SDValue SITargetLowering::performMinMaxCombine(SDNode *N,
if (Opc != AMDGPUISD::FMIN_LEGACY && Opc != AMDGPUISD::FMAX_LEGACY &&
VT != MVT::f64) {
VT != MVT::f64 &&
((VT != MVT::f16 && VT != MVT::i16) || Subtarget->hasMin3Max3_16())) {
// max(max(a, b), c) -> max3(a, b, c)
// min(min(a, b), c) -> min3(a, b, c)
if (Op0.getOpcode() == Opc && Op0.hasOneUse()) {

View File

@ -765,7 +765,7 @@ void SIInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
.addFrameIndex(FrameIndex) // addr
.addMemOperand(MMO)
.addReg(MFI->getScratchRSrcReg(), RegState::Implicit)
.addReg(MFI->getScratchWaveOffsetReg(), RegState::Implicit);
.addReg(MFI->getFrameOffsetReg(), RegState::Implicit);
// Add the scratch resource registers as implicit uses because we may end up
// needing them, and need to ensure that the reserved registers are
// correctly handled.
@ -796,7 +796,7 @@ void SIInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
.addReg(SrcReg, getKillRegState(isKill)) // data
.addFrameIndex(FrameIndex) // addr
.addReg(MFI->getScratchRSrcReg()) // scratch_rsrc
.addReg(MFI->getScratchWaveOffsetReg()) // scratch_offset
.addReg(MFI->getFrameOffsetReg()) // scratch_offset
.addImm(0) // offset
.addMemOperand(MMO);
}
@ -869,7 +869,7 @@ void SIInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
.addFrameIndex(FrameIndex) // addr
.addMemOperand(MMO)
.addReg(MFI->getScratchRSrcReg(), RegState::Implicit)
.addReg(MFI->getScratchWaveOffsetReg(), RegState::Implicit);
.addReg(MFI->getFrameOffsetReg(), RegState::Implicit);
if (ST.hasScalarStores()) {
// m0 is used for offset to scalar stores if used to spill.
@ -892,10 +892,10 @@ void SIInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
unsigned Opcode = getVGPRSpillRestoreOpcode(SpillSize);
BuildMI(MBB, MI, DL, get(Opcode), DestReg)
.addFrameIndex(FrameIndex) // vaddr
.addReg(MFI->getScratchRSrcReg()) // scratch_rsrc
.addReg(MFI->getScratchWaveOffsetReg()) // scratch_offset
.addImm(0) // offset
.addFrameIndex(FrameIndex) // vaddr
.addReg(MFI->getScratchRSrcReg()) // scratch_rsrc
.addReg(MFI->getFrameOffsetReg()) // scratch_offset
.addImm(0) // offset
.addMemOperand(MMO);
}

View File

@ -654,11 +654,11 @@ bool SIRegisterInfo::spillSGPR(MachineBasicBlock::iterator MI,
int64_t Offset = (ST.getWavefrontSize() * FrOffset) + (EltSize * i);
if (Offset != 0) {
BuildMI(*MBB, MI, DL, TII->get(AMDGPU::S_ADD_U32), OffsetReg)
.addReg(MFI->getScratchWaveOffsetReg())
.addReg(MFI->getFrameOffsetReg())
.addImm(Offset);
} else {
BuildMI(*MBB, MI, DL, TII->get(AMDGPU::S_MOV_B32), OffsetReg)
.addReg(MFI->getScratchWaveOffsetReg());
.addReg(MFI->getFrameOffsetReg());
}
BuildMI(*MBB, MI, DL, TII->get(ScalarStoreOp))
@ -715,11 +715,11 @@ bool SIRegisterInfo::spillSGPR(MachineBasicBlock::iterator MI,
= MF->getMachineMemOperand(PtrInfo, MachineMemOperand::MOStore,
EltSize, MinAlign(Align, EltSize * i));
BuildMI(*MBB, MI, DL, TII->get(AMDGPU::SI_SPILL_V32_SAVE))
.addReg(TmpReg, RegState::Kill) // src
.addFrameIndex(Index) // vaddr
.addReg(MFI->getScratchRSrcReg()) // srrsrc
.addReg(MFI->getScratchWaveOffsetReg()) // soffset
.addImm(i * 4) // offset
.addReg(TmpReg, RegState::Kill) // src
.addFrameIndex(Index) // vaddr
.addReg(MFI->getScratchRSrcReg()) // srrsrc
.addReg(MFI->getFrameOffsetReg()) // soffset
.addImm(i * 4) // offset
.addMemOperand(MMO);
}
}
@ -806,11 +806,11 @@ bool SIRegisterInfo::restoreSGPR(MachineBasicBlock::iterator MI,
int64_t Offset = (ST.getWavefrontSize() * FrOffset) + (EltSize * i);
if (Offset != 0) {
BuildMI(*MBB, MI, DL, TII->get(AMDGPU::S_ADD_U32), OffsetReg)
.addReg(MFI->getScratchWaveOffsetReg())
.addReg(MFI->getFrameOffsetReg())
.addImm(Offset);
} else {
BuildMI(*MBB, MI, DL, TII->get(AMDGPU::S_MOV_B32), OffsetReg)
.addReg(MFI->getScratchWaveOffsetReg());
.addReg(MFI->getFrameOffsetReg());
}
auto MIB =
@ -853,10 +853,10 @@ bool SIRegisterInfo::restoreSGPR(MachineBasicBlock::iterator MI,
MinAlign(Align, EltSize * i));
BuildMI(*MBB, MI, DL, TII->get(AMDGPU::SI_SPILL_V32_RESTORE), TmpReg)
.addFrameIndex(Index) // vaddr
.addReg(MFI->getScratchRSrcReg()) // srsrc
.addReg(MFI->getScratchWaveOffsetReg()) // soffset
.addImm(i * 4) // offset
.addFrameIndex(Index) // vaddr
.addReg(MFI->getScratchRSrcReg()) // srsrc
.addReg(MFI->getFrameOffsetReg()) // soffset
.addImm(i * 4) // offset
.addMemOperand(MMO);
auto MIB =

View File

@ -300,10 +300,19 @@ def V_AND_OR_B32 : VOP3Inst <"v_and_or_b32", VOP3_Profile<VOP_I32_I32_I32_I32>>;
def V_OR3_B32 : VOP3Inst <"v_or3_b32", VOP3_Profile<VOP_I32_I32_I32_I32>>;
def V_XAD_U32 : VOP3Inst <"v_xad_u32", VOP3_Profile<VOP_I32_I32_I32_I32>>;
def V_MED3_F16 : VOP3Inst <"v_med3_f16", VOP3_Profile<VOP_F16_F16_F16_F16>, AMDGPUfmed3>;
def V_MED3_I16 : VOP3Inst <"v_med3_i16", VOP3_Profile<VOP_I16_I16_I16_I16>, AMDGPUsmed3>;
def V_MED3_U16 : VOP3Inst <"v_med3_u16", VOP3_Profile<VOP_I16_I16_I16_I16>, AMDGPUumed3>;
}
def V_MIN3_F16 : VOP3Inst <"v_min3_f16", VOP3_Profile<VOP_F16_F16_F16_F16>, AMDGPUfmin3>;
def V_MIN3_I16 : VOP3Inst <"v_min3_i16", VOP3_Profile<VOP_I16_I16_I16_I16>, AMDGPUsmin3>;
def V_MIN3_U16 : VOP3Inst <"v_min3_u16", VOP3_Profile<VOP_I16_I16_I16_I16>, AMDGPUumin3>;
def V_MAX3_F16 : VOP3Inst <"v_max3_f16", VOP3_Profile<VOP_F16_F16_F16_F16>, AMDGPUfmax3>;
def V_MAX3_I16 : VOP3Inst <"v_max3_i16", VOP3_Profile<VOP_I16_I16_I16_I16>, AMDGPUsmax3>;
def V_MAX3_U16 : VOP3Inst <"v_max3_u16", VOP3_Profile<VOP_I16_I16_I16_I16>, AMDGPUumax3>;
} // End SubtargetPredicate = isGFX9
//===----------------------------------------------------------------------===//
@ -509,6 +518,15 @@ defm V_OR3_B32 : VOP3_Real_vi <0x202>;
defm V_PACK_B32_F16 : VOP3_Real_vi <0x2a0>;
defm V_XAD_U32 : VOP3_Real_vi <0x1f3>;
defm V_MIN3_F16 : VOP3_Real_vi <0x1f4>;
defm V_MIN3_I16 : VOP3_Real_vi <0x1f5>;
defm V_MIN3_U16 : VOP3_Real_vi <0x1f6>;
defm V_MAX3_F16 : VOP3_Real_vi <0x1f7>;
defm V_MAX3_I16 : VOP3_Real_vi <0x1f8>;
defm V_MAX3_U16 : VOP3_Real_vi <0x1f9>;
defm V_MED3_F16 : VOP3_Real_vi <0x1fa>;
defm V_MED3_I16 : VOP3_Real_vi <0x1fb>;
defm V_MED3_U16 : VOP3_Real_vi <0x1fc>;

View File

@ -345,25 +345,10 @@ bool ARMInstructionSelector::select(MachineInstr &I) const {
I.setDesc(TII.get(COPY));
return selectCopy(I, TII, MRI, TRI, RBI);
}
case G_ADD:
case G_GEP:
I.setDesc(TII.get(ARM::ADDrr));
MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
break;
case G_SUB:
I.setDesc(TII.get(ARM::SUBrr));
MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
break;
case G_MUL:
if (TII.getSubtarget().hasV6Ops()) {
I.setDesc(TII.get(ARM::MUL));
} else {
assert(TII.getSubtarget().useMulOps() && "Unsupported target");
I.setDesc(TII.get(ARM::MULv5));
MIB->getOperand(0).setIsEarlyClobber(true);
}
MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
break;
case G_FRAME_INDEX:
// Add 0 to the given frame index and hope it will eventually be folded into
// the user(s).

View File

@ -571,8 +571,7 @@ bool Thumb1FrameLowering::emitPopSpecialFixUp(MachineBasicBlock &MBB,
GPRsNoLRSP.reset(ARM::LR);
GPRsNoLRSP.reset(ARM::SP);
GPRsNoLRSP.reset(ARM::PC);
for (int Register = GPRsNoLRSP.find_first(); Register != -1;
Register = GPRsNoLRSP.find_next(Register)) {
for (unsigned Register : GPRsNoLRSP.set_bits()) {
if (!UsedRegs.contains(Register)) {
// Remember the first pop-friendly register and exit.
if (PopFriendly.test(Register)) {

View File

@ -386,7 +386,7 @@ void RegDefsUses::setCallerSaved(const MachineInstr &MI) {
void RegDefsUses::setUnallocatableRegs(const MachineFunction &MF) {
BitVector AllocSet = TRI.getAllocatableSet(MF);
for (int R = AllocSet.find_first(); R != -1; R = AllocSet.find_next(R))
for (unsigned R : AllocSet.set_bits())
for (MCRegAliasIterator AI(R, &TRI, false); AI.isValid(); ++AI)
AllocSet.set(*AI);

View File

@ -1765,31 +1765,36 @@ void PPCFrameLowering::processFunctionBeforeFrameFinalized(MachineFunction &MF,
// Check whether the frame pointer register is allocated. If so, make sure it
// is spilled to the correct offset.
if (needsFP(MF)) {
HasGPSaveArea = true;
int FI = PFI->getFramePointerSaveIndex();
assert(FI && "No Frame Pointer Save Slot!");
MFI.setObjectOffset(FI, LowerBound + MFI.getObjectOffset(FI));
// FP is R31/X31, so no need to update MinGPR/MinG8R.
HasGPSaveArea = true;
}
if (PFI->usesPICBase()) {
HasGPSaveArea = true;
int FI = PFI->getPICBasePointerSaveIndex();
assert(FI && "No PIC Base Pointer Save Slot!");
MFI.setObjectOffset(FI, LowerBound + MFI.getObjectOffset(FI));
MinGPR = std::min<unsigned>(MinGPR, PPC::R30);
HasGPSaveArea = true;
}
const PPCRegisterInfo *RegInfo = Subtarget.getRegisterInfo();
if (RegInfo->hasBasePointer(MF)) {
HasGPSaveArea = true;
int FI = PFI->getBasePointerSaveIndex();
assert(FI && "No Base Pointer Save Slot!");
MFI.setObjectOffset(FI, LowerBound + MFI.getObjectOffset(FI));
unsigned BP = RegInfo->getBaseRegister(MF);
if (PPC::G8RCRegClass.contains(BP)) {
MinG8R = std::min<unsigned>(MinG8R, BP);
HasG8SaveArea = true;
} else if (PPC::GPRCRegClass.contains(BP)) {
MinGPR = std::min<unsigned>(MinGPR, BP);
HasGPSaveArea = true;
}
}
// General register save area starts right below the Floating-point

View File

@ -410,6 +410,11 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
// To handle counter-based loop conditions.
setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::i1, Custom);
setOperationAction(ISD::INTRINSIC_VOID, MVT::i8, Custom);
setOperationAction(ISD::INTRINSIC_VOID, MVT::i16, Custom);
setOperationAction(ISD::INTRINSIC_VOID, MVT::i32, Custom);
setOperationAction(ISD::INTRINSIC_VOID, MVT::Other, Custom);
// Comparisons that require checking two conditions.
setCondCodeAction(ISD::SETULT, MVT::f32, Expand);
setCondCodeAction(ISD::SETULT, MVT::f64, Expand);
@ -8184,6 +8189,26 @@ SDValue PPCTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
return Flags;
}
SDValue PPCTargetLowering::LowerINTRINSIC_VOID(SDValue Op,
SelectionDAG &DAG) const {
// SelectionDAGBuilder::visitTargetIntrinsic may insert one extra chain to
// the beginning of the argument list.
int ArgStart = isa<ConstantSDNode>(Op.getOperand(0)) ? 0 : 1;
SDLoc DL(Op);
switch (cast<ConstantSDNode>(Op.getOperand(ArgStart))->getZExtValue()) {
case Intrinsic::ppc_cfence: {
assert(Subtarget.isPPC64() && "Only 64-bit is supported for now.");
return SDValue(DAG.getMachineNode(PPC::CFENCE8, DL, MVT::Other,
DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64,
Op.getOperand(ArgStart + 1))),
0);
}
default:
break;
}
return SDValue();
}
SDValue PPCTargetLowering::LowerSIGN_EXTEND_INREG(SDValue Op,
SelectionDAG &DAG) const {
SDLoc dl(Op);
@ -8649,6 +8674,9 @@ SDValue PPCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
// Frame & Return address.
case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG);
case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG);
case ISD::INTRINSIC_VOID:
return LowerINTRINSIC_VOID(Op, DAG);
}
}
@ -8753,12 +8781,19 @@ Instruction *PPCTargetLowering::emitLeadingFence(IRBuilder<> &Builder,
Instruction *PPCTargetLowering::emitTrailingFence(IRBuilder<> &Builder,
Instruction *Inst,
AtomicOrdering Ord) const {
if (Inst->hasAtomicLoad() && isAcquireOrStronger(Ord))
if (Inst->hasAtomicLoad() && isAcquireOrStronger(Ord)) {
// See http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html and
// http://www.rdrop.com/users/paulmck/scalability/paper/N2745r.2011.03.04a.html
// and http://www.cl.cam.ac.uk/~pes20/cppppc/ for justification.
if (isa<LoadInst>(Inst) && Subtarget.isPPC64())
return Builder.CreateCall(
Intrinsic::getDeclaration(
Builder.GetInsertBlock()->getParent()->getParent(),
Intrinsic::ppc_cfence, {Inst->getType()}),
{Inst});
// FIXME: Can use isync for rmw operation.
return callIntrinsic(Builder, Intrinsic::ppc_lwsync);
// FIXME: this is too conservative, a dependent branch + isync is enough.
// See http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html and
// http://www.rdrop.com/users/paulmck/scalability/paper/N2745r.2011.03.04a.html
// and http://www.cl.cam.ac.uk/~pes20/cppppc/ for justification.
}
return nullptr;
}

View File

@ -905,6 +905,7 @@ namespace llvm {
SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerINTRINSIC_VOID(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerSIGN_EXTEND_INREG(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerMUL(SDValue Op, SelectionDAG &DAG) const;

View File

@ -983,6 +983,10 @@ def LDgotTprelL: Pseudo<(outs g8rc:$rD), (ins s16imm64:$disp, g8rc_nox0:$reg),
[(set i64:$rD,
(PPCldGotTprelL tglobaltlsaddr:$disp, i64:$reg))]>,
isPPC64;
let isBarrier = 1, isPseudo = 1, Defs = [CR7], Itinerary = IIC_LdStSync in
def CFENCE8 : Pseudo<(outs), (ins g8rc:$cr), "#CFENCE8", []>;
def : Pat<(PPCaddTls i64:$in, tglobaltlsaddr:$g),
(ADD8TLS $in, tglobaltlsaddr:$g)>;
def ADDIStlsgdHA: Pseudo<(outs g8rc:$rD), (ins g8rc_nox0:$reg, s16imm64:$disp),

View File

@ -1873,6 +1873,8 @@ PPCInstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const {
}
bool PPCInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
auto &MBB = *MI.getParent();
auto DL = MI.getDebugLoc();
switch (MI.getOpcode()) {
case TargetOpcode::LOAD_STACK_GUARD: {
assert(Subtarget.isTargetLinux() &&
@ -1920,6 +1922,17 @@ bool PPCInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
MI.setDesc(get(Opcode));
return true;
}
case PPC::CFENCE8: {
auto Val = MI.getOperand(0).getReg();
BuildMI(MBB, MI, DL, get(PPC::CMPW), PPC::CR7).addReg(Val).addReg(Val);
BuildMI(MBB, MI, DL, get(PPC::CTRL_DEP))
.addImm(PPC::PRED_NE_MINUS)
.addReg(PPC::CR7)
.addImm(1);
MI.setDesc(get(PPC::ISYNC));
MI.RemoveOperand(0);
return true;
}
}
return false;
}

View File

@ -1223,9 +1223,15 @@ let isBranch = 1, isTerminator = 1, hasCtrlDep = 1, PPC970_Unit = 7 in {
// FIXME: should be able to write a pattern for PPCcondbranch, but can't use
// a two-value operand where a dag node expects two operands. :(
let isCodeGenOnly = 1 in {
def BCC : BForm<16, 0, 0, (outs), (ins pred:$cond, condbrtarget:$dst),
"b${cond:cc}${cond:pm} ${cond:reg}, $dst"
/*[(PPCcondbranch crrc:$crS, imm:$opc, bb:$dst)]*/>;
class BCC_class : BForm<16, 0, 0, (outs), (ins pred:$cond, condbrtarget:$dst),
"b${cond:cc}${cond:pm} ${cond:reg}, $dst"
/*[(PPCcondbranch crrc:$crS, imm:$opc, bb:$dst)]*/>;
def BCC : BCC_class;
// The same as BCC, except that it's not a terminator. Used for introducing
// control flow dependency without creating new blocks.
let isTerminator = 0 in def CTRL_DEP : BCC_class;
def BCCA : BForm<16, 1, 0, (outs), (ins pred:$cond, abscondbrtarget:$dst),
"b${cond:cc}a${cond:pm} ${cond:reg}, $dst">;

View File

@ -325,6 +325,30 @@ int SystemZTTIImpl::getArithmeticInstrCost(
unsigned ScalarBits = Ty->getScalarSizeInBits();
// Div with a constant which is a power of 2 will be converted by
// DAGCombiner to use shifts. With vector shift-element instructions, a
// vector sdiv costs about as much as a scalar one.
const unsigned SDivCostEstimate = 4;
bool SDivPow2 = false;
bool UDivPow2 = false;
if ((Opcode == Instruction::SDiv || Opcode == Instruction::UDiv) &&
Args.size() == 2) {
const ConstantInt *CI = nullptr;
if (const Constant *C = dyn_cast<Constant>(Args[1])) {
if (C->getType()->isVectorTy())
CI = dyn_cast_or_null<const ConstantInt>(C->getSplatValue());
else
CI = dyn_cast<const ConstantInt>(C);
}
if (CI != nullptr &&
(CI->getValue().isPowerOf2() || (-CI->getValue()).isPowerOf2())) {
if (Opcode == Instruction::SDiv)
SDivPow2 = true;
else
UDivPow2 = true;
}
}
if (Ty->isVectorTy()) {
assert (ST->hasVector() && "getArithmeticInstrCost() called with vector type.");
unsigned VF = Ty->getVectorNumElements();
@ -333,10 +357,13 @@ int SystemZTTIImpl::getArithmeticInstrCost(
// These vector operations are custom handled, but are still supported
// with one instruction per vector, regardless of element size.
if (Opcode == Instruction::Shl || Opcode == Instruction::LShr ||
Opcode == Instruction::AShr) {
Opcode == Instruction::AShr || UDivPow2) {
return NumVectors;
}
if (SDivPow2)
return (NumVectors * SDivCostEstimate);
// These FP operations are supported with a single vector instruction for
// double (base implementation assumes float generally costs 2). For
// FP128, the scalar cost is 1, and there is no overhead since the values
@ -395,6 +422,11 @@ int SystemZTTIImpl::getArithmeticInstrCost(
// 2 * ipm sequences ; xor ; shift ; compare
return 7;
if (UDivPow2)
return 1;
if (SDivPow2)
return SDivCostEstimate;
// An extra extension for narrow types is needed.
if ((Opcode == Instruction::SDiv || Opcode == Instruction::SRem))
// sext of op(s) for narrow types

View File

@ -140,8 +140,7 @@ bool WebAssemblyRegColoring::runOnMachineFunction(MachineFunction &MF) {
// Check if it's possible to reuse any of the used colors.
if (!MRI->isLiveIn(Old))
for (int C(UsedColors.find_first()); C != -1;
C = UsedColors.find_next(C)) {
for (unsigned C : UsedColors.set_bits()) {
if (MRI->getRegClass(SortedIntervals[C]->reg) != RC)
continue;
for (LiveInterval *OtherLI : Assignments[C])

View File

@ -33,9 +33,6 @@ built-in-setjmp.c
pr60003.c
# Error in the program / unsupported by Clang.
scal-to-vec1.c
scal-to-vec2.c
scal-to-vec3.c
20000822-1.c
20010209-1.c
20010605-1.c

View File

@ -235,8 +235,6 @@ def FeatureLEAUsesAG : SubtargetFeature<"lea-uses-ag", "LEAUsesAG", "true",
"LEA instruction needs inputs at AG stage">;
def FeatureSlowLEA : SubtargetFeature<"slow-lea", "SlowLEA", "true",
"LEA instruction with certain arguments is slow">;
def FeatureSlow3OpsLEA : SubtargetFeature<"slow-3ops-lea", "Slow3OpsLEA", "true",
"LEA instruction with 3 ops or certain registers is slow">;
def FeatureSlowIncDec : SubtargetFeature<"slow-incdec", "SlowIncDec", "true",
"INC and DEC instructions are slower than ADD and SUB">;
def FeatureSoftFloat
@ -482,7 +480,6 @@ def SNBFeatures : ProcessorFeatures<[], [
FeatureXSAVE,
FeatureXSAVEOPT,
FeatureLAHFSAHF,
FeatureSlow3OpsLEA,
FeatureFastScalarFSQRT,
FeatureFastSHLDRotate
]>;

View File

@ -27,26 +27,20 @@
#include "llvm/Target/TargetInstrInfo.h"
using namespace llvm;
namespace llvm {
void initializeFixupLEAPassPass(PassRegistry &);
}
#define FIXUPLEA_DESC "X86 LEA Fixup"
#define FIXUPLEA_NAME "x86-fixup-LEAs"
#define DEBUG_TYPE FIXUPLEA_NAME
#define DEBUG_TYPE "x86-fixup-LEAs"
STATISTIC(NumLEAs, "Number of LEA instructions created");
namespace {
class FixupLEAPass : public MachineFunctionPass {
enum RegUsageState { RU_NotUsed, RU_Write, RU_Read };
static char ID;
/// \brief Loop over all of the instructions in the basic block
/// replacing applicable instructions with LEA instructions,
/// where appropriate.
bool processBasicBlock(MachineFunction &MF, MachineFunction::iterator MFI);
StringRef getPassName() const override { return "X86 LEA Fixup"; }
/// \brief Given a machine register, look for the instruction
/// which writes it in the current basic block. If found,
@ -68,22 +62,6 @@ class FixupLEAPass : public MachineFunctionPass {
void processInstructionForSLM(MachineBasicBlock::iterator &I,
MachineFunction::iterator MFI);
/// \brief Given a LEA instruction which is unprofitable
/// on SNB+ try to replace it with other instructions.
/// According to Intel's Optimization Reference Manual:
/// " For LEA instructions with three source operands and some specific
/// situations, instruction latency has increased to 3 cycles, and must
/// dispatch via port 1:
/// - LEA that has all three source operands: base, index, and offset
/// - LEA that uses base and index registers where the base is EBP, RBP,
/// or R13
/// - LEA that uses RIP relative addressing mode
/// - LEA that uses 16-bit addressing mode "
/// This function currently handles the first 2 cases only.
MachineInstr *processInstrForSlow3OpLEA(MachineInstr &MI,
MachineFunction::iterator MFI);
/// \brief Look for LEAs that add 1 to reg or subtract 1 from reg
/// and convert them to INC or DEC respectively.
bool fixupIncDec(MachineBasicBlock::iterator &I,
@ -107,13 +85,7 @@ class FixupLEAPass : public MachineFunctionPass {
MachineBasicBlock::iterator &MBBI) const;
public:
static char ID;
StringRef getPassName() const override { return FIXUPLEA_DESC; }
FixupLEAPass() : MachineFunctionPass(ID) {
initializeFixupLEAPassPass(*PassRegistry::getPassRegistry());
}
FixupLEAPass() : MachineFunctionPass(ID) {}
/// \brief Loop over all of the basic blocks,
/// replacing instructions by equivalent LEA instructions
@ -132,11 +104,8 @@ class FixupLEAPass : public MachineFunctionPass {
bool OptIncDec;
bool OptLEA;
};
}
char FixupLEAPass::ID = 0;
INITIALIZE_PASS(FixupLEAPass, FIXUPLEA_NAME, FIXUPLEA_DESC, false, false)
}
MachineInstr *
FixupLEAPass::postRAConvertToLEA(MachineFunction::iterator &MFI,
@ -199,7 +168,7 @@ bool FixupLEAPass::runOnMachineFunction(MachineFunction &Func) {
MF = &Func;
const X86Subtarget &ST = Func.getSubtarget<X86Subtarget>();
OptIncDec = !ST.slowIncDec() || Func.getFunction()->optForMinSize();
OptLEA = ST.LEAusesAG() || ST.slowLEA() || ST.slow3OpsLEA();
OptLEA = ST.LEAusesAG() || ST.slowLEA();
if (!OptLEA && !OptIncDec)
return false;
@ -273,64 +242,9 @@ FixupLEAPass::searchBackwards(MachineOperand &p, MachineBasicBlock::iterator &I,
return MachineBasicBlock::iterator();
}
static inline bool isLEA(const int Opcode) {
return Opcode == X86::LEA16r || Opcode == X86::LEA32r ||
Opcode == X86::LEA64r || Opcode == X86::LEA64_32r;
}
static inline bool isInefficientLEAReg(unsigned int Reg) {
return Reg == X86::EBP || Reg == X86::RBP || Reg == X86::R13;
}
static inline bool isRegOperand(const MachineOperand &Op) {
return Op.isReg() && Op.getReg() != X86::NoRegister;
}
/// hasIneffecientLEARegs - LEA that uses base and index registers
/// where the base is EBP, RBP, or R13
static inline bool hasInefficientLEABaseReg(const MachineOperand &Base,
const MachineOperand &Index) {
return Base.isReg() && isInefficientLEAReg(Base.getReg()) &&
isRegOperand(Index);
}
static inline bool hasLEAOffset(const MachineOperand &Offset) {
return (Offset.isImm() && Offset.getImm() != 0) || Offset.isGlobal();
}
// LEA instruction that has all three operands: offset, base and index
static inline bool isThreeOperandsLEA(const MachineOperand &Base,
const MachineOperand &Index,
const MachineOperand &Offset) {
return isRegOperand(Base) && isRegOperand(Index) && hasLEAOffset(Offset);
}
static inline int getADDrrFromLEA(int LEAOpcode) {
switch (LEAOpcode) {
default:
llvm_unreachable("Unexpected LEA instruction");
case X86::LEA16r:
return X86::ADD16rr;
case X86::LEA32r:
return X86::ADD32rr;
case X86::LEA64_32r:
case X86::LEA64r:
return X86::ADD64rr;
}
}
static inline int getADDriFromLEA(int LEAOpcode, const MachineOperand &Offset) {
bool IsInt8 = Offset.isImm() && isInt<8>(Offset.getImm());
switch (LEAOpcode) {
default:
llvm_unreachable("Unexpected LEA instruction");
case X86::LEA16r:
return IsInt8 ? X86::ADD16ri8 : X86::ADD16ri;
case X86::LEA32r:
case X86::LEA64_32r:
return IsInt8 ? X86::ADD32ri8 : X86::ADD32ri;
case X86::LEA64r:
return IsInt8 ? X86::ADD64ri8 : X86::ADD64ri32;
}
static inline bool isLEA(const int opcode) {
return opcode == X86::LEA16r || opcode == X86::LEA32r ||
opcode == X86::LEA64r || opcode == X86::LEA64_32r;
}
/// isLEASimpleIncOrDec - Does this LEA have one these forms:
@ -423,8 +337,8 @@ void FixupLEAPass::seekLEAFixup(MachineOperand &p,
void FixupLEAPass::processInstructionForSLM(MachineBasicBlock::iterator &I,
MachineFunction::iterator MFI) {
MachineInstr &MI = *I;
const int Opcode = MI.getOpcode();
if (!isLEA(Opcode))
const int opcode = MI.getOpcode();
if (!isLEA(opcode))
return;
if (MI.getOperand(5).getReg() != 0 || !MI.getOperand(4).isImm() ||
!TII->isSafeToClobberEFLAGS(*MFI, I))
@ -436,144 +350,55 @@ void FixupLEAPass::processInstructionForSLM(MachineBasicBlock::iterator &I,
return;
if (MI.getOperand(2).getImm() > 1)
return;
int addrr_opcode, addri_opcode;
switch (opcode) {
default:
llvm_unreachable("Unexpected LEA instruction");
case X86::LEA16r:
addrr_opcode = X86::ADD16rr;
addri_opcode = X86::ADD16ri;
break;
case X86::LEA32r:
addrr_opcode = X86::ADD32rr;
addri_opcode = X86::ADD32ri;
break;
case X86::LEA64_32r:
case X86::LEA64r:
addrr_opcode = X86::ADD64rr;
addri_opcode = X86::ADD64ri32;
break;
}
DEBUG(dbgs() << "FixLEA: Candidate to replace:"; I->dump(););
DEBUG(dbgs() << "FixLEA: Replaced by: ";);
MachineInstr *NewMI = nullptr;
const MachineOperand &Dst = MI.getOperand(0);
// Make ADD instruction for two registers writing to LEA's destination
if (SrcR1 != 0 && SrcR2 != 0) {
const MCInstrDesc &ADDrr = TII->get(getADDrrFromLEA(Opcode));
const MachineOperand &Src = MI.getOperand(SrcR1 == DstR ? 3 : 1);
NewMI =
BuildMI(*MFI, I, MI.getDebugLoc(), ADDrr, DstR).addReg(DstR).add(Src);
const MachineOperand &Src1 = MI.getOperand(SrcR1 == DstR ? 1 : 3);
const MachineOperand &Src2 = MI.getOperand(SrcR1 == DstR ? 3 : 1);
NewMI = BuildMI(*MF, MI.getDebugLoc(), TII->get(addrr_opcode))
.add(Dst)
.add(Src1)
.add(Src2);
MFI->insert(I, NewMI);
DEBUG(NewMI->dump(););
}
// Make ADD instruction for immediate
if (MI.getOperand(4).getImm() != 0) {
const MCInstrDesc &ADDri =
TII->get(getADDriFromLEA(Opcode, MI.getOperand(4)));
const MachineOperand &SrcR = MI.getOperand(SrcR1 == DstR ? 1 : 3);
NewMI = BuildMI(*MFI, I, MI.getDebugLoc(), ADDri, DstR)
NewMI = BuildMI(*MF, MI.getDebugLoc(), TII->get(addri_opcode))
.add(Dst)
.add(SrcR)
.addImm(MI.getOperand(4).getImm());
MFI->insert(I, NewMI);
DEBUG(NewMI->dump(););
}
if (NewMI) {
MFI->erase(I);
I = NewMI;
I = static_cast<MachineBasicBlock::iterator>(NewMI);
}
}
MachineInstr *
FixupLEAPass::processInstrForSlow3OpLEA(MachineInstr &MI,
MachineFunction::iterator MFI) {
const int LEAOpcode = MI.getOpcode();
if (!isLEA(LEAOpcode))
return nullptr;
const MachineOperand &Dst = MI.getOperand(0);
const MachineOperand &Base = MI.getOperand(1);
const MachineOperand &Scale = MI.getOperand(2);
const MachineOperand &Index = MI.getOperand(3);
const MachineOperand &Offset = MI.getOperand(4);
const MachineOperand &Segment = MI.getOperand(5);
if (!(isThreeOperandsLEA(Base, Index, Offset) ||
hasInefficientLEABaseReg(Base, Index)) ||
!TII->isSafeToClobberEFLAGS(*MFI, MI) ||
Segment.getReg() != X86::NoRegister)
return nullptr;
unsigned int DstR = Dst.getReg();
unsigned int BaseR = Base.getReg();
unsigned int IndexR = Index.getReg();
unsigned SSDstR =
(LEAOpcode == X86::LEA64_32r) ? getX86SubSuperRegister(DstR, 64) : DstR;
bool IsScale1 = Scale.getImm() == 1;
bool IsInefficientBase = isInefficientLEAReg(BaseR);
bool IsInefficientIndex = isInefficientLEAReg(IndexR);
// Skip these cases since it takes more than 2 instructions
// to replace the LEA instruction.
if (IsInefficientBase && SSDstR == BaseR && !IsScale1)
return nullptr;
if (LEAOpcode == X86::LEA64_32r && IsInefficientBase &&
(IsInefficientIndex || !IsScale1))
return nullptr;
const DebugLoc DL = MI.getDebugLoc();
const MCInstrDesc &ADDrr = TII->get(getADDrrFromLEA(LEAOpcode));
const MCInstrDesc &ADDri = TII->get(getADDriFromLEA(LEAOpcode, Offset));
DEBUG(dbgs() << "FixLEA: Candidate to replace:"; MI.dump(););
DEBUG(dbgs() << "FixLEA: Replaced by: ";);
// First try to replace LEA with one or two (for the 3-op LEA case)
// add instructions:
// 1.lea (%base,%index,1), %base => add %index,%base
// 2.lea (%base,%index,1), %index => add %base,%index
if (IsScale1 && (DstR == BaseR || DstR == IndexR)) {
const MachineOperand &Src = DstR == BaseR ? Index : Base;
MachineInstr *NewMI =
BuildMI(*MFI, MI, DL, ADDrr, DstR).addReg(DstR).add(Src);
DEBUG(NewMI->dump(););
// Create ADD instruction for the Offset in case of 3-Ops LEA.
if (hasLEAOffset(Offset)) {
NewMI = BuildMI(*MFI, MI, DL, ADDri, DstR).addReg(DstR).add(Offset);
DEBUG(NewMI->dump(););
}
return NewMI;
}
// If the base is inefficient try switching the index and base operands,
// otherwise just break the 3-Ops LEA inst into 2-Ops LEA + ADD instruction:
// lea offset(%base,%index,scale),%dst =>
// lea (%base,%index,scale); add offset,%dst
if (!IsInefficientBase || (!IsInefficientIndex && IsScale1)) {
MachineInstr *NewMI = BuildMI(*MFI, MI, DL, TII->get(LEAOpcode))
.add(Dst)
.add(IsInefficientBase ? Index : Base)
.add(Scale)
.add(IsInefficientBase ? Base : Index)
.addImm(0)
.add(Segment);
DEBUG(NewMI->dump(););
// Create ADD instruction for the Offset in case of 3-Ops LEA.
if (hasLEAOffset(Offset)) {
NewMI = BuildMI(*MFI, MI, DL, ADDri, DstR).addReg(DstR).add(Offset);
DEBUG(NewMI->dump(););
}
return NewMI;
}
// Handle the rest of the cases with inefficient base register:
assert(SSDstR != BaseR && "SSDstR == BaseR should be handled already!");
assert(IsInefficientBase && "efficient base should be handled already!");
// lea (%base,%index,1), %dst => mov %base,%dst; add %index,%dst
if (IsScale1 && !hasLEAOffset(Offset)) {
TII->copyPhysReg(*MFI, MI, DL, DstR, BaseR, Base.isKill());
DEBUG(MI.getPrevNode()->dump(););
MachineInstr *NewMI =
BuildMI(*MFI, MI, DL, ADDrr, DstR).addReg(DstR).add(Index);
DEBUG(NewMI->dump(););
return NewMI;
}
// lea offset(%base,%index,scale), %dst =>
// lea offset( ,%index,scale), %dst; add %base,%dst
MachineInstr *NewMI = BuildMI(*MFI, MI, DL, TII->get(LEAOpcode))
.add(Dst)
.addReg(0)
.add(Scale)
.add(Index)
.add(Offset)
.add(Segment);
DEBUG(NewMI->dump(););
NewMI = BuildMI(*MFI, MI, DL, ADDrr, DstR).addReg(DstR).add(Base);
DEBUG(NewMI->dump(););
return NewMI;
}
bool FixupLEAPass::processBasicBlock(MachineFunction &MF,
MachineFunction::iterator MFI) {
@ -585,16 +410,8 @@ bool FixupLEAPass::processBasicBlock(MachineFunction &MF,
if (OptLEA) {
if (MF.getSubtarget<X86Subtarget>().isSLM())
processInstructionForSLM(I, MFI);
else {
if (MF.getSubtarget<X86Subtarget>().slow3OpsLEA()) {
if (auto *NewMI = processInstrForSlow3OpLEA(*I, MFI)) {
MFI->erase(I);
I = NewMI;
}
} else
processInstruction(I, MFI);
}
else
processInstruction(I, MFI);
}
}
return false;

View File

@ -19,6 +19,7 @@
#include "X86Subtarget.h"
#include "X86TargetMachine.h"
#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
#include "llvm/CodeGen/GlobalISel/Utils.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
@ -72,6 +73,9 @@ class X86InstructionSelector : public InstructionSelector {
bool selectCmp(MachineInstr &I, MachineRegisterInfo &MRI,
MachineFunction &MF) const;
bool selectUadde(MachineInstr &I, MachineRegisterInfo &MRI,
MachineFunction &MF) const;
const X86TargetMachine &TM;
const X86Subtarget &STI;
const X86InstrInfo &TII;
@ -243,6 +247,8 @@ bool X86InstructionSelector::select(MachineInstr &I) const {
return true;
if (selectCmp(I, MRI, MF))
return true;
if (selectUadde(I, MRI, MF))
return true;
return false;
}
@ -564,6 +570,66 @@ bool X86InstructionSelector::selectCmp(MachineInstr &I,
return true;
}
bool X86InstructionSelector::selectUadde(MachineInstr &I,
MachineRegisterInfo &MRI,
MachineFunction &MF) const {
if (I.getOpcode() != TargetOpcode::G_UADDE)
return false;
const unsigned DstReg = I.getOperand(0).getReg();
const unsigned CarryOutReg = I.getOperand(1).getReg();
const unsigned Op0Reg = I.getOperand(2).getReg();
const unsigned Op1Reg = I.getOperand(3).getReg();
unsigned CarryInReg = I.getOperand(4).getReg();
const LLT DstTy = MRI.getType(DstReg);
if (DstTy != LLT::scalar(32))
return false;
// find CarryIn def instruction.
MachineInstr *Def = MRI.getVRegDef(CarryInReg);
while (Def->getOpcode() == TargetOpcode::G_TRUNC) {
CarryInReg = Def->getOperand(1).getReg();
Def = MRI.getVRegDef(CarryInReg);
}
unsigned Opcode;
if (Def->getOpcode() == TargetOpcode::G_UADDE) {
// carry set by prev ADD.
BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY), X86::EFLAGS)
.addReg(CarryInReg);
if (!RBI.constrainGenericRegister(CarryInReg, X86::GR32RegClass, MRI))
return false;
Opcode = X86::ADC32rr;
} else if (auto val = getConstantVRegVal(CarryInReg, MRI)) {
// carry is constant, support only 0.
if (*val != 0)
return false;
Opcode = X86::ADD32rr;
} else
return false;
MachineInstr &AddInst =
*BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcode), DstReg)
.addReg(Op0Reg)
.addReg(Op1Reg);
BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY), CarryOutReg)
.addReg(X86::EFLAGS);
if (!constrainSelectedInstRegOperands(AddInst, TII, TRI, RBI) ||
!RBI.constrainGenericRegister(CarryOutReg, X86::GR32RegClass, MRI))
return false;
I.eraseFromParent();
return true;
}
InstructionSelector *
llvm::createX86InstructionSelector(const X86TargetMachine &TM,
X86Subtarget &Subtarget,

View File

@ -59,6 +59,11 @@ void X86LegalizerInfo::setLegalizerInfo32bit() {
for (auto Ty : {s8, s16, s32})
setAction({BinOp, Ty}, Legal);
for (unsigned Op : {G_UADDE}) {
setAction({Op, s32}, Legal);
setAction({Op, 1, s1}, Legal);
}
for (unsigned MemOp : {G_LOAD, G_STORE}) {
for (auto Ty : {s8, s16, s32, p0})
setAction({MemOp, Ty}, Legal);

View File

@ -253,11 +253,6 @@ class X86Subtarget final : public X86GenSubtargetInfo {
/// True if the LEA instruction with certain arguments is slow
bool SlowLEA;
/// True if the LEA instruction has all three source operands: base, index,
/// and offset or if the LEA instruction uses base and index registers where
/// the base is EBP, RBP,or R13
bool Slow3OpsLEA;
/// True if INC and DEC instructions are slow when writing to flags
bool SlowIncDec;
@ -495,7 +490,6 @@ class X86Subtarget final : public X86GenSubtargetInfo {
bool callRegIndirect() const { return CallRegIndirect; }
bool LEAusesAG() const { return LEAUsesAG; }
bool slowLEA() const { return SlowLEA; }
bool slow3OpsLEA() const { return Slow3OpsLEA; }
bool slowIncDec() const { return SlowIncDec; }
bool hasCDI() const { return HasCDI; }
bool hasPFI() const { return HasPFI; }

View File

@ -61,7 +61,6 @@ static cl::opt<bool> EnableMachineCombinerPass("x86-machine-combiner",
namespace llvm {
void initializeWinEHStatePassPass(PassRegistry &);
void initializeFixupLEAPassPass(PassRegistry &);
void initializeX86ExecutionDepsFixPass(PassRegistry &);
} // end namespace llvm
@ -76,7 +75,6 @@ extern "C" void LLVMInitializeX86Target() {
initializeWinEHStatePassPass(PR);
initializeFixupBWInstPassPass(PR);
initializeEvexToVexInstPassPass(PR);
initializeFixupLEAPassPass(PR);
initializeX86ExecutionDepsFixPass(PR);
}

View File

@ -1392,6 +1392,16 @@ int X86TTIImpl::getIntrinsicInstrCost(Intrinsic::ID IID, Type *RetTy,
// CTLZ: llvm\test\CodeGen\X86\vector-lzcnt-*.ll
// CTPOP: llvm\test\CodeGen\X86\vector-popcnt-*.ll
// CTTZ: llvm\test\CodeGen\X86\vector-tzcnt-*.ll
static const CostTblEntry AVX512BWCostTbl[] = {
{ ISD::BITREVERSE, MVT::v8i64, 5 },
{ ISD::BITREVERSE, MVT::v16i32, 5 },
{ ISD::BITREVERSE, MVT::v32i16, 5 },
{ ISD::BITREVERSE, MVT::v64i8, 5 },
};
static const CostTblEntry AVX512CostTbl[] = {
{ ISD::BITREVERSE, MVT::v8i64, 36 },
{ ISD::BITREVERSE, MVT::v16i32, 24 },
};
static const CostTblEntry XOPCostTbl[] = {
{ ISD::BITREVERSE, MVT::v4i64, 4 },
{ ISD::BITREVERSE, MVT::v8i32, 4 },
@ -1550,6 +1560,14 @@ int X86TTIImpl::getIntrinsicInstrCost(Intrinsic::ID IID, Type *RetTy,
MVT MTy = LT.second;
// Attempt to lookup cost.
if (ST->hasBWI())
if (const auto *Entry = CostTableLookup(AVX512BWCostTbl, ISD, MTy))
return LT.first * Entry->Cost;
if (ST->hasAVX512())
if (const auto *Entry = CostTableLookup(AVX512CostTbl, ISD, MTy))
return LT.first * Entry->Cost;
if (ST->hasXOP())
if (const auto *Entry = CostTableLookup(XOPCostTbl, ISD, MTy))
return LT.first * Entry->Cost;

View File

@ -347,6 +347,27 @@ static StructType *buildFrameType(Function &F, coro::Shape &Shape,
return FrameTy;
}
// We need to make room to insert a spill after initial PHIs, but before
// catchswitch instruction. Placing it before violates the requirement that
// catchswitch, like all other EHPads must be the first nonPHI in a block.
//
// Split away catchswitch into a separate block and insert in its place:
//
// cleanuppad <InsertPt> cleanupret.
//
// cleanupret instruction will act as an insert point for the spill.
static Instruction *splitBeforeCatchSwitch(CatchSwitchInst *CatchSwitch) {
BasicBlock *CurrentBlock = CatchSwitch->getParent();
BasicBlock *NewBlock = CurrentBlock->splitBasicBlock(CatchSwitch);
CurrentBlock->getTerminator()->eraseFromParent();
auto *CleanupPad =
CleanupPadInst::Create(CatchSwitch->getParentPad(), {}, "", CurrentBlock);
auto *CleanupRet =
CleanupReturnInst::Create(CleanupPad, NewBlock, CurrentBlock);
return CleanupRet;
}
// Replace all alloca and SSA values that are accessed across suspend points
// with GetElementPointer from coroutine frame + loads and stores. Create an
// AllocaSpillBB that will become the new entry block for the resume parts of
@ -437,8 +458,11 @@ static Instruction *insertSpills(SpillInfo &Spills, coro::Shape &Shape) {
InsertPt = NewBB->getTerminator();
} else if (dyn_cast<PHINode>(CurrentValue)) {
// Skip the PHINodes and EH pads instructions.
InsertPt =
&*cast<Instruction>(E.def())->getParent()->getFirstInsertionPt();
BasicBlock *DefBlock = cast<Instruction>(E.def())->getParent();
if (auto *CSI = dyn_cast<CatchSwitchInst>(DefBlock->getTerminator()))
InsertPt = splitBeforeCatchSwitch(CSI);
else
InsertPt = &*DefBlock->getFirstInsertionPt();
} else {
// For all other values, the spill is placed immediately after
// the definition.

View File

@ -74,6 +74,27 @@ static inline unsigned getComplexity(Value *V) {
return isa<Constant>(V) ? (isa<UndefValue>(V) ? 0 : 1) : 2;
}
/// Predicate canonicalization reduces the number of patterns that need to be
/// matched by other transforms. For example, we may swap the operands of a
/// conditional branch or select to create a compare with a canonical (inverted)
/// predicate which is then more likely to be matched with other values.
static inline bool isCanonicalPredicate(CmpInst::Predicate Pred) {
switch (Pred) {
case CmpInst::ICMP_NE:
case CmpInst::ICMP_ULE:
case CmpInst::ICMP_SLE:
case CmpInst::ICMP_UGE:
case CmpInst::ICMP_SGE:
// TODO: There are 16 FCMP predicates. Should others be (not) canonical?
case CmpInst::FCMP_ONE:
case CmpInst::FCMP_OLE:
case CmpInst::FCMP_OGE:
return false;
default:
return true;
}
}
/// \brief Add one to a Constant
static inline Constant *AddOne(Constant *C) {
return ConstantExpr::getAdd(C, ConstantInt::get(C->getType(), 1));

View File

@ -2210,37 +2210,17 @@ Instruction *InstCombiner::visitBranchInst(BranchInst &BI) {
return &BI;
}
// Canonicalize fcmp_one -> fcmp_oeq
FCmpInst::Predicate FPred; Value *Y;
if (match(&BI, m_Br(m_OneUse(m_FCmp(FPred, m_Value(X), m_Value(Y))),
TrueDest, FalseDest))) {
// TODO: Why are we only transforming these 3 predicates?
if (FPred == FCmpInst::FCMP_ONE || FPred == FCmpInst::FCMP_OLE ||
FPred == FCmpInst::FCMP_OGE) {
FCmpInst *Cond = cast<FCmpInst>(BI.getCondition());
Cond->setPredicate(FCmpInst::getInversePredicate(FPred));
// Swap Destinations and condition.
BI.swapSuccessors();
Worklist.Add(Cond);
return &BI;
}
}
// Canonicalize icmp_ne -> icmp_eq
ICmpInst::Predicate IPred;
if (match(&BI, m_Br(m_OneUse(m_ICmp(IPred, m_Value(X), m_Value(Y))),
TrueDest, FalseDest))) {
if (IPred == ICmpInst::ICMP_NE || IPred == ICmpInst::ICMP_ULE ||
IPred == ICmpInst::ICMP_SLE || IPred == ICmpInst::ICMP_UGE ||
IPred == ICmpInst::ICMP_SGE) {
ICmpInst *Cond = cast<ICmpInst>(BI.getCondition());
Cond->setPredicate(ICmpInst::getInversePredicate(IPred));
// Swap Destinations and condition.
BI.swapSuccessors();
Worklist.Add(Cond);
return &BI;
}
// Canonicalize, for example, icmp_ne -> icmp_eq or fcmp_one -> fcmp_oeq.
CmpInst::Predicate Pred;
if (match(&BI, m_Br(m_OneUse(m_Cmp(Pred, m_Value(), m_Value())), TrueDest,
FalseDest)) &&
!isCanonicalPredicate(Pred)) {
// Swap destinations and condition.
CmpInst *Cond = cast<CmpInst>(BI.getCondition());
Cond->setPredicate(CmpInst::getInversePredicate(Pred));
BI.swapSuccessors();
Worklist.Add(Cond);
return &BI;
}
return nullptr;
@ -3053,7 +3033,10 @@ static bool AddReachableCodeToWorklist(BasicBlock *BB, const DataLayout &DL,
}
}
InstrsForInstCombineWorklist.push_back(Inst);
// Skip processing debug intrinsics in InstCombine. Processing these call instructions
// consumes non-trivial amount of time and provides no value for the optimization.
if (!isa<DbgInfoIntrinsic>(Inst))
InstrsForInstCombineWorklist.push_back(Inst);
}
// Recursively visit successors. If this is a branch or switch on a

View File

@ -546,7 +546,7 @@ static bool isLoadInvariantInLoop(LoadInst *LI, DominatorTree *DT,
// If there are escaping uses of invariant.start instruction, the load maybe
// non-invariant.
if (!II || II->getIntrinsicID() != Intrinsic::invariant_start ||
II->hasNUsesOrMore(1))
!II->use_empty())
continue;
unsigned InvariantSizeInBits =
cast<ConstantInt>(II->getArgOperand(0))->getSExtValue() * 8;

View File

@ -1292,13 +1292,15 @@ bool LoopIdiomRecognize::recognizeAndInsertCTLZ() {
BasicBlock *PH = CurLoop->getLoopPreheader();
Value *InitX = PhiX->getIncomingValueForBlock(PH);
// If we check X != 0 before entering the loop we don't need a zero
// check in CTLZ intrinsic.
if (BasicBlock *PreCondBB = PH->getSinglePredecessor())
if (BranchInst *PreCondBr =
dyn_cast<BranchInst>(PreCondBB->getTerminator())) {
if (matchCondition(PreCondBr, PH) == InitX)
ZeroCheck = true;
}
// check in CTLZ intrinsic, but only if Cnt Phi is not used outside of the
// loop (if it is used we count CTLZ(X >> 1)).
if (!IsCntPhiUsedOutsideLoop)
if (BasicBlock *PreCondBB = PH->getSinglePredecessor())
if (BranchInst *PreCondBr =
dyn_cast<BranchInst>(PreCondBB->getTerminator())) {
if (matchCondition(PreCondBr, PH) == InitX)
ZeroCheck = true;
}
// Check if CTLZ intrinsic is profitable. Assume it is always profitable
// if we delete the loop (the loop has only 6 instructions):

View File

@ -3902,8 +3902,7 @@ void LSRInstance::GenerateCrossUseConstantOffsets() {
// Compute the difference between the two.
int64_t Imm = (uint64_t)JImm - M->first;
for (int LUIdx = UsedByIndices.find_first(); LUIdx != -1;
LUIdx = UsedByIndices.find_next(LUIdx))
for (unsigned LUIdx : UsedByIndices.set_bits())
// Make a memo of this use, offset, and register tuple.
if (UniqueItems.insert(std::make_pair(LUIdx, Imm)).second)
WorkItems.push_back(WorkItem(LUIdx, Imm, OrigReg));

Some files were not shown because too many files have changed in this diff Show More