Merge llvm trunk r238337 from ^/vendor/llvm/dist, resolve conflicts, and

preserve our customizations, where necessary.
This commit is contained in:
Dimitry Andric 2015-05-27 20:26:41 +00:00
commit ff0cc061ec
1987 changed files with 174516 additions and 94666 deletions

View File

@ -4,7 +4,7 @@ LLVM Release License
University of Illinois/NCSA
Open Source License
Copyright (c) 2003-2014 University of Illinois at Urbana-Champaign.
Copyright (c) 2003-2015 University of Illinois at Urbana-Champaign.
All rights reserved.
Developed by:

View File

@ -169,6 +169,7 @@ typedef enum {
LLVMNonNullAttribute = 1ULL << 37,
LLVMJumpTableAttribute = 1ULL << 38,
LLVMDereferenceableAttribute = 1ULL << 39,
LLVMDereferenceableOrNullAttribute = 1ULL << 40,
*/
} LLVMAttribute;

View File

@ -20,21 +20,23 @@
extern "C" {
#endif
/* Note: LLVMLinkerPreserveSource has no effect. */
/* This enum is provided for backwards-compatibility only. It has no effect. */
typedef enum {
LLVMLinkerDestroySource = 0, /* Allow source module to be destroyed. */
LLVMLinkerPreserveSource = 1 /* Preserve the source module. */
LLVMLinkerDestroySource = 0, /* This is the default behavior. */
LLVMLinkerPreserveSource_Removed = 1 /* This option has been deprecated and
should not be used. */
} LLVMLinkerMode;
/* Links the source module into the destination module, taking ownership
* of the source module away from the caller. Optionally returns a
* human-readable description of any errors that occurred in linking.
* OutMessage must be disposed with LLVMDisposeMessage. The return value
* is true if an error occurred, false otherwise. */
* is true if an error occurred, false otherwise.
*
* Note that the linker mode parameter \p Unused is no longer used, and has
* no effect. */
LLVMBool LLVMLinkModules(LLVMModuleRef Dest, LLVMModuleRef Src,
LLVMLinkerMode Mode, char **OutMessage);
LLVMLinkerMode Unused, char **OutMessage);
#ifdef __cplusplus
}

View File

@ -35,6 +35,9 @@ extern "C" {
/** See llvm::createAggressiveDCEPass function. */
void LLVMAddAggressiveDCEPass(LLVMPassManagerRef PM);
/** See llvm::createBitTrackingDCEPass function. */
void LLVMAddBitTrackingDCEPass(LLVMPassManagerRef PM);
/** See llvm::createAlignmentFromAssumptionsPass function. */
void LLVMAddAlignmentFromAssumptionsPass(LLVMPassManagerRef PM);

View File

@ -40,7 +40,7 @@ typedef bool lto_bool_t;
* @{
*/
#define LTO_API_VERSION 11
#define LTO_API_VERSION 15
/**
* \since prior to LTO_API_VERSION=3
@ -171,7 +171,7 @@ lto_module_create_from_memory(const void* mem, size_t length);
* Loads an object file from memory with an extra path argument.
* Returns NULL on error (check lto_get_error_message() for details).
*
* \since prior to LTO_API_VERSION=9
* \since LTO_API_VERSION=9
*/
extern lto_module_t
lto_module_create_from_memory_with_path(const void* mem, size_t length,
@ -395,6 +395,17 @@ lto_codegen_dispose(lto_code_gen_t);
extern lto_bool_t
lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod);
/**
* Sets the object module for code generation. This will transfer the ownship of
* the module to code generator.
*
* \c cg and \c mod must both be in the same context.
*
* \since LTO_API_VERSION=13
*/
extern void
lto_codegen_set_module(lto_code_gen_t cg, lto_module_t mod);
/**
* Sets if debug info should be generated.
* Returns true on error (check lto_get_error_message() for details).
@ -464,6 +475,8 @@ lto_codegen_write_merged_modules(lto_code_gen_t cg, const char* path);
/**
* Generates code for all added modules into one native object file.
* This calls lto_codegen_optimize then lto_codegen_compile_optimized.
*
* On success returns a pointer to a generated mach-o/ELF buffer and
* length set to the buffer size. The buffer is owned by the
* lto_code_gen_t and will be freed when lto_codegen_dispose()
@ -477,6 +490,9 @@ lto_codegen_compile(lto_code_gen_t cg, size_t* length);
/**
* Generates code for all added modules into one native object file.
* This calls lto_codegen_optimize then lto_codegen_compile_optimized (instead
* of returning a generated mach-o/ELF buffer, it writes to a file).
*
* The name of the file is written to name. Returns true on error.
*
* \since LTO_API_VERSION=5
@ -484,6 +500,36 @@ lto_codegen_compile(lto_code_gen_t cg, size_t* length);
extern lto_bool_t
lto_codegen_compile_to_file(lto_code_gen_t cg, const char** name);
/**
* Runs optimization for the merged module. Returns true on error.
*
* \since LTO_API_VERSION=12
*/
extern lto_bool_t
lto_codegen_optimize(lto_code_gen_t cg);
/**
* Generates code for the optimized merged module into one native object file.
* It will not run any IR optimizations on the merged module.
*
* On success returns a pointer to a generated mach-o/ELF buffer and length set
* to the buffer size. The buffer is owned by the lto_code_gen_t and will be
* freed when lto_codegen_dispose() is called, or
* lto_codegen_compile_optimized() is called again. On failure, returns NULL
* (check lto_get_error_message() for details).
*
* \since LTO_API_VERSION=12
*/
extern const void*
lto_codegen_compile_optimized(lto_code_gen_t cg, size_t* length);
/**
* Returns the runtime API version.
*
* \since LTO_API_VERSION=12
*/
extern unsigned int
lto_api_version(void);
/**
* Sets options to help debug codegen bugs.
@ -502,6 +548,28 @@ lto_codegen_debug_options(lto_code_gen_t cg, const char *);
extern void
lto_initialize_disassembler(void);
/**
* Sets if we should run internalize pass during optimization and code
* generation.
*
* \since LTO_API_VERSION=14
*/
extern void
lto_codegen_set_should_internalize(lto_code_gen_t cg,
lto_bool_t ShouldInternalize);
/**
* \brief Set whether to embed uselists in bitcode.
*
* Sets whether \a lto_codegen_write_merged_modules() should embed uselists in
* output bitcode. This should be turned on for all -save-temps output.
*
* \since LTO_API_VERSION=15
*/
extern void
lto_codegen_set_should_embed_uselists(lto_code_gen_t cg,
lto_bool_t ShouldEmbedUselists);
#ifdef __cplusplus
}
#endif

View File

@ -282,12 +282,6 @@ class APFloat {
/// into FoldingSets.
void Profile(FoldingSetNodeID &NID) const;
/// \brief Used by the Bitcode serializer to emit APInts to Bitcode.
void Emit(Serializer &S) const;
/// \brief Used by the Bitcode deserializer to deserialize APInts.
static APFloat ReadVal(Deserializer &D);
/// \name Arithmetic
/// @{
@ -349,7 +343,7 @@ class APFloat {
/// copied from some other APFloat.
static APFloat copySign(APFloat Value, const APFloat &Sign) {
Value.copySign(Sign);
return std::move(Value);
return Value;
}
/// @}
@ -376,7 +370,7 @@ class APFloat {
/// The definition of equality is not straightforward for floating point, so
/// we won't use operator==. Use one of the following, or write whatever it
/// is you really mean.
bool operator==(const APFloat &) const LLVM_DELETED_FUNCTION;
bool operator==(const APFloat &) const = delete;
/// IEEE comparison with another floating point number (NaNs compare
/// unordered, 0==-0).

View File

@ -25,9 +25,7 @@
#include <string>
namespace llvm {
class Deserializer;
class FoldingSetNodeID;
class Serializer;
class StringRef;
class hash_code;
class raw_ostream;
@ -409,6 +407,13 @@ class APInt {
: getZExtValue();
}
/// \brief Check if the APInt consists of a repeated bit pattern.
///
/// e.g. 0x01010101 satisfies isSplat(8).
/// \param SplatSizeInBits The size of the pattern in bits. Must divide bit
/// width without remainder.
bool isSplat(unsigned SplatSizeInBits) const;
/// @}
/// \name Value Generators
/// @{
@ -1356,7 +1361,7 @@ class APInt {
/// \brief Count the number of leading one bits.
///
/// This function is an APInt version of the countLeadingOnes_{32,64}
/// This function is an APInt version of the countLeadingOnes
/// functions in MathExtras.h. It counts the number of ones from the most
/// significant bit to the first zero bit.
///
@ -1372,7 +1377,7 @@ class APInt {
/// \brief Count the number of trailing zero bits.
///
/// This function is an APInt version of the countTrailingZeros_{32,64}
/// This function is an APInt version of the countTrailingZeros
/// functions in MathExtras.h. It counts the number of zeros from the least
/// significant bit to the first set bit.
///
@ -1382,7 +1387,7 @@ class APInt {
/// \brief Count the number of trailing one bits.
///
/// This function is an APInt version of the countTrailingOnes_{32,64}
/// This function is an APInt version of the countTrailingOnes
/// functions in MathExtras.h. It counts the number of ones from the least
/// significant bit to the first zero bit.
///
@ -1390,19 +1395,19 @@ class APInt {
/// of ones from the least significant bit to the first zero bit.
unsigned countTrailingOnes() const {
if (isSingleWord())
return CountTrailingOnes_64(VAL);
return llvm::countTrailingOnes(VAL);
return countTrailingOnesSlowCase();
}
/// \brief Count the number of bits set.
///
/// This function is an APInt version of the countPopulation_{32,64} functions
/// This function is an APInt version of the countPopulation functions
/// in MathExtras.h. It counts the number of 1 bits in the APInt value.
///
/// \returns 0 if the value is zero, otherwise returns the number of set bits.
unsigned countPopulation() const {
if (isSingleWord())
return CountPopulation_64(VAL);
return llvm::countPopulation(VAL);
return countPopulationSlowCase();
}

View File

@ -62,6 +62,12 @@ class APSInt : public APInt {
}
using APInt::toString;
/// \brief Get the correctly-extended \c int64_t value.
int64_t getExtValue() const {
assert(getMinSignedBits() <= 64 && "Too many bits for int64_t");
return isSigned() ? getSExtValue() : getZExtValue();
}
APSInt LLVM_ATTRIBUTE_UNUSED_RESULT trunc(uint32_t width) const {
return APSInt(APInt::trunc(width), IsUnsigned);
}
@ -133,14 +139,27 @@ class APSInt : public APInt {
assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
return eq(RHS);
}
inline bool operator==(int64_t RHS) const {
return isSameValue(*this, APSInt(APInt(64, RHS), true));
}
inline bool operator!=(const APSInt& RHS) const {
return !((*this) == RHS);
}
inline bool operator!=(int64_t RHS) const {
return !((*this) == RHS);
bool operator==(int64_t RHS) const {
return compareValues(*this, get(RHS)) == 0;
}
bool operator!=(int64_t RHS) const {
return compareValues(*this, get(RHS)) != 0;
}
bool operator<=(int64_t RHS) const {
return compareValues(*this, get(RHS)) <= 0;
}
bool operator>=(int64_t RHS) const {
return compareValues(*this, get(RHS)) >= 0;
}
bool operator<(int64_t RHS) const {
return compareValues(*this, get(RHS)) < 0;
}
bool operator>(int64_t RHS) const {
return compareValues(*this, get(RHS)) > 0;
}
// The remaining operators just wrap the logic of APInt, but retain the
@ -260,37 +279,49 @@ class APSInt : public APInt {
/// \brief Determine if two APSInts have the same value, zero- or
/// sign-extending as needed.
static bool isSameValue(const APSInt &I1, const APSInt &I2) {
return !compareValues(I1, I2);
}
/// \brief Compare underlying values of two numbers.
static int compareValues(const APSInt &I1, const APSInt &I2) {
if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned())
return I1 == I2;
return I1 == I2 ? 0 : I1 > I2 ? 1 : -1;
// Check for a bit-width mismatch.
if (I1.getBitWidth() > I2.getBitWidth())
return isSameValue(I1, I2.extend(I1.getBitWidth()));
return compareValues(I1, I2.extend(I1.getBitWidth()));
else if (I2.getBitWidth() > I1.getBitWidth())
return isSameValue(I1.extend(I2.getBitWidth()), I2);
assert(I1.isSigned() != I2.isSigned());
return compareValues(I1.extend(I2.getBitWidth()), I2);
// We have a signedness mismatch. Check for negative values and do an
// unsigned compare if signs match.
if ((I1.isSigned() && I1.isNegative()) ||
(!I1.isSigned() && I2.isNegative()))
return false;
// unsigned compare if both are positive.
if (I1.isSigned()) {
assert(!I2.isSigned() && "Expected signed mismatch");
if (I1.isNegative())
return -1;
} else {
assert(I2.isSigned() && "Expected signed mismatch");
if (I2.isNegative())
return 1;
}
return I1.eq(I2);
return I1.eq(I2) ? 0 : I1.ugt(I2) ? 1 : -1;
}
static APSInt get(int64_t X) { return APSInt(APInt(64, X), false); }
static APSInt getUnsigned(uint64_t X) { return APSInt(APInt(64, X), true); }
/// Profile - Used to insert APSInt objects, or objects that contain APSInt
/// objects, into FoldingSets.
void Profile(FoldingSetNodeID& ID) const;
};
inline bool operator==(int64_t V1, const APSInt& V2) {
return V2 == V1;
}
inline bool operator!=(int64_t V1, const APSInt& V2) {
return V2 != V1;
}
inline bool operator==(int64_t V1, const APSInt &V2) { return V2 == V1; }
inline bool operator!=(int64_t V1, const APSInt &V2) { return V2 != V1; }
inline bool operator<=(int64_t V1, const APSInt &V2) { return V2 >= V1; }
inline bool operator>=(int64_t V1, const APSInt &V2) { return V2 <= V1; }
inline bool operator<(int64_t V1, const APSInt &V2) { return V2 > V1; }
inline bool operator>(int64_t V1, const APSInt &V2) { return V2 < V1; }
inline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) {
I.print(OS, I.isSigned());

View File

@ -11,7 +11,6 @@
#define LLVM_ADT_ARRAYREF_H
#include "llvm/ADT/None.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include <vector>
@ -44,19 +43,6 @@ namespace llvm {
/// The number of elements.
size_type Length;
/// \brief A dummy "optional" type that is only created by implicit
/// conversion from a reference to T.
///
/// This type must *only* be used in a function argument or as a copy of
/// a function argument, as otherwise it will hold a pointer to a temporary
/// past that temporaries' lifetime.
struct TRefOrNothing {
const T *TPtr;
TRefOrNothing() : TPtr(nullptr) {}
TRefOrNothing(const T &TRef) : TPtr(&TRef) {}
};
public:
/// @name Constructors
/// @{
@ -97,12 +83,10 @@ namespace llvm {
/*implicit*/ LLVM_CONSTEXPR ArrayRef(const T (&Arr)[N])
: Data(Arr), Length(N) {}
#if LLVM_HAS_INITIALIZER_LISTS
/// Construct an ArrayRef from a std::initializer_list.
/*implicit*/ ArrayRef(const std::initializer_list<T> &Vec)
: Data(Vec.begin() == Vec.end() ? (T*)0 : Vec.begin()),
Length(Vec.size()) {}
#endif
/// Construct an ArrayRef<const T*> from ArrayRef<T*>. This uses SFINAE to
/// ensure that only ArrayRefs of pointers can be converted.
@ -112,6 +96,25 @@ namespace llvm {
std::is_convertible<U *const *, T const *>::value>::type* = 0)
: Data(A.data()), Length(A.size()) {}
/// Construct an ArrayRef<const T*> from a SmallVector<T*>. This is
/// templated in order to avoid instantiating SmallVectorTemplateCommon<T>
/// whenever we copy-construct an ArrayRef.
template<typename U, typename DummyT>
/*implicit*/ ArrayRef(const SmallVectorTemplateCommon<U*, DummyT> &Vec,
typename std::enable_if<
std::is_convertible<U *const *,
T const *>::value>::type* = 0)
: Data(Vec.data()), Length(Vec.size()) {
}
/// Construct an ArrayRef<const T*> from std::vector<T*>. This uses SFINAE
/// to ensure that only vectors of pointers can be converted.
template<typename U, typename A>
ArrayRef(const std::vector<U *, A> &Vec,
typename std::enable_if<
std::is_convertible<U *const *, T const *>::value>::type* = 0)
: Data(Vec.data()), Length(Vec.size()) {}
/// @}
/// @name Simple Operations
/// @{
@ -153,13 +156,9 @@ namespace llvm {
bool equals(ArrayRef RHS) const {
if (Length != RHS.Length)
return false;
// Don't use std::equal(), since it asserts in MSVC on nullptr iterators.
for (auto L = begin(), LE = end(), R = RHS.begin(); L != LE; ++L, ++R)
// Match std::equal() in using == (instead of !=) to minimize API
// requirements of ArrayRef'ed types.
if (!(*L == *R))
return false;
return true;
if (Length == 0)
return true;
return std::equal(begin(), end(), RHS.begin());
}
/// slice(n) - Chop off the first N elements of the array.
@ -203,47 +202,6 @@ namespace llvm {
return std::vector<T>(Data, Data+Length);
}
/// @}
/// @{
/// @name Convenience methods
/// @brief Predicate for testing that the array equals the exact sequence of
/// arguments.
///
/// Will return false if the size is not equal to the exact number of
/// arguments given or if the array elements don't equal the argument
/// elements in order. Currently supports up to 16 arguments, but can
/// easily be extended.
bool equals(TRefOrNothing Arg0 = TRefOrNothing(),
TRefOrNothing Arg1 = TRefOrNothing(),
TRefOrNothing Arg2 = TRefOrNothing(),
TRefOrNothing Arg3 = TRefOrNothing(),
TRefOrNothing Arg4 = TRefOrNothing(),
TRefOrNothing Arg5 = TRefOrNothing(),
TRefOrNothing Arg6 = TRefOrNothing(),
TRefOrNothing Arg7 = TRefOrNothing(),
TRefOrNothing Arg8 = TRefOrNothing(),
TRefOrNothing Arg9 = TRefOrNothing(),
TRefOrNothing Arg10 = TRefOrNothing(),
TRefOrNothing Arg11 = TRefOrNothing(),
TRefOrNothing Arg12 = TRefOrNothing(),
TRefOrNothing Arg13 = TRefOrNothing(),
TRefOrNothing Arg14 = TRefOrNothing(),
TRefOrNothing Arg15 = TRefOrNothing()) {
TRefOrNothing Args[] = {Arg0, Arg1, Arg2, Arg3, Arg4, Arg5,
Arg6, Arg7, Arg8, Arg9, Arg10, Arg11,
Arg12, Arg13, Arg14, Arg15};
if (size() > array_lengthof(Args))
return false;
for (unsigned i = 0, e = size(); i != e; ++i)
if (Args[i].TPtr == nullptr || (*this)[i] != *Args[i].TPtr)
return false;
// Either the size is exactly as many args, or the next arg must be null.
return size() == array_lengthof(Args) || Args[size()].TPtr == nullptr;
}
/// @}
};

View File

@ -29,6 +29,9 @@ class BitVector {
enum { BITWORD_SIZE = (unsigned)sizeof(BitWord) * CHAR_BIT };
static_assert(BITWORD_SIZE == 64 || BITWORD_SIZE == 32,
"Unsupported word size");
BitWord *Bits; // Actual bits.
unsigned Size; // Size of bitvector in bits.
unsigned Capacity; // Size of allocated memory in BitWord.
@ -50,7 +53,7 @@ class BitVector {
BitPos = Idx % BITWORD_SIZE;
}
~reference() {}
reference(const reference&) = default;
reference &operator=(reference t) {
*this = bool(t);
@ -118,12 +121,7 @@ class BitVector {
size_type count() const {
unsigned NumBits = 0;
for (unsigned i = 0; i < NumBitWords(size()); ++i)
if (sizeof(BitWord) == 4)
NumBits += CountPopulation_32((uint32_t)Bits[i]);
else if (sizeof(BitWord) == 8)
NumBits += CountPopulation_64(Bits[i]);
else
llvm_unreachable("Unsupported!");
NumBits += countPopulation(Bits[i]);
return NumBits;
}
@ -157,13 +155,8 @@ class BitVector {
/// of the bits are set.
int find_first() const {
for (unsigned i = 0; i < NumBitWords(size()); ++i)
if (Bits[i] != 0) {
if (sizeof(BitWord) == 4)
return i * BITWORD_SIZE + countTrailingZeros((uint32_t)Bits[i]);
if (sizeof(BitWord) == 8)
return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
llvm_unreachable("Unsupported!");
}
if (Bits[i] != 0)
return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
return -1;
}
@ -180,23 +173,13 @@ class BitVector {
// Mask off previous bits.
Copy &= ~0UL << BitPos;
if (Copy != 0) {
if (sizeof(BitWord) == 4)
return WordPos * BITWORD_SIZE + countTrailingZeros((uint32_t)Copy);
if (sizeof(BitWord) == 8)
return WordPos * BITWORD_SIZE + countTrailingZeros(Copy);
llvm_unreachable("Unsupported!");
}
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) {
if (sizeof(BitWord) == 4)
return i * BITWORD_SIZE + countTrailingZeros((uint32_t)Bits[i]);
if (sizeof(BitWord) == 8)
return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
llvm_unreachable("Unsupported!");
}
if (Bits[i] != 0)
return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
return -1;
}
@ -559,7 +542,7 @@ class BitVector {
template<bool AddBits, bool InvertMask>
void applyMask(const uint32_t *Mask, unsigned MaskWords) {
assert(BITWORD_SIZE % 32 == 0 && "Unsupported BitWord size.");
static_assert(BITWORD_SIZE % 32 == 0, "Unsupported BitWord size.");
MaskWords = std::min(MaskWords, (size() + 31) / 32);
const unsigned Scale = BITWORD_SIZE / 32;
unsigned i;

View File

@ -77,6 +77,8 @@ class DeltaAlgorithm {
/// ExecuteOneTest - Execute a single test predicate on the change set \p S.
virtual bool ExecuteOneTest(const changeset_ty &S) = 0;
DeltaAlgorithm& operator=(const DeltaAlgorithm&) = default;
public:
virtual ~DeltaAlgorithm();

View File

@ -15,6 +15,7 @@
#define LLVM_ADT_DENSEMAP_H
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/EpochTracker.h"
#include "llvm/Support/AlignOf.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MathExtras.h"
@ -50,7 +51,7 @@ class DenseMapIterator;
template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
typename BucketT>
class DenseMapBase {
class DenseMapBase : public DebugEpochBase {
public:
typedef unsigned size_type;
typedef KeyT key_type;
@ -62,16 +63,17 @@ class DenseMapBase {
const_iterator;
inline iterator begin() {
// When the map is empty, avoid the overhead of AdvancePastEmptyBuckets().
return empty() ? end() : iterator(getBuckets(), getBucketsEnd());
return empty() ? end() : iterator(getBuckets(), getBucketsEnd(), *this);
}
inline iterator end() {
return iterator(getBucketsEnd(), getBucketsEnd(), true);
return iterator(getBucketsEnd(), getBucketsEnd(), *this, true);
}
inline const_iterator begin() const {
return empty() ? end() : const_iterator(getBuckets(), getBucketsEnd());
return empty() ? end()
: const_iterator(getBuckets(), getBucketsEnd(), *this);
}
inline const_iterator end() const {
return const_iterator(getBucketsEnd(), getBucketsEnd(), true);
return const_iterator(getBucketsEnd(), getBucketsEnd(), *this, true);
}
bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const {
@ -81,11 +83,13 @@ class DenseMapBase {
/// Grow the densemap so that it has at least Size buckets. Does not shrink
void resize(size_type Size) {
incrementEpoch();
if (Size > getNumBuckets())
grow(Size);
}
void clear() {
incrementEpoch();
if (getNumEntries() == 0 && getNumTombstones() == 0) return;
// If the capacity of the array is huge, and the # elements used is small,
@ -96,16 +100,18 @@ class DenseMapBase {
}
const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
unsigned NumEntries = getNumEntries();
for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) {
if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey)) {
if (!KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) {
P->getSecond().~ValueT();
decrementNumEntries();
--NumEntries;
}
P->getFirst() = EmptyKey;
}
}
assert(getNumEntries() == 0 && "Node count imbalance!");
assert(NumEntries == 0 && "Node count imbalance!");
setNumEntries(0);
setNumTombstones(0);
}
@ -118,13 +124,13 @@ class DenseMapBase {
iterator find(const KeyT &Val) {
BucketT *TheBucket;
if (LookupBucketFor(Val, TheBucket))
return iterator(TheBucket, getBucketsEnd(), true);
return iterator(TheBucket, getBucketsEnd(), *this, true);
return end();
}
const_iterator find(const KeyT &Val) const {
const BucketT *TheBucket;
if (LookupBucketFor(Val, TheBucket))
return const_iterator(TheBucket, getBucketsEnd(), true);
return const_iterator(TheBucket, getBucketsEnd(), *this, true);
return end();
}
@ -137,14 +143,14 @@ class DenseMapBase {
iterator find_as(const LookupKeyT &Val) {
BucketT *TheBucket;
if (LookupBucketFor(Val, TheBucket))
return iterator(TheBucket, getBucketsEnd(), true);
return iterator(TheBucket, getBucketsEnd(), *this, true);
return end();
}
template<class LookupKeyT>
const_iterator find_as(const LookupKeyT &Val) const {
const BucketT *TheBucket;
if (LookupBucketFor(Val, TheBucket))
return const_iterator(TheBucket, getBucketsEnd(), true);
return const_iterator(TheBucket, getBucketsEnd(), *this, true);
return end();
}
@ -163,12 +169,13 @@ class DenseMapBase {
std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) {
BucketT *TheBucket;
if (LookupBucketFor(KV.first, TheBucket))
return std::make_pair(iterator(TheBucket, getBucketsEnd(), true),
return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
false); // Already in map.
// Otherwise, insert the new element.
TheBucket = InsertIntoBucket(KV.first, KV.second, TheBucket);
return std::make_pair(iterator(TheBucket, getBucketsEnd(), true), true);
return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
true);
}
// Inserts key,value pair into the map if the key isn't already in the map.
@ -177,14 +184,15 @@ class DenseMapBase {
std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) {
BucketT *TheBucket;
if (LookupBucketFor(KV.first, TheBucket))
return std::make_pair(iterator(TheBucket, getBucketsEnd(), true),
return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
false); // Already in map.
// Otherwise, insert the new element.
TheBucket = InsertIntoBucket(std::move(KV.first),
std::move(KV.second),
TheBucket);
return std::make_pair(iterator(TheBucket, getBucketsEnd(), true), true);
return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
true);
}
/// insert - Range insertion of pairs.
@ -251,7 +259,7 @@ class DenseMapBase {
const void *getPointerIntoBucketsArray() const { return getBuckets(); }
protected:
DenseMapBase() {}
DenseMapBase() = default;
void destroyAll() {
if (getNumBuckets() == 0) // Nothing to do.
@ -264,10 +272,6 @@ class DenseMapBase {
P->getSecond().~ValueT();
P->getFirst().~KeyT();
}
#ifndef NDEBUG
memset((void*)getBuckets(), 0x5a, sizeof(BucketT)*getNumBuckets());
#endif
}
void initEmpty() {
@ -304,12 +308,6 @@ class DenseMapBase {
}
B->getFirst().~KeyT();
}
#ifndef NDEBUG
if (OldBucketsBegin != OldBucketsEnd)
memset((void*)OldBucketsBegin, 0x5a,
sizeof(BucketT) * (OldBucketsEnd - OldBucketsBegin));
#endif
}
template <typename OtherBaseT>
@ -335,11 +333,6 @@ class DenseMapBase {
}
}
void swap(DenseMapBase& RHS) {
std::swap(getNumEntries(), RHS.getNumEntries());
std::swap(getNumTombstones(), RHS.getNumTombstones());
}
static unsigned getHashValue(const KeyT &Val) {
return KeyInfoT::getHashValue(Val);
}
@ -431,6 +424,8 @@ class DenseMapBase {
}
BucketT *InsertIntoBucketImpl(const KeyT &Key, BucketT *TheBucket) {
incrementEpoch();
// If the load of the hash table is more than 3/4, or if fewer than 1/8 of
// the buckets are empty (meaning that many are filled with tombstones),
// grow the table.
@ -442,11 +437,12 @@ class DenseMapBase {
// causing infinite loops in lookup.
unsigned NewNumEntries = getNumEntries() + 1;
unsigned NumBuckets = getNumBuckets();
if (NewNumEntries*4 >= NumBuckets*3) {
if (LLVM_UNLIKELY(NewNumEntries * 4 >= NumBuckets * 3)) {
this->grow(NumBuckets * 2);
LookupBucketFor(Key, TheBucket);
NumBuckets = getNumBuckets();
} else if (NumBuckets-(NewNumEntries+getNumTombstones()) <= NumBuckets/8) {
} else if (LLVM_UNLIKELY(NumBuckets-(NewNumEntries+getNumTombstones()) <=
NumBuckets/8)) {
this->grow(NumBuckets);
LookupBucketFor(Key, TheBucket);
}
@ -492,14 +488,14 @@ class DenseMapBase {
while (1) {
const BucketT *ThisBucket = BucketsPtr + BucketNo;
// Found Val's bucket? If so, return it.
if (KeyInfoT::isEqual(Val, ThisBucket->getFirst())) {
if (LLVM_LIKELY(KeyInfoT::isEqual(Val, ThisBucket->getFirst()))) {
FoundBucket = ThisBucket;
return true;
}
// If we found an empty bucket, the key doesn't exist in the set.
// Insert it and return the default value.
if (KeyInfoT::isEqual(ThisBucket->getFirst(), EmptyKey)) {
if (LLVM_LIKELY(KeyInfoT::isEqual(ThisBucket->getFirst(), EmptyKey))) {
// If we've already seen a tombstone while probing, fill it in instead
// of the empty bucket we eventually probed to.
FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket;
@ -580,6 +576,8 @@ class DenseMap : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>,
}
void swap(DenseMap& RHS) {
this->incrementEpoch();
RHS.incrementEpoch();
std::swap(Buckets, RHS.Buckets);
std::swap(NumEntries, RHS.NumEntries);
std::swap(NumTombstones, RHS.NumTombstones);
@ -986,9 +984,10 @@ class SmallDenseMap
template <typename KeyT, typename ValueT, typename KeyInfoT, typename Bucket,
bool IsConst>
class DenseMapIterator {
class DenseMapIterator : DebugEpochBase::HandleBase {
typedef DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true> ConstIterator;
friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true>;
friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, false>;
public:
typedef ptrdiff_t difference_type;
@ -1002,38 +1001,54 @@ class DenseMapIterator {
public:
DenseMapIterator() : Ptr(nullptr), End(nullptr) {}
DenseMapIterator(pointer Pos, pointer E, bool NoAdvance = false)
: Ptr(Pos), End(E) {
DenseMapIterator(pointer Pos, pointer E, const DebugEpochBase &Epoch,
bool NoAdvance = false)
: DebugEpochBase::HandleBase(&Epoch), Ptr(Pos), End(E) {
assert(isHandleInSync() && "invalid construction!");
if (!NoAdvance) AdvancePastEmptyBuckets();
}
// If IsConst is true this is a converting constructor from iterator to
// const_iterator and the default copy constructor is used.
// Otherwise this is a copy constructor for iterator.
// Converting ctor from non-const iterators to const iterators. SFINAE'd out
// for const iterator destinations so it doesn't end up as a user defined copy
// constructor.
template <bool IsConstSrc,
typename = typename std::enable_if<!IsConstSrc && IsConst>::type>
DenseMapIterator(
const DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, false> &I)
: Ptr(I.Ptr), End(I.End) {}
const DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, IsConstSrc> &I)
: DebugEpochBase::HandleBase(I), Ptr(I.Ptr), End(I.End) {}
reference operator*() const {
assert(isHandleInSync() && "invalid iterator access!");
return *Ptr;
}
pointer operator->() const {
assert(isHandleInSync() && "invalid iterator access!");
return Ptr;
}
bool operator==(const ConstIterator &RHS) const {
return Ptr == RHS.operator->();
assert((!Ptr || isHandleInSync()) && "handle not in sync!");
assert((!RHS.Ptr || RHS.isHandleInSync()) && "handle not in sync!");
assert(getEpochAddress() == RHS.getEpochAddress() &&
"comparing incomparable iterators!");
return Ptr == RHS.Ptr;
}
bool operator!=(const ConstIterator &RHS) const {
return Ptr != RHS.operator->();
assert((!Ptr || isHandleInSync()) && "handle not in sync!");
assert((!RHS.Ptr || RHS.isHandleInSync()) && "handle not in sync!");
assert(getEpochAddress() == RHS.getEpochAddress() &&
"comparing incomparable iterators!");
return Ptr != RHS.Ptr;
}
inline DenseMapIterator& operator++() { // Preincrement
assert(isHandleInSync() && "invalid iterator access!");
++Ptr;
AdvancePastEmptyBuckets();
return *this;
}
DenseMapIterator operator++(int) { // Postincrement
assert(isHandleInSync() && "invalid iterator access!");
DenseMapIterator tmp = *this; ++*this; return tmp;
}

View File

@ -113,9 +113,8 @@ class df_iterator : public std::iterator<std::forward_iterator_tag,
while (It != GT::child_end(Node)) {
NodeType *Next = *It++;
// Has our next sibling been visited?
if (Next && !this->Visited.count(Next)) {
if (Next && this->Visited.insert(Next).second) {
// No, do it now.
this->Visited.insert(Next);
VisitStack.push_back(std::make_pair(PointerIntTy(Next, 0),
GT::child_begin(Next)));
return;
@ -129,58 +128,59 @@ class df_iterator : public std::iterator<std::forward_iterator_tag,
public:
typedef typename super::pointer pointer;
typedef df_iterator<GraphT, SetType, ExtStorage, GT> _Self;
// Provide static begin and end methods as our public "constructors"
static inline _Self begin(const GraphT& G) {
return _Self(GT::getEntryNode(G));
static df_iterator begin(const GraphT &G) {
return df_iterator(GT::getEntryNode(G));
}
static inline _Self end(const GraphT& G) { return _Self(); }
static df_iterator end(const GraphT &G) { return df_iterator(); }
// Static begin and end methods as our public ctors for external iterators
static inline _Self begin(const GraphT& G, SetType &S) {
return _Self(GT::getEntryNode(G), S);
static df_iterator begin(const GraphT &G, SetType &S) {
return df_iterator(GT::getEntryNode(G), S);
}
static inline _Self end(const GraphT& G, SetType &S) { return _Self(S); }
static df_iterator end(const GraphT &G, SetType &S) { return df_iterator(S); }
inline bool operator==(const _Self& x) const {
bool operator==(const df_iterator &x) const {
return VisitStack == x.VisitStack;
}
inline bool operator!=(const _Self& x) const { return !operator==(x); }
bool operator!=(const df_iterator &x) const { return !(*this == x); }
inline pointer operator*() const {
return VisitStack.back().first.getPointer();
}
pointer operator*() const { return VisitStack.back().first.getPointer(); }
// This is a nonstandard operator-> that dereferences the pointer an extra
// time... so that you can actually call methods ON the Node, because
// the contained type is a pointer. This allows BBIt->getTerminator() f.e.
//
inline NodeType *operator->() const { return operator*(); }
NodeType *operator->() const { return **this; }
inline _Self& operator++() { // Preincrement
df_iterator &operator++() { // Preincrement
toNext();
return *this;
}
// skips all children of the current node and traverses to next node
//
inline _Self& skipChildren() {
/// \brief Skips all children of the current node and traverses to next node
///
/// Note: This function takes care of incrementing the iterator. If you
/// always increment and call this function, you risk walking off the end.
df_iterator &skipChildren() {
VisitStack.pop_back();
if (!VisitStack.empty())
toNext();
return *this;
}
inline _Self operator++(int) { // Postincrement
_Self tmp = *this; ++*this; return tmp;
df_iterator operator++(int) { // Postincrement
df_iterator tmp = *this;
++*this;
return tmp;
}
// nodeVisited - return true if this iterator has already visited the
// specified node. This is public, and will probably be used to iterate over
// nodes that a depth first iteration did not find: ie unreachable nodes.
//
inline bool nodeVisited(NodeType *Node) const {
bool nodeVisited(NodeType *Node) const {
return this->Visited.count(Node) != 0;
}
@ -211,7 +211,7 @@ df_iterator<T> df_end(const T& G) {
// Provide an accessor method to use them in range-based patterns.
template <class T>
iterator_range<df_iterator<T>> depth_first(const T& G) {
return iterator_range<df_iterator<T>>(df_begin(G), df_end(G));
return make_range(df_begin(G), df_end(G));
}
// Provide global definitions of external depth first iterators...
@ -234,8 +234,7 @@ df_ext_iterator<T, SetTy> df_ext_end(const T& G, SetTy &S) {
template <class T, class SetTy>
iterator_range<df_ext_iterator<T, SetTy>> depth_first_ext(const T& G,
SetTy &S) {
return iterator_range<df_ext_iterator<T, SetTy>>(df_ext_begin(G, S),
df_ext_end(G, S));
return make_range(df_ext_begin(G, S), df_ext_end(G, S));
}
@ -261,7 +260,7 @@ idf_iterator<T> idf_end(const T& G){
// Provide an accessor method to use them in range-based patterns.
template <class T>
iterator_range<idf_iterator<T>> inverse_depth_first(const T& G) {
return iterator_range<idf_iterator<T>>(idf_begin(G), idf_end(G));
return make_range(idf_begin(G), idf_end(G));
}
// Provide global definitions of external inverse depth first iterators...
@ -286,8 +285,7 @@ idf_ext_iterator<T, SetTy> idf_ext_end(const T& G, SetTy &S) {
template <class T, class SetTy>
iterator_range<idf_ext_iterator<T, SetTy>> inverse_depth_first_ext(const T& G,
SetTy &S) {
return iterator_range<idf_ext_iterator<T, SetTy>>(idf_ext_begin(G, S),
idf_ext_end(G, S));
return make_range(idf_ext_begin(G, S), idf_ext_end(G, S));
}
} // End llvm namespace

View File

@ -0,0 +1,99 @@
//===- llvm/ADT/EpochTracker.h - ADT epoch tracking --------------*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the DebugEpochBase and DebugEpochBase::HandleBase classes.
// These can be used to write iterators that are fail-fast when LLVM is built
// with asserts enabled.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ADT_EPOCH_TRACKER_H
#define LLVM_ADT_EPOCH_TRACKER_H
#include "llvm/Config/llvm-config.h"
#include <cstdint>
namespace llvm {
#ifndef LLVM_ENABLE_ABI_BREAKING_CHECKS
class DebugEpochBase {
public:
void incrementEpoch() {}
class HandleBase {
public:
HandleBase() = default;
explicit HandleBase(const DebugEpochBase *) {}
bool isHandleInSync() const { return true; }
const void *getEpochAddress() const { return nullptr; }
};
};
#else
/// \brief A base class for data structure classes wishing to make iterators
/// ("handles") pointing into themselves fail-fast. When building without
/// asserts, this class is empty and does nothing.
///
/// DebugEpochBase does not by itself track handles pointing into itself. The
/// expectation is that routines touching the handles will poll on
/// isHandleInSync at appropriate points to assert that the handle they're using
/// is still valid.
///
class DebugEpochBase {
uint64_t Epoch;
public:
DebugEpochBase() : Epoch(0) {}
/// \brief Calling incrementEpoch invalidates all handles pointing into the
/// calling instance.
void incrementEpoch() { ++Epoch; }
/// \brief The destructor calls incrementEpoch to make use-after-free bugs
/// more likely to crash deterministically.
~DebugEpochBase() { incrementEpoch(); }
/// \brief A base class for iterator classes ("handles") that wish to poll for
/// iterator invalidating modifications in the underlying data structure.
/// When LLVM is built without asserts, this class is empty and does nothing.
///
/// HandleBase does not track the parent data structure by itself. It expects
/// the routines modifying the data structure to call incrementEpoch when they
/// make an iterator-invalidating modification.
///
class HandleBase {
const uint64_t *EpochAddress;
uint64_t EpochAtCreation;
public:
HandleBase() : EpochAddress(nullptr), EpochAtCreation(UINT64_MAX) {}
explicit HandleBase(const DebugEpochBase *Parent)
: EpochAddress(&Parent->Epoch), EpochAtCreation(Parent->Epoch) {}
/// \brief Returns true if the DebugEpochBase this Handle is linked to has
/// not called incrementEpoch on itself since the creation of this
/// HandleBase instance.
bool isHandleInSync() const { return *EpochAddress == EpochAtCreation; }
/// \brief Returns a pointer to the epoch word stored in the data structure
/// this handle points into. Can be used to check if two iterators point
/// into the same data structure.
const void *getEpochAddress() const { return EpochAddress; }
};
};
#endif // LLVM_ENABLE_ABI_BREAKING_CHECKS
} // namespace llvm
#endif

View File

@ -17,6 +17,7 @@
#include "llvm/Support/DataTypes.h"
#include <cassert>
#include <cstddef>
#include <set>
namespace llvm {
@ -254,7 +255,7 @@ class EquivalenceClasses {
assert(Node != nullptr && "Dereferencing end()!");
return Node->getData();
}
reference operator->() const { return operator*(); }
pointer operator->() const { return &operator*(); }
member_iterator &operator++() {
assert(Node != nullptr && "++'d off the end of the list!");

View File

@ -18,13 +18,11 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
class APFloat;
class APInt;
/// This folding set used for two purposes:
/// 1. Given information about a node we want to create, look up the unique
/// instance of the node in the set. If the node already exists, return
@ -109,6 +107,8 @@ class FoldingSetNodeID;
/// back to the bucket to facilitate node removal.
///
class FoldingSetImpl {
virtual void anchor(); // Out of line virtual method.
protected:
/// Buckets - Array of bucket chains.
///
@ -122,10 +122,11 @@ class FoldingSetImpl {
/// is greater than twice the number of buckets.
unsigned NumNodes;
public:
explicit FoldingSetImpl(unsigned Log2InitSize = 6);
virtual ~FoldingSetImpl();
~FoldingSetImpl();
explicit FoldingSetImpl(unsigned Log2InitSize = 6);
public:
//===--------------------------------------------------------------------===//
/// Node - This class is used to maintain the singly linked bucket list in
/// a folding set.
@ -392,7 +393,7 @@ DefaultContextualFoldingSetTrait<T, Ctx>::ComputeHash(T &X,
/// implementation of the folding set to the node class T. T must be a
/// subclass of FoldingSetNode and implement a Profile function.
///
template<class T> class FoldingSet : public FoldingSetImpl {
template <class T> class FoldingSet final : public FoldingSetImpl {
private:
/// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a
/// way to convert nodes into a unique specifier.
@ -462,7 +463,7 @@ template<class T> class FoldingSet : public FoldingSetImpl {
/// function with signature
/// void Profile(llvm::FoldingSetNodeID &, Ctx);
template <class T, class Ctx>
class ContextualFoldingSet : public FoldingSetImpl {
class ContextualFoldingSet final : public FoldingSetImpl {
// Unfortunately, this can't derive from FoldingSet<T> because the
// construction vtable for FoldingSet<T> requires
// FoldingSet<T>::GetNodeProfile to be instantiated, which in turn
@ -531,46 +532,6 @@ class ContextualFoldingSet : public FoldingSetImpl {
}
};
//===----------------------------------------------------------------------===//
/// FoldingSetVectorIterator - This implements an iterator for
/// FoldingSetVector. It is only necessary because FoldingSetIterator provides
/// a value_type of T, while the vector in FoldingSetVector exposes
/// a value_type of T*. Fortunately, FoldingSetIterator doesn't expose very
/// much besides operator* and operator->, so we just wrap the inner vector
/// iterator and perform the extra dereference.
template <class T, class VectorIteratorT>
class FoldingSetVectorIterator {
// Provide a typedef to workaround the lack of correct injected class name
// support in older GCCs.
typedef FoldingSetVectorIterator<T, VectorIteratorT> SelfT;
VectorIteratorT Iterator;
public:
FoldingSetVectorIterator(VectorIteratorT I) : Iterator(I) {}
bool operator==(const SelfT &RHS) const {
return Iterator == RHS.Iterator;
}
bool operator!=(const SelfT &RHS) const {
return Iterator != RHS.Iterator;
}
T &operator*() const { return **Iterator; }
T *operator->() const { return *Iterator; }
inline SelfT &operator++() {
++Iterator;
return *this;
}
SelfT operator++(int) {
SelfT tmp = *this;
++*this;
return tmp;
}
};
//===----------------------------------------------------------------------===//
/// FoldingSetVector - This template class combines a FoldingSet and a vector
/// to provide the interface of FoldingSet but with deterministic iteration
@ -586,12 +547,11 @@ class FoldingSetVector {
: Set(Log2InitSize) {
}
typedef FoldingSetVectorIterator<T, typename VectorT::iterator> iterator;
typedef pointee_iterator<typename VectorT::iterator> iterator;
iterator begin() { return Vector.begin(); }
iterator end() { return Vector.end(); }
typedef FoldingSetVectorIterator<const T, typename VectorT::const_iterator>
const_iterator;
typedef pointee_iterator<typename VectorT::const_iterator> const_iterator;
const_iterator begin() const { return Vector.begin(); }
const_iterator end() const { return Vector.end(); }
@ -735,31 +695,9 @@ template <typename T>
class FoldingSetNodeWrapper : public FoldingSetNode {
T data;
public:
explicit FoldingSetNodeWrapper(const T &x) : data(x) {}
virtual ~FoldingSetNodeWrapper() {}
template<typename A1>
explicit FoldingSetNodeWrapper(const A1 &a1)
: data(a1) {}
template <typename A1, typename A2>
explicit FoldingSetNodeWrapper(const A1 &a1, const A2 &a2)
: data(a1,a2) {}
template <typename A1, typename A2, typename A3>
explicit FoldingSetNodeWrapper(const A1 &a1, const A2 &a2, const A3 &a3)
: data(a1,a2,a3) {}
template <typename A1, typename A2, typename A3, typename A4>
explicit FoldingSetNodeWrapper(const A1 &a1, const A2 &a2, const A3 &a3,
const A4 &a4)
: data(a1,a2,a3,a4) {}
template <typename A1, typename A2, typename A3, typename A4, typename A5>
explicit FoldingSetNodeWrapper(const A1 &a1, const A2 &a2, const A3 &a3,
const A4 &a4, const A5 &a5)
: data(a1,a2,a3,a4,a5) {}
template <typename... Ts>
explicit FoldingSetNodeWrapper(Ts &&... Args)
: data(std::forward<Ts>(Args)...) {}
void Profile(FoldingSetNodeID &ID) { FoldingSetTrait<T>::Profile(data, ID); }

View File

@ -55,12 +55,6 @@
#include <iterator>
#include <utility>
// Allow detecting C++11 feature availability when building with Clang without
// breaking other compilers.
#ifndef __has_feature
# define __has_feature(x) 0
#endif
namespace llvm {
/// \brief An opaque object representing a hash code.
@ -81,7 +75,7 @@ class hash_code {
public:
/// \brief Default construct a hash_code.
/// Note that this leaves the value uninitialized.
hash_code() {}
hash_code() = default;
/// \brief Form a hash code directly from a numerical value.
hash_code(size_t value) : value(value) {}
@ -553,8 +547,6 @@ struct hash_combine_recursive_helper {
return buffer_ptr;
}
#if defined(__has_feature) && __has_feature(__cxx_variadic_templates__)
/// \brief Recursive, variadic combining method.
///
/// This function recurses through each argument, combining that argument
@ -568,53 +560,6 @@ struct hash_combine_recursive_helper {
return combine(length, buffer_ptr, buffer_end, args...);
}
#else
// Manually expanded recursive combining methods. See variadic above for
// documentation.
template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6>
hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
const T1 &arg1, const T2 &arg2, const T3 &arg3,
const T4 &arg4, const T5 &arg5, const T6 &arg6) {
buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1));
return combine(length, buffer_ptr, buffer_end, arg2, arg3, arg4, arg5, arg6);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5>
hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
const T1 &arg1, const T2 &arg2, const T3 &arg3,
const T4 &arg4, const T5 &arg5) {
buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1));
return combine(length, buffer_ptr, buffer_end, arg2, arg3, arg4, arg5);
}
template <typename T1, typename T2, typename T3, typename T4>
hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
const T1 &arg1, const T2 &arg2, const T3 &arg3,
const T4 &arg4) {
buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1));
return combine(length, buffer_ptr, buffer_end, arg2, arg3, arg4);
}
template <typename T1, typename T2, typename T3>
hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
const T1 &arg1, const T2 &arg2, const T3 &arg3) {
buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1));
return combine(length, buffer_ptr, buffer_end, arg2, arg3);
}
template <typename T1, typename T2>
hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
const T1 &arg1, const T2 &arg2) {
buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1));
return combine(length, buffer_ptr, buffer_end, arg2);
}
template <typename T1>
hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
const T1 &arg1) {
buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1));
return combine(length, buffer_ptr, buffer_end);
}
#endif
/// \brief Base case for recursive, variadic combining.
///
/// The base case when combining arguments recursively is reached when all
@ -643,9 +588,6 @@ struct hash_combine_recursive_helper {
} // namespace detail
} // namespace hashing
#if __has_feature(__cxx_variadic_templates__)
/// \brief Combine values into a single hash_code.
///
/// This routine accepts a varying number of arguments of any type. It will
@ -663,52 +605,6 @@ template <typename ...Ts> hash_code hash_combine(const Ts &...args) {
return helper.combine(0, helper.buffer, helper.buffer + 64, args...);
}
#else
// What follows are manually exploded overloads for each argument width. See
// the above variadic definition for documentation and specification.
template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6>
hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3,
const T4 &arg4, const T5 &arg5, const T6 &arg6) {
::llvm::hashing::detail::hash_combine_recursive_helper helper;
return helper.combine(0, helper.buffer, helper.buffer + 64,
arg1, arg2, arg3, arg4, arg5, arg6);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5>
hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3,
const T4 &arg4, const T5 &arg5) {
::llvm::hashing::detail::hash_combine_recursive_helper helper;
return helper.combine(0, helper.buffer, helper.buffer + 64,
arg1, arg2, arg3, arg4, arg5);
}
template <typename T1, typename T2, typename T3, typename T4>
hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3,
const T4 &arg4) {
::llvm::hashing::detail::hash_combine_recursive_helper helper;
return helper.combine(0, helper.buffer, helper.buffer + 64,
arg1, arg2, arg3, arg4);
}
template <typename T1, typename T2, typename T3>
hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3) {
::llvm::hashing::detail::hash_combine_recursive_helper helper;
return helper.combine(0, helper.buffer, helper.buffer + 64, arg1, arg2, arg3);
}
template <typename T1, typename T2>
hash_code hash_combine(const T1 &arg1, const T2 &arg2) {
::llvm::hashing::detail::hash_combine_recursive_helper helper;
return helper.combine(0, helper.buffer, helper.buffer + 64, arg1, arg2);
}
template <typename T1>
hash_code hash_combine(const T1 &arg1) {
::llvm::hashing::detail::hash_combine_recursive_helper helper;
return helper.combine(0, helper.buffer, helper.buffer + 64, arg1);
}
#endif
// Implementation details for implementations of hash_value overloads provided
// here.
namespace hashing {

View File

@ -33,8 +33,8 @@ class ImmutableListImpl : public FoldingSetNode {
friend class ImmutableListFactory<T>;
void operator=(const ImmutableListImpl&) LLVM_DELETED_FUNCTION;
ImmutableListImpl(const ImmutableListImpl&) LLVM_DELETED_FUNCTION;
void operator=(const ImmutableListImpl&) = delete;
ImmutableListImpl(const ImmutableListImpl&) = delete;
public:
const T& getHead() const { return Head; }

View File

@ -122,8 +122,8 @@ class ImmutableMap {
}
private:
Factory(const Factory& RHS) LLVM_DELETED_FUNCTION;
void operator=(const Factory& RHS) LLVM_DELETED_FUNCTION;
Factory(const Factory& RHS) = delete;
void operator=(const Factory& RHS) = delete;
};
bool contains(key_type_ref K) const {
@ -203,33 +203,14 @@ class ImmutableMap {
// Iterators.
//===--------------------------------------------------===//
class iterator {
typename TreeTy::iterator itr;
iterator() {}
iterator(TreeTy* t) : itr(t) {}
class iterator : public ImutAVLValueIterator<ImmutableMap> {
iterator() = default;
explicit iterator(TreeTy *Tree) : iterator::ImutAVLValueIterator(Tree) {}
friend class ImmutableMap;
public:
typedef ptrdiff_t difference_type;
typedef typename ImmutableMap<KeyT,ValT,ValInfo>::value_type value_type;
typedef typename ImmutableMap<KeyT,ValT,ValInfo>::value_type_ref reference;
typedef typename iterator::value_type *pointer;
typedef std::bidirectional_iterator_tag iterator_category;
typename iterator::reference operator*() const { return itr->getValue(); }
typename iterator::pointer operator->() const { return &itr->getValue(); }
key_type_ref getKey() const { return itr->getValue().first; }
data_type_ref getData() const { return itr->getValue().second; }
iterator& operator++() { ++itr; return *this; }
iterator operator++(int) { iterator tmp(*this); ++itr; return tmp; }
iterator& operator--() { --itr; return *this; }
iterator operator--(int) { iterator tmp(*this); --itr; return tmp; }
bool operator==(const iterator& RHS) const { return RHS.itr == itr; }
bool operator!=(const iterator& RHS) const { return RHS.itr != itr; }
key_type_ref getKey() const { return (*this)->first; }
data_type_ref getData() const { return (*this)->second; }
};
iterator begin() const { return iterator(Root); }
@ -376,30 +357,17 @@ class ImmutableMapRef {
//===--------------------------------------------------===//
// Iterators.
//===--------------------------------------------------===//
class iterator {
typename TreeTy::iterator itr;
iterator() {}
iterator(TreeTy* t) : itr(t) {}
class iterator : public ImutAVLValueIterator<ImmutableMapRef> {
iterator() = default;
explicit iterator(TreeTy *Tree) : iterator::ImutAVLValueIterator(Tree) {}
friend class ImmutableMapRef;
public:
value_type_ref operator*() const { return itr->getValue(); }
value_type* operator->() const { return &itr->getValue(); }
key_type_ref getKey() const { return itr->getValue().first; }
data_type_ref getData() const { return itr->getValue().second; }
iterator& operator++() { ++itr; return *this; }
iterator operator++(int) { iterator tmp(*this); ++itr; return tmp; }
iterator& operator--() { --itr; return *this; }
iterator operator--(int) { iterator tmp(*this); --itr; return tmp; }
bool operator==(const iterator& RHS) const { return RHS.itr == itr; }
bool operator!=(const iterator& RHS) const { return RHS.itr != itr; }
key_type_ref getKey() const { return (*this)->first; }
data_type_ref getData() const { return (*this)->second; }
};
iterator begin() const { return iterator(Root); }
iterator end() const { return iterator(); }

View File

@ -142,13 +142,13 @@ class ImutAVLTree {
iterator RItr = RHS.begin(), REnd = RHS.end();
while (LItr != LEnd && RItr != REnd) {
if (*LItr == *RItr) {
if (&*LItr == &*RItr) {
LItr.skipSubTree();
RItr.skipSubTree();
continue;
}
if (!LItr->isElementEqual(*RItr))
if (!LItr->isElementEqual(&*RItr))
return false;
++LItr;
@ -293,8 +293,8 @@ class ImutAVLTree {
height = h;
}
static inline
uint32_t computeDigest(ImutAVLTree* L, ImutAVLTree* R, value_type_ref V) {
static uint32_t computeDigest(ImutAVLTree *L, ImutAVLTree *R,
value_type_ref V) {
uint32_t digest = 0;
if (L)
@ -311,7 +311,7 @@ class ImutAVLTree {
return digest;
}
inline uint32_t computeDigest() {
uint32_t computeDigest() {
// Check the lowest bit to determine if digest has actually been
// pre-computed.
if (hasCachedDigest())
@ -429,9 +429,7 @@ class ImutAVLFactory {
value_type_ref getValue(TreeTy* T) const { return T->value; }
// Make sure the index is not the Tombstone or Entry key of the DenseMap.
static inline unsigned maskCacheIndex(unsigned I) {
return (I & ~0x02);
}
static unsigned maskCacheIndex(unsigned I) { return (I & ~0x02); }
unsigned incrementHeight(TreeTy* L, TreeTy* R) const {
unsigned hl = getHeight(L);
@ -444,7 +442,7 @@ class ImutAVLFactory {
typename TreeTy::iterator& TE) {
typename TreeTy::iterator I = T->begin(), E = T->end();
for ( ; I!=E ; ++I, ++TI) {
if (TI == TE || !I->isElementEqual(*TI))
if (TI == TE || !I->isElementEqual(&*TI))
return false;
}
return true;
@ -647,24 +645,26 @@ class ImutAVLFactory {
//===----------------------------------------------------------------------===//
template <typename ImutInfo>
class ImutAVLTreeGenericIterator {
class ImutAVLTreeGenericIterator
: public std::iterator<std::bidirectional_iterator_tag,
ImutAVLTree<ImutInfo>> {
SmallVector<uintptr_t,20> stack;
public:
enum VisitFlag { VisitedNone=0x0, VisitedLeft=0x1, VisitedRight=0x3,
Flags=0x3 };
typedef ImutAVLTree<ImutInfo> TreeTy;
typedef ImutAVLTreeGenericIterator<ImutInfo> _Self;
inline ImutAVLTreeGenericIterator() {}
inline ImutAVLTreeGenericIterator(const TreeTy* Root) {
ImutAVLTreeGenericIterator() {}
ImutAVLTreeGenericIterator(const TreeTy *Root) {
if (Root) stack.push_back(reinterpret_cast<uintptr_t>(Root));
}
TreeTy* operator*() const {
TreeTy &operator*() const {
assert(!stack.empty());
return reinterpret_cast<TreeTy*>(stack.back() & ~Flags);
return *reinterpret_cast<TreeTy *>(stack.back() & ~Flags);
}
TreeTy *operator->() const { return &*this; }
uintptr_t getVisitState() const {
assert(!stack.empty());
@ -695,13 +695,15 @@ class ImutAVLTreeGenericIterator {
}
}
inline bool operator==(const _Self& x) const {
bool operator==(const ImutAVLTreeGenericIterator &x) const {
return stack == x.stack;
}
inline bool operator!=(const _Self& x) const { return !operator==(x); }
bool operator!=(const ImutAVLTreeGenericIterator &x) const {
return !(*this == x);
}
_Self& operator++() {
ImutAVLTreeGenericIterator &operator++() {
assert(!stack.empty());
TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags);
assert(Current);
@ -727,7 +729,7 @@ class ImutAVLTreeGenericIterator {
return *this;
}
_Self& operator--() {
ImutAVLTreeGenericIterator &operator--() {
assert(!stack.empty());
TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags);
assert(Current);
@ -754,30 +756,34 @@ class ImutAVLTreeGenericIterator {
};
template <typename ImutInfo>
class ImutAVLTreeInOrderIterator {
class ImutAVLTreeInOrderIterator
: public std::iterator<std::bidirectional_iterator_tag,
ImutAVLTree<ImutInfo>> {
typedef ImutAVLTreeGenericIterator<ImutInfo> InternalIteratorTy;
InternalIteratorTy InternalItr;
public:
typedef ImutAVLTree<ImutInfo> TreeTy;
typedef ImutAVLTreeInOrderIterator<ImutInfo> _Self;
ImutAVLTreeInOrderIterator(const TreeTy* Root) : InternalItr(Root) {
if (Root) operator++(); // Advance to first element.
if (Root)
++*this; // Advance to first element.
}
ImutAVLTreeInOrderIterator() : InternalItr() {}
inline bool operator==(const _Self& x) const {
bool operator==(const ImutAVLTreeInOrderIterator &x) const {
return InternalItr == x.InternalItr;
}
inline bool operator!=(const _Self& x) const { return !operator==(x); }
bool operator!=(const ImutAVLTreeInOrderIterator &x) const {
return !(*this == x);
}
inline TreeTy* operator*() const { return *InternalItr; }
inline TreeTy* operator->() const { return *InternalItr; }
TreeTy &operator*() const { return *InternalItr; }
TreeTy *operator->() const { return &*InternalItr; }
inline _Self& operator++() {
ImutAVLTreeInOrderIterator &operator++() {
do ++InternalItr;
while (!InternalItr.atEnd() &&
InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft);
@ -785,7 +791,7 @@ class ImutAVLTreeInOrderIterator {
return *this;
}
inline _Self& operator--() {
ImutAVLTreeInOrderIterator &operator--() {
do --InternalItr;
while (!InternalItr.atBeginning() &&
InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft);
@ -793,7 +799,7 @@ class ImutAVLTreeInOrderIterator {
return *this;
}
inline void skipSubTree() {
void skipSubTree() {
InternalItr.skipToParent();
while (!InternalItr.atEnd() &&
@ -802,6 +808,24 @@ class ImutAVLTreeInOrderIterator {
}
};
/// Generic iterator that wraps a T::TreeTy::iterator and exposes
/// iterator::getValue() on dereference.
template <typename T>
struct ImutAVLValueIterator
: iterator_adaptor_base<
ImutAVLValueIterator<T>, typename T::TreeTy::iterator,
typename std::iterator_traits<
typename T::TreeTy::iterator>::iterator_category,
const typename T::value_type> {
ImutAVLValueIterator() = default;
explicit ImutAVLValueIterator(typename T::TreeTy *Tree)
: ImutAVLValueIterator::iterator_adaptor_base(Tree) {}
typename ImutAVLValueIterator::reference operator*() const {
return this->I->getValue();
}
};
//===----------------------------------------------------------------------===//
// Trait classes for Profile information.
//===----------------------------------------------------------------------===//
@ -814,7 +838,7 @@ struct ImutProfileInfo {
typedef const T value_type;
typedef const T& value_type_ref;
static inline void Profile(FoldingSetNodeID& ID, value_type_ref X) {
static void Profile(FoldingSetNodeID &ID, value_type_ref X) {
FoldingSetTrait<T>::Profile(X,ID);
}
};
@ -825,7 +849,7 @@ struct ImutProfileInteger {
typedef const T value_type;
typedef const T& value_type_ref;
static inline void Profile(FoldingSetNodeID& ID, value_type_ref X) {
static void Profile(FoldingSetNodeID &ID, value_type_ref X) {
ID.AddInteger(X);
}
};
@ -852,7 +876,7 @@ struct ImutProfileInfo<bool> {
typedef const bool value_type;
typedef const bool& value_type_ref;
static inline void Profile(FoldingSetNodeID& ID, value_type_ref X) {
static void Profile(FoldingSetNodeID &ID, value_type_ref X) {
ID.AddBoolean(X);
}
};
@ -865,7 +889,7 @@ struct ImutProfileInfo<T*> {
typedef const T* value_type;
typedef value_type value_type_ref;
static inline void Profile(FoldingSetNodeID &ID, value_type_ref X) {
static void Profile(FoldingSetNodeID &ID, value_type_ref X) {
ID.AddPointer(X);
}
};
@ -890,18 +914,18 @@ struct ImutContainerInfo : public ImutProfileInfo<T> {
typedef bool data_type;
typedef bool data_type_ref;
static inline key_type_ref KeyOfValue(value_type_ref D) { return D; }
static inline data_type_ref DataOfValue(value_type_ref) { return true; }
static key_type_ref KeyOfValue(value_type_ref D) { return D; }
static data_type_ref DataOfValue(value_type_ref) { return true; }
static inline bool isEqual(key_type_ref LHS, key_type_ref RHS) {
static bool isEqual(key_type_ref LHS, key_type_ref RHS) {
return std::equal_to<key_type>()(LHS,RHS);
}
static inline bool isLess(key_type_ref LHS, key_type_ref RHS) {
static bool isLess(key_type_ref LHS, key_type_ref RHS) {
return std::less<key_type>()(LHS,RHS);
}
static inline bool isDataEqual(data_type_ref,data_type_ref) { return true; }
static bool isDataEqual(data_type_ref, data_type_ref) { return true; }
};
/// ImutContainerInfo - Specialization for pointer values to treat pointers
@ -916,18 +940,14 @@ struct ImutContainerInfo<T*> : public ImutProfileInfo<T*> {
typedef bool data_type;
typedef bool data_type_ref;
static inline key_type_ref KeyOfValue(value_type_ref D) { return D; }
static inline data_type_ref DataOfValue(value_type_ref) { return true; }
static key_type_ref KeyOfValue(value_type_ref D) { return D; }
static data_type_ref DataOfValue(value_type_ref) { return true; }
static inline bool isEqual(key_type_ref LHS, key_type_ref RHS) {
return LHS == RHS;
}
static bool isEqual(key_type_ref LHS, key_type_ref RHS) { return LHS == RHS; }
static inline bool isLess(key_type_ref LHS, key_type_ref RHS) {
return LHS < RHS;
}
static bool isLess(key_type_ref LHS, key_type_ref RHS) { return LHS < RHS; }
static inline bool isDataEqual(data_type_ref,data_type_ref) { return true; }
static bool isDataEqual(data_type_ref, data_type_ref) { return true; }
};
//===----------------------------------------------------------------------===//
@ -1014,8 +1034,8 @@ class ImmutableSet {
}
private:
Factory(const Factory& RHS) LLVM_DELETED_FUNCTION;
void operator=(const Factory& RHS) LLVM_DELETED_FUNCTION;
Factory(const Factory& RHS) = delete;
void operator=(const Factory& RHS) = delete;
};
friend class Factory;
@ -1059,31 +1079,7 @@ class ImmutableSet {
// Iterators.
//===--------------------------------------------------===//
class iterator {
typename TreeTy::iterator itr;
iterator() {}
iterator(TreeTy* t) : itr(t) {}
friend class ImmutableSet<ValT,ValInfo>;
public:
typedef ptrdiff_t difference_type;
typedef typename ImmutableSet<ValT,ValInfo>::value_type value_type;
typedef typename ImmutableSet<ValT,ValInfo>::value_type_ref reference;
typedef typename iterator::value_type *pointer;
typedef std::bidirectional_iterator_tag iterator_category;
typename iterator::reference operator*() const { return itr->getValue(); }
typename iterator::pointer operator->() const { return &(operator*()); }
iterator& operator++() { ++itr; return *this; }
iterator operator++(int) { iterator tmp(*this); ++itr; return tmp; }
iterator& operator--() { --itr; return *this; }
iterator operator--(int) { iterator tmp(*this); --itr; return tmp; }
bool operator==(const iterator& RHS) const { return RHS.itr == itr; }
bool operator!=(const iterator& RHS) const { return RHS.itr != itr; }
};
typedef ImutAVLValueIterator<ImmutableSet> iterator;
iterator begin() const { return iterator(Root); }
iterator end() const { return iterator(); }
@ -1094,13 +1090,11 @@ class ImmutableSet {
unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
static inline void Profile(FoldingSetNodeID& ID, const ImmutableSet& S) {
static void Profile(FoldingSetNodeID &ID, const ImmutableSet &S) {
ID.AddPointer(S.Root);
}
inline void Profile(FoldingSetNodeID& ID) const {
return Profile(ID,*this);
}
void Profile(FoldingSetNodeID &ID) const { return Profile(ID, *this); }
//===--------------------------------------------------===//
// For testing.
@ -1150,7 +1144,7 @@ class ImmutableSetRef {
if (Root) { Root->release(); }
}
static inline ImmutableSetRef getEmptySet(FactoryTy *F) {
static ImmutableSetRef getEmptySet(FactoryTy *F) {
return ImmutableSetRef(0, F);
}
@ -1195,21 +1189,7 @@ class ImmutableSetRef {
// Iterators.
//===--------------------------------------------------===//
class iterator {
typename TreeTy::iterator itr;
iterator(TreeTy* t) : itr(t) {}
friend class ImmutableSetRef<ValT,ValInfo>;
public:
iterator() {}
inline value_type_ref operator*() const { return itr->getValue(); }
inline iterator& operator++() { ++itr; return *this; }
inline iterator operator++(int) { iterator tmp(*this); ++itr; return tmp; }
inline iterator& operator--() { --itr; return *this; }
inline iterator operator--(int) { iterator tmp(*this); --itr; return tmp; }
inline bool operator==(const iterator& RHS) const { return RHS.itr == itr; }
inline bool operator!=(const iterator& RHS) const { return RHS.itr != itr; }
inline value_type *operator->() const { return &(operator*()); }
};
typedef ImutAVLValueIterator<ImmutableSetRef> iterator;
iterator begin() const { return iterator(Root); }
iterator end() const { return iterator(); }
@ -1220,13 +1200,11 @@ class ImmutableSetRef {
unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
static inline void Profile(FoldingSetNodeID& ID, const ImmutableSetRef& S) {
static void Profile(FoldingSetNodeID &ID, const ImmutableSetRef &S) {
ID.AddPointer(S.Root);
}
inline void Profile(FoldingSetNodeID& ID) const {
return Profile(ID,*this);
}
void Profile(FoldingSetNodeID &ID) const { return Profile(ID, *this); }
//===--------------------------------------------------===//
// For testing.

View File

@ -21,16 +21,19 @@
#define LLVM_ADT_INDEXEDMAP_H
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include <cassert>
#include <functional>
#include <vector>
namespace llvm {
template <typename T, typename ToIndexT = llvm::identity<unsigned> >
class IndexedMap {
typedef typename ToIndexT::argument_type IndexT;
typedef std::vector<T> StorageT;
// Prefer SmallVector with zero inline storage over std::vector. IndexedMaps
// can grow very large and SmallVector grows more efficiently as long as T
// is trivially copyable.
typedef SmallVector<T, 0> StorageT;
StorageT storage_;
T nullVal_;
ToIndexT toIndex_;

View File

@ -101,6 +101,7 @@
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/AlignOf.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/RecyclingAllocator.h"
#include <iterator>
@ -496,7 +497,7 @@ class NodeRef {
NodeRef() {}
/// operator bool - Detect a null ref.
LLVM_EXPLICIT operator bool() const { return pip.getOpaqueValue(); }
explicit operator bool() const { return pip.getOpaqueValue(); }
/// NodeRef - Create a reference to the node p with n elements.
template <typename NodeT>
@ -953,11 +954,6 @@ class IntervalMap {
RootBranch node;
};
enum {
RootDataSize = sizeof(RootBranchData) > sizeof(RootLeaf) ?
sizeof(RootBranchData) : sizeof(RootLeaf)
};
public:
typedef typename Sizer::Allocator Allocator;
typedef KeyT KeyType;
@ -966,13 +962,7 @@ class IntervalMap {
private:
// The root data is either a RootLeaf or a RootBranchData instance.
// We can't put them in a union since C++03 doesn't allow non-trivial
// constructors in unions.
// Instead, we use a char array with pointer alignment. The alignment is
// ensured by the allocator member in the class, but still verified in the
// constructor. We don't support keys or values that are more aligned than a
// pointer.
char data[RootDataSize];
AlignedCharArrayUnion<RootLeaf, RootBranchData> data;
// Tree height.
// 0: Leaves in root.
@ -993,7 +983,7 @@ class IntervalMap {
const char *d;
T *t;
} u;
u.d = data;
u.d = data.buffer;
return *u.t;
}
@ -1051,7 +1041,7 @@ class IntervalMap {
public:
explicit IntervalMap(Allocator &a) : height(0), rootSize(0), allocator(a) {
assert((uintptr_t(data) & (alignOf<RootLeaf>() - 1)) == 0 &&
assert((uintptr_t(data.buffer) & (alignOf<RootLeaf>() - 1)) == 0 &&
"Insufficient alignment");
new(&rootLeaf()) RootLeaf();
}

View File

@ -21,10 +21,9 @@
#ifndef LLVM_ADT_INTRUSIVEREFCNTPTR_H
#define LLVM_ADT_INTRUSIVEREFCNTPTR_H
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include <atomic>
#include <memory>
#include <cassert>
#include <cstddef>
namespace llvm {
@ -84,7 +83,7 @@ namespace llvm {
friend struct IntrusiveRefCntPtrInfo;
};
template <typename T> struct IntrusiveRefCntPtrInfo {
static void retain(T *obj) { obj->Retain(); }
static void release(T *obj) { obj->Release(); }
@ -114,7 +113,7 @@ class ThreadSafeRefCountedBase {
delete static_cast<const Derived*>(this);
}
};
//===----------------------------------------------------------------------===//
/// IntrusiveRefCntPtr - A template class that implements a "smart pointer"
/// that assumes the wrapped object has a reference count associated
@ -177,7 +176,7 @@ class ThreadSafeRefCountedBase {
T* get() const { return Obj; }
LLVM_EXPLICIT operator bool() const { return Obj; }
explicit operator bool() const { return Obj; }
void swap(IntrusiveRefCntPtr& other) {
T* tmp = other.Obj;
@ -268,6 +267,8 @@ class ThreadSafeRefCountedBase {
// LLVM-style downcasting support for IntrusiveRefCntPtr objects
//===----------------------------------------------------------------------===//
template <typename From> struct simplify_type;
template<class T> struct simplify_type<IntrusiveRefCntPtr<T> > {
typedef T* SimpleType;
static SimpleType getSimplifiedValue(IntrusiveRefCntPtr<T>& Val) {

View File

@ -67,6 +67,11 @@ class MapVector {
Vector.clear();
}
void swap(MapVector &RHS) {
std::swap(Map, RHS.Map);
std::swap(Vector, RHS.Vector);
}
ValueT &operator[](const KeyT &Key) {
std::pair<KeyT, unsigned> Pair = std::make_pair(Key, 0);
std::pair<typename MapType::iterator, bool> Result = Map.insert(Pair);

View File

@ -19,9 +19,8 @@
namespace llvm {
/// \brief A simple null object to allow implicit construction of Optional<T>
/// and similar types without having to spell out the specialization's name.
enum NoneType {
None
};
enum class NoneType { None };
const NoneType None = None;
}
#endif

View File

@ -70,8 +70,6 @@ class Optional {
return *this;
}
#if LLVM_HAS_VARIADIC_TEMPLATES
/// Create a new object by constructing it in place with the given arguments.
template<typename ...ArgTypes>
void emplace(ArgTypes &&...Args) {
@ -80,51 +78,6 @@ class Optional {
new (storage.buffer) T(std::forward<ArgTypes>(Args)...);
}
#else
/// Create a new object by default-constructing it in place.
void emplace() {
reset();
hasVal = true;
new (storage.buffer) T();
}
/// Create a new object by constructing it in place with the given arguments.
template<typename T1>
void emplace(T1 &&A1) {
reset();
hasVal = true;
new (storage.buffer) T(std::forward<T1>(A1));
}
/// Create a new object by constructing it in place with the given arguments.
template<typename T1, typename T2>
void emplace(T1 &&A1, T2 &&A2) {
reset();
hasVal = true;
new (storage.buffer) T(std::forward<T1>(A1), std::forward<T2>(A2));
}
/// Create a new object by constructing it in place with the given arguments.
template<typename T1, typename T2, typename T3>
void emplace(T1 &&A1, T2 &&A2, T3 &&A3) {
reset();
hasVal = true;
new (storage.buffer) T(std::forward<T1>(A1), std::forward<T2>(A2),
std::forward<T3>(A3));
}
/// Create a new object by constructing it in place with the given arguments.
template<typename T1, typename T2, typename T3, typename T4>
void emplace(T1 &&A1, T2 &&A2, T3 &&A3, T4 &&A4) {
reset();
hasVal = true;
new (storage.buffer) T(std::forward<T1>(A1), std::forward<T2>(A2),
std::forward<T3>(A3), std::forward<T4>(A4));
}
#endif // LLVM_HAS_VARIADIC_TEMPLATES
static inline Optional create(const T* y) {
return y ? Optional(*y) : Optional();
}
@ -168,7 +121,7 @@ class Optional {
const T& getValue() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
T& getValue() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
LLVM_EXPLICIT operator bool() const { return hasVal; }
explicit operator bool() const { return hasVal; }
bool hasValue() const { return hasVal; }
const T* operator->() const { return getPointer(); }
T* operator->() { return getPointer(); }

View File

@ -61,7 +61,7 @@ namespace llvm {
NumLowBitsAvailable = PT1BitsAv < PT2BitsAv ? PT1BitsAv : PT2BitsAv
};
};
/// PointerUnion - This implements a discriminated union of two pointer types,
/// and keeps the discriminator bit-mangled into the low bits of the pointer.
/// This allows the implementation to be extremely efficient in space, but
@ -80,7 +80,7 @@ namespace llvm {
template <typename PT1, typename PT2>
class PointerUnion {
public:
typedef PointerIntPair<void*, 1, bool,
typedef PointerIntPair<void*, 1, bool,
PointerUnionUIntTraits<PT1,PT2> > ValTy;
private:
ValTy Val;
@ -96,14 +96,14 @@ namespace llvm {
public:
PointerUnion() {}
PointerUnion(PT1 V) : Val(
const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(V))) {
}
PointerUnion(PT2 V) : Val(
const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(V)), 1) {
}
/// isNull - Return true if the pointer held in the union is null,
/// regardless of which type it is.
bool isNull() const {
@ -111,7 +111,7 @@ namespace llvm {
// we recursively strip off low bits if we have a nested PointerUnion.
return !PointerLikeTypeTraits<PT1>::getFromVoidPointer(Val.getPointer());
}
LLVM_EXPLICIT operator bool() const { return !isNull(); }
explicit operator bool() const { return !isNull(); }
/// is<T>() return true if the Union currently holds the type matching T.
template<typename T>
@ -123,7 +123,7 @@ namespace llvm {
int TyNo = Ty::Num;
return static_cast<int>(Val.getInt()) == TyNo;
}
/// get<T>() - Return the value of the specified pointer type. If the
/// specified pointer type is incorrect, assert.
template<typename T>
@ -131,7 +131,7 @@ namespace llvm {
assert(is<T>() && "Invalid accessor called");
return PointerLikeTypeTraits<T>::getFromVoidPointer(Val.getPointer());
}
/// dyn_cast<T>() - If the current value is of the specified pointer type,
/// return it, otherwise return null.
template<typename T>
@ -160,7 +160,7 @@ namespace llvm {
Val.initWithPointer(nullptr);
return *this;
}
/// Assignment operators - Allow assigning into this union from either
/// pointer type, setting the discriminator to remember what it came from.
const PointerUnion &operator=(const PT1 &RHS) {
@ -174,7 +174,7 @@ namespace llvm {
1);
return *this;
}
void *getOpaqueValue() const { return Val.getOpaqueValue(); }
static inline PointerUnion getFromOpaqueValue(void *VP) {
PointerUnion V;
@ -195,6 +195,12 @@ namespace llvm {
return lhs.getOpaqueValue() != rhs.getOpaqueValue();
}
template<typename PT1, typename PT2>
static bool operator<(PointerUnion<PT1, PT2> lhs,
PointerUnion<PT1, PT2> rhs) {
return lhs.getOpaqueValue() < rhs.getOpaqueValue();
}
// Teach SmallPtrSet that PointerUnion is "basically a pointer", that has
// # low bits available = min(PT1bits,PT2bits)-1.
template<typename PT1, typename PT2>
@ -208,16 +214,16 @@ namespace llvm {
getFromVoidPointer(void *P) {
return PointerUnion<PT1, PT2>::getFromOpaqueValue(P);
}
// The number of bits available are the min of the two pointer types.
enum {
NumLowBitsAvailable =
NumLowBitsAvailable =
PointerLikeTypeTraits<typename PointerUnion<PT1,PT2>::ValTy>
::NumLowBitsAvailable
};
};
/// PointerUnion3 - This is a pointer union of three pointer types. See
/// documentation for PointerUnion for usage.
template <typename PT1, typename PT2, typename PT3>
@ -233,7 +239,7 @@ namespace llvm {
IsInnerUnion(ValTy val) : Val(val) { }
template<typename T>
int is() const {
return Val.template is<InnerUnion>() &&
return Val.template is<InnerUnion>() &&
Val.template get<InnerUnion>().template is<T>();
}
template<typename T>
@ -257,7 +263,7 @@ namespace llvm {
public:
PointerUnion3() {}
PointerUnion3(PT1 V) {
Val = InnerUnion(V);
}
@ -267,12 +273,12 @@ namespace llvm {
PointerUnion3(PT3 V) {
Val = V;
}
/// isNull - Return true if the pointer held in the union is null,
/// regardless of which type it is.
bool isNull() const { return Val.isNull(); }
LLVM_EXPLICIT operator bool() const { return !isNull(); }
explicit operator bool() const { return !isNull(); }
/// is<T>() return true if the Union currently holds the type matching T.
template<typename T>
int is() const {
@ -283,7 +289,7 @@ namespace llvm {
>::Return Ty;
return Ty(Val).template is<T>();
}
/// get<T>() - Return the value of the specified pointer type. If the
/// specified pointer type is incorrect, assert.
template<typename T>
@ -296,7 +302,7 @@ namespace llvm {
>::Return Ty;
return Ty(Val).template get<T>();
}
/// dyn_cast<T>() - If the current value is of the specified pointer type,
/// return it, otherwise return null.
template<typename T>
@ -310,7 +316,7 @@ namespace llvm {
Val = nullptr;
return *this;
}
/// Assignment operators - Allow assigning into this union from either
/// pointer type, setting the discriminator to remember what it came from.
const PointerUnion3 &operator=(const PT1 &RHS) {
@ -325,7 +331,7 @@ namespace llvm {
Val = RHS;
return *this;
}
void *getOpaqueValue() const { return Val.getOpaqueValue(); }
static inline PointerUnion3 getFromOpaqueValue(void *VP) {
PointerUnion3 V;
@ -333,7 +339,7 @@ namespace llvm {
return V;
}
};
// Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has
// # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
template<typename PT1, typename PT2, typename PT3>
@ -347,10 +353,10 @@ namespace llvm {
getFromVoidPointer(void *P) {
return PointerUnion3<PT1, PT2, PT3>::getFromOpaqueValue(P);
}
// The number of bits available are the min of the two pointer types.
enum {
NumLowBitsAvailable =
NumLowBitsAvailable =
PointerLikeTypeTraits<typename PointerUnion3<PT1, PT2, PT3>::ValTy>
::NumLowBitsAvailable
};
@ -368,7 +374,7 @@ namespace llvm {
ValTy Val;
public:
PointerUnion4() {}
PointerUnion4(PT1 V) {
Val = InnerUnion1(V);
}
@ -381,12 +387,12 @@ namespace llvm {
PointerUnion4(PT4 V) {
Val = InnerUnion2(V);
}
/// isNull - Return true if the pointer held in the union is null,
/// regardless of which type it is.
bool isNull() const { return Val.isNull(); }
LLVM_EXPLICIT operator bool() const { return !isNull(); }
explicit operator bool() const { return !isNull(); }
/// is<T>() return true if the Union currently holds the type matching T.
template<typename T>
int is() const {
@ -395,10 +401,10 @@ namespace llvm {
::llvm::PointerUnionTypeSelector<PT1, T, InnerUnion1,
::llvm::PointerUnionTypeSelector<PT2, T, InnerUnion1, InnerUnion2 >
>::Return Ty;
return Val.template is<Ty>() &&
return Val.template is<Ty>() &&
Val.template get<Ty>().template is<T>();
}
/// get<T>() - Return the value of the specified pointer type. If the
/// specified pointer type is incorrect, assert.
template<typename T>
@ -411,7 +417,7 @@ namespace llvm {
>::Return Ty;
return Val.template get<Ty>().template get<T>();
}
/// dyn_cast<T>() - If the current value is of the specified pointer type,
/// return it, otherwise return null.
template<typename T>
@ -425,7 +431,7 @@ namespace llvm {
Val = nullptr;
return *this;
}
/// Assignment operators - Allow assigning into this union from either
/// pointer type, setting the discriminator to remember what it came from.
const PointerUnion4 &operator=(const PT1 &RHS) {
@ -444,7 +450,7 @@ namespace llvm {
Val = InnerUnion2(RHS);
return *this;
}
void *getOpaqueValue() const { return Val.getOpaqueValue(); }
static inline PointerUnion4 getFromOpaqueValue(void *VP) {
PointerUnion4 V;
@ -452,7 +458,7 @@ namespace llvm {
return V;
}
};
// Teach SmallPtrSet that PointerUnion4 is "basically a pointer", that has
// # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
template<typename PT1, typename PT2, typename PT3, typename PT4>
@ -466,10 +472,10 @@ namespace llvm {
getFromVoidPointer(void *P) {
return PointerUnion4<PT1, PT2, PT3, PT4>::getFromOpaqueValue(P);
}
// The number of bits available are the min of the two pointer types.
enum {
NumLowBitsAvailable =
NumLowBitsAvailable =
PointerLikeTypeTraits<typename PointerUnion4<PT1, PT2, PT3, PT4>::ValTy>
::NumLowBitsAvailable
};

View File

@ -18,6 +18,7 @@
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/iterator_range.h"
#include <set>
#include <vector>
@ -111,53 +112,52 @@ class po_iterator : public std::iterator<std::forward_iterator_tag,
}
}
inline po_iterator(NodeType *BB) {
po_iterator(NodeType *BB) {
this->insertEdge((NodeType*)nullptr, BB);
VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB)));
traverseChild();
}
inline po_iterator() {} // End is when stack is empty.
po_iterator() {} // End is when stack is empty.
inline po_iterator(NodeType *BB, SetType &S) :
po_iterator_storage<SetType, ExtStorage>(S) {
po_iterator(NodeType *BB, SetType &S)
: po_iterator_storage<SetType, ExtStorage>(S) {
if (this->insertEdge((NodeType*)nullptr, BB)) {
VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB)));
traverseChild();
}
}
inline po_iterator(SetType &S) :
po_iterator_storage<SetType, ExtStorage>(S) {
po_iterator(SetType &S)
: po_iterator_storage<SetType, ExtStorage>(S) {
} // End is when stack is empty.
public:
typedef typename super::pointer pointer;
typedef po_iterator<GraphT, SetType, ExtStorage, GT> _Self;
// Provide static "constructors"...
static inline _Self begin(GraphT G) { return _Self(GT::getEntryNode(G)); }
static inline _Self end (GraphT G) { return _Self(); }
static inline _Self begin(GraphT G, SetType &S) {
return _Self(GT::getEntryNode(G), S);
static po_iterator begin(GraphT G) {
return po_iterator(GT::getEntryNode(G));
}
static inline _Self end (GraphT G, SetType &S) { return _Self(S); }
static po_iterator end(GraphT G) { return po_iterator(); }
inline bool operator==(const _Self& x) const {
static po_iterator begin(GraphT G, SetType &S) {
return po_iterator(GT::getEntryNode(G), S);
}
static po_iterator end(GraphT G, SetType &S) { return po_iterator(S); }
bool operator==(const po_iterator &x) const {
return VisitStack == x.VisitStack;
}
inline bool operator!=(const _Self& x) const { return !operator==(x); }
bool operator!=(const po_iterator &x) const { return !(*this == x); }
inline pointer operator*() const {
return VisitStack.back().first;
}
pointer operator*() const { return VisitStack.back().first; }
// This is a nonstandard operator-> that dereferences the pointer an extra
// time... so that you can actually call methods ON the BasicBlock, because
// the contained type is a pointer. This allows BBIt->getTerminator() f.e.
//
inline NodeType *operator->() const { return operator*(); }
NodeType *operator->() const { return **this; }
inline _Self& operator++() { // Preincrement
po_iterator &operator++() { // Preincrement
this->finishPostorder(VisitStack.back().first);
VisitStack.pop_back();
if (!VisitStack.empty())
@ -165,17 +165,23 @@ class po_iterator : public std::iterator<std::forward_iterator_tag,
return *this;
}
inline _Self operator++(int) { // Postincrement
_Self tmp = *this; ++*this; return tmp;
po_iterator operator++(int) { // Postincrement
po_iterator tmp = *this;
++*this;
return tmp;
}
};
// Provide global constructors that automatically figure out correct types...
//
template <class T>
po_iterator<T> po_begin(T G) { return po_iterator<T>::begin(G); }
po_iterator<T> po_begin(const T &G) { return po_iterator<T>::begin(G); }
template <class T>
po_iterator<T> po_end (T G) { return po_iterator<T>::end(G); }
po_iterator<T> po_end (const T &G) { return po_iterator<T>::end(G); }
template <class T> iterator_range<po_iterator<T>> post_order(const T &G) {
return make_range(po_begin(G), po_end(G));
}
// Provide global definitions of external postorder iterators...
template<class T, class SetType=std::set<typename GraphTraits<T>::NodeType*> >
@ -194,6 +200,11 @@ po_ext_iterator<T, SetType> po_ext_end(T G, SetType &S) {
return po_ext_iterator<T, SetType>::end(G, S);
}
template <class T, class SetType>
iterator_range<po_ext_iterator<T, SetType>> post_order_ext(const T &G, SetType &S) {
return make_range(po_ext_begin(G, S), po_ext_end(G, S));
}
// Provide global definitions of inverse post order iterators...
template <class T,
class SetType = std::set<typename GraphTraits<T>::NodeType*>,
@ -204,15 +215,20 @@ struct ipo_iterator : public po_iterator<Inverse<T>, SetType, External > {
};
template <class T>
ipo_iterator<T> ipo_begin(T G, bool Reverse = false) {
ipo_iterator<T> ipo_begin(const T &G, bool Reverse = false) {
return ipo_iterator<T>::begin(G, Reverse);
}
template <class T>
ipo_iterator<T> ipo_end(T G){
ipo_iterator<T> ipo_end(const T &G){
return ipo_iterator<T>::end(G);
}
template <class T>
iterator_range<ipo_iterator<T>> inverse_post_order(const T &G, bool Reverse = false) {
return make_range(ipo_begin(G, Reverse), ipo_end(G));
}
// Provide global definitions of external inverse postorder iterators...
template <class T,
class SetType = std::set<typename GraphTraits<T>::NodeType*> >
@ -224,15 +240,21 @@ struct ipo_ext_iterator : public ipo_iterator<T, SetType, true> {
};
template <class T, class SetType>
ipo_ext_iterator<T, SetType> ipo_ext_begin(T G, SetType &S) {
ipo_ext_iterator<T, SetType> ipo_ext_begin(const T &G, SetType &S) {
return ipo_ext_iterator<T, SetType>::begin(G, S);
}
template <class T, class SetType>
ipo_ext_iterator<T, SetType> ipo_ext_end(T G, SetType &S) {
ipo_ext_iterator<T, SetType> ipo_ext_end(const T &G, SetType &S) {
return ipo_ext_iterator<T, SetType>::end(G, S);
}
template <class T, class SetType>
iterator_range<ipo_ext_iterator<T, SetType>>
inverse_post_order_ext(const T &G, SetType &S) {
return make_range(ipo_ext_begin(G, S), ipo_ext_end(G, S));
}
//===--------------------------------------------------------------------===//
// Reverse Post Order CFG iterator code
//===--------------------------------------------------------------------===//
@ -260,19 +282,17 @@ template<class GraphT, class GT = GraphTraits<GraphT> >
class ReversePostOrderTraversal {
typedef typename GT::NodeType NodeType;
std::vector<NodeType*> Blocks; // Block list in normal PO order
inline void Initialize(NodeType *BB) {
void Initialize(NodeType *BB) {
std::copy(po_begin(BB), po_end(BB), std::back_inserter(Blocks));
}
public:
typedef typename std::vector<NodeType*>::reverse_iterator rpo_iterator;
inline ReversePostOrderTraversal(GraphT G) {
Initialize(GT::getEntryNode(G));
}
ReversePostOrderTraversal(GraphT G) { Initialize(GT::getEntryNode(G)); }
// Because we want a reverse post order, use reverse iterators from the vector
inline rpo_iterator begin() { return Blocks.rbegin(); }
inline rpo_iterator end() { return Blocks.rend(); }
rpo_iterator begin() { return Blocks.rbegin(); }
rpo_iterator end() { return Blocks.rend(); }
};
} // End llvm namespace

View File

@ -18,6 +18,8 @@
#define LLVM_ADT_STLEXTRAS_H
#include "llvm/Support/Compiler.h"
#include <algorithm> // for std::all_of
#include <cassert>
#include <cstddef> // for std::size_t
#include <cstdlib> // for qsort
#include <functional>
@ -63,8 +65,6 @@ struct greater_ptr : public std::binary_function<Ty, Ty, bool> {
/// a function_ref.
template<typename Fn> class function_ref;
#if LLVM_HAS_VARIADIC_TEMPLATES
template<typename Ret, typename ...Params>
class function_ref<Ret(Params...)> {
Ret (*callback)(intptr_t callable, Params ...params);
@ -89,112 +89,6 @@ class function_ref<Ret(Params...)> {
}
};
#else
template<typename Ret>
class function_ref<Ret()> {
Ret (*callback)(intptr_t callable);
intptr_t callable;
template<typename Callable>
static Ret callback_fn(intptr_t callable) {
return (*reinterpret_cast<Callable*>(callable))();
}
public:
template<typename Callable>
function_ref(Callable &&callable,
typename std::enable_if<
!std::is_same<typename std::remove_reference<Callable>::type,
function_ref>::value>::type * = nullptr)
: callback(callback_fn<typename std::remove_reference<Callable>::type>),
callable(reinterpret_cast<intptr_t>(&callable)) {}
Ret operator()() const { return callback(callable); }
};
template<typename Ret, typename Param1>
class function_ref<Ret(Param1)> {
Ret (*callback)(intptr_t callable, Param1 param1);
intptr_t callable;
template<typename Callable>
static Ret callback_fn(intptr_t callable, Param1 param1) {
return (*reinterpret_cast<Callable*>(callable))(
std::forward<Param1>(param1));
}
public:
template<typename Callable>
function_ref(Callable &&callable,
typename std::enable_if<
!std::is_same<typename std::remove_reference<Callable>::type,
function_ref>::value>::type * = nullptr)
: callback(callback_fn<typename std::remove_reference<Callable>::type>),
callable(reinterpret_cast<intptr_t>(&callable)) {}
Ret operator()(Param1 param1) {
return callback(callable, std::forward<Param1>(param1));
}
};
template<typename Ret, typename Param1, typename Param2>
class function_ref<Ret(Param1, Param2)> {
Ret (*callback)(intptr_t callable, Param1 param1, Param2 param2);
intptr_t callable;
template<typename Callable>
static Ret callback_fn(intptr_t callable, Param1 param1, Param2 param2) {
return (*reinterpret_cast<Callable*>(callable))(
std::forward<Param1>(param1),
std::forward<Param2>(param2));
}
public:
template<typename Callable>
function_ref(Callable &&callable,
typename std::enable_if<
!std::is_same<typename std::remove_reference<Callable>::type,
function_ref>::value>::type * = nullptr)
: callback(callback_fn<typename std::remove_reference<Callable>::type>),
callable(reinterpret_cast<intptr_t>(&callable)) {}
Ret operator()(Param1 param1, Param2 param2) {
return callback(callable,
std::forward<Param1>(param1),
std::forward<Param2>(param2));
}
};
template<typename Ret, typename Param1, typename Param2, typename Param3>
class function_ref<Ret(Param1, Param2, Param3)> {
Ret (*callback)(intptr_t callable, Param1 param1, Param2 param2, Param3 param3);
intptr_t callable;
template<typename Callable>
static Ret callback_fn(intptr_t callable, Param1 param1, Param2 param2,
Param3 param3) {
return (*reinterpret_cast<Callable*>(callable))(
std::forward<Param1>(param1),
std::forward<Param2>(param2),
std::forward<Param3>(param3));
}
public:
template<typename Callable>
function_ref(Callable &&callable,
typename std::enable_if<
!std::is_same<typename std::remove_reference<Callable>::type,
function_ref>::value>::type * = nullptr)
: callback(callback_fn<typename std::remove_reference<Callable>::type>),
callable(reinterpret_cast<intptr_t>(&callable)) {}
Ret operator()(Param1 param1, Param2 param2, Param3 param3) {
return callback(callable,
std::forward<Param1>(param1),
std::forward<Param2>(param2),
std::forward<Param3>(param3));
}
};
#endif
// deleter - Very very very simple method that is used to invoke operator
// delete on something. It is used like this:
//
@ -230,7 +124,6 @@ class mapped_iterator {
typedef void reference; // Can't modify value returned by fn
typedef RootIt iterator_type;
typedef mapped_iterator<RootIt, UnaryFunc> _Self;
inline const RootIt &getCurrent() const { return current; }
inline const UnaryFunc &getFunc() const { return Fn; }
@ -242,34 +135,56 @@ class mapped_iterator {
return Fn(*current); // little change
}
_Self& operator++() { ++current; return *this; }
_Self& operator--() { --current; return *this; }
_Self operator++(int) { _Self __tmp = *this; ++current; return __tmp; }
_Self operator--(int) { _Self __tmp = *this; --current; return __tmp; }
_Self operator+ (difference_type n) const {
return _Self(current + n, Fn);
mapped_iterator &operator++() {
++current;
return *this;
}
_Self& operator+= (difference_type n) { current += n; return *this; }
_Self operator- (difference_type n) const {
return _Self(current - n, Fn);
mapped_iterator &operator--() {
--current;
return *this;
}
mapped_iterator operator++(int) {
mapped_iterator __tmp = *this;
++current;
return __tmp;
}
mapped_iterator operator--(int) {
mapped_iterator __tmp = *this;
--current;
return __tmp;
}
mapped_iterator operator+(difference_type n) const {
return mapped_iterator(current + n, Fn);
}
mapped_iterator &operator+=(difference_type n) {
current += n;
return *this;
}
mapped_iterator operator-(difference_type n) const {
return mapped_iterator(current - n, Fn);
}
mapped_iterator &operator-=(difference_type n) {
current -= n;
return *this;
}
_Self& operator-= (difference_type n) { current -= n; return *this; }
reference operator[](difference_type n) const { return *(*this + n); }
inline bool operator!=(const _Self &X) const { return !operator==(X); }
inline bool operator==(const _Self &X) const { return current == X.current; }
inline bool operator< (const _Self &X) const { return current < X.current; }
bool operator!=(const mapped_iterator &X) const { return !operator==(X); }
bool operator==(const mapped_iterator &X) const {
return current == X.current;
}
bool operator<(const mapped_iterator &X) const { return current < X.current; }
inline difference_type operator-(const _Self &X) const {
difference_type operator-(const mapped_iterator &X) const {
return current - X.current;
}
};
template <class _Iterator, class Func>
inline mapped_iterator<_Iterator, Func>
operator+(typename mapped_iterator<_Iterator, Func>::difference_type N,
const mapped_iterator<_Iterator, Func>& X) {
return mapped_iterator<_Iterator, Func>(X.getCurrent() - N, X.getFunc());
template <class Iterator, class Func>
inline mapped_iterator<Iterator, Func>
operator+(typename mapped_iterator<Iterator, Func>::difference_type N,
const mapped_iterator<Iterator, Func> &X) {
return mapped_iterator<Iterator, Func>(X.getCurrent() - N, X.getFunc());
}
@ -301,6 +216,28 @@ struct less_second {
}
};
// A subset of N3658. More stuff can be added as-needed.
/// \brief Represents a compile-time sequence of integers.
template <class T, T... I> struct integer_sequence {
typedef T value_type;
static LLVM_CONSTEXPR size_t size() { return sizeof...(I); }
};
/// \brief Alias for the common case of a sequence of size_ts.
template <size_t... I>
struct index_sequence : integer_sequence<std::size_t, I...> {};
template <std::size_t N, std::size_t... I>
struct build_index_impl : build_index_impl<N - 1, N - 1, I...> {};
template <std::size_t... I>
struct build_index_impl<0, I...> : index_sequence<I...> {};
/// \brief Creates a compile-time integer sequence for a parameter pack.
template <class... Ts>
struct index_sequence_for : build_index_impl<sizeof...(Ts)> {};
//===----------------------------------------------------------------------===//
// Extra additions for arrays
//===----------------------------------------------------------------------===//
@ -348,10 +285,11 @@ inline int (*get_array_pod_sort_comparator(const T &))
/// default to std::less.
template<class IteratorTy>
inline void array_pod_sort(IteratorTy Start, IteratorTy End) {
// Don't dereference start iterator of empty sequence.
if (Start == End) return;
qsort(&*Start, End-Start, sizeof(*Start),
get_array_pod_sort_comparator(*Start));
// Don't inefficiently call qsort with one element or trigger undefined
// behavior with an empty sequence.
auto NElts = End - Start;
if (NElts <= 1) return;
qsort(&*Start, NElts, sizeof(*Start), get_array_pod_sort_comparator(*Start));
}
template <class IteratorTy>
@ -360,9 +298,11 @@ inline void array_pod_sort(
int (*Compare)(
const typename std::iterator_traits<IteratorTy>::value_type *,
const typename std::iterator_traits<IteratorTy>::value_type *)) {
// Don't dereference start iterator of empty sequence.
if (Start == End) return;
qsort(&*Start, End - Start, sizeof(*Start),
// Don't inefficiently call qsort with one element or trigger undefined
// behavior with an empty sequence.
auto NElts = End - Start;
if (NElts <= 1) return;
qsort(&*Start, NElts, sizeof(*Start),
reinterpret_cast<int (*)(const void *, const void *)>(Compare));
}
@ -388,12 +328,18 @@ void DeleteContainerSeconds(Container &C) {
C.clear();
}
/// Provide wrappers to std::all_of which take ranges instead of having to pass
/// being/end explicitly.
template<typename R, class UnaryPredicate>
bool all_of(R &&Range, UnaryPredicate &&P) {
return std::all_of(Range.begin(), Range.end(),
std::forward<UnaryPredicate>(P));
}
//===----------------------------------------------------------------------===//
// Extra additions to <memory>
//===----------------------------------------------------------------------===//
#if LLVM_HAS_VARIADIC_TEMPLATES
// Implement make_unique according to N3656.
/// \brief Constructs a `new T()` with the given args and returns a
@ -427,123 +373,7 @@ make_unique(size_t n) {
/// This function isn't used and is only here to provide better compile errors.
template <class T, class... Args>
typename std::enable_if<std::extent<T>::value != 0>::type
make_unique(Args &&...) LLVM_DELETED_FUNCTION;
#else
template <class T>
typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique() {
return std::unique_ptr<T>(new T());
}
template <class T, class Arg1>
typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(Arg1 &&arg1) {
return std::unique_ptr<T>(new T(std::forward<Arg1>(arg1)));
}
template <class T, class Arg1, class Arg2>
typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(Arg1 &&arg1, Arg2 &&arg2) {
return std::unique_ptr<T>(
new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2)));
}
template <class T, class Arg1, class Arg2, class Arg3>
typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3) {
return std::unique_ptr<T>(new T(std::forward<Arg1>(arg1),
std::forward<Arg2>(arg2),
std::forward<Arg3>(arg3)));
}
template <class T, class Arg1, class Arg2, class Arg3, class Arg4>
typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4) {
return std::unique_ptr<T>(
new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
std::forward<Arg3>(arg3), std::forward<Arg4>(arg4)));
}
template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5>
typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5) {
return std::unique_ptr<T>(
new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
std::forward<Arg3>(arg3), std::forward<Arg4>(arg4),
std::forward<Arg5>(arg5)));
}
template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5,
class Arg6>
typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5,
Arg6 &&arg6) {
return std::unique_ptr<T>(
new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
std::forward<Arg3>(arg3), std::forward<Arg4>(arg4),
std::forward<Arg5>(arg5), std::forward<Arg6>(arg6)));
}
template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5,
class Arg6, class Arg7>
typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5,
Arg6 &&arg6, Arg7 &&arg7) {
return std::unique_ptr<T>(
new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
std::forward<Arg3>(arg3), std::forward<Arg4>(arg4),
std::forward<Arg5>(arg5), std::forward<Arg6>(arg6),
std::forward<Arg7>(arg7)));
}
template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5,
class Arg6, class Arg7, class Arg8>
typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5,
Arg6 &&arg6, Arg7 &&arg7, Arg8 &&arg8) {
return std::unique_ptr<T>(
new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
std::forward<Arg3>(arg3), std::forward<Arg4>(arg4),
std::forward<Arg5>(arg5), std::forward<Arg6>(arg6),
std::forward<Arg7>(arg7), std::forward<Arg8>(arg8)));
}
template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5,
class Arg6, class Arg7, class Arg8, class Arg9>
typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5,
Arg6 &&arg6, Arg7 &&arg7, Arg8 &&arg8, Arg9 &&arg9) {
return std::unique_ptr<T>(
new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
std::forward<Arg3>(arg3), std::forward<Arg4>(arg4),
std::forward<Arg5>(arg5), std::forward<Arg6>(arg6),
std::forward<Arg7>(arg7), std::forward<Arg8>(arg8),
std::forward<Arg9>(arg9)));
}
template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5,
class Arg6, class Arg7, class Arg8, class Arg9, class Arg10>
typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5,
Arg6 &&arg6, Arg7 &&arg7, Arg8 &&arg8, Arg9 &&arg9, Arg10 &&arg10) {
return std::unique_ptr<T>(
new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
std::forward<Arg3>(arg3), std::forward<Arg4>(arg4),
std::forward<Arg5>(arg5), std::forward<Arg6>(arg6),
std::forward<Arg7>(arg7), std::forward<Arg8>(arg8),
std::forward<Arg9>(arg9), std::forward<Arg10>(arg10)));
}
template <class T>
typename std::enable_if<std::is_array<T>::value &&std::extent<T>::value == 0,
std::unique_ptr<T>>::type
make_unique(size_t n) {
return std::unique_ptr<T>(new typename std::remove_extent<T>::type[n]());
}
#endif
make_unique(Args &&...) = delete;
struct FreeDeleter {
void operator()(void* v) {
@ -558,6 +388,35 @@ struct pair_hash {
}
};
/// A functor like C++14's std::less<void> in its absence.
struct less {
template <typename A, typename B> bool operator()(A &&a, B &&b) const {
return std::forward<A>(a) < std::forward<B>(b);
}
};
/// A functor like C++14's std::equal<void> in its absence.
struct equal {
template <typename A, typename B> bool operator()(A &&a, B &&b) const {
return std::forward<A>(a) == std::forward<B>(b);
}
};
/// Binary functor that adapts to any other binary functor after dereferencing
/// operands.
template <typename T> struct deref {
T func;
// Could be further improved to cope with non-derivable functors and
// non-binary functors (should be a variadic template member function
// operator()).
template <typename A, typename B>
auto operator()(A &lhs, B &rhs) const -> decltype(func(*lhs, *rhs)) {
assert(lhs);
assert(rhs);
return func(*lhs, *rhs);
}
};
} // End llvm namespace
#endif

View File

@ -90,8 +90,8 @@ class ScopedHashTableScope {
/// LastValInScope - This is the last value that was inserted for this scope
/// or null if none have been inserted yet.
ScopedHashTableVal<K, V> *LastValInScope;
void operator=(ScopedHashTableScope&) LLVM_DELETED_FUNCTION;
ScopedHashTableScope(ScopedHashTableScope&) LLVM_DELETED_FUNCTION;
void operator=(ScopedHashTableScope&) = delete;
ScopedHashTableScope(ScopedHashTableScope&) = delete;
public:
ScopedHashTableScope(ScopedHashTable<K, V, KInfo, AllocatorTy> &HT);
~ScopedHashTableScope();

View File

@ -53,6 +53,9 @@ class SmallBitVector {
SmallNumDataBits = SmallNumRawBits - SmallNumSizeBits
};
static_assert(NumBaseBits == 64 || NumBaseBits == 32,
"Unsupported word size");
public:
typedef unsigned size_type;
// Encapsulation of a single bit.
@ -63,6 +66,8 @@ class SmallBitVector {
public:
reference(SmallBitVector &b, unsigned Idx) : TheVector(b), BitPos(Idx) {}
reference(const reference&) = default;
reference& operator=(reference t) {
*this = bool(t);
return *this;
@ -177,11 +182,7 @@ class SmallBitVector {
size_type count() const {
if (isSmall()) {
uintptr_t Bits = getSmallBits();
if (NumBaseBits == 32)
return CountPopulation_32(Bits);
if (NumBaseBits == 64)
return CountPopulation_64(Bits);
llvm_unreachable("Unsupported!");
return countPopulation(Bits);
}
return getPointer()->count();
}
@ -214,11 +215,7 @@ class SmallBitVector {
uintptr_t Bits = getSmallBits();
if (Bits == 0)
return -1;
if (NumBaseBits == 32)
return countTrailingZeros(Bits);
if (NumBaseBits == 64)
return countTrailingZeros(Bits);
llvm_unreachable("Unsupported!");
return countTrailingZeros(Bits);
}
return getPointer()->find_first();
}
@ -232,11 +229,7 @@ class SmallBitVector {
Bits &= ~uintptr_t(0) << (Prev + 1);
if (Bits == 0 || Prev + 1 >= getSmallSize())
return -1;
if (NumBaseBits == 32)
return countTrailingZeros(Bits);
if (NumBaseBits == 64)
return countTrailingZeros(Bits);
llvm_unreachable("Unsupported!");
return countTrailingZeros(Bits);
}
return getPointer()->find_next(Prev);
}
@ -560,7 +553,6 @@ class SmallBitVector {
private:
template<bool AddBits, bool InvertMask>
void applyMask(const uint32_t *Mask, unsigned MaskWords) {
assert((NumBaseBits == 64 || NumBaseBits == 32) && "Unsupported word size");
if (NumBaseBits == 64 && MaskWords >= 2) {
uint64_t M = Mask[0] | (uint64_t(Mask[1]) << 32);
if (InvertMask) M = ~M;

View File

@ -132,7 +132,7 @@ class SmallPtrSetImplBase {
/// Grow - Allocate a larger backing store for the buckets and move it over.
void Grow(unsigned NewSize);
void operator=(const SmallPtrSetImplBase &RHS) LLVM_DELETED_FUNCTION;
void operator=(const SmallPtrSetImplBase &RHS) = delete;
protected:
/// swap - Swaps the elements of two sets.
/// Note: This method assumes that both sets have the same small size.
@ -242,7 +242,7 @@ template <typename PtrType>
class SmallPtrSetImpl : public SmallPtrSetImplBase {
typedef PointerLikeTypeTraits<PtrType> PtrTraits;
SmallPtrSetImpl(const SmallPtrSetImpl&) LLVM_DELETED_FUNCTION;
SmallPtrSetImpl(const SmallPtrSetImpl&) = delete;
protected:
// Constructors that forward to the base.
SmallPtrSetImpl(const void **SmallStorage, const SmallPtrSetImpl &that)

View File

@ -24,6 +24,7 @@
#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <initializer_list>
#include <iterator>
#include <memory>
@ -236,51 +237,6 @@ class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T> {
this->setEnd(this->end()-1);
this->end()->~T();
}
#if LLVM_HAS_VARIADIC_TEMPLATES
template <typename... ArgTypes> void emplace_back(ArgTypes &&... Args) {
if (LLVM_UNLIKELY(this->EndX >= this->CapacityX))
this->grow();
::new ((void *)this->end()) T(std::forward<ArgTypes>(Args)...);
this->setEnd(this->end() + 1);
}
#else
private:
template <typename Constructor> void emplace_back_impl(Constructor construct) {
if (LLVM_UNLIKELY(this->EndX >= this->CapacityX))
this->grow();
construct((void *)this->end());
this->setEnd(this->end() + 1);
}
public:
void emplace_back() {
emplace_back_impl([](void *Mem) { ::new (Mem) T(); });
}
template <typename T1> void emplace_back(T1 &&A1) {
emplace_back_impl([&](void *Mem) { ::new (Mem) T(std::forward<T1>(A1)); });
}
template <typename T1, typename T2> void emplace_back(T1 &&A1, T2 &&A2) {
emplace_back_impl([&](void *Mem) {
::new (Mem) T(std::forward<T1>(A1), std::forward<T2>(A2));
});
}
template <typename T1, typename T2, typename T3>
void emplace_back(T1 &&A1, T2 &&A2, T3 &&A3) {
T(std::forward<T1>(A1), std::forward<T2>(A2), std::forward<T3>(A3));
emplace_back_impl([&](void *Mem) {
::new (Mem)
T(std::forward<T1>(A1), std::forward<T2>(A2), std::forward<T3>(A3));
});
}
template <typename T1, typename T2, typename T3, typename T4>
void emplace_back(T1 &&A1, T2 &&A2, T3 &&A3, T4 &&A4) {
emplace_back_impl([&](void *Mem) {
::new (Mem) T(std::forward<T1>(A1), std::forward<T2>(A2),
std::forward<T3>(A3), std::forward<T4>(A4));
});
}
#endif // LLVM_HAS_VARIADIC_TEMPLATES
};
// Define this out-of-line to dissuade the C++ compiler from inlining it.
@ -352,8 +308,11 @@ class SmallVectorTemplateBase<T, true> : public SmallVectorTemplateCommon<T> {
/// Copy the range [I, E) onto the uninitialized memory
/// starting with "Dest", constructing elements into it as needed.
template<typename T1, typename T2>
static void uninitialized_copy(T1 *I, T1 *E, T2 *Dest) {
template <typename T1, typename T2>
static void uninitialized_copy(
T1 *I, T1 *E, T2 *Dest,
typename std::enable_if<std::is_same<typename std::remove_const<T1>::type,
T2>::value>::type * = nullptr) {
// Use memcpy for PODs iterated by pointers (which includes SmallVector
// iterators): std::uninitialized_copy optimizes to memmove, but we can
// use memcpy here.
@ -385,7 +344,7 @@ template <typename T>
class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
typedef SmallVectorTemplateBase<T, isPodLike<T>::value > SuperClass;
SmallVectorImpl(const SmallVectorImpl&) LLVM_DELETED_FUNCTION;
SmallVectorImpl(const SmallVectorImpl&) = delete;
public:
typedef typename SuperClass::iterator iterator;
typedef typename SuperClass::size_type size_type;
@ -459,9 +418,7 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
this->grow(this->size()+NumInputs);
// Copy the new elements over.
// TODO: NEED To compile time dispatch on whether in_iter is a random access
// iterator to use the fast uninitialized_copy.
std::uninitialized_copy(in_start, in_end, this->end());
this->uninitialized_copy(in_start, in_end, this->end());
this->setEnd(this->end() + NumInputs);
}
@ -476,6 +433,10 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
this->setEnd(this->end() + NumInputs);
}
void append(std::initializer_list<T> IL) {
append(IL.begin(), IL.end());
}
void assign(size_type NumElts, const T &Elt) {
clear();
if (this->capacity() < NumElts)
@ -484,6 +445,11 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
std::uninitialized_fill(this->begin(), this->end(), Elt);
}
void assign(std::initializer_list<T> IL) {
clear();
append(IL);
}
iterator erase(iterator I) {
assert(I >= this->begin() && "Iterator to erase is out of bounds.");
assert(I < this->end() && "Erasing at past-the-end iterator.");
@ -677,6 +643,17 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
return I;
}
void insert(iterator I, std::initializer_list<T> IL) {
insert(I, IL.begin(), IL.end());
}
template <typename... ArgTypes> void emplace_back(ArgTypes &&... Args) {
if (LLVM_UNLIKELY(this->EndX >= this->CapacityX))
this->grow();
::new ((void *)this->end()) T(std::forward<ArgTypes>(Args)...);
this->setEnd(this->end() + 1);
}
SmallVectorImpl &operator=(const SmallVectorImpl &RHS);
SmallVectorImpl &operator=(SmallVectorImpl &&RHS);
@ -902,6 +879,10 @@ class SmallVector : public SmallVectorImpl<T> {
this->append(R.begin(), R.end());
}
SmallVector(std::initializer_list<T> IL) : SmallVectorImpl<T>(N) {
this->assign(IL);
}
SmallVector(const SmallVector &RHS) : SmallVectorImpl<T>(N) {
if (!RHS.empty())
SmallVectorImpl<T>::operator=(RHS);
@ -921,6 +902,21 @@ class SmallVector : public SmallVectorImpl<T> {
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=(SmallVectorImpl<T> &&RHS) {
SmallVectorImpl<T>::operator=(::std::move(RHS));
return *this;
}
const SmallVector &operator=(std::initializer_list<T> IL) {
this->assign(IL);
return *this;
}
};
template<typename T, unsigned N>

View File

@ -124,25 +124,15 @@ struct SparseBitVectorElement
size_type count() const {
unsigned NumBits = 0;
for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
if (sizeof(BitWord) == 4)
NumBits += CountPopulation_32(Bits[i]);
else if (sizeof(BitWord) == 8)
NumBits += CountPopulation_64(Bits[i]);
else
llvm_unreachable("Unsupported!");
NumBits += countPopulation(Bits[i]);
return NumBits;
}
/// find_first - Returns the index of the first set bit.
int find_first() const {
for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
if (Bits[i] != 0) {
if (sizeof(BitWord) == 4)
return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
if (sizeof(BitWord) == 8)
return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
llvm_unreachable("Unsupported!");
}
if (Bits[i] != 0)
return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
llvm_unreachable("Illegal empty element");
}
@ -161,23 +151,13 @@ struct SparseBitVectorElement
// Mask off previous bits.
Copy &= ~0UL << BitPos;
if (Copy != 0) {
if (sizeof(BitWord) == 4)
return WordPos * BITWORD_SIZE + countTrailingZeros(Copy);
if (sizeof(BitWord) == 8)
return WordPos * BITWORD_SIZE + countTrailingZeros(Copy);
llvm_unreachable("Unsupported!");
}
if (Copy != 0)
return WordPos * BITWORD_SIZE + countTrailingZeros(Copy);
// Check subsequent words.
for (unsigned i = WordPos+1; i < BITWORDS_PER_ELEMENT; ++i)
if (Bits[i] != 0) {
if (sizeof(BitWord) == 4)
return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
if (sizeof(BitWord) == 8)
return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
llvm_unreachable("Unsupported!");
}
if (Bits[i] != 0)
return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
return -1;
}

View File

@ -133,8 +133,8 @@ class SparseMultiSet {
// Disable copy construction and assignment.
// This data structure is not meant to be used that way.
SparseMultiSet(const SparseMultiSet&) LLVM_DELETED_FUNCTION;
SparseMultiSet &operator=(const SparseMultiSet&) LLVM_DELETED_FUNCTION;
SparseMultiSet(const SparseMultiSet&) = delete;
SparseMultiSet &operator=(const SparseMultiSet&) = delete;
/// Whether the given entry is the head of the list. List heads's previous
/// pointers are to the tail of the list, allowing for efficient access to the

View File

@ -133,8 +133,8 @@ class SparseSet {
// Disable copy construction and assignment.
// This data structure is not meant to be used that way.
SparseSet(const SparseSet&) LLVM_DELETED_FUNCTION;
SparseSet &operator=(const SparseSet&) LLVM_DELETED_FUNCTION;
SparseSet(const SparseSet&) = delete;
SparseSet &operator=(const SparseSet&) = delete;
public:
typedef ValueT value_type;

View File

@ -111,7 +111,7 @@ class StringMapImpl {
/// and data.
template<typename ValueTy>
class StringMapEntry : public StringMapEntryBase {
StringMapEntry(StringMapEntry &E) LLVM_DELETED_FUNCTION;
StringMapEntry(StringMapEntry &E) = delete;
public:
ValueTy second;

View File

@ -238,9 +238,12 @@ namespace llvm {
/// \returns The index of the first occurrence of \p C, or npos if not
/// found.
size_t find(char C, size_t From = 0) const {
for (size_t i = std::min(From, Length), e = Length; i != e; ++i)
if (Data[i] == C)
return i;
size_t FindBegin = std::min(From, Length);
if (FindBegin < Length) { // Avoid calling memchr with nullptr.
// Just forward to memchr, which is faster than a hand-rolled loop.
if (const void *P = ::memchr(Data + FindBegin, C, Length - FindBegin))
return static_cast<const char *>(P) - Data;
}
return npos;
}

View File

@ -27,9 +27,12 @@ class TinyPtrVector {
public:
typedef llvm::SmallVector<EltTy, 4> VecTy;
typedef typename VecTy::value_type value_type;
typedef llvm::PointerUnion<EltTy, VecTy *> PtrUnion;
llvm::PointerUnion<EltTy, VecTy*> Val;
private:
PtrUnion Val;
public:
TinyPtrVector() {}
~TinyPtrVector() {
if (VecTy *V = Val.template dyn_cast<VecTy*>())
@ -96,12 +99,13 @@ class TinyPtrVector {
return *this;
}
/// Constructor from a single element.
explicit TinyPtrVector(EltTy Elt) : Val(Elt) {}
/// Constructor from an ArrayRef.
///
/// This also is a constructor for individual array elements due to the single
/// element constructor for ArrayRef.
explicit TinyPtrVector(ArrayRef<EltTy> Elts)
: Val(new VecTy(Elts.begin(), Elts.end())) {}
: Val(Elts.size() == 1 ? PtrUnion(Elts[0])
: PtrUnion(new VecTy(Elts.begin(), Elts.end()))) {}
// implicit conversion operator to ArrayRef.
operator ArrayRef<EltTy>() const {
@ -112,6 +116,15 @@ class TinyPtrVector {
return *Val.template get<VecTy*>();
}
// implicit conversion operator to MutableArrayRef.
operator MutableArrayRef<EltTy>() {
if (Val.isNull())
return None;
if (Val.template is<EltTy>())
return *Val.getAddrOfPtr1();
return *Val.template get<VecTy*>();
}
bool empty() const {
// This vector can be empty if it contains no element, or if it
// contains a pointer to an empty vector.

View File

@ -50,6 +50,7 @@ class Triple {
armeb, // ARM (big endian): armeb
aarch64, // AArch64 (little endian): aarch64
aarch64_be, // AArch64 (big endian): aarch64_be
bpf, // eBPF or extended BPF or 64-bit BPF (little endian)
hexagon, // Hexagon: hexagon
mips, // MIPS: mips, mipsallegrex
mipsel, // MIPSEL: mipsel, mipsallegrexel
@ -63,6 +64,7 @@ class Triple {
amdgcn, // AMDGCN: AMD GCN GPUs
sparc, // Sparc: sparc
sparcv9, // Sparcv9: Sparcv9
sparcel, // Sparc: (endianness = little). NB: 'Sparcle' is a CPU variant
systemz, // SystemZ: s390x
tce, // TCE (http://tce.cs.tut.fi/): tce
thumb, // Thumb (little endian): thumb, thumbv.*
@ -80,11 +82,13 @@ class Triple {
hsail64, // AMD HSAIL with 64-bit pointers
spir, // SPIR: standard portable IR for OpenCL 32-bit version
spir64, // SPIR: standard portable IR for OpenCL 64-bit version
kalimba // Kalimba: generic kalimba
kalimba, // Kalimba: generic kalimba
LastArchType = kalimba
};
enum SubArchType {
NoSubArch,
ARMSubArch_v8_1a,
ARMSubArch_v8,
ARMSubArch_v7,
ARMSubArch_v7em,
@ -92,6 +96,7 @@ class Triple {
ARMSubArch_v7s,
ARMSubArch_v6,
ARMSubArch_v6m,
ARMSubArch_v6k,
ARMSubArch_v6t2,
ARMSubArch_v5,
ARMSubArch_v5te,
@ -114,11 +119,13 @@ class Triple {
ImaginationTechnologies,
MipsTechnologies,
NVIDIA,
CSR
CSR,
LastVendorType = CSR
};
enum OSType {
UnknownOS,
CloudABI,
Darwin,
DragonFly,
FreeBSD,
@ -140,7 +147,9 @@ class Triple {
AIX,
CUDA, // NVIDIA CUDA
NVCL, // NVIDIA OpenCL
AMDHSA // AMD HSA Runtime
AMDHSA, // AMD HSA Runtime
PS4,
LastOSType = PS4
};
enum EnvironmentType {
UnknownEnvironment,
@ -157,6 +166,7 @@ class Triple {
MSVC,
Itanium,
Cygnus,
LastEnvironmentType = Cygnus
};
enum ObjectFormatType {
UnknownObjectFormat,
@ -200,6 +210,13 @@ class Triple {
Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr,
const Twine &EnvironmentStr);
bool operator==(const Triple &Other) const {
return Arch == Other.Arch && SubArch == Other.SubArch &&
Vendor == Other.Vendor && OS == Other.OS &&
Environment == Other.Environment &&
ObjectFormat == Other.ObjectFormat;
}
/// @}
/// @name Normalization
/// @{
@ -210,6 +227,9 @@ class Triple {
/// common case in which otherwise valid components are in the wrong order.
static std::string normalize(StringRef Str);
/// \brief Return the normalized form of this triple's string.
std::string normalize() const { return normalize(Data); }
/// @}
/// @name Typed Component Access
/// @{
@ -334,6 +354,12 @@ class Triple {
return false;
}
bool isOSVersionLT(const Triple &Other) const {
unsigned RHS[3];
Other.getOSVersion(RHS[0], RHS[1], RHS[2]);
return isOSVersionLT(RHS[0], RHS[1], RHS[2]);
}
/// isMacOSXVersionLT - Comparison function for checking OS X version
/// compatibility, which handles supporting skewed version numbering schemes
/// used by the "darwin" triples.
@ -423,7 +449,7 @@ class Triple {
/// \brief Tests whether the OS is Windows.
bool isOSWindows() const {
return getOS() == Triple::Win32 || isOSCygMing();
return getOS() == Triple::Win32;
}
/// \brief Tests whether the OS is NaCl (Native Client)
@ -451,6 +477,19 @@ class Triple {
return getObjectFormat() == Triple::MachO;
}
/// \brief Tests whether the target is the PS4 CPU
bool isPS4CPU() const {
return getArch() == Triple::x86_64 &&
getVendor() == Triple::SCEI &&
getOS() == Triple::PS4;
}
/// \brief Tests whether the target is the PS4 platform
bool isPS4() const {
return getVendor() == Triple::SCEI &&
getOS() == Triple::PS4;
}
/// @}
/// @name Mutators
/// @{

View File

@ -10,6 +10,7 @@
#ifndef LLVM_ADT_TWINE_H
#define LLVM_ADT_TWINE_H
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/ErrorHandling.h"
@ -17,9 +18,6 @@
#include <string>
namespace llvm {
template <typename T>
class SmallVectorImpl;
class StringRef;
class raw_ostream;
/// Twine - A lightweight data structure for efficiently representing the
@ -100,6 +98,9 @@ namespace llvm {
/// A pointer to a StringRef instance.
StringRefKind,
/// A pointer to a SmallString instance.
SmallStringKind,
/// A char value reinterpreted as a pointer, to render as a character.
CharKind,
@ -136,6 +137,7 @@ namespace llvm {
const char *cString;
const std::string *stdString;
const StringRef *stringRef;
const SmallVectorImpl<char> *smallString;
char character;
unsigned int decUI;
int decI;
@ -166,50 +168,49 @@ namespace llvm {
}
/// Construct a binary twine.
explicit Twine(const Twine &_LHS, const Twine &_RHS)
: LHSKind(TwineKind), RHSKind(TwineKind) {
LHS.twine = &_LHS;
RHS.twine = &_RHS;
explicit Twine(const Twine &LHS, const Twine &RHS)
: LHSKind(TwineKind), RHSKind(TwineKind) {
this->LHS.twine = &LHS;
this->RHS.twine = &RHS;
assert(isValid() && "Invalid twine!");
}
/// Construct a twine from explicit values.
explicit Twine(Child _LHS, NodeKind _LHSKind,
Child _RHS, NodeKind _RHSKind)
: LHS(_LHS), RHS(_RHS), LHSKind(_LHSKind), RHSKind(_RHSKind) {
explicit Twine(Child LHS, NodeKind LHSKind, Child RHS, NodeKind RHSKind)
: LHS(LHS), RHS(RHS), LHSKind(LHSKind), RHSKind(RHSKind) {
assert(isValid() && "Invalid twine!");
}
/// Since the intended use of twines is as temporary objects, assignments
/// when concatenating might cause undefined behavior or stack corruptions
Twine &operator=(const Twine &Other) LLVM_DELETED_FUNCTION;
Twine &operator=(const Twine &Other) = delete;
/// isNull - Check for the null twine.
/// Check for the null twine.
bool isNull() const {
return getLHSKind() == NullKind;
}
/// isEmpty - Check for the empty twine.
/// Check for the empty twine.
bool isEmpty() const {
return getLHSKind() == EmptyKind;
}
/// isNullary - Check if this is a nullary twine (null or empty).
/// Check if this is a nullary twine (null or empty).
bool isNullary() const {
return isNull() || isEmpty();
}
/// isUnary - Check if this is a unary twine.
/// Check if this is a unary twine.
bool isUnary() const {
return getRHSKind() == EmptyKind && !isNullary();
}
/// isBinary - Check if this is a binary twine.
/// Check if this is a binary twine.
bool isBinary() const {
return getLHSKind() != NullKind && getRHSKind() != EmptyKind;
}
/// isValid - Check if this is a valid twine (satisfying the invariants on
/// Check if this is a valid twine (satisfying the invariants on
/// order and number of arguments).
bool isValid() const {
// Nullary twines always have Empty on the RHS.
@ -235,16 +236,16 @@ namespace llvm {
return true;
}
/// getLHSKind - Get the NodeKind of the left-hand side.
/// Get the NodeKind of the left-hand side.
NodeKind getLHSKind() const { return LHSKind; }
/// getRHSKind - Get the NodeKind of the right-hand side.
/// Get the NodeKind of the right-hand side.
NodeKind getRHSKind() const { return RHSKind; }
/// printOneChild - Print one child from a twine.
/// Print one child from a twine.
void printOneChild(raw_ostream &OS, Child Ptr, NodeKind Kind) const;
/// printOneChildRepr - Print the representation of one child from a twine.
/// Print the representation of one child from a twine.
void printOneChildRepr(raw_ostream &OS, Child Ptr,
NodeKind Kind) const;
@ -257,6 +258,8 @@ namespace llvm {
assert(isValid() && "Invalid twine!");
}
Twine(const Twine &) = default;
/// Construct from a C string.
///
/// We take care here to optimize "" into the empty twine -- this will be
@ -287,6 +290,13 @@ namespace llvm {
assert(isValid() && "Invalid twine!");
}
/// Construct from a SmallString.
/*implicit*/ Twine(const SmallVectorImpl<char> &Str)
: LHSKind(SmallStringKind), RHSKind(EmptyKind) {
LHS.smallString = &Str;
assert(isValid() && "Invalid twine!");
}
/// Construct from a char.
explicit Twine(char Val)
: LHSKind(CharKind), RHSKind(EmptyKind) {
@ -347,18 +357,18 @@ namespace llvm {
// right thing. Yet.
/// Construct as the concatenation of a C string and a StringRef.
/*implicit*/ Twine(const char *_LHS, const StringRef &_RHS)
: LHSKind(CStringKind), RHSKind(StringRefKind) {
LHS.cString = _LHS;
RHS.stringRef = &_RHS;
/*implicit*/ Twine(const char *LHS, const StringRef &RHS)
: LHSKind(CStringKind), RHSKind(StringRefKind) {
this->LHS.cString = LHS;
this->RHS.stringRef = &RHS;
assert(isValid() && "Invalid twine!");
}
/// Construct as the concatenation of a StringRef and a C string.
/*implicit*/ Twine(const StringRef &_LHS, const char *_RHS)
: LHSKind(StringRefKind), RHSKind(CStringKind) {
LHS.stringRef = &_LHS;
RHS.cString = _RHS;
/*implicit*/ Twine(const StringRef &LHS, const char *RHS)
: LHSKind(StringRefKind), RHSKind(CStringKind) {
this->LHS.stringRef = &LHS;
this->RHS.cString = RHS;
assert(isValid() && "Invalid twine!");
}
@ -384,14 +394,14 @@ namespace llvm {
/// @name Predicate Operations
/// @{
/// isTriviallyEmpty - Check if this twine is trivially empty; a false
/// return value does not necessarily mean the twine is empty.
/// Check if this twine is trivially empty; a false return value does not
/// necessarily mean the twine is empty.
bool isTriviallyEmpty() const {
return isNullary();
}
/// isSingleStringRef - Return true if this twine can be dynamically
/// accessed as a single StringRef value with getSingleStringRef().
/// Return true if this twine can be dynamically accessed as a single
/// StringRef value with getSingleStringRef().
bool isSingleStringRef() const {
if (getRHSKind() != EmptyKind) return false;
@ -400,6 +410,7 @@ namespace llvm {
case CStringKind:
case StdStringKind:
case StringRefKind:
case SmallStringKind:
return true;
default:
return false;
@ -416,15 +427,14 @@ namespace llvm {
/// @name Output & Conversion.
/// @{
/// str - Return the twine contents as a std::string.
/// Return the twine contents as a std::string.
std::string str() const;
/// toVector - Write the concatenated string into the given SmallString or
/// SmallVector.
/// Append the concatenated string into the given SmallString or SmallVector.
void toVector(SmallVectorImpl<char> &Out) const;
/// getSingleStringRef - This returns the twine as a single StringRef. This
/// method is only valid if isSingleStringRef() is true.
/// This returns the twine as a single StringRef. This method is only valid
/// if isSingleStringRef() is true.
StringRef getSingleStringRef() const {
assert(isSingleStringRef() &&"This cannot be had as a single stringref!");
switch (getLHSKind()) {
@ -433,18 +443,24 @@ namespace llvm {
case CStringKind: return StringRef(LHS.cString);
case StdStringKind: return StringRef(*LHS.stdString);
case StringRefKind: return *LHS.stringRef;
case SmallStringKind:
return StringRef(LHS.smallString->data(), LHS.smallString->size());
}
}
/// toStringRef - This returns the twine as a single StringRef if it can be
/// This returns the twine as a single StringRef if it can be
/// represented as such. Otherwise the twine is written into the given
/// SmallVector and a StringRef to the SmallVector's data is returned.
StringRef toStringRef(SmallVectorImpl<char> &Out) const;
StringRef toStringRef(SmallVectorImpl<char> &Out) const {
if (isSingleStringRef())
return getSingleStringRef();
toVector(Out);
return StringRef(Out.data(), Out.size());
}
/// toNullTerminatedStringRef - This returns the twine as a single null
/// terminated StringRef if it can be represented as such. Otherwise the
/// twine is written into the given SmallVector and a StringRef to the
/// SmallVector's data is returned.
/// This returns the twine as a single null terminated StringRef if it
/// can be represented as such. Otherwise the twine is written into the
/// given SmallVector and a StringRef to the SmallVector's data is returned.
///
/// The returned StringRef's size does not include the null terminator.
StringRef toNullTerminatedStringRef(SmallVectorImpl<char> &Out) const;

View File

@ -50,7 +50,7 @@ unsigned ComputeEditDistance(ArrayRef<T> FromArray, ArrayRef<T> ToArray,
// http://en.wikipedia.org/wiki/Levenshtein_distance
//
// Although the algorithm is typically described using an m x n
// array, only two rows are used at a time, so this implemenation
// array, only two rows are used at a time, so this implementation
// just keeps two separate vectors for those two rows.
typename ArrayRef<T>::size_type m = FromArray.size();
typename ArrayRef<T>::size_type n = ToArray.size();

View File

@ -237,14 +237,14 @@ class ilist_iterator
// These are to catch errors when people try to use them as random access
// iterators.
template<typename T>
void operator-(int, ilist_iterator<T>) LLVM_DELETED_FUNCTION;
void operator-(int, ilist_iterator<T>) = delete;
template<typename T>
void operator-(ilist_iterator<T>,int) LLVM_DELETED_FUNCTION;
void operator-(ilist_iterator<T>,int) = delete;
template<typename T>
void operator+(int, ilist_iterator<T>) LLVM_DELETED_FUNCTION;
void operator+(int, ilist_iterator<T>) = delete;
template<typename T>
void operator+(ilist_iterator<T>,int) LLVM_DELETED_FUNCTION;
void operator+(ilist_iterator<T>,int) = delete;
// operator!=/operator== - Allow mixed comparisons without dereferencing
// the iterator, which could very likely be pointing to end().
@ -332,8 +332,8 @@ class iplist : public Traits {
// No fundamental reason why iplist can't be copyable, but the default
// copy/copy-assign won't do.
iplist(const iplist &) LLVM_DELETED_FUNCTION;
void operator=(const iplist &) LLVM_DELETED_FUNCTION;
iplist(const iplist &) = delete;
void operator=(const iplist &) = delete;
public:
typedef NodeTy *pointer;

View File

@ -150,7 +150,7 @@ class iterator_adaptor_base
protected:
WrappedIteratorT I;
iterator_adaptor_base() {}
iterator_adaptor_base() = default;
template <typename U>
explicit iterator_adaptor_base(
@ -231,7 +231,7 @@ struct pointee_iterator
pointee_iterator<WrappedIteratorT>, WrappedIteratorT,
typename std::iterator_traits<WrappedIteratorT>::iterator_category,
T> {
pointee_iterator() {}
pointee_iterator() = default;
template <typename U>
pointee_iterator(U &&u)
: pointee_iterator::iterator_adaptor_base(std::forward<U &&>(u)) {}

View File

@ -68,7 +68,7 @@ class AliasAnalysis {
/// typically called by the run* methods of these subclasses. This may be
/// called multiple times.
///
void InitializeAliasAnalysis(Pass *P);
void InitializeAliasAnalysis(Pass *P, const DataLayout *DL);
/// getAnalysisUsage - All alias analysis implementations should invoke this
/// directly (using AliasAnalysis::getAnalysisUsage(AU)).
@ -84,11 +84,6 @@ class AliasAnalysis {
/// know the sizes of the potential memory references.
static uint64_t const UnknownSize = ~UINT64_C(0);
/// getDataLayout - Return a pointer to the current DataLayout object, or
/// null if no DataLayout object is available.
///
const DataLayout *getDataLayout() const { return DL; }
/// getTargetLibraryInfo - Return a pointer to the current TargetLibraryInfo
/// object, or null if no TargetLibraryInfo object is available.
///
@ -139,6 +134,10 @@ class AliasAnalysis {
Copy.AATags = AAMDNodes();
return Copy;
}
bool operator==(const AliasAnalysis::Location &Other) const {
return Ptr == Other.Ptr && Size == Other.Size && AATags == Other.AATags;
}
};
/// getLocation - Fill in Loc with information about the memory reference by
@ -150,6 +149,19 @@ class AliasAnalysis {
Location getLocation(const AtomicRMWInst *RMWI);
static Location getLocationForSource(const MemTransferInst *MTI);
static Location getLocationForDest(const MemIntrinsic *MI);
Location getLocation(const Instruction *Inst) {
if (auto *I = dyn_cast<LoadInst>(Inst))
return getLocation(I);
else if (auto *I = dyn_cast<StoreInst>(Inst))
return getLocation(I);
else if (auto *I = dyn_cast<VAArgInst>(Inst))
return getLocation(I);
else if (auto *I = dyn_cast<AtomicCmpXchgInst>(Inst))
return getLocation(I);
else if (auto *I = dyn_cast<AtomicRMWInst>(Inst))
return getLocation(I);
llvm_unreachable("unsupported memory instruction");
}
/// Alias analysis result - Either we know for sure that it does not alias, we
/// know for sure it must alias, or we don't know anything: The two pointers
@ -357,6 +369,24 @@ class AliasAnalysis {
return (MRB & ModRef) && (MRB & ArgumentPointees);
}
/// getModRefInfo - Return information about whether or not an
/// instruction may read or write memory (without regard to a
/// specific location)
ModRefResult getModRefInfo(const Instruction *I) {
if (auto CS = ImmutableCallSite(I)) {
auto MRB = getModRefBehavior(CS);
if (MRB & ModRef)
return ModRef;
else if (MRB & Ref)
return Ref;
else if (MRB & Mod)
return Mod;
return NoModRef;
}
return getModRefInfo(I, Location());
}
/// getModRefInfo - Return information about whether or not an instruction may
/// read or write the specified memory location. An instruction
/// that doesn't read or write memory may be trivially LICM'd for example.
@ -477,6 +507,10 @@ class AliasAnalysis {
ModRefResult getModRefInfo(const VAArgInst* I, const Value* P, uint64_t Size){
return getModRefInfo(I, Location(P, Size));
}
/// getModRefInfo - Return information about whether a call and an instruction
/// may refer to the same memory locations.
ModRefResult getModRefInfo(Instruction *I,
ImmutableCallSite Call);
/// getModRefInfo - Return information about whether two call sites may refer
/// to the same set of memory locations. See
@ -585,9 +619,7 @@ struct DenseMapInfo<AliasAnalysis::Location> {
}
static bool isEqual(const AliasAnalysis::Location &LHS,
const AliasAnalysis::Location &RHS) {
return LHS.Ptr == RHS.Ptr &&
LHS.Size == RHS.Size &&
LHS.AATags == RHS.AATags;
return LHS == RHS;
}
};

View File

@ -192,11 +192,6 @@ class AliasSet : public ilist_node<AliasSet> {
}
bool operator!=(const iterator& x) const { return !operator==(x); }
const iterator &operator=(const iterator &I) {
CurNode = I.CurNode;
return *this;
}
value_type &operator*() const {
assert(CurNode && "Dereferencing AliasSet.end()!");
return *CurNode;
@ -226,8 +221,8 @@ class AliasSet : public ilist_node<AliasSet> {
AccessTy(NoModRef), AliasTy(MustAlias), Volatile(false) {
}
AliasSet(const AliasSet &AS) LLVM_DELETED_FUNCTION;
void operator=(const AliasSet &AS) LLVM_DELETED_FUNCTION;
AliasSet(const AliasSet &AS) = delete;
void operator=(const AliasSet &AS) = delete;
PointerRec *getSomePointer() const {
return PtrList;
@ -273,7 +268,7 @@ class AliasSet : public ilist_node<AliasSet> {
///
bool aliasesPointer(const Value *Ptr, uint64_t Size, const AAMDNodes &AAInfo,
AliasAnalysis &AA) const;
bool aliasesUnknownInst(Instruction *Inst, AliasAnalysis &AA) const;
bool aliasesUnknownInst(const Instruction *Inst, AliasAnalysis &AA) const;
};
inline raw_ostream& operator<<(raw_ostream &OS, const AliasSet &AS) {
@ -363,7 +358,7 @@ class AliasSetTracker {
/// getAliasSetForPointerIfExists - Return the alias set containing the
/// location specified if one exists, otherwise return null.
AliasSet *getAliasSetForPointerIfExists(Value *P, uint64_t Size,
AliasSet *getAliasSetForPointerIfExists(const Value *P, uint64_t Size,
const AAMDNodes &AAInfo) {
return findAliasSetForPointer(P, Size, AAInfo);
}
@ -371,11 +366,12 @@ class AliasSetTracker {
/// containsPointer - Return true if the specified location is represented by
/// this alias set, false otherwise. This does not modify the AST object or
/// alias sets.
bool containsPointer(Value *P, uint64_t Size, const AAMDNodes &AAInfo) const;
bool containsPointer(const Value *P, uint64_t Size,
const AAMDNodes &AAInfo) const;
/// Return true if the specified instruction "may" (or must) alias one of the
/// members in any of the sets.
bool containsUnknown(Instruction *I) const;
bool containsUnknown(const Instruction *I) const;
/// getAliasAnalysis - Return the underlying alias analysis object used by
/// this tracker.

View File

@ -27,6 +27,11 @@
namespace llvm {
// FIXME: Replace this brittle forward declaration with the include of the new
// PassManager.h when doing so doesn't break the PassManagerBuilder.
template <typename IRUnitT> class AnalysisManager;
class PreservedAnalyses;
/// \brief A cache of @llvm.assume calls within a function.
///
/// This cache provides fast lookup of assumptions within a function by caching
@ -88,6 +93,42 @@ class AssumptionCache {
}
};
/// \brief A function analysis which provides an \c AssumptionCache.
///
/// This analysis is intended for use with the new pass manager and will vend
/// assumption caches for a given function.
class AssumptionAnalysis {
static char PassID;
public:
typedef AssumptionCache Result;
/// \brief Opaque, unique identifier for this analysis pass.
static void *ID() { return (void *)&PassID; }
/// \brief Provide a name for the analysis for debugging and logging.
static StringRef name() { return "AssumptionAnalysis"; }
AssumptionAnalysis() {}
AssumptionAnalysis(const AssumptionAnalysis &Arg) {}
AssumptionAnalysis(AssumptionAnalysis &&Arg) {}
AssumptionAnalysis &operator=(const AssumptionAnalysis &RHS) { return *this; }
AssumptionAnalysis &operator=(AssumptionAnalysis &&RHS) { return *this; }
AssumptionCache run(Function &F) { return AssumptionCache(F); }
};
/// \brief Printer pass for the \c AssumptionAnalysis results.
class AssumptionPrinterPass {
raw_ostream &OS;
public:
explicit AssumptionPrinterPass(raw_ostream &OS) : OS(OS) {}
PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM);
static StringRef name() { return "AssumptionPrinterPass"; }
};
/// \brief An immutable pass that tracks lazily created \c AssumptionCache
/// objects.
///
@ -124,7 +165,7 @@ class AssumptionCacheTracker : public ImmutablePass {
AssumptionCache &getAssumptionCache(Function &F);
AssumptionCacheTracker();
~AssumptionCacheTracker();
~AssumptionCacheTracker() override;
void releaseMemory() override { AssumptionCaches.shrink_and_clear(); }

View File

@ -34,7 +34,7 @@ class BlockFrequencyInfo : public FunctionPass {
BlockFrequencyInfo();
~BlockFrequencyInfo();
~BlockFrequencyInfo() override;
void getAnalysisUsage(AnalysisUsage &AU) const override;

View File

@ -718,9 +718,6 @@ void IrreducibleGraph::addEdges(const BlockNode &Node,
///
/// It has some known flaws.
///
/// - Loop scale is limited to 4096 per loop (2^12) to avoid exhausting
/// BlockFrequency's 64-bit integer precision.
///
/// - The model of irreducible control flow is a rough approximation.
///
/// Modelling irreducible control flow exactly involves setting up and

View File

@ -263,8 +263,7 @@ template <typename CGSCCPassT> class ModuleToPostOrderCGSCCPassAdaptor {
template <typename CGSCCPassT>
ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>
createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass) {
return std::move(
ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>(std::move(Pass)));
return ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>(std::move(Pass));
}
/// \brief A CGSCC analysis which acts as a proxy for a function analysis
@ -484,7 +483,7 @@ template <typename FunctionPassT> class CGSCCToFunctionPassAdaptor {
template <typename FunctionPassT>
CGSCCToFunctionPassAdaptor<FunctionPassT>
createCGSCCToFunctionPassAdaptor(FunctionPassT Pass) {
return std::move(CGSCCToFunctionPassAdaptor<FunctionPassT>(std::move(Pass)));
return CGSCCToFunctionPassAdaptor<FunctionPassT>(std::move(Pass));
}
}

View File

@ -273,8 +273,8 @@ class CallGraphNode {
/// CalledFunctions array of this or other CallGraphNodes.
unsigned NumReferences;
CallGraphNode(const CallGraphNode &) LLVM_DELETED_FUNCTION;
void operator=(const CallGraphNode &) LLVM_DELETED_FUNCTION;
CallGraphNode(const CallGraphNode &) = delete;
void operator=(const CallGraphNode &) = delete;
void DropRef() { --NumReferences; }
void AddRef() { ++NumReferences; }
@ -318,7 +318,7 @@ class CallGraphWrapperPass : public ModulePass {
static char ID; // Class identification, replacement for typeinfo
CallGraphWrapperPass();
virtual ~CallGraphWrapperPass();
~CallGraphWrapperPass() override;
/// \brief The internal \c CallGraph around which the rest of this interface
/// is wrapped.

View File

@ -36,16 +36,15 @@ namespace llvm {
/// Note that this fails if not all of the operands are constant. Otherwise,
/// this function can only fail when attempting to fold instructions like loads
/// and stores, which have no constant expression form.
Constant *ConstantFoldInstruction(Instruction *I,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr);
Constant *ConstantFoldInstruction(Instruction *I, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr);
/// ConstantFoldConstantExpression - Attempt to fold the constant expression
/// using the specified DataLayout. If successful, the constant result is
/// result is returned, if not, null is returned.
Constant *ConstantFoldConstantExpression(const ConstantExpr *CE,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI =nullptr);
Constant *
ConstantFoldConstantExpression(const ConstantExpr *CE, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr);
/// ConstantFoldInstOperands - Attempt to constant fold an instruction with the
/// specified operands. If successful, the constant result is returned, if not,
@ -53,19 +52,19 @@ Constant *ConstantFoldConstantExpression(const ConstantExpr *CE,
/// fold instructions like loads and stores, which have no constant expression
/// form.
///
Constant *ConstantFoldInstOperands(unsigned Opcode, Type *DestTy,
ArrayRef<Constant *> Ops,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr);
Constant *ConstantFoldInstOperands(unsigned Opcode, Type *DestTy,
ArrayRef<Constant *> Ops,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr);
/// ConstantFoldCompareInstOperands - Attempt to constant fold a compare
/// instruction (icmp/fcmp) with the specified operands. If it fails, it
/// returns a constant expression of the specified operands.
///
Constant *ConstantFoldCompareInstOperands(unsigned Predicate,
Constant *LHS, Constant *RHS,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI=nullptr);
Constant *
ConstantFoldCompareInstOperands(unsigned Predicate, Constant *LHS,
Constant *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr);
/// ConstantFoldInsertValueInstruction - Attempt to constant fold an insertvalue
/// instruction with the specified operands and indices. The constant result is
@ -76,8 +75,7 @@ Constant *ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val,
/// ConstantFoldLoadFromConstPtr - Return the value that a load from C would
/// produce if it is constant and determinable. If this is not determinable,
/// return null.
Constant *ConstantFoldLoadFromConstPtr(Constant *C,
const DataLayout *TD = nullptr);
Constant *ConstantFoldLoadFromConstPtr(Constant *C, const DataLayout &DL);
/// ConstantFoldLoadThroughGEPConstantExpr - Given a constant and a
/// getelementptr constantexpr, return the constant value being addressed by the

View File

@ -1,93 +0,0 @@
//==- llvm/Analysis/ConstantsScanner.h - Iterate over constants -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This class implements an iterator to walk through the constants referenced by
// a method. This is used by the Bitcode & Assembly writers to build constant
// pools.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_CONSTANTSSCANNER_H
#define LLVM_ANALYSIS_CONSTANTSSCANNER_H
#include "llvm/IR/InstIterator.h"
namespace llvm {
class Constant;
class constant_iterator : public std::iterator<std::forward_iterator_tag,
const Constant, ptrdiff_t> {
const_inst_iterator InstI; // Method instruction iterator
unsigned OpIdx; // Operand index
typedef constant_iterator _Self;
inline bool isAtConstant() const {
assert(!InstI.atEnd() && OpIdx < InstI->getNumOperands() &&
"isAtConstant called with invalid arguments!");
return isa<Constant>(InstI->getOperand(OpIdx));
}
public:
inline constant_iterator(const Function *F) : InstI(inst_begin(F)), OpIdx(0) {
// Advance to first constant... if we are not already at constant or end
if (InstI != inst_end(F) && // InstI is valid?
(InstI->getNumOperands() == 0 || !isAtConstant())) // Not at constant?
operator++();
}
inline constant_iterator(const Function *F, bool) // end ctor
: InstI(inst_end(F)), OpIdx(0) {
}
inline bool operator==(const _Self& x) const { return OpIdx == x.OpIdx &&
InstI == x.InstI; }
inline bool operator!=(const _Self& x) const { return !operator==(x); }
inline pointer operator*() const {
assert(isAtConstant() && "Dereferenced an iterator at the end!");
return cast<Constant>(InstI->getOperand(OpIdx));
}
inline pointer operator->() const { return operator*(); }
inline _Self& operator++() { // Preincrement implementation
++OpIdx;
do {
unsigned NumOperands = InstI->getNumOperands();
while (OpIdx < NumOperands && !isAtConstant()) {
++OpIdx;
}
if (OpIdx < NumOperands) return *this; // Found a constant!
++InstI;
OpIdx = 0;
} while (!InstI.atEnd());
return *this; // At the end of the method
}
inline _Self operator++(int) { // Postincrement
_Self tmp = *this; ++*this; return tmp;
}
inline bool atEnd() const { return InstI.atEnd(); }
};
inline constant_iterator constant_begin(const Function *F) {
return constant_iterator(F);
}
inline constant_iterator constant_end(const Function *F) {
return constant_iterator(F, true);
}
} // End llvm namespace
#endif

View File

@ -217,13 +217,9 @@ namespace llvm {
/// input dependences are unordered.
class FullDependence : public Dependence {
public:
FullDependence(Instruction *Src,
Instruction *Dst,
bool LoopIndependent,
FullDependence(Instruction *Src, Instruction *Dst, bool LoopIndependent,
unsigned Levels);
~FullDependence() {
delete[] DV;
}
~FullDependence() override { delete[] DV; }
/// isLoopIndependent - Returns true if this is a loop-independent
/// dependence.
@ -266,6 +262,7 @@ namespace llvm {
/// if no subscript in the source or destination mention the induction
/// variable associated with the loop at this level.
bool isScalar(unsigned Level) const override;
private:
unsigned short Levels;
bool LoopIndependent;
@ -278,8 +275,8 @@ namespace llvm {
/// DependenceAnalysis - This class is the main dependence-analysis driver.
///
class DependenceAnalysis : public FunctionPass {
void operator=(const DependenceAnalysis &) LLVM_DELETED_FUNCTION;
DependenceAnalysis(const DependenceAnalysis &) LLVM_DELETED_FUNCTION;
void operator=(const DependenceAnalysis &) = delete;
DependenceAnalysis(const DependenceAnalysis &) = delete;
public:
/// depends - Tests for a dependence between the Src and Dst instructions.
/// Returns NULL if no dependence; otherwise, returns a Dependence (or a

View File

@ -19,11 +19,12 @@
#define LLVM_ANALYSIS_DOMINANCEFRONTIERIMPL_H
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/DominanceFrontier.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/GenericDomTree.h"
namespace llvm {
namespace {
template <class BlockT>
class DFCalculateWorkObject {
public:
@ -37,7 +38,6 @@ class DFCalculateWorkObject {
const DomTreeNodeT *Node;
const DomTreeNodeT *parentNode;
};
}
template <class BlockT>
void DominanceFrontierBase<BlockT>::removeBlock(BlockT *BB) {

View File

@ -1,49 +0,0 @@
//===- llvm/Analysis/FunctionTargetTransformInfo.h --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass wraps a TargetTransformInfo in a FunctionPass so that it can
// forward along the current Function so that we can make target specific
// decisions based on the particular subtarget specified for each Function.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_FUNCTIONTARGETTRANSFORMINFO_H
#define LLVM_ANALYSIS_FUNCTIONTARGETTRANSFORMINFO_H
#include "TargetTransformInfo.h"
#include "llvm/Pass.h"
namespace llvm {
class FunctionTargetTransformInfo final : public FunctionPass {
private:
const Function *Fn;
const TargetTransformInfo *TTI;
FunctionTargetTransformInfo(const FunctionTargetTransformInfo &)
LLVM_DELETED_FUNCTION;
void operator=(const FunctionTargetTransformInfo &) LLVM_DELETED_FUNCTION;
public:
static char ID;
FunctionTargetTransformInfo();
// Implementation boilerplate.
void getAnalysisUsage(AnalysisUsage &AU) const override;
void releaseMemory() override;
bool runOnFunction(Function &F) override;
// Shimmed functions from TargetTransformInfo.
void
getUnrollingPreferences(Loop *L,
TargetTransformInfo::UnrollingPreferences &UP) const {
TTI->getUnrollingPreferences(Fn, L, UP);
}
};
}
#endif

View File

@ -122,7 +122,6 @@ class IVUsers : public LoopPass {
LoopInfo *LI;
DominatorTree *DT;
ScalarEvolution *SE;
const DataLayout *DL;
SmallPtrSet<Instruction*,16> Processed;
/// IVUses - A list of all tracked IV uses of induction variable expressions

View File

@ -23,7 +23,7 @@ class AssumptionCacheTracker;
class CallSite;
class DataLayout;
class Function;
class TargetTransformInfo;
class TargetTransformInfoWrapperPass;
namespace InlineConstants {
// Various magic constants used to adjust heuristics.
@ -77,7 +77,7 @@ class InlineCost {
}
/// \brief Test whether the inline cost is low enough for inlining.
LLVM_EXPLICIT operator bool() const {
explicit operator bool() const {
return Cost < Threshold;
}
@ -100,14 +100,14 @@ class InlineCost {
/// \brief Cost analyzer used by inliner.
class InlineCostAnalysis : public CallGraphSCCPass {
const TargetTransformInfo *TTI;
TargetTransformInfoWrapperPass *TTIWP;
AssumptionCacheTracker *ACT;
public:
static char ID;
InlineCostAnalysis();
~InlineCostAnalysis();
~InlineCostAnalysis() override;
// Pass interface implementation.
void getAnalysisUsage(AnalysisUsage &AU) const override;

View File

@ -49,7 +49,7 @@ namespace llvm {
/// SimplifyAddInst - Given operands for an Add, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyAddInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW,
const DataLayout *TD = nullptr,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@ -58,7 +58,7 @@ namespace llvm {
/// SimplifySubInst - Given operands for a Sub, see if we can
/// fold the result. If not, this returns null.
Value *SimplifySubInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW,
const DataLayout *TD = nullptr,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@ -67,7 +67,7 @@ namespace llvm {
/// Given operands for an FAdd, see if we can fold the result. If not, this
/// returns null.
Value *SimplifyFAddInst(Value *LHS, Value *RHS, FastMathFlags FMF,
const DataLayout *TD = nullptr,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@ -76,7 +76,7 @@ namespace llvm {
/// Given operands for an FSub, see if we can fold the result. If not, this
/// returns null.
Value *SimplifyFSubInst(Value *LHS, Value *RHS, FastMathFlags FMF,
const DataLayout *TD = nullptr,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@ -85,7 +85,7 @@ namespace llvm {
/// Given operands for an FMul, see if we can fold the result. If not, this
/// returns null.
Value *SimplifyFMulInst(Value *LHS, Value *RHS, FastMathFlags FMF,
const DataLayout *TD = nullptr,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@ -93,7 +93,7 @@ namespace llvm {
/// SimplifyMulInst - Given operands for a Mul, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyMulInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr,
Value *SimplifyMulInst(Value *LHS, Value *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@ -101,8 +101,7 @@ namespace llvm {
/// SimplifySDivInst - Given operands for an SDiv, see if we can
/// fold the result. If not, this returns null.
Value *SimplifySDivInst(Value *LHS, Value *RHS,
const DataLayout *TD = nullptr,
Value *SimplifySDivInst(Value *LHS, Value *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@ -110,8 +109,7 @@ namespace llvm {
/// SimplifyUDivInst - Given operands for a UDiv, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyUDivInst(Value *LHS, Value *RHS,
const DataLayout *TD = nullptr,
Value *SimplifyUDivInst(Value *LHS, Value *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@ -119,8 +117,8 @@ namespace llvm {
/// SimplifyFDivInst - Given operands for an FDiv, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyFDivInst(Value *LHS, Value *RHS,
const DataLayout *TD = nullptr,
Value *SimplifyFDivInst(Value *LHS, Value *RHS, FastMathFlags FMF,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@ -128,8 +126,7 @@ namespace llvm {
/// SimplifySRemInst - Given operands for an SRem, see if we can
/// fold the result. If not, this returns null.
Value *SimplifySRemInst(Value *LHS, Value *RHS,
const DataLayout *TD = nullptr,
Value *SimplifySRemInst(Value *LHS, Value *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@ -137,8 +134,7 @@ namespace llvm {
/// SimplifyURemInst - Given operands for a URem, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyURemInst(Value *LHS, Value *RHS,
const DataLayout *TD = nullptr,
Value *SimplifyURemInst(Value *LHS, Value *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@ -146,8 +142,8 @@ namespace llvm {
/// SimplifyFRemInst - Given operands for an FRem, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyFRemInst(Value *LHS, Value *RHS,
const DataLayout *TD = nullptr,
Value *SimplifyFRemInst(Value *LHS, Value *RHS, FastMathFlags FMF,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@ -156,7 +152,7 @@ namespace llvm {
/// SimplifyShlInst - Given operands for a Shl, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
const DataLayout *TD = nullptr,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@ -165,7 +161,7 @@ namespace llvm {
/// SimplifyLShrInst - Given operands for a LShr, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact,
const DataLayout *TD = nullptr,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@ -174,7 +170,7 @@ namespace llvm {
/// SimplifyAShrInst - Given operands for a AShr, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact,
const DataLayout *TD = nullptr,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@ -182,7 +178,7 @@ namespace llvm {
/// SimplifyAndInst - Given operands for an And, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyAndInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr,
Value *SimplifyAndInst(Value *LHS, Value *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@ -190,7 +186,7 @@ namespace llvm {
/// SimplifyOrInst - Given operands for an Or, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyOrInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr,
Value *SimplifyOrInst(Value *LHS, Value *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@ -198,7 +194,7 @@ namespace llvm {
/// SimplifyXorInst - Given operands for a Xor, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyXorInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr,
Value *SimplifyXorInst(Value *LHS, Value *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@ -207,7 +203,7 @@ namespace llvm {
/// SimplifyICmpInst - Given operands for an ICmpInst, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
const DataLayout *TD = nullptr,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@ -216,7 +212,7 @@ namespace llvm {
/// SimplifyFCmpInst - Given operands for an FCmpInst, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
const DataLayout *TD = nullptr,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@ -225,7 +221,7 @@ namespace llvm {
/// SimplifySelectInst - Given operands for a SelectInst, see if we can fold
/// the result. If not, this returns null.
Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
const DataLayout *TD = nullptr,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@ -233,7 +229,7 @@ namespace llvm {
/// SimplifyGEPInst - Given operands for an GetElementPtrInst, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyGEPInst(ArrayRef<Value *> Ops, const DataLayout *TD = nullptr,
Value *SimplifyGEPInst(ArrayRef<Value *> Ops, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@ -242,8 +238,7 @@ namespace llvm {
/// SimplifyInsertValueInst - Given operands for an InsertValueInst, see if we
/// can fold the result. If not, this returns null.
Value *SimplifyInsertValueInst(Value *Agg, Value *Val,
ArrayRef<unsigned> Idxs,
const DataLayout *TD = nullptr,
ArrayRef<unsigned> Idxs, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@ -251,7 +246,7 @@ namespace llvm {
/// SimplifyTruncInst - Given operands for an TruncInst, see if we can fold
/// the result. If not, this returns null.
Value *SimplifyTruncInst(Value *Op, Type *Ty, const DataLayout *TD = nullptr,
Value *SimplifyTruncInst(Value *Op, Type *Ty, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@ -263,7 +258,7 @@ namespace llvm {
/// SimplifyCmpInst - Given operands for a CmpInst, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
const DataLayout *TD = nullptr,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@ -272,18 +267,28 @@ namespace llvm {
/// SimplifyBinOp - Given operands for a BinaryOperator, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS,
const DataLayout *TD = nullptr,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// SimplifyFPBinOp - Given operands for a BinaryOperator, see if we can
/// fold the result. If not, this returns null.
/// In contrast to SimplifyBinOp, try to use FastMathFlag when folding the
/// result. In case we don't need FastMathFlags, simply fall to SimplifyBinOp.
Value *SimplifyFPBinOp(unsigned Opcode, Value *LHS, Value *RHS,
const FastMathFlags &FMF, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// \brief Given a function and iterators over arguments, see if we can fold
/// the result.
///
/// If this call could not be simplified returns null.
Value *SimplifyCall(Value *V, User::op_iterator ArgBegin,
User::op_iterator ArgEnd, const DataLayout *TD = nullptr,
User::op_iterator ArgEnd, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@ -293,8 +298,7 @@ namespace llvm {
/// result.
///
/// If this call could not be simplified returns null.
Value *SimplifyCall(Value *V, ArrayRef<Value *> Args,
const DataLayout *TD = nullptr,
Value *SimplifyCall(Value *V, ArrayRef<Value *> Args, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@ -302,7 +306,7 @@ namespace llvm {
/// SimplifyInstruction - See if we can compute a simplified version of this
/// instruction. If not, this returns null.
Value *SimplifyInstruction(Instruction *I, const DataLayout *TD = nullptr,
Value *SimplifyInstruction(Instruction *I, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr);
@ -316,7 +320,6 @@ namespace llvm {
///
/// The function returns true if any simplifications were performed.
bool replaceAndRecursivelySimplify(Instruction *I, Value *SimpleV,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr);
@ -328,7 +331,6 @@ namespace llvm {
/// of the users impacted. It returns true if any simplifications were
/// performed.
bool recursivelySimplifyInstruction(Instruction *I,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr);

View File

@ -78,7 +78,7 @@ inline void addNodeToInterval(Interval *Int, BasicBlock *BB) {
//
inline void addNodeToInterval(Interval *Int, Interval *I) {
// Add all of the nodes in I as new nodes in Int.
copy(I->Nodes.begin(), I->Nodes.end(), back_inserter(Int->Nodes));
Int->Nodes.insert(Int->Nodes.end(), I->Nodes.begin(), I->Nodes.end());
}
@ -94,7 +94,6 @@ class IntervalIterator {
bool IOwnMem; // If True, delete intervals when done with them
// See file header for conditions of use
public:
typedef IntervalIterator<NodeTy, OrigContainer_t> _Self;
typedef std::forward_iterator_tag iterator_category;
IntervalIterator() {} // End iterator, empty stack
@ -105,6 +104,12 @@ class IntervalIterator {
}
}
IntervalIterator(IntervalIterator &&x)
: IntStack(std::move(x.IntStack)), Visited(std::move(x.Visited)),
OrigContainer(x.OrigContainer), IOwnMem(x.IOwnMem) {
x.IOwnMem = false;
}
IntervalIterator(IntervalPartition &IP, bool OwnMemory) : IOwnMem(OwnMemory) {
OrigContainer = &IP;
if (!ProcessInterval(IP.getRootInterval())) {
@ -112,7 +117,7 @@ class IntervalIterator {
}
}
inline ~IntervalIterator() {
~IntervalIterator() {
if (IOwnMem)
while (!IntStack.empty()) {
delete operator*();
@ -120,15 +125,17 @@ class IntervalIterator {
}
}
inline bool operator==(const _Self& x) const { return IntStack == x.IntStack;}
inline bool operator!=(const _Self& x) const { return !operator==(x); }
bool operator==(const IntervalIterator &x) const {
return IntStack == x.IntStack;
}
bool operator!=(const IntervalIterator &x) const { return !(*this == x); }
inline const Interval *operator*() const { return IntStack.back().first; }
inline Interval *operator*() { return IntStack.back().first; }
inline const Interval *operator->() const { return operator*(); }
inline Interval *operator->() { return operator*(); }
const Interval *operator*() const { return IntStack.back().first; }
Interval *operator*() { return IntStack.back().first; }
const Interval *operator->() const { return operator*(); }
Interval *operator->() { return operator*(); }
_Self& operator++() { // Preincrement
IntervalIterator &operator++() { // Preincrement
assert(!IntStack.empty() && "Attempting to use interval iterator at end!");
do {
// All of the intervals on the stack have been visited. Try visiting
@ -150,8 +157,10 @@ class IntervalIterator {
return *this;
}
inline _Self operator++(int) { // Postincrement
_Self tmp = *this; ++*this; return tmp;
IntervalIterator operator++(int) { // Postincrement
IntervalIterator tmp = *this;
++*this;
return tmp;
}
private:

View File

@ -0,0 +1,96 @@
//===- IteratedDominanceFrontier.h - Calculate IDF --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
/// \brief Compute iterated dominance frontiers using a linear time algorithm.
///
/// The algorithm used here is based on:
///
/// Sreedhar and Gao. A linear time algorithm for placing phi-nodes.
/// In Proceedings of the 22nd ACM SIGPLAN-SIGACT Symposium on Principles of
/// Programming Languages
/// POPL '95. ACM, New York, NY, 62-73.
///
/// It has been modified to not explicitly use the DJ graph data structure and
/// to directly compute pruned SSA using per-variable liveness information.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_IDF_H
#define LLVM_ANALYSIS_IDF_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
namespace llvm {
class BasicBlock;
template <class T> class DomTreeNodeBase;
typedef DomTreeNodeBase<BasicBlock> DomTreeNode;
class DominatorTree;
/// \brief Determine the iterated dominance frontier, given a set of defining
/// blocks, and optionally, a set of live-in blocks.
///
/// In turn, the results can be used to place phi nodes.
///
/// This algorithm is a linear time computation of Iterated Dominance Frontiers,
/// pruned using the live-in set.
/// By default, liveness is not used to prune the IDF computation.
class IDFCalculator {
public:
IDFCalculator(DominatorTree &DT) : DT(DT), useLiveIn(false) {}
/// \brief Give the IDF calculator the set of blocks in which the value is
/// defined. This is equivalent to the set of starting blocks it should be
/// calculating the IDF for (though later gets pruned based on liveness).
///
/// Note: This set *must* live for the entire lifetime of the IDF calculator.
void setDefiningBlocks(const SmallPtrSetImpl<BasicBlock *> &Blocks) {
DefBlocks = &Blocks;
}
/// \brief Give the IDF calculator the set of blocks in which the value is
/// live on entry to the block. This is used to prune the IDF calculation to
/// not include blocks where any phi insertion would be dead.
///
/// Note: This set *must* live for the entire lifetime of the IDF calculator.
void setLiveInBlocks(const SmallPtrSetImpl<BasicBlock *> &Blocks) {
LiveInBlocks = &Blocks;
useLiveIn = true;
}
/// \brief Reset the live-in block set to be empty, and tell the IDF
/// calculator to not use liveness anymore.
void resetLiveInBlocks() {
LiveInBlocks = nullptr;
useLiveIn = false;
}
/// \brief Calculate iterated dominance frontiers
///
/// This uses the linear-time phi algorithm based on DJ-graphs mentioned in
/// the file-level comment. It performs DF->IDF pruning using the live-in
/// set, to avoid computing the IDF for blocks where an inserted PHI node
/// would be dead.
void calculate(SmallVectorImpl<BasicBlock *> &IDFBlocks);
private:
DominatorTree &DT;
bool useLiveIn;
DenseMap<DomTreeNode *, unsigned> DomLevels;
const SmallPtrSetImpl<BasicBlock *> *LiveInBlocks;
const SmallPtrSetImpl<BasicBlock *> *DefBlocks;
SmallVector<BasicBlock *, 32> PHIBlocks;
};
}
#endif

View File

@ -39,7 +39,7 @@ class JumpInstrTableInfo : public ImmutablePass {
/// The default byte alignment for jump tables is 16, which is large but
/// usually safe.
JumpInstrTableInfo(uint64_t ByteAlign = 16);
virtual ~JumpInstrTableInfo();
~JumpInstrTableInfo() override;
const char *getPassName() const override {
return "Jump-Instruction Table Info";
}

View File

@ -29,18 +29,17 @@ namespace llvm {
/// This pass computes, caches, and vends lazy value constraint information.
class LazyValueInfo : public FunctionPass {
AssumptionCache *AC;
const DataLayout *DL;
class TargetLibraryInfo *TLI;
DominatorTree *DT;
void *PImpl;
LazyValueInfo(const LazyValueInfo&) LLVM_DELETED_FUNCTION;
void operator=(const LazyValueInfo&) LLVM_DELETED_FUNCTION;
LazyValueInfo(const LazyValueInfo&) = delete;
void operator=(const LazyValueInfo&) = delete;
public:
static char ID;
LazyValueInfo() : FunctionPass(ID), PImpl(nullptr) {
initializeLazyValueInfoPass(*PassRegistry::getPassRegistry());
}
~LazyValueInfo() { assert(!PImpl && "releaseMemory not called"); }
~LazyValueInfo() override { assert(!PImpl && "releaseMemory not called"); }
/// This is used to return true/false/dunno results.
enum Tristate {

View File

@ -15,6 +15,7 @@
#define LLVM_ANALYSIS_LIBCALLALIASANALYSIS_H
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
namespace llvm {
@ -35,8 +36,8 @@ namespace llvm {
: FunctionPass(ID), LCI(LC) {
initializeLibCallAliasAnalysisPass(*PassRegistry::getPassRegistry());
}
~LibCallAliasAnalysis();
~LibCallAliasAnalysis() override;
ModRefResult getModRefInfo(ImmutableCallSite CS,
const Location &Loc) override;
@ -48,11 +49,8 @@ namespace llvm {
void getAnalysisUsage(AnalysisUsage &AU) const override;
bool runOnFunction(Function &F) override {
InitializeAliasAnalysis(this); // set up super class
return false;
}
bool runOnFunction(Function &F) override;
/// getAdjustedAnalysisPointer - This method is used when a pass implements
/// an analysis interface through multiple inheritance. If needed, it
/// should override this to adjust the this pointer as needed for the

View File

@ -18,6 +18,7 @@
#include "llvm/Analysis/AliasAnalysis.h"
namespace llvm {
class InvokeInst;
/// LibCallLocationInfo - This struct describes a set of memory locations that
/// are accessed by libcalls. Identification of a location is doing with a
@ -162,6 +163,52 @@ namespace llvm {
virtual const LibCallFunctionInfo *getFunctionInfoArray() const = 0;
};
enum class EHPersonality {
Unknown,
GNU_Ada,
GNU_C,
GNU_CXX,
GNU_ObjC,
MSVC_X86SEH,
MSVC_Win64SEH,
MSVC_CXX,
};
/// \brief See if the given exception handling personality function is one
/// that we understand. If so, return a description of it; otherwise return
/// Unknown.
EHPersonality classifyEHPersonality(const Value *Pers);
/// \brief Returns true if this personality function catches asynchronous
/// exceptions.
inline bool isAsynchronousEHPersonality(EHPersonality Pers) {
// The two SEH personality functions can catch asynch exceptions. We assume
// unknown personalities don't catch asynch exceptions.
switch (Pers) {
case EHPersonality::MSVC_X86SEH:
case EHPersonality::MSVC_Win64SEH:
return true;
default: return false;
}
llvm_unreachable("invalid enum");
}
/// \brief Returns true if this is an MSVC personality function.
inline bool isMSVCEHPersonality(EHPersonality Pers) {
// The two SEH personality functions can catch asynch exceptions. We assume
// unknown personalities don't catch asynch exceptions.
switch (Pers) {
case EHPersonality::MSVC_CXX:
case EHPersonality::MSVC_X86SEH:
case EHPersonality::MSVC_Win64SEH:
return true;
default: return false;
}
llvm_unreachable("invalid enum");
}
bool canSimplifyInvokeNoUnwind(const InvokeInst *II);
} // end namespace llvm
#endif

View File

@ -27,8 +27,7 @@ class MDNode;
/// specified pointer, we do a quick local scan of the basic block containing
/// ScanFrom, to determine if the address is already accessed.
bool isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom,
unsigned Align,
const DataLayout *TD = nullptr);
unsigned Align);
/// FindAvailableLoadedValue - Scan the ScanBB block backwards (starting at
/// the instruction before ScanFrom) checking to see if we have the value at

View File

@ -0,0 +1,552 @@
//===- llvm/Analysis/LoopAccessAnalysis.h -----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the interface for the loop memory dependence framework that
// was originally developed for the Loop Vectorizer.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_LOOPACCESSANALYSIS_H
#define LLVM_ANALYSIS_LOOPACCESSANALYSIS_H
#include "llvm/ADT/EquivalenceClasses.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/AliasSetTracker.h"
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
namespace llvm {
class Value;
class DataLayout;
class AliasAnalysis;
class ScalarEvolution;
class Loop;
class SCEV;
/// Optimization analysis message produced during vectorization. Messages inform
/// the user why vectorization did not occur.
class LoopAccessReport {
std::string Message;
const Instruction *Instr;
protected:
LoopAccessReport(const Twine &Message, const Instruction *I)
: Message(Message.str()), Instr(I) {}
public:
LoopAccessReport(const Instruction *I = nullptr) : Instr(I) {}
template <typename A> LoopAccessReport &operator<<(const A &Value) {
raw_string_ostream Out(Message);
Out << Value;
return *this;
}
const Instruction *getInstr() const { return Instr; }
std::string &str() { return Message; }
const std::string &str() const { return Message; }
operator Twine() { return Message; }
/// \brief Emit an analysis note for \p PassName with the debug location from
/// the instruction in \p Message if available. Otherwise use the location of
/// \p TheLoop.
static void emitAnalysis(const LoopAccessReport &Message,
const Function *TheFunction,
const Loop *TheLoop,
const char *PassName);
};
/// \brief Collection of parameters shared beetween the Loop Vectorizer and the
/// Loop Access Analysis.
struct VectorizerParams {
/// \brief Maximum SIMD width.
static const unsigned MaxVectorWidth;
/// \brief VF as overridden by the user.
static unsigned VectorizationFactor;
/// \brief Interleave factor as overridden by the user.
static unsigned VectorizationInterleave;
/// \brief True if force-vector-interleave was specified by the user.
static bool isInterleaveForced();
/// \\brief When performing memory disambiguation checks at runtime do not
/// make more than this number of comparisons.
static unsigned RuntimeMemoryCheckThreshold;
};
/// \brief Checks memory dependences among accesses to the same underlying
/// object to determine whether there vectorization is legal or not (and at
/// which vectorization factor).
///
/// Note: This class will compute a conservative dependence for access to
/// different underlying pointers. Clients, such as the loop vectorizer, will
/// sometimes deal these potential dependencies by emitting runtime checks.
///
/// We use the ScalarEvolution framework to symbolically evalutate access
/// functions pairs. Since we currently don't restructure the loop we can rely
/// on the program order of memory accesses to determine their safety.
/// At the moment we will only deem accesses as safe for:
/// * A negative constant distance assuming program order.
///
/// Safe: tmp = a[i + 1]; OR a[i + 1] = x;
/// a[i] = tmp; y = a[i];
///
/// The latter case is safe because later checks guarantuee that there can't
/// be a cycle through a phi node (that is, we check that "x" and "y" is not
/// the same variable: a header phi can only be an induction or a reduction, a
/// reduction can't have a memory sink, an induction can't have a memory
/// source). This is important and must not be violated (or we have to
/// resort to checking for cycles through memory).
///
/// * A positive constant distance assuming program order that is bigger
/// than the biggest memory access.
///
/// tmp = a[i] OR b[i] = x
/// a[i+2] = tmp y = b[i+2];
///
/// Safe distance: 2 x sizeof(a[0]), and 2 x sizeof(b[0]), respectively.
///
/// * Zero distances and all accesses have the same size.
///
class MemoryDepChecker {
public:
typedef PointerIntPair<Value *, 1, bool> MemAccessInfo;
typedef SmallPtrSet<MemAccessInfo, 8> MemAccessInfoSet;
/// \brief Set of potential dependent memory accesses.
typedef EquivalenceClasses<MemAccessInfo> DepCandidates;
/// \brief Dependece between memory access instructions.
struct Dependence {
/// \brief The type of the dependence.
enum DepType {
// No dependence.
NoDep,
// We couldn't determine the direction or the distance.
Unknown,
// Lexically forward.
Forward,
// Forward, but if vectorized, is likely to prevent store-to-load
// forwarding.
ForwardButPreventsForwarding,
// Lexically backward.
Backward,
// Backward, but the distance allows a vectorization factor of
// MaxSafeDepDistBytes.
BackwardVectorizable,
// Same, but may prevent store-to-load forwarding.
BackwardVectorizableButPreventsForwarding
};
/// \brief String version of the types.
static const char *DepName[];
/// \brief Index of the source of the dependence in the InstMap vector.
unsigned Source;
/// \brief Index of the destination of the dependence in the InstMap vector.
unsigned Destination;
/// \brief The type of the dependence.
DepType Type;
Dependence(unsigned Source, unsigned Destination, DepType Type)
: Source(Source), Destination(Destination), Type(Type) {}
/// \brief Dependence types that don't prevent vectorization.
static bool isSafeForVectorization(DepType Type);
/// \brief Dependence types that can be queried from the analysis.
static bool isInterestingDependence(DepType Type);
/// \brief Lexically backward dependence types.
bool isPossiblyBackward() const;
/// \brief Print the dependence. \p Instr is used to map the instruction
/// indices to instructions.
void print(raw_ostream &OS, unsigned Depth,
const SmallVectorImpl<Instruction *> &Instrs) const;
};
MemoryDepChecker(ScalarEvolution *Se, const Loop *L)
: SE(Se), InnermostLoop(L), AccessIdx(0),
ShouldRetryWithRuntimeCheck(false), SafeForVectorization(true),
RecordInterestingDependences(true) {}
/// \brief Register the location (instructions are given increasing numbers)
/// of a write access.
void addAccess(StoreInst *SI) {
Value *Ptr = SI->getPointerOperand();
Accesses[MemAccessInfo(Ptr, true)].push_back(AccessIdx);
InstMap.push_back(SI);
++AccessIdx;
}
/// \brief Register the location (instructions are given increasing numbers)
/// of a write access.
void addAccess(LoadInst *LI) {
Value *Ptr = LI->getPointerOperand();
Accesses[MemAccessInfo(Ptr, false)].push_back(AccessIdx);
InstMap.push_back(LI);
++AccessIdx;
}
/// \brief Check whether the dependencies between the accesses are safe.
///
/// Only checks sets with elements in \p CheckDeps.
bool areDepsSafe(DepCandidates &AccessSets, MemAccessInfoSet &CheckDeps,
const ValueToValueMap &Strides);
/// \brief No memory dependence was encountered that would inhibit
/// vectorization.
bool isSafeForVectorization() const { return SafeForVectorization; }
/// \brief The maximum number of bytes of a vector register we can vectorize
/// the accesses safely with.
unsigned getMaxSafeDepDistBytes() { return MaxSafeDepDistBytes; }
/// \brief In same cases when the dependency check fails we can still
/// vectorize the loop with a dynamic array access check.
bool shouldRetryWithRuntimeCheck() { return ShouldRetryWithRuntimeCheck; }
/// \brief Returns the interesting dependences. If null is returned we
/// exceeded the MaxInterestingDependence threshold and this information is
/// not available.
const SmallVectorImpl<Dependence> *getInterestingDependences() const {
return RecordInterestingDependences ? &InterestingDependences : nullptr;
}
void clearInterestingDependences() { InterestingDependences.clear(); }
/// \brief The vector of memory access instructions. The indices are used as
/// instruction identifiers in the Dependence class.
const SmallVectorImpl<Instruction *> &getMemoryInstructions() const {
return InstMap;
}
/// \brief Find the set of instructions that read or write via \p Ptr.
SmallVector<Instruction *, 4> getInstructionsForAccess(Value *Ptr,
bool isWrite) const;
private:
ScalarEvolution *SE;
const Loop *InnermostLoop;
/// \brief Maps access locations (ptr, read/write) to program order.
DenseMap<MemAccessInfo, std::vector<unsigned> > Accesses;
/// \brief Memory access instructions in program order.
SmallVector<Instruction *, 16> InstMap;
/// \brief The program order index to be used for the next instruction.
unsigned AccessIdx;
// We can access this many bytes in parallel safely.
unsigned MaxSafeDepDistBytes;
/// \brief If we see a non-constant dependence distance we can still try to
/// vectorize this loop with runtime checks.
bool ShouldRetryWithRuntimeCheck;
/// \brief No memory dependence was encountered that would inhibit
/// vectorization.
bool SafeForVectorization;
//// \brief True if InterestingDependences reflects the dependences in the
//// loop. If false we exceeded MaxInterestingDependence and
//// InterestingDependences is invalid.
bool RecordInterestingDependences;
/// \brief Interesting memory dependences collected during the analysis as
/// defined by isInterestingDependence. Only valid if
/// RecordInterestingDependences is true.
SmallVector<Dependence, 8> InterestingDependences;
/// \brief Check whether there is a plausible dependence between the two
/// accesses.
///
/// Access \p A must happen before \p B in program order. The two indices
/// identify the index into the program order map.
///
/// This function checks whether there is a plausible dependence (or the
/// absence of such can't be proved) between the two accesses. If there is a
/// plausible dependence but the dependence distance is bigger than one
/// element access it records this distance in \p MaxSafeDepDistBytes (if this
/// distance is smaller than any other distance encountered so far).
/// Otherwise, this function returns true signaling a possible dependence.
Dependence::DepType isDependent(const MemAccessInfo &A, unsigned AIdx,
const MemAccessInfo &B, unsigned BIdx,
const ValueToValueMap &Strides);
/// \brief Check whether the data dependence could prevent store-load
/// forwarding.
bool couldPreventStoreLoadForward(unsigned Distance, unsigned TypeByteSize);
};
/// \brief Drive the analysis of memory accesses in the loop
///
/// This class is responsible for analyzing the memory accesses of a loop. It
/// collects the accesses and then its main helper the AccessAnalysis class
/// finds and categorizes the dependences in buildDependenceSets.
///
/// For memory dependences that can be analyzed at compile time, it determines
/// whether the dependence is part of cycle inhibiting vectorization. This work
/// is delegated to the MemoryDepChecker class.
///
/// For memory dependences that cannot be determined at compile time, it
/// generates run-time checks to prove independence. This is done by
/// AccessAnalysis::canCheckPtrAtRT and the checks are maintained by the
/// RuntimePointerCheck class.
class LoopAccessInfo {
public:
/// This struct holds information about the memory runtime legality check that
/// a group of pointers do not overlap.
struct RuntimePointerCheck {
RuntimePointerCheck() : Need(false) {}
/// Reset the state of the pointer runtime information.
void reset() {
Need = false;
Pointers.clear();
Starts.clear();
Ends.clear();
IsWritePtr.clear();
DependencySetId.clear();
AliasSetId.clear();
}
/// Insert a pointer and calculate the start and end SCEVs.
void insert(ScalarEvolution *SE, Loop *Lp, Value *Ptr, bool WritePtr,
unsigned DepSetId, unsigned ASId,
const ValueToValueMap &Strides);
/// \brief No run-time memory checking is necessary.
bool empty() const { return Pointers.empty(); }
/// \brief Decide whether we need to issue a run-time check for pointer at
/// index \p I and \p J to prove their independence.
///
/// If \p PtrPartition is set, it contains the partition number for
/// pointers (-1 if the pointer belongs to multiple partitions). In this
/// case omit checks between pointers belonging to the same partition.
bool needsChecking(unsigned I, unsigned J,
const SmallVectorImpl<int> *PtrPartition) const;
/// \brief Return true if any pointer requires run-time checking according
/// to needsChecking.
bool needsAnyChecking(const SmallVectorImpl<int> *PtrPartition) const;
/// \brief Print the list run-time memory checks necessary.
///
/// If \p PtrPartition is set, it contains the partition number for
/// pointers (-1 if the pointer belongs to multiple partitions). In this
/// case omit checks between pointers belonging to the same partition.
void print(raw_ostream &OS, unsigned Depth = 0,
const SmallVectorImpl<int> *PtrPartition = nullptr) const;
/// This flag indicates if we need to add the runtime check.
bool Need;
/// Holds the pointers that we need to check.
SmallVector<TrackingVH<Value>, 2> Pointers;
/// Holds the pointer value at the beginning of the loop.
SmallVector<const SCEV*, 2> Starts;
/// Holds the pointer value at the end of the loop.
SmallVector<const SCEV*, 2> Ends;
/// Holds the information if this pointer is used for writing to memory.
SmallVector<bool, 2> IsWritePtr;
/// Holds the id of the set of pointers that could be dependent because of a
/// shared underlying object.
SmallVector<unsigned, 2> DependencySetId;
/// Holds the id of the disjoint alias set to which this pointer belongs.
SmallVector<unsigned, 2> AliasSetId;
};
LoopAccessInfo(Loop *L, ScalarEvolution *SE, const DataLayout &DL,
const TargetLibraryInfo *TLI, AliasAnalysis *AA,
DominatorTree *DT, LoopInfo *LI,
const ValueToValueMap &Strides);
/// Return true we can analyze the memory accesses in the loop and there are
/// no memory dependence cycles.
bool canVectorizeMemory() const { return CanVecMem; }
const RuntimePointerCheck *getRuntimePointerCheck() const {
return &PtrRtCheck;
}
/// \brief Number of memchecks required to prove independence of otherwise
/// may-alias pointers.
unsigned getNumRuntimePointerChecks() const { return NumComparisons; }
/// Return true if the block BB needs to be predicated in order for the loop
/// to be vectorized.
static bool blockNeedsPredication(BasicBlock *BB, Loop *TheLoop,
DominatorTree *DT);
/// Returns true if the value V is uniform within the loop.
bool isUniform(Value *V) const;
unsigned getMaxSafeDepDistBytes() const { return MaxSafeDepDistBytes; }
unsigned getNumStores() const { return NumStores; }
unsigned getNumLoads() const { return NumLoads;}
/// \brief Add code that checks at runtime if the accessed arrays overlap.
///
/// Returns a pair of instructions where the first element is the first
/// instruction generated in possibly a sequence of instructions and the
/// second value is the final comparator value or NULL if no check is needed.
///
/// If \p PtrPartition is set, it contains the partition number for pointers
/// (-1 if the pointer belongs to multiple partitions). In this case omit
/// checks between pointers belonging to the same partition.
std::pair<Instruction *, Instruction *>
addRuntimeCheck(Instruction *Loc,
const SmallVectorImpl<int> *PtrPartition = nullptr) const;
/// \brief The diagnostics report generated for the analysis. E.g. why we
/// couldn't analyze the loop.
const Optional<LoopAccessReport> &getReport() const { return Report; }
/// \brief the Memory Dependence Checker which can determine the
/// loop-independent and loop-carried dependences between memory accesses.
const MemoryDepChecker &getDepChecker() const { return DepChecker; }
/// \brief Return the list of instructions that use \p Ptr to read or write
/// memory.
SmallVector<Instruction *, 4> getInstructionsForAccess(Value *Ptr,
bool isWrite) const {
return DepChecker.getInstructionsForAccess(Ptr, isWrite);
}
/// \brief Print the information about the memory accesses in the loop.
void print(raw_ostream &OS, unsigned Depth = 0) const;
/// \brief Used to ensure that if the analysis was run with speculating the
/// value of symbolic strides, the client queries it with the same assumption.
/// Only used in DEBUG build but we don't want NDEBUG-dependent ABI.
unsigned NumSymbolicStrides;
/// \brief Checks existence of store to invariant address inside loop.
/// If the loop has any store to invariant address, then it returns true,
/// else returns false.
bool hasStoreToLoopInvariantAddress() const {
return StoreToLoopInvariantAddress;
}
private:
/// \brief Analyze the loop. Substitute symbolic strides using Strides.
void analyzeLoop(const ValueToValueMap &Strides);
/// \brief Check if the structure of the loop allows it to be analyzed by this
/// pass.
bool canAnalyzeLoop();
void emitAnalysis(LoopAccessReport &Message);
/// We need to check that all of the pointers in this list are disjoint
/// at runtime.
RuntimePointerCheck PtrRtCheck;
/// \brief the Memory Dependence Checker which can determine the
/// loop-independent and loop-carried dependences between memory accesses.
MemoryDepChecker DepChecker;
/// \brief Number of memchecks required to prove independence of otherwise
/// may-alias pointers
unsigned NumComparisons;
Loop *TheLoop;
ScalarEvolution *SE;
const DataLayout &DL;
const TargetLibraryInfo *TLI;
AliasAnalysis *AA;
DominatorTree *DT;
LoopInfo *LI;
unsigned NumLoads;
unsigned NumStores;
unsigned MaxSafeDepDistBytes;
/// \brief Cache the result of analyzeLoop.
bool CanVecMem;
/// \brief Indicator for storing to uniform addresses.
/// If a loop has write to a loop invariant address then it should be true.
bool StoreToLoopInvariantAddress;
/// \brief The diagnostics report generated for the analysis. E.g. why we
/// couldn't analyze the loop.
Optional<LoopAccessReport> Report;
};
Value *stripIntegerCast(Value *V);
///\brief Return the SCEV corresponding to a pointer with the symbolic stride
///replaced with constant one.
///
/// If \p OrigPtr is not null, use it to look up the stride value instead of \p
/// Ptr. \p PtrToStride provides the mapping between the pointer value and its
/// stride as collected by LoopVectorizationLegality::collectStridedAccess.
const SCEV *replaceSymbolicStrideSCEV(ScalarEvolution *SE,
const ValueToValueMap &PtrToStride,
Value *Ptr, Value *OrigPtr = nullptr);
/// \brief This analysis provides dependence information for the memory accesses
/// of a loop.
///
/// It runs the analysis for a loop on demand. This can be initiated by
/// querying the loop access info via LAA::getInfo. getInfo return a
/// LoopAccessInfo object. See this class for the specifics of what information
/// is provided.
class LoopAccessAnalysis : public FunctionPass {
public:
static char ID;
LoopAccessAnalysis() : FunctionPass(ID) {
initializeLoopAccessAnalysisPass(*PassRegistry::getPassRegistry());
}
bool runOnFunction(Function &F) override;
void getAnalysisUsage(AnalysisUsage &AU) const override;
/// \brief Query the result of the loop access information for the loop \p L.
///
/// If the client speculates (and then issues run-time checks) for the values
/// of symbolic strides, \p Strides provides the mapping (see
/// replaceSymbolicStrideSCEV). If there is no cached result available run
/// the analysis.
const LoopAccessInfo &getInfo(Loop *L, const ValueToValueMap &Strides);
void releaseMemory() override {
// Invalidate the cache when the pass is freed.
LoopAccessInfoMap.clear();
}
/// \brief Print the result of the analysis when invoked with -analyze.
void print(raw_ostream &OS, const Module *M = nullptr) const override;
private:
/// \brief The cache.
DenseMap<Loop *, std::unique_ptr<LoopAccessInfo>> LoopAccessInfoMap;
// The used analysis passes.
ScalarEvolution *SE;
const TargetLibraryInfo *TLI;
AliasAnalysis *AA;
DominatorTree *DT;
LoopInfo *LI;
};
} // End llvm namespace
#endif

View File

@ -42,6 +42,11 @@
namespace llvm {
// FIXME: Replace this brittle forward declaration with the include of the new
// PassManager.h when doing so doesn't break the PassManagerBuilder.
template <typename IRUnitT> class AnalysisManager;
class PreservedAnalyses;
template<typename T>
inline void RemoveFromVector(std::vector<T*> &V, T *N) {
typename std::vector<T*>::iterator I = std::find(V.begin(), V.end(), N);
@ -74,9 +79,9 @@ class LoopBase {
SmallPtrSet<const BlockT*, 8> DenseBlockSet;
LoopBase(const LoopBase<BlockT, LoopT> &) LLVM_DELETED_FUNCTION;
LoopBase(const LoopBase<BlockT, LoopT> &) = delete;
const LoopBase<BlockT, LoopT>&
operator=(const LoopBase<BlockT, LoopT> &) LLVM_DELETED_FUNCTION;
operator=(const LoopBase<BlockT, LoopT> &) = delete;
public:
/// Loop ctor - This creates an empty loop.
LoopBase() : ParentLoop(nullptr) {}
@ -356,11 +361,11 @@ class Loop : public LoopBase<BasicBlock, Loop> {
/// isLoopInvariant - Return true if the specified value is loop invariant
///
bool isLoopInvariant(Value *V) const;
bool isLoopInvariant(const Value *V) const;
/// hasLoopInvariantOperands - Return true if all the operands of the
/// specified instruction are loop invariant.
bool hasLoopInvariantOperands(Instruction *I) const;
bool hasLoopInvariantOperands(const Instruction *I) const;
/// makeLoopInvariant - If the given value is an instruction inside of the
/// loop and it can be hoisted, do so to make it trivially loop-invariant.
@ -459,23 +464,20 @@ class Loop : public LoopBase<BasicBlock, Loop> {
/// cannot find a terminating instruction with location information,
/// it returns an unknown location.
DebugLoc getStartLoc() const {
DebugLoc StartLoc;
BasicBlock *HeadBB;
// Try the pre-header first.
if ((HeadBB = getLoopPreheader()) != nullptr) {
StartLoc = HeadBB->getTerminator()->getDebugLoc();
if (!StartLoc.isUnknown())
return StartLoc;
}
if ((HeadBB = getLoopPreheader()) != nullptr)
if (DebugLoc DL = HeadBB->getTerminator()->getDebugLoc())
return DL;
// If we have no pre-header or there are no instructions with debug
// info in it, try the header.
HeadBB = getHeader();
if (HeadBB)
StartLoc = HeadBB->getTerminator()->getDebugLoc();
return HeadBB->getTerminator()->getDebugLoc();
return StartLoc;
return DebugLoc();
}
private:
@ -496,18 +498,33 @@ class LoopInfoBase {
friend class LoopBase<BlockT, LoopT>;
friend class LoopInfo;
void operator=(const LoopInfoBase &) LLVM_DELETED_FUNCTION;
LoopInfoBase(const LoopInfo &) LLVM_DELETED_FUNCTION;
void operator=(const LoopInfoBase &) = delete;
LoopInfoBase(const LoopInfoBase &) = delete;
public:
LoopInfoBase() { }
~LoopInfoBase() { releaseMemory(); }
void releaseMemory() {
for (typename std::vector<LoopT *>::iterator I =
TopLevelLoops.begin(), E = TopLevelLoops.end(); I != E; ++I)
delete *I; // Delete all of the loops...
LoopInfoBase(LoopInfoBase &&Arg)
: BBMap(std::move(Arg.BBMap)),
TopLevelLoops(std::move(Arg.TopLevelLoops)) {
// We have to clear the arguments top level loops as we've taken ownership.
Arg.TopLevelLoops.clear();
}
LoopInfoBase &operator=(LoopInfoBase &&RHS) {
BBMap = std::move(RHS.BBMap);
BBMap.clear(); // Reset internal state of analysis
for (auto *L : TopLevelLoops)
delete L;
TopLevelLoops = std::move(RHS.TopLevelLoops);
RHS.TopLevelLoops.clear();
return *this;
}
void releaseMemory() {
BBMap.clear();
for (auto *L : TopLevelLoops)
delete L;
TopLevelLoops.clear();
}
@ -576,8 +593,7 @@ class LoopInfoBase {
/// list with the indicated loop.
void changeTopLevelLoop(LoopT *OldLoop,
LoopT *NewLoop) {
typename std::vector<LoopT *>::iterator I =
std::find(TopLevelLoops.begin(), TopLevelLoops.end(), OldLoop);
auto I = std::find(TopLevelLoops.begin(), TopLevelLoops.end(), OldLoop);
assert(I != TopLevelLoops.end() && "Old loop not at top level!");
*I = NewLoop;
assert(!NewLoop->ParentLoop && !OldLoop->ParentLoop &&
@ -595,7 +611,7 @@ class LoopInfoBase {
/// including all of the Loop objects it is nested in and our mapping from
/// BasicBlocks to loops.
void removeBlock(BlockT *BB) {
typename DenseMap<BlockT *, LoopT *>::iterator I = BBMap.find(BB);
auto I = BBMap.find(BB);
if (I != BBMap.end()) {
for (LoopT *L = I->second; L; L = L->getParentLoop())
L->removeBlockFromLoop(BB);
@ -617,8 +633,9 @@ class LoopInfoBase {
void Analyze(DominatorTreeBase<BlockT> &DomTree);
// Debugging
void print(raw_ostream &OS) const;
void verify() const;
};
// Implementation in LoopInfoImpl.h
@ -626,99 +643,23 @@ class LoopInfoBase {
__extension__ extern template class LoopInfoBase<BasicBlock, Loop>;
#endif
class LoopInfo : public FunctionPass {
LoopInfoBase<BasicBlock, Loop> LI;
class LoopInfo : public LoopInfoBase<BasicBlock, Loop> {
typedef LoopInfoBase<BasicBlock, Loop> BaseT;
friend class LoopBase<BasicBlock, Loop>;
void operator=(const LoopInfo &) LLVM_DELETED_FUNCTION;
LoopInfo(const LoopInfo &) LLVM_DELETED_FUNCTION;
void operator=(const LoopInfo &) = delete;
LoopInfo(const LoopInfo &) = delete;
public:
static char ID; // Pass identification, replacement for typeid
LoopInfo() {}
LoopInfo() : FunctionPass(ID) {
initializeLoopInfoPass(*PassRegistry::getPassRegistry());
LoopInfo(LoopInfo &&Arg) : BaseT(std::move(static_cast<BaseT &>(Arg))) {}
LoopInfo &operator=(LoopInfo &&RHS) {
BaseT::operator=(std::move(static_cast<BaseT &>(RHS)));
return *this;
}
LoopInfoBase<BasicBlock, Loop>& getBase() { return LI; }
/// iterator/begin/end - The interface to the top-level loops in the current
/// function.
///
typedef LoopInfoBase<BasicBlock, Loop>::iterator iterator;
typedef LoopInfoBase<BasicBlock, Loop>::reverse_iterator reverse_iterator;
inline iterator begin() const { return LI.begin(); }
inline iterator end() const { return LI.end(); }
inline reverse_iterator rbegin() const { return LI.rbegin(); }
inline reverse_iterator rend() const { return LI.rend(); }
bool empty() const { return LI.empty(); }
/// getLoopFor - Return the inner most loop that BB lives in. If a basic
/// block is in no loop (for example the entry node), null is returned.
///
inline Loop *getLoopFor(const BasicBlock *BB) const {
return LI.getLoopFor(BB);
}
/// operator[] - same as getLoopFor...
///
inline const Loop *operator[](const BasicBlock *BB) const {
return LI.getLoopFor(BB);
}
/// getLoopDepth - Return the loop nesting level of the specified block. A
/// depth of 0 means the block is not inside any loop.
///
inline unsigned getLoopDepth(const BasicBlock *BB) const {
return LI.getLoopDepth(BB);
}
// isLoopHeader - True if the block is a loop header node
inline bool isLoopHeader(BasicBlock *BB) const {
return LI.isLoopHeader(BB);
}
/// runOnFunction - Calculate the natural loop information.
///
bool runOnFunction(Function &F) override;
void verifyAnalysis() const override;
void releaseMemory() override { LI.releaseMemory(); }
void print(raw_ostream &O, const Module* M = nullptr) const override;
void getAnalysisUsage(AnalysisUsage &AU) const override;
/// removeLoop - This removes the specified top-level loop from this loop info
/// object. The loop is not deleted, as it will presumably be inserted into
/// another loop.
inline Loop *removeLoop(iterator I) { return LI.removeLoop(I); }
/// changeLoopFor - Change the top-level loop that contains BB to the
/// specified loop. This should be used by transformations that restructure
/// the loop hierarchy tree.
inline void changeLoopFor(BasicBlock *BB, Loop *L) {
LI.changeLoopFor(BB, L);
}
/// changeTopLevelLoop - Replace the specified loop in the top-level loops
/// list with the indicated loop.
inline void changeTopLevelLoop(Loop *OldLoop, Loop *NewLoop) {
LI.changeTopLevelLoop(OldLoop, NewLoop);
}
/// addTopLevelLoop - This adds the specified loop to the collection of
/// top-level loops.
inline void addTopLevelLoop(Loop *New) {
LI.addTopLevelLoop(New);
}
/// removeBlock - This method completely removes BB from all data structures,
/// including all of the Loop objects it is nested in and our mapping from
/// BasicBlocks to loops.
void removeBlock(BasicBlock *BB) {
LI.removeBlock(BB);
}
// Most of the public interface is provided via LoopInfoBase.
/// updateUnloop - Update LoopInfo after removing the last backedge from a
/// loop--now the "unloop". This updates the loop forest and parent loops for
@ -748,7 +689,6 @@ class LoopInfo : public FunctionPass {
}
};
// Allow clients to walk the list of nested loops...
template <> struct GraphTraits<const Loop*> {
typedef const Loop NodeType;
@ -776,6 +716,65 @@ template <> struct GraphTraits<Loop*> {
}
};
/// \brief Analysis pass that exposes the \c LoopInfo for a function.
class LoopAnalysis {
static char PassID;
public:
typedef LoopInfo Result;
/// \brief Opaque, unique identifier for this analysis pass.
static void *ID() { return (void *)&PassID; }
/// \brief Provide a name for the analysis for debugging and logging.
static StringRef name() { return "LoopAnalysis"; }
LoopAnalysis() {}
LoopAnalysis(const LoopAnalysis &Arg) {}
LoopAnalysis(LoopAnalysis &&Arg) {}
LoopAnalysis &operator=(const LoopAnalysis &RHS) { return *this; }
LoopAnalysis &operator=(LoopAnalysis &&RHS) { return *this; }
LoopInfo run(Function &F, AnalysisManager<Function> *AM);
};
/// \brief Printer pass for the \c LoopAnalysis results.
class LoopPrinterPass {
raw_ostream &OS;
public:
explicit LoopPrinterPass(raw_ostream &OS) : OS(OS) {}
PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM);
static StringRef name() { return "LoopPrinterPass"; }
};
/// \brief The legacy pass manager's analysis pass to compute loop information.
class LoopInfoWrapperPass : public FunctionPass {
LoopInfo LI;
public:
static char ID; // Pass identification, replacement for typeid
LoopInfoWrapperPass() : FunctionPass(ID) {
initializeLoopInfoWrapperPassPass(*PassRegistry::getPassRegistry());
}
LoopInfo &getLoopInfo() { return LI; }
const LoopInfo &getLoopInfo() const { return LI; }
/// \brief Calculate the natural loop information for a given function.
bool runOnFunction(Function &F) override;
void verifyAnalysis() const override;
void releaseMemory() override { LI.releaseMemory(); }
void print(raw_ostream &O, const Module *M = nullptr) const override;
void getAnalysisUsage(AnalysisUsage &AU) const override;
};
} // End llvm namespace
#endif

View File

@ -402,7 +402,6 @@ static void discoverAndMapSubloop(LoopT *L, ArrayRef<BlockT*> Backedges,
L->reserveBlocks(NumBlocks);
}
namespace {
/// Populate all loop data in a stable order during a single forward DFS.
template<class BlockT, class LoopT>
class PopulateLoopsDFS {
@ -410,9 +409,6 @@ class PopulateLoopsDFS {
typedef typename BlockTraits::ChildIteratorType SuccIterTy;
LoopInfoBase<BlockT, LoopT> *LI;
DenseSet<const BlockT *> VisitedBlocks;
std::vector<std::pair<BlockT*, SuccIterTy> > DFSStack;
public:
PopulateLoopsDFS(LoopInfoBase<BlockT, LoopT> *li):
LI(li) {}
@ -421,37 +417,13 @@ class PopulateLoopsDFS {
protected:
void insertIntoLoop(BlockT *Block);
BlockT *dfsSource() { return DFSStack.back().first; }
SuccIterTy &dfsSucc() { return DFSStack.back().second; }
SuccIterTy dfsSuccEnd() { return BlockTraits::child_end(dfsSource()); }
void pushBlock(BlockT *Block) {
DFSStack.push_back(std::make_pair(Block, BlockTraits::child_begin(Block)));
}
};
} // anonymous
/// Top-level driver for the forward DFS within the loop.
template<class BlockT, class LoopT>
void PopulateLoopsDFS<BlockT, LoopT>::traverse(BlockT *EntryBlock) {
pushBlock(EntryBlock);
VisitedBlocks.insert(EntryBlock);
while (!DFSStack.empty()) {
// Traverse the leftmost path as far as possible.
while (dfsSucc() != dfsSuccEnd()) {
BlockT *BB = *dfsSucc();
++dfsSucc();
if (!VisitedBlocks.insert(BB).second)
continue;
// Push the next DFS successor onto the stack.
pushBlock(BB);
}
// Visit the top of the stack in postorder and backtrack.
insertIntoLoop(dfsSource());
DFSStack.pop_back();
}
for (BlockT *BB : post_order(EntryBlock))
insertIntoLoop(BB);
}
/// Add a single Block to its ancestor loops in PostOrder. If the block is a
@ -500,10 +472,9 @@ Analyze(DominatorTreeBase<BlockT> &DomTree) {
// Postorder traversal of the dominator tree.
DomTreeNodeBase<BlockT>* DomRoot = DomTree.getRootNode();
for (po_iterator<DomTreeNodeBase<BlockT>*> DomIter = po_begin(DomRoot),
DomEnd = po_end(DomRoot); DomIter != DomEnd; ++DomIter) {
for (auto DomNode : post_order(DomRoot)) {
BlockT *Header = DomIter->getBlock();
BlockT *Header = DomNode->getBlock();
SmallVector<BlockT *, 4> Backedges;
// Check each predecessor of the potential loop header.
@ -545,6 +516,25 @@ void LoopInfoBase<BlockT, LoopT>::print(raw_ostream &OS) const {
#endif
}
template<class BlockT, class LoopT>
void LoopInfoBase<BlockT, LoopT>::verify() const {
DenseSet<const LoopT*> Loops;
for (iterator I = begin(), E = end(); I != E; ++I) {
assert(!(*I)->getParentLoop() && "Top-level loop has a parent!");
(*I)->verifyLoopNest(&Loops);
}
// Verify that blocks are mapped to valid loops.
#ifndef NDEBUG
for (auto &Entry : BBMap) {
BlockT *BB = Entry.first;
LoopT *L = Entry.second;
assert(Loops.count(L) && "orphaned loop");
assert(L->contains(BB) && "orphaned block");
}
#endif
}
} // End llvm namespace
#endif

View File

@ -82,12 +82,6 @@ static inline CallInst *extractMallocCall(Value *I,
return const_cast<CallInst*>(extractMallocCall((const Value*)I, TLI));
}
/// isArrayMalloc - Returns the corresponding CallInst if the instruction
/// is a call to malloc whose array size can be determined and the array size
/// is not constant 1. Otherwise, return NULL.
const CallInst *isArrayMalloc(const Value *I, const DataLayout *DL,
const TargetLibraryInfo *TLI);
/// getMallocType - Returns the PointerType resulting from the malloc call.
/// The PointerType depends on the number of bitcast uses of the malloc call:
/// 0: PointerType is the malloc calls' return type.
@ -107,11 +101,10 @@ Type *getMallocAllocatedType(const CallInst *CI, const TargetLibraryInfo *TLI);
/// then return that multiple. For non-array mallocs, the multiple is
/// constant 1. Otherwise, return NULL for mallocs whose array size cannot be
/// determined.
Value *getMallocArraySize(CallInst *CI, const DataLayout *DL,
Value *getMallocArraySize(CallInst *CI, const DataLayout &DL,
const TargetLibraryInfo *TLI,
bool LookThroughSExt = false);
//===----------------------------------------------------------------------===//
// calloc Call Utility Functions.
//
@ -147,11 +140,9 @@ static inline CallInst *isFreeCall(Value *I, const TargetLibraryInfo *TLI) {
/// underlying object pointed to by Ptr.
/// If RoundToAlign is true, then Size is rounded up to the aligment of allocas,
/// byval arguments, and global variables.
bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout *DL,
bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL,
const TargetLibraryInfo *TLI, bool RoundToAlign = false);
typedef std::pair<APInt, APInt> SizeOffsetType;
/// \brief Evaluate the size and offset of an object pointed to by a Value*
@ -159,7 +150,7 @@ typedef std::pair<APInt, APInt> SizeOffsetType;
class ObjectSizeOffsetVisitor
: public InstVisitor<ObjectSizeOffsetVisitor, SizeOffsetType> {
const DataLayout *DL;
const DataLayout &DL;
const TargetLibraryInfo *TLI;
bool RoundToAlign;
unsigned IntTyBits;
@ -173,7 +164,7 @@ class ObjectSizeOffsetVisitor
}
public:
ObjectSizeOffsetVisitor(const DataLayout *DL, const TargetLibraryInfo *TLI,
ObjectSizeOffsetVisitor(const DataLayout &DL, const TargetLibraryInfo *TLI,
LLVMContext &Context, bool RoundToAlign = false);
SizeOffsetType compute(Value *V);
@ -222,7 +213,7 @@ class ObjectSizeOffsetEvaluator
typedef DenseMap<const Value*, WeakEvalType> CacheMapTy;
typedef SmallPtrSet<const Value*, 8> PtrSetTy;
const DataLayout *DL;
const DataLayout &DL;
const TargetLibraryInfo *TLI;
LLVMContext &Context;
BuilderTy Builder;
@ -238,7 +229,7 @@ class ObjectSizeOffsetEvaluator
SizeOffsetEvalType compute_(Value *V);
public:
ObjectSizeOffsetEvaluator(const DataLayout *DL, const TargetLibraryInfo *TLI,
ObjectSizeOffsetEvaluator(const DataLayout &DL, const TargetLibraryInfo *TLI,
LLVMContext &Context, bool RoundToAlign = false);
SizeOffsetEvalType compute(Value *V);

View File

@ -19,6 +19,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/PredIteratorCache.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Pass.h"
@ -29,7 +30,6 @@ namespace llvm {
class CallSite;
class AliasAnalysis;
class AssumptionCache;
class DataLayout;
class MemoryDependenceAnalysis;
class PredIteratorCache;
class DominatorTree;
@ -324,14 +324,13 @@ namespace llvm {
/// Current AA implementation, just a cache.
AliasAnalysis *AA;
const DataLayout *DL;
DominatorTree *DT;
AssumptionCache *AC;
std::unique_ptr<PredIteratorCache> PredCache;
PredIteratorCache PredCache;
public:
MemoryDependenceAnalysis();
~MemoryDependenceAnalysis();
~MemoryDependenceAnalysis() override;
static char ID;
/// Pass Implementation stuff. This doesn't do any analysis eagerly.
@ -421,20 +420,21 @@ namespace llvm {
static unsigned getLoadLoadClobberFullWidthSize(const Value *MemLocBase,
int64_t MemLocOffs,
unsigned MemLocSize,
const LoadInst *LI,
const DataLayout &DL);
const LoadInst *LI);
private:
MemDepResult getCallSiteDependencyFrom(CallSite C, bool isReadOnlyCall,
BasicBlock::iterator ScanIt,
BasicBlock *BB);
bool getNonLocalPointerDepFromBB(const PHITransAddr &Pointer,
bool getNonLocalPointerDepFromBB(Instruction *QueryInst,
const PHITransAddr &Pointer,
const AliasAnalysis::Location &Loc,
bool isLoad, BasicBlock *BB,
SmallVectorImpl<NonLocalDepResult> &Result,
DenseMap<BasicBlock*, Value*> &Visited,
bool SkipFirstBlock = false);
MemDepResult GetNonLocalInfoForBlock(const AliasAnalysis::Location &Loc,
MemDepResult GetNonLocalInfoForBlock(Instruction *QueryInst,
const AliasAnalysis::Location &Loc,
bool isLoad, BasicBlock *BB,
NonLocalDepInfo *Cache,
unsigned NumSortedEntries);

View File

@ -36,9 +36,9 @@ namespace llvm {
class PHITransAddr {
/// Addr - The actual address we're analyzing.
Value *Addr;
/// The DataLayout we are playing with if known, otherwise null.
const DataLayout *DL;
/// The DataLayout we are playing with.
const DataLayout &DL;
/// TLI - The target library info if known, otherwise null.
const TargetLibraryInfo *TLI;
@ -49,7 +49,7 @@ class PHITransAddr {
/// InstInputs - The inputs for our symbolic address.
SmallVector<Instruction*, 4> InstInputs;
public:
PHITransAddr(Value *addr, const DataLayout *DL, AssumptionCache *AC)
PHITransAddr(Value *addr, const DataLayout &DL, AssumptionCache *AC)
: Addr(addr), DL(DL), TLI(nullptr), AC(AC) {
// If the address is an instruction, the whole thing is considered an input.
if (Instruction *I = dyn_cast<Instruction>(Addr))

View File

@ -136,6 +136,13 @@ namespace llvm {
//
FunctionPass *createDelinearizationPass();
//===--------------------------------------------------------------------===//
//
// createDivergenceAnalysisPass - This pass determines which branches in a GPU
// program are divergent.
//
FunctionPass *createDivergenceAnalysisPass();
//===--------------------------------------------------------------------===//
//
// Minor pass prototypes, allowing us to expose them through bugpoint and
@ -159,9 +166,13 @@ namespace llvm {
//
FunctionPass *createMemDepPrinter();
// createJumpInstrTableInfoPass - This creates a pass that stores information
// about the jump tables created by JumpInstrTables
ImmutablePass *createJumpInstrTableInfoPass();
//===--------------------------------------------------------------------===//
//
// createMemDerefPrinter - This pass collects memory dereferenceability
// information and prints it with -analyze.
//
FunctionPass *createMemDerefPrinter();
}
#endif

View File

@ -30,7 +30,7 @@ struct PostDominatorTree : public FunctionPass {
DT = new DominatorTreeBase<BasicBlock>(true);
}
~PostDominatorTree();
~PostDominatorTree() override;
bool runOnFunction(Function &F) override;

View File

@ -115,8 +115,8 @@ class RegionNodeBase {
typedef typename Tr::RegionT RegionT;
private:
RegionNodeBase(const RegionNodeBase &) LLVM_DELETED_FUNCTION;
const RegionNodeBase &operator=(const RegionNodeBase &) LLVM_DELETED_FUNCTION;
RegionNodeBase(const RegionNodeBase &) = delete;
const RegionNodeBase &operator=(const RegionNodeBase &) = delete;
/// This is the entry basic block that starts this region node. If this is a
/// BasicBlock RegionNode, then entry is just the basic block, that this
@ -261,8 +261,8 @@ class RegionBase : public RegionNodeBase<Tr> {
typedef typename InvBlockTraits::ChildIteratorType PredIterTy;
friend class RegionInfoBase<Tr>;
RegionBase(const RegionBase &) LLVM_DELETED_FUNCTION;
const RegionBase &operator=(const RegionBase &) LLVM_DELETED_FUNCTION;
RegionBase(const RegionBase &) = delete;
const RegionBase &operator=(const RegionBase &) = delete;
// Information necessary to manage this Region.
RegionInfoT *RI;
@ -674,8 +674,8 @@ class RegionInfoBase {
RegionInfoBase();
virtual ~RegionInfoBase();
RegionInfoBase(const RegionInfoBase &) LLVM_DELETED_FUNCTION;
const RegionInfoBase &operator=(const RegionInfoBase &) LLVM_DELETED_FUNCTION;
RegionInfoBase(const RegionInfoBase &) = delete;
const RegionInfoBase &operator=(const RegionInfoBase &) = delete;
DomTreeT *DT;
PostDomTreeT *PDT;
@ -820,8 +820,6 @@ class RegionNode : public RegionNodeBase<RegionTraits<Function>> {
inline RegionNode(Region *Parent, BasicBlock *Entry, bool isSubRegion = false)
: RegionNodeBase<RegionTraits<Function>>(Parent, Entry, isSubRegion) {}
~RegionNode() {}
bool operator==(const Region &RN) const {
return this == reinterpret_cast<const RegionNode *>(&RN);
}
@ -842,7 +840,7 @@ class RegionInfo : public RegionInfoBase<RegionTraits<Function>> {
public:
explicit RegionInfo();
virtual ~RegionInfo();
~RegionInfo() override;
// updateStatistics - Update statistic about created regions.
void updateStatistics(Region *R) final;
@ -858,7 +856,7 @@ class RegionInfoPass : public FunctionPass {
static char ID;
explicit RegionInfoPass();
~RegionInfoPass();
~RegionInfoPass() override;
RegionInfo &getRegionInfo() { return RI; }

View File

@ -487,7 +487,7 @@ void RegionBase<Tr>::print(raw_ostream &OS, bool print_tree, unsigned level,
OS.indent(level * 2 + 2);
if (Style == PrintBB) {
for (const auto &BB : blocks())
for (const auto *BB : blocks())
OS << BB->getName() << ", "; // TODO: remove the last ","
} else if (Style == PrintRN) {
for (const_element_iterator I = element_begin(), E = element_end();
@ -714,10 +714,8 @@ void RegionInfoBase<Tr>::scanForRegions(FuncT &F, BBtoBBMap *ShortCut) {
// regions from the bottom of the dominance tree. If the small regions are
// detected first, detection of bigger regions is faster, as we can jump
// over the small regions.
for (po_iterator<DomTreeNodeT *> FI = po_begin(N), FE = po_end(N); FI != FE;
++FI) {
findRegionsWithEntry(FI->getBlock(), ShortCut);
}
for (auto DomNode : post_order(N))
findRegionsWithEntry(DomNode->getBlock(), ShortCut);
}
template <class Tr>

View File

@ -145,16 +145,6 @@ class RNSuccIterator : public std::iterator<std::forward_iterator_tag,
++*this;
return tmp;
}
inline const Self &operator=(const Self &I) {
if (this != &I) {
assert(getNode()->getParent() == I.getNode()->getParent()
&& "Cannot assign iterators of two different regions!");
Node = I.Node;
BItor = I.BItor;
}
return *this;
}
};
@ -240,16 +230,6 @@ class RNSuccIterator<FlatIt<NodeType>, BlockT, RegionT>
++*this;
return tmp;
}
inline const Self &operator=(const Self &I) {
if (this != &I) {
assert(Node->getParent() == I.Node->getParent()
&& "Cannot assign iterators to two different regions!");
Node = I.Node;
Itor = I.Itor;
}
return *this;
}
};
template<class NodeType, class BlockT, class RegionT>

View File

@ -71,8 +71,8 @@ namespace llvm {
unsigned short SubclassData;
private:
SCEV(const SCEV &) LLVM_DELETED_FUNCTION;
void operator=(const SCEV &) LLVM_DELETED_FUNCTION;
SCEV(const SCEV &) = delete;
void operator=(const SCEV &) = delete;
public:
/// NoWrapFlags are bitfield indices into SubclassData.
@ -82,12 +82,13 @@ namespace llvm {
/// operator. NSW is a misnomer that we use to mean no signed overflow or
/// underflow.
///
/// AddRec expression may have a no-self-wraparound <NW> property if the
/// result can never reach the start value. This property is independent of
/// the actual start value and step direction. Self-wraparound is defined
/// purely in terms of the recurrence's loop, step size, and
/// bitwidth. Formally, a recurrence with no self-wraparound satisfies:
/// abs(step) * max-iteration(loop) <= unsigned-max(bitwidth).
/// AddRec expressions may have a no-self-wraparound <NW> property if, in
/// the integer domain, abs(step) * max-iteration(loop) <=
/// unsigned-max(bitwidth). This means that the recurrence will never reach
/// its start value if the step is non-zero. Computing the same value on
/// each iteration is not considered wrapping, and recurrences with step = 0
/// are trivially <NW>. <NW> is independent of the sign of step and the
/// value the add recurrence starts with.
///
/// Note that NUW and NSW are also valid properties of a recurrence, and
/// either implies NW. For convenience, NW will be set for a recurrence
@ -231,10 +232,6 @@ namespace llvm {
///
LoopInfo *LI;
/// The DataLayout information for the target we are targeting.
///
const DataLayout *DL;
/// TLI - The target library information for the target we are targeting.
///
TargetLibraryInfo *TLI;
@ -259,6 +256,10 @@ namespace llvm {
/// Mark predicate values currently being processed by isImpliedCond.
DenseSet<Value*> PendingLoopPredicates;
/// Set to true by isLoopBackedgeGuardedByCond when we're walking the set of
/// conditions dominating the backedge of a loop.
bool WalkingBEDominatingConds;
/// ExitLimit - Information about the number of loop iterations for which a
/// loop exit's branch condition evaluates to the not-taken path. This is a
/// temporary pair of exact and max expressions that are eventually
@ -372,43 +373,45 @@ namespace llvm {
/// LoopDispositions - Memoized computeLoopDisposition results.
DenseMap<const SCEV *,
SmallVector<std::pair<const Loop *, LoopDisposition>, 2> > LoopDispositions;
SmallVector<PointerIntPair<const Loop *, 2, LoopDisposition>, 2>>
LoopDispositions;
/// computeLoopDisposition - Compute a LoopDisposition value.
LoopDisposition computeLoopDisposition(const SCEV *S, const Loop *L);
/// BlockDispositions - Memoized computeBlockDisposition results.
DenseMap<const SCEV *,
SmallVector<std::pair<const BasicBlock *, BlockDisposition>, 2> > BlockDispositions;
DenseMap<
const SCEV *,
SmallVector<PointerIntPair<const BasicBlock *, 2, BlockDisposition>, 2>>
BlockDispositions;
/// computeBlockDisposition - Compute a BlockDisposition value.
BlockDisposition computeBlockDisposition(const SCEV *S, const BasicBlock *BB);
/// UnsignedRanges - Memoized results from getUnsignedRange
/// UnsignedRanges - Memoized results from getRange
DenseMap<const SCEV *, ConstantRange> UnsignedRanges;
/// SignedRanges - Memoized results from getSignedRange
/// SignedRanges - Memoized results from getRange
DenseMap<const SCEV *, ConstantRange> SignedRanges;
/// setUnsignedRange - Set the memoized unsigned range for the given SCEV.
const ConstantRange &setUnsignedRange(const SCEV *S,
const ConstantRange &CR) {
/// RangeSignHint - Used to parameterize getRange
enum RangeSignHint { HINT_RANGE_UNSIGNED, HINT_RANGE_SIGNED };
/// setRange - Set the memoized range for the given SCEV.
const ConstantRange &setRange(const SCEV *S, RangeSignHint Hint,
const ConstantRange &CR) {
DenseMap<const SCEV *, ConstantRange> &Cache =
Hint == HINT_RANGE_UNSIGNED ? UnsignedRanges : SignedRanges;
std::pair<DenseMap<const SCEV *, ConstantRange>::iterator, bool> Pair =
UnsignedRanges.insert(std::make_pair(S, CR));
Cache.insert(std::make_pair(S, CR));
if (!Pair.second)
Pair.first->second = CR;
return Pair.first->second;
}
/// setUnsignedRange - Set the memoized signed range for the given SCEV.
const ConstantRange &setSignedRange(const SCEV *S,
const ConstantRange &CR) {
std::pair<DenseMap<const SCEV *, ConstantRange>::iterator, bool> Pair =
SignedRanges.insert(std::make_pair(S, CR));
if (!Pair.second)
Pair.first->second = CR;
return Pair.first->second;
}
/// getRange - Determine the range for a particular SCEV.
ConstantRange getRange(const SCEV *S, RangeSignHint Hint);
/// createSCEV - We know that there is no SCEV for the specified value.
/// Analyze the expression.
@ -536,6 +539,15 @@ namespace llvm {
const SCEV *FoundLHS,
const SCEV *FoundRHS);
/// isImpliedCondOperandsViaRanges - Test whether the condition described by
/// Pred, LHS, and RHS is true whenever the condition described by Pred,
/// FoundLHS, and FoundRHS is true. Utility function used by
/// isImpliedCondOperands.
bool isImpliedCondOperandsViaRanges(ICmpInst::Predicate Pred,
const SCEV *LHS, const SCEV *RHS,
const SCEV *FoundLHS,
const SCEV *FoundRHS);
/// getConstantEvolutionLoopExitValue - If we know that the specified Phi is
/// in the header of its containing loop, we know the loop executes a
/// constant number of times, and the PHI node is just a recurrence
@ -557,6 +569,15 @@ namespace llvm {
/// pointer.
bool checkValidity(const SCEV *S) const;
// Return true if `ExtendOpTy`({`Start`,+,`Step`}) can be proved to be equal
// to {`ExtendOpTy`(`Start`),+,`ExtendOpTy`(`Step`)}. This is equivalent to
// proving no signed (resp. unsigned) wrap in {`Start`,+,`Step`} if
// `ExtendOpTy` is `SCEVSignExtendExpr` (resp. `SCEVZeroExtendExpr`).
//
template<typename ExtendOpTy>
bool proveNoWrapByVaryingStart(const SCEV *Start, const SCEV *Step,
const Loop *L);
public:
static char ID; // Pass identification, replacement for typeid
ScalarEvolution();
@ -636,6 +657,15 @@ namespace llvm {
SmallVector<const SCEV *, 4> NewOp(Operands.begin(), Operands.end());
return getAddRecExpr(NewOp, L, Flags);
}
/// \brief Returns an expression for a GEP
///
/// \p PointeeType The type used as the basis for the pointer arithmetics
/// \p BaseExpr The expression for the pointer operand.
/// \p IndexExprs The expressions for the indices.
/// \p InBounds Whether the GEP is in bounds.
const SCEV *getGEPExpr(Type *PointeeType, const SCEV *BaseExpr,
const SmallVectorImpl<const SCEV *> &IndexExprs,
bool InBounds = false);
const SCEV *getSMaxExpr(const SCEV *LHS, const SCEV *RHS);
const SCEV *getSMaxExpr(SmallVectorImpl<const SCEV *> &Operands);
const SCEV *getUMaxExpr(const SCEV *LHS, const SCEV *RHS);
@ -830,11 +860,15 @@ namespace llvm {
/// getUnsignedRange - Determine the unsigned range for a particular SCEV.
///
ConstantRange getUnsignedRange(const SCEV *S);
ConstantRange getUnsignedRange(const SCEV *S) {
return getRange(S, HINT_RANGE_UNSIGNED);
}
/// getSignedRange - Determine the signed range for a particular SCEV.
///
ConstantRange getSignedRange(const SCEV *S);
ConstantRange getSignedRange(const SCEV *S) {
return getRange(S, HINT_RANGE_SIGNED);
}
/// isKnownNegative - Test if the given expression is known to be negative.
///

View File

@ -28,7 +28,7 @@ namespace llvm {
/// all materialized values are safe to speculate.
bool isSafeToExpand(const SCEV *S, ScalarEvolution &SE);
/// SCEVExpander - This class uses information about analyze scalars to
/// This class uses information about analyze scalars to
/// rewrite expressions in canonical form.
///
/// Clients should create an instance of this class when rewriting is needed,
@ -36,6 +36,7 @@ namespace llvm {
/// memory.
class SCEVExpander : public SCEVVisitor<SCEVExpander, Value*> {
ScalarEvolution &SE;
const DataLayout &DL;
// New instructions receive a name to identifies them with the current pass.
const char* IVName;
@ -47,37 +48,36 @@ namespace llvm {
std::set<AssertingVH<Value> > InsertedValues;
std::set<AssertingVH<Value> > InsertedPostIncValues;
/// RelevantLoops - A memoization of the "relevant" loop for a given SCEV.
/// A memoization of the "relevant" loop for a given SCEV.
DenseMap<const SCEV *, const Loop *> RelevantLoops;
/// PostIncLoops - Addrecs referring to any of the given loops are expanded
/// \brief Addrecs referring to any of the given loops are expanded
/// in post-inc mode. For example, expanding {1,+,1}<L> in post-inc mode
/// returns the add instruction that adds one to the phi for {0,+,1}<L>,
/// as opposed to a new phi starting at 1. This is only supported in
/// non-canonical mode.
PostIncLoopSet PostIncLoops;
/// IVIncInsertPos - When this is non-null, addrecs expanded in the
/// loop it indicates should be inserted with increments at
/// IVIncInsertPos.
/// \brief When this is non-null, addrecs expanded in the loop it indicates
/// should be inserted with increments at IVIncInsertPos.
const Loop *IVIncInsertLoop;
/// IVIncInsertPos - When expanding addrecs in the IVIncInsertLoop loop,
/// insert the IV increment at this position.
/// \brief When expanding addrecs in the IVIncInsertLoop loop, insert the IV
/// increment at this position.
Instruction *IVIncInsertPos;
/// Phis that complete an IV chain. Reuse
/// \brief Phis that complete an IV chain. Reuse
std::set<AssertingVH<PHINode> > ChainedPhis;
/// CanonicalMode - When true, expressions are expanded in "canonical"
/// form. In particular, addrecs are expanded as arithmetic based on
/// a canonical induction variable. When false, expression are expanded
/// in a more literal form.
/// \brief When true, expressions are expanded in "canonical" form. In
/// particular, addrecs are expanded as arithmetic based on a canonical
/// induction variable. When false, expression are expanded in a more
/// literal form.
bool CanonicalMode;
/// When invoked from LSR, the expander is in "strength reduction" mode. The
/// only difference is that phi's are only reused if they are already in
/// "expanded" form.
/// \brief When invoked from LSR, the expander is in "strength reduction"
/// mode. The only difference is that phi's are only reused if they are
/// already in "expanded" form.
bool LSRMode;
typedef IRBuilder<true, TargetFolder> BuilderType;
@ -90,11 +90,12 @@ namespace llvm {
friend struct SCEVVisitor<SCEVExpander, Value*>;
public:
/// SCEVExpander - Construct a SCEVExpander in "canonical" mode.
explicit SCEVExpander(ScalarEvolution &se, const char *name)
: SE(se), IVName(name), IVIncInsertLoop(nullptr), IVIncInsertPos(nullptr),
CanonicalMode(true), LSRMode(false),
Builder(se.getContext(), TargetFolder(se.DL)) {
/// \brief Construct a SCEVExpander in "canonical" mode.
explicit SCEVExpander(ScalarEvolution &se, const DataLayout &DL,
const char *name)
: SE(se), DL(DL), IVName(name), IVIncInsertLoop(nullptr),
IVIncInsertPos(nullptr), CanonicalMode(true), LSRMode(false),
Builder(se.getContext(), TargetFolder(DL)) {
#ifndef NDEBUG
DebugType = "";
#endif
@ -104,7 +105,7 @@ namespace llvm {
void setDebugType(const char* s) { DebugType = s; }
#endif
/// clear - Erase the contents of the InsertedExpressions map so that users
/// \brief Erase the contents of the InsertedExpressions map so that users
/// trying to expand the same expression into multiple BasicBlocks or
/// different places within the same BasicBlock can do so.
void clear() {
@ -114,31 +115,38 @@ namespace llvm {
ChainedPhis.clear();
}
/// getOrInsertCanonicalInductionVariable - This method returns the
/// canonical induction variable of the specified type for the specified
/// loop (inserting one if there is none). A canonical induction variable
/// starts at zero and steps by one on each iteration.
/// \brief Return true for expressions that may incur non-trivial cost to
/// evaluate at runtime.
bool isHighCostExpansion(const SCEV *Expr, Loop *L) {
SmallPtrSet<const SCEV *, 8> Processed;
return isHighCostExpansionHelper(Expr, L, Processed);
}
/// \brief This method returns the canonical induction variable of the
/// specified type for the specified loop (inserting one if there is none).
/// A canonical induction variable starts at zero and steps by one on each
/// iteration.
PHINode *getOrInsertCanonicalInductionVariable(const Loop *L, Type *Ty);
/// getIVIncOperand - Return the induction variable increment's IV operand.
/// \brief Return the induction variable increment's IV operand.
Instruction *getIVIncOperand(Instruction *IncV, Instruction *InsertPos,
bool allowScale);
/// hoistIVInc - Utility for hoisting an IV increment.
/// \brief Utility for hoisting an IV increment.
bool hoistIVInc(Instruction *IncV, Instruction *InsertPos);
/// replaceCongruentIVs - replace congruent phis with their most canonical
/// \brief replace congruent phis with their most canonical
/// representative. Return the number of phis eliminated.
unsigned replaceCongruentIVs(Loop *L, const DominatorTree *DT,
SmallVectorImpl<WeakVH> &DeadInsts,
const TargetTransformInfo *TTI = nullptr);
/// expandCodeFor - Insert code to directly compute the specified SCEV
/// expression into the program. The inserted code is inserted into the
/// specified block.
/// \brief Insert code to directly compute the specified SCEV expression
/// into the program. The inserted code is inserted into the specified
/// block.
Value *expandCodeFor(const SCEV *SH, Type *Ty, Instruction *I);
/// setIVIncInsertPos - Set the current IV increment loop and position.
/// \brief Set the current IV increment loop and position.
void setIVIncInsertPos(const Loop *L, Instruction *Pos) {
assert(!CanonicalMode &&
"IV increment positions are not supported in CanonicalMode");
@ -146,16 +154,15 @@ namespace llvm {
IVIncInsertPos = Pos;
}
/// setPostInc - Enable post-inc expansion for addrecs referring to the
/// given loops. Post-inc expansion is only supported in non-canonical
/// mode.
/// \brief Enable post-inc expansion for addrecs referring to the given
/// loops. Post-inc expansion is only supported in non-canonical mode.
void setPostInc(const PostIncLoopSet &L) {
assert(!CanonicalMode &&
"Post-inc expansion is not supported in CanonicalMode");
PostIncLoops = L;
}
/// clearPostInc - Disable all post-inc expansion.
/// \brief Disable all post-inc expansion.
void clearPostInc() {
PostIncLoops.clear();
@ -164,23 +171,22 @@ namespace llvm {
InsertedPostIncValues.clear();
}
/// disableCanonicalMode - Disable the behavior of expanding expressions in
/// canonical form rather than in a more literal form. Non-canonical mode
/// is useful for late optimization passes.
/// \brief Disable the behavior of expanding expressions in canonical form
/// rather than in a more literal form. Non-canonical mode is useful for
/// late optimization passes.
void disableCanonicalMode() { CanonicalMode = false; }
void enableLSRMode() { LSRMode = true; }
/// clearInsertPoint - Clear the current insertion point. This is useful
/// if the instruction that had been serving as the insertion point may
/// have been deleted.
/// \brief Clear the current insertion point. This is useful if the
/// instruction that had been serving as the insertion point may have been
/// deleted.
void clearInsertPoint() {
Builder.ClearInsertionPoint();
}
/// isInsertedInstruction - Return true if the specified instruction was
/// inserted by the code rewriter. If so, the client should not modify the
/// instruction.
/// \brief Return true if the specified instruction was inserted by the code
/// rewriter. If so, the client should not modify the instruction.
bool isInsertedInstruction(Instruction *I) const {
return InsertedValues.count(I) || InsertedPostIncValues.count(I);
}
@ -190,24 +196,27 @@ namespace llvm {
private:
LLVMContext &getContext() const { return SE.getContext(); }
/// InsertBinop - Insert the specified binary operator, doing a small amount
/// \brief Recursive helper function for isHighCostExpansion.
bool isHighCostExpansionHelper(const SCEV *S, Loop *L,
SmallPtrSetImpl<const SCEV *> &Processed);
/// \brief Insert the specified binary operator, doing a small amount
/// of work to avoid inserting an obviously redundant operation.
Value *InsertBinop(Instruction::BinaryOps Opcode, Value *LHS, Value *RHS);
/// ReuseOrCreateCast - Arange for there to be a cast of V to Ty at IP,
/// reusing an existing cast if a suitable one exists, moving an existing
/// cast if a suitable one exists but isn't in the right place, or
/// or creating a new one.
/// \brief Arrange for there to be a cast of V to Ty at IP, reusing an
/// existing cast if a suitable one exists, moving an existing cast if a
/// suitable one exists but isn't in the right place, or or creating a new
/// one.
Value *ReuseOrCreateCast(Value *V, Type *Ty,
Instruction::CastOps Op,
BasicBlock::iterator IP);
/// InsertNoopCastOfTo - Insert a cast of V to the specified type,
/// which must be possible with a noop cast, doing what we can to
/// share the casts.
/// \brief Insert a cast of V to the specified type, which must be possible
/// with a noop cast, doing what we can to share the casts.
Value *InsertNoopCastOfTo(Value *V, Type *Ty);
/// expandAddToGEP - Expand a SCEVAddExpr with a pointer type into a GEP
/// \brief Expand a SCEVAddExpr with a pointer type into a GEP
/// instead of using ptrtoint+arithmetic+inttoptr.
Value *expandAddToGEP(const SCEV *const *op_begin,
const SCEV *const *op_end,
@ -215,13 +224,13 @@ namespace llvm {
Value *expand(const SCEV *S);
/// expandCodeFor - Insert code to directly compute the specified SCEV
/// expression into the program. The inserted code is inserted into the
/// SCEVExpander's current insertion point. If a type is specified, the
/// result will be expanded to have that type, with a cast if necessary.
/// \brief Insert code to directly compute the specified SCEV expression
/// into the program. The inserted code is inserted into the SCEVExpander's
/// current insertion point. If a type is specified, the result will be
/// expanded to have that type, with a cast if necessary.
Value *expandCodeFor(const SCEV *SH, Type *Ty = nullptr);
/// getRelevantLoop - Determine the most "relevant" loop for the given SCEV.
/// \brief Determine the most "relevant" loop for the given SCEV.
const Loop *getRelevantLoop(const SCEV *);
Value *visitConstant(const SCEVConstant *S) {

View File

@ -131,8 +131,8 @@ class SparseSolver {
typedef std::pair<BasicBlock*,BasicBlock*> Edge;
std::set<Edge> KnownFeasibleEdges;
SparseSolver(const SparseSolver&) LLVM_DELETED_FUNCTION;
void operator=(const SparseSolver&) LLVM_DELETED_FUNCTION;
SparseSolver(const SparseSolver&) = delete;
void operator=(const SparseSolver&) = delete;
public:
explicit SparseSolver(AbstractLatticeFunction *Lattice)
: LatticeFunc(Lattice) {}

View File

@ -30,7 +30,7 @@ class DataLayout;
/// TargetFolder - Create constants with target dependent folding.
class TargetFolder {
const DataLayout *DL;
const DataLayout &DL;
/// Fold - Fold the constant using target specific information.
Constant *Fold(Constant *C) const {
@ -41,7 +41,7 @@ class TargetFolder {
}
public:
explicit TargetFolder(const DataLayout *DL) : DL(DL) {}
explicit TargetFolder(const DataLayout &DL) : DL(DL) {}
//===--------------------------------------------------------------------===//
// Binary Operators
@ -130,34 +130,35 @@ class TargetFolder {
// Memory Instructions
//===--------------------------------------------------------------------===//
Constant *CreateGetElementPtr(Constant *C,
Constant *CreateGetElementPtr(Type *Ty, Constant *C,
ArrayRef<Constant *> IdxList) const {
return Fold(ConstantExpr::getGetElementPtr(C, IdxList));
return Fold(ConstantExpr::getGetElementPtr(Ty, C, IdxList));
}
Constant *CreateGetElementPtr(Constant *C, Constant *Idx) const {
Constant *CreateGetElementPtr(Type *Ty, Constant *C, Constant *Idx) const {
// This form of the function only exists to avoid ambiguous overload
// warnings about whether to convert Idx to ArrayRef<Constant *> or
// ArrayRef<Value *>.
return Fold(ConstantExpr::getGetElementPtr(C, Idx));
return Fold(ConstantExpr::getGetElementPtr(Ty, C, Idx));
}
Constant *CreateGetElementPtr(Constant *C,
Constant *CreateGetElementPtr(Type *Ty, Constant *C,
ArrayRef<Value *> IdxList) const {
return Fold(ConstantExpr::getGetElementPtr(C, IdxList));
return Fold(ConstantExpr::getGetElementPtr(Ty, C, IdxList));
}
Constant *CreateInBoundsGetElementPtr(Constant *C,
Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C,
ArrayRef<Constant *> IdxList) const {
return Fold(ConstantExpr::getInBoundsGetElementPtr(C, IdxList));
return Fold(ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList));
}
Constant *CreateInBoundsGetElementPtr(Constant *C, Constant *Idx) const {
Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C,
Constant *Idx) const {
// This form of the function only exists to avoid ambiguous overload
// warnings about whether to convert Idx to ArrayRef<Constant *> or
// ArrayRef<Value *>.
return Fold(ConstantExpr::getInBoundsGetElementPtr(C, Idx));
return Fold(ConstantExpr::getInBoundsGetElementPtr(Ty, C, Idx));
}
Constant *CreateInBoundsGetElementPtr(Constant *C,
Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C,
ArrayRef<Value *> IdxList) const {
return Fold(ConstantExpr::getInBoundsGetElementPtr(C, IdxList));
return Fold(ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList));
}
//===--------------------------------------------------------------------===//

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,328 @@
//===-- TargetLibraryInfo.h - Library information ---------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_TARGETLIBRARYINFO_H
#define LLVM_ANALYSIS_TARGETLIBRARYINFO_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/Triple.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
namespace llvm {
/// VecDesc - Describes a possible vectorization of a function.
/// Function 'VectorFnName' is equivalent to 'ScalarFnName' vectorized
/// by a factor 'VectorizationFactor'.
struct VecDesc {
const char *ScalarFnName;
const char *VectorFnName;
unsigned VectorizationFactor;
};
class PreservedAnalyses;
namespace LibFunc {
enum Func {
#define TLI_DEFINE_ENUM
#include "llvm/Analysis/TargetLibraryInfo.def"
NumLibFuncs
};
}
/// \brief Implementation of the target library information.
///
/// This class constructs tables that hold the target library information and
/// make it available. However, it is somewhat expensive to compute and only
/// depends on the triple. So users typicaly interact with the \c
/// TargetLibraryInfo wrapper below.
class TargetLibraryInfoImpl {
friend class TargetLibraryInfo;
unsigned char AvailableArray[(LibFunc::NumLibFuncs+3)/4];
llvm::DenseMap<unsigned, std::string> CustomNames;
static const char *const StandardNames[LibFunc::NumLibFuncs];
enum AvailabilityState {
StandardName = 3, // (memset to all ones)
CustomName = 1,
Unavailable = 0 // (memset to all zeros)
};
void setState(LibFunc::Func F, AvailabilityState State) {
AvailableArray[F/4] &= ~(3 << 2*(F&3));
AvailableArray[F/4] |= State << 2*(F&3);
}
AvailabilityState getState(LibFunc::Func F) const {
return static_cast<AvailabilityState>((AvailableArray[F/4] >> 2*(F&3)) & 3);
}
/// Vectorization descriptors - sorted by ScalarFnName.
std::vector<VecDesc> VectorDescs;
/// Scalarization descriptors - same content as VectorDescs but sorted based
/// on VectorFnName rather than ScalarFnName.
std::vector<VecDesc> ScalarDescs;
public:
/// \brief List of known vector-functions libraries.
///
/// The vector-functions library defines, which functions are vectorizable
/// and with which factor. The library can be specified by either frontend,
/// or a commandline option, and then used by
/// addVectorizableFunctionsFromVecLib for filling up the tables of
/// vectorizable functions.
enum VectorLibrary {
NoLibrary, // Don't use any vector library.
Accelerate // Use Accelerate framework.
};
TargetLibraryInfoImpl();
explicit TargetLibraryInfoImpl(const Triple &T);
// Provide value semantics.
TargetLibraryInfoImpl(const TargetLibraryInfoImpl &TLI);
TargetLibraryInfoImpl(TargetLibraryInfoImpl &&TLI);
TargetLibraryInfoImpl &operator=(const TargetLibraryInfoImpl &TLI);
TargetLibraryInfoImpl &operator=(TargetLibraryInfoImpl &&TLI);
/// \brief Searches for a particular function name.
///
/// If it is one of the known library functions, return true and set F to the
/// corresponding value.
bool getLibFunc(StringRef funcName, LibFunc::Func &F) const;
/// \brief Forces a function to be marked as unavailable.
void setUnavailable(LibFunc::Func F) {
setState(F, Unavailable);
}
/// \brief Forces a function to be marked as available.
void setAvailable(LibFunc::Func F) {
setState(F, StandardName);
}
/// \brief Forces a function to be marked as available and provide an
/// alternate name that must be used.
void setAvailableWithName(LibFunc::Func F, StringRef Name) {
if (StandardNames[F] != Name) {
setState(F, CustomName);
CustomNames[F] = Name;
assert(CustomNames.find(F) != CustomNames.end());
} else {
setState(F, StandardName);
}
}
/// \brief Disables all builtins.
///
/// This can be used for options like -fno-builtin.
void disableAllFunctions();
/// addVectorizableFunctions - Add a set of scalar -> vector mappings,
/// queryable via getVectorizedFunction and getScalarizedFunction.
void addVectorizableFunctions(ArrayRef<VecDesc> Fns);
/// Calls addVectorizableFunctions with a known preset of functions for the
/// given vector library.
void addVectorizableFunctionsFromVecLib(enum VectorLibrary VecLib);
/// isFunctionVectorizable - Return true if the function F has a
/// vector equivalent with vectorization factor VF.
bool isFunctionVectorizable(StringRef F, unsigned VF) const {
return !getVectorizedFunction(F, VF).empty();
}
/// isFunctionVectorizable - Return true if the function F has a
/// vector equivalent with any vectorization factor.
bool isFunctionVectorizable(StringRef F) const;
/// getVectorizedFunction - Return the name of the equivalent of
/// F, vectorized with factor VF. If no such mapping exists,
/// return the empty string.
StringRef getVectorizedFunction(StringRef F, unsigned VF) const;
/// isFunctionScalarizable - Return true if the function F has a
/// scalar equivalent, and set VF to be the vectorization factor.
bool isFunctionScalarizable(StringRef F, unsigned &VF) const {
return !getScalarizedFunction(F, VF).empty();
}
/// getScalarizedFunction - Return the name of the equivalent of
/// F, scalarized. If no such mapping exists, return the empty string.
///
/// Set VF to the vectorization factor.
StringRef getScalarizedFunction(StringRef F, unsigned &VF) const;
};
/// \brief Provides information about what library functions are available for
/// the current target.
///
/// This both allows optimizations to handle them specially and frontends to
/// disable such optimizations through -fno-builtin etc.
class TargetLibraryInfo {
friend class TargetLibraryAnalysis;
friend class TargetLibraryInfoWrapperPass;
const TargetLibraryInfoImpl *Impl;
public:
explicit TargetLibraryInfo(const TargetLibraryInfoImpl &Impl) : Impl(&Impl) {}
// Provide value semantics.
TargetLibraryInfo(const TargetLibraryInfo &TLI) : Impl(TLI.Impl) {}
TargetLibraryInfo(TargetLibraryInfo &&TLI) : Impl(TLI.Impl) {}
TargetLibraryInfo &operator=(const TargetLibraryInfo &TLI) {
Impl = TLI.Impl;
return *this;
}
TargetLibraryInfo &operator=(TargetLibraryInfo &&TLI) {
Impl = TLI.Impl;
return *this;
}
/// \brief Searches for a particular function name.
///
/// If it is one of the known library functions, return true and set F to the
/// corresponding value.
bool getLibFunc(StringRef funcName, LibFunc::Func &F) const {
return Impl->getLibFunc(funcName, F);
}
/// \brief Tests whether a library function is available.
bool has(LibFunc::Func F) const {
return Impl->getState(F) != TargetLibraryInfoImpl::Unavailable;
}
bool isFunctionVectorizable(StringRef F, unsigned VF) const {
return Impl->isFunctionVectorizable(F, VF);
};
bool isFunctionVectorizable(StringRef F) const {
return Impl->isFunctionVectorizable(F);
};
StringRef getVectorizedFunction(StringRef F, unsigned VF) const {
return Impl->getVectorizedFunction(F, VF);
};
/// \brief Tests if the function is both available and a candidate for
/// optimized code generation.
bool hasOptimizedCodeGen(LibFunc::Func F) const {
if (Impl->getState(F) == TargetLibraryInfoImpl::Unavailable)
return false;
switch (F) {
default: break;
case LibFunc::copysign: case LibFunc::copysignf: case LibFunc::copysignl:
case LibFunc::fabs: case LibFunc::fabsf: case LibFunc::fabsl:
case LibFunc::sin: case LibFunc::sinf: case LibFunc::sinl:
case LibFunc::cos: case LibFunc::cosf: case LibFunc::cosl:
case LibFunc::sqrt: case LibFunc::sqrtf: case LibFunc::sqrtl:
case LibFunc::sqrt_finite: case LibFunc::sqrtf_finite:
case LibFunc::sqrtl_finite:
case LibFunc::fmax: case LibFunc::fmaxf: case LibFunc::fmaxl:
case LibFunc::fmin: case LibFunc::fminf: case LibFunc::fminl:
case LibFunc::floor: case LibFunc::floorf: case LibFunc::floorl:
case LibFunc::nearbyint: case LibFunc::nearbyintf: case LibFunc::nearbyintl:
case LibFunc::ceil: case LibFunc::ceilf: case LibFunc::ceill:
case LibFunc::rint: case LibFunc::rintf: case LibFunc::rintl:
case LibFunc::round: case LibFunc::roundf: case LibFunc::roundl:
case LibFunc::trunc: case LibFunc::truncf: case LibFunc::truncl:
case LibFunc::log2: case LibFunc::log2f: case LibFunc::log2l:
case LibFunc::exp2: case LibFunc::exp2f: case LibFunc::exp2l:
case LibFunc::memcmp: case LibFunc::strcmp: case LibFunc::strcpy:
case LibFunc::stpcpy: case LibFunc::strlen: case LibFunc::strnlen:
case LibFunc::memchr:
return true;
}
return false;
}
StringRef getName(LibFunc::Func F) const {
auto State = Impl->getState(F);
if (State == TargetLibraryInfoImpl::Unavailable)
return StringRef();
if (State == TargetLibraryInfoImpl::StandardName)
return Impl->StandardNames[F];
assert(State == TargetLibraryInfoImpl::CustomName);
return Impl->CustomNames.find(F)->second;
}
/// \brief Handle invalidation from the pass manager.
///
/// If we try to invalidate this info, just return false. It cannot become
/// invalid even if the module changes.
bool invalidate(Module &, const PreservedAnalyses &) { return false; }
};
/// \brief Analysis pass providing the \c TargetLibraryInfo.
///
/// Note that this pass's result cannot be invalidated, it is immutable for the
/// life of the module.
class TargetLibraryAnalysis {
public:
typedef TargetLibraryInfo Result;
/// \brief Opaque, unique identifier for this analysis pass.
static void *ID() { return (void *)&PassID; }
/// \brief Default construct the library analysis.
///
/// This will use the module's triple to construct the library info for that
/// module.
TargetLibraryAnalysis() {}
/// \brief Construct a library analysis with preset info.
///
/// This will directly copy the preset info into the result without
/// consulting the module's triple.
TargetLibraryAnalysis(TargetLibraryInfoImpl PresetInfoImpl)
: PresetInfoImpl(std::move(PresetInfoImpl)) {}
// Move semantics. We spell out the constructors for MSVC.
TargetLibraryAnalysis(TargetLibraryAnalysis &&Arg)
: PresetInfoImpl(std::move(Arg.PresetInfoImpl)), Impls(std::move(Arg.Impls)) {}
TargetLibraryAnalysis &operator=(TargetLibraryAnalysis &&RHS) {
PresetInfoImpl = std::move(RHS.PresetInfoImpl);
Impls = std::move(RHS.Impls);
return *this;
}
TargetLibraryInfo run(Module &M);
TargetLibraryInfo run(Function &F);
/// \brief Provide access to a name for this pass for debugging purposes.
static StringRef name() { return "TargetLibraryAnalysis"; }
private:
static char PassID;
Optional<TargetLibraryInfoImpl> PresetInfoImpl;
StringMap<std::unique_ptr<TargetLibraryInfoImpl>> Impls;
TargetLibraryInfoImpl &lookupInfoImpl(Triple T);
};
class TargetLibraryInfoWrapperPass : public ImmutablePass {
TargetLibraryInfoImpl TLIImpl;
TargetLibraryInfo TLI;
virtual void anchor();
public:
static char ID;
TargetLibraryInfoWrapperPass();
explicit TargetLibraryInfoWrapperPass(const Triple &T);
explicit TargetLibraryInfoWrapperPass(const TargetLibraryInfoImpl &TLI);
TargetLibraryInfo &getTLI() { return TLI; }
const TargetLibraryInfo &getTLI() const { return TLI; }
};
} // end namespace llvm
#endif

View File

@ -1,4 +1,4 @@
//===- llvm/Analysis/TargetTransformInfo.h ----------------------*- C++ -*-===//
//===- TargetTransformInfo.h ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -6,66 +6,89 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass exposes codegen information to IR-level passes. Every
// transformation that uses codegen information is broken into three parts:
// 1. The IR-level analysis pass.
// 2. The IR-level transformation interface which provides the needed
// information.
// 3. Codegen-level implementation which uses target-specific hooks.
//
// This file defines #2, which is the interface that IR-level transformations
// use for querying the codegen.
//
/// \file
/// This pass exposes codegen information to IR-level passes. Every
/// transformation that uses codegen information is broken into three parts:
/// 1. The IR-level analysis pass.
/// 2. The IR-level transformation interface which provides the needed
/// information.
/// 3. Codegen-level implementation which uses target-specific hooks.
///
/// This file defines #2, which is the interface that IR-level transformations
/// use for querying the codegen.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_TARGETTRANSFORMINFO_H
#define LLVM_ANALYSIS_TARGETTRANSFORMINFO_H
#include "llvm/ADT/Optional.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/Pass.h"
#include "llvm/Support/DataTypes.h"
#include <functional>
namespace llvm {
class Function;
class GlobalValue;
class Loop;
class PreservedAnalyses;
class Type;
class User;
class Value;
/// TargetTransformInfo - This pass provides access to the codegen
/// interfaces that are needed for IR-level transformations.
/// \brief Information about a load/store intrinsic defined by the target.
struct MemIntrinsicInfo {
MemIntrinsicInfo()
: ReadMem(false), WriteMem(false), Vol(false), MatchingId(0),
NumMemRefs(0), PtrVal(nullptr) {}
bool ReadMem;
bool WriteMem;
bool Vol;
// Same Id is set by the target for corresponding load/store intrinsics.
unsigned short MatchingId;
int NumMemRefs;
Value *PtrVal;
};
/// \brief This pass provides access to the codegen interfaces that are needed
/// for IR-level transformations.
class TargetTransformInfo {
protected:
/// \brief The TTI instance one level down the stack.
///
/// This is used to implement the default behavior all of the methods which
/// is to delegate up through the stack of TTIs until one can answer the
/// query.
TargetTransformInfo *PrevTTI;
/// \brief The top of the stack of TTI analyses available.
///
/// This is a convenience routine maintained as TTI analyses become available
/// that complements the PrevTTI delegation chain. When one part of an
/// analysis pass wants to query another part of the analysis pass it can use
/// this to start back at the top of the stack.
TargetTransformInfo *TopTTI;
/// All pass subclasses must in their initializePass routine call
/// pushTTIStack with themselves to update the pointers tracking the previous
/// TTI instance in the analysis group's stack, and the top of the analysis
/// group's stack.
void pushTTIStack(Pass *P);
/// All pass subclasses must call TargetTransformInfo::getAnalysisUsage.
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
public:
/// This class is intended to be subclassed by real implementations.
virtual ~TargetTransformInfo() = 0;
/// \brief Construct a TTI object using a type implementing the \c Concept
/// API below.
///
/// This is used by targets to construct a TTI wrapping their target-specific
/// implementaion that encodes appropriate costs for their target.
template <typename T> TargetTransformInfo(T Impl);
/// \brief Construct a baseline TTI object using a minimal implementation of
/// the \c Concept API below.
///
/// The TTI implementation will reflect the information in the DataLayout
/// provided if non-null.
explicit TargetTransformInfo(const DataLayout *DL);
// Provide move semantics.
TargetTransformInfo(TargetTransformInfo &&Arg);
TargetTransformInfo &operator=(TargetTransformInfo &&RHS);
// We need to define the destructor out-of-line to define our sub-classes
// out-of-line.
~TargetTransformInfo();
/// \brief Handle the invalidation of this information.
///
/// When used as a result of \c TargetIRAnalysis this method will be called
/// when the function this was computed for changes. When it returns false,
/// the information is preserved across those changes.
bool invalidate(Function &, const PreservedAnalyses &) {
// FIXME: We should probably in some way ensure that the subtarget
// information for a function hasn't changed.
return false;
}
/// \name Generic Target Information
/// @{
@ -86,9 +109,9 @@ class TargetTransformInfo {
/// skipped by renaming the registers in the CPU, but they still are encoded
/// and thus wouldn't be considered 'free' here.
enum TargetCostConstants {
TCC_Free = 0, ///< Expected to fold away in lowering.
TCC_Basic = 1, ///< The cost of a typical 'add' instruction.
TCC_Expensive = 4 ///< The cost of a 'div' instruction on x86.
TCC_Free = 0, ///< Expected to fold away in lowering.
TCC_Basic = 1, ///< The cost of a typical 'add' instruction.
TCC_Expensive = 4 ///< The cost of a 'div' instruction on x86.
};
/// \brief Estimate the cost of a specific operation when lowered.
@ -105,16 +128,15 @@ class TargetTransformInfo {
///
/// The returned cost is defined in terms of \c TargetCostConstants, see its
/// comments for a detailed explanation of the cost values.
virtual unsigned getOperationCost(unsigned Opcode, Type *Ty,
Type *OpTy = nullptr) const;
unsigned getOperationCost(unsigned Opcode, Type *Ty,
Type *OpTy = nullptr) const;
/// \brief Estimate the cost of a GEP operation when lowered.
///
/// The contract for this function is the same as \c getOperationCost except
/// that it supports an interface that provides extra information specific to
/// the GEP operation.
virtual unsigned getGEPCost(const Value *Ptr,
ArrayRef<const Value *> Operands) const;
unsigned getGEPCost(const Value *Ptr, ArrayRef<const Value *> Operands) const;
/// \brief Estimate the cost of a function call when lowered.
///
@ -125,31 +147,31 @@ class TargetTransformInfo {
/// This is the most basic query for estimating call cost: it only knows the
/// function type and (potentially) the number of arguments at the call site.
/// The latter is only interesting for varargs function types.
virtual unsigned getCallCost(FunctionType *FTy, int NumArgs = -1) const;
unsigned getCallCost(FunctionType *FTy, int NumArgs = -1) const;
/// \brief Estimate the cost of calling a specific function when lowered.
///
/// This overload adds the ability to reason about the particular function
/// being called in the event it is a library call with special lowering.
virtual unsigned getCallCost(const Function *F, int NumArgs = -1) const;
unsigned getCallCost(const Function *F, int NumArgs = -1) const;
/// \brief Estimate the cost of calling a specific function when lowered.
///
/// This overload allows specifying a set of candidate argument values.
virtual unsigned getCallCost(const Function *F,
ArrayRef<const Value *> Arguments) const;
unsigned getCallCost(const Function *F,
ArrayRef<const Value *> Arguments) const;
/// \brief Estimate the cost of an intrinsic when lowered.
///
/// Mirrors the \c getCallCost method but uses an intrinsic identifier.
virtual unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
ArrayRef<Type *> ParamTys) const;
unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
ArrayRef<Type *> ParamTys) const;
/// \brief Estimate the cost of an intrinsic when lowered.
///
/// Mirrors the \c getCallCost method but uses an intrinsic identifier.
virtual unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
ArrayRef<const Value *> Arguments) const;
unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
ArrayRef<const Value *> Arguments) const;
/// \brief Estimate the cost of a given IR user when lowered.
///
@ -166,13 +188,22 @@ class TargetTransformInfo {
///
/// The returned cost is defined in terms of \c TargetCostConstants, see its
/// comments for a detailed explanation of the cost values.
virtual unsigned getUserCost(const User *U) const;
unsigned getUserCost(const User *U) const;
/// \brief hasBranchDivergence - Return true if branch divergence exists.
/// \brief Return true if branch divergence exists.
///
/// Branch divergence has a significantly negative impact on GPU performance
/// when threads in the same wavefront take different paths due to conditional
/// branches.
virtual bool hasBranchDivergence() const;
bool hasBranchDivergence() const;
/// \brief Returns whether V is a source of divergence.
///
/// This function provides the target-dependent information for
/// the target-independent DivergenceAnalysis. DivergenceAnalysis first
/// builds the dependency graph, and then runs the reachability algorithm
/// starting with the sources of divergence.
bool isSourceOfDivergence(const Value *V) const;
/// \brief Test whether calls to a function lower to actual program function
/// calls.
@ -186,7 +217,7 @@ class TargetTransformInfo {
/// and execution-speed costs. This would allow modelling the core of this
/// query more accurately as a call is a single small instruction, but
/// incurs significant execution cost.
virtual bool isLoweredToCall(const Function *F) const;
bool isLoweredToCall(const Function *F) const;
/// Parameters that control the generic loop unrolling transformation.
struct UnrollingPreferences {
@ -196,6 +227,13 @@ class TargetTransformInfo {
/// exceed this cost. Set this to UINT_MAX to disable the loop body cost
/// restriction.
unsigned Threshold;
/// If complete unrolling could help other optimizations (e.g. InstSimplify)
/// to remove N% of instructions, then we can go beyond unroll threshold.
/// This value set the minimal percent for allowing that.
unsigned MinPercentOfOptimized;
/// The absolute cost threshold. We won't go beyond this even if complete
/// unrolling could result in optimizing out 90% of instructions.
unsigned AbsoluteThreshold;
/// The cost threshold for the unrolled loop when optimizing for size (set
/// to UINT_MAX to disable).
unsigned OptSizeThreshold;
@ -203,8 +241,8 @@ class TargetTransformInfo {
/// for partial/runtime unrolling (set to UINT_MAX to disable).
unsigned PartialThreshold;
/// The cost threshold for the unrolled loop when optimizing for size, like
/// OptSizeThreshold, but used for partial/runtime unrolling (set to UINT_MAX
/// to disable).
/// OptSizeThreshold, but used for partial/runtime unrolling (set to
/// UINT_MAX to disable).
unsigned PartialOptSizeThreshold;
/// A forced unrolling factor (the number of concatenated bodies of the
/// original loop in the unrolled loop body). When set to 0, the unrolling
@ -218,18 +256,20 @@ class TargetTransformInfo {
unsigned MaxCount;
/// Allow partial unrolling (unrolling of loops to expand the size of the
/// loop body, not only to eliminate small constant-trip-count loops).
bool Partial;
bool Partial;
/// Allow runtime unrolling (unrolling of loops to expand the size of the
/// loop body even when the number of loop iterations is not known at compile
/// time).
bool Runtime;
/// loop body even when the number of loop iterations is not known at
/// compile time).
bool Runtime;
/// Allow emitting expensive instructions (such as divisions) when computing
/// the trip count of a loop for runtime unrolling.
bool AllowExpensiveTripCount;
};
/// \brief Get target-customized preferences for the generic loop unrolling
/// transformation. The caller will initialize UP with the current
/// target-independent defaults.
virtual void getUnrollingPreferences(const Function *F, Loop *L,
UnrollingPreferences &UP) const;
void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) const;
/// @}
@ -244,38 +284,33 @@ class TargetTransformInfo {
/// support is considered as "Fast" if it can outperform, or is on a par
/// with, SW implementation when the population is sparse; otherwise, it is
/// considered as "Slow".
enum PopcntSupportKind {
PSK_Software,
PSK_SlowHardware,
PSK_FastHardware
};
enum PopcntSupportKind { PSK_Software, PSK_SlowHardware, PSK_FastHardware };
/// \brief Return true if the specified immediate is legal add immediate, that
/// is the target has add instructions which can add a register with the
/// immediate without having to materialize the immediate into a register.
virtual bool isLegalAddImmediate(int64_t Imm) const;
bool isLegalAddImmediate(int64_t Imm) const;
/// \brief Return true if the specified immediate is legal icmp immediate,
/// that is the target has icmp instructions which can compare a register
/// against the immediate without having to materialize the immediate into a
/// register.
virtual bool isLegalICmpImmediate(int64_t Imm) const;
bool isLegalICmpImmediate(int64_t Imm) const;
/// \brief Return true if the addressing mode represented by AM is legal for
/// this target, for a load/store of the specified type.
/// The type may be VoidTy, in which case only return true if the addressing
/// mode is legal for a load/store of any legal type.
/// TODO: Handle pre/postinc as well.
virtual bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV,
int64_t BaseOffset, bool HasBaseReg,
int64_t Scale) const;
bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
bool HasBaseReg, int64_t Scale) const;
/// \brief Return true if the target works with masked instruction
/// AVX2 allows masks for consecutive load and store for i32 and i64 elements.
/// AVX-512 architecture will also allow masks for non-consecutive memory
/// accesses.
virtual bool isLegalMaskedStore(Type *DataType, int Consecutive) const;
virtual bool isLegalMaskedLoad (Type *DataType, int Consecutive) const;
bool isLegalMaskedStore(Type *DataType, int Consecutive) const;
bool isLegalMaskedLoad(Type *DataType, int Consecutive) const;
/// \brief Return the cost of the scaling factor used in the addressing
/// mode represented by AM for this target, for a load/store
@ -283,45 +318,55 @@ class TargetTransformInfo {
/// If the AM is supported, the return value must be >= 0.
/// If the AM is not supported, it returns a negative value.
/// TODO: Handle pre/postinc as well.
virtual int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV,
int64_t BaseOffset, bool HasBaseReg,
int64_t Scale) const;
int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
bool HasBaseReg, int64_t Scale) const;
/// \brief Return true if it's free to truncate a value of type Ty1 to type
/// Ty2. e.g. On x86 it's free to truncate a i32 value in register EAX to i16
/// by referencing its sub-register AX.
virtual bool isTruncateFree(Type *Ty1, Type *Ty2) const;
bool isTruncateFree(Type *Ty1, Type *Ty2) const;
/// \brief Return true if it is profitable to hoist instruction in the
/// then/else to before if.
bool isProfitableToHoist(Instruction *I) const;
/// \brief Return true if this type is legal.
virtual bool isTypeLegal(Type *Ty) const;
bool isTypeLegal(Type *Ty) const;
/// \brief Returns the target's jmp_buf alignment in bytes.
virtual unsigned getJumpBufAlignment() const;
unsigned getJumpBufAlignment() const;
/// \brief Returns the target's jmp_buf size in bytes.
virtual unsigned getJumpBufSize() const;
unsigned getJumpBufSize() const;
/// \brief Return true if switches should be turned into lookup tables for the
/// target.
virtual bool shouldBuildLookupTables() const;
bool shouldBuildLookupTables() const;
/// \brief Don't restrict interleaved unrolling to small loops.
bool enableAggressiveInterleaving(bool LoopHasReductions) const;
/// \brief Return hardware support for population count.
virtual PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) const;
PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) const;
/// \brief Return true if the hardware has a fast square-root instruction.
virtual bool haveFastSqrt(Type *Ty) const;
bool haveFastSqrt(Type *Ty) const;
/// \brief Return the expected cost of supporting the floating point operation
/// of the specified type.
unsigned getFPOpCost(Type *Ty) const;
/// \brief Return the expected cost of materializing for the given integer
/// immediate of the specified type.
virtual unsigned getIntImmCost(const APInt &Imm, Type *Ty) const;
unsigned getIntImmCost(const APInt &Imm, Type *Ty) const;
/// \brief Return the expected cost of materialization for the given integer
/// immediate of the specified type for a given instruction. The cost can be
/// zero if the immediate can be folded into the specified instruction.
virtual unsigned getIntImmCost(unsigned Opc, unsigned Idx, const APInt &Imm,
Type *Ty) const;
virtual unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx,
const APInt &Imm, Type *Ty) const;
unsigned getIntImmCost(unsigned Opc, unsigned Idx, const APInt &Imm,
Type *Ty) const;
unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx, const APInt &Imm,
Type *Ty) const;
/// @}
/// \name Vector Target Information
@ -338,10 +383,10 @@ class TargetTransformInfo {
/// \brief Additional information about an operand's possible values.
enum OperandValueKind {
OK_AnyValue, // Operand can have any value.
OK_UniformValue, // Operand is uniform (splat of a value).
OK_UniformConstantValue, // Operand is uniform constant.
OK_NonUniformConstantValue // Operand is a non uniform constant value.
OK_AnyValue, // Operand can have any value.
OK_UniformValue, // Operand is uniform (splat of a value).
OK_UniformConstantValue, // Operand is uniform constant.
OK_NonUniformConstantValue // Operand is a non uniform constant value.
};
/// \brief Additional properties of an operand's values.
@ -350,18 +395,18 @@ class TargetTransformInfo {
/// \return The number of scalar or vector registers that the target has.
/// If 'Vectors' is true, it returns the number of vector registers. If it is
/// set to false, it returns the number of scalar registers.
virtual unsigned getNumberOfRegisters(bool Vector) const;
unsigned getNumberOfRegisters(bool Vector) const;
/// \return The width of the largest scalar or vector register type.
virtual unsigned getRegisterBitWidth(bool Vector) const;
unsigned getRegisterBitWidth(bool Vector) const;
/// \return The maximum interleave factor that any transform should try to
/// perform for this target. This number depends on the level of parallelism
/// and the number of execution units in the CPU.
virtual unsigned getMaxInterleaveFactor() const;
unsigned getMaxInterleaveFactor(unsigned VF) const;
/// \return The expected cost of arithmetic ops, such as mul, xor, fsub, etc.
virtual unsigned
unsigned
getArithmeticInstrCost(unsigned Opcode, Type *Ty,
OperandValueKind Opd1Info = OK_AnyValue,
OperandValueKind Opd2Info = OK_AnyValue,
@ -371,31 +416,33 @@ class TargetTransformInfo {
/// \return The cost of a shuffle instruction of kind Kind and of type Tp.
/// The index and subtype parameters are used by the subvector insertion and
/// extraction shuffle kinds.
virtual unsigned getShuffleCost(ShuffleKind Kind, Type *Tp, int Index = 0,
Type *SubTp = nullptr) const;
unsigned getShuffleCost(ShuffleKind Kind, Type *Tp, int Index = 0,
Type *SubTp = nullptr) const;
/// \return The expected cost of cast instructions, such as bitcast, trunc,
/// zext, etc.
virtual unsigned getCastInstrCost(unsigned Opcode, Type *Dst,
Type *Src) const;
unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) const;
/// \return The expected cost of control-flow related instructions such as
/// Phi, Ret, Br.
virtual unsigned getCFInstrCost(unsigned Opcode) const;
unsigned getCFInstrCost(unsigned Opcode) const;
/// \returns The expected cost of compare and select instructions.
virtual unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy,
Type *CondTy = nullptr) const;
unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy,
Type *CondTy = nullptr) const;
/// \return The expected cost of vector Insert and Extract.
/// Use -1 to indicate that there is no information on the index value.
virtual unsigned getVectorInstrCost(unsigned Opcode, Type *Val,
unsigned Index = -1) const;
unsigned getVectorInstrCost(unsigned Opcode, Type *Val,
unsigned Index = -1) const;
/// \return The cost of Load and Store instructions.
virtual unsigned getMemoryOpCost(unsigned Opcode, Type *Src,
unsigned Alignment,
unsigned AddressSpace) const;
unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment,
unsigned AddressSpace) const;
/// \return The cost of masked Load and Store instructions.
unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment,
unsigned AddressSpace) const;
/// \brief Calculate the cost of performing a vector reduction.
///
@ -410,16 +457,20 @@ class TargetTransformInfo {
/// Split:
/// (v0, v1, v2, v3)
/// ((v0+v2), (v1+v3), undef, undef)
virtual unsigned getReductionCost(unsigned Opcode, Type *Ty,
bool IsPairwiseForm) const;
unsigned getReductionCost(unsigned Opcode, Type *Ty,
bool IsPairwiseForm) const;
/// \returns The cost of Intrinsic instructions.
virtual unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
ArrayRef<Type *> Tys) const;
unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
ArrayRef<Type *> Tys) const;
/// \returns The cost of Call instructions.
unsigned getCallInstrCost(Function *F, Type *RetTy,
ArrayRef<Type *> Tys) const;
/// \returns The number of pieces into which the provided type must be
/// split during legalization. Zero is returned when the answer is unknown.
virtual unsigned getNumberOfParts(Type *Tp) const;
unsigned getNumberOfParts(Type *Tp) const;
/// \returns The cost of the address computation. For most targets this can be
/// merged into the instruction indexing mode. Some targets might want to
@ -428,28 +479,399 @@ class TargetTransformInfo {
/// The 'IsComplex' parameter is a hint that the address computation is likely
/// to involve multiple instructions and as such unlikely to be merged into
/// the address indexing mode.
virtual unsigned getAddressComputationCost(Type *Ty,
bool IsComplex = false) const;
unsigned getAddressComputationCost(Type *Ty, bool IsComplex = false) const;
/// \returns The cost, if any, of keeping values of the given types alive
/// over a callsite.
///
/// Some types may require the use of register classes that do not have
/// any callee-saved registers, so would require a spill and fill.
virtual unsigned getCostOfKeepingLiveOverCall(ArrayRef<Type*> Tys) const;
unsigned getCostOfKeepingLiveOverCall(ArrayRef<Type *> Tys) const;
/// \returns True if the intrinsic is a supported memory intrinsic. Info
/// will contain additional information - whether the intrinsic may write
/// or read to memory, volatility and the pointer. Info is undefined
/// if false is returned.
bool getTgtMemIntrinsic(IntrinsicInst *Inst, MemIntrinsicInfo &Info) const;
/// \returns A value which is the result of the given memory intrinsic. New
/// instructions may be created to extract the result from the given intrinsic
/// memory operation. Returns nullptr if the target cannot create a result
/// from the given intrinsic.
Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst,
Type *ExpectedType) const;
/// @}
/// Analysis group identification.
static char ID;
private:
/// \brief The abstract base class used to type erase specific TTI
/// implementations.
class Concept;
/// \brief The template model for the base class which wraps a concrete
/// implementation in a type erased interface.
template <typename T> class Model;
std::unique_ptr<Concept> TTIImpl;
};
/// \brief Create the base case instance of a pass in the TTI analysis group.
class TargetTransformInfo::Concept {
public:
virtual ~Concept() = 0;
virtual unsigned getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy) = 0;
virtual unsigned getGEPCost(const Value *Ptr,
ArrayRef<const Value *> Operands) = 0;
virtual unsigned getCallCost(FunctionType *FTy, int NumArgs) = 0;
virtual unsigned getCallCost(const Function *F, int NumArgs) = 0;
virtual unsigned getCallCost(const Function *F,
ArrayRef<const Value *> Arguments) = 0;
virtual unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
ArrayRef<Type *> ParamTys) = 0;
virtual unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
ArrayRef<const Value *> Arguments) = 0;
virtual unsigned getUserCost(const User *U) = 0;
virtual bool hasBranchDivergence() = 0;
virtual bool isSourceOfDivergence(const Value *V) = 0;
virtual bool isLoweredToCall(const Function *F) = 0;
virtual void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) = 0;
virtual bool isLegalAddImmediate(int64_t Imm) = 0;
virtual bool isLegalICmpImmediate(int64_t Imm) = 0;
virtual bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV,
int64_t BaseOffset, bool HasBaseReg,
int64_t Scale) = 0;
virtual bool isLegalMaskedStore(Type *DataType, int Consecutive) = 0;
virtual bool isLegalMaskedLoad(Type *DataType, int Consecutive) = 0;
virtual int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV,
int64_t BaseOffset, bool HasBaseReg,
int64_t Scale) = 0;
virtual bool isTruncateFree(Type *Ty1, Type *Ty2) = 0;
virtual bool isProfitableToHoist(Instruction *I) = 0;
virtual bool isTypeLegal(Type *Ty) = 0;
virtual unsigned getJumpBufAlignment() = 0;
virtual unsigned getJumpBufSize() = 0;
virtual bool shouldBuildLookupTables() = 0;
virtual bool enableAggressiveInterleaving(bool LoopHasReductions) = 0;
virtual PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) = 0;
virtual bool haveFastSqrt(Type *Ty) = 0;
virtual unsigned getFPOpCost(Type *Ty) = 0;
virtual unsigned getIntImmCost(const APInt &Imm, Type *Ty) = 0;
virtual unsigned getIntImmCost(unsigned Opc, unsigned Idx, const APInt &Imm,
Type *Ty) = 0;
virtual unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx,
const APInt &Imm, Type *Ty) = 0;
virtual unsigned getNumberOfRegisters(bool Vector) = 0;
virtual unsigned getRegisterBitWidth(bool Vector) = 0;
virtual unsigned getMaxInterleaveFactor(unsigned VF) = 0;
virtual unsigned
getArithmeticInstrCost(unsigned Opcode, Type *Ty, OperandValueKind Opd1Info,
OperandValueKind Opd2Info,
OperandValueProperties Opd1PropInfo,
OperandValueProperties Opd2PropInfo) = 0;
virtual unsigned getShuffleCost(ShuffleKind Kind, Type *Tp, int Index,
Type *SubTp) = 0;
virtual unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) = 0;
virtual unsigned getCFInstrCost(unsigned Opcode) = 0;
virtual unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy,
Type *CondTy) = 0;
virtual unsigned getVectorInstrCost(unsigned Opcode, Type *Val,
unsigned Index) = 0;
virtual unsigned getMemoryOpCost(unsigned Opcode, Type *Src,
unsigned Alignment,
unsigned AddressSpace) = 0;
virtual unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src,
unsigned Alignment,
unsigned AddressSpace) = 0;
virtual unsigned getReductionCost(unsigned Opcode, Type *Ty,
bool IsPairwiseForm) = 0;
virtual unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
ArrayRef<Type *> Tys) = 0;
virtual unsigned getCallInstrCost(Function *F, Type *RetTy,
ArrayRef<Type *> Tys) = 0;
virtual unsigned getNumberOfParts(Type *Tp) = 0;
virtual unsigned getAddressComputationCost(Type *Ty, bool IsComplex) = 0;
virtual unsigned getCostOfKeepingLiveOverCall(ArrayRef<Type *> Tys) = 0;
virtual bool getTgtMemIntrinsic(IntrinsicInst *Inst,
MemIntrinsicInfo &Info) = 0;
virtual Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst,
Type *ExpectedType) = 0;
};
template <typename T>
class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
T Impl;
public:
Model(T Impl) : Impl(std::move(Impl)) {}
~Model() override {}
unsigned getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy) override {
return Impl.getOperationCost(Opcode, Ty, OpTy);
}
unsigned getGEPCost(const Value *Ptr,
ArrayRef<const Value *> Operands) override {
return Impl.getGEPCost(Ptr, Operands);
}
unsigned getCallCost(FunctionType *FTy, int NumArgs) override {
return Impl.getCallCost(FTy, NumArgs);
}
unsigned getCallCost(const Function *F, int NumArgs) override {
return Impl.getCallCost(F, NumArgs);
}
unsigned getCallCost(const Function *F,
ArrayRef<const Value *> Arguments) override {
return Impl.getCallCost(F, Arguments);
}
unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
ArrayRef<Type *> ParamTys) override {
return Impl.getIntrinsicCost(IID, RetTy, ParamTys);
}
unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
ArrayRef<const Value *> Arguments) override {
return Impl.getIntrinsicCost(IID, RetTy, Arguments);
}
unsigned getUserCost(const User *U) override { return Impl.getUserCost(U); }
bool hasBranchDivergence() override { return Impl.hasBranchDivergence(); }
bool isSourceOfDivergence(const Value *V) override {
return Impl.isSourceOfDivergence(V);
}
bool isLoweredToCall(const Function *F) override {
return Impl.isLoweredToCall(F);
}
void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) override {
return Impl.getUnrollingPreferences(L, UP);
}
bool isLegalAddImmediate(int64_t Imm) override {
return Impl.isLegalAddImmediate(Imm);
}
bool isLegalICmpImmediate(int64_t Imm) override {
return Impl.isLegalICmpImmediate(Imm);
}
bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
bool HasBaseReg, int64_t Scale) override {
return Impl.isLegalAddressingMode(Ty, BaseGV, BaseOffset, HasBaseReg,
Scale);
}
bool isLegalMaskedStore(Type *DataType, int Consecutive) override {
return Impl.isLegalMaskedStore(DataType, Consecutive);
}
bool isLegalMaskedLoad(Type *DataType, int Consecutive) override {
return Impl.isLegalMaskedLoad(DataType, Consecutive);
}
int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
bool HasBaseReg, int64_t Scale) override {
return Impl.getScalingFactorCost(Ty, BaseGV, BaseOffset, HasBaseReg, Scale);
}
bool isTruncateFree(Type *Ty1, Type *Ty2) override {
return Impl.isTruncateFree(Ty1, Ty2);
}
bool isProfitableToHoist(Instruction *I) override {
return Impl.isProfitableToHoist(I);
}
bool isTypeLegal(Type *Ty) override { return Impl.isTypeLegal(Ty); }
unsigned getJumpBufAlignment() override { return Impl.getJumpBufAlignment(); }
unsigned getJumpBufSize() override { return Impl.getJumpBufSize(); }
bool shouldBuildLookupTables() override {
return Impl.shouldBuildLookupTables();
}
bool enableAggressiveInterleaving(bool LoopHasReductions) override {
return Impl.enableAggressiveInterleaving(LoopHasReductions);
}
PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) override {
return Impl.getPopcntSupport(IntTyWidthInBit);
}
bool haveFastSqrt(Type *Ty) override { return Impl.haveFastSqrt(Ty); }
unsigned getFPOpCost(Type *Ty) override {
return Impl.getFPOpCost(Ty);
}
unsigned getIntImmCost(const APInt &Imm, Type *Ty) override {
return Impl.getIntImmCost(Imm, Ty);
}
unsigned getIntImmCost(unsigned Opc, unsigned Idx, const APInt &Imm,
Type *Ty) override {
return Impl.getIntImmCost(Opc, Idx, Imm, Ty);
}
unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx, const APInt &Imm,
Type *Ty) override {
return Impl.getIntImmCost(IID, Idx, Imm, Ty);
}
unsigned getNumberOfRegisters(bool Vector) override {
return Impl.getNumberOfRegisters(Vector);
}
unsigned getRegisterBitWidth(bool Vector) override {
return Impl.getRegisterBitWidth(Vector);
}
unsigned getMaxInterleaveFactor(unsigned VF) override {
return Impl.getMaxInterleaveFactor(VF);
}
unsigned
getArithmeticInstrCost(unsigned Opcode, Type *Ty, OperandValueKind Opd1Info,
OperandValueKind Opd2Info,
OperandValueProperties Opd1PropInfo,
OperandValueProperties Opd2PropInfo) override {
return Impl.getArithmeticInstrCost(Opcode, Ty, Opd1Info, Opd2Info,
Opd1PropInfo, Opd2PropInfo);
}
unsigned getShuffleCost(ShuffleKind Kind, Type *Tp, int Index,
Type *SubTp) override {
return Impl.getShuffleCost(Kind, Tp, Index, SubTp);
}
unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) override {
return Impl.getCastInstrCost(Opcode, Dst, Src);
}
unsigned getCFInstrCost(unsigned Opcode) override {
return Impl.getCFInstrCost(Opcode);
}
unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy,
Type *CondTy) override {
return Impl.getCmpSelInstrCost(Opcode, ValTy, CondTy);
}
unsigned getVectorInstrCost(unsigned Opcode, Type *Val,
unsigned Index) override {
return Impl.getVectorInstrCost(Opcode, Val, Index);
}
unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment,
unsigned AddressSpace) override {
return Impl.getMemoryOpCost(Opcode, Src, Alignment, AddressSpace);
}
unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment,
unsigned AddressSpace) override {
return Impl.getMaskedMemoryOpCost(Opcode, Src, Alignment, AddressSpace);
}
unsigned getReductionCost(unsigned Opcode, Type *Ty,
bool IsPairwiseForm) override {
return Impl.getReductionCost(Opcode, Ty, IsPairwiseForm);
}
unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
ArrayRef<Type *> Tys) override {
return Impl.getIntrinsicInstrCost(ID, RetTy, Tys);
}
unsigned getCallInstrCost(Function *F, Type *RetTy,
ArrayRef<Type *> Tys) override {
return Impl.getCallInstrCost(F, RetTy, Tys);
}
unsigned getNumberOfParts(Type *Tp) override {
return Impl.getNumberOfParts(Tp);
}
unsigned getAddressComputationCost(Type *Ty, bool IsComplex) override {
return Impl.getAddressComputationCost(Ty, IsComplex);
}
unsigned getCostOfKeepingLiveOverCall(ArrayRef<Type *> Tys) override {
return Impl.getCostOfKeepingLiveOverCall(Tys);
}
bool getTgtMemIntrinsic(IntrinsicInst *Inst,
MemIntrinsicInfo &Info) override {
return Impl.getTgtMemIntrinsic(Inst, Info);
}
Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst,
Type *ExpectedType) override {
return Impl.getOrCreateResultFromMemIntrinsic(Inst, ExpectedType);
}
};
template <typename T>
TargetTransformInfo::TargetTransformInfo(T Impl)
: TTIImpl(new Model<T>(Impl)) {}
/// \brief Analysis pass providing the \c TargetTransformInfo.
///
/// This class provides the base case for the stack of TTI analyzes. It doesn't
/// delegate to anything and uses the STTI and VTTI objects passed in to
/// satisfy the queries.
ImmutablePass *createNoTargetTransformInfoPass();
/// The core idea of the TargetIRAnalysis is to expose an interface through
/// which LLVM targets can analyze and provide information about the middle
/// end's target-independent IR. This supports use cases such as target-aware
/// cost modeling of IR constructs.
///
/// This is a function analysis because much of the cost modeling for targets
/// is done in a subtarget specific way and LLVM supports compiling different
/// functions targeting different subtargets in order to support runtime
/// dispatch according to the observed subtarget.
class TargetIRAnalysis {
public:
typedef TargetTransformInfo Result;
/// \brief Opaque, unique identifier for this analysis pass.
static void *ID() { return (void *)&PassID; }
/// \brief Provide access to a name for this pass for debugging purposes.
static StringRef name() { return "TargetIRAnalysis"; }
/// \brief Default construct a target IR analysis.
///
/// This will use the module's datalayout to construct a baseline
/// conservative TTI result.
TargetIRAnalysis();
/// \brief Construct an IR analysis pass around a target-provide callback.
///
/// The callback will be called with a particular function for which the TTI
/// is needed and must return a TTI object for that function.
TargetIRAnalysis(std::function<Result(Function &)> TTICallback);
// Value semantics. We spell out the constructors for MSVC.
TargetIRAnalysis(const TargetIRAnalysis &Arg)
: TTICallback(Arg.TTICallback) {}
TargetIRAnalysis(TargetIRAnalysis &&Arg)
: TTICallback(std::move(Arg.TTICallback)) {}
TargetIRAnalysis &operator=(const TargetIRAnalysis &RHS) {
TTICallback = RHS.TTICallback;
return *this;
}
TargetIRAnalysis &operator=(TargetIRAnalysis &&RHS) {
TTICallback = std::move(RHS.TTICallback);
return *this;
}
Result run(Function &F);
private:
static char PassID;
/// \brief The callback used to produce a result.
///
/// We use a completely opaque callback so that targets can provide whatever
/// mechanism they desire for constructing the TTI for a given function.
///
/// FIXME: Should we really use std::function? It's relatively inefficient.
/// It might be possible to arrange for even stateful callbacks to outlive
/// the analysis and thus use a function_ref which would be lighter weight.
/// This may also be less error prone as the callback is likely to reference
/// the external TargetMachine, and that reference needs to never dangle.
std::function<Result(Function &)> TTICallback;
/// \brief Helper function used as the callback in the default constructor.
static Result getDefaultTTI(Function &F);
};
/// \brief Wrapper pass for TargetTransformInfo.
///
/// This pass can be constructed from a TTI object which it stores internally
/// and is queried by passes.
class TargetTransformInfoWrapperPass : public ImmutablePass {
TargetIRAnalysis TIRA;
Optional<TargetTransformInfo> TTI;
virtual void anchor();
public:
static char ID;
/// \brief We must provide a default constructor for the pass but it should
/// never be used.
///
/// Use the constructor below or call one of the creation routines.
TargetTransformInfoWrapperPass();
explicit TargetTransformInfoWrapperPass(TargetIRAnalysis TIRA);
TargetTransformInfo &getTTI(Function &F);
};
/// \brief Create an analysis pass wrapper around a TTI object.
///
/// This analysis pass just holds the TTI instance and makes it available to
/// clients.
ImmutablePass *createTargetTransformInfoWrapperPass(TargetIRAnalysis TIRA);
} // End llvm namespace

View File

@ -0,0 +1,441 @@
//===- TargetTransformInfoImpl.h --------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
/// This file provides helpers for the implementation of
/// a TargetTransformInfo-conforming class.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_TARGETTRANSFORMINFOIMPL_H
#define LLVM_ANALYSIS_TARGETTRANSFORMINFOIMPL_H
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/Type.h"
namespace llvm {
/// \brief Base class for use as a mix-in that aids implementing
/// a TargetTransformInfo-compatible class.
class TargetTransformInfoImplBase {
protected:
typedef TargetTransformInfo TTI;
const DataLayout *DL;
explicit TargetTransformInfoImplBase(const DataLayout *DL)
: DL(DL) {}
public:
// Provide value semantics. MSVC requires that we spell all of these out.
TargetTransformInfoImplBase(const TargetTransformInfoImplBase &Arg)
: DL(Arg.DL) {}
TargetTransformInfoImplBase(TargetTransformInfoImplBase &&Arg)
: DL(std::move(Arg.DL)) {}
TargetTransformInfoImplBase &
operator=(const TargetTransformInfoImplBase &RHS) {
DL = RHS.DL;
return *this;
}
TargetTransformInfoImplBase &operator=(TargetTransformInfoImplBase &&RHS) {
DL = std::move(RHS.DL);
return *this;
}
unsigned getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy) {
switch (Opcode) {
default:
// By default, just classify everything as 'basic'.
return TTI::TCC_Basic;
case Instruction::GetElementPtr:
llvm_unreachable("Use getGEPCost for GEP operations!");
case Instruction::BitCast:
assert(OpTy && "Cast instructions must provide the operand type");
if (Ty == OpTy || (Ty->isPointerTy() && OpTy->isPointerTy()))
// Identity and pointer-to-pointer casts are free.
return TTI::TCC_Free;
// Otherwise, the default basic cost is used.
return TTI::TCC_Basic;
case Instruction::IntToPtr: {
if (!DL)
return TTI::TCC_Basic;
// An inttoptr cast is free so long as the input is a legal integer type
// which doesn't contain values outside the range of a pointer.
unsigned OpSize = OpTy->getScalarSizeInBits();
if (DL->isLegalInteger(OpSize) &&
OpSize <= DL->getPointerTypeSizeInBits(Ty))
return TTI::TCC_Free;
// Otherwise it's not a no-op.
return TTI::TCC_Basic;
}
case Instruction::PtrToInt: {
if (!DL)
return TTI::TCC_Basic;
// A ptrtoint cast is free so long as the result is large enough to store
// the pointer, and a legal integer type.
unsigned DestSize = Ty->getScalarSizeInBits();
if (DL->isLegalInteger(DestSize) &&
DestSize >= DL->getPointerTypeSizeInBits(OpTy))
return TTI::TCC_Free;
// Otherwise it's not a no-op.
return TTI::TCC_Basic;
}
case Instruction::Trunc:
// trunc to a native type is free (assuming the target has compare and
// shift-right of the same width).
if (DL && DL->isLegalInteger(DL->getTypeSizeInBits(Ty)))
return TTI::TCC_Free;
return TTI::TCC_Basic;
}
}
unsigned getGEPCost(const Value *Ptr, ArrayRef<const Value *> Operands) {
// In the basic model, we just assume that all-constant GEPs will be folded
// into their uses via addressing modes.
for (unsigned Idx = 0, Size = Operands.size(); Idx != Size; ++Idx)
if (!isa<Constant>(Operands[Idx]))
return TTI::TCC_Basic;
return TTI::TCC_Free;
}
unsigned getCallCost(FunctionType *FTy, int NumArgs) {
assert(FTy && "FunctionType must be provided to this routine.");
// The target-independent implementation just measures the size of the
// function by approximating that each argument will take on average one
// instruction to prepare.
if (NumArgs < 0)
// Set the argument number to the number of explicit arguments in the
// function.
NumArgs = FTy->getNumParams();
return TTI::TCC_Basic * (NumArgs + 1);
}
unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
ArrayRef<Type *> ParamTys) {
switch (IID) {
default:
// Intrinsics rarely (if ever) have normal argument setup constraints.
// Model them as having a basic instruction cost.
// FIXME: This is wrong for libc intrinsics.
return TTI::TCC_Basic;
case Intrinsic::annotation:
case Intrinsic::assume:
case Intrinsic::dbg_declare:
case Intrinsic::dbg_value:
case Intrinsic::invariant_start:
case Intrinsic::invariant_end:
case Intrinsic::lifetime_start:
case Intrinsic::lifetime_end:
case Intrinsic::objectsize:
case Intrinsic::ptr_annotation:
case Intrinsic::var_annotation:
case Intrinsic::experimental_gc_result_int:
case Intrinsic::experimental_gc_result_float:
case Intrinsic::experimental_gc_result_ptr:
case Intrinsic::experimental_gc_result:
case Intrinsic::experimental_gc_relocate:
// These intrinsics don't actually represent code after lowering.
return TTI::TCC_Free;
}
}
bool hasBranchDivergence() { return false; }
bool isSourceOfDivergence(const Value *V) { return false; }
bool isLoweredToCall(const Function *F) {
// FIXME: These should almost certainly not be handled here, and instead
// handled with the help of TLI or the target itself. This was largely
// ported from existing analysis heuristics here so that such refactorings
// can take place in the future.
if (F->isIntrinsic())
return false;
if (F->hasLocalLinkage() || !F->hasName())
return true;
StringRef Name = F->getName();
// These will all likely lower to a single selection DAG node.
if (Name == "copysign" || Name == "copysignf" || Name == "copysignl" ||
Name == "fabs" || Name == "fabsf" || Name == "fabsl" || Name == "sin" ||
Name == "fmin" || Name == "fminf" || Name == "fminl" ||
Name == "fmax" || Name == "fmaxf" || Name == "fmaxl" ||
Name == "sinf" || Name == "sinl" || Name == "cos" || Name == "cosf" ||
Name == "cosl" || Name == "sqrt" || Name == "sqrtf" || Name == "sqrtl")
return false;
// These are all likely to be optimized into something smaller.
if (Name == "pow" || Name == "powf" || Name == "powl" || Name == "exp2" ||
Name == "exp2l" || Name == "exp2f" || Name == "floor" ||
Name == "floorf" || Name == "ceil" || Name == "round" ||
Name == "ffs" || Name == "ffsl" || Name == "abs" || Name == "labs" ||
Name == "llabs")
return false;
return true;
}
void getUnrollingPreferences(Loop *, TTI::UnrollingPreferences &) {}
bool isLegalAddImmediate(int64_t Imm) { return false; }
bool isLegalICmpImmediate(int64_t Imm) { return false; }
bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
bool HasBaseReg, int64_t Scale) {
// Guess that only reg and reg+reg addressing is allowed. This heuristic is
// taken from the implementation of LSR.
return !BaseGV && BaseOffset == 0 && (Scale == 0 || Scale == 1);
}
bool isLegalMaskedStore(Type *DataType, int Consecutive) { return false; }
bool isLegalMaskedLoad(Type *DataType, int Consecutive) { return false; }
int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
bool HasBaseReg, int64_t Scale) {
// Guess that all legal addressing mode are free.
if (isLegalAddressingMode(Ty, BaseGV, BaseOffset, HasBaseReg, Scale))
return 0;
return -1;
}
bool isTruncateFree(Type *Ty1, Type *Ty2) { return false; }
bool isProfitableToHoist(Instruction *I) { return true; }
bool isTypeLegal(Type *Ty) { return false; }
unsigned getJumpBufAlignment() { return 0; }
unsigned getJumpBufSize() { return 0; }
bool shouldBuildLookupTables() { return true; }
bool enableAggressiveInterleaving(bool LoopHasReductions) { return false; }
TTI::PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) {
return TTI::PSK_Software;
}
bool haveFastSqrt(Type *Ty) { return false; }
unsigned getFPOpCost(Type *Ty) { return TargetTransformInfo::TCC_Basic; }
unsigned getIntImmCost(const APInt &Imm, Type *Ty) { return TTI::TCC_Basic; }
unsigned getIntImmCost(unsigned Opcode, unsigned Idx, const APInt &Imm,
Type *Ty) {
return TTI::TCC_Free;
}
unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx, const APInt &Imm,
Type *Ty) {
return TTI::TCC_Free;
}
unsigned getNumberOfRegisters(bool Vector) { return 8; }
unsigned getRegisterBitWidth(bool Vector) { return 32; }
unsigned getMaxInterleaveFactor(unsigned VF) { return 1; }
unsigned getArithmeticInstrCost(unsigned Opcode, Type *Ty,
TTI::OperandValueKind Opd1Info,
TTI::OperandValueKind Opd2Info,
TTI::OperandValueProperties Opd1PropInfo,
TTI::OperandValueProperties Opd2PropInfo) {
return 1;
}
unsigned getShuffleCost(TTI::ShuffleKind Kind, Type *Ty, int Index,
Type *SubTp) {
return 1;
}
unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) { return 1; }
unsigned getCFInstrCost(unsigned Opcode) { return 1; }
unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy) {
return 1;
}
unsigned getVectorInstrCost(unsigned Opcode, Type *Val, unsigned Index) {
return 1;
}
unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment,
unsigned AddressSpace) {
return 1;
}
unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment,
unsigned AddressSpace) {
return 1;
}
unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
ArrayRef<Type *> Tys) {
return 1;
}
unsigned getCallInstrCost(Function *F, Type *RetTy, ArrayRef<Type *> Tys) {
return 1;
}
unsigned getNumberOfParts(Type *Tp) { return 0; }
unsigned getAddressComputationCost(Type *Tp, bool) { return 0; }
unsigned getReductionCost(unsigned, Type *, bool) { return 1; }
unsigned getCostOfKeepingLiveOverCall(ArrayRef<Type *> Tys) { return 0; }
bool getTgtMemIntrinsic(IntrinsicInst *Inst, MemIntrinsicInfo &Info) {
return false;
}
Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst,
Type *ExpectedType) {
return nullptr;
}
};
/// \brief CRTP base class for use as a mix-in that aids implementing
/// a TargetTransformInfo-compatible class.
template <typename T>
class TargetTransformInfoImplCRTPBase : public TargetTransformInfoImplBase {
private:
typedef TargetTransformInfoImplBase BaseT;
protected:
explicit TargetTransformInfoImplCRTPBase(const DataLayout *DL)
: BaseT(DL) {}
public:
// Provide value semantics. MSVC requires that we spell all of these out.
TargetTransformInfoImplCRTPBase(const TargetTransformInfoImplCRTPBase &Arg)
: BaseT(static_cast<const BaseT &>(Arg)) {}
TargetTransformInfoImplCRTPBase(TargetTransformInfoImplCRTPBase &&Arg)
: BaseT(std::move(static_cast<BaseT &>(Arg))) {}
TargetTransformInfoImplCRTPBase &
operator=(const TargetTransformInfoImplCRTPBase &RHS) {
BaseT::operator=(static_cast<const BaseT &>(RHS));
return *this;
}
TargetTransformInfoImplCRTPBase &
operator=(TargetTransformInfoImplCRTPBase &&RHS) {
BaseT::operator=(std::move(static_cast<BaseT &>(RHS)));
return *this;
}
using BaseT::getCallCost;
unsigned getCallCost(const Function *F, int NumArgs) {
assert(F && "A concrete function must be provided to this routine.");
if (NumArgs < 0)
// Set the argument number to the number of explicit arguments in the
// function.
NumArgs = F->arg_size();
if (Intrinsic::ID IID = F->getIntrinsicID()) {
FunctionType *FTy = F->getFunctionType();
SmallVector<Type *, 8> ParamTys(FTy->param_begin(), FTy->param_end());
return static_cast<T *>(this)
->getIntrinsicCost(IID, FTy->getReturnType(), ParamTys);
}
if (!static_cast<T *>(this)->isLoweredToCall(F))
return TTI::TCC_Basic; // Give a basic cost if it will be lowered
// directly.
return static_cast<T *>(this)->getCallCost(F->getFunctionType(), NumArgs);
}
unsigned getCallCost(const Function *F, ArrayRef<const Value *> Arguments) {
// Simply delegate to generic handling of the call.
// FIXME: We should use instsimplify or something else to catch calls which
// will constant fold with these arguments.
return static_cast<T *>(this)->getCallCost(F, Arguments.size());
}
using BaseT::getIntrinsicCost;
unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
ArrayRef<const Value *> Arguments) {
// Delegate to the generic intrinsic handling code. This mostly provides an
// opportunity for targets to (for example) special case the cost of
// certain intrinsics based on constants used as arguments.
SmallVector<Type *, 8> ParamTys;
ParamTys.reserve(Arguments.size());
for (unsigned Idx = 0, Size = Arguments.size(); Idx != Size; ++Idx)
ParamTys.push_back(Arguments[Idx]->getType());
return static_cast<T *>(this)->getIntrinsicCost(IID, RetTy, ParamTys);
}
unsigned getUserCost(const User *U) {
if (isa<PHINode>(U))
return TTI::TCC_Free; // Model all PHI nodes as free.
if (const GEPOperator *GEP = dyn_cast<GEPOperator>(U)) {
SmallVector<const Value *, 4> Indices(GEP->idx_begin(), GEP->idx_end());
return static_cast<T *>(this)
->getGEPCost(GEP->getPointerOperand(), Indices);
}
if (auto CS = ImmutableCallSite(U)) {
const Function *F = CS.getCalledFunction();
if (!F) {
// Just use the called value type.
Type *FTy = CS.getCalledValue()->getType()->getPointerElementType();
return static_cast<T *>(this)
->getCallCost(cast<FunctionType>(FTy), CS.arg_size());
}
SmallVector<const Value *, 8> Arguments(CS.arg_begin(), CS.arg_end());
return static_cast<T *>(this)->getCallCost(F, Arguments);
}
if (const CastInst *CI = dyn_cast<CastInst>(U)) {
// Result of a cmp instruction is often extended (to be used by other
// cmp instructions, logical or return instructions). These are usually
// nop on most sane targets.
if (isa<CmpInst>(CI->getOperand(0)))
return TTI::TCC_Free;
}
return static_cast<T *>(this)->getOperationCost(
Operator::getOpcode(U), U->getType(),
U->getNumOperands() == 1 ? U->getOperand(0)->getType() : nullptr);
}
};
}
#endif

View File

@ -16,6 +16,7 @@
#define LLVM_ANALYSIS_VALUETRACKING_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/IR/Instruction.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
@ -28,17 +29,18 @@ namespace llvm {
class AssumptionCache;
class DominatorTree;
class TargetLibraryInfo;
class LoopInfo;
/// Determine which bits of V are known to be either zero or one and return
/// them in the KnownZero/KnownOne bit sets.
///
/// This function is defined on values with integer type, values with pointer
/// type (but only if TD is non-null), and vectors of integers. In the case
/// type, and vectors of integers. In the case
/// where V is a vector, the known zero and known one values are the
/// same width as the vector element, and the bit is set only if it is true
/// for all of the elements in the vector.
void computeKnownBits(Value *V, APInt &KnownZero, APInt &KnownOne,
const DataLayout *TD = nullptr, unsigned Depth = 0,
const DataLayout &DL, unsigned Depth = 0,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
@ -46,11 +48,16 @@ namespace llvm {
/// \p KnownZero the set of bits that are known to be zero
void computeKnownBitsFromRangeMetadata(const MDNode &Ranges,
APInt &KnownZero);
/// Returns true if LHS and RHS have no common bits set.
bool haveNoCommonBitsSet(Value *LHS, Value *RHS, const DataLayout &DL,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
/// ComputeSignBit - Determine whether the sign bit is known to be zero or
/// one. Convenience wrapper around computeKnownBits.
void ComputeSignBit(Value *V, bool &KnownZero, bool &KnownOne,
const DataLayout *TD = nullptr, unsigned Depth = 0,
const DataLayout &DL, unsigned Depth = 0,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
@ -60,7 +67,8 @@ namespace llvm {
/// element is known to be a power of two when defined. Supports values with
/// integer or pointer type and vectors of integers. If 'OrZero' is set then
/// returns true if the given value is either a power of two or zero.
bool isKnownToBeAPowerOfTwo(Value *V, bool OrZero = false, unsigned Depth = 0,
bool isKnownToBeAPowerOfTwo(Value *V, const DataLayout &DL,
bool OrZero = false, unsigned Depth = 0,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
@ -69,8 +77,8 @@ namespace llvm {
/// when defined. For vectors return true if every element is known to be
/// non-zero when defined. Supports values with integer or pointer type and
/// vectors of integers.
bool isKnownNonZero(Value *V, const DataLayout *TD = nullptr,
unsigned Depth = 0, AssumptionCache *AC = nullptr,
bool isKnownNonZero(Value *V, const DataLayout &DL, unsigned Depth = 0,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
@ -79,13 +87,12 @@ namespace llvm {
/// zero for bits that V cannot have.
///
/// This function is defined on values with integer type, values with pointer
/// type (but only if TD is non-null), and vectors of integers. In the case
/// type, and vectors of integers. In the case
/// where V is a vector, the mask, known zero, and known one values are the
/// same width as the vector element, and the bit is set only if it is true
/// for all of the elements in the vector.
bool MaskedValueIsZero(Value *V, const APInt &Mask,
const DataLayout *TD = nullptr, unsigned Depth = 0,
AssumptionCache *AC = nullptr,
bool MaskedValueIsZero(Value *V, const APInt &Mask, const DataLayout &DL,
unsigned Depth = 0, AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
@ -97,7 +104,7 @@ namespace llvm {
///
/// 'Op' must have a scalar integer type.
///
unsigned ComputeNumSignBits(Value *Op, const DataLayout *TD = nullptr,
unsigned ComputeNumSignBits(Value *Op, const DataLayout &DL,
unsigned Depth = 0, AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
@ -116,6 +123,11 @@ namespace llvm {
///
bool CannotBeNegativeZero(const Value *V, unsigned Depth = 0);
/// CannotBeOrderedLessThanZero - Return true if we can prove that the
/// specified FP value is either a NaN or never less than 0.0.
///
bool CannotBeOrderedLessThanZero(const Value *V, unsigned Depth = 0);
/// isBytewiseValue - If the specified value can be set by repeating the same
/// byte in memory, return the i8 value that it is represented with. This is
/// true for all i8 values obviously, but is also true for i32 0, i32 -1,
@ -137,11 +149,12 @@ namespace llvm {
/// it can be expressed as a base pointer plus a constant offset. Return the
/// base and offset to the caller.
Value *GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset,
const DataLayout *TD);
const DataLayout &DL);
static inline const Value *
GetPointerBaseWithConstantOffset(const Value *Ptr, int64_t &Offset,
const DataLayout *TD) {
return GetPointerBaseWithConstantOffset(const_cast<Value*>(Ptr), Offset,TD);
const DataLayout &DL) {
return GetPointerBaseWithConstantOffset(const_cast<Value *>(Ptr), Offset,
DL);
}
/// getConstantStringInfo - This function computes the length of a
@ -162,26 +175,59 @@ namespace llvm {
/// being addressed. Note that the returned value has pointer type if the
/// specified value does. If the MaxLookup value is non-zero, it limits the
/// number of instructions to be stripped off.
Value *GetUnderlyingObject(Value *V, const DataLayout *TD = nullptr,
Value *GetUnderlyingObject(Value *V, const DataLayout &DL,
unsigned MaxLookup = 6);
static inline const Value *
GetUnderlyingObject(const Value *V, const DataLayout *TD = nullptr,
unsigned MaxLookup = 6) {
return GetUnderlyingObject(const_cast<Value *>(V), TD, MaxLookup);
static inline const Value *GetUnderlyingObject(const Value *V,
const DataLayout &DL,
unsigned MaxLookup = 6) {
return GetUnderlyingObject(const_cast<Value *>(V), DL, MaxLookup);
}
/// GetUnderlyingObjects - This method is similar to GetUnderlyingObject
/// except that it can look through phi and select instructions and return
/// multiple objects.
void GetUnderlyingObjects(Value *V,
SmallVectorImpl<Value *> &Objects,
const DataLayout *TD = nullptr,
/// \brief This method is similar to GetUnderlyingObject except that it can
/// look through phi and select instructions and return multiple objects.
///
/// If LoopInfo is passed, loop phis are further analyzed. If a pointer
/// accesses different objects in each iteration, we don't look through the
/// phi node. E.g. consider this loop nest:
///
/// int **A;
/// for (i)
/// for (j) {
/// A[i][j] = A[i-1][j] * B[j]
/// }
///
/// This is transformed by Load-PRE to stash away A[i] for the next iteration
/// of the outer loop:
///
/// Curr = A[0]; // Prev_0
/// for (i: 1..N) {
/// Prev = Curr; // Prev = PHI (Prev_0, Curr)
/// Curr = A[i];
/// for (j: 0..N) {
/// Curr[j] = Prev[j] * B[j]
/// }
/// }
///
/// Since A[i] and A[i-1] are independent pointers, getUnderlyingObjects
/// should not assume that Curr and Prev share the same underlying object thus
/// it shouldn't look through the phi above.
void GetUnderlyingObjects(Value *V, SmallVectorImpl<Value *> &Objects,
const DataLayout &DL, LoopInfo *LI = nullptr,
unsigned MaxLookup = 6);
/// onlyUsedByLifetimeMarkers - Return true if the only users of this pointer
/// are lifetime markers.
bool onlyUsedByLifetimeMarkers(const Value *V);
/// isDereferenceablePointer - Return true if this is always a dereferenceable
/// pointer. If the context instruction is specified perform context-sensitive
/// analysis and return true if the pointer is dereferenceable at the
/// specified instruction.
bool isDereferenceablePointer(const Value *V, const DataLayout &DL,
const Instruction *CtxI = nullptr,
const DominatorTree *DT = nullptr,
const TargetLibraryInfo *TLI = nullptr);
/// isSafeToSpeculativelyExecute - Return true if the instruction does not
/// have any effects besides calculating the result and does not have
/// undefined behavior.
@ -195,37 +241,82 @@ namespace llvm {
/// memory leak. It also returns false for instructions related to control
/// flow, specifically terminators and PHI nodes.
///
/// This method only looks at the instruction itself and its operands, so if
/// this method returns true, it is safe to move the instruction as long as
/// the correct dominance relationships for the operands and users hold.
/// However, this method can return true for instructions that read memory;
/// If the CtxI is specified this method performs context-sensitive analysis
/// and returns true if it is safe to execute the instruction immediately
/// before the CtxI.
///
/// If the CtxI is NOT specified this method only looks at the instruction
/// itself and its operands, so if this method returns true, it is safe to
/// move the instruction as long as the correct dominance relationships for
/// the operands and users hold.
///
/// This method can return true for instructions that read memory;
/// for such instructions, moving them may change the resulting value.
bool isSafeToSpeculativelyExecute(const Value *V,
const DataLayout *TD = nullptr);
const Instruction *CtxI = nullptr,
const DominatorTree *DT = nullptr,
const TargetLibraryInfo *TLI = nullptr);
/// isKnownNonNull - Return true if this pointer couldn't possibly be null by
/// its definition. This returns true for allocas, non-extern-weak globals
/// and byval arguments.
bool isKnownNonNull(const Value *V, const TargetLibraryInfo *TLI = nullptr);
/// isKnownNonNullAt - Return true if this pointer couldn't possibly be null.
/// If the context instruction is specified perform context-sensitive analysis
/// and return true if the pointer couldn't possibly be null at the specified
/// instruction.
bool isKnownNonNullAt(const Value *V,
const Instruction *CtxI = nullptr,
const DominatorTree *DT = nullptr,
const TargetLibraryInfo *TLI = nullptr);
/// Return true if it is valid to use the assumptions provided by an
/// assume intrinsic, I, at the point in the control-flow identified by the
/// context instruction, CxtI.
bool isValidAssumeForContext(const Instruction *I, const Instruction *CxtI,
const DataLayout *DL = nullptr,
const DominatorTree *DT = nullptr);
enum class OverflowResult { AlwaysOverflows, MayOverflow, NeverOverflows };
OverflowResult computeOverflowForUnsignedMul(Value *LHS, Value *RHS,
const DataLayout *DL,
const DataLayout &DL,
AssumptionCache *AC,
const Instruction *CxtI,
const DominatorTree *DT);
OverflowResult computeOverflowForUnsignedAdd(Value *LHS, Value *RHS,
const DataLayout *DL,
const DataLayout &DL,
AssumptionCache *AC,
const Instruction *CxtI,
const DominatorTree *DT);
/// \brief Specific patterns of select instructions we can match.
enum SelectPatternFlavor {
SPF_UNKNOWN = 0,
SPF_SMIN, // Signed minimum
SPF_UMIN, // Unsigned minimum
SPF_SMAX, // Signed maximum
SPF_UMAX, // Unsigned maximum
SPF_ABS, // Absolute value
SPF_NABS // Negated absolute value
};
/// Pattern match integer [SU]MIN, [SU]MAX and ABS idioms, returning the kind
/// and providing the out parameter results if we successfully match.
///
/// If CastOp is not nullptr, also match MIN/MAX idioms where the type does
/// not match that of the original select. If this is the case, the cast
/// operation (one of Trunc,SExt,Zext) that must be done to transform the
/// type of LHS and RHS into the type of V is returned in CastOp.
///
/// For example:
/// %1 = icmp slt i32 %a, i32 4
/// %2 = sext i32 %a to i64
/// %3 = select i1 %1, i64 %2, i64 4
///
/// -> LHS = %a, RHS = i32 4, *CastOp = Instruction::SExt
///
SelectPatternFlavor matchSelectPattern(Value *V, Value *&LHS, Value *&RHS,
Instruction::CastOps *CastOp = nullptr);
} // end namespace llvm
#endif

View File

@ -125,7 +125,7 @@ class BitCodeAbbrevOp {
case Blob:
return false;
}
llvm_unreachable("Invalid encoding");
report_fatal_error("Invalid encoding");
}
/// isChar6 - Return true if this character is legal in the Char6 encoding.
@ -164,8 +164,8 @@ template <> struct isPodLike<BitCodeAbbrevOp> { static const bool value=true; };
/// specialized format instead of the fully-general, fully-vbr, format.
class BitCodeAbbrev : public RefCountedBase<BitCodeAbbrev> {
SmallVector<BitCodeAbbrevOp, 32> OperandList;
~BitCodeAbbrev() {}
// Only RefCountedBase is allowed to delete.
~BitCodeAbbrev() = default;
friend class RefCountedBase<BitCodeAbbrev>;
public:

View File

@ -26,7 +26,11 @@ class PreservedAnalyses;
/// \brief Create and return a pass that writes the module to the specified
/// ostream. Note that this pass is designed for use with the legacy pass
/// manager.
ModulePass *createBitcodeWriterPass(raw_ostream &Str);
///
/// If \c ShouldPreserveUseListOrder, encode use-list order so it can be
/// reproduced when deserialized.
ModulePass *createBitcodeWriterPass(raw_ostream &Str,
bool ShouldPreserveUseListOrder = false);
/// \brief Pass for writing a module of IR out to a bitcode file.
///
@ -34,10 +38,16 @@ ModulePass *createBitcodeWriterPass(raw_ostream &Str);
/// a pass for the legacy pass manager, use the function above.
class BitcodeWriterPass {
raw_ostream &OS;
bool ShouldPreserveUseListOrder;
public:
/// \brief Construct a bitcode writer pass around a particular output stream.
explicit BitcodeWriterPass(raw_ostream &OS) : OS(OS) {}
///
/// If \c ShouldPreserveUseListOrder, encode use-list order so it can be
/// reproduced when deserialized.
explicit BitcodeWriterPass(raw_ostream &OS,
bool ShouldPreserveUseListOrder = false)
: OS(OS), ShouldPreserveUseListOrder(ShouldPreserveUseListOrder) {}
/// \brief Run the bitcode writer pass, and output the module to the selected
/// output stream.

View File

@ -24,8 +24,6 @@
namespace llvm {
class Deserializer;
/// This class is used to read from an LLVM bitcode stream, maintaining
/// information that is global to decoding the entire file. While a file is
/// being read, multiple cursors can be independently advanced or skipped around
@ -50,8 +48,8 @@ class BitstreamReader {
/// information in the BlockInfo block. Only llvm-bcanalyzer uses this.
bool IgnoreBlockInfoNames;
BitstreamReader(const BitstreamReader&) LLVM_DELETED_FUNCTION;
void operator=(const BitstreamReader&) LLVM_DELETED_FUNCTION;
BitstreamReader(const BitstreamReader&) = delete;
void operator=(const BitstreamReader&) = delete;
public:
BitstreamReader() : IgnoreBlockInfoNames(true) {
}
@ -164,7 +162,6 @@ struct BitstreamEntry {
/// Unlike iterators, BitstreamCursors are heavy-weight objects that should not
/// be passed by value.
class BitstreamCursor {
friend class Deserializer;
BitstreamReader *BitStream;
size_t NextChar;
@ -201,6 +198,8 @@ class BitstreamCursor {
public:
static const size_t MaxChunkSize = sizeof(word_t) * 8;
BitstreamCursor() { init(nullptr); }
explicit BitstreamCursor(BitstreamReader &R) { init(&R); }
@ -258,8 +257,8 @@ class BitstreamCursor {
AF_DontAutoprocessAbbrevs = 2
};
/// Advance the current bitstream, returning the next entry in the stream.
BitstreamEntry advance(unsigned Flags = 0) {
/// Advance the current bitstream, returning the next entry in the stream.
BitstreamEntry advance(unsigned Flags = 0) {
while (1) {
unsigned Code = ReadCode();
if (Code == bitc::END_BLOCK) {
@ -301,7 +300,7 @@ class BitstreamCursor {
/// Reset the stream to the specified bit number.
void JumpToBit(uint64_t BitNo) {
uintptr_t ByteNo = uintptr_t(BitNo/8) & ~(sizeof(word_t)-1);
size_t ByteNo = size_t(BitNo/8) & ~(sizeof(word_t)-1);
unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1));
assert(canSkipToPos(ByteNo) && "Invalid location");
@ -315,7 +314,8 @@ class BitstreamCursor {
}
void fillCurWord() {
assert(Size == 0 || NextChar < (unsigned)Size);
if (Size != 0 && NextChar >= Size)
report_fatal_error("Unexpected end of file");
// Read the next word from the stream.
uint8_t Array[sizeof(word_t)] = {0};
@ -337,7 +337,7 @@ class BitstreamCursor {
}
word_t Read(unsigned NumBits) {
static const unsigned BitsInWord = sizeof(word_t) * 8;
static const unsigned BitsInWord = MaxChunkSize;
assert(NumBits && NumBits <= BitsInWord &&
"Cannot return zero or more than BitsInWord bits!");
@ -490,11 +490,11 @@ class BitstreamCursor {
//===--------------------------------------------------------------------===//
public:
/// Return the abbreviation for the specified AbbrevId.
const BitCodeAbbrev *getAbbrev(unsigned AbbrevID) {
unsigned AbbrevNo = AbbrevID-bitc::FIRST_APPLICATION_ABBREV;
assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!");
unsigned AbbrevNo = AbbrevID - bitc::FIRST_APPLICATION_ABBREV;
if (AbbrevNo >= CurAbbrevs.size())
report_fatal_error("Invalid abbrev number");
return CurAbbrevs[AbbrevNo].get();
}

View File

@ -146,7 +146,27 @@ namespace bitc {
METADATA_OLD_NODE = 8, // OLD_NODE: [n x (type num, value num)]
METADATA_OLD_FN_NODE = 9, // OLD_FN_NODE: [n x (type num, value num)]
METADATA_NAMED_NODE = 10, // NAMED_NODE: [n x mdnodes]
METADATA_ATTACHMENT = 11 // [m x [value, [n x [id, mdnode]]]
METADATA_ATTACHMENT = 11, // [m x [value, [n x [id, mdnode]]]
METADATA_GENERIC_DEBUG = 12, // [distinct, tag, vers, header, n x md num]
METADATA_SUBRANGE = 13, // [distinct, count, lo]
METADATA_ENUMERATOR = 14, // [distinct, value, name]
METADATA_BASIC_TYPE = 15, // [distinct, tag, name, size, align, enc]
METADATA_FILE = 16, // [distinct, filename, directory]
METADATA_DERIVED_TYPE = 17, // [distinct, ...]
METADATA_COMPOSITE_TYPE= 18, // [distinct, ...]
METADATA_SUBROUTINE_TYPE=19, // [distinct, flags, types]
METADATA_COMPILE_UNIT = 20, // [distinct, ...]
METADATA_SUBPROGRAM = 21, // [distinct, ...]
METADATA_LEXICAL_BLOCK = 22, // [distinct, scope, file, line, column]
METADATA_LEXICAL_BLOCK_FILE=23,//[distinct, scope, file, discriminator]
METADATA_NAMESPACE = 24, // [distinct, scope, file, name, line]
METADATA_TEMPLATE_TYPE = 25, // [distinct, scope, name, type, ...]
METADATA_TEMPLATE_VALUE= 26, // [distinct, scope, name, type, value, ...]
METADATA_GLOBAL_VAR = 27, // [distinct, ...]
METADATA_LOCAL_VAR = 28, // [distinct, ...]
METADATA_EXPRESSION = 29, // [distinct, n x element]
METADATA_OBJC_PROPERTY = 30, // [distinct, name, file, line, ...]
METADATA_IMPORTED_ENTITY=31, // [distinct, tag, scope, entity, line, name]
};
// The constants block (CONSTANTS_BLOCK_ID) describes emission for each
@ -273,7 +293,7 @@ namespace bitc {
FUNC_CODE_INST_BINOP = 2, // BINOP: [opcode, ty, opval, opval]
FUNC_CODE_INST_CAST = 3, // CAST: [opcode, ty, opty, opval]
FUNC_CODE_INST_GEP = 4, // GEP: [n x operands]
FUNC_CODE_INST_GEP_OLD = 4, // GEP: [n x operands]
FUNC_CODE_INST_SELECT = 5, // SELECT: [ty, opval, opval, opval]
FUNC_CODE_INST_EXTRACTELT = 6, // EXTRACTELT: [opty, opval, opval]
FUNC_CODE_INST_INSERTELT = 7, // INSERTELT: [ty, opval, opval, opval]
@ -298,7 +318,7 @@ namespace bitc {
// This store code encodes the pointer type, rather than the value type
// this is so information only available in the pointer type (e.g. address
// spaces) is retained.
FUNC_CODE_INST_STORE = 24, // STORE: [ptrty,ptr,val, align, vol]
FUNC_CODE_INST_STORE_OLD = 24, // STORE: [ptrty,ptr,val, align, vol]
// 25 is unused.
FUNC_CODE_INST_EXTRACTVAL = 26, // EXTRACTVAL: [n x operands]
FUNC_CODE_INST_INSERTVAL = 27, // INSERTVAL: [n x operands]
@ -307,7 +327,7 @@ namespace bitc {
FUNC_CODE_INST_CMP2 = 28, // CMP2: [opty, opval, opval, pred]
// new select on i1 or [N x i1]
FUNC_CODE_INST_VSELECT = 29, // VSELECT: [ty,opval,opval,predty,pred]
FUNC_CODE_INST_INBOUNDS_GEP= 30, // INBOUNDS_GEP: [n x operands]
FUNC_CODE_INST_INBOUNDS_GEP_OLD = 30, // INBOUNDS_GEP: [n x operands]
FUNC_CODE_INST_INDIRECTBR = 31, // INDIRECTBR: [opty, op0, op1, ...]
// 32 is unused.
FUNC_CODE_DEBUG_LOC_AGAIN = 33, // DEBUG_LOC_AGAIN
@ -316,7 +336,7 @@ namespace bitc {
FUNC_CODE_DEBUG_LOC = 35, // DEBUG_LOC: [Line,Col,ScopeVal, IAVal]
FUNC_CODE_INST_FENCE = 36, // FENCE: [ordering, synchscope]
FUNC_CODE_INST_CMPXCHG = 37, // CMPXCHG: [ptrty,ptr,cmp,new, align, vol,
FUNC_CODE_INST_CMPXCHG_OLD = 37, // CMPXCHG: [ptrty,ptr,cmp,new, align, vol,
// ordering, synchscope]
FUNC_CODE_INST_ATOMICRMW = 38, // ATOMICRMW: [ptrty,ptr,val, operation,
// align, vol,
@ -325,8 +345,13 @@ namespace bitc {
FUNC_CODE_INST_LANDINGPAD = 40, // LANDINGPAD: [ty,val,val,num,id0,val0...]
FUNC_CODE_INST_LOADATOMIC = 41, // LOAD: [opty, op, align, vol,
// ordering, synchscope]
FUNC_CODE_INST_STOREATOMIC = 42 // STORE: [ptrty,ptr,val, align, vol
FUNC_CODE_INST_STOREATOMIC_OLD = 42, // STORE: [ptrty,ptr,val, align, vol
// ordering, synchscope]
FUNC_CODE_INST_GEP = 43, // GEP: [inbounds, n x operands]
FUNC_CODE_INST_STORE = 44, // STORE: [ptrty,ptr,valty,val, align, vol]
FUNC_CODE_INST_STOREATOMIC = 45, // STORE: [ptrty,ptr,val, align, vol
FUNC_CODE_INST_CMPXCHG = 46, // CMPXCHG: [ptrty,ptr,valty,cmp,new, align,
// vol,ordering,synchscope]
};
enum UseListCodes {
@ -376,7 +401,9 @@ namespace bitc {
ATTR_KIND_IN_ALLOCA = 38,
ATTR_KIND_NON_NULL = 39,
ATTR_KIND_JUMP_TABLE = 40,
ATTR_KIND_DEREFERENCEABLE = 41
ATTR_KIND_DEREFERENCEABLE = 41,
ATTR_KIND_DEREFERENCEABLE_OR_NULL = 42,
ATTR_KIND_CONVERGENT = 43
};
enum ComdatSelectionKindCodes {

View File

@ -29,12 +29,14 @@ namespace llvm {
class raw_ostream;
/// Read the header of the specified bitcode buffer and prepare for lazy
/// deserialization of function bodies. If successful, this moves Buffer. On
/// deserialization of function bodies. If ShouldLazyLoadMetadata is true,
/// lazily load metadata as well. If successful, this moves Buffer. On
/// error, this *does not* move Buffer.
ErrorOr<Module *>
getLazyBitcodeModule(std::unique_ptr<MemoryBuffer> &&Buffer,
LLVMContext &Context,
DiagnosticHandlerFunction DiagnosticHandler = nullptr);
DiagnosticHandlerFunction DiagnosticHandler = nullptr,
bool ShouldLazyLoadMetadata = false);
/// Read the header of the specified stream and prepare for lazy
/// deserialization and streaming of function bodies.
@ -54,11 +56,16 @@ namespace llvm {
parseBitcodeFile(MemoryBufferRef Buffer, LLVMContext &Context,
DiagnosticHandlerFunction DiagnosticHandler = nullptr);
/// WriteBitcodeToFile - Write the specified module to the specified
/// raw output stream. For streams where it matters, the given stream
/// should be in "binary" mode.
void WriteBitcodeToFile(const Module *M, raw_ostream &Out);
/// \brief Write the specified module to the specified raw output stream.
///
/// For streams where it matters, the given stream should be in "binary"
/// mode.
///
/// If \c ShouldPreserveUseListOrder, encode the use-list order for each \a
/// Value in \c M. These will be reconstructed exactly when \a M is
/// deserialized.
void WriteBitcodeToFile(const Module *M, raw_ostream &Out,
bool ShouldPreserveUseListOrder = false);
/// isBitcodeWrapper - Return true if the given bytes are the magic bytes
/// for an LLVM IR bitcode wrapper.

View File

@ -16,8 +16,10 @@
#ifndef LLVM_CODEGEN_ASMPRINTER_H
#define LLVM_CODEGEN_ASMPRINTER_H
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/Twine.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/DwarfStringPoolEntry.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/ErrorHandling.h"
@ -29,6 +31,8 @@ class ByteStreamer;
class GCStrategy;
class Constant;
class ConstantArray;
class DIE;
class DIEAbbrev;
class GCMetadataPrinter;
class GlobalValue;
class GlobalVariable;
@ -46,11 +50,11 @@ class MCCFIInstruction;
class MCContext;
class MCExpr;
class MCInst;
class MCInstrInfo;
class MCSection;
class MCStreamer;
class MCSubtargetInfo;
class MCSymbol;
class MCTargetOptions;
class MDNode;
class DwarfDebug;
class Mangler;
@ -69,7 +73,6 @@ class AsmPrinter : public MachineFunctionPass {
///
const MCAsmInfo *MAI;
const MCInstrInfo *MII;
/// This is the context for the output file that we are streaming. This owns
/// all of the global MC-related objects for the generated translation unit.
MCContext &OutContext;
@ -77,7 +80,7 @@ class AsmPrinter : public MachineFunctionPass {
/// This is the MCStreamer object for the file we are generating. This
/// contains the transient state for the current translation unit that we are
/// generating (such as the current section etc).
MCStreamer &OutStreamer;
std::unique_ptr<MCStreamer> OutStreamer;
/// The current machine function.
const MachineFunction *MF;
@ -99,7 +102,16 @@ class AsmPrinter : public MachineFunctionPass {
/// default, this is equal to CurrentFnSym.
MCSymbol *CurrentFnSymForSize;
/// Map global GOT equivalent MCSymbols to GlobalVariables and keep track of
/// its number of uses by other globals.
typedef std::pair<const GlobalVariable *, unsigned> GOTEquivUsePair;
MapVector<const MCSymbol *, GOTEquivUsePair> GlobalGOTEquivs;
private:
MCSymbol *CurrentFnBegin;
MCSymbol *CurrentFnEnd;
MCSymbol *CurExceptionSym;
// The garbage collection metadata printer table.
void *GCMetadataPrinters; // Really a DenseMap.
@ -127,10 +139,10 @@ class AsmPrinter : public MachineFunctionPass {
DwarfDebug *DD;
protected:
explicit AsmPrinter(TargetMachine &TM, MCStreamer &Streamer);
explicit AsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer);
public:
virtual ~AsmPrinter();
~AsmPrinter() override;
DwarfDebug *getDwarfDebug() { return DD; }
DwarfDebug *getDwarfDebug() const { return DD; }
@ -143,6 +155,10 @@ class AsmPrinter : public MachineFunctionPass {
///
unsigned getFunctionNumber() const;
MCSymbol *getFunctionBegin() const { return CurrentFnBegin; }
MCSymbol *getFunctionEnd() const { return CurrentFnEnd; }
MCSymbol *getCurExceptionSym();
/// Return information about object file lowering.
const TargetLoweringObjectFile &getObjFileLowering() const;
@ -184,7 +200,6 @@ class AsmPrinter : public MachineFunctionPass {
/// Emit the specified function out to the OutStreamer.
bool runOnMachineFunction(MachineFunction &MF) override {
SetupMachineFunction(MF);
EmitFunctionHeader();
EmitFunctionBody();
return false;
}
@ -197,9 +212,6 @@ class AsmPrinter : public MachineFunctionPass {
/// runOnMachineFunction.
void SetupMachineFunction(MachineFunction &MF);
/// This method emits the header for the current function.
void EmitFunctionHeader();
/// This method emits the body and trailer for a function.
void EmitFunctionBody();
@ -238,16 +250,27 @@ class AsmPrinter : public MachineFunctionPass {
///
void EmitAlignment(unsigned NumBits, const GlobalObject *GO = nullptr) const;
/// This method prints the label for the specified MachineBasicBlock, an
/// alignment (if present) and a comment describing it if appropriate.
void EmitBasicBlockStart(const MachineBasicBlock &MBB) const;
/// Lower the specified LLVM Constant to an MCExpr.
const MCExpr *lowerConstant(const Constant *CV);
/// \brief Print a general LLVM constant to the .s file.
void EmitGlobalConstant(const Constant *CV);
/// \brief Unnamed constant global variables solely contaning a pointer to
/// another globals variable act like a global variable "proxy", or GOT
/// equivalents, i.e., it's only used to hold the address of the latter. One
/// optimization is to replace accesses to these proxies by using the GOT
/// entry for the final global instead. Hence, we select GOT equivalent
/// candidates among all the module global variables, avoid emitting them
/// unnecessarily and finally replace references to them by pc relative
/// accesses to GOT entries.
void computeGlobalGOTEquivs(Module &M);
/// \brief Constant expressions using GOT equivalent globals may not be
/// eligible for PC relative GOT entry conversion, in such cases we need to
/// emit the proxies we previously omitted in EmitGlobalVariable.
void emitGlobalGOTEquivs();
//===------------------------------------------------------------------===//
// Overridable Hooks
//===------------------------------------------------------------------===//
@ -271,6 +294,12 @@ class AsmPrinter : public MachineFunctionPass {
/// function.
virtual void EmitFunctionBodyEnd() {}
/// Targets can override this to emit stuff at the start of a basic block.
/// By default, this method prints the label for the specified
/// MachineBasicBlock, an alignment (if present) and a comment describing it
/// if appropriate.
virtual void EmitBasicBlockStart(const MachineBasicBlock &MBB) const;
/// Targets can override this to emit stuff at the end of a basic block.
virtual void EmitBasicBlockEnd(const MachineBasicBlock &MBB) {}
@ -304,12 +333,7 @@ class AsmPrinter : public MachineFunctionPass {
// Symbol Lowering Routines.
//===------------------------------------------------------------------===//
public:
/// Return the MCSymbol corresponding to the assembler temporary label with
/// the specified stem and unique ID.
MCSymbol *GetTempSymbol(Twine Name, unsigned ID) const;
/// Return an assembler temporary label with the specified stem.
MCSymbol *GetTempSymbol(Twine Name) const;
MCSymbol *createTempSymbol(const Twine &Name) const;
/// Return the MCSymbol for a private symbol with global value name as its
/// base, with the specified suffix.
@ -397,42 +421,21 @@ class AsmPrinter : public MachineFunctionPass {
/// Emit the 4-byte offset of Label from the start of its section. This can
/// be done with a special directive if the target supports it (e.g. cygwin)
/// or by emitting it as an offset from a label at the start of the section.
void emitSectionOffset(const MCSymbol *Label) const;
/// Emit the 4-byte offset of a string from the start of its section.
///
/// SectionLabel is a temporary label emitted at the start of the section
/// that Label lives in.
void EmitSectionOffset(const MCSymbol *Label,
const MCSymbol *SectionLabel) const;
/// When possible, emit a DwarfStringPool section offset without any
/// relocations, and without using the symbol. Otherwise, defers to \a
/// emitSectionOffset().
void emitDwarfStringOffset(DwarfStringPoolEntryRef S) const;
/// Get the value for DW_AT_APPLE_isa. Zero if no isa encoding specified.
virtual unsigned getISAEncoding() { return 0; }
/// Emit a dwarf register operation for describing
/// - a small value occupying only part of a register or
/// - a register representing only part of a value.
void EmitDwarfOpPiece(ByteStreamer &Streamer, unsigned SizeInBits,
unsigned OffsetInBits = 0) const;
/// \brief Emit a partial DWARF register operation.
/// \param MLoc the register
/// \param PieceSize size and
/// \param PieceOffset offset of the piece in bits, if this is one
/// piece of an aggregate value.
///
/// If size and offset is zero an operation for the entire
/// register is emitted: Some targets do not provide a DWARF
/// register number for every register. If this is the case, this
/// function will attempt to emit a DWARF register by emitting a
/// piece of a super-register or by piecing together multiple
/// subregisters that alias the register.
void EmitDwarfRegOpPiece(ByteStreamer &BS, const MachineLocation &MLoc,
unsigned PieceSize = 0,
unsigned PieceOffset = 0) const;
/// EmitDwarfRegOp - Emit a dwarf register operation.
/// \param Indirect whether this is a register-indirect address
virtual void EmitDwarfRegOp(ByteStreamer &BS, const MachineLocation &MLoc,
bool Indirect) const;
virtual void EmitDwarfRegOp(ByteStreamer &BS,
const MachineLocation &MLoc) const;
//===------------------------------------------------------------------===//
// Dwarf Lowering Routines
@ -441,6 +444,12 @@ class AsmPrinter : public MachineFunctionPass {
/// \brief Emit frame instruction to describe the layout of the frame.
void emitCFIInstruction(const MCCFIInstruction &Inst) const;
/// \brief Emit Dwarf abbreviation table.
void emitDwarfAbbrevs(const std::vector<DIEAbbrev *>& Abbrevs) const;
/// \brief Recursively emit Dwarf DIE tree.
void emitDwarfDIE(const DIE &Die) const;
//===------------------------------------------------------------------===//
// Inline Asm Support
//===------------------------------------------------------------------===//
@ -474,7 +483,7 @@ class AsmPrinter : public MachineFunctionPass {
/// Let the target do anything it needs to do before emitting inlineasm.
/// \p StartInfo - the subtarget info before parsing inline asm
virtual void emitInlineAsmStart(const MCSubtargetInfo &StartInfo) const;
virtual void emitInlineAsmStart() const;
/// Let the target do anything it needs to do after emitting inlineasm.
/// This callback can be used restore the original mode in case the
@ -491,11 +500,15 @@ class AsmPrinter : public MachineFunctionPass {
mutable const MachineInstr *LastMI;
mutable unsigned LastFn;
mutable unsigned Counter;
mutable unsigned SetCounter;
/// This method emits the header for the current function.
virtual void EmitFunctionHeader();
/// Emit a blob of inline asm to the output streamer.
void
EmitInlineAsm(StringRef Str, const MDNode *LocMDNode = nullptr,
EmitInlineAsm(StringRef Str, const MCSubtargetInfo &STI,
const MCTargetOptions &MCOptions,
const MDNode *LocMDNode = nullptr,
InlineAsm::AsmDialect AsmDialect = InlineAsm::AD_ATT) const;
/// This method formats and emits the specified machine instruction that is an

View File

@ -0,0 +1,767 @@
//===- BasicTTIImpl.h -------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
/// This file provides a helper that implements much of the TTI interface in
/// terms of the target-independent code generator and TargetLowering
/// interfaces.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_BASICTTIIMPL_H
#define LLVM_CODEGEN_BASICTTIIMPL_H
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/TargetTransformInfoImpl.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetSubtargetInfo.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
namespace llvm {
extern cl::opt<unsigned> PartialUnrollingThreshold;
/// \brief Base class which can be used to help build a TTI implementation.
///
/// This class provides as much implementation of the TTI interface as is
/// possible using the target independent parts of the code generator.
///
/// In order to subclass it, your class must implement a getST() method to
/// return the subtarget, and a getTLI() method to return the target lowering.
/// We need these methods implemented in the derived class so that this class
/// doesn't have to duplicate storage for them.
template <typename T>
class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
private:
typedef TargetTransformInfoImplCRTPBase<T> BaseT;
typedef TargetTransformInfo TTI;
/// Estimate the overhead of scalarizing an instruction. Insert and Extract
/// are set if the result needs to be inserted and/or extracted from vectors.
unsigned getScalarizationOverhead(Type *Ty, bool Insert, bool Extract) {
assert(Ty->isVectorTy() && "Can only scalarize vectors");
unsigned Cost = 0;
for (int i = 0, e = Ty->getVectorNumElements(); i < e; ++i) {
if (Insert)
Cost += static_cast<T *>(this)
->getVectorInstrCost(Instruction::InsertElement, Ty, i);
if (Extract)
Cost += static_cast<T *>(this)
->getVectorInstrCost(Instruction::ExtractElement, Ty, i);
}
return Cost;
}
/// Estimate the cost overhead of SK_Alternate shuffle.
unsigned getAltShuffleOverhead(Type *Ty) {
assert(Ty->isVectorTy() && "Can only shuffle vectors");
unsigned Cost = 0;
// Shuffle cost is equal to the cost of extracting element from its argument
// plus the cost of inserting them onto the result vector.
// e.g. <4 x float> has a mask of <0,5,2,7> i.e we need to extract from
// index 0 of first vector, index 1 of second vector,index 2 of first
// vector and finally index 3 of second vector and insert them at index
// <0,1,2,3> of result vector.
for (int i = 0, e = Ty->getVectorNumElements(); i < e; ++i) {
Cost += static_cast<T *>(this)
->getVectorInstrCost(Instruction::InsertElement, Ty, i);
Cost += static_cast<T *>(this)
->getVectorInstrCost(Instruction::ExtractElement, Ty, i);
}
return Cost;
}
/// \brief Local query method delegates up to T which *must* implement this!
const TargetSubtargetInfo *getST() const {
return static_cast<const T *>(this)->getST();
}
/// \brief Local query method delegates up to T which *must* implement this!
const TargetLoweringBase *getTLI() const {
return static_cast<const T *>(this)->getTLI();
}
protected:
explicit BasicTTIImplBase(const TargetMachine *TM)
: BaseT(TM->getDataLayout()) {}
public:
// Provide value semantics. MSVC requires that we spell all of these out.
BasicTTIImplBase(const BasicTTIImplBase &Arg)
: BaseT(static_cast<const BaseT &>(Arg)) {}
BasicTTIImplBase(BasicTTIImplBase &&Arg)
: BaseT(std::move(static_cast<BaseT &>(Arg))) {}
BasicTTIImplBase &operator=(const BasicTTIImplBase &RHS) {
BaseT::operator=(static_cast<const BaseT &>(RHS));
return *this;
}
BasicTTIImplBase &operator=(BasicTTIImplBase &&RHS) {
BaseT::operator=(std::move(static_cast<BaseT &>(RHS)));
return *this;
}
/// \name Scalar TTI Implementations
/// @{
bool hasBranchDivergence() { return false; }
bool isSourceOfDivergence(const Value *V) { return false; }
bool isLegalAddImmediate(int64_t imm) {
return getTLI()->isLegalAddImmediate(imm);
}
bool isLegalICmpImmediate(int64_t imm) {
return getTLI()->isLegalICmpImmediate(imm);
}
bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
bool HasBaseReg, int64_t Scale) {
TargetLoweringBase::AddrMode AM;
AM.BaseGV = BaseGV;
AM.BaseOffs = BaseOffset;
AM.HasBaseReg = HasBaseReg;
AM.Scale = Scale;
return getTLI()->isLegalAddressingMode(AM, Ty);
}
int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
bool HasBaseReg, int64_t Scale) {
TargetLoweringBase::AddrMode AM;
AM.BaseGV = BaseGV;
AM.BaseOffs = BaseOffset;
AM.HasBaseReg = HasBaseReg;
AM.Scale = Scale;
return getTLI()->getScalingFactorCost(AM, Ty);
}
bool isTruncateFree(Type *Ty1, Type *Ty2) {
return getTLI()->isTruncateFree(Ty1, Ty2);
}
bool isProfitableToHoist(Instruction *I) {
return getTLI()->isProfitableToHoist(I);
}
bool isTypeLegal(Type *Ty) {
EVT VT = getTLI()->getValueType(Ty);
return getTLI()->isTypeLegal(VT);
}
unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
ArrayRef<const Value *> Arguments) {
return BaseT::getIntrinsicCost(IID, RetTy, Arguments);
}
unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
ArrayRef<Type *> ParamTys) {
if (IID == Intrinsic::cttz) {
if (getTLI()->isCheapToSpeculateCttz())
return TargetTransformInfo::TCC_Basic;
return TargetTransformInfo::TCC_Expensive;
}
if (IID == Intrinsic::ctlz) {
if (getTLI()->isCheapToSpeculateCtlz())
return TargetTransformInfo::TCC_Basic;
return TargetTransformInfo::TCC_Expensive;
}
return BaseT::getIntrinsicCost(IID, RetTy, ParamTys);
}
unsigned getJumpBufAlignment() { return getTLI()->getJumpBufAlignment(); }
unsigned getJumpBufSize() { return getTLI()->getJumpBufSize(); }
bool shouldBuildLookupTables() {
const TargetLoweringBase *TLI = getTLI();
return TLI->isOperationLegalOrCustom(ISD::BR_JT, MVT::Other) ||
TLI->isOperationLegalOrCustom(ISD::BRIND, MVT::Other);
}
bool haveFastSqrt(Type *Ty) {
const TargetLoweringBase *TLI = getTLI();
EVT VT = TLI->getValueType(Ty);
return TLI->isTypeLegal(VT) &&
TLI->isOperationLegalOrCustom(ISD::FSQRT, VT);
}
unsigned getFPOpCost(Type *Ty) {
// By default, FP instructions are no more expensive since they are
// implemented in HW. Target specific TTI can override this.
return TargetTransformInfo::TCC_Basic;
}
unsigned getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy) {
const TargetLoweringBase *TLI = getTLI();
switch (Opcode) {
default: break;
case Instruction::Trunc: {
if (TLI->isTruncateFree(OpTy, Ty))
return TargetTransformInfo::TCC_Free;
return TargetTransformInfo::TCC_Basic;
}
case Instruction::ZExt: {
if (TLI->isZExtFree(OpTy, Ty))
return TargetTransformInfo::TCC_Free;
return TargetTransformInfo::TCC_Basic;
}
}
return BaseT::getOperationCost(Opcode, Ty, OpTy);
}
void getUnrollingPreferences(Loop *L, TTI::UnrollingPreferences &UP) {
// This unrolling functionality is target independent, but to provide some
// motivation for its intended use, for x86:
// According to the Intel 64 and IA-32 Architectures Optimization Reference
// Manual, Intel Core models and later have a loop stream detector (and
// associated uop queue) that can benefit from partial unrolling.
// The relevant requirements are:
// - The loop must have no more than 4 (8 for Nehalem and later) branches
// taken, and none of them may be calls.
// - The loop can have no more than 18 (28 for Nehalem and later) uops.
// According to the Software Optimization Guide for AMD Family 15h
// Processors, models 30h-4fh (Steamroller and later) have a loop predictor
// and loop buffer which can benefit from partial unrolling.
// The relevant requirements are:
// - The loop must have fewer than 16 branches
// - The loop must have less than 40 uops in all executed loop branches
// The number of taken branches in a loop is hard to estimate here, and
// benchmarking has revealed that it is better not to be conservative when
// estimating the branch count. As a result, we'll ignore the branch limits
// until someone finds a case where it matters in practice.
unsigned MaxOps;
const TargetSubtargetInfo *ST = getST();
if (PartialUnrollingThreshold.getNumOccurrences() > 0)
MaxOps = PartialUnrollingThreshold;
else if (ST->getSchedModel().LoopMicroOpBufferSize > 0)
MaxOps = ST->getSchedModel().LoopMicroOpBufferSize;
else
return;
// Scan the loop: don't unroll loops with calls.
for (Loop::block_iterator I = L->block_begin(), E = L->block_end(); I != E;
++I) {
BasicBlock *BB = *I;
for (BasicBlock::iterator J = BB->begin(), JE = BB->end(); J != JE; ++J)
if (isa<CallInst>(J) || isa<InvokeInst>(J)) {
ImmutableCallSite CS(J);
if (const Function *F = CS.getCalledFunction()) {
if (!static_cast<T *>(this)->isLoweredToCall(F))
continue;
}
return;
}
}
// Enable runtime and partial unrolling up to the specified size.
UP.Partial = UP.Runtime = true;
UP.PartialThreshold = UP.PartialOptSizeThreshold = MaxOps;
}
/// @}
/// \name Vector TTI Implementations
/// @{
unsigned getNumberOfRegisters(bool Vector) { return 1; }
unsigned getRegisterBitWidth(bool Vector) { return 32; }
unsigned getMaxInterleaveFactor(unsigned VF) { return 1; }
unsigned getArithmeticInstrCost(
unsigned Opcode, Type *Ty,
TTI::OperandValueKind Opd1Info = TTI::OK_AnyValue,
TTI::OperandValueKind Opd2Info = TTI::OK_AnyValue,
TTI::OperandValueProperties Opd1PropInfo = TTI::OP_None,
TTI::OperandValueProperties Opd2PropInfo = TTI::OP_None) {
// Check if any of the operands are vector operands.
const TargetLoweringBase *TLI = getTLI();
int ISD = TLI->InstructionOpcodeToISD(Opcode);
assert(ISD && "Invalid opcode");
std::pair<unsigned, MVT> LT = TLI->getTypeLegalizationCost(Ty);
bool IsFloat = Ty->getScalarType()->isFloatingPointTy();
// Assume that floating point arithmetic operations cost twice as much as
// integer operations.
unsigned OpCost = (IsFloat ? 2 : 1);
if (TLI->isOperationLegalOrPromote(ISD, LT.second)) {
// The operation is legal. Assume it costs 1.
// If the type is split to multiple registers, assume that there is some
// overhead to this.
// TODO: Once we have extract/insert subvector cost we need to use them.
if (LT.first > 1)
return LT.first * 2 * OpCost;
return LT.first * 1 * OpCost;
}
if (!TLI->isOperationExpand(ISD, LT.second)) {
// If the operation is custom lowered then assume
// thare the code is twice as expensive.
return LT.first * 2 * OpCost;
}
// Else, assume that we need to scalarize this op.
if (Ty->isVectorTy()) {
unsigned Num = Ty->getVectorNumElements();
unsigned Cost = static_cast<T *>(this)
->getArithmeticInstrCost(Opcode, Ty->getScalarType());
// return the cost of multiple scalar invocation plus the cost of
// inserting
// and extracting the values.
return getScalarizationOverhead(Ty, true, true) + Num * Cost;
}
// We don't know anything about this scalar instruction.
return OpCost;
}
unsigned getShuffleCost(TTI::ShuffleKind Kind, Type *Tp, int Index,
Type *SubTp) {
if (Kind == TTI::SK_Alternate) {
return getAltShuffleOverhead(Tp);
}
return 1;
}
unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) {
const TargetLoweringBase *TLI = getTLI();
int ISD = TLI->InstructionOpcodeToISD(Opcode);
assert(ISD && "Invalid opcode");
std::pair<unsigned, MVT> SrcLT = TLI->getTypeLegalizationCost(Src);
std::pair<unsigned, MVT> DstLT = TLI->getTypeLegalizationCost(Dst);
// Check for NOOP conversions.
if (SrcLT.first == DstLT.first &&
SrcLT.second.getSizeInBits() == DstLT.second.getSizeInBits()) {
// Bitcast between types that are legalized to the same type are free.
if (Opcode == Instruction::BitCast || Opcode == Instruction::Trunc)
return 0;
}
if (Opcode == Instruction::Trunc &&
TLI->isTruncateFree(SrcLT.second, DstLT.second))
return 0;
if (Opcode == Instruction::ZExt &&
TLI->isZExtFree(SrcLT.second, DstLT.second))
return 0;
// If the cast is marked as legal (or promote) then assume low cost.
if (SrcLT.first == DstLT.first &&
TLI->isOperationLegalOrPromote(ISD, DstLT.second))
return 1;
// Handle scalar conversions.
if (!Src->isVectorTy() && !Dst->isVectorTy()) {
// Scalar bitcasts are usually free.
if (Opcode == Instruction::BitCast)
return 0;
// Just check the op cost. If the operation is legal then assume it costs
// 1.
if (!TLI->isOperationExpand(ISD, DstLT.second))
return 1;
// Assume that illegal scalar instruction are expensive.
return 4;
}
// Check vector-to-vector casts.
if (Dst->isVectorTy() && Src->isVectorTy()) {
// If the cast is between same-sized registers, then the check is simple.
if (SrcLT.first == DstLT.first &&
SrcLT.second.getSizeInBits() == DstLT.second.getSizeInBits()) {
// Assume that Zext is done using AND.
if (Opcode == Instruction::ZExt)
return 1;
// Assume that sext is done using SHL and SRA.
if (Opcode == Instruction::SExt)
return 2;
// Just check the op cost. If the operation is legal then assume it
// costs
// 1 and multiply by the type-legalization overhead.
if (!TLI->isOperationExpand(ISD, DstLT.second))
return SrcLT.first * 1;
}
// If we are converting vectors and the operation is illegal, or
// if the vectors are legalized to different types, estimate the
// scalarization costs.
unsigned Num = Dst->getVectorNumElements();
unsigned Cost = static_cast<T *>(this)->getCastInstrCost(
Opcode, Dst->getScalarType(), Src->getScalarType());
// Return the cost of multiple scalar invocation plus the cost of
// inserting and extracting the values.
return getScalarizationOverhead(Dst, true, true) + Num * Cost;
}
// We already handled vector-to-vector and scalar-to-scalar conversions.
// This
// is where we handle bitcast between vectors and scalars. We need to assume
// that the conversion is scalarized in one way or another.
if (Opcode == Instruction::BitCast)
// Illegal bitcasts are done by storing and loading from a stack slot.
return (Src->isVectorTy() ? getScalarizationOverhead(Src, false, true)
: 0) +
(Dst->isVectorTy() ? getScalarizationOverhead(Dst, true, false)
: 0);
llvm_unreachable("Unhandled cast");
}
unsigned getCFInstrCost(unsigned Opcode) {
// Branches are assumed to be predicted.
return 0;
}
unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy) {
const TargetLoweringBase *TLI = getTLI();
int ISD = TLI->InstructionOpcodeToISD(Opcode);
assert(ISD && "Invalid opcode");
// Selects on vectors are actually vector selects.
if (ISD == ISD::SELECT) {
assert(CondTy && "CondTy must exist");
if (CondTy->isVectorTy())
ISD = ISD::VSELECT;
}
std::pair<unsigned, MVT> LT = TLI->getTypeLegalizationCost(ValTy);
if (!(ValTy->isVectorTy() && !LT.second.isVector()) &&
!TLI->isOperationExpand(ISD, LT.second)) {
// The operation is legal. Assume it costs 1. Multiply
// by the type-legalization overhead.
return LT.first * 1;
}
// Otherwise, assume that the cast is scalarized.
if (ValTy->isVectorTy()) {
unsigned Num = ValTy->getVectorNumElements();
if (CondTy)
CondTy = CondTy->getScalarType();
unsigned Cost = static_cast<T *>(this)->getCmpSelInstrCost(
Opcode, ValTy->getScalarType(), CondTy);
// Return the cost of multiple scalar invocation plus the cost of
// inserting
// and extracting the values.
return getScalarizationOverhead(ValTy, true, false) + Num * Cost;
}
// Unknown scalar opcode.
return 1;
}
unsigned getVectorInstrCost(unsigned Opcode, Type *Val, unsigned Index) {
std::pair<unsigned, MVT> LT =
getTLI()->getTypeLegalizationCost(Val->getScalarType());
return LT.first;
}
unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment,
unsigned AddressSpace) {
assert(!Src->isVoidTy() && "Invalid type");
std::pair<unsigned, MVT> LT = getTLI()->getTypeLegalizationCost(Src);
// Assuming that all loads of legal types cost 1.
unsigned Cost = LT.first;
if (Src->isVectorTy() &&
Src->getPrimitiveSizeInBits() < LT.second.getSizeInBits()) {
// This is a vector load that legalizes to a larger type than the vector
// itself. Unless the corresponding extending load or truncating store is
// legal, then this will scalarize.
TargetLowering::LegalizeAction LA = TargetLowering::Expand;
EVT MemVT = getTLI()->getValueType(Src, true);
if (MemVT.isSimple() && MemVT != MVT::Other) {
if (Opcode == Instruction::Store)
LA = getTLI()->getTruncStoreAction(LT.second, MemVT.getSimpleVT());
else
LA = getTLI()->getLoadExtAction(ISD::EXTLOAD, LT.second, MemVT);
}
if (LA != TargetLowering::Legal && LA != TargetLowering::Custom) {
// This is a vector load/store for some illegal type that is scalarized.
// We must account for the cost of building or decomposing the vector.
Cost += getScalarizationOverhead(Src, Opcode != Instruction::Store,
Opcode == Instruction::Store);
}
}
return Cost;
}
unsigned getIntrinsicInstrCost(Intrinsic::ID IID, Type *RetTy,
ArrayRef<Type *> Tys) {
unsigned ISD = 0;
switch (IID) {
default: {
// Assume that we need to scalarize this intrinsic.
unsigned ScalarizationCost = 0;
unsigned ScalarCalls = 1;
Type *ScalarRetTy = RetTy;
if (RetTy->isVectorTy()) {
ScalarizationCost = getScalarizationOverhead(RetTy, true, false);
ScalarCalls = std::max(ScalarCalls, RetTy->getVectorNumElements());
ScalarRetTy = RetTy->getScalarType();
}
SmallVector<Type *, 4> ScalarTys;
for (unsigned i = 0, ie = Tys.size(); i != ie; ++i) {
Type *Ty = Tys[i];
if (Ty->isVectorTy()) {
ScalarizationCost += getScalarizationOverhead(Ty, false, true);
ScalarCalls = std::max(ScalarCalls, Ty->getVectorNumElements());
Ty = Ty->getScalarType();
}
ScalarTys.push_back(Ty);
}
if (ScalarCalls == 1)
return 1; // Return cost of a scalar intrinsic. Assume it to be cheap.
unsigned ScalarCost = static_cast<T *>(this)->getIntrinsicInstrCost(
IID, ScalarRetTy, ScalarTys);
return ScalarCalls * ScalarCost + ScalarizationCost;
}
// Look for intrinsics that can be lowered directly or turned into a scalar
// intrinsic call.
case Intrinsic::sqrt:
ISD = ISD::FSQRT;
break;
case Intrinsic::sin:
ISD = ISD::FSIN;
break;
case Intrinsic::cos:
ISD = ISD::FCOS;
break;
case Intrinsic::exp:
ISD = ISD::FEXP;
break;
case Intrinsic::exp2:
ISD = ISD::FEXP2;
break;
case Intrinsic::log:
ISD = ISD::FLOG;
break;
case Intrinsic::log10:
ISD = ISD::FLOG10;
break;
case Intrinsic::log2:
ISD = ISD::FLOG2;
break;
case Intrinsic::fabs:
ISD = ISD::FABS;
break;
case Intrinsic::minnum:
ISD = ISD::FMINNUM;
break;
case Intrinsic::maxnum:
ISD = ISD::FMAXNUM;
break;
case Intrinsic::copysign:
ISD = ISD::FCOPYSIGN;
break;
case Intrinsic::floor:
ISD = ISD::FFLOOR;
break;
case Intrinsic::ceil:
ISD = ISD::FCEIL;
break;
case Intrinsic::trunc:
ISD = ISD::FTRUNC;
break;
case Intrinsic::nearbyint:
ISD = ISD::FNEARBYINT;
break;
case Intrinsic::rint:
ISD = ISD::FRINT;
break;
case Intrinsic::round:
ISD = ISD::FROUND;
break;
case Intrinsic::pow:
ISD = ISD::FPOW;
break;
case Intrinsic::fma:
ISD = ISD::FMA;
break;
case Intrinsic::fmuladd:
ISD = ISD::FMA;
break;
// FIXME: We should return 0 whenever getIntrinsicCost == TCC_Free.
case Intrinsic::lifetime_start:
case Intrinsic::lifetime_end:
return 0;
case Intrinsic::masked_store:
return static_cast<T *>(this)
->getMaskedMemoryOpCost(Instruction::Store, Tys[0], 0, 0);
case Intrinsic::masked_load:
return static_cast<T *>(this)
->getMaskedMemoryOpCost(Instruction::Load, RetTy, 0, 0);
}
const TargetLoweringBase *TLI = getTLI();
std::pair<unsigned, MVT> LT = TLI->getTypeLegalizationCost(RetTy);
if (TLI->isOperationLegalOrPromote(ISD, LT.second)) {
// The operation is legal. Assume it costs 1.
// If the type is split to multiple registers, assume that there is some
// overhead to this.
// TODO: Once we have extract/insert subvector cost we need to use them.
if (LT.first > 1)
return LT.first * 2;
return LT.first * 1;
}
if (!TLI->isOperationExpand(ISD, LT.second)) {
// If the operation is custom lowered then assume
// thare the code is twice as expensive.
return LT.first * 2;
}
// If we can't lower fmuladd into an FMA estimate the cost as a floating
// point mul followed by an add.
if (IID == Intrinsic::fmuladd)
return static_cast<T *>(this)
->getArithmeticInstrCost(BinaryOperator::FMul, RetTy) +
static_cast<T *>(this)
->getArithmeticInstrCost(BinaryOperator::FAdd, RetTy);
// Else, assume that we need to scalarize this intrinsic. For math builtins
// this will emit a costly libcall, adding call overhead and spills. Make it
// very expensive.
if (RetTy->isVectorTy()) {
unsigned ScalarizationCost = getScalarizationOverhead(RetTy, true, false);
unsigned ScalarCalls = RetTy->getVectorNumElements();
SmallVector<Type *, 4> ScalarTys;
for (unsigned i = 0, ie = Tys.size(); i != ie; ++i) {
Type *Ty = Tys[i];
if (Ty->isVectorTy())
Ty = Ty->getScalarType();
ScalarTys.push_back(Ty);
}
unsigned ScalarCost = static_cast<T *>(this)->getIntrinsicInstrCost(
IID, RetTy->getScalarType(), ScalarTys);
for (unsigned i = 0, ie = Tys.size(); i != ie; ++i) {
if (Tys[i]->isVectorTy()) {
ScalarizationCost += getScalarizationOverhead(Tys[i], false, true);
ScalarCalls = std::max(ScalarCalls, Tys[i]->getVectorNumElements());
}
}
return ScalarCalls * ScalarCost + ScalarizationCost;
}
// This is going to be turned into a library call, make it expensive.
return 10;
}
/// \brief Compute a cost of the given call instruction.
///
/// Compute the cost of calling function F with return type RetTy and
/// argument types Tys. F might be nullptr, in this case the cost of an
/// arbitrary call with the specified signature will be returned.
/// This is used, for instance, when we estimate call of a vector
/// counterpart of the given function.
/// \param F Called function, might be nullptr.
/// \param RetTy Return value types.
/// \param Tys Argument types.
/// \returns The cost of Call instruction.
unsigned getCallInstrCost(Function *F, Type *RetTy, ArrayRef<Type *> Tys) {
return 10;
}
unsigned getNumberOfParts(Type *Tp) {
std::pair<unsigned, MVT> LT = getTLI()->getTypeLegalizationCost(Tp);
return LT.first;
}
unsigned getAddressComputationCost(Type *Ty, bool IsComplex) { return 0; }
unsigned getReductionCost(unsigned Opcode, Type *Ty, bool IsPairwise) {
assert(Ty->isVectorTy() && "Expect a vector type");
unsigned NumVecElts = Ty->getVectorNumElements();
unsigned NumReduxLevels = Log2_32(NumVecElts);
unsigned ArithCost =
NumReduxLevels *
static_cast<T *>(this)->getArithmeticInstrCost(Opcode, Ty);
// Assume the pairwise shuffles add a cost.
unsigned ShuffleCost =
NumReduxLevels * (IsPairwise + 1) *
static_cast<T *>(this)
->getShuffleCost(TTI::SK_ExtractSubvector, Ty, NumVecElts / 2, Ty);
return ShuffleCost + ArithCost + getScalarizationOverhead(Ty, false, true);
}
/// @}
};
/// \brief Concrete BasicTTIImpl that can be used if no further customization
/// is needed.
class BasicTTIImpl : public BasicTTIImplBase<BasicTTIImpl> {
typedef BasicTTIImplBase<BasicTTIImpl> BaseT;
friend class BasicTTIImplBase<BasicTTIImpl>;
const TargetSubtargetInfo *ST;
const TargetLoweringBase *TLI;
const TargetSubtargetInfo *getST() const { return ST; }
const TargetLoweringBase *getTLI() const { return TLI; }
public:
explicit BasicTTIImpl(const TargetMachine *ST, Function &F);
// Provide value semantics. MSVC requires that we spell all of these out.
BasicTTIImpl(const BasicTTIImpl &Arg)
: BaseT(static_cast<const BaseT &>(Arg)), ST(Arg.ST), TLI(Arg.TLI) {}
BasicTTIImpl(BasicTTIImpl &&Arg)
: BaseT(std::move(static_cast<BaseT &>(Arg))), ST(std::move(Arg.ST)),
TLI(std::move(Arg.TLI)) {}
BasicTTIImpl &operator=(const BasicTTIImpl &RHS) {
BaseT::operator=(static_cast<const BaseT &>(RHS));
ST = RHS.ST;
TLI = RHS.TLI;
return *this;
}
BasicTTIImpl &operator=(BasicTTIImpl &&RHS) {
BaseT::operator=(std::move(static_cast<BaseT &>(RHS)));
ST = std::move(RHS.ST);
TLI = std::move(RHS.TLI);
return *this;
}
};
}
#endif

View File

@ -19,6 +19,7 @@
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Target/TargetCallingConv.h"
namespace llvm {
@ -313,13 +314,13 @@ class CCState {
/// produce a single value.
void AnalyzeCallResult(MVT VT, CCAssignFn Fn);
/// getFirstUnallocated - Return the first unallocated register in the set, or
/// NumRegs if they are all allocated.
unsigned getFirstUnallocated(const MCPhysReg *Regs, unsigned NumRegs) const {
for (unsigned i = 0; i != NumRegs; ++i)
/// getFirstUnallocated - Return the index of the first unallocated register
/// in the set, or Regs.size() if they are all allocated.
unsigned getFirstUnallocated(ArrayRef<MCPhysReg> Regs) const {
for (unsigned i = 0; i < Regs.size(); ++i)
if (!isAllocated(Regs[i]))
return i;
return NumRegs;
return Regs.size();
}
/// AllocateReg - Attempt to allocate one register. If it is not available,
@ -342,9 +343,9 @@ class CCState {
/// AllocateReg - Attempt to allocate one of the specified registers. If none
/// are available, return zero. Otherwise, return the first one available,
/// marking it and any aliases as allocated.
unsigned AllocateReg(const MCPhysReg *Regs, unsigned NumRegs) {
unsigned FirstUnalloc = getFirstUnallocated(Regs, NumRegs);
if (FirstUnalloc == NumRegs)
unsigned AllocateReg(ArrayRef<MCPhysReg> Regs) {
unsigned FirstUnalloc = getFirstUnallocated(Regs);
if (FirstUnalloc == Regs.size())
return 0; // Didn't find the reg.
// Mark the register and any aliases as allocated.
@ -383,10 +384,9 @@ class CCState {
}
/// Version of AllocateReg with list of registers to be shadowed.
unsigned AllocateReg(const MCPhysReg *Regs, const MCPhysReg *ShadowRegs,
unsigned NumRegs) {
unsigned FirstUnalloc = getFirstUnallocated(Regs, NumRegs);
if (FirstUnalloc == NumRegs)
unsigned AllocateReg(ArrayRef<MCPhysReg> Regs, const MCPhysReg *ShadowRegs) {
unsigned FirstUnalloc = getFirstUnallocated(Regs);
if (FirstUnalloc == Regs.size())
return 0; // Didn't find the reg.
// Mark the register and any aliases as allocated.
@ -416,8 +416,8 @@ class CCState {
/// Version of AllocateStack with list of extra registers to be shadowed.
/// Note that, unlike AllocateReg, this shadows ALL of the shadow registers.
unsigned AllocateStack(unsigned Size, unsigned Align,
const MCPhysReg *ShadowRegs, unsigned NumShadowRegs) {
for (unsigned i = 0; i < NumShadowRegs; ++i)
ArrayRef<MCPhysReg> ShadowRegs) {
for (unsigned i = 0; i < ShadowRegs.size(); ++i)
MarkAllocated(ShadowRegs[i]);
return AllocateStack(Size, Align);
}

View File

@ -16,9 +16,12 @@
#ifndef LLVM_CODEGEN_COMMANDFLAGS_H
#define LLVM_CODEGEN_COMMANDFLAGS_H
#include "llvm/IR/Module.h"
#include "llvm/MC/MCTargetOptionsCommandFlags.h"
#include "llvm//MC/SubtargetFeature.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Host.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include <string>
@ -123,11 +126,6 @@ EnableHonorSignDependentRoundingFPMath("enable-sign-dependent-rounding-fp-math",
cl::desc("Force codegen to assume rounding mode can change dynamically"),
cl::init(false));
cl::opt<bool>
GenerateSoftFloatCalls("soft-float",
cl::desc("Generate software floating point library calls"),
cl::init(false));
cl::opt<llvm::FloatABI::ABIType>
FloatABIForCalls("float-abi",
cl::desc("Choose float ABI type"),
@ -207,6 +205,10 @@ FunctionSections("function-sections",
cl::desc("Emit functions into separate sections"),
cl::init(false));
cl::opt<bool> UniqueSectionNames("unique-section-names",
cl::desc("Give unique names to every section"),
cl::init(true));
cl::opt<llvm::JumpTable::JumpTableType>
JTableType("jump-table-type",
cl::desc("Choose the type of Jump-Instruction Table for jumptable."),
@ -222,57 +224,17 @@ JTableType("jump-table-type",
"Create one table per unique function type."),
clEnumValEnd));
cl::opt<bool>
FCFI("fcfi",
cl::desc("Apply forward-edge control-flow integrity"),
cl::init(false));
cl::opt<llvm::CFIntegrity>
CFIType("cfi-type",
cl::desc("Choose the type of Control-Flow Integrity check to add"),
cl::init(CFIntegrity::Sub),
cl::values(
clEnumValN(CFIntegrity::Sub, "sub",
"Subtract the pointer from the table base, then mask."),
clEnumValN(CFIntegrity::Ror, "ror",
"Use rotate to check the offset from a table base."),
clEnumValN(CFIntegrity::Add, "add",
"Mask out the high bits and add to an aligned base."),
clEnumValEnd));
cl::opt<bool>
CFIEnforcing("cfi-enforcing",
cl::desc("Enforce CFI or pass the violation to a function."),
cl::init(false));
// Note that this option is linked to the cfi-enforcing option above: if
// cfi-enforcing is set, then the cfi-func-name option is entirely ignored. If
// cfi-enforcing is false and no cfi-func-name is set, then a default function
// will be generated that ignores all CFI violations. The expected signature for
// functions called with CFI violations is
//
// void (i8*, i8*)
//
// The first pointer is a C string containing the name of the function in which
// the violation occurs, and the second pointer is the pointer that violated
// CFI.
cl::opt<std::string>
CFIFuncName("cfi-func-name", cl::desc("The name of the CFI function to call"),
cl::init(""));
// Common utility function tightly tied to the options listed here. Initializes
// a TargetOptions object with CodeGen flags and returns it.
static inline TargetOptions InitTargetOptionsFromCodeGenFlags() {
TargetOptions Options;
Options.LessPreciseFPMADOption = EnableFPMAD;
Options.NoFramePointerElim = DisableFPElim;
Options.AllowFPOpFusion = FuseFPOps;
Options.UnsafeFPMath = EnableUnsafeFPMath;
Options.NoInfsFPMath = EnableNoInfsFPMath;
Options.NoNaNsFPMath = EnableNoNaNsFPMath;
Options.HonorSignDependentRoundingFPMathOption =
EnableHonorSignDependentRoundingFPMath;
Options.UseSoftFloat = GenerateSoftFloatCalls;
if (FloatABIForCalls != FloatABI::Default)
Options.FloatABIType = FloatABIForCalls;
Options.NoZerosInBSS = DontPlaceZerosInBSS;
@ -284,17 +246,71 @@ static inline TargetOptions InitTargetOptionsFromCodeGenFlags() {
Options.UseInitArray = !UseCtors;
Options.DataSections = DataSections;
Options.FunctionSections = FunctionSections;
Options.UniqueSectionNames = UniqueSectionNames;
Options.MCOptions = InitMCTargetOptionsFromFlags();
Options.JTType = JTableType;
Options.FCFI = FCFI;
Options.CFIType = CFIType;
Options.CFIEnforcing = CFIEnforcing;
Options.CFIFuncName = CFIFuncName;
Options.ThreadModel = TMModel;
return Options;
}
static inline std::string getCPUStr() {
// If user asked for the 'native' CPU, autodetect here. If autodection fails,
// this will set the CPU to an empty string which tells the target to
// pick a basic default.
if (MCPU == "native")
return sys::getHostCPUName();
return MCPU;
}
static inline std::string getFeaturesStr() {
SubtargetFeatures Features;
// If user asked for the 'native' CPU, we need to autodetect features.
// This is necessary for x86 where the CPU might not support all the
// features the autodetected CPU name lists in the target. For example,
// not all Sandybridge processors support AVX.
if (MCPU == "native") {
StringMap<bool> HostFeatures;
if (sys::getHostCPUFeatures(HostFeatures))
for (auto &F : HostFeatures)
Features.AddFeature(F.first(), F.second);
}
for (unsigned i = 0; i != MAttrs.size(); ++i)
Features.AddFeature(MAttrs[i]);
return Features.getString();
}
/// \brief Set function attributes of functions in Module M based on CPU,
/// Features, and command line flags.
static inline void setFunctionAttributes(StringRef CPU, StringRef Features,
Module &M) {
for (auto &F : M) {
auto &Ctx = F.getContext();
AttributeSet Attrs = F.getAttributes(), NewAttrs;
if (!CPU.empty())
NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex,
"target-cpu", CPU);
if (!Features.empty())
NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex,
"target-features", Features);
if (DisableFPElim.getNumOccurrences() > 0)
NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex,
"no-frame-pointer-elim",
DisableFPElim ? "true" : "false");
// Let NewAttrs override Attrs.
NewAttrs = Attrs.addAttributes(Ctx, AttributeSet::FunctionIndex, NewAttrs);
F.setAttributes(NewAttrs);
}
}
#endif

View File

@ -16,6 +16,7 @@
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/DwarfStringPoolEntry.h"
#include "llvm/Support/Dwarf.h"
#include <vector>
@ -95,7 +96,7 @@ class DIEAbbrev : public FoldingSetNode {
/// Emit - Print the abbreviation using the specified asm printer.
///
void Emit(AsmPrinter *AP) const;
void Emit(const AsmPrinter *AP) const;
#ifndef NDEBUG
void print(raw_ostream &O);
@ -200,8 +201,6 @@ class DIE {
/// to DWARF attribute classes.
///
class DIEValue {
virtual void anchor();
public:
enum Type {
isInteger,
@ -216,13 +215,14 @@ class DIEValue {
isLocList,
};
protected:
private:
/// Ty - Type of data stored in the value.
///
Type Ty;
protected:
explicit DIEValue(Type T) : Ty(T) {}
virtual ~DIEValue() {}
~DIEValue() {}
public:
// Accessors
@ -230,14 +230,14 @@ class DIEValue {
/// EmitValue - Emit value via the Dwarf writer.
///
virtual void EmitValue(AsmPrinter *AP, dwarf::Form Form) const = 0;
void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
/// SizeOf - Return the size of a value in bytes.
///
virtual unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const = 0;
unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const;
#ifndef NDEBUG
virtual void print(raw_ostream &O) const = 0;
void print(raw_ostream &O) const;
void dump() const;
#endif
};
@ -246,6 +246,8 @@ class DIEValue {
/// DIEInteger - An integer value DIE.
///
class DIEInteger : public DIEValue {
friend DIEValue;
uint64_t Integer;
public:
@ -273,21 +275,18 @@ class DIEInteger : public DIEValue {
return dwarf::DW_FORM_data8;
}
/// EmitValue - Emit integer of appropriate size.
///
void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
uint64_t getValue() const { return Integer; }
/// SizeOf - Determine size of integer value in bytes.
///
unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override;
void setValue(uint64_t Val) { Integer = Val; }
// Implement isa/cast/dyncast.
static bool classof(const DIEValue *I) { return I->getType() == isInteger; }
private:
void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const;
#ifndef NDEBUG
void print(raw_ostream &O) const override;
void printImpl(raw_ostream &O) const;
#endif
};
@ -295,28 +294,26 @@ class DIEInteger : public DIEValue {
/// DIEExpr - An expression DIE.
//
class DIEExpr : public DIEValue {
friend class DIEValue;
const MCExpr *Expr;
public:
explicit DIEExpr(const MCExpr *E) : DIEValue(isExpr), Expr(E) {}
/// EmitValue - Emit expression value.
///
void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
/// getValue - Get MCExpr.
///
const MCExpr *getValue() const { return Expr; }
/// SizeOf - Determine size of expression value in bytes.
///
unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override;
// Implement isa/cast/dyncast.
static bool classof(const DIEValue *E) { return E->getType() == isExpr; }
private:
void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const;
#ifndef NDEBUG
void print(raw_ostream &O) const override;
void printImpl(raw_ostream &O) const;
#endif
};
@ -324,28 +321,26 @@ class DIEExpr : public DIEValue {
/// DIELabel - A label DIE.
//
class DIELabel : public DIEValue {
friend class DIEValue;
const MCSymbol *Label;
public:
explicit DIELabel(const MCSymbol *L) : DIEValue(isLabel), Label(L) {}
/// EmitValue - Emit label value.
///
void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
/// getValue - Get MCSymbol.
///
const MCSymbol *getValue() const { return Label; }
/// SizeOf - Determine size of label value in bytes.
///
unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override;
// Implement isa/cast/dyncast.
static bool classof(const DIEValue *L) { return L->getType() == isLabel; }
private:
void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const;
#ifndef NDEBUG
void print(raw_ostream &O) const override;
void printImpl(raw_ostream &O) const;
#endif
};
@ -353,6 +348,8 @@ class DIELabel : public DIEValue {
/// DIEDelta - A simple label difference DIE.
///
class DIEDelta : public DIEValue {
friend class DIEValue;
const MCSymbol *LabelHi;
const MCSymbol *LabelLo;
@ -360,19 +357,15 @@ class DIEDelta : public DIEValue {
DIEDelta(const MCSymbol *Hi, const MCSymbol *Lo)
: DIEValue(isDelta), LabelHi(Hi), LabelLo(Lo) {}
/// EmitValue - Emit delta value.
///
void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
/// SizeOf - Determine size of delta value in bytes.
///
unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override;
// Implement isa/cast/dyncast.
static bool classof(const DIEValue *D) { return D->getType() == isDelta; }
private:
void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const;
#ifndef NDEBUG
void print(raw_ostream &O) const override;
void printImpl(raw_ostream &O) const;
#endif
};
@ -380,29 +373,25 @@ class DIEDelta : public DIEValue {
/// DIEString - A container for string values.
///
class DIEString : public DIEValue {
const DIEValue *Access;
StringRef Str;
friend class DIEValue;
DwarfStringPoolEntryRef S;
public:
DIEString(const DIEValue *Acc, StringRef S)
: DIEValue(isString), Access(Acc), Str(S) {}
DIEString(DwarfStringPoolEntryRef S) : DIEValue(isString), S(S) {}
/// getString - Grab the string out of the object.
StringRef getString() const { return Str; }
/// EmitValue - Emit delta value.
///
void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
/// SizeOf - Determine size of delta value in bytes.
///
unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override;
StringRef getString() const { return S.getString(); }
// Implement isa/cast/dyncast.
static bool classof(const DIEValue *D) { return D->getType() == isString; }
private:
void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const;
#ifndef NDEBUG
void print(raw_ostream &O) const override;
void printImpl(raw_ostream &O) const;
#endif
};
@ -411,6 +400,8 @@ class DIEString : public DIEValue {
/// this class can also be used as a proxy for a debug information entry not
/// yet defined (ie. types.)
class DIEEntry : public DIEValue {
friend class DIEValue;
DIE &Entry;
public:
@ -419,53 +410,49 @@ class DIEEntry : public DIEValue {
DIE &getEntry() const { return Entry; }
/// EmitValue - Emit debug information entry offset.
///
void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
/// SizeOf - Determine size of debug information entry in bytes.
///
unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override {
return Form == dwarf::DW_FORM_ref_addr ? getRefAddrSize(AP)
: sizeof(int32_t);
}
/// Returns size of a ref_addr entry.
static unsigned getRefAddrSize(AsmPrinter *AP);
static unsigned getRefAddrSize(const AsmPrinter *AP);
// Implement isa/cast/dyncast.
static bool classof(const DIEValue *E) { return E->getType() == isEntry; }
private:
void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const {
return Form == dwarf::DW_FORM_ref_addr ? getRefAddrSize(AP)
: sizeof(int32_t);
}
#ifndef NDEBUG
void print(raw_ostream &O) const override;
void printImpl(raw_ostream &O) const;
#endif
};
//===--------------------------------------------------------------------===//
/// \brief A signature reference to a type unit.
class DIETypeSignature : public DIEValue {
friend class DIEValue;
const DwarfTypeUnit &Unit;
public:
explicit DIETypeSignature(const DwarfTypeUnit &Unit)
: DIEValue(isTypeSignature), Unit(Unit) {}
/// \brief Emit type unit signature.
void EmitValue(AsmPrinter *Asm, dwarf::Form Form) const override;
/// Returns size of a ref_sig8 entry.
unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override {
assert(Form == dwarf::DW_FORM_ref_sig8);
return 8;
}
// \brief Implement isa/cast/dyncast.
static bool classof(const DIEValue *E) {
return E->getType() == isTypeSignature;
}
private:
void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const {
assert(Form == dwarf::DW_FORM_ref_sig8);
return 8;
}
#ifndef NDEBUG
void print(raw_ostream &O) const override;
void dump() const;
void printImpl(raw_ostream &O) const;
#endif
};
@ -473,13 +460,15 @@ class DIETypeSignature : public DIEValue {
/// DIELoc - Represents an expression location.
//
class DIELoc : public DIEValue, public DIE {
friend class DIEValue;
mutable unsigned Size; // Size in bytes excluding size header.
public:
DIELoc() : DIEValue(isLoc), Size(0) {}
/// ComputeSize - Calculate the size of the location expression.
///
unsigned ComputeSize(AsmPrinter *AP) const;
unsigned ComputeSize(const AsmPrinter *AP) const;
/// BestForm - Choose the best form for data.
///
@ -496,19 +485,15 @@ class DIELoc : public DIEValue, public DIE {
return dwarf::DW_FORM_block;
}
/// EmitValue - Emit location data.
///
void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
/// SizeOf - Determine size of location data in bytes.
///
unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override;
// Implement isa/cast/dyncast.
static bool classof(const DIEValue *E) { return E->getType() == isLoc; }
private:
void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const;
#ifndef NDEBUG
void print(raw_ostream &O) const override;
void printImpl(raw_ostream &O) const;
#endif
};
@ -516,13 +501,15 @@ class DIELoc : public DIEValue, public DIE {
/// DIEBlock - Represents a block of values.
//
class DIEBlock : public DIEValue, public DIE {
friend class DIEValue;
mutable unsigned Size; // Size in bytes excluding size header.
public:
DIEBlock() : DIEValue(isBlock), Size(0) {}
/// ComputeSize - Calculate the size of the location expression.
///
unsigned ComputeSize(AsmPrinter *AP) const;
unsigned ComputeSize(const AsmPrinter *AP) const;
/// BestForm - Choose the best form for data.
///
@ -536,19 +523,15 @@ class DIEBlock : public DIEValue, public DIE {
return dwarf::DW_FORM_block;
}
/// EmitValue - Emit location data.
///
void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
/// SizeOf - Determine size of location data in bytes.
///
unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override;
// Implement isa/cast/dyncast.
static bool classof(const DIEValue *E) { return E->getType() == isBlock; }
private:
void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const;
#ifndef NDEBUG
void print(raw_ostream &O) const override;
void printImpl(raw_ostream &O) const;
#endif
};
@ -557,6 +540,8 @@ class DIEBlock : public DIEValue, public DIE {
/// section.
//
class DIELocList : public DIEValue {
friend class DIEValue;
// Index into the .debug_loc vector.
size_t Index;
@ -566,19 +551,15 @@ class DIELocList : public DIEValue {
/// getValue - Grab the current index out.
size_t getValue() const { return Index; }
/// EmitValue - Emit location data.
///
void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
/// SizeOf - Determine size of location data in bytes.
///
unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override;
// Implement isa/cast/dyncast.
static bool classof(const DIEValue *E) { return E->getType() == isLocList; }
private:
void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const;
unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const;
#ifndef NDEBUG
void print(raw_ostream &O) const override;
void printImpl(raw_ostream &O) const;
#endif
};

View File

@ -0,0 +1,51 @@
//===- llvm/CodeGen/DwarfStringPoolEntry.h - String pool entry --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_DWARFSTRINGPOOLENTRY_H
#define LLVM_CODEGEN_DWARFSTRINGPOOLENTRY_H
#include "llvm/ADT/StringMap.h"
namespace llvm {
class MCSymbol;
/// Data for a string pool entry.
struct DwarfStringPoolEntry {
MCSymbol *Symbol;
unsigned Offset;
unsigned Index;
};
/// String pool entry reference.
struct DwarfStringPoolEntryRef {
const StringMapEntry<DwarfStringPoolEntry> *I = nullptr;
public:
DwarfStringPoolEntryRef() = default;
explicit DwarfStringPoolEntryRef(
const StringMapEntry<DwarfStringPoolEntry> &I)
: I(&I) {}
explicit operator bool() const { return I; }
MCSymbol *getSymbol() const {
assert(I->second.Symbol && "No symbol available!");
return I->second.Symbol;
}
unsigned getOffset() const { return I->second.Offset; }
unsigned getIndex() const { return I->second.Index; }
StringRef getString() const { return I->first(); }
bool operator==(const DwarfStringPoolEntryRef &X) const { return I == X.I; }
bool operator!=(const DwarfStringPoolEntryRef &X) const { return I != X.I; }
};
} // end namespace llvm
#endif

View File

@ -1,122 +0,0 @@
//===-- ForwardControlFlowIntegrity.h: Forward-Edge CFI ---------*- C++ -*-===//
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass instruments indirect calls with checks to ensure that these calls
// pass through the appropriate jump-instruction table generated by
// JumpInstrTables.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_FORWARDCONTROLFLOWINTEGRITY_H
#define LLVM_CODEGEN_FORWARDCONTROLFLOWINTEGRITY_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Pass.h"
#include "llvm/Target/TargetOptions.h"
#include <string>
namespace llvm {
class AnalysisUsage;
class BasicBlock;
class Constant;
class Function;
class Instruction;
class Module;
class Value;
/// ForwardControlFlowIntegrity uses the information from JumpInstrTableInfo to
/// prepend checks to indirect calls to make sure that these calls target valid
/// locations.
class ForwardControlFlowIntegrity : public ModulePass {
public:
static char ID;
ForwardControlFlowIntegrity();
ForwardControlFlowIntegrity(JumpTable::JumpTableType JTT,
CFIntegrity CFIType,
bool CFIEnforcing, std::string CFIFuncName);
~ForwardControlFlowIntegrity() override;
/// Runs the CFI pass on a given module. This works best if the module in
/// question is the result of link-time optimization (see lib/LTO).
bool runOnModule(Module &M) override;
const char *getPassName() const override {
return "Forward Control-Flow Integrity";
}
void getAnalysisUsage(AnalysisUsage &AU) const override;
private:
typedef SmallVector<Instruction *, 64> CallSet;
/// A structure that is used to keep track of constant table information.
struct CFIConstants {
Constant *StartValue;
Constant *MaskValue;
Constant *Size;
};
/// A map from function type to the base of the table for this type and a mask
/// for the table
typedef DenseMap<FunctionType *, CFIConstants> CFITables;
CallSet IndirectCalls;
/// The type of jumptable implementation.
JumpTable::JumpTableType JTType;
/// The type of CFI check to add before each indirect call.
CFIntegrity CFIType;
/// A value that controls whether or not CFI violations cause a halt.
bool CFIEnforcing;
/// The name of the function to call in case of a CFI violation when
/// CFIEnforcing is false. There is a default function that ignores
/// violations.
std::string CFIFuncName;
/// The alignment of each entry in the table, from JumpInstrTableInfo. The
/// JumpInstrTableInfo class always makes this a power of two.
uint64_t ByteAlignment;
/// The base-2 logarithm of ByteAlignment, needed for some of the transforms
/// (like CFIntegrity::Ror)
unsigned LogByteAlignment;
/// Adds checks to each indirect call site to make sure that it is calling a
/// function in our jump table.
void updateIndirectCalls(Module &M, CFITables &CFIT);
/// Walks the instructions to find all the indirect calls.
void getIndirectCalls(Module &M);
/// Adds a function that handles violations in non-enforcing mode
/// (!CFIEnforcing). The default warning function simply returns, since the
/// exact details of how to handle CFI violations depend on the application.
void addWarningFunction(Module &M);
/// Rewrites a function pointer in a call/invoke instruction to force it into
/// a table.
void rewriteFunctionPointer(Module &M, Instruction *I, Value *FunPtr,
Constant *JumpTableStart, Constant *JumpTableMask,
Constant *JumpTableSize);
/// Inserts a check and a call to a warning function at a given instruction
/// that must be an indirect call.
void insertWarning(Module &M, BasicBlock *Block, Instruction *I,
Value *FunPtr);
};
ModulePass *
createForwardControlFlowIntegrityPass(JumpTable::JumpTableType JTT,
CFIntegrity CFIType,
bool CFIEnforcing, StringRef CFIFuncName);
}
#endif // LLVM_CODEGEN_FORWARDCONTROLFLOWINTEGRITY_H

View File

@ -18,6 +18,7 @@
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IndexedMap.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/ISDOpcodes.h"
@ -73,6 +74,16 @@ class FunctionLoweringInfo {
/// cross-basic-block values.
DenseMap<const Value*, unsigned> ValueMap;
// Keep track of frame indices allocated for statepoints as they could be used
// across basic block boundaries.
// Key of the map is statepoint instruction, value is a map from spilled
// llvm Value to the optional stack stack slot index.
// If optional is unspecified it means that we have visited this value
// but didn't spill it.
typedef DenseMap<const Value*, Optional<int>> StatepointSpilledValueMapTy;
DenseMap<const Instruction*, StatepointSpilledValueMapTy>
StatepointRelocatedValues;
/// StaticAllocaMap - Keep track of frame indices for fixed sized allocas in
/// the entry block. This allows the allocas to be efficiently referenced
/// anywhere in the function.
@ -221,6 +232,8 @@ class FunctionLoweringInfo {
int getArgumentFrameIndex(const Argument *A);
private:
void addSEHHandlersForLPads(ArrayRef<const LandingPadInst *> LPads);
/// LiveOutRegInfo - Information about live out vregs.
IndexedMap<LiveOutInfo, VirtReg2IndexFunctor> LiveOutRegInfo;
};
@ -232,11 +245,6 @@ class FunctionLoweringInfo {
/// floating-point support.
void ComputeUsesVAFloatArgument(const CallInst &I, MachineModuleInfo *MMI);
/// AddCatchInfo - Extract the personality and type infos from an eh.selector
/// call, and add them to the specified machine basic block.
void AddCatchInfo(const CallInst &I,
MachineModuleInfo *MMI, MachineBasicBlock *MBB);
/// AddLandingPadInfo - Extract the exception handling information from the
/// landingpad instruction and add them to the specified machine module info.
void AddLandingPadInfo(const LandingPadInst &I, MachineModuleInfo &MMI,

View File

@ -34,184 +34,173 @@
#define LLVM_CODEGEN_GCMETADATA_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/CodeGen/GCStrategy.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/Pass.h"
#include <memory>
namespace llvm {
class AsmPrinter;
class GCStrategy;
class Constant;
class MCSymbol;
class AsmPrinter;
class Constant;
class MCSymbol;
namespace GC {
/// PointKind - The type of a collector-safe point.
///
enum PointKind {
Loop, ///< Instr is a loop (backwards branch).
Return, ///< Instr is a return instruction.
PreCall, ///< Instr is a call instruction.
PostCall ///< Instr is the return address of a call.
};
/// GCPoint - Metadata for a collector-safe point in machine code.
///
struct GCPoint {
GC::PointKind Kind; ///< The kind of the safe point.
MCSymbol *Label; ///< A label.
DebugLoc Loc;
GCPoint(GC::PointKind K, MCSymbol *L, DebugLoc DL)
: Kind(K), Label(L), Loc(DL) {}
};
/// GCRoot - Metadata for a pointer to an object managed by the garbage
/// collector.
struct GCRoot {
int Num; ///< Usually a frame index.
int StackOffset; ///< Offset from the stack pointer.
const Constant *Metadata; ///< Metadata straight from the call
///< to llvm.gcroot.
GCRoot(int N, const Constant *MD) : Num(N), StackOffset(-1), Metadata(MD) {}
};
/// Garbage collection metadata for a single function. Currently, this
/// information only applies to GCStrategies which use GCRoot.
class GCFunctionInfo {
public:
typedef std::vector<GCPoint>::iterator iterator;
typedef std::vector<GCRoot>::iterator roots_iterator;
typedef std::vector<GCRoot>::const_iterator live_iterator;
private:
const Function &F;
GCStrategy &S;
uint64_t FrameSize;
std::vector<GCRoot> Roots;
std::vector<GCPoint> SafePoints;
// FIXME: Liveness. A 2D BitVector, perhaps?
//
// BitVector Liveness;
//
// bool islive(int point, int root) =
// Liveness[point * SafePoints.size() + root]
//
// The bit vector is the more compact representation where >3.2% of roots
// are live per safe point (1.5% on 64-bit hosts).
public:
GCFunctionInfo(const Function &F, GCStrategy &S);
~GCFunctionInfo();
/// getFunction - Return the function to which this metadata applies.
///
const Function &getFunction() const { return F; }
/// getStrategy - Return the GC strategy for the function.
///
GCStrategy &getStrategy() { return S; }
/// addStackRoot - Registers a root that lives on the stack. Num is the
/// stack object ID for the alloca (if the code generator is
// using MachineFrameInfo).
void addStackRoot(int Num, const Constant *Metadata) {
Roots.push_back(GCRoot(Num, Metadata));
}
/// GCPoint - Metadata for a collector-safe point in machine code.
/// removeStackRoot - Removes a root.
roots_iterator removeStackRoot(roots_iterator position) {
return Roots.erase(position);
}
/// addSafePoint - Notes the existence of a safe point. Num is the ID of the
/// label just prior to the safe point (if the code generator is using
/// MachineModuleInfo).
void addSafePoint(GC::PointKind Kind, MCSymbol *Label, DebugLoc DL) {
SafePoints.push_back(GCPoint(Kind, Label, DL));
}
/// getFrameSize/setFrameSize - Records the function's frame size.
///
struct GCPoint {
GC::PointKind Kind; ///< The kind of the safe point.
MCSymbol *Label; ///< A label.
DebugLoc Loc;
uint64_t getFrameSize() const { return FrameSize; }
void setFrameSize(uint64_t S) { FrameSize = S; }
GCPoint(GC::PointKind K, MCSymbol *L, DebugLoc DL)
: Kind(K), Label(L), Loc(DL) {}
};
/// begin/end - Iterators for safe points.
///
iterator begin() { return SafePoints.begin(); }
iterator end() { return SafePoints.end(); }
size_t size() const { return SafePoints.size(); }
/// GCRoot - Metadata for a pointer to an object managed by the garbage
/// collector.
struct GCRoot {
int Num; ///< Usually a frame index.
int StackOffset; ///< Offset from the stack pointer.
const Constant *Metadata; ///< Metadata straight from the call
///< to llvm.gcroot.
/// roots_begin/roots_end - Iterators for all roots in the function.
///
roots_iterator roots_begin() { return Roots.begin(); }
roots_iterator roots_end() { return Roots.end(); }
size_t roots_size() const { return Roots.size(); }
GCRoot(int N, const Constant *MD) : Num(N), StackOffset(-1), Metadata(MD) {}
};
/// live_begin/live_end - Iterators for live roots at a given safe point.
///
live_iterator live_begin(const iterator &p) { return roots_begin(); }
live_iterator live_end(const iterator &p) { return roots_end(); }
size_t live_size(const iterator &p) const { return roots_size(); }
};
/// An analysis pass which caches information about the entire Module.
/// Records both the function level information used by GCRoots and a
/// cache of the 'active' gc strategy objects for the current Module.
class GCModuleInfo : public ImmutablePass {
/// An owning list of all GCStrategies which have been created
SmallVector<std::unique_ptr<GCStrategy>, 1> GCStrategyList;
/// A helper map to speedup lookups into the above list
StringMap<GCStrategy*> GCStrategyMap;
/// Garbage collection metadata for a single function. Currently, this
/// information only applies to GCStrategies which use GCRoot.
class GCFunctionInfo {
public:
typedef std::vector<GCPoint>::iterator iterator;
typedef std::vector<GCRoot>::iterator roots_iterator;
typedef std::vector<GCRoot>::const_iterator live_iterator;
public:
/// Lookup the GCStrategy object associated with the given gc name.
/// Objects are owned internally; No caller should attempt to delete the
/// returned objects.
GCStrategy *getGCStrategy(const StringRef Name);
/// List of per function info objects. In theory, Each of these
/// may be associated with a different GC.
typedef std::vector<std::unique_ptr<GCFunctionInfo>> FuncInfoVec;
private:
const Function &F;
GCStrategy &S;
uint64_t FrameSize;
std::vector<GCRoot> Roots;
std::vector<GCPoint> SafePoints;
FuncInfoVec::iterator funcinfo_begin() { return Functions.begin(); }
FuncInfoVec::iterator funcinfo_end() { return Functions.end(); }
// FIXME: Liveness. A 2D BitVector, perhaps?
//
// BitVector Liveness;
//
// bool islive(int point, int root) =
// Liveness[point * SafePoints.size() + root]
//
// The bit vector is the more compact representation where >3.2% of roots
// are live per safe point (1.5% on 64-bit hosts).
private:
/// Owning list of all GCFunctionInfos associated with this Module
FuncInfoVec Functions;
public:
GCFunctionInfo(const Function &F, GCStrategy &S);
~GCFunctionInfo();
/// Non-owning map to bypass linear search when finding the GCFunctionInfo
/// associated with a particular Function.
typedef DenseMap<const Function *, GCFunctionInfo *> finfo_map_type;
finfo_map_type FInfoMap;
/// getFunction - Return the function to which this metadata applies.
///
const Function &getFunction() const { return F; }
public:
typedef SmallVector<std::unique_ptr<GCStrategy>,1>::const_iterator iterator;
/// getStrategy - Return the GC strategy for the function.
///
GCStrategy &getStrategy() { return S; }
static char ID;
/// addStackRoot - Registers a root that lives on the stack. Num is the
/// stack object ID for the alloca (if the code generator is
// using MachineFrameInfo).
void addStackRoot(int Num, const Constant *Metadata) {
Roots.push_back(GCRoot(Num, Metadata));
}
GCModuleInfo();
/// removeStackRoot - Removes a root.
roots_iterator removeStackRoot(roots_iterator position) {
return Roots.erase(position);
}
/// clear - Resets the pass. Any pass, which uses GCModuleInfo, should
/// call it in doFinalization().
///
void clear();
/// addSafePoint - Notes the existence of a safe point. Num is the ID of the
/// label just prior to the safe point (if the code generator is using
/// MachineModuleInfo).
void addSafePoint(GC::PointKind Kind, MCSymbol *Label, DebugLoc DL) {
SafePoints.push_back(GCPoint(Kind, Label, DL));
}
/// getFrameSize/setFrameSize - Records the function's frame size.
///
uint64_t getFrameSize() const { return FrameSize; }
void setFrameSize(uint64_t S) { FrameSize = S; }
/// begin/end - Iterators for safe points.
///
iterator begin() { return SafePoints.begin(); }
iterator end() { return SafePoints.end(); }
size_t size() const { return SafePoints.size(); }
/// roots_begin/roots_end - Iterators for all roots in the function.
///
roots_iterator roots_begin() { return Roots.begin(); }
roots_iterator roots_end () { return Roots.end(); }
size_t roots_size() const { return Roots.size(); }
/// live_begin/live_end - Iterators for live roots at a given safe point.
///
live_iterator live_begin(const iterator &p) { return roots_begin(); }
live_iterator live_end (const iterator &p) { return roots_end(); }
size_t live_size(const iterator &p) const { return roots_size(); }
};
/// An analysis pass which caches information about the entire Module.
/// Records both the function level information used by GCRoots and a
/// cache of the 'active' gc strategy objects for the current Module.
class GCModuleInfo : public ImmutablePass {
typedef StringMap<GCStrategy*> strategy_map_type;
typedef std::vector<std::unique_ptr<GCStrategy>> list_type;
strategy_map_type StrategyMap;
list_type StrategyList;
GCStrategy *getOrCreateStrategy(const Module *M, const std::string &Name);
public:
/// List of per function info objects. In theory, Each of these
/// may be associated with a different GC.
typedef std::vector<std::unique_ptr<GCFunctionInfo>> FuncInfoVec;
FuncInfoVec::iterator funcinfo_begin() { return Functions.begin(); }
FuncInfoVec::iterator funcinfo_end() { return Functions.end(); }
private:
/// Owning list of all GCFunctionInfos associated with this Module
FuncInfoVec Functions;
/// Non-owning map to bypass linear search when finding the GCFunctionInfo
/// associated with a particular Function.
typedef DenseMap<const Function*,GCFunctionInfo*> finfo_map_type;
finfo_map_type FInfoMap;
public:
typedef list_type::const_iterator iterator;
static char ID;
GCModuleInfo();
/// clear - Resets the pass. Any pass, which uses GCModuleInfo, should
/// call it in doFinalization().
///
void clear();
/// begin/end - Iterators for used strategies.
///
iterator begin() const { return StrategyList.begin(); }
iterator end() const { return StrategyList.end(); }
/// get - Look up function metadata. This is currently assumed
/// have the side effect of initializing the associated GCStrategy. That
/// will soon change.
GCFunctionInfo &getFunctionInfo(const Function &F);
};
/// begin/end - Iterators for used strategies.
///
iterator begin() const { return GCStrategyList.begin(); }
iterator end() const { return GCStrategyList.end(); }
/// get - Look up function metadata. This is currently assumed
/// have the side effect of initializing the associated GCStrategy. That
/// will soon change.
GCFunctionInfo &getFunctionInfo(const Function &F);
};
}
#endif

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