Merge llvm trunk r300422 and resolve conflicts.

This commit is contained in:
dim 2017-04-16 16:25:46 +00:00
commit 990b41b569
2025 changed files with 185772 additions and 75156 deletions

View File

@ -44,6 +44,9 @@ void LLVMAddAlignmentFromAssumptionsPass(LLVMPassManagerRef PM);
/** See llvm::createCFGSimplificationPass function. */
void LLVMAddCFGSimplificationPass(LLVMPassManagerRef PM);
/** See llvm::createLateCFGSimplificationPass function. */
void LLVMAddLateCFGSimplificationPass(LLVMPassManagerRef PM);
/** See llvm::createDeadStoreEliminationPass function. */
void LLVMAddDeadStoreEliminationPass(LLVMPassManagerRef PM);

View File

@ -551,7 +551,7 @@ lto_codegen_set_should_embed_uselists(lto_code_gen_t cg,
lto_bool_t ShouldEmbedUselists);
/**
* @}
* @} // endgoup LLVMCLTO
* @defgroup LLVMCTLTO ThinLTO
* @ingroup LLVMC
*
@ -668,75 +668,6 @@ const char *thinlto_module_get_object_file(thinlto_code_gen_t cg,
extern lto_bool_t thinlto_codegen_set_pic_model(thinlto_code_gen_t cg,
lto_codegen_model);
/**
* @}
* @defgroup LLVMCTLTO_CACHING ThinLTO Cache Control
* @ingroup LLVMCTLTO
*
* These entry points control the ThinLTO cache. The cache is intended to
* support incremental build, and thus needs to be persistent accross build.
* The client enabled the cache by supplying a path to an existing directory.
* The code generator will use this to store objects files that may be reused
* during a subsequent build.
* To avoid filling the disk space, a few knobs are provided:
* - The pruning interval limit the frequency at which the garbage collector
* will try to scan the cache directory to prune it from expired entries.
* Setting to -1 disable the pruning (default).
* - The pruning expiration time indicates to the garbage collector how old an
* entry needs to be to be removed.
* - Finally, the garbage collector can be instructed to prune the cache till
* the occupied space goes below a threshold.
* @{
*/
/**
* Sets the path to a directory to use as a cache storage for incremental build.
* Setting this activates caching.
*
* \since LTO_API_VERSION=18
*/
extern void thinlto_codegen_set_cache_dir(thinlto_code_gen_t cg,
const char *cache_dir);
/**
* Sets the cache pruning interval (in seconds). A negative value disable the
* pruning. An unspecified default value will be applied, and a value of 0 will
* be ignored.
*
* \since LTO_API_VERSION=18
*/
extern void thinlto_codegen_set_cache_pruning_interval(thinlto_code_gen_t cg,
int interval);
/**
* Sets the maximum cache size that can be persistent across build, in terms of
* percentage of the available space on the the disk. Set to 100 to indicate
* no limit, 50 to indicate that the cache size will not be left over half the
* available space. A value over 100 will be reduced to 100, a value of 0 will
* be ignored. An unspecified default value will be applied.
*
* The formula looks like:
* AvailableSpace = FreeSpace + ExistingCacheSize
* NewCacheSize = AvailableSpace * P/100
*
* \since LTO_API_VERSION=18
*/
extern void thinlto_codegen_set_final_cache_size_relative_to_available_space(
thinlto_code_gen_t cg, unsigned percentage);
/**
* Sets the expiration (in seconds) for an entry in the cache. An unspecified
* default value will be applied. A value of 0 will be ignored.
*
* \since LTO_API_VERSION=18
*/
extern void thinlto_codegen_set_cache_entry_expiration(thinlto_code_gen_t cg,
unsigned expiration);
/**
* @}
*/
/**
* Sets the path to a directory to use as a storage for temporary bitcode files.
* The intention is to make the bitcode files available for debugging at various
@ -820,12 +751,77 @@ extern void thinlto_codegen_add_cross_referenced_symbol(thinlto_code_gen_t cg,
const char *name,
int length);
/**
* @} // endgoup LLVMCTLTO
* @defgroup LLVMCTLTO_CACHING ThinLTO Cache Control
* @ingroup LLVMCTLTO
*
* These entry points control the ThinLTO cache. The cache is intended to
* support incremental build, and thus needs to be persistent accross build.
* The client enabled the cache by supplying a path to an existing directory.
* The code generator will use this to store objects files that may be reused
* during a subsequent build.
* To avoid filling the disk space, a few knobs are provided:
* - The pruning interval limit the frequency at which the garbage collector
* will try to scan the cache directory to prune it from expired entries.
* Setting to -1 disable the pruning (default).
* - The pruning expiration time indicates to the garbage collector how old an
* entry needs to be to be removed.
* - Finally, the garbage collector can be instructed to prune the cache till
* the occupied space goes below a threshold.
* @{
*/
/**
* Sets the path to a directory to use as a cache storage for incremental build.
* Setting this activates caching.
*
* \since LTO_API_VERSION=18
*/
extern void thinlto_codegen_set_cache_dir(thinlto_code_gen_t cg,
const char *cache_dir);
/**
* Sets the cache pruning interval (in seconds). A negative value disable the
* pruning. An unspecified default value will be applied, and a value of 0 will
* be ignored.
*
* \since LTO_API_VERSION=18
*/
extern void thinlto_codegen_set_cache_pruning_interval(thinlto_code_gen_t cg,
int interval);
/**
* Sets the maximum cache size that can be persistent across build, in terms of
* percentage of the available space on the the disk. Set to 100 to indicate
* no limit, 50 to indicate that the cache size will not be left over half the
* available space. A value over 100 will be reduced to 100, a value of 0 will
* be ignored. An unspecified default value will be applied.
*
* The formula looks like:
* AvailableSpace = FreeSpace + ExistingCacheSize
* NewCacheSize = AvailableSpace * P/100
*
* \since LTO_API_VERSION=18
*/
extern void thinlto_codegen_set_final_cache_size_relative_to_available_space(
thinlto_code_gen_t cg, unsigned percentage);
/**
* Sets the expiration (in seconds) for an entry in the cache. An unspecified
* default value will be applied. A value of 0 will be ignored.
*
* \since LTO_API_VERSION=18
*/
extern void thinlto_codegen_set_cache_entry_expiration(thinlto_code_gen_t cg,
unsigned expiration);
/**
* @} // endgroup LLVMCTLTO_CACHING
*/
#ifdef __cplusplus
}
#endif
/**
* @}
*/
#endif /* LLVM_C_LTO_H */

View File

@ -18,9 +18,19 @@
#define LLVM_ADT_APFLOAT_H
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/ErrorHandling.h"
#include <memory>
#define APFLOAT_DISPATCH_ON_SEMANTICS(METHOD_CALL) \
do { \
if (usesLayout<IEEEFloat>(getSemantics())) \
return U.IEEE.METHOD_CALL; \
if (usesLayout<DoubleAPFloat>(getSemantics())) \
return U.Double.METHOD_CALL; \
llvm_unreachable("Unexpected semantics"); \
} while (false)
namespace llvm {
struct fltSemantics;
@ -42,7 +52,7 @@ enum lostFraction { // Example of truncated bits:
lfMoreThanHalf // 1xxxxx x's not all zero
};
/// \brief A self-contained host- and target-independent arbitrary-precision
/// A self-contained host- and target-independent arbitrary-precision
/// floating-point software implementation.
///
/// APFloat uses bignum integer arithmetic as provided by static functions in
@ -130,22 +140,25 @@ enum lostFraction { // Example of truncated bits:
// implementation classes. This struct should not define any non-static data
// members.
struct APFloatBase {
// TODO remove this and use APInt typedef directly.
typedef APInt::WordType integerPart;
/// A signed type to represent a floating point numbers unbiased exponent.
typedef signed short ExponentType;
/// \name Floating Point Semantics.
/// @{
static const fltSemantics &IEEEhalf();
static const fltSemantics &IEEEsingle();
static const fltSemantics &IEEEdouble();
static const fltSemantics &IEEEquad();
static const fltSemantics &PPCDoubleDouble();
static const fltSemantics &x87DoubleExtended();
static const fltSemantics &IEEEhalf() LLVM_READNONE;
static const fltSemantics &IEEEsingle() LLVM_READNONE;
static const fltSemantics &IEEEdouble() LLVM_READNONE;
static const fltSemantics &IEEEquad() LLVM_READNONE;
static const fltSemantics &PPCDoubleDouble() LLVM_READNONE;
static const fltSemantics &x87DoubleExtended() LLVM_READNONE;
/// A Pseudo fltsemantic used to construct APFloats that cannot conflict with
/// anything real.
static const fltSemantics &Bogus();
static const fltSemantics &Bogus() LLVM_READNONE;
/// @}
@ -191,7 +204,7 @@ struct APFloatBase {
uninitialized
};
/// \brief Enumeration of \c ilogb error results.
/// Enumeration of \c ilogb error results.
enum IlogbErrorKinds {
IEK_Zero = INT_MIN + 1,
IEK_NaN = INT_MIN,
@ -227,7 +240,7 @@ class IEEEFloat final : public APFloatBase {
/// @}
/// \brief Returns whether this instance allocated memory.
/// Returns whether this instance allocated memory.
bool needsCleanup() const { return partCount() > 1; }
/// \name Convenience "constructors"
@ -235,10 +248,6 @@ class IEEEFloat final : public APFloatBase {
/// @}
/// Used to insert APFloat objects, or objects that contain APFloat objects,
/// into FoldingSets.
void Profile(FoldingSetNodeID &NID) const;
/// \name Arithmetic
/// @{
@ -255,53 +264,12 @@ class IEEEFloat final : public APFloatBase {
/// IEEE-754R 5.3.1: nextUp/nextDown.
opStatus next(bool nextDown);
/// \brief Operator+ overload which provides the default
/// \c nmNearestTiesToEven rounding mode and *no* error checking.
IEEEFloat operator+(const IEEEFloat &RHS) const {
IEEEFloat Result = *this;
Result.add(RHS, rmNearestTiesToEven);
return Result;
}
/// \brief Operator- overload which provides the default
/// \c nmNearestTiesToEven rounding mode and *no* error checking.
IEEEFloat operator-(const IEEEFloat &RHS) const {
IEEEFloat Result = *this;
Result.subtract(RHS, rmNearestTiesToEven);
return Result;
}
/// \brief Operator* overload which provides the default
/// \c nmNearestTiesToEven rounding mode and *no* error checking.
IEEEFloat operator*(const IEEEFloat &RHS) const {
IEEEFloat Result = *this;
Result.multiply(RHS, rmNearestTiesToEven);
return Result;
}
/// \brief Operator/ overload which provides the default
/// \c nmNearestTiesToEven rounding mode and *no* error checking.
IEEEFloat operator/(const IEEEFloat &RHS) const {
IEEEFloat Result = *this;
Result.divide(RHS, rmNearestTiesToEven);
return Result;
}
/// @}
/// \name Sign operations.
/// @{
void changeSign();
void clearSign();
void copySign(const IEEEFloat &);
/// \brief A static helper to produce a copy of an APFloat value with its sign
/// copied from some other APFloat.
static IEEEFloat copySign(IEEEFloat Value, const IEEEFloat &Sign) {
Value.copySign(Sign);
return Value;
}
/// @}
@ -309,9 +277,8 @@ class IEEEFloat final : public APFloatBase {
/// @{
opStatus convert(const fltSemantics &, roundingMode, bool *);
opStatus convertToInteger(integerPart *, unsigned int, bool, roundingMode,
bool *) const;
opStatus convertToInteger(APSInt &, roundingMode, bool *) const;
opStatus convertToInteger(MutableArrayRef<integerPart>, unsigned int, bool,
roundingMode, bool *) const;
opStatus convertFromAPInt(const APInt &, bool, roundingMode);
opStatus convertFromSignExtendedInteger(const integerPart *, unsigned int,
bool, roundingMode);
@ -398,7 +365,7 @@ class IEEEFloat final : public APFloatBase {
/// Returns true if and only if the number has the largest possible finite
/// magnitude in the current semantics.
bool isLargest() const;
/// Returns true if and only if the number is an exact integer.
bool isInteger() const;
@ -407,7 +374,7 @@ class IEEEFloat final : public APFloatBase {
IEEEFloat &operator=(const IEEEFloat &);
IEEEFloat &operator=(IEEEFloat &&);
/// \brief Overload to compute a hash code for an APFloat value.
/// Overload to compute a hash code for an APFloat value.
///
/// Note that the use of hash codes for floating point values is in general
/// frought with peril. Equality is hard to define for these values. For
@ -443,9 +410,9 @@ class IEEEFloat final : public APFloatBase {
/// If this value has an exact multiplicative inverse, store it in inv and
/// return true.
bool getExactInverse(IEEEFloat *inv) const;
bool getExactInverse(APFloat *inv) const;
/// \brief Returns the exponent of the internal representation of the APFloat.
/// Returns the exponent of the internal representation of the APFloat.
///
/// Because the radix of APFloat is 2, this is equivalent to floor(log2(x)).
/// For special APFloat values, this returns special error codes:
@ -456,7 +423,7 @@ class IEEEFloat final : public APFloatBase {
///
friend int ilogb(const IEEEFloat &Arg);
/// \brief Returns: X * 2^Exp for integral exponents.
/// Returns: X * 2^Exp for integral exponents.
friend IEEEFloat scalbn(IEEEFloat X, int Exp, roundingMode);
friend IEEEFloat frexp(const IEEEFloat &X, int &Exp, roundingMode);
@ -532,8 +499,9 @@ class IEEEFloat final : public APFloatBase {
opStatus addOrSubtract(const IEEEFloat &, roundingMode, bool subtract);
opStatus handleOverflow(roundingMode);
bool roundAwayFromZero(roundingMode, lostFraction, unsigned int) const;
opStatus convertToSignExtendedInteger(integerPart *, unsigned int, bool,
roundingMode, bool *) const;
opStatus convertToSignExtendedInteger(MutableArrayRef<integerPart>,
unsigned int, bool, roundingMode,
bool *) const;
opStatus convertFromUnsignedParts(const integerPart *, unsigned int,
roundingMode);
opStatus convertFromHexadecimalString(StringRef, roundingMode);
@ -636,6 +604,13 @@ class DoubleAPFloat final : public APFloatBase {
opStatus add(const DoubleAPFloat &RHS, roundingMode RM);
opStatus subtract(const DoubleAPFloat &RHS, roundingMode RM);
opStatus multiply(const DoubleAPFloat &RHS, roundingMode RM);
opStatus divide(const DoubleAPFloat &RHS, roundingMode RM);
opStatus remainder(const DoubleAPFloat &RHS);
opStatus mod(const DoubleAPFloat &RHS);
opStatus fusedMultiplyAdd(const DoubleAPFloat &Multiplicand,
const DoubleAPFloat &Addend, roundingMode RM);
opStatus roundToIntegral(roundingMode RM);
void changeSign();
cmpResult compareAbsoluteValue(const DoubleAPFloat &RHS) const;
@ -643,9 +618,49 @@ class DoubleAPFloat final : public APFloatBase {
bool isNegative() const;
void makeInf(bool Neg);
void makeZero(bool Neg);
void makeLargest(bool Neg);
void makeSmallest(bool Neg);
void makeSmallestNormalized(bool Neg);
void makeNaN(bool SNaN, bool Neg, const APInt *fill);
cmpResult compare(const DoubleAPFloat &RHS) const;
bool bitwiseIsEqual(const DoubleAPFloat &RHS) const;
APInt bitcastToAPInt() const;
opStatus convertFromString(StringRef, roundingMode);
opStatus next(bool nextDown);
opStatus convertToInteger(MutableArrayRef<integerPart> Input,
unsigned int Width, bool IsSigned, roundingMode RM,
bool *IsExact) const;
opStatus convertFromAPInt(const APInt &Input, bool IsSigned, roundingMode RM);
opStatus convertFromSignExtendedInteger(const integerPart *Input,
unsigned int InputSize, bool IsSigned,
roundingMode RM);
opStatus convertFromZeroExtendedInteger(const integerPart *Input,
unsigned int InputSize, bool IsSigned,
roundingMode RM);
unsigned int convertToHexString(char *DST, unsigned int HexDigits,
bool UpperCase, roundingMode RM) const;
bool isDenormal() const;
bool isSmallest() const;
bool isLargest() const;
bool isInteger() const;
void toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision,
unsigned FormatMaxPadding) const;
bool getExactInverse(APFloat *inv) const;
friend int ilogb(const DoubleAPFloat &Arg);
friend DoubleAPFloat scalbn(DoubleAPFloat X, int Exp, roundingMode);
friend DoubleAPFloat frexp(const DoubleAPFloat &X, int &Exp, roundingMode);
friend hash_code hash_value(const DoubleAPFloat &Arg);
};
hash_code hash_value(const DoubleAPFloat &Arg);
} // End detail namespace
// This is a interface class that is currently forwarding functionalities from
@ -770,26 +785,24 @@ class APFloat : public APFloatBase {
llvm_unreachable("Unexpected semantics");
}
void makeZero(bool Neg) { getIEEE().makeZero(Neg); }
void makeZero(bool Neg) { APFLOAT_DISPATCH_ON_SEMANTICS(makeZero(Neg)); }
void makeInf(bool Neg) {
if (usesLayout<IEEEFloat>(*U.semantics))
return U.IEEE.makeInf(Neg);
if (usesLayout<DoubleAPFloat>(*U.semantics))
return U.Double.makeInf(Neg);
llvm_unreachable("Unexpected semantics");
}
void makeInf(bool Neg) { APFLOAT_DISPATCH_ON_SEMANTICS(makeInf(Neg)); }
void makeNaN(bool SNaN, bool Neg, const APInt *fill) {
getIEEE().makeNaN(SNaN, Neg, fill);
APFLOAT_DISPATCH_ON_SEMANTICS(makeNaN(SNaN, Neg, fill));
}
void makeLargest(bool Neg) { getIEEE().makeLargest(Neg); }
void makeLargest(bool Neg) {
APFLOAT_DISPATCH_ON_SEMANTICS(makeLargest(Neg));
}
void makeSmallest(bool Neg) { getIEEE().makeSmallest(Neg); }
void makeSmallest(bool Neg) {
APFLOAT_DISPATCH_ON_SEMANTICS(makeSmallest(Neg));
}
void makeSmallestNormalized(bool Neg) {
getIEEE().makeSmallestNormalized(Neg);
APFLOAT_DISPATCH_ON_SEMANTICS(makeSmallestNormalized(Neg));
}
// FIXME: This is due to clang 3.3 (or older version) always checks for the
@ -804,7 +817,8 @@ class APFloat : public APFloatBase {
: U(std::move(F), S) {}
cmpResult compareAbsoluteValue(const APFloat &RHS) const {
assert(&getSemantics() == &RHS.getSemantics());
assert(&getSemantics() == &RHS.getSemantics() &&
"Should only compare APFloats with the same semantics");
if (usesLayout<IEEEFloat>(getSemantics()))
return U.IEEE.compareAbsoluteValue(RHS.U.IEEE);
if (usesLayout<DoubleAPFloat>(getSemantics()))
@ -827,13 +841,7 @@ class APFloat : public APFloatBase {
~APFloat() = default;
bool needsCleanup() const {
if (usesLayout<IEEEFloat>(getSemantics()))
return U.IEEE.needsCleanup();
if (usesLayout<DoubleAPFloat>(getSemantics()))
return U.Double.needsCleanup();
llvm_unreachable("Unexpected semantics");
}
bool needsCleanup() const { APFLOAT_DISPATCH_ON_SEMANTICS(needsCleanup()); }
/// Factory for Positive and Negative Zero.
///
@ -920,9 +928,13 @@ class APFloat : public APFloatBase {
/// \param isIEEE - If 128 bit number, select between PPC and IEEE
static APFloat getAllOnesValue(unsigned BitWidth, bool isIEEE = false);
void Profile(FoldingSetNodeID &NID) const { getIEEE().Profile(NID); }
/// Used to insert APFloat objects, or objects that contain APFloat objects,
/// into FoldingSets.
void Profile(FoldingSetNodeID &NID) const;
opStatus add(const APFloat &RHS, roundingMode RM) {
assert(&getSemantics() == &RHS.getSemantics() &&
"Should only call on two APFloats with the same semantics");
if (usesLayout<IEEEFloat>(getSemantics()))
return U.IEEE.add(RHS.U.IEEE, RM);
if (usesLayout<DoubleAPFloat>(getSemantics()))
@ -930,6 +942,8 @@ class APFloat : public APFloatBase {
llvm_unreachable("Unexpected semantics");
}
opStatus subtract(const APFloat &RHS, roundingMode RM) {
assert(&getSemantics() == &RHS.getSemantics() &&
"Should only call on two APFloats with the same semantics");
if (usesLayout<IEEEFloat>(getSemantics()))
return U.IEEE.subtract(RHS.U.IEEE, RM);
if (usesLayout<DoubleAPFloat>(getSemantics()))
@ -937,95 +951,172 @@ class APFloat : public APFloatBase {
llvm_unreachable("Unexpected semantics");
}
opStatus multiply(const APFloat &RHS, roundingMode RM) {
return getIEEE().multiply(RHS.getIEEE(), RM);
assert(&getSemantics() == &RHS.getSemantics() &&
"Should only call on two APFloats with the same semantics");
if (usesLayout<IEEEFloat>(getSemantics()))
return U.IEEE.multiply(RHS.U.IEEE, RM);
if (usesLayout<DoubleAPFloat>(getSemantics()))
return U.Double.multiply(RHS.U.Double, RM);
llvm_unreachable("Unexpected semantics");
}
opStatus divide(const APFloat &RHS, roundingMode RM) {
return getIEEE().divide(RHS.getIEEE(), RM);
assert(&getSemantics() == &RHS.getSemantics() &&
"Should only call on two APFloats with the same semantics");
if (usesLayout<IEEEFloat>(getSemantics()))
return U.IEEE.divide(RHS.U.IEEE, RM);
if (usesLayout<DoubleAPFloat>(getSemantics()))
return U.Double.divide(RHS.U.Double, RM);
llvm_unreachable("Unexpected semantics");
}
opStatus remainder(const APFloat &RHS) {
return getIEEE().remainder(RHS.getIEEE());
assert(&getSemantics() == &RHS.getSemantics() &&
"Should only call on two APFloats with the same semantics");
if (usesLayout<IEEEFloat>(getSemantics()))
return U.IEEE.remainder(RHS.U.IEEE);
if (usesLayout<DoubleAPFloat>(getSemantics()))
return U.Double.remainder(RHS.U.Double);
llvm_unreachable("Unexpected semantics");
}
opStatus mod(const APFloat &RHS) {
assert(&getSemantics() == &RHS.getSemantics() &&
"Should only call on two APFloats with the same semantics");
if (usesLayout<IEEEFloat>(getSemantics()))
return U.IEEE.mod(RHS.U.IEEE);
if (usesLayout<DoubleAPFloat>(getSemantics()))
return U.Double.mod(RHS.U.Double);
llvm_unreachable("Unexpected semantics");
}
opStatus mod(const APFloat &RHS) { return getIEEE().mod(RHS.getIEEE()); }
opStatus fusedMultiplyAdd(const APFloat &Multiplicand, const APFloat &Addend,
roundingMode RM) {
return getIEEE().fusedMultiplyAdd(Multiplicand.getIEEE(), Addend.getIEEE(),
RM);
assert(&getSemantics() == &Multiplicand.getSemantics() &&
"Should only call on APFloats with the same semantics");
assert(&getSemantics() == &Addend.getSemantics() &&
"Should only call on APFloats with the same semantics");
if (usesLayout<IEEEFloat>(getSemantics()))
return U.IEEE.fusedMultiplyAdd(Multiplicand.U.IEEE, Addend.U.IEEE, RM);
if (usesLayout<DoubleAPFloat>(getSemantics()))
return U.Double.fusedMultiplyAdd(Multiplicand.U.Double, Addend.U.Double,
RM);
llvm_unreachable("Unexpected semantics");
}
opStatus roundToIntegral(roundingMode RM) {
return getIEEE().roundToIntegral(RM);
APFLOAT_DISPATCH_ON_SEMANTICS(roundToIntegral(RM));
}
opStatus next(bool nextDown) { return getIEEE().next(nextDown); }
// TODO: bool parameters are not readable and a source of bugs.
// Do something.
opStatus next(bool nextDown) {
APFLOAT_DISPATCH_ON_SEMANTICS(next(nextDown));
}
/// Add two APFloats, rounding ties to the nearest even.
/// No error checking.
APFloat operator+(const APFloat &RHS) const {
return APFloat(getIEEE() + RHS.getIEEE(), getSemantics());
APFloat Result(*this);
(void)Result.add(RHS, rmNearestTiesToEven);
return Result;
}
/// Subtract two APFloats, rounding ties to the nearest even.
/// No error checking.
APFloat operator-(const APFloat &RHS) const {
return APFloat(getIEEE() - RHS.getIEEE(), getSemantics());
APFloat Result(*this);
(void)Result.subtract(RHS, rmNearestTiesToEven);
return Result;
}
/// Multiply two APFloats, rounding ties to the nearest even.
/// No error checking.
APFloat operator*(const APFloat &RHS) const {
return APFloat(getIEEE() * RHS.getIEEE(), getSemantics());
APFloat Result(*this);
(void)Result.multiply(RHS, rmNearestTiesToEven);
return Result;
}
/// Divide the first APFloat by the second, rounding ties to the nearest even.
/// No error checking.
APFloat operator/(const APFloat &RHS) const {
return APFloat(getIEEE() / RHS.getIEEE(), getSemantics());
APFloat Result(*this);
(void)Result.divide(RHS, rmNearestTiesToEven);
return Result;
}
void changeSign() { getIEEE().changeSign(); }
void clearSign() { getIEEE().clearSign(); }
void copySign(const APFloat &RHS) { getIEEE().copySign(RHS.getIEEE()); }
void changeSign() { APFLOAT_DISPATCH_ON_SEMANTICS(changeSign()); }
void clearSign() {
if (isNegative())
changeSign();
}
void copySign(const APFloat &RHS) {
if (isNegative() != RHS.isNegative())
changeSign();
}
/// A static helper to produce a copy of an APFloat value with its sign
/// copied from some other APFloat.
static APFloat copySign(APFloat Value, const APFloat &Sign) {
return APFloat(IEEEFloat::copySign(Value.getIEEE(), Sign.getIEEE()),
Value.getSemantics());
Value.copySign(Sign);
return Value;
}
opStatus convert(const fltSemantics &ToSemantics, roundingMode RM,
bool *losesInfo);
opStatus convertToInteger(integerPart *Input, unsigned int Width,
bool IsSigned, roundingMode RM,
opStatus convertToInteger(MutableArrayRef<integerPart> Input,
unsigned int Width, bool IsSigned, roundingMode RM,
bool *IsExact) const {
return getIEEE().convertToInteger(Input, Width, IsSigned, RM, IsExact);
APFLOAT_DISPATCH_ON_SEMANTICS(
convertToInteger(Input, Width, IsSigned, RM, IsExact));
}
opStatus convertToInteger(APSInt &Result, roundingMode RM,
bool *IsExact) const {
return getIEEE().convertToInteger(Result, RM, IsExact);
}
bool *IsExact) const;
opStatus convertFromAPInt(const APInt &Input, bool IsSigned,
roundingMode RM) {
return getIEEE().convertFromAPInt(Input, IsSigned, RM);
APFLOAT_DISPATCH_ON_SEMANTICS(convertFromAPInt(Input, IsSigned, RM));
}
opStatus convertFromSignExtendedInteger(const integerPart *Input,
unsigned int InputSize, bool IsSigned,
roundingMode RM) {
return getIEEE().convertFromSignExtendedInteger(Input, InputSize, IsSigned,
RM);
APFLOAT_DISPATCH_ON_SEMANTICS(
convertFromSignExtendedInteger(Input, InputSize, IsSigned, RM));
}
opStatus convertFromZeroExtendedInteger(const integerPart *Input,
unsigned int InputSize, bool IsSigned,
roundingMode RM) {
return getIEEE().convertFromZeroExtendedInteger(Input, InputSize, IsSigned,
RM);
APFLOAT_DISPATCH_ON_SEMANTICS(
convertFromZeroExtendedInteger(Input, InputSize, IsSigned, RM));
}
opStatus convertFromString(StringRef, roundingMode);
APInt bitcastToAPInt() const { return getIEEE().bitcastToAPInt(); }
APInt bitcastToAPInt() const {
APFLOAT_DISPATCH_ON_SEMANTICS(bitcastToAPInt());
}
double convertToDouble() const { return getIEEE().convertToDouble(); }
float convertToFloat() const { return getIEEE().convertToFloat(); }
bool operator==(const APFloat &) const = delete;
cmpResult compare(const APFloat &RHS) const {
return getIEEE().compare(RHS.getIEEE());
assert(&getSemantics() == &RHS.getSemantics() &&
"Should only compare APFloats with the same semantics");
if (usesLayout<IEEEFloat>(getSemantics()))
return U.IEEE.compare(RHS.U.IEEE);
if (usesLayout<DoubleAPFloat>(getSemantics()))
return U.Double.compare(RHS.U.Double);
llvm_unreachable("Unexpected semantics");
}
bool bitwiseIsEqual(const APFloat &RHS) const {
return getIEEE().bitwiseIsEqual(RHS.getIEEE());
if (&getSemantics() != &RHS.getSemantics())
return false;
if (usesLayout<IEEEFloat>(getSemantics()))
return U.IEEE.bitwiseIsEqual(RHS.U.IEEE);
if (usesLayout<DoubleAPFloat>(getSemantics()))
return U.Double.bitwiseIsEqual(RHS.U.Double);
llvm_unreachable("Unexpected semantics");
}
unsigned int convertToHexString(char *DST, unsigned int HexDigits,
bool UpperCase, roundingMode RM) const {
return getIEEE().convertToHexString(DST, HexDigits, UpperCase, RM);
APFLOAT_DISPATCH_ON_SEMANTICS(
convertToHexString(DST, HexDigits, UpperCase, RM));
}
bool isZero() const { return getCategory() == fcZero; }
@ -1033,7 +1124,7 @@ class APFloat : public APFloatBase {
bool isNaN() const { return getCategory() == fcNaN; }
bool isNegative() const { return getIEEE().isNegative(); }
bool isDenormal() const { return getIEEE().isDenormal(); }
bool isDenormal() const { APFLOAT_DISPATCH_ON_SEMANTICS(isDenormal()); }
bool isSignaling() const { return getIEEE().isSignaling(); }
bool isNormal() const { return !isDenormal() && isFiniteNonZero(); }
@ -1045,30 +1136,24 @@ class APFloat : public APFloatBase {
bool isFiniteNonZero() const { return isFinite() && !isZero(); }
bool isPosZero() const { return isZero() && !isNegative(); }
bool isNegZero() const { return isZero() && isNegative(); }
bool isSmallest() const { return getIEEE().isSmallest(); }
bool isLargest() const { return getIEEE().isLargest(); }
bool isInteger() const { return getIEEE().isInteger(); }
bool isSmallest() const { APFLOAT_DISPATCH_ON_SEMANTICS(isSmallest()); }
bool isLargest() const { APFLOAT_DISPATCH_ON_SEMANTICS(isLargest()); }
bool isInteger() const { APFLOAT_DISPATCH_ON_SEMANTICS(isInteger()); }
APFloat &operator=(const APFloat &RHS) = default;
APFloat &operator=(APFloat &&RHS) = default;
void toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision = 0,
unsigned FormatMaxPadding = 3) const {
return getIEEE().toString(Str, FormatPrecision, FormatMaxPadding);
APFLOAT_DISPATCH_ON_SEMANTICS(
toString(Str, FormatPrecision, FormatMaxPadding));
}
void print(raw_ostream &) const;
void dump() const;
bool getExactInverse(APFloat *inv) const {
return getIEEE().getExactInverse(inv ? &inv->getIEEE() : nullptr);
}
// This is for internal test only.
// TODO: Remove it after the PPCDoubleDouble transition.
const APFloat &getSecondFloat() const {
assert(&getSemantics() == &PPCDoubleDouble());
return U.Double.getSecond();
APFLOAT_DISPATCH_ON_SEMANTICS(getExactInverse(inv));
}
friend hash_code hash_value(const APFloat &Arg);
@ -1085,22 +1170,36 @@ class APFloat : public APFloatBase {
/// xlC compiler.
hash_code hash_value(const APFloat &Arg);
inline APFloat scalbn(APFloat X, int Exp, APFloat::roundingMode RM) {
return APFloat(scalbn(X.getIEEE(), Exp, RM), X.getSemantics());
if (APFloat::usesLayout<detail::IEEEFloat>(X.getSemantics()))
return APFloat(scalbn(X.U.IEEE, Exp, RM), X.getSemantics());
if (APFloat::usesLayout<detail::DoubleAPFloat>(X.getSemantics()))
return APFloat(scalbn(X.U.Double, Exp, RM), X.getSemantics());
llvm_unreachable("Unexpected semantics");
}
/// \brief Equivalent of C standard library function.
/// Equivalent of C standard library function.
///
/// While the C standard says Exp is an unspecified value for infinity and nan,
/// this returns INT_MAX for infinities, and INT_MIN for NaNs.
inline APFloat frexp(const APFloat &X, int &Exp, APFloat::roundingMode RM) {
return APFloat(frexp(X.getIEEE(), Exp, RM), X.getSemantics());
if (APFloat::usesLayout<detail::IEEEFloat>(X.getSemantics()))
return APFloat(frexp(X.U.IEEE, Exp, RM), X.getSemantics());
if (APFloat::usesLayout<detail::DoubleAPFloat>(X.getSemantics()))
return APFloat(frexp(X.U.Double, Exp, RM), X.getSemantics());
llvm_unreachable("Unexpected semantics");
}
/// \brief Returns the absolute value of the argument.
/// Returns the absolute value of the argument.
inline APFloat abs(APFloat X) {
X.clearSign();
return X;
}
/// \brief Returns the negated value of the argument.
inline APFloat neg(APFloat X) {
X.changeSign();
return X;
}
/// Implements IEEE minNum semantics. Returns the smaller of the 2 arguments if
/// both are not NaN. If either argument is a NaN, returns the other argument.
LLVM_READONLY
@ -1125,4 +1224,5 @@ inline APFloat maxnum(const APFloat &A, const APFloat &B) {
} // namespace llvm
#undef APFLOAT_DISPATCH_ON_SEMANTICS
#endif // LLVM_ADT_APFLOAT_H

View File

@ -32,14 +32,6 @@ class raw_ostream;
template <typename T> class SmallVectorImpl;
template <typename T> class ArrayRef;
// An unsigned host type used as a single part of a multi-part
// bignum.
typedef uint64_t integerPart;
const unsigned int host_char_bit = 8;
const unsigned int integerPartWidth =
host_char_bit * static_cast<unsigned int>(sizeof(integerPart));
class APInt;
inline APInt operator-(APInt);
@ -75,8 +67,18 @@ inline APInt operator-(APInt);
/// uses in its IR. This simplifies its use for LLVM.
///
class LLVM_NODISCARD APInt {
unsigned BitWidth; ///< The number of bits in this APInt.
public:
typedef uint64_t WordType;
/// This enum is used to hold the constants we needed for APInt.
enum : unsigned {
/// Byte size of a word.
APINT_WORD_SIZE = sizeof(WordType),
/// Bits in a word.
APINT_BITS_PER_WORD = APINT_WORD_SIZE * CHAR_BIT
};
private:
/// This union is used to store the integer value. When the
/// integer bit-width <= 64, it uses VAL, otherwise it uses pVal.
union {
@ -84,14 +86,7 @@ class LLVM_NODISCARD APInt {
uint64_t *pVal; ///< Used to store the >64 bits integer value.
};
/// This enum is used to hold the constants we needed for APInt.
enum {
/// Bits in a word
APINT_BITS_PER_WORD =
static_cast<unsigned int>(sizeof(uint64_t)) * CHAR_BIT,
/// Byte size of a word
APINT_WORD_SIZE = static_cast<unsigned int>(sizeof(uint64_t))
};
unsigned BitWidth; ///< The number of bits in this APInt.
friend struct DenseMapAPIntKeyInfo;
@ -99,7 +94,7 @@ class LLVM_NODISCARD APInt {
///
/// This constructor is used only internally for speed of construction of
/// temporaries. It is unsafe for general use so it is not public.
APInt(uint64_t *val, unsigned bits) : BitWidth(bits), pVal(val) {}
APInt(uint64_t *val, unsigned bits) : pVal(val), BitWidth(bits) {}
/// \brief Determine if this APInt just has one word to store value.
///
@ -147,7 +142,7 @@ class LLVM_NODISCARD APInt {
return *this;
// Mask out the high bits.
uint64_t mask = ~uint64_t(0ULL) >> (APINT_BITS_PER_WORD - wordBits);
uint64_t mask = UINT64_MAX >> (APINT_BITS_PER_WORD - wordBits);
if (isSingleWord())
VAL &= mask;
else
@ -196,32 +191,38 @@ class LLVM_NODISCARD APInt {
/// out-of-line slow case for shl
APInt shlSlowCase(unsigned shiftAmt) const;
/// out-of-line slow case for operator&
APInt AndSlowCase(const APInt &RHS) const;
/// out-of-line slow case for operator|
APInt OrSlowCase(const APInt &RHS) const;
/// out-of-line slow case for operator^
APInt XorSlowCase(const APInt &RHS) const;
/// out-of-line slow case for operator=
APInt &AssignSlowCase(const APInt &RHS);
/// out-of-line slow case for operator==
bool EqualSlowCase(const APInt &RHS) const;
bool EqualSlowCase(const APInt &RHS) const LLVM_READONLY;
/// out-of-line slow case for operator==
bool EqualSlowCase(uint64_t Val) const;
bool EqualSlowCase(uint64_t Val) const LLVM_READONLY;
/// out-of-line slow case for countLeadingZeros
unsigned countLeadingZerosSlowCase() const;
unsigned countLeadingZerosSlowCase() const LLVM_READONLY;
/// out-of-line slow case for countTrailingOnes
unsigned countTrailingOnesSlowCase() const;
unsigned countTrailingOnesSlowCase() const LLVM_READONLY;
/// out-of-line slow case for countPopulation
unsigned countPopulationSlowCase() const;
unsigned countPopulationSlowCase() const LLVM_READONLY;
/// out-of-line slow case for setBits.
void setBitsSlowCase(unsigned loBit, unsigned hiBit);
/// out-of-line slow case for flipAllBits.
void flipAllBitsSlowCase();
/// out-of-line slow case for operator&=.
APInt& AndAssignSlowCase(const APInt& RHS);
/// out-of-line slow case for operator|=.
APInt& OrAssignSlowCase(const APInt& RHS);
/// out-of-line slow case for operator^=.
APInt& XorAssignSlowCase(const APInt& RHS);
public:
/// \name Constructors
@ -238,13 +239,14 @@ class LLVM_NODISCARD APInt {
/// \param val the initial value of the APInt
/// \param isSigned how to treat signedness of val
APInt(unsigned numBits, uint64_t val, bool isSigned = false)
: BitWidth(numBits), VAL(0) {
: BitWidth(numBits) {
assert(BitWidth && "bitwidth too small");
if (isSingleWord())
if (isSingleWord()) {
VAL = val;
else
clearUnusedBits();
} else {
initSlowCase(val, isSigned);
clearUnusedBits();
}
}
/// \brief Construct an APInt of numBits width, initialized as bigVal[].
@ -280,7 +282,7 @@ class LLVM_NODISCARD APInt {
/// Simply makes *this a copy of that.
/// @brief Copy Constructor.
APInt(const APInt &that) : BitWidth(that.BitWidth), VAL(0) {
APInt(const APInt &that) : BitWidth(that.BitWidth) {
if (isSingleWord())
VAL = that.VAL;
else
@ -288,7 +290,7 @@ class LLVM_NODISCARD APInt {
}
/// \brief Move Constructor.
APInt(APInt &&that) : BitWidth(that.BitWidth), VAL(that.VAL) {
APInt(APInt &&that) : VAL(that.VAL), BitWidth(that.BitWidth) {
that.BitWidth = 0;
}
@ -303,7 +305,7 @@ class LLVM_NODISCARD APInt {
///
/// This is useful for object deserialization (pair this with the static
/// method Read).
explicit APInt() : BitWidth(1), VAL(0) {}
explicit APInt() : VAL(0), BitWidth(1) {}
/// \brief Returns whether this instance allocated memory.
bool needsCleanup() const { return !isSingleWord(); }
@ -341,7 +343,7 @@ class LLVM_NODISCARD APInt {
/// This checks to see if the value has all bits of the APInt are set or not.
bool isAllOnesValue() const {
if (isSingleWord())
return VAL == ~integerPart(0) >> (APINT_BITS_PER_WORD - BitWidth);
return VAL == UINT64_MAX >> (APINT_BITS_PER_WORD - BitWidth);
return countPopulationSlowCase() == BitWidth;
}
@ -406,7 +408,7 @@ class LLVM_NODISCARD APInt {
/// If this value is smaller than the specified limit, return it, otherwise
/// return the limit value. This causes the value to saturate to the limit.
uint64_t getLimitedValue(uint64_t Limit = ~0ULL) const {
uint64_t getLimitedValue(uint64_t Limit = UINT64_MAX) const {
return (getActiveBits() > 64 || getZExtValue() > Limit) ? Limit
: getZExtValue();
}
@ -418,6 +420,36 @@ class LLVM_NODISCARD APInt {
/// width without remainder.
bool isSplat(unsigned SplatSizeInBits) const;
/// \returns true if this APInt value is a sequence of \param numBits ones
/// starting at the least significant bit with the remainder zero.
bool isMask(unsigned numBits) const {
assert(numBits != 0 && "numBits must be non-zero");
assert(numBits <= BitWidth && "numBits out of range");
if (isSingleWord())
return VAL == (UINT64_MAX >> (APINT_BITS_PER_WORD - numBits));
unsigned Ones = countTrailingOnes();
return (numBits == Ones) && ((Ones + countLeadingZeros()) == BitWidth);
}
/// \returns true if this APInt is a non-empty sequence of ones starting at
/// the least significant bit with the remainder zero.
/// Ex. isMask(0x0000FFFFU) == true.
bool isMask() const {
if (isSingleWord())
return isMask_64(VAL);
unsigned Ones = countTrailingOnes();
return (Ones > 0) && ((Ones + countLeadingZeros()) == BitWidth);
}
/// \brief Return true if this APInt value contains a sequence of ones with
/// the remainder zero.
bool isShiftedMask() const {
if (isSingleWord())
return isShiftedMask_64(VAL);
unsigned Ones = countPopulation();
return (Ones + countTrailingZeros() + countLeadingZeros()) == BitWidth;
}
/// @}
/// \name Value Generators
/// @{
@ -501,12 +533,26 @@ class LLVM_NODISCARD APInt {
///
/// \returns An APInt value with the requested bits set.
static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit) {
assert(hiBit <= numBits && "hiBit out of range");
assert(loBit < numBits && "loBit out of range");
if (hiBit < loBit)
return getLowBitsSet(numBits, hiBit) |
getHighBitsSet(numBits, numBits - loBit);
return getLowBitsSet(numBits, hiBit - loBit).shl(loBit);
APInt Res(numBits, 0);
Res.setBits(loBit, hiBit);
return Res;
}
/// \brief Get a value with upper bits starting at loBit set.
///
/// Constructs an APInt value that has a contiguous range of bits set. The
/// bits from loBit (inclusive) to numBits (exclusive) will be set. All other
/// bits will be zero. For example, with parameters(32, 12) you would get
/// 0xFFFFF000.
///
/// \param numBits the intended bit width of the result
/// \param loBit the index of the lowest bit to set.
///
/// \returns An APInt value with the requested bits set.
static APInt getBitsSetFrom(unsigned numBits, unsigned loBit) {
APInt Res(numBits, 0);
Res.setBitsFrom(loBit);
return Res;
}
/// \brief Get a value with high bits set
@ -516,15 +562,9 @@ class LLVM_NODISCARD APInt {
/// \param numBits the bitwidth of the result
/// \param hiBitsSet the number of high-order bits set in the result.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet) {
assert(hiBitsSet <= numBits && "Too many bits to set!");
// Handle a degenerate case, to avoid shifting by word size
if (hiBitsSet == 0)
return APInt(numBits, 0);
unsigned shiftAmt = numBits - hiBitsSet;
// For small values, return quickly
if (numBits <= APINT_BITS_PER_WORD)
return APInt(numBits, ~0ULL << shiftAmt);
return getAllOnesValue(numBits).shl(shiftAmt);
APInt Res(numBits, 0);
Res.setHighBits(hiBitsSet);
return Res;
}
/// \brief Get a value with low bits set
@ -534,16 +574,9 @@ class LLVM_NODISCARD APInt {
/// \param numBits the bitwidth of the result
/// \param loBitsSet the number of low-order bits set in the result.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet) {
assert(loBitsSet <= numBits && "Too many bits to set!");
// Handle a degenerate case, to avoid shifting by word size
if (loBitsSet == 0)
return APInt(numBits, 0);
if (loBitsSet == APINT_BITS_PER_WORD)
return APInt(numBits, UINT64_MAX);
// For small values, return quickly.
if (loBitsSet <= APINT_BITS_PER_WORD)
return APInt(numBits, UINT64_MAX >> (APINT_BITS_PER_WORD - loBitsSet));
return getAllOnesValue(numBits).lshr(numBits - loBitsSet);
APInt Res(numBits, 0);
Res.setLowBits(loBitsSet);
return Res;
}
/// \brief Return a value containing V broadcasted over NewLen bits.
@ -587,7 +620,9 @@ class LLVM_NODISCARD APInt {
/// \brief Postfix increment operator.
///
/// \returns a new APInt value representing *this incremented by one
/// Increments *this by 1.
///
/// \returns a new APInt value representing the original value of *this.
const APInt operator++(int) {
APInt API(*this);
++(*this);
@ -601,7 +636,9 @@ class LLVM_NODISCARD APInt {
/// \brief Postfix decrement operator.
///
/// \returns a new APInt representing *this decremented by one.
/// Decrements *this by 1.
///
/// \returns a new APInt value representing the original value of *this.
const APInt operator--(int) {
APInt API(*this);
--(*this);
@ -613,30 +650,13 @@ class LLVM_NODISCARD APInt {
/// \returns *this decremented by one.
APInt &operator--();
/// \brief Unary bitwise complement operator.
///
/// Performs a bitwise complement operation on this APInt.
///
/// \returns an APInt that is the bitwise complement of *this
APInt operator~() const {
APInt Result(*this);
Result.flipAllBits();
return Result;
}
/// \brief Logical negation operator.
///
/// Performs logical negation operation on this APInt.
///
/// \returns true if *this is zero, false otherwise.
bool operator!() const {
if (isSingleWord())
return !VAL;
for (unsigned i = 0; i != getNumWords(); ++i)
if (pVal[i])
return false;
return true;
return *this == 0;
}
/// @}
@ -688,7 +708,16 @@ class LLVM_NODISCARD APInt {
/// than 64, the value is zero filled in the unspecified high order bits.
///
/// \returns *this after assignment of RHS value.
APInt &operator=(uint64_t RHS);
APInt &operator=(uint64_t RHS) {
if (isSingleWord()) {
VAL = RHS;
clearUnusedBits();
} else {
pVal[0] = RHS;
memset(pVal+1, 0, (getNumWords() - 1) * APINT_WORD_SIZE);
}
return *this;
}
/// \brief Bitwise AND assignment operator.
///
@ -696,7 +725,29 @@ class LLVM_NODISCARD APInt {
/// assigned to *this.
///
/// \returns *this after ANDing with RHS.
APInt &operator&=(const APInt &RHS);
APInt &operator&=(const APInt &RHS) {
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
if (isSingleWord()) {
VAL &= RHS.VAL;
return *this;
}
return AndAssignSlowCase(RHS);
}
/// \brief Bitwise AND assignment operator.
///
/// Performs a bitwise AND operation on this APInt and RHS. RHS is
/// logically zero-extended or truncated to match the bit-width of
/// the LHS.
APInt &operator&=(uint64_t RHS) {
if (isSingleWord()) {
VAL &= RHS;
return *this;
}
pVal[0] &= RHS;
memset(pVal+1, 0, (getNumWords() - 1) * APINT_WORD_SIZE);
return *this;
}
/// \brief Bitwise OR assignment operator.
///
@ -704,7 +755,14 @@ class LLVM_NODISCARD APInt {
/// assigned *this;
///
/// \returns *this after ORing with RHS.
APInt &operator|=(const APInt &RHS);
APInt &operator|=(const APInt &RHS) {
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
if (isSingleWord()) {
VAL |= RHS.VAL;
return *this;
}
return OrAssignSlowCase(RHS);
}
/// \brief Bitwise OR assignment operator.
///
@ -727,7 +785,29 @@ class LLVM_NODISCARD APInt {
/// assigned to *this.
///
/// \returns *this after XORing with RHS.
APInt &operator^=(const APInt &RHS);
APInt &operator^=(const APInt &RHS) {
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
if (isSingleWord()) {
VAL ^= RHS.VAL;
return *this;
}
return XorAssignSlowCase(RHS);
}
/// \brief Bitwise XOR assignment operator.
///
/// Performs a bitwise XOR operation on this APInt and RHS. RHS is
/// logically zero-extended or truncated to match the bit-width of
/// the LHS.
APInt &operator^=(uint64_t RHS) {
if (isSingleWord()) {
VAL ^= RHS;
clearUnusedBits();
} else {
pVal[0] ^= RHS;
}
return *this;
}
/// \brief Multiplication assignment operator.
///
@ -766,59 +846,6 @@ class LLVM_NODISCARD APInt {
/// \name Binary Operators
/// @{
/// \brief Bitwise AND operator.
///
/// Performs a bitwise AND operation on *this and RHS.
///
/// \returns An APInt value representing the bitwise AND of *this and RHS.
APInt operator&(const APInt &RHS) const {
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
if (isSingleWord())
return APInt(getBitWidth(), VAL & RHS.VAL);
return AndSlowCase(RHS);
}
APInt And(const APInt &RHS) const { return this->operator&(RHS); }
/// \brief Bitwise OR operator.
///
/// Performs a bitwise OR operation on *this and RHS.
///
/// \returns An APInt value representing the bitwise OR of *this and RHS.
APInt operator|(const APInt &RHS) const {
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
if (isSingleWord())
return APInt(getBitWidth(), VAL | RHS.VAL);
return OrSlowCase(RHS);
}
/// \brief Bitwise OR function.
///
/// Performs a bitwise or on *this and RHS. This is implemented by simply
/// calling operator|.
///
/// \returns An APInt value representing the bitwise OR of *this and RHS.
APInt Or(const APInt &RHS) const { return this->operator|(RHS); }
/// \brief Bitwise XOR operator.
///
/// Performs a bitwise XOR operation on *this and RHS.
///
/// \returns An APInt value representing the bitwise XOR of *this and RHS.
APInt operator^(const APInt &RHS) const {
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
if (isSingleWord())
return APInt(BitWidth, VAL ^ RHS.VAL);
return XorSlowCase(RHS);
}
/// \brief Bitwise XOR function.
///
/// Performs a bitwise XOR operation on *this and RHS. This is implemented
/// through the usage of operator^.
///
/// \returns An APInt value representing the bitwise XOR of *this and RHS.
APInt Xor(const APInt &RHS) const { return this->operator^(RHS); }
/// \brief Multiplication operator.
///
/// Multiplies this APInt by RHS and returns the result.
@ -842,7 +869,14 @@ class LLVM_NODISCARD APInt {
/// \brief Logical right-shift function.
///
/// Logical right-shift this APInt by shiftAmt.
APInt lshr(unsigned shiftAmt) const;
APInt lshr(unsigned shiftAmt) const {
APInt R(*this);
R.lshrInPlace(shiftAmt);
return R;
}
/// Logical right-shift this APInt by shiftAmt in place.
void lshrInPlace(unsigned shiftAmt);
/// \brief Left-shift function.
///
@ -1012,7 +1046,7 @@ class LLVM_NODISCARD APInt {
/// the validity of the less-than relationship.
///
/// \returns true if *this < RHS when both are considered unsigned.
bool ult(const APInt &RHS) const;
bool ult(const APInt &RHS) const LLVM_READONLY;
/// \brief Unsigned less than comparison
///
@ -1030,7 +1064,7 @@ class LLVM_NODISCARD APInt {
/// validity of the less-than relationship.
///
/// \returns true if *this < RHS when both are considered signed.
bool slt(const APInt &RHS) const;
bool slt(const APInt &RHS) const LLVM_READONLY;
/// \brief Signed less than comparison
///
@ -1144,7 +1178,11 @@ class LLVM_NODISCARD APInt {
/// This operation tests if there are any pairs of corresponding bits
/// between this APInt and RHS that are both set.
bool intersects(const APInt &RHS) const { return (*this & RHS) != 0; }
bool intersects(const APInt &RHS) const {
APInt temp(*this);
temp &= RHS;
return temp != 0;
}
/// @}
/// \name Resizing Operators
@ -1203,11 +1241,9 @@ class LLVM_NODISCARD APInt {
void setAllBits() {
if (isSingleWord())
VAL = UINT64_MAX;
else {
else
// Set all the bits in all the words.
for (unsigned i = 0; i < getNumWords(); ++i)
pVal[i] = UINT64_MAX;
}
memset(pVal, -1, getNumWords() * APINT_WORD_SIZE);
// Clear the unused ones
clearUnusedBits();
}
@ -1217,6 +1253,49 @@ class LLVM_NODISCARD APInt {
/// Set the given bit to 1 whose position is given as "bitPosition".
void setBit(unsigned bitPosition);
/// Set the sign bit to 1.
void setSignBit() {
setBit(BitWidth - 1);
}
/// Set the bits from loBit (inclusive) to hiBit (exclusive) to 1.
void setBits(unsigned loBit, unsigned hiBit) {
assert(hiBit <= BitWidth && "hiBit out of range");
assert(loBit <= BitWidth && "loBit out of range");
if (loBit == hiBit)
return;
if (loBit > hiBit) {
setLowBits(hiBit);
setHighBits(BitWidth - loBit);
return;
}
if (loBit < APINT_BITS_PER_WORD && hiBit <= APINT_BITS_PER_WORD) {
uint64_t mask = UINT64_MAX >> (APINT_BITS_PER_WORD - (hiBit - loBit));
mask <<= loBit;
if (isSingleWord())
VAL |= mask;
else
pVal[0] |= mask;
} else {
setBitsSlowCase(loBit, hiBit);
}
}
/// Set the top bits starting from loBit.
void setBitsFrom(unsigned loBit) {
return setBits(loBit, BitWidth);
}
/// Set the bottom loBits bits.
void setLowBits(unsigned loBits) {
return setBits(0, loBits);
}
/// Set the top hiBits bits.
void setHighBits(unsigned hiBits) {
return setBits(BitWidth - hiBits, BitWidth);
}
/// \brief Set every bit to 0.
void clearAllBits() {
if (isSingleWord())
@ -1232,13 +1311,12 @@ class LLVM_NODISCARD APInt {
/// \brief Toggle every bit to its opposite value.
void flipAllBits() {
if (isSingleWord())
if (isSingleWord()) {
VAL ^= UINT64_MAX;
else {
for (unsigned i = 0; i < getNumWords(); ++i)
pVal[i] ^= UINT64_MAX;
clearUnusedBits();
} else {
flipAllBitsSlowCase();
}
clearUnusedBits();
}
/// \brief Toggles a given bit to its opposite value.
@ -1247,6 +1325,12 @@ class LLVM_NODISCARD APInt {
/// as "bitPosition".
void flipBit(unsigned bitPosition);
/// Insert the bits from a smaller APInt starting at bitPosition.
void insertBits(const APInt &SubBits, unsigned bitPosition);
/// Return an APInt with the extracted bits [bitPosition,bitPosition+numBits).
APInt extractBits(unsigned numBits, unsigned bitPosition) const;
/// @}
/// \name Value Characterization Functions
/// @{
@ -1356,7 +1440,7 @@ class LLVM_NODISCARD APInt {
///
/// \returns 0 if the high order bit is not set, otherwise returns the number
/// of 1 bits from the most significant to the least
unsigned countLeadingOnes() const;
unsigned countLeadingOnes() const LLVM_READONLY;
/// Computes the number of leading bits of this APInt that are equal to its
/// sign bit.
@ -1372,7 +1456,7 @@ class LLVM_NODISCARD APInt {
///
/// \returns BitWidth if the value is zero, otherwise returns the number of
/// zeros from the least significant bit to the first one bit.
unsigned countTrailingZeros() const;
unsigned countTrailingZeros() const LLVM_READONLY;
/// \brief Count the number of trailing one bits.
///
@ -1589,46 +1673,50 @@ class LLVM_NODISCARD APInt {
/// Sets the least significant part of a bignum to the input value, and zeroes
/// out higher parts.
static void tcSet(integerPart *, integerPart, unsigned int);
static void tcSet(WordType *, WordType, unsigned);
/// Assign one bignum to another.
static void tcAssign(integerPart *, const integerPart *, unsigned int);
static void tcAssign(WordType *, const WordType *, unsigned);
/// Returns true if a bignum is zero, false otherwise.
static bool tcIsZero(const integerPart *, unsigned int);
static bool tcIsZero(const WordType *, unsigned);
/// Extract the given bit of a bignum; returns 0 or 1. Zero-based.
static int tcExtractBit(const integerPart *, unsigned int bit);
static int tcExtractBit(const WordType *, unsigned bit);
/// Copy the bit vector of width srcBITS from SRC, starting at bit srcLSB, to
/// DST, of dstCOUNT parts, such that the bit srcLSB becomes the least
/// significant bit of DST. All high bits above srcBITS in DST are
/// zero-filled.
static void tcExtract(integerPart *, unsigned int dstCount,
const integerPart *, unsigned int srcBits,
unsigned int srcLSB);
static void tcExtract(WordType *, unsigned dstCount,
const WordType *, unsigned srcBits,
unsigned srcLSB);
/// Set the given bit of a bignum. Zero-based.
static void tcSetBit(integerPart *, unsigned int bit);
static void tcSetBit(WordType *, unsigned bit);
/// Clear the given bit of a bignum. Zero-based.
static void tcClearBit(integerPart *, unsigned int bit);
static void tcClearBit(WordType *, unsigned bit);
/// Returns the bit number of the least or most significant set bit of a
/// number. If the input number has no bits set -1U is returned.
static unsigned int tcLSB(const integerPart *, unsigned int);
static unsigned int tcMSB(const integerPart *parts, unsigned int n);
static unsigned tcLSB(const WordType *, unsigned n);
static unsigned tcMSB(const WordType *parts, unsigned n);
/// Negate a bignum in-place.
static void tcNegate(integerPart *, unsigned int);
static void tcNegate(WordType *, unsigned);
/// DST += RHS + CARRY where CARRY is zero or one. Returns the carry flag.
static integerPart tcAdd(integerPart *, const integerPart *,
integerPart carry, unsigned);
static WordType tcAdd(WordType *, const WordType *,
WordType carry, unsigned);
/// DST += RHS. Returns the carry flag.
static WordType tcAddPart(WordType *, WordType, unsigned);
/// DST -= RHS + CARRY where CARRY is zero or one. Returns the carry flag.
static integerPart tcSubtract(integerPart *, const integerPart *,
integerPart carry, unsigned);
static WordType tcSubtract(WordType *, const WordType *,
WordType carry, unsigned);
/// DST -= RHS. Returns the carry flag.
static WordType tcSubtractPart(WordType *, WordType, unsigned);
/// DST += SRC * MULTIPLIER + PART if add is true
/// DST = SRC * MULTIPLIER + PART if add is false
@ -1640,23 +1728,23 @@ class LLVM_NODISCARD APInt {
/// Otherwise DST is filled with the least significant DSTPARTS parts of the
/// result, and if all of the omitted higher parts were zero return zero,
/// otherwise overflow occurred and return one.
static int tcMultiplyPart(integerPart *dst, const integerPart *src,
integerPart multiplier, integerPart carry,
unsigned int srcParts, unsigned int dstParts,
static int tcMultiplyPart(WordType *dst, const WordType *src,
WordType multiplier, WordType carry,
unsigned srcParts, unsigned dstParts,
bool add);
/// DST = LHS * RHS, where DST has the same width as the operands and is
/// filled with the least significant parts of the result. Returns one if
/// overflow occurred, otherwise zero. DST must be disjoint from both
/// operands.
static int tcMultiply(integerPart *, const integerPart *, const integerPart *,
static int tcMultiply(WordType *, const WordType *, const WordType *,
unsigned);
/// DST = LHS * RHS, where DST has width the sum of the widths of the
/// operands. No overflow occurs. DST must be disjoint from both
/// operands. Returns the number of parts required to hold the result.
static unsigned int tcFullMultiply(integerPart *, const integerPart *,
const integerPart *, unsigned, unsigned);
static unsigned tcFullMultiply(WordType *, const WordType *,
const WordType *, unsigned, unsigned);
/// If RHS is zero LHS and REMAINDER are left unchanged, return one.
/// Otherwise set LHS to LHS / RHS with the fractional part discarded, set
@ -1667,38 +1755,39 @@ class LLVM_NODISCARD APInt {
/// SCRATCH is a bignum of the same size as the operands and result for use by
/// the routine; its contents need not be initialized and are destroyed. LHS,
/// REMAINDER and SCRATCH must be distinct.
static int tcDivide(integerPart *lhs, const integerPart *rhs,
integerPart *remainder, integerPart *scratch,
unsigned int parts);
static int tcDivide(WordType *lhs, const WordType *rhs,
WordType *remainder, WordType *scratch,
unsigned parts);
/// Shift a bignum left COUNT bits. Shifted in bits are zero. There are no
/// restrictions on COUNT.
static void tcShiftLeft(integerPart *, unsigned int parts,
unsigned int count);
static void tcShiftLeft(WordType *, unsigned parts, unsigned count);
/// Shift a bignum right COUNT bits. Shifted in bits are zero. There are no
/// restrictions on COUNT.
static void tcShiftRight(integerPart *, unsigned int parts,
unsigned int count);
static void tcShiftRight(WordType *, unsigned parts, unsigned count);
/// The obvious AND, OR and XOR and complement operations.
static void tcAnd(integerPart *, const integerPart *, unsigned int);
static void tcOr(integerPart *, const integerPart *, unsigned int);
static void tcXor(integerPart *, const integerPart *, unsigned int);
static void tcComplement(integerPart *, unsigned int);
static void tcAnd(WordType *, const WordType *, unsigned);
static void tcOr(WordType *, const WordType *, unsigned);
static void tcXor(WordType *, const WordType *, unsigned);
static void tcComplement(WordType *, unsigned);
/// Comparison (unsigned) of two bignums.
static int tcCompare(const integerPart *, const integerPart *, unsigned int);
static int tcCompare(const WordType *, const WordType *, unsigned);
/// Increment a bignum in-place. Return the carry flag.
static integerPart tcIncrement(integerPart *, unsigned int);
static WordType tcIncrement(WordType *dst, unsigned parts) {
return tcAddPart(dst, 1, parts);
}
/// Decrement a bignum in-place. Return the borrow flag.
static integerPart tcDecrement(integerPart *, unsigned int);
static WordType tcDecrement(WordType *dst, unsigned parts) {
return tcSubtractPart(dst, 1, parts);
}
/// Set the least significant BITS and clear the rest.
static void tcSetLeastSignificantBits(integerPart *, unsigned int,
unsigned int bits);
static void tcSetLeastSignificantBits(WordType *, unsigned, unsigned bits);
/// \brief debug method
void dump() const;
@ -1723,6 +1812,74 @@ inline bool operator==(uint64_t V1, const APInt &V2) { return V2 == V1; }
inline bool operator!=(uint64_t V1, const APInt &V2) { return V2 != V1; }
/// \brief Unary bitwise complement operator.
///
/// \returns an APInt that is the bitwise complement of \p v.
inline APInt operator~(APInt v) {
v.flipAllBits();
return v;
}
inline APInt operator&(APInt a, const APInt &b) {
a &= b;
return a;
}
inline APInt operator&(const APInt &a, APInt &&b) {
b &= a;
return std::move(b);
}
inline APInt operator&(APInt a, uint64_t RHS) {
a &= RHS;
return a;
}
inline APInt operator&(uint64_t LHS, APInt b) {
b &= LHS;
return b;
}
inline APInt operator|(APInt a, const APInt &b) {
a |= b;
return a;
}
inline APInt operator|(const APInt &a, APInt &&b) {
b |= a;
return std::move(b);
}
inline APInt operator|(APInt a, uint64_t RHS) {
a |= RHS;
return a;
}
inline APInt operator|(uint64_t LHS, APInt b) {
b |= LHS;
return b;
}
inline APInt operator^(APInt a, const APInt &b) {
a ^= b;
return a;
}
inline APInt operator^(const APInt &a, APInt &&b) {
b ^= a;
return std::move(b);
}
inline APInt operator^(APInt a, uint64_t RHS) {
a ^= RHS;
return a;
}
inline APInt operator^(uint64_t LHS, APInt b) {
b ^= LHS;
return b;
}
inline raw_ostream &operator<<(raw_ostream &OS, const APInt &I) {
I.print(OS, true);
return OS;
@ -1799,47 +1956,13 @@ inline const APInt &umax(const APInt &A, const APInt &B) {
return A.ugt(B) ? A : B;
}
/// \brief Check if the specified APInt has a N-bits unsigned integer value.
inline bool isIntN(unsigned N, const APInt &APIVal) { return APIVal.isIntN(N); }
/// \brief Check if the specified APInt has a N-bits signed integer value.
inline bool isSignedIntN(unsigned N, const APInt &APIVal) {
return APIVal.isSignedIntN(N);
}
/// \returns true if the argument APInt value is a sequence of ones starting at
/// the least significant bit with the remainder zero.
inline bool isMask(unsigned numBits, const APInt &APIVal) {
return numBits <= APIVal.getBitWidth() &&
APIVal == APInt::getLowBitsSet(APIVal.getBitWidth(), numBits);
}
/// \returns true if the argument is a non-empty sequence of ones starting at
/// the least significant bit with the remainder zero (32 bit version).
/// Ex. isMask(0x0000FFFFU) == true.
inline bool isMask(const APInt &Value) {
return (Value != 0) && ((Value + 1) & Value) == 0;
}
/// \brief Return true if the argument APInt value contains a sequence of ones
/// with the remainder zero.
inline bool isShiftedMask(unsigned numBits, const APInt &APIVal) {
return isMask(numBits, (APIVal - APInt(numBits, 1)) | APIVal);
}
/// \brief Returns a byte-swapped representation of the specified APInt Value.
inline APInt byteSwap(const APInt &APIVal) { return APIVal.byteSwap(); }
/// \brief Returns the floor log base 2 of the specified APInt value.
inline unsigned logBase2(const APInt &APIVal) { return APIVal.logBase2(); }
/// \brief Compute GCD of two APInt values.
/// \brief Compute GCD of two unsigned APInt values.
///
/// This function returns the greatest common divisor of the two APInt values
/// using Euclid's algorithm.
///
/// \returns the greatest common divisor of Val1 and Val2
APInt GreatestCommonDivisor(const APInt &Val1, const APInt &Val2);
/// \returns the greatest common divisor of A and B.
APInt GreatestCommonDivisor(APInt A, APInt B);
/// \brief Converts the given APInt to a double value.
///
@ -1879,83 +2002,6 @@ inline APInt RoundFloatToAPInt(float Float, unsigned width) {
return RoundDoubleToAPInt(double(Float), width);
}
/// \brief Arithmetic right-shift function.
///
/// Arithmetic right-shift the APInt by shiftAmt.
inline APInt ashr(const APInt &LHS, unsigned shiftAmt) {
return LHS.ashr(shiftAmt);
}
/// \brief Logical right-shift function.
///
/// Logical right-shift the APInt by shiftAmt.
inline APInt lshr(const APInt &LHS, unsigned shiftAmt) {
return LHS.lshr(shiftAmt);
}
/// \brief Left-shift function.
///
/// Left-shift the APInt by shiftAmt.
inline APInt shl(const APInt &LHS, unsigned shiftAmt) {
return LHS.shl(shiftAmt);
}
/// \brief Signed division function for APInt.
///
/// Signed divide APInt LHS by APInt RHS.
inline APInt sdiv(const APInt &LHS, const APInt &RHS) { return LHS.sdiv(RHS); }
/// \brief Unsigned division function for APInt.
///
/// Unsigned divide APInt LHS by APInt RHS.
inline APInt udiv(const APInt &LHS, const APInt &RHS) { return LHS.udiv(RHS); }
/// \brief Function for signed remainder operation.
///
/// Signed remainder operation on APInt.
inline APInt srem(const APInt &LHS, const APInt &RHS) { return LHS.srem(RHS); }
/// \brief Function for unsigned remainder operation.
///
/// Unsigned remainder operation on APInt.
inline APInt urem(const APInt &LHS, const APInt &RHS) { return LHS.urem(RHS); }
/// \brief Function for multiplication operation.
///
/// Performs multiplication on APInt values.
inline APInt mul(const APInt &LHS, const APInt &RHS) { return LHS * RHS; }
/// \brief Function for addition operation.
///
/// Performs addition on APInt values.
inline APInt add(const APInt &LHS, const APInt &RHS) { return LHS + RHS; }
/// \brief Function for subtraction operation.
///
/// Performs subtraction on APInt values.
inline APInt sub(const APInt &LHS, const APInt &RHS) { return LHS - RHS; }
/// \brief Bitwise AND function for APInt.
///
/// Performs bitwise AND operation on APInt LHS and
/// APInt RHS.
inline APInt And(const APInt &LHS, const APInt &RHS) { return LHS & RHS; }
/// \brief Bitwise OR function for APInt.
///
/// Performs bitwise OR operation on APInt LHS and APInt RHS.
inline APInt Or(const APInt &LHS, const APInt &RHS) { return LHS | RHS; }
/// \brief Bitwise XOR function for APInt.
///
/// Performs bitwise XOR operation on APInt.
inline APInt Xor(const APInt &LHS, const APInt &RHS) { return LHS ^ RHS; }
/// \brief Bitwise complement function.
///
/// Performs a bitwise complement operation on APInt.
inline APInt Not(const APInt &APIVal) { return ~APIVal; }
} // End of APIntOps namespace
// See friend declaration above. This additional declaration is required in

View File

@ -235,19 +235,16 @@ class LLVM_NODISCARD APSInt : public APInt {
assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
return APSInt(static_cast<const APInt&>(*this) & RHS, IsUnsigned);
}
APSInt And(const APSInt &RHS) const { return this->operator&(RHS); }
APSInt operator|(const APSInt& RHS) const {
assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
return APSInt(static_cast<const APInt&>(*this) | RHS, IsUnsigned);
}
APSInt Or(const APSInt &RHS) const { return this->operator|(RHS); }
APSInt operator^(const APSInt &RHS) const {
assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
return APSInt(static_cast<const APInt&>(*this) ^ RHS, IsUnsigned);
}
APSInt Xor(const APSInt &RHS) const { return this->operator^(RHS); }
APSInt operator*(const APSInt& RHS) const {
assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");

View File

@ -487,6 +487,18 @@ namespace llvm {
return ArrayRef<T>(Arr);
}
/// Construct a MutableArrayRef from a single element.
template<typename T>
MutableArrayRef<T> makeMutableArrayRef(T &OneElt) {
return OneElt;
}
/// Construct a MutableArrayRef from a pointer and length.
template<typename T>
MutableArrayRef<T> makeMutableArrayRef(T *data, size_t length) {
return MutableArrayRef<T>(data, length);
}
/// @}
/// @name ArrayRef Comparison Operators
/// @{

View File

@ -161,6 +161,17 @@ class BitVector {
return -1;
}
/// find_first_unset - Returns the index of the first unset bit, -1 if all
/// of the bits are set.
int find_first_unset() const {
for (unsigned i = 0; i < NumBitWords(size()); ++i)
if (Bits[i] != ~0UL) {
unsigned Result = i * BITWORD_SIZE + countTrailingOnes(Bits[i]);
return Result < size() ? Result : -1;
}
return -1;
}
/// find_next - Returns the index of the next set bit following the
/// "Prev" bit. Returns -1 if the next set bit is not found.
int find_next(unsigned Prev) const {
@ -184,6 +195,30 @@ class BitVector {
return -1;
}
/// find_next_unset - Returns the index of the next usnet bit following the
/// "Prev" bit. Returns -1 if all remaining bits are set.
int find_next_unset(unsigned Prev) const {
++Prev;
if (Prev >= Size)
return -1;
unsigned WordPos = Prev / BITWORD_SIZE;
unsigned BitPos = Prev % BITWORD_SIZE;
BitWord Copy = Bits[WordPos];
// Mask in previous bits.
BitWord Mask = (1 << BitPos) - 1;
Copy |= Mask;
if (Copy != ~0UL)
return next_unset_in_word(WordPos, Copy);
// Check subsequent words.
for (unsigned i = WordPos + 1; i < NumBitWords(size()); ++i)
if (Bits[i] != ~0UL)
return next_unset_in_word(i, Bits[i]);
return -1;
}
/// clear - Clear all bits.
void clear() {
Size = 0;
@ -503,6 +538,11 @@ class BitVector {
}
private:
int next_unset_in_word(int WordIndex, BitWord Word) const {
unsigned Result = WordIndex * BITWORD_SIZE + countTrailingOnes(Word);
return Result < size() ? Result : -1;
}
unsigned NumBitWords(unsigned S) const {
return (S + BITWORD_SIZE-1) / BITWORD_SIZE;
}
@ -539,7 +579,8 @@ class BitVector {
}
void init_words(BitWord *B, unsigned NumWords, bool t) {
memset(B, 0 - (int)t, NumWords*sizeof(BitWord));
if (NumWords > 0)
memset(B, 0 - (int)t, NumWords*sizeof(BitWord));
}
template<bool AddBits, bool InvertMask>

View File

@ -0,0 +1,164 @@
//===- llvm/ADT/BreadthFirstIterator.h - Breadth First iterator -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file builds on the ADT/GraphTraits.h file to build a generic breadth
// first graph iterator. This file exposes the following functions/types:
//
// bf_begin/bf_end/bf_iterator
// * Normal breadth-first iteration - visit a graph level-by-level.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ADT_BREADTHFIRSTITERATOR_H
#define LLVM_ADT_BREADTHFIRSTITERATOR_H
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/iterator_range.h"
#include <iterator>
#include <queue>
#include <set>
#include <utility>
namespace llvm {
// bf_iterator_storage - A private class which is used to figure out where to
// store the visited set. We only provide a non-external variant for now.
template <class SetType> class bf_iterator_storage {
public:
SetType Visited;
};
// The visited state for the iteration is a simple set.
template <typename NodeRef, unsigned SmallSize = 8>
using bf_iterator_default_set = SmallPtrSet<NodeRef, SmallSize>;
// Generic Breadth first search iterator.
template <class GraphT,
class SetType =
bf_iterator_default_set<typename GraphTraits<GraphT>::NodeRef>,
class GT = GraphTraits<GraphT>>
class bf_iterator
: public std::iterator<std::forward_iterator_tag, typename GT::NodeRef>,
public bf_iterator_storage<SetType> {
typedef std::iterator<std::forward_iterator_tag, typename GT::NodeRef> super;
typedef typename GT::NodeRef NodeRef;
typedef typename GT::ChildIteratorType ChildItTy;
// First element is the node reference, second is the next child to visit.
typedef std::pair<NodeRef, Optional<ChildItTy>> QueueElement;
// Visit queue - used to maintain BFS ordering.
// Optional<> because we need markers for levels.
std::queue<Optional<QueueElement>> VisitQueue;
// Current level.
unsigned Level;
private:
inline bf_iterator(NodeRef Node) {
this->Visited.insert(Node);
Level = 0;
// Also, insert a dummy node as marker.
VisitQueue.push(QueueElement(Node, None));
VisitQueue.push(None);
}
inline bf_iterator() = default;
inline void toNext() {
Optional<QueueElement> Head = VisitQueue.front();
QueueElement H = Head.getValue();
NodeRef Node = H.first;
Optional<ChildItTy> &ChildIt = H.second;
if (!ChildIt)
ChildIt.emplace(GT::child_begin(Node));
while (*ChildIt != GT::child_end(Node)) {
NodeRef Next = *(*ChildIt)++;
// Already visited?
if (this->Visited.insert(Next).second)
VisitQueue.push(QueueElement(Next, None));
}
VisitQueue.pop();
// Go to the next element skipping markers if needed.
if (!VisitQueue.empty()) {
Head = VisitQueue.front();
if (Head != None)
return;
Level += 1;
VisitQueue.pop();
// Don't push another marker if this is the last
// element.
if (!VisitQueue.empty())
VisitQueue.push(None);
}
}
public:
typedef typename super::pointer pointer;
// Provide static begin and end methods as our public "constructors"
static bf_iterator begin(const GraphT &G) {
return bf_iterator(GT::getEntryNode(G));
}
static bf_iterator end(const GraphT &G) { return bf_iterator(); }
bool operator==(const bf_iterator &RHS) const {
return VisitQueue == RHS.VisitQueue;
}
bool operator!=(const bf_iterator &RHS) const { return !(*this == RHS); }
const NodeRef &operator*() const { return VisitQueue.front()->first; }
// This is a nonstandard operator-> that dereferenfces the pointer an extra
// time so that you can actually call methods on the node, because the
// contained type is a pointer.
NodeRef operator->() const { return **this; }
bf_iterator &operator++() { // Pre-increment
toNext();
return *this;
}
bf_iterator operator++(int) { // Post-increment
bf_iterator ItCopy = *this;
++*this;
return ItCopy;
}
unsigned getLevel() const { return Level; }
};
// Provide global constructors that automatically figure out correct types.
template <class T> bf_iterator<T> bf_begin(const T &G) {
return bf_iterator<T>::begin(G);
}
template <class T> bf_iterator<T> bf_end(const T &G) {
return bf_iterator<T>::end(G);
}
// Provide an accessor method to use them in range-based patterns.
template <class T> iterator_range<bf_iterator<T>> breadth_first(const T &G) {
return make_range(bf_begin(G), bf_end(G));
}
} // end namespace llvm
#endif // LLVM_ADT_BREADTHFIRSTITERATOR_H

View File

@ -53,6 +53,9 @@ class DenseMapIterator;
template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
typename BucketT>
class DenseMapBase : public DebugEpochBase {
template <typename T>
using const_arg_type_t = typename const_pointer_or_const_ref<T>::type;
public:
typedef unsigned size_type;
typedef KeyT key_type;
@ -119,18 +122,18 @@ class DenseMapBase : public DebugEpochBase {
}
/// Return 1 if the specified key is in the map, 0 otherwise.
size_type count(const KeyT &Val) const {
size_type count(const_arg_type_t<KeyT> Val) const {
const BucketT *TheBucket;
return LookupBucketFor(Val, TheBucket) ? 1 : 0;
}
iterator find(const KeyT &Val) {
iterator find(const_arg_type_t<KeyT> Val) {
BucketT *TheBucket;
if (LookupBucketFor(Val, TheBucket))
return iterator(TheBucket, getBucketsEnd(), *this, true);
return end();
}
const_iterator find(const KeyT &Val) const {
const_iterator find(const_arg_type_t<KeyT> Val) const {
const BucketT *TheBucket;
if (LookupBucketFor(Val, TheBucket))
return const_iterator(TheBucket, getBucketsEnd(), *this, true);
@ -159,7 +162,7 @@ class DenseMapBase : public DebugEpochBase {
/// lookup - Return the entry for the specified key, or a default
/// constructed value if no such entry exists.
ValueT lookup(const KeyT &Val) const {
ValueT lookup(const_arg_type_t<KeyT> Val) const {
const BucketT *TheBucket;
if (LookupBucketFor(Val, TheBucket))
return TheBucket->getSecond();
@ -389,6 +392,8 @@ class DenseMapBase : public DebugEpochBase {
return KeyInfoT::getHashValue(Val);
}
static const KeyT getEmptyKey() {
static_assert(std::is_base_of<DenseMapBase, DerivedT>::value,
"Must pass the derived type to this template!");
return KeyInfoT::getEmptyKey();
}
static const KeyT getTombstoneKey() {

View File

@ -60,6 +60,16 @@ template<> struct DenseMapInfo<char> {
}
};
// Provide DenseMapInfo for unsigned shorts.
template <> struct DenseMapInfo<unsigned short> {
static inline unsigned short getEmptyKey() { return 0xFFFF; }
static inline unsigned short getTombstoneKey() { return 0xFFFF - 1; }
static unsigned getHashValue(const unsigned short &Val) { return Val * 37U; }
static bool isEqual(const unsigned short &LHS, const unsigned short &RHS) {
return LHS == RHS;
}
};
// Provide DenseMapInfo for unsigned ints.
template<> struct DenseMapInfo<unsigned> {
static inline unsigned getEmptyKey() { return ~0U; }
@ -95,6 +105,14 @@ template<> struct DenseMapInfo<unsigned long long> {
}
};
// Provide DenseMapInfo for shorts.
template <> struct DenseMapInfo<short> {
static inline short getEmptyKey() { return 0x7FFF; }
static inline short getTombstoneKey() { return -0x7FFF - 1; }
static unsigned getHashValue(const short &Val) { return Val * 37U; }
static bool isEqual(const short &LHS, const short &RHS) { return LHS == RHS; }
};
// Provide DenseMapInfo for ints.
template<> struct DenseMapInfo<int> {
static inline int getEmptyKey() { return 0x7fffffff; }

View File

@ -48,6 +48,8 @@ class DenseSetImpl {
static_assert(sizeof(typename MapTy::value_type) == sizeof(ValueT),
"DenseMap buckets unexpectedly large!");
MapTy TheMap;
template <typename T>
using const_arg_type_t = typename const_pointer_or_const_ref<T>::type;
public:
typedef ValueT key_type;
@ -78,7 +80,7 @@ class DenseSetImpl {
}
/// Return 1 if the specified key is in the set, 0 otherwise.
size_type count(const ValueT &V) const {
size_type count(const_arg_type_t<ValueT> V) const {
return TheMap.count(V);
}
@ -90,9 +92,12 @@ class DenseSetImpl {
// Iterators.
class ConstIterator;
class Iterator {
typename MapTy::iterator I;
friend class DenseSetImpl;
friend class ConstIterator;
public:
typedef typename MapTy::iterator::difference_type difference_type;
@ -101,20 +106,24 @@ class DenseSetImpl {
typedef value_type &reference;
typedef std::forward_iterator_tag iterator_category;
Iterator() = default;
Iterator(const typename MapTy::iterator &i) : I(i) {}
ValueT &operator*() { return I->getFirst(); }
const ValueT &operator*() const { return I->getFirst(); }
ValueT *operator->() { return &I->getFirst(); }
const ValueT *operator->() const { return &I->getFirst(); }
Iterator& operator++() { ++I; return *this; }
Iterator operator++(int) { auto T = *this; ++I; return T; }
bool operator==(const Iterator& X) const { return I == X.I; }
bool operator!=(const Iterator& X) const { return I != X.I; }
bool operator==(const ConstIterator& X) const { return I == X.I; }
bool operator!=(const ConstIterator& X) const { return I != X.I; }
};
class ConstIterator {
typename MapTy::const_iterator I;
friend class DenseSet;
friend class Iterator;
public:
typedef typename MapTy::const_iterator::difference_type difference_type;
@ -123,10 +132,14 @@ class DenseSetImpl {
typedef value_type &reference;
typedef std::forward_iterator_tag iterator_category;
ConstIterator(const Iterator &B) : I(B.I) {}
ConstIterator() = default;
ConstIterator(const typename MapTy::const_iterator &i) : I(i) {}
const ValueT &operator*() { return I->getFirst(); }
const ValueT *operator->() { return &I->getFirst(); }
const ValueT &operator*() const { return I->getFirst(); }
const ValueT *operator->() const { return &I->getFirst(); }
ConstIterator& operator++() { ++I; return *this; }
ConstIterator operator++(int) { auto T = *this; ++I; return T; }
@ -143,8 +156,8 @@ class DenseSetImpl {
const_iterator begin() const { return ConstIterator(TheMap.begin()); }
const_iterator end() const { return ConstIterator(TheMap.end()); }
iterator find(const ValueT &V) { return Iterator(TheMap.find(V)); }
const_iterator find(const ValueT &V) const {
iterator find(const_arg_type_t<ValueT> V) { return Iterator(TheMap.find(V)); }
const_iterator find(const_arg_type_t<ValueT> V) const {
return ConstIterator(TheMap.find(V));
}

View File

@ -135,7 +135,7 @@ class df_iterator
}
}
this->Visited.completed(Node);
// Oops, ran out of successors... go up a level on the stack.
VisitStack.pop_back();
} while (!VisitStack.empty());

View File

@ -18,6 +18,8 @@
#ifndef LLVM_ADT_GRAPHTRAITS_H
#define LLVM_ADT_GRAPHTRAITS_H
#include "llvm/ADT/iterator_range.h"
namespace llvm {
// GraphTraits - This class should be specialized by different graph types...
@ -86,6 +88,33 @@ struct Inverse {
// inverse falls back to the original graph.
template <class T> struct GraphTraits<Inverse<Inverse<T>>> : GraphTraits<T> {};
// Provide iterator ranges for the graph traits nodes and children
template <class GraphType>
iterator_range<typename GraphTraits<GraphType>::nodes_iterator>
nodes(const GraphType &G) {
return make_range(GraphTraits<GraphType>::nodes_begin(G),
GraphTraits<GraphType>::nodes_end(G));
}
template <class GraphType>
iterator_range<typename GraphTraits<Inverse<GraphType>>::nodes_iterator>
inverse_nodes(const GraphType &G) {
return make_range(GraphTraits<Inverse<GraphType>>::nodes_begin(G),
GraphTraits<Inverse<GraphType>>::nodes_end(G));
}
template <class GraphType>
iterator_range<typename GraphTraits<GraphType>::ChildIteratorType>
children(const typename GraphTraits<GraphType>::NodeRef &G) {
return make_range(GraphTraits<GraphType>::child_begin(G),
GraphTraits<GraphType>::child_end(G));
}
template <class GraphType>
iterator_range<typename GraphTraits<Inverse<GraphType>>::ChildIteratorType>
inverse_children(const typename GraphTraits<GraphType>::NodeRef &G) {
return make_range(GraphTraits<Inverse<GraphType>>::child_begin(G),
GraphTraits<Inverse<GraphType>>::child_end(G));
}
} // End llvm namespace
#endif

View File

@ -19,8 +19,9 @@
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 class NoneType { None };
const NoneType None = None;
// (constant value 1 in an attempt to workaround MSVC build issue... )
enum class NoneType { None = 1 };
const NoneType None = NoneType::None;
}
#endif

View File

@ -31,7 +31,7 @@ template <typename T> struct PointerUnionTypeSelectorReturn {
/// Get a type based on whether two types are the same or not.
///
/// For:
///
///
/// \code
/// typedef typename PointerUnionTypeSelector<T1, T2, EQ, NE>::Return Ret;
/// \endcode
@ -190,17 +190,17 @@ template <typename PT1, typename PT2> class PointerUnion {
};
template <typename PT1, typename PT2>
static bool operator==(PointerUnion<PT1, PT2> lhs, PointerUnion<PT1, PT2> rhs) {
bool operator==(PointerUnion<PT1, PT2> lhs, PointerUnion<PT1, PT2> rhs) {
return lhs.getOpaqueValue() == rhs.getOpaqueValue();
}
template <typename PT1, typename PT2>
static bool operator!=(PointerUnion<PT1, PT2> lhs, PointerUnion<PT1, PT2> rhs) {
bool operator!=(PointerUnion<PT1, PT2> lhs, PointerUnion<PT1, PT2> rhs) {
return lhs.getOpaqueValue() != rhs.getOpaqueValue();
}
template <typename PT1, typename PT2>
static bool operator<(PointerUnion<PT1, PT2> lhs, PointerUnion<PT1, PT2> rhs) {
bool operator<(PointerUnion<PT1, PT2> lhs, PointerUnion<PT1, PT2> rhs) {
return lhs.getOpaqueValue() < rhs.getOpaqueValue();
}

View File

@ -268,6 +268,10 @@ inverse_post_order_ext(const T &G, SetType &S) {
// with a postorder iterator to build the data structures). The moral of this
// story is: Don't create more ReversePostOrderTraversal classes than necessary.
//
// Because it does the traversal in its constructor, it won't invalidate when
// BasicBlocks are removed, *but* it may contain erased blocks. Some places
// rely on this behavior (i.e. GVN).
//
// This class should be used like this:
// {
// ReversePostOrderTraversal<Function*> RPOT(FuncPtr); // Expensive to create

View File

@ -23,11 +23,13 @@
#include <cstdlib> // for qsort
#include <functional>
#include <iterator>
#include <limits>
#include <memory>
#include <tuple>
#include <utility> // for std::pair
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Compiler.h"
@ -44,6 +46,10 @@ namespace detail {
template <typename RangeT>
using IterOfRange = decltype(std::begin(std::declval<RangeT &>()));
template <typename RangeT>
using ValueOfRange = typename std::remove_reference<decltype(
*std::begin(std::declval<RangeT &>()))>::type;
} // End detail namespace
//===----------------------------------------------------------------------===//
@ -123,7 +129,7 @@ inline void deleter(T *Ptr) {
//===----------------------------------------------------------------------===//
// mapped_iterator - This is a simple iterator adapter that causes a function to
// be dereferenced whenever operator* is invoked on the iterator.
// be applied whenever operator* is invoked on the iterator.
//
template <class RootIt, class UnaryFunc>
class mapped_iterator {
@ -134,9 +140,8 @@ class mapped_iterator {
iterator_category;
typedef typename std::iterator_traits<RootIt>::difference_type
difference_type;
typedef typename std::result_of<
UnaryFunc(decltype(*std::declval<RootIt>()))>
::type value_type;
typedef decltype(std::declval<UnaryFunc>()(*std::declval<RootIt>()))
value_type;
typedef void pointer;
//typedef typename UnaryFunc::result_type *pointer;
@ -356,65 +361,126 @@ template <size_t... I> struct index_sequence;
template <class... Ts> struct index_sequence_for;
namespace detail {
template <typename... Iters> class zip_first {
public:
typedef std::input_iterator_tag iterator_category;
typedef std::tuple<decltype(*std::declval<Iters>())...> value_type;
using std::declval;
// We have to alias this since inlining the actual type at the usage site
// in the parameter list of iterator_facade_base<> below ICEs MSVC 2017.
template<typename... Iters> struct ZipTupleType {
typedef std::tuple<decltype(*declval<Iters>())...> type;
};
template <typename ZipType, typename... Iters>
using zip_traits = iterator_facade_base<
ZipType, typename std::common_type<std::bidirectional_iterator_tag,
typename std::iterator_traits<
Iters>::iterator_category...>::type,
// ^ TODO: Implement random access methods.
typename ZipTupleType<Iters...>::type,
typename std::iterator_traits<typename std::tuple_element<
0, std::tuple<Iters...>>::type>::difference_type,
// ^ FIXME: This follows boost::make_zip_iterator's assumption that all
// inner iterators have the same difference_type. It would fail if, for
// instance, the second field's difference_type were non-numeric while the
// first is.
typename ZipTupleType<Iters...>::type *,
typename ZipTupleType<Iters...>::type>;
template <typename ZipType, typename... Iters>
struct zip_common : public zip_traits<ZipType, Iters...> {
using Base = zip_traits<ZipType, Iters...>;
using value_type = typename Base::value_type;
std::tuple<Iters...> iterators;
private:
template <size_t... Ns> value_type deres(index_sequence<Ns...>) {
protected:
template <size_t... Ns> value_type deref(index_sequence<Ns...>) const {
return value_type(*std::get<Ns>(iterators)...);
}
template <size_t... Ns> decltype(iterators) tup_inc(index_sequence<Ns...>) {
template <size_t... Ns>
decltype(iterators) tup_inc(index_sequence<Ns...>) const {
return std::tuple<Iters...>(std::next(std::get<Ns>(iterators))...);
}
public:
value_type operator*() { return deres(index_sequence_for<Iters...>{}); }
void operator++() { iterators = tup_inc(index_sequence_for<Iters...>{}); }
bool operator!=(const zip_first<Iters...> &other) const {
return std::get<0>(iterators) != std::get<0>(other.iterators);
template <size_t... Ns>
decltype(iterators) tup_dec(index_sequence<Ns...>) const {
return std::tuple<Iters...>(std::prev(std::get<Ns>(iterators))...);
}
public:
zip_common(Iters &&... ts) : iterators(std::forward<Iters>(ts)...) {}
value_type operator*() { return deref(index_sequence_for<Iters...>{}); }
const value_type operator*() const {
return deref(index_sequence_for<Iters...>{});
}
ZipType &operator++() {
iterators = tup_inc(index_sequence_for<Iters...>{});
return *reinterpret_cast<ZipType *>(this);
}
ZipType &operator--() {
static_assert(Base::IsBidirectional,
"All inner iterators must be at least bidirectional.");
iterators = tup_dec(index_sequence_for<Iters...>{});
return *reinterpret_cast<ZipType *>(this);
}
zip_first(Iters &&... ts) : iterators(std::forward<Iters>(ts)...) {}
};
template <typename... Iters> class zip_shortest : public zip_first<Iters...> {
template <typename... Iters>
struct zip_first : public zip_common<zip_first<Iters...>, Iters...> {
using Base = zip_common<zip_first<Iters...>, Iters...>;
bool operator==(const zip_first<Iters...> &other) const {
return std::get<0>(this->iterators) == std::get<0>(other.iterators);
}
zip_first(Iters &&... ts) : Base(std::forward<Iters>(ts)...) {}
};
template <typename... Iters>
class zip_shortest : public zip_common<zip_shortest<Iters...>, Iters...> {
template <size_t... Ns>
bool test(const zip_first<Iters...> &other, index_sequence<Ns...>) const {
bool test(const zip_shortest<Iters...> &other, index_sequence<Ns...>) const {
return all_of(std::initializer_list<bool>{std::get<Ns>(this->iterators) !=
std::get<Ns>(other.iterators)...},
identity<bool>{});
}
public:
bool operator!=(const zip_first<Iters...> &other) const {
return test(other, index_sequence_for<Iters...>{});
using Base = zip_common<zip_shortest<Iters...>, Iters...>;
bool operator==(const zip_shortest<Iters...> &other) const {
return !test(other, index_sequence_for<Iters...>{});
}
zip_shortest(Iters &&... ts)
: zip_first<Iters...>(std::forward<Iters>(ts)...) {}
zip_shortest(Iters &&... ts) : Base(std::forward<Iters>(ts)...) {}
};
template <template <typename...> class ItType, typename... Args> class zippy {
public:
typedef ItType<decltype(std::begin(std::declval<Args>()))...> iterator;
using iterator = ItType<decltype(std::begin(std::declval<Args>()))...>;
using iterator_category = typename iterator::iterator_category;
using value_type = typename iterator::value_type;
using difference_type = typename iterator::difference_type;
using pointer = typename iterator::pointer;
using reference = typename iterator::reference;
private:
std::tuple<Args...> ts;
template <size_t... Ns> iterator begin_impl(index_sequence<Ns...>) {
template <size_t... Ns> iterator begin_impl(index_sequence<Ns...>) const {
return iterator(std::begin(std::get<Ns>(ts))...);
}
template <size_t... Ns> iterator end_impl(index_sequence<Ns...>) {
template <size_t... Ns> iterator end_impl(index_sequence<Ns...>) const {
return iterator(std::end(std::get<Ns>(ts))...);
}
public:
iterator begin() { return begin_impl(index_sequence_for<Args...>{}); }
iterator end() { return end_impl(index_sequence_for<Args...>{}); }
iterator begin() const { return begin_impl(index_sequence_for<Args...>{}); }
iterator end() const { return end_impl(index_sequence_for<Args...>{}); }
zippy(Args &&... ts_) : ts(std::forward<Args>(ts_)...) {}
};
} // End detail namespace
@ -777,6 +843,13 @@ auto remove_if(R &&Range, UnaryPredicate P) -> decltype(std::begin(Range)) {
return std::remove_if(std::begin(Range), std::end(Range), P);
}
/// Provide wrappers to std::copy_if which take ranges instead of having to
/// pass begin/end explicitly.
template <typename R, typename OutputIt, typename UnaryPredicate>
OutputIt copy_if(R &&Range, OutputIt Out, UnaryPredicate P) {
return std::copy_if(std::begin(Range), std::end(Range), Out, P);
}
/// Wrapper function around std::find to detect if an element exists
/// in a container.
template <typename R, typename E>
@ -815,6 +888,15 @@ auto partition(R &&Range, UnaryPredicate P) -> decltype(std::begin(Range)) {
return std::partition(std::begin(Range), std::end(Range), P);
}
/// \brief Given a range of type R, iterate the entire range and return a
/// SmallVector with elements of the vector. This is useful, for example,
/// when you want to iterate a range and then sort the results.
template <unsigned Size, typename R>
SmallVector<typename std::remove_const<detail::ValueOfRange<R>>::type, Size>
to_vector(R &&Range) {
return {std::begin(Range), std::end(Range)};
}
/// Provide a container algorithm similar to C++ Library Fundamentals v2's
/// `erase_if` which is equivalent to:
///
@ -909,47 +991,85 @@ template <typename T> struct deref {
};
namespace detail {
template <typename R> class enumerator_impl {
public:
template <typename X> struct result_pair {
result_pair(std::size_t Index, X Value) : Index(Index), Value(Value) {}
template <typename R> class enumerator_iter;
const std::size_t Index;
X Value;
};
template <typename R> struct result_pair {
friend class enumerator_iter<R>;
class iterator {
typedef
typename std::iterator_traits<IterOfRange<R>>::reference iter_reference;
typedef result_pair<iter_reference> result_type;
result_pair() : Index(-1) {}
result_pair(std::size_t Index, IterOfRange<R> Iter)
: Index(Index), Iter(Iter) {}
public:
iterator(IterOfRange<R> &&Iter, std::size_t Index)
: Iter(Iter), Index(Index) {}
result_pair<R> &operator=(const result_pair<R> &Other) {
Index = Other.Index;
Iter = Other.Iter;
return *this;
}
result_type operator*() const { return result_type(Index, *Iter); }
iterator &operator++() {
++Iter;
++Index;
return *this;
}
bool operator!=(const iterator &RHS) const { return Iter != RHS.Iter; }
private:
IterOfRange<R> Iter;
std::size_t Index;
};
public:
explicit enumerator_impl(R &&Range) : Range(std::forward<R>(Range)) {}
iterator begin() { return iterator(std::begin(Range), 0); }
iterator end() { return iterator(std::end(Range), std::size_t(-1)); }
std::size_t index() const { return Index; }
const ValueOfRange<R> &value() const { return *Iter; }
ValueOfRange<R> &value() { return *Iter; }
private:
R Range;
std::size_t Index;
IterOfRange<R> Iter;
};
template <typename R>
class enumerator_iter
: public iterator_facade_base<
enumerator_iter<R>, std::forward_iterator_tag, result_pair<R>,
typename std::iterator_traits<IterOfRange<R>>::difference_type,
typename std::iterator_traits<IterOfRange<R>>::pointer,
typename std::iterator_traits<IterOfRange<R>>::reference> {
using result_type = result_pair<R>;
public:
explicit enumerator_iter(IterOfRange<R> EndIter)
: Result(std::numeric_limits<size_t>::max(), EndIter) { }
enumerator_iter(std::size_t Index, IterOfRange<R> Iter)
: Result(Index, Iter) {}
result_type &operator*() { return Result; }
const result_type &operator*() const { return Result; }
enumerator_iter<R> &operator++() {
assert(Result.Index != std::numeric_limits<size_t>::max());
++Result.Iter;
++Result.Index;
return *this;
}
bool operator==(const enumerator_iter<R> &RHS) const {
// Don't compare indices here, only iterators. It's possible for an end
// iterator to have different indices depending on whether it was created
// by calling std::end() versus incrementing a valid iterator.
return Result.Iter == RHS.Result.Iter;
}
enumerator_iter<R> &operator=(const enumerator_iter<R> &Other) {
Result = Other.Result;
return *this;
}
private:
result_type Result;
};
template <typename R> class enumerator {
public:
explicit enumerator(R &&Range) : TheRange(std::forward<R>(Range)) {}
enumerator_iter<R> begin() {
return enumerator_iter<R>(0, std::begin(TheRange));
}
enumerator_iter<R> end() {
return enumerator_iter<R>(std::end(TheRange));
}
private:
R TheRange;
};
}
@ -968,8 +1088,8 @@ template <typename R> class enumerator_impl {
/// Item 2 - C
/// Item 3 - D
///
template <typename R> detail::enumerator_impl<R> enumerate(R &&Range) {
return detail::enumerator_impl<R>(std::forward<R>(Range));
template <typename R> detail::enumerator<R> enumerate(R &&TheRange) {
return detail::enumerator<R>(std::forward<R>(TheRange));
}
namespace detail {

View File

@ -182,8 +182,8 @@ class ScopedHashTable {
return TopLevelMap.count(Key);
}
V lookup(const K &Key) {
typename DenseMap<K, ValTy*, KInfo>::iterator I = TopLevelMap.find(Key);
V lookup(const K &Key) const {
auto I = TopLevelMap.find(Key);
if (I != TopLevelMap.end())
return I->second->getValue();

View File

@ -119,6 +119,12 @@ class SetVector {
return vector_.rend();
}
/// \brief Return the first element of the SetVector.
const T &front() const {
assert(!empty() && "Cannot call front() on empty SetVector!");
return vector_.front();
}
/// \brief Return the last element of the SetVector.
const T &back() const {
assert(!empty() && "Cannot call back() on empty SetVector!");
@ -232,7 +238,7 @@ class SetVector {
bool operator!=(const SetVector &that) const {
return vector_ != that.vector_;
}
/// \brief Compute This := This u S, return whether 'This' changed.
/// TODO: We should be able to use set_union from SetOperations.h, but
/// SetVector interface is inconsistent with DenseSet.

View File

@ -216,6 +216,18 @@ class SmallBitVector {
return getPointer()->find_first();
}
/// Returns the index of the first unset bit, -1 if all of the bits are set.
int find_first_unset() const {
if (isSmall()) {
if (count() == getSmallSize())
return -1;
uintptr_t Bits = getSmallBits();
return countTrailingOnes(Bits);
}
return getPointer()->find_first_unset();
}
/// Returns the index of the next set bit following the "Prev" bit.
/// Returns -1 if the next set bit is not found.
int find_next(unsigned Prev) const {
@ -230,6 +242,23 @@ class SmallBitVector {
return getPointer()->find_next(Prev);
}
/// Returns the index of the next unset bit following the "Prev" bit.
/// Returns -1 if the next unset bit is not found.
int find_next_unset(unsigned Prev) const {
if (isSmall()) {
++Prev;
uintptr_t Bits = getSmallBits();
// Mask in previous bits.
uintptr_t Mask = (1 << Prev) - 1;
Bits |= Mask;
if (Bits == ~uintptr_t(0) || Prev + 1 >= getSmallSize())
return -1;
return countTrailingOnes(Bits);
}
return getPointer()->find_next_unset(Prev);
}
/// Clear all bits.
void clear() {
if (!isSmall())

View File

@ -18,6 +18,7 @@
#include "llvm/Config/abi-breaking.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
#include "llvm/Support/type_traits.h"
#include <cassert>
#include <cstddef>
#include <cstring>
@ -166,8 +167,8 @@ class SmallPtrSetImplBase {
const void *const *P = find_imp(Ptr);
if (P == EndPointer())
return false;
const void ** Loc = const_cast<const void **>(P);
const void **Loc = const_cast<const void **>(P);
assert(*Loc == Ptr && "broken find!");
*Loc = getTombstoneMarker();
NumTombstones++;
@ -193,7 +194,7 @@ class SmallPtrSetImplBase {
return Bucket;
return EndPointer();
}
private:
bool isSmall() const { return CurArray == SmallArray; }
@ -259,11 +260,10 @@ class SmallPtrSetIteratorImpl {
}
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
void RetreatIfNotValid() {
--Bucket;
assert(Bucket <= End);
assert(Bucket >= End);
while (Bucket != End &&
(*Bucket == SmallPtrSetImplBase::getEmptyMarker() ||
*Bucket == SmallPtrSetImplBase::getTombstoneMarker())) {
(Bucket[-1] == SmallPtrSetImplBase::getEmptyMarker() ||
Bucket[-1] == SmallPtrSetImplBase::getTombstoneMarker())) {
--Bucket;
}
}
@ -288,6 +288,12 @@ class SmallPtrSetIterator : public SmallPtrSetIteratorImpl {
// Most methods provided by baseclass.
const PtrTy operator*() const {
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
if (ReverseIterate<bool>::value) {
assert(Bucket > End);
return PtrTraits::getFromVoidPointer(const_cast<void *>(Bucket[-1]));
}
#endif
assert(Bucket < End);
return PtrTraits::getFromVoidPointer(const_cast<void*>(*Bucket));
}
@ -295,6 +301,7 @@ class SmallPtrSetIterator : public SmallPtrSetIteratorImpl {
inline SmallPtrSetIterator& operator++() { // Preincrement
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
if (ReverseIterate<bool>::value) {
--Bucket;
RetreatIfNotValid();
return *this;
}
@ -343,7 +350,9 @@ struct RoundUpToPowerOfTwo {
/// to avoid encoding a particular small size in the interface boundary.
template <typename PtrType>
class SmallPtrSetImpl : public SmallPtrSetImplBase {
using ConstPtrType = typename add_const_past_pointer<PtrType>::type;
typedef PointerLikeTypeTraits<PtrType> PtrTraits;
typedef PointerLikeTypeTraits<ConstPtrType> ConstPtrTraits;
protected:
// Constructors that forward to the base.
@ -367,7 +376,7 @@ class SmallPtrSetImpl : public SmallPtrSetImplBase {
/// the element equal to Ptr.
std::pair<iterator, bool> insert(PtrType Ptr) {
auto p = insert_imp(PtrTraits::getAsVoidPointer(Ptr));
return std::make_pair(iterator(p.first, EndPointer()), p.second);
return std::make_pair(makeIterator(p.first), p.second);
}
/// erase - If the set contains the specified pointer, remove it and return
@ -375,14 +384,10 @@ class SmallPtrSetImpl : public SmallPtrSetImplBase {
bool erase(PtrType Ptr) {
return erase_imp(PtrTraits::getAsVoidPointer(Ptr));
}
/// count - Return 1 if the specified pointer is in the set, 0 otherwise.
size_type count(PtrType Ptr) const {
return find(Ptr) != endPtr() ? 1 : 0;
}
iterator find(PtrType Ptr) const {
auto *P = find_imp(PtrTraits::getAsVoidPointer(Ptr));
return iterator(P, EndPointer());
size_type count(ConstPtrType Ptr) const { return find(Ptr) != end() ? 1 : 0; }
iterator find(ConstPtrType Ptr) const {
return makeIterator(find_imp(ConstPtrTraits::getAsVoidPointer(Ptr)));
}
template <typename IterT>
@ -395,25 +400,23 @@ class SmallPtrSetImpl : public SmallPtrSetImplBase {
insert(IL.begin(), IL.end());
}
inline iterator begin() const {
iterator begin() const {
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
if (ReverseIterate<bool>::value)
return endPtr();
return makeIterator(EndPointer() - 1);
#endif
return iterator(CurArray, EndPointer());
}
inline iterator end() const {
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
if (ReverseIterate<bool>::value)
return iterator(CurArray, CurArray);
#endif
return endPtr();
return makeIterator(CurArray);
}
iterator end() const { return makeIterator(EndPointer()); }
private:
inline iterator endPtr() const {
const void *const *End = EndPointer();
return iterator(End, End);
/// Create an iterator that dereferences to same place as the given pointer.
iterator makeIterator(const void *const *P) const {
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
if (ReverseIterate<bool>::value)
return iterator(P == EndPointer() ? CurArray : P + 1, CurArray);
#endif
return iterator(P, EndPointer());
}
};

View File

@ -132,6 +132,17 @@ template <unsigned ElementSize = 128> struct SparseBitVectorElement {
llvm_unreachable("Illegal empty element");
}
/// find_last - Returns the index of the last set bit.
int find_last() const {
for (unsigned I = 0; I < BITWORDS_PER_ELEMENT; ++I) {
unsigned Idx = BITWORDS_PER_ELEMENT - I - 1;
if (Bits[Idx] != 0)
return Idx * BITWORD_SIZE + BITWORD_SIZE -
countLeadingZeros(Bits[Idx]) - 1;
}
llvm_unreachable("Illegal empty element");
}
/// find_next - Returns the index of the next set bit starting from the
/// "Curr" bit. Returns -1 if the next set bit is not found.
int find_next(unsigned Curr) const {
@ -768,6 +779,14 @@ class SparseBitVector {
return (First.index() * ElementSize) + First.find_first();
}
// Return the last set bit in the bitmap. Return -1 if no bits are set.
int find_last() const {
if (Elements.empty())
return -1;
const SparseBitVectorElement<ElementSize> &Last = *(Elements.rbegin());
return (Last.index() * ElementSize) + Last.find_last();
}
// Return true if the SparseBitVector is empty
bool empty() const {
return Elements.empty();

View File

@ -234,6 +234,13 @@ inline std::string join(IteratorT Begin, IteratorT End, StringRef Separator) {
return detail::join_impl(Begin, End, Separator, tag());
}
/// Joins the strings in the range [R.begin(), R.end()), adding Separator
/// between the elements.
template <typename Range>
inline std::string join(Range &&R, StringRef Separator) {
return join(R.begin(), R.end(), Separator);
}
/// Joins the strings in the parameter pack \p Items, adding \p Separator
/// between the elements. All arguments must be implicitly convertible to
/// std::string, or there should be an overload of std::string::operator+=()

View File

@ -15,13 +15,13 @@
#define LLVM_ADT_STRINGMAP_H
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
#include <cassert>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <utility>
#include <initializer_list>
#include <new>
#include <utility>
@ -32,6 +32,7 @@ namespace llvm {
class StringMapConstIterator;
template<typename ValueT>
class StringMapIterator;
template <typename ValueT> class StringMapKeyIterator;
template<typename ValueTy>
class StringMapEntry;
@ -312,6 +313,11 @@ class StringMap : public StringMapImpl {
return const_iterator(TheTable+NumBuckets, true);
}
llvm::iterator_range<StringMapKeyIterator<ValueTy>> keys() const {
return make_range(StringMapKeyIterator<ValueTy>(begin()),
StringMapKeyIterator<ValueTy>(end()));
}
iterator find(StringRef Key) {
int Bucket = FindKey(Key);
if (Bucket == -1) return end();
@ -444,42 +450,39 @@ class StringMap : public StringMapImpl {
}
};
template <typename ValueTy> class StringMapConstIterator {
template <typename DerivedTy, typename ValueTy>
class StringMapIterBase
: public iterator_facade_base<DerivedTy, std::forward_iterator_tag,
ValueTy> {
protected:
StringMapEntryBase **Ptr = nullptr;
public:
typedef StringMapEntry<ValueTy> value_type;
StringMapIterBase() = default;
StringMapConstIterator() = default;
explicit StringMapConstIterator(StringMapEntryBase **Bucket,
bool NoAdvance = false)
: Ptr(Bucket) {
explicit StringMapIterBase(StringMapEntryBase **Bucket,
bool NoAdvance = false)
: Ptr(Bucket) {
if (!NoAdvance) AdvancePastEmptyBuckets();
}
const value_type &operator*() const {
return *static_cast<StringMapEntry<ValueTy>*>(*Ptr);
}
const value_type *operator->() const {
return static_cast<StringMapEntry<ValueTy>*>(*Ptr);
DerivedTy &operator=(const DerivedTy &Other) {
Ptr = Other.Ptr;
return static_cast<DerivedTy &>(*this);
}
bool operator==(const StringMapConstIterator &RHS) const {
return Ptr == RHS.Ptr;
}
bool operator!=(const StringMapConstIterator &RHS) const {
return Ptr != RHS.Ptr;
}
bool operator==(const DerivedTy &RHS) const { return Ptr == RHS.Ptr; }
inline StringMapConstIterator& operator++() { // Preincrement
DerivedTy &operator++() { // Preincrement
++Ptr;
AdvancePastEmptyBuckets();
return *this;
return static_cast<DerivedTy &>(*this);
}
StringMapConstIterator operator++(int) { // Postincrement
StringMapConstIterator tmp = *this; ++*this; return tmp;
DerivedTy operator++(int) { // Post-increment
DerivedTy Tmp(Ptr);
++*this;
return Tmp;
}
private:
@ -489,24 +492,69 @@ template <typename ValueTy> class StringMapConstIterator {
}
};
template<typename ValueTy>
class StringMapIterator : public StringMapConstIterator<ValueTy> {
template <typename ValueTy>
class StringMapConstIterator
: public StringMapIterBase<StringMapConstIterator<ValueTy>,
const StringMapEntry<ValueTy>> {
using base = StringMapIterBase<StringMapConstIterator<ValueTy>,
const StringMapEntry<ValueTy>>;
public:
StringMapConstIterator() = default;
explicit StringMapConstIterator(StringMapEntryBase **Bucket,
bool NoAdvance = false)
: base(Bucket, NoAdvance) {}
const StringMapEntry<ValueTy> &operator*() const {
return *static_cast<const StringMapEntry<ValueTy> *>(*this->Ptr);
}
};
template <typename ValueTy>
class StringMapIterator : public StringMapIterBase<StringMapIterator<ValueTy>,
StringMapEntry<ValueTy>> {
using base =
StringMapIterBase<StringMapIterator<ValueTy>, StringMapEntry<ValueTy>>;
public:
StringMapIterator() = default;
explicit StringMapIterator(StringMapEntryBase **Bucket,
bool NoAdvance = false)
: StringMapConstIterator<ValueTy>(Bucket, NoAdvance) {
}
: base(Bucket, NoAdvance) {}
StringMapEntry<ValueTy> &operator*() const {
return *static_cast<StringMapEntry<ValueTy>*>(*this->Ptr);
return *static_cast<StringMapEntry<ValueTy> *>(*this->Ptr);
}
StringMapEntry<ValueTy> *operator->() const {
return static_cast<StringMapEntry<ValueTy>*>(*this->Ptr);
operator StringMapConstIterator<ValueTy>() const {
return StringMapConstIterator<ValueTy>(this->Ptr, true);
}
};
template <typename ValueTy>
class StringMapKeyIterator
: public iterator_adaptor_base<StringMapKeyIterator<ValueTy>,
StringMapConstIterator<ValueTy>,
std::forward_iterator_tag, StringRef> {
using base = iterator_adaptor_base<StringMapKeyIterator<ValueTy>,
StringMapConstIterator<ValueTy>,
std::forward_iterator_tag, StringRef>;
public:
StringMapKeyIterator() = default;
explicit StringMapKeyIterator(StringMapConstIterator<ValueTy> Iter)
: base(std::move(Iter)) {}
StringRef &operator*() {
Key = this->wrapped()->getKey();
return Key;
}
private:
StringRef Key;
};
} // end namespace llvm
#endif // LLVM_ADT_STRINGMAP_H

View File

@ -557,6 +557,14 @@ namespace llvm {
/// string is well-formed in the given radix.
bool getAsInteger(unsigned Radix, APInt &Result) const;
/// Parse the current string as an IEEE double-precision floating
/// point value. The string must be a well-formed double.
///
/// If \p AllowInexact is false, the function will fail if the string
/// cannot be represented exactly. Otherwise, the function only fails
/// in case of an overflow or underflow.
bool getAsDouble(double &Result, bool AllowInexact = true) const;
/// @}
/// @name String Operations
/// @{
@ -600,7 +608,7 @@ namespace llvm {
return drop_back(size() - N);
}
/// Return a StringRef equal to 'this' but with only the first \p N
/// Return a StringRef equal to 'this' but with only the last \p N
/// elements remaining. If \p N is greater than the length of the
/// string, the entire string is returned.
LLVM_NODISCARD

View File

@ -110,6 +110,7 @@ class Triple {
ARMSubArch_v7m,
ARMSubArch_v7s,
ARMSubArch_v7k,
ARMSubArch_v7ve,
ARMSubArch_v6,
ARMSubArch_v6m,
ARMSubArch_v6k,
@ -206,6 +207,7 @@ class Triple {
COFF,
ELF,
MachO,
Wasm,
};
private:
@ -558,7 +560,8 @@ class Triple {
/// Tests whether the OS uses glibc.
bool isOSGlibc() const {
return getOS() == Triple::Linux || getOS() == Triple::KFreeBSD;
return (getOS() == Triple::Linux || getOS() == Triple::KFreeBSD) &&
!isAndroid();
}
/// Tests whether the OS uses the ELF binary format.
@ -576,6 +579,11 @@ class Triple {
return getObjectFormat() == Triple::MachO;
}
/// Tests whether the OS uses the Wasm binary format.
bool isOSBinFormatWasm() const {
return getObjectFormat() == Triple::Wasm;
}
/// Tests whether the target is the PS4 CPU
bool isPS4CPU() const {
return getArch() == Triple::x86_64 &&
@ -592,6 +600,19 @@ class Triple {
/// Tests whether the target is Android
bool isAndroid() const { return getEnvironment() == Triple::Android; }
bool isAndroidVersionLT(unsigned Major) const {
assert(isAndroid() && "Not an Android triple!");
unsigned Env[3];
getEnvironmentVersion(Env[0], Env[1], Env[2]);
// 64-bit targets did not exist before API level 21 (Lollipop).
if (isArch64Bit() && Env[0] < 21)
Env[0] = 21;
return Env[0] < Major;
}
/// Tests whether the environment is musl-libc
bool isMusl() const {
return getEnvironment() == Triple::Musl ||

View File

@ -10,6 +10,7 @@
#ifndef LLVM_ADT_ITERATOR_H
#define LLVM_ADT_ITERATOR_H
#include "llvm/ADT/iterator_range.h"
#include <cstddef>
#include <iterator>
#include <type_traits>
@ -91,6 +92,8 @@ class iterator_facade_base
public:
DerivedT operator+(DifferenceTypeT n) const {
static_assert(std::is_base_of<iterator_facade_base, DerivedT>::value,
"Must pass the derived type to this template!");
static_assert(
IsRandomAccess,
"The '+' operator is only defined for random access iterators.");
@ -114,6 +117,8 @@ class iterator_facade_base
}
DerivedT &operator++() {
static_assert(std::is_base_of<iterator_facade_base, DerivedT>::value,
"Must pass the derived type to this template!");
return static_cast<DerivedT *>(this)->operator+=(1);
}
DerivedT operator++(int) {
@ -160,9 +165,15 @@ class iterator_facade_base
return !static_cast<const DerivedT *>(this)->operator<(RHS);
}
PointerT operator->() { return &static_cast<DerivedT *>(this)->operator*(); }
PointerT operator->() const {
return &static_cast<const DerivedT *>(this)->operator*();
}
ReferenceProxy operator[](DifferenceTypeT n) {
static_assert(IsRandomAccess,
"Subscripting is only defined for random access iterators.");
return ReferenceProxy(static_cast<DerivedT *>(this)->operator+(n));
}
ReferenceProxy operator[](DifferenceTypeT n) const {
static_assert(IsRandomAccess,
"Subscripting is only defined for random access iterators.");
@ -202,7 +213,10 @@ class iterator_adaptor_base
iterator_adaptor_base() = default;
explicit iterator_adaptor_base(WrappedIteratorT u) : I(std::move(u)) {}
explicit iterator_adaptor_base(WrappedIteratorT u) : I(std::move(u)) {
static_assert(std::is_base_of<iterator_adaptor_base, DerivedT>::value,
"Must pass the derived type to this template!");
}
const WrappedIteratorT &wrapped() const { return I; }
@ -283,6 +297,15 @@ struct pointee_iterator
T &operator*() const { return **this->I; }
};
template <typename RangeT, typename WrappedIteratorT =
decltype(std::begin(std::declval<RangeT>()))>
iterator_range<pointee_iterator<WrappedIteratorT>>
make_pointee_range(RangeT &&Range) {
using PointeeIteratorT = pointee_iterator<WrappedIteratorT>;
return make_range(PointeeIteratorT(std::begin(std::forward<RangeT>(Range))),
PointeeIteratorT(std::end(std::forward<RangeT>(Range))));
}
template <typename WrappedIteratorT,
typename T = decltype(&*std::declval<WrappedIteratorT>())>
class pointer_iterator
@ -300,6 +323,15 @@ class pointer_iterator
const T &operator*() const { return Ptr = &*this->I; }
};
template <typename RangeT, typename WrappedIteratorT =
decltype(std::begin(std::declval<RangeT>()))>
iterator_range<pointer_iterator<WrappedIteratorT>>
make_pointer_range(RangeT &&Range) {
using PointerIteratorT = pointer_iterator<WrappedIteratorT>;
return make_range(PointerIteratorT(std::begin(std::forward<RangeT>(Range))),
PointerIteratorT(std::end(std::forward<RangeT>(Range))));
}
} // end namespace llvm
#endif // LLVM_ADT_ITERATOR_H

View File

@ -443,11 +443,7 @@ class AAResults {
/// getModRefInfo (for fences) - Return information about whether
/// a particular store modifies or reads the specified memory location.
ModRefInfo getModRefInfo(const FenceInst *S, const MemoryLocation &Loc) {
// Conservatively correct. (We could possibly be a bit smarter if
// Loc is a alloca that doesn't escape.)
return MRI_ModRef;
}
ModRefInfo getModRefInfo(const FenceInst *S, const MemoryLocation &Loc);
/// getModRefInfo (for fences) - A convenience wrapper.
ModRefInfo getModRefInfo(const FenceInst *S, const Value *P, uint64_t Size) {
@ -528,6 +524,14 @@ class AAResults {
/// Check whether or not an instruction may read or write the specified
/// memory location.
///
/// Note explicitly that getModRefInfo considers the effects of reading and
/// writing the memory location, and not the effect of ordering relative to
/// other instructions. Thus, a volatile load is considered to be Ref,
/// because it does not actually write memory, it just can't be reordered
/// relative to other volatiles (or removed). Atomic ordered loads/stores are
/// considered ModRef ATM because conservatively, the visible effect appears
/// as if memory was written, not just an ordering constraint.
///
/// An instruction that doesn't read or write memory may be trivially LICM'd
/// for example.
///

View File

@ -121,7 +121,10 @@ class AliasSet : public ilist_node<AliasSet> {
AliasSet *Forward;
/// All instructions without a specific address in this alias set.
std::vector<AssertingVH<Instruction> > UnknownInsts;
/// In rare cases this vector can have a null'ed out WeakVH
/// instances (can happen if some other loop pass deletes an
/// instruction in this list).
std::vector<WeakVH> UnknownInsts;
/// Number of nodes pointing to this AliasSet plus the number of AliasSets
/// forwarding to it.
@ -171,7 +174,7 @@ class AliasSet : public ilist_node<AliasSet> {
Instruction *getUnknownInst(unsigned i) const {
assert(i < UnknownInsts.size());
return UnknownInsts[i];
return cast_or_null<Instruction>(UnknownInsts[i]);
}
public:

View File

@ -31,11 +31,10 @@ namespace llvm {
/// \brief A cache of @llvm.assume calls within a function.
///
/// This cache provides fast lookup of assumptions within a function by caching
/// them and amortizing the cost of scanning for them across all queries. The
/// cache is also conservatively self-updating so that it will never return
/// incorrect results about a function even as the function is being mutated.
/// However, flushing the cache and rebuilding it (or explicitly updating it)
/// may allow it to discover new assumptions.
/// them and amortizing the cost of scanning for them across all queries. Passes
/// that create new assumptions are required to call registerAssumption() to
/// register any new @llvm.assume calls that they create. Deletions of
/// @llvm.assume calls do not require special handling.
class AssumptionCache {
/// \brief The function for which this cache is handling assumptions.
///
@ -87,6 +86,13 @@ class AssumptionCache {
/// its instructions.
AssumptionCache(Function &F) : F(F), Scanned(false) {}
/// This cache is designed to be self-updating and so it should never be
/// invalidated.
bool invalidate(Function &, const PreservedAnalyses &,
FunctionAnalysisManager::Invalidator &) {
return false;
}
/// \brief Add an @llvm.assume intrinsic to this function's cache.
///
/// The call passed in must be an instruction within this function and must
@ -196,7 +202,10 @@ class AssumptionCacheTracker : public ImmutablePass {
AssumptionCacheTracker();
~AssumptionCacheTracker() override;
void releaseMemory() override { AssumptionCaches.shrink_and_clear(); }
void releaseMemory() override {
verifyAnalysis();
AssumptionCaches.shrink_and_clear();
}
void verifyAnalysis() const override;
bool doFinalization(Module &) override {

View File

@ -233,6 +233,24 @@ FunctionPass *createBasicAAWrapperPass();
/// populated to the best of our ability for a particular function when inside
/// of a \c ModulePass or a \c CallGraphSCCPass.
BasicAAResult createLegacyPMBasicAAResult(Pass &P, Function &F);
/// This class is a functor to be used in legacy module or SCC passes for
/// computing AA results for a function. We store the results in fields so that
/// they live long enough to be queried, but we re-use them each time.
class LegacyAARGetter {
Pass &P;
Optional<BasicAAResult> BAR;
Optional<AAResults> AAR;
public:
LegacyAARGetter(Pass &P) : P(P) {}
AAResults &operator()(Function &F) {
BAR.emplace(createLegacyPMBasicAAResult(P, F));
AAR.emplace(createLegacyPMAAResults(P, F, *BAR));
return *AAR;
}
};
}
#endif

View File

@ -45,6 +45,10 @@ class BlockFrequencyInfo {
~BlockFrequencyInfo();
/// Handle invalidation explicitly.
bool invalidate(Function &F, const PreservedAnalyses &PA,
FunctionAnalysisManager::Invalidator &);
const Function *getFunction() const;
const BranchProbabilityInfo *getBPI() const;
void view() const;
@ -69,6 +73,12 @@ class BlockFrequencyInfo {
// Set the frequency of the given basic block.
void setBlockFreq(const BasicBlock *BB, uint64_t Freq);
/// Set the frequency of \p ReferenceBB to \p Freq and scale the frequencies
/// of the blocks in \p BlocksToScale such that their frequencies relative
/// to \p ReferenceBB remain unchanged.
void setBlockFreqAndScale(const BasicBlock *ReferenceBB, uint64_t Freq,
SmallPtrSetImpl<BasicBlock *> &BlocksToScale);
/// calculate - compute block frequency info for the given function.
void calculate(const Function &F, const BranchProbabilityInfo &BPI,
const LoopInfo &LI);

View File

@ -1291,11 +1291,14 @@ struct BFIDOTGraphTraitsBase : public DefaultDOTGraphTraits {
}
std::string getNodeLabel(NodeRef Node, const BlockFrequencyInfoT *Graph,
GVDAGType GType) {
GVDAGType GType, int layout_order = -1) {
std::string Result;
raw_string_ostream OS(Result);
OS << Node->getName().str() << " : ";
if (layout_order != -1)
OS << Node->getName() << "[" << layout_order << "] : ";
else
OS << Node->getName() << " : ";
switch (GType) {
case GVDT_Fraction:
Graph->printBlockFreq(OS, Node);

View File

@ -164,6 +164,8 @@ class BranchProbabilityInfo {
/// \brief Track the set of blocks that always lead to a cold call.
SmallPtrSet<const BasicBlock *, 16> PostDominatedByColdCall;
void updatePostDominatedByUnreachable(const BasicBlock *BB);
void updatePostDominatedByColdCall(const BasicBlock *BB);
bool calcUnreachableHeuristics(const BasicBlock *BB);
bool calcMetadataWeights(const BasicBlock *BB);
bool calcColdCallHeuristics(const BasicBlock *BB);

View File

@ -140,8 +140,7 @@ struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits {
std::string Str;
raw_string_ostream OS(Str);
SwitchInst::ConstCaseIt Case =
SwitchInst::ConstCaseIt::fromSuccessorIndex(SI, SuccNo);
auto Case = *SwitchInst::ConstCaseIt::fromSuccessorIndex(SI, SuccNo);
OS << Case.getCaseValue()->getValue();
return OS.str();
}

View File

@ -334,6 +334,7 @@ class ModuleToPostOrderCGSCCPassAdaptor
InvalidSCCSet, nullptr, nullptr};
PreservedAnalyses PA = PreservedAnalyses::all();
CG.buildRefSCCs();
for (auto RCI = CG.postorder_ref_scc_begin(),
RCE = CG.postorder_ref_scc_end();
RCI != RCE;) {

View File

@ -272,7 +272,7 @@ class CallGraphNode {
private:
friend class CallGraph;
AssertingVH<Function> F;
Function *F;
std::vector<CallRecord> CalledFunctions;

View File

@ -100,6 +100,12 @@ Constant *ConstantFoldExtractValueInstruction(Constant *Agg,
/// successful; if not, null is returned.
Constant *ConstantFoldExtractElementInstruction(Constant *Val, Constant *Idx);
/// \brief Attempt to constant fold a shufflevector instruction with the
/// specified operands and indices. The constant result is returned if
/// successful; if not, null is returned.
Constant *ConstantFoldShuffleVectorInstruction(Constant *V1, Constant *V2,
Constant *Mask);
/// ConstantFoldLoadFromConstPtr - Return the value that a load from C would
/// produce if it is constant and determinable. If this is not determinable,
/// return null.

View File

@ -141,6 +141,10 @@ class DominanceFrontier : public ForwardDominanceFrontierBase<BasicBlock> {
typedef DominanceFrontierBase<BasicBlock>::DomSetType DomSetType;
typedef DominanceFrontierBase<BasicBlock>::iterator iterator;
typedef DominanceFrontierBase<BasicBlock>::const_iterator const_iterator;
/// Handle invalidation explicitly.
bool invalidate(Function &F, const PreservedAnalyses &PA,
FunctionAnalysisManager::Invalidator &);
};
class DominanceFrontierWrapperPass : public FunctionPass {

View File

@ -21,16 +21,8 @@ struct PGOIndirectCallSiteVisitor
PGOIndirectCallSiteVisitor() {}
void visitCallSite(CallSite CS) {
if (CS.getCalledFunction() || !CS.getCalledValue())
return;
Instruction *I = CS.getInstruction();
if (CallInst *CI = dyn_cast<CallInst>(I)) {
if (CI->isInlineAsm())
return;
}
if (isa<Constant>(CS.getCalledValue()))
return;
IndirectCallInsts.push_back(I);
if (CS.isIndirectCall())
IndirectCallInsts.push_back(CS.getInstruction());
}
};

View File

@ -21,6 +21,7 @@
namespace llvm {
class AssumptionCacheTracker;
class BlockFrequencyInfo;
class CallSite;
class DataLayout;
class Function;
@ -137,6 +138,9 @@ struct InlineParams {
/// Threshold to use when the callsite is considered hot.
Optional<int> HotCallSiteThreshold;
/// Threshold to use when the callsite is considered cold.
Optional<int> ColdCallSiteThreshold;
};
/// Generate the parameters to tune the inline cost analysis based only on the
@ -171,6 +175,7 @@ InlineCost
getInlineCost(CallSite CS, const InlineParams &Params,
TargetTransformInfo &CalleeTTI,
std::function<AssumptionCache &(Function &)> &GetAssumptionCache,
Optional<function_ref<BlockFrequencyInfo &(Function &)>> GetBFI,
ProfileSummaryInfo *PSI);
/// \brief Get an InlineCost with the callee explicitly specified.
@ -182,6 +187,7 @@ InlineCost
getInlineCost(CallSite CS, Function *Callee, const InlineParams &Params,
TargetTransformInfo &CalleeTTI,
std::function<AssumptionCache &(Function &)> &GetAssumptionCache,
Optional<function_ref<BlockFrequencyInfo &(Function &)>> GetBFI,
ProfileSummaryInfo *PSI);
/// \brief Minimal filter to detect invalid constructs for inlining.

View File

@ -42,6 +42,7 @@ namespace llvm {
class Instruction;
class DataLayout;
class FastMathFlags;
class OptimizationRemarkEmitter;
class TargetLibraryInfo;
class Type;
class Value;
@ -246,6 +247,14 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// Given operands for a ShuffleVectorInst, fold the result or return null.
Value *SimplifyShuffleVectorInst(Value *Op0, Value *Op1, Constant *Mask,
Type *RetTy, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
//=== Helper functions for higher up the class hierarchy.
@ -296,7 +305,8 @@ namespace llvm {
Value *SimplifyInstruction(Instruction *I, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr);
AssumptionCache *AC = nullptr,
OptimizationRemarkEmitter *ORE = nullptr);
/// Replace all uses of 'I' with 'SimpleV' and simplify the uses recursively.
///

View File

@ -9,7 +9,7 @@
//
// This is an alternative analysis pass to BlockFrequencyInfoWrapperPass. The
// difference is that with this pass the block frequencies are not computed when
// the analysis pass is executed but rather when the BFI results is explicitly
// the analysis pass is executed but rather when the BFI result is explicitly
// requested by the analysis client.
//
//===----------------------------------------------------------------------===//
@ -27,10 +27,58 @@ class BranchProbabilityInfo;
class Function;
class LoopInfo;
/// Wraps a BFI to allow lazy computation of the block frequencies.
///
/// A pass that only conditionally uses BFI can uncondtionally require the
/// analysis without paying for the overhead if BFI doesn't end up being used.
template <typename FunctionT, typename BranchProbabilityInfoPassT,
typename LoopInfoT, typename BlockFrequencyInfoT>
class LazyBlockFrequencyInfo {
public:
LazyBlockFrequencyInfo()
: Calculated(false), F(nullptr), BPIPass(nullptr), LI(nullptr) {}
/// Set up the per-function input.
void setAnalysis(const FunctionT *F, BranchProbabilityInfoPassT *BPIPass,
const LoopInfoT *LI) {
this->F = F;
this->BPIPass = BPIPass;
this->LI = LI;
}
/// Retrieve the BFI with the block frequencies computed.
BlockFrequencyInfoT &getCalculated() {
if (!Calculated) {
assert(F && BPIPass && LI && "call setAnalysis");
BFI.calculate(
*F, BPIPassTrait<BranchProbabilityInfoPassT>::getBPI(BPIPass), *LI);
Calculated = true;
}
return BFI;
}
const BlockFrequencyInfoT &getCalculated() const {
return const_cast<LazyBlockFrequencyInfo *>(this)->getCalculated();
}
void releaseMemory() {
BFI.releaseMemory();
Calculated = false;
setAnalysis(nullptr, nullptr, nullptr);
}
private:
BlockFrequencyInfoT BFI;
bool Calculated;
const FunctionT *F;
BranchProbabilityInfoPassT *BPIPass;
const LoopInfoT *LI;
};
/// \brief This is an alternative analysis pass to
/// BlockFrequencyInfoWrapperPass. The difference is that with this pass the
/// block frequencies are not computed when the analysis pass is executed but
/// rather when the BFI results is explicitly requested by the analysis client.
/// rather when the BFI result is explicitly requested by the analysis client.
///
/// There are some additional requirements for any client pass that wants to use
/// the analysis:
@ -49,54 +97,12 @@ class LoopInfo;
///
/// Note that it is expected that we wouldn't need this functionality for the
/// new PM since with the new PM, analyses are executed on demand.
class LazyBlockFrequencyInfoPass : public FunctionPass {
/// Wraps a BFI to allow lazy computation of the block frequencies.
///
/// A pass that only conditionally uses BFI can uncondtionally require the
/// analysis without paying for the overhead if BFI doesn't end up being used.
class LazyBlockFrequencyInfo {
public:
LazyBlockFrequencyInfo()
: Calculated(false), F(nullptr), BPIPass(nullptr), LI(nullptr) {}
/// Set up the per-function input.
void setAnalysis(const Function *F, LazyBranchProbabilityInfoPass *BPIPass,
const LoopInfo *LI) {
this->F = F;
this->BPIPass = BPIPass;
this->LI = LI;
}
/// Retrieve the BFI with the block frequencies computed.
BlockFrequencyInfo &getCalculated() {
if (!Calculated) {
assert(F && BPIPass && LI && "call setAnalysis");
BFI.calculate(*F, BPIPass->getBPI(), *LI);
Calculated = true;
}
return BFI;
}
const BlockFrequencyInfo &getCalculated() const {
return const_cast<LazyBlockFrequencyInfo *>(this)->getCalculated();
}
void releaseMemory() {
BFI.releaseMemory();
Calculated = false;
setAnalysis(nullptr, nullptr, nullptr);
}
private:
BlockFrequencyInfo BFI;
bool Calculated;
const Function *F;
LazyBranchProbabilityInfoPass *BPIPass;
const LoopInfo *LI;
};
LazyBlockFrequencyInfo LBFI;
private:
LazyBlockFrequencyInfo<Function, LazyBranchProbabilityInfoPass, LoopInfo,
BlockFrequencyInfo>
LBFI;
public:
static char ID;

View File

@ -105,5 +105,17 @@ class LazyBranchProbabilityInfoPass : public FunctionPass {
/// \brief Helper for client passes to initialize dependent passes for LBPI.
void initializeLazyBPIPassPass(PassRegistry &Registry);
/// \brief Simple trait class that provides a mapping between BPI passes and the
/// corresponding BPInfo.
template <typename PassT> struct BPIPassTrait {
static PassT &getBPI(PassT *P) { return *P; }
};
template <> struct BPIPassTrait<LazyBranchProbabilityInfoPass> {
static BranchProbabilityInfo &getBPI(LazyBranchProbabilityInfoPass *P) {
return P->getBPI();
}
};
}
#endif

View File

@ -106,6 +106,7 @@ class raw_ostream;
class LazyCallGraph {
public:
class Node;
class EdgeSequence;
class SCC;
class RefSCC;
class edge_iterator;
@ -121,16 +122,6 @@ class LazyCallGraph {
/// inherently reference edges, and so the reference graph forms a superset
/// of the formal call graph.
///
/// Furthermore, edges also may point to raw \c Function objects when those
/// functions have not been scanned and incorporated into the graph (yet).
/// This is one of the primary ways in which the graph can be lazy. When
/// functions are scanned and fully incorporated into the graph, all of the
/// edges referencing them are updated to point to the graph \c Node objects
/// instead of to the raw \c Function objects. This class even provides
/// methods to trigger this scan on-demand by attempting to get the target
/// node of the graph and providing a reference back to the graph in order to
/// lazily build it if necessary.
///
/// All of these forms of edges are fundamentally represented as outgoing
/// edges. The edges are stored in the source node and point at the target
/// node. This allows the edge structure itself to be a very compact data
@ -141,7 +132,6 @@ class LazyCallGraph {
enum Kind : bool { Ref = false, Call = true };
Edge();
explicit Edge(Function &F, Kind K);
explicit Edge(Node &N, Kind K);
/// Test whether the edge is null.
@ -158,51 +148,218 @@ class LazyCallGraph {
/// This requires that the edge is not null.
bool isCall() const;
/// Get the call graph node referenced by this edge.
///
/// This requires that the edge is not null.
Node &getNode() const;
/// Get the function referenced by this edge.
///
/// This requires that the edge is not null, but will succeed whether we
/// have built a graph node for the function yet or not.
/// This requires that the edge is not null.
Function &getFunction() const;
/// Get the call graph node referenced by this edge if one exists.
///
/// This requires that the edge is not null. If we have built a graph node
/// for the function this edge points to, this will return that node,
/// otherwise it will return null.
Node *getNode() const;
/// Get the call graph node for this edge, building it if necessary.
///
/// This requires that the edge is not null. If we have not yet built
/// a graph node for the function this edge points to, this will first ask
/// the graph to build that node, inserting it into all the relevant
/// structures.
Node &getNode(LazyCallGraph &G);
private:
friend class LazyCallGraph::Node;
friend class LazyCallGraph::EdgeSequence;
friend class LazyCallGraph::RefSCC;
PointerIntPair<PointerUnion<Function *, Node *>, 1, Kind> Value;
PointerIntPair<Node *, 1, Kind> Value;
void setKind(Kind K) { Value.setInt(K); }
};
typedef SmallVector<Edge, 4> EdgeVectorT;
typedef SmallVectorImpl<Edge> EdgeVectorImplT;
/// The edge sequence object.
///
/// This typically exists entirely within the node but is exposed as
/// a separate type because a node doesn't initially have edges. An explicit
/// population step is required to produce this sequence at first and it is
/// then cached in the node. It is also used to represent edges entering the
/// graph from outside the module to model the graph's roots.
///
/// The sequence itself both iterable and indexable. The indexes remain
/// stable even as the sequence mutates (including removal).
class EdgeSequence {
friend class LazyCallGraph;
friend class LazyCallGraph::Node;
friend class LazyCallGraph::RefSCC;
typedef SmallVector<Edge, 4> VectorT;
typedef SmallVectorImpl<Edge> VectorImplT;
public:
/// An iterator used for the edges to both entry nodes and child nodes.
class iterator
: public iterator_adaptor_base<iterator, VectorImplT::iterator,
std::forward_iterator_tag> {
friend class LazyCallGraph;
friend class LazyCallGraph::Node;
VectorImplT::iterator E;
// Build the iterator for a specific position in the edge list.
iterator(VectorImplT::iterator BaseI, VectorImplT::iterator E)
: iterator_adaptor_base(BaseI), E(E) {
while (I != E && !*I)
++I;
}
public:
iterator() {}
using iterator_adaptor_base::operator++;
iterator &operator++() {
do {
++I;
} while (I != E && !*I);
return *this;
}
};
/// An iterator over specifically call edges.
///
/// This has the same iteration properties as the \c iterator, but
/// restricts itself to edges which represent actual calls.
class call_iterator
: public iterator_adaptor_base<call_iterator, VectorImplT::iterator,
std::forward_iterator_tag> {
friend class LazyCallGraph;
friend class LazyCallGraph::Node;
VectorImplT::iterator E;
/// Advance the iterator to the next valid, call edge.
void advanceToNextEdge() {
while (I != E && (!*I || !I->isCall()))
++I;
}
// Build the iterator for a specific position in the edge list.
call_iterator(VectorImplT::iterator BaseI, VectorImplT::iterator E)
: iterator_adaptor_base(BaseI), E(E) {
advanceToNextEdge();
}
public:
call_iterator() {}
using iterator_adaptor_base::operator++;
call_iterator &operator++() {
++I;
advanceToNextEdge();
return *this;
}
};
iterator begin() { return iterator(Edges.begin(), Edges.end()); }
iterator end() { return iterator(Edges.end(), Edges.end()); }
Edge &operator[](int i) { return Edges[i]; }
Edge &operator[](Node &N) {
assert(EdgeIndexMap.find(&N) != EdgeIndexMap.end() && "No such edge!");
return Edges[EdgeIndexMap.find(&N)->second];
}
Edge *lookup(Node &N) {
auto EI = EdgeIndexMap.find(&N);
return EI != EdgeIndexMap.end() ? &Edges[EI->second] : nullptr;
}
call_iterator call_begin() {
return call_iterator(Edges.begin(), Edges.end());
}
call_iterator call_end() { return call_iterator(Edges.end(), Edges.end()); }
iterator_range<call_iterator> calls() {
return make_range(call_begin(), call_end());
}
bool empty() {
for (auto &E : Edges)
if (E)
return false;
return true;
}
private:
VectorT Edges;
DenseMap<Node *, int> EdgeIndexMap;
EdgeSequence() = default;
/// Internal helper to insert an edge to a node.
void insertEdgeInternal(Node &ChildN, Edge::Kind EK);
/// Internal helper to change an edge kind.
void setEdgeKind(Node &ChildN, Edge::Kind EK);
/// Internal helper to remove the edge to the given function.
bool removeEdgeInternal(Node &ChildN);
/// Internal helper to replace an edge key with a new one.
///
/// This should be used when the function for a particular node in the
/// graph gets replaced and we are updating all of the edges to that node
/// to use the new function as the key.
void replaceEdgeKey(Function &OldTarget, Function &NewTarget);
};
/// A node in the call graph.
///
/// This represents a single node. It's primary roles are to cache the list of
/// callees, de-duplicate and provide fast testing of whether a function is
/// a callee, and facilitate iteration of child nodes in the graph.
///
/// The node works much like an optional in order to lazily populate the
/// edges of each node. Until populated, there are no edges. Once populated,
/// you can access the edges by dereferencing the node or using the `->`
/// operator as if the node was an `Optional<EdgeSequence>`.
class Node {
friend class LazyCallGraph;
friend class LazyCallGraph::SCC;
friend class LazyCallGraph::RefSCC;
public:
LazyCallGraph &getGraph() const { return *G; }
Function &getFunction() const { return *F; }
StringRef getName() const { return F->getName(); }
/// Equality is defined as address equality.
bool operator==(const Node &N) const { return this == &N; }
bool operator!=(const Node &N) const { return !operator==(N); }
/// Tests whether the node has been populated with edges.
operator bool() const { return Edges.hasValue(); }
// We allow accessing the edges by dereferencing or using the arrow
// operator, essentially wrapping the internal optional.
EdgeSequence &operator*() const {
// Rip const off because the node itself isn't changing here.
return const_cast<EdgeSequence &>(*Edges);
}
EdgeSequence *operator->() const { return &**this; }
/// Populate the edges of this node if necessary.
///
/// The first time this is called it will populate the edges for this node
/// in the graph. It does this by scanning the underlying function, so once
/// this is done, any changes to that function must be explicitly reflected
/// in updates to the graph.
///
/// \returns the populated \c EdgeSequence to simplify walking it.
///
/// This will not update or re-scan anything if called repeatedly. Instead,
/// the edge sequence is cached and returned immediately on subsequent
/// calls.
EdgeSequence &populate() {
if (Edges)
return *Edges;
return populateSlow();
}
private:
LazyCallGraph *G;
Function &F;
Function *F;
// We provide for the DFS numbering and Tarjan walk lowlink numbers to be
// stored directly within the node. These are both '-1' when nodes are part
@ -210,145 +367,32 @@ class LazyCallGraph {
int DFSNumber;
int LowLink;
mutable EdgeVectorT Edges;
DenseMap<Function *, int> EdgeIndexMap;
Optional<EdgeSequence> Edges;
/// Basic constructor implements the scanning of F into Edges and
/// EdgeIndexMap.
Node(LazyCallGraph &G, Function &F);
Node(LazyCallGraph &G, Function &F)
: G(&G), F(&F), DFSNumber(0), LowLink(0) {}
/// Internal helper to insert an edge to a function.
void insertEdgeInternal(Function &ChildF, Edge::Kind EK);
/// Implementation of the scan when populating.
EdgeSequence &populateSlow();
/// Internal helper to insert an edge to a node.
void insertEdgeInternal(Node &ChildN, Edge::Kind EK);
/// Internal helper to directly replace the function with a new one.
///
/// This is used to facilitate tranfsormations which need to replace the
/// formal Function object but directly move the body and users from one to
/// the other.
void replaceFunction(Function &NewF);
/// Internal helper to change an edge kind.
void setEdgeKind(Function &ChildF, Edge::Kind EK);
/// Internal helper to remove the edge to the given function.
void removeEdgeInternal(Function &ChildF);
void clear() {
Edges.clear();
EdgeIndexMap.clear();
}
void clear() { Edges.reset(); }
/// Print the name of this node's function.
friend raw_ostream &operator<<(raw_ostream &OS, const Node &N) {
return OS << N.F.getName();
return OS << N.F->getName();
}
/// Dump the name of this node's function to stderr.
void dump() const;
public:
LazyCallGraph &getGraph() const { return *G; }
Function &getFunction() const { return F; }
edge_iterator begin() const {
return edge_iterator(Edges.begin(), Edges.end());
}
edge_iterator end() const { return edge_iterator(Edges.end(), Edges.end()); }
const Edge &operator[](int i) const { return Edges[i]; }
const Edge &operator[](Function &F) const {
assert(EdgeIndexMap.find(&F) != EdgeIndexMap.end() && "No such edge!");
return Edges[EdgeIndexMap.find(&F)->second];
}
const Edge &operator[](Node &N) const { return (*this)[N.getFunction()]; }
const Edge *lookup(Function &F) const {
auto EI = EdgeIndexMap.find(&F);
return EI != EdgeIndexMap.end() ? &Edges[EI->second] : nullptr;
}
call_edge_iterator call_begin() const {
return call_edge_iterator(Edges.begin(), Edges.end());
}
call_edge_iterator call_end() const {
return call_edge_iterator(Edges.end(), Edges.end());
}
iterator_range<call_edge_iterator> calls() const {
return make_range(call_begin(), call_end());
}
/// Equality is defined as address equality.
bool operator==(const Node &N) const { return this == &N; }
bool operator!=(const Node &N) const { return !operator==(N); }
};
/// A lazy iterator used for both the entry nodes and child nodes.
///
/// When this iterator is dereferenced, if not yet available, a function will
/// be scanned for "calls" or uses of functions and its child information
/// will be constructed. All of these results are accumulated and cached in
/// the graph.
class edge_iterator
: public iterator_adaptor_base<edge_iterator, EdgeVectorImplT::iterator,
std::forward_iterator_tag> {
friend class LazyCallGraph;
friend class LazyCallGraph::Node;
EdgeVectorImplT::iterator E;
// Build the iterator for a specific position in the edge list.
edge_iterator(EdgeVectorImplT::iterator BaseI,
EdgeVectorImplT::iterator E)
: iterator_adaptor_base(BaseI), E(E) {
while (I != E && !*I)
++I;
}
public:
edge_iterator() {}
using iterator_adaptor_base::operator++;
edge_iterator &operator++() {
do {
++I;
} while (I != E && !*I);
return *this;
}
};
/// A lazy iterator over specifically call edges.
///
/// This has the same iteration properties as the \c edge_iterator, but
/// restricts itself to edges which represent actual calls.
class call_edge_iterator
: public iterator_adaptor_base<call_edge_iterator,
EdgeVectorImplT::iterator,
std::forward_iterator_tag> {
friend class LazyCallGraph;
friend class LazyCallGraph::Node;
EdgeVectorImplT::iterator E;
/// Advance the iterator to the next valid, call edge.
void advanceToNextEdge() {
while (I != E && (!*I || !I->isCall()))
++I;
}
// Build the iterator for a specific position in the edge list.
call_edge_iterator(EdgeVectorImplT::iterator BaseI,
EdgeVectorImplT::iterator E)
: iterator_adaptor_base(BaseI), E(E) {
advanceToNextEdge();
}
public:
call_edge_iterator() {}
using iterator_adaptor_base::operator++;
call_edge_iterator &operator++() {
++I;
advanceToNextEdge();
return *this;
}
};
/// An SCC of the call graph.
@ -789,19 +833,26 @@ class LazyCallGraph {
/// already existing edges.
void insertTrivialRefEdge(Node &SourceN, Node &TargetN);
/// Directly replace a node's function with a new function.
///
/// This should be used when moving the body and users of a function to
/// a new formal function object but not otherwise changing the call graph
/// structure in any way.
///
/// It requires that the old function in the provided node have zero uses
/// and the new function must have calls and references to it establishing
/// an equivalent graph.
void replaceNodeFunction(Node &N, Function &NewF);
///@}
};
/// A post-order depth-first RefSCC iterator over the call graph.
///
/// This iterator triggers the Tarjan DFS-based formation of the RefSCC (and
/// SCC) DAG for the call graph, walking it lazily in depth-first post-order.
/// That is, it always visits RefSCCs for the target of a reference edge
/// prior to visiting the RefSCC for a source of the edge (when they are in
/// different RefSCCs).
///
/// When forming each RefSCC, the call edges within it are used to form SCCs
/// within it, so iterating this also controls the lazy formation of SCCs.
/// This iterator walks the cached post-order sequence of RefSCCs. However,
/// it trades stability for flexibility. It is restricted to a forward
/// iterator but will survive mutations which insert new RefSCCs and continue
/// to point to the same RefSCC even if it moves in the post-order sequence.
class postorder_ref_scc_iterator
: public iterator_facade_base<postorder_ref_scc_iterator,
std::forward_iterator_tag, RefSCC> {
@ -825,12 +876,9 @@ class LazyCallGraph {
/// populating it if necessary.
static RefSCC *getRC(LazyCallGraph &G, int Index) {
if (Index == (int)G.PostOrderRefSCCs.size())
if (!G.buildNextRefSCCInPostOrder())
// We're at the end.
return nullptr;
// We're at the end.
return nullptr;
assert(Index < (int)G.PostOrderRefSCCs.size() &&
"Built the next post-order RefSCC without growing list!");
return G.PostOrderRefSCCs[Index];
}
@ -859,17 +907,21 @@ class LazyCallGraph {
LazyCallGraph(LazyCallGraph &&G);
LazyCallGraph &operator=(LazyCallGraph &&RHS);
edge_iterator begin() {
return edge_iterator(EntryEdges.begin(), EntryEdges.end());
}
edge_iterator end() {
return edge_iterator(EntryEdges.end(), EntryEdges.end());
}
EdgeSequence::iterator begin() { return EntryEdges.begin(); }
EdgeSequence::iterator end() { return EntryEdges.end(); }
void buildRefSCCs();
postorder_ref_scc_iterator postorder_ref_scc_begin() {
if (!EntryEdges.empty())
assert(!PostOrderRefSCCs.empty() &&
"Must form RefSCCs before iterating them!");
return postorder_ref_scc_iterator(*this);
}
postorder_ref_scc_iterator postorder_ref_scc_end() {
if (!EntryEdges.empty())
assert(!PostOrderRefSCCs.empty() &&
"Must form RefSCCs before iterating them!");
return postorder_ref_scc_iterator(*this,
postorder_ref_scc_iterator::IsAtEndT());
}
@ -920,19 +972,19 @@ class LazyCallGraph {
/// below.
/// Update the call graph after inserting a new edge.
void insertEdge(Node &Caller, Function &Callee, Edge::Kind EK);
void insertEdge(Node &SourceN, Node &TargetN, Edge::Kind EK);
/// Update the call graph after inserting a new edge.
void insertEdge(Function &Caller, Function &Callee, Edge::Kind EK) {
return insertEdge(get(Caller), Callee, EK);
void insertEdge(Function &Source, Function &Target, Edge::Kind EK) {
return insertEdge(get(Source), get(Target), EK);
}
/// Update the call graph after deleting an edge.
void removeEdge(Node &Caller, Function &Callee);
void removeEdge(Node &SourceN, Node &TargetN);
/// Update the call graph after deleting an edge.
void removeEdge(Function &Caller, Function &Callee) {
return removeEdge(get(Caller), Callee);
void removeEdge(Function &Source, Function &Target) {
return removeEdge(get(Source), get(Target));
}
///@}
@ -1013,14 +1065,11 @@ class LazyCallGraph {
/// Maps function->node for fast lookup.
DenseMap<const Function *, Node *> NodeMap;
/// The entry nodes to the graph.
/// The entry edges into the graph.
///
/// These nodes are reachable through "external" means. Put another way, they
/// These edges are from "external" sources. Put another way, they
/// escape at the module scope.
EdgeVectorT EntryEdges;
/// Map of the entry nodes in the graph to their indices in \c EntryEdges.
DenseMap<Function *, int> EntryIndexMap;
EdgeSequence EntryEdges;
/// Allocator that holds all the call graph SCCs.
SpecificBumpPtrAllocator<SCC> SCCBPA;
@ -1045,18 +1094,6 @@ class LazyCallGraph {
/// These are all of the RefSCCs which have no children.
SmallVector<RefSCC *, 4> LeafRefSCCs;
/// Stack of nodes in the DFS walk.
SmallVector<std::pair<Node *, edge_iterator>, 4> DFSStack;
/// Set of entry nodes not-yet-processed into RefSCCs.
SmallVector<Function *, 4> RefSCCEntryNodes;
/// Stack of nodes the DFS has walked but not yet put into a RefSCC.
SmallVector<Node *, 4> PendingRefSCCStack;
/// Counter for the next DFS number to assign.
int NextDFSNumber;
/// Helper to insert a new function, with an already looked-up entry in
/// the NodeMap.
Node &insertInto(Function &F, Node *&MappedN);
@ -1078,6 +1115,23 @@ class LazyCallGraph {
return new (RefSCCBPA.Allocate()) RefSCC(std::forward<Ts>(Args)...);
}
/// Common logic for building SCCs from a sequence of roots.
///
/// This is a very generic implementation of the depth-first walk and SCC
/// formation algorithm. It uses a generic sequence of roots and generic
/// callbacks for each step. This is designed to be used to implement both
/// the RefSCC formation and SCC formation with shared logic.
///
/// Currently this is a relatively naive implementation of Tarjan's DFS
/// algorithm to form the SCCs.
///
/// FIXME: We should consider newer variants such as Nuutila.
template <typename RootsT, typename GetBeginT, typename GetEndT,
typename GetNodeT, typename FormSCCCallbackT>
static void buildGenericSCCs(RootsT &&Roots, GetBeginT &&GetBegin,
GetEndT &&GetEnd, GetNodeT &&GetNode,
FormSCCCallbackT &&FormSCC);
/// Build the SCCs for a RefSCC out of a list of nodes.
void buildSCCs(RefSCC &RC, node_stack_range Nodes);
@ -1098,22 +1152,12 @@ class LazyCallGraph {
"Index does not point back at RC!");
return IndexIt->second;
}
/// Builds the next node in the post-order RefSCC walk of the call graph and
/// appends it to the \c PostOrderRefSCCs vector.
///
/// Returns true if a new RefSCC was successfully constructed, and false if
/// there are no more RefSCCs to build in the graph.
bool buildNextRefSCCInPostOrder();
};
inline LazyCallGraph::Edge::Edge() : Value() {}
inline LazyCallGraph::Edge::Edge(Function &F, Kind K) : Value(&F, K) {}
inline LazyCallGraph::Edge::Edge(Node &N, Kind K) : Value(&N, K) {}
inline LazyCallGraph::Edge::operator bool() const {
return !Value.getPointer().isNull();
}
inline LazyCallGraph::Edge::operator bool() const { return Value.getPointer(); }
inline LazyCallGraph::Edge::Kind LazyCallGraph::Edge::getKind() const {
assert(*this && "Queried a null edge!");
@ -1125,51 +1169,32 @@ inline bool LazyCallGraph::Edge::isCall() const {
return getKind() == Call;
}
inline LazyCallGraph::Node &LazyCallGraph::Edge::getNode() const {
assert(*this && "Queried a null edge!");
return *Value.getPointer();
}
inline Function &LazyCallGraph::Edge::getFunction() const {
assert(*this && "Queried a null edge!");
auto P = Value.getPointer();
if (auto *F = P.dyn_cast<Function *>())
return *F;
return P.get<Node *>()->getFunction();
}
inline LazyCallGraph::Node *LazyCallGraph::Edge::getNode() const {
assert(*this && "Queried a null edge!");
auto P = Value.getPointer();
if (auto *N = P.dyn_cast<Node *>())
return N;
return nullptr;
}
inline LazyCallGraph::Node &LazyCallGraph::Edge::getNode(LazyCallGraph &G) {
assert(*this && "Queried a null edge!");
auto P = Value.getPointer();
if (auto *N = P.dyn_cast<Node *>())
return *N;
Node &N = G.get(*P.get<Function *>());
Value.setPointer(&N);
return N;
return getNode().getFunction();
}
// Provide GraphTraits specializations for call graphs.
template <> struct GraphTraits<LazyCallGraph::Node *> {
typedef LazyCallGraph::Node *NodeRef;
typedef LazyCallGraph::edge_iterator ChildIteratorType;
typedef LazyCallGraph::EdgeSequence::iterator ChildIteratorType;
static NodeRef getEntryNode(NodeRef N) { return N; }
static ChildIteratorType child_begin(NodeRef N) { return N->begin(); }
static ChildIteratorType child_end(NodeRef N) { return N->end(); }
static ChildIteratorType child_begin(NodeRef N) { return (*N)->begin(); }
static ChildIteratorType child_end(NodeRef N) { return (*N)->end(); }
};
template <> struct GraphTraits<LazyCallGraph *> {
typedef LazyCallGraph::Node *NodeRef;
typedef LazyCallGraph::edge_iterator ChildIteratorType;
typedef LazyCallGraph::EdgeSequence::iterator ChildIteratorType;
static NodeRef getEntryNode(NodeRef N) { return N; }
static ChildIteratorType child_begin(NodeRef N) { return N->begin(); }
static ChildIteratorType child_end(NodeRef N) { return N->end(); }
static ChildIteratorType child_begin(NodeRef N) { return (*N)->begin(); }
static ChildIteratorType child_end(NodeRef N) { return (*N)->end(); }
};
/// An analysis pass which computes the call graph for a module.

View File

@ -32,6 +32,7 @@ namespace llvm {
class LazyValueInfo {
friend class LazyValueInfoWrapperPass;
AssumptionCache *AC = nullptr;
const DataLayout *DL = nullptr;
class TargetLibraryInfo *TLI = nullptr;
DominatorTree *DT = nullptr;
void *PImpl = nullptr;
@ -40,16 +41,17 @@ class LazyValueInfo {
public:
~LazyValueInfo();
LazyValueInfo() {}
LazyValueInfo(AssumptionCache *AC_, TargetLibraryInfo *TLI_,
LazyValueInfo(AssumptionCache *AC_, const DataLayout *DL_, TargetLibraryInfo *TLI_,
DominatorTree *DT_)
: AC(AC_), TLI(TLI_), DT(DT_) {}
: AC(AC_), DL(DL_), TLI(TLI_), DT(DT_) {}
LazyValueInfo(LazyValueInfo &&Arg)
: AC(Arg.AC), TLI(Arg.TLI), DT(Arg.DT), PImpl(Arg.PImpl) {
: AC(Arg.AC), DL(Arg.DL), TLI(Arg.TLI), DT(Arg.DT), PImpl(Arg.PImpl) {
Arg.PImpl = nullptr;
}
LazyValueInfo &operator=(LazyValueInfo &&Arg) {
releaseMemory();
AC = Arg.AC;
DL = Arg.DL;
TLI = Arg.TLI;
DT = Arg.DT;
PImpl = Arg.PImpl;
@ -98,8 +100,15 @@ class LazyValueInfo {
/// Inform the analysis cache that we have erased a block.
void eraseBlock(BasicBlock *BB);
/// Print the \LazyValueInfoCache.
void printCache(Function &F, raw_ostream &OS);
// For old PM pass. Delete once LazyValueInfoWrapperPass is gone.
void releaseMemory();
/// Handle invalidation events in the new pass manager.
bool invalidate(Function &F, const PreservedAnalyses &PA,
FunctionAnalysisManager::Invalidator &Inv);
};
/// \brief Analysis to compute lazy value information.

View File

@ -85,8 +85,37 @@ Value *FindAvailableLoadedValue(LoadInst *Load,
BasicBlock::iterator &ScanFrom,
unsigned MaxInstsToScan = DefMaxInstsToScan,
AliasAnalysis *AA = nullptr,
bool *IsLoadCSE = nullptr);
bool *IsLoadCSE = nullptr,
unsigned *NumScanedInst = nullptr);
/// Scan backwards to see if we have the value of the given pointer available
/// locally within a small number of instructions.
///
/// You can use this function to scan across multiple blocks: after you call
/// this function, if ScanFrom points at the beginning of the block, it's safe
/// to continue scanning the predecessors.
///
/// \param Ptr The pointer we want the load and store to originate from.
/// \param AccessTy The access type of the pointer.
/// \param AtLeastAtomic Are we looking for at-least an atomic load/store ? In
/// case it is false, we can return an atomic or non-atomic load or store. In
/// case it is true, we need to return an atomic load or store.
/// \param ScanBB The basic block to scan.
/// \param [in,out] ScanFrom The location to start scanning from. When this
/// function returns, it points at the last instruction scanned.
/// \param MaxInstsToScan The maximum number of instructions to scan. If this
/// is zero, the whole block will be scanned.
/// \param AA Optional pointer to alias analysis, to make the scan more
/// precise.
/// \param [out] IsLoad Whether the returned value is a load from the same
/// location in memory, as opposed to the value operand of a store.
///
/// \returns The found value, or nullptr if no value is found.
Value *FindAvailablePtrLoadStore(Value *Ptr, Type *AccessTy, bool AtLeastAtomic,
BasicBlock *ScanBB,
BasicBlock::iterator &ScanFrom,
unsigned MaxInstsToScan, AliasAnalysis *AA,
bool *IsLoad, unsigned *NumScanedInst);
}
#endif

View File

@ -38,39 +38,6 @@ class SCEVUnionPredicate;
class LoopAccessInfo;
class OptimizationRemarkEmitter;
/// 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 Loop *TheLoop,
const char *PassName,
OptimizationRemarkEmitter &ORE);
};
/// \brief Collection of parameters shared beetween the Loop Vectorizer and the
/// Loop Access Analysis.
struct VectorizerParams {
@ -126,7 +93,7 @@ struct VectorizerParams {
class MemoryDepChecker {
public:
typedef PointerIntPair<Value *, 1, bool> MemAccessInfo;
typedef SmallPtrSet<MemAccessInfo, 8> MemAccessInfoSet;
typedef SmallVector<MemAccessInfo, 8> MemAccessInfoList;
/// \brief Set of potential dependent memory accesses.
typedef EquivalenceClasses<MemAccessInfo> DepCandidates;
@ -221,7 +188,7 @@ class MemoryDepChecker {
/// \brief Check whether the dependencies between the accesses are safe.
///
/// Only checks sets with elements in \p CheckDeps.
bool areDepsSafe(DepCandidates &AccessSets, MemAccessInfoSet &CheckDeps,
bool areDepsSafe(DepCandidates &AccessSets, MemAccessInfoList &CheckDeps,
const ValueToValueMap &Strides);
/// \brief No memory dependence was encountered that would inhibit

View File

@ -26,7 +26,7 @@
// * etc...
//
// Note that this analysis specifically identifies *Loops* not cycles or SCCs
// in the CFG. There can be strongly connected compontents in the CFG which
// in the CFG. There can be strongly connected components in the CFG which
// this analysis will not recognize and that will not be represented by a Loop
// instance. In particular, a Loop might be inside such a non-loop SCC, or a
// non-loop SCC might contain a sub-SCC which is a Loop.
@ -364,7 +364,7 @@ extern template class LoopBase<BasicBlock, Loop>;
/// Represents a single loop in the control flow graph. Note that not all SCCs
/// in the CFG are neccessarily loops.
/// in the CFG are necessarily loops.
class Loop : public LoopBase<BasicBlock, Loop> {
public:
/// \brief A range representing the start and end location of a loop.
@ -469,7 +469,7 @@ class Loop : public LoopBase<BasicBlock, Loop> {
/// the loop that branches to the loop header.
///
/// The LoopID metadata node should have one or more operands and the first
/// operand should should be the node itself.
/// operand should be the node itself.
void setLoopID(MDNode *LoopID) const;
/// Return true if no exit block for the loop has a predecessor that is
@ -478,7 +478,8 @@ class Loop : public LoopBase<BasicBlock, Loop> {
/// Return all unique successor blocks of this loop.
/// These are the blocks _outside of the current loop_ which are branched to.
/// This assumes that loop exits are in canonical form.
/// This assumes that loop exits are in canonical form, i.e. all exits are
/// dedicated exits.
void getUniqueExitBlocks(SmallVectorImpl<BasicBlock *> &ExitBlocks) const;
/// If getUniqueExitBlocks would return exactly one block, return that block.
@ -570,6 +571,23 @@ class LoopInfoBase {
reverse_iterator rend() const { return TopLevelLoops.rend(); }
bool empty() const { return TopLevelLoops.empty(); }
/// Return all of the loops in the function in preorder across the loop
/// nests, with siblings in forward program order.
///
/// Note that because loops form a forest of trees, preorder is equivalent to
/// reverse postorder.
SmallVector<LoopT *, 4> getLoopsInPreorder();
/// Return all of the loops in the function in preorder across the loop
/// nests, with siblings in *reverse* program order.
///
/// Note that because loops form a forest of trees, preorder is equivalent to
/// reverse postorder.
///
/// Also note that this is *not* a reverse preorder. Only the siblings are in
/// reverse program order.
SmallVector<LoopT *, 4> getLoopsInReverseSiblingPreorder();
/// 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.
LoopT *getLoopFor(const BlockT *BB) const { return BBMap.lookup(BB); }
@ -682,6 +700,10 @@ class LoopInfo : public LoopInfoBase<BasicBlock, Loop> {
return *this;
}
/// Handle invalidation explicitly.
bool invalidate(Function &F, const PreservedAnalyses &PA,
FunctionAnalysisManager::Invalidator &);
// Most of the public interface is provided via LoopInfoBase.
/// Update LoopInfo after removing the last backedge from a loop. This updates

View File

@ -507,6 +507,55 @@ analyze(const DominatorTreeBase<BlockT> &DomTree) {
DFS.traverse(DomRoot->getBlock());
}
template <class BlockT, class LoopT>
SmallVector<LoopT *, 4> LoopInfoBase<BlockT, LoopT>::getLoopsInPreorder() {
SmallVector<LoopT *, 4> PreOrderLoops, PreOrderWorklist;
// The outer-most loop actually goes into the result in the same relative
// order as we walk it. But LoopInfo stores the top level loops in reverse
// program order so for here we reverse it to get forward program order.
// FIXME: If we change the order of LoopInfo we will want to remove the
// reverse here.
for (LoopT *RootL : reverse(*this)) {
assert(PreOrderWorklist.empty() &&
"Must start with an empty preorder walk worklist.");
PreOrderWorklist.push_back(RootL);
do {
LoopT *L = PreOrderWorklist.pop_back_val();
// Sub-loops are stored in forward program order, but will process the
// worklist backwards so append them in reverse order.
PreOrderWorklist.append(L->rbegin(), L->rend());
PreOrderLoops.push_back(L);
} while (!PreOrderWorklist.empty());
}
return PreOrderLoops;
}
template <class BlockT, class LoopT>
SmallVector<LoopT *, 4>
LoopInfoBase<BlockT, LoopT>::getLoopsInReverseSiblingPreorder() {
SmallVector<LoopT *, 4> PreOrderLoops, PreOrderWorklist;
// The outer-most loop actually goes into the result in the same relative
// order as we walk it. LoopInfo stores the top level loops in reverse
// program order so we walk in order here.
// FIXME: If we change the order of LoopInfo we will want to add a reverse
// here.
for (LoopT *RootL : *this) {
assert(PreOrderWorklist.empty() &&
"Must start with an empty preorder walk worklist.");
PreOrderWorklist.push_back(RootL);
do {
LoopT *L = PreOrderWorklist.pop_back_val();
// Sub-loops are stored in forward program order, but will process the
// worklist backwards so we can just append them in order.
PreOrderWorklist.append(L->begin(), L->end());
PreOrderLoops.push_back(L);
} while (!PreOrderWorklist.empty());
}
return PreOrderLoops;
}
// Debugging
template<class BlockT, class LoopT>
void LoopInfoBase<BlockT, LoopT>::print(raw_ostream &OS) const {
@ -528,15 +577,48 @@ bool compareVectors(std::vector<T> &BB1, std::vector<T> &BB2) {
}
template <class BlockT, class LoopT>
static void
addInnerLoopsToHeadersMap(DenseMap<BlockT *, const LoopT *> &LoopHeaders,
const LoopInfoBase<BlockT, LoopT> &LI,
const LoopT &L) {
void addInnerLoopsToHeadersMap(DenseMap<BlockT *, const LoopT *> &LoopHeaders,
const LoopInfoBase<BlockT, LoopT> &LI,
const LoopT &L) {
LoopHeaders[L.getHeader()] = &L;
for (LoopT *SL : L)
addInnerLoopsToHeadersMap(LoopHeaders, LI, *SL);
}
#ifndef NDEBUG
template <class BlockT, class LoopT>
static void compareLoops(const LoopT *L, const LoopT *OtherL,
DenseMap<BlockT *, const LoopT *> &OtherLoopHeaders) {
BlockT *H = L->getHeader();
BlockT *OtherH = OtherL->getHeader();
assert(H == OtherH &&
"Mismatched headers even though found in the same map entry!");
assert(L->getLoopDepth() == OtherL->getLoopDepth() &&
"Mismatched loop depth!");
const LoopT *ParentL = L, *OtherParentL = OtherL;
do {
assert(ParentL->getHeader() == OtherParentL->getHeader() &&
"Mismatched parent loop headers!");
ParentL = ParentL->getParentLoop();
OtherParentL = OtherParentL->getParentLoop();
} while (ParentL);
for (const LoopT *SubL : *L) {
BlockT *SubH = SubL->getHeader();
const LoopT *OtherSubL = OtherLoopHeaders.lookup(SubH);
assert(OtherSubL && "Inner loop is missing in computed loop info!");
OtherLoopHeaders.erase(SubH);
compareLoops(SubL, OtherSubL, OtherLoopHeaders);
}
std::vector<BlockT *> BBs = L->getBlocks();
std::vector<BlockT *> OtherBBs = OtherL->getBlocks();
assert(compareVectors(BBs, OtherBBs) &&
"Mismatched basic blocks in the loops!");
}
#endif
template <class BlockT, class LoopT>
void LoopInfoBase<BlockT, LoopT>::verify(
const DominatorTreeBase<BlockT> &DomTree) const {
@ -559,42 +641,32 @@ void LoopInfoBase<BlockT, LoopT>::verify(
LoopInfoBase<BlockT, LoopT> OtherLI;
OtherLI.analyze(DomTree);
DenseMap<BlockT *, const LoopT *> LoopHeaders1;
DenseMap<BlockT *, const LoopT *> LoopHeaders2;
for (LoopT *L : *this)
addInnerLoopsToHeadersMap(LoopHeaders1, *this, *L);
// Build a map we can use to move from our LI to the computed one. This
// allows us to ignore the particular order in any layer of the loop forest
// while still comparing the structure.
DenseMap<BlockT *, const LoopT *> OtherLoopHeaders;
for (LoopT *L : OtherLI)
addInnerLoopsToHeadersMap(LoopHeaders2, OtherLI, *L);
assert(LoopHeaders1.size() == LoopHeaders2.size() &&
"LoopInfo is incorrect.");
addInnerLoopsToHeadersMap(OtherLoopHeaders, OtherLI, *L);
auto compareLoops = [&](const LoopT *L1, const LoopT *L2) {
BlockT *H1 = L1->getHeader();
BlockT *H2 = L2->getHeader();
if (H1 != H2)
return false;
std::vector<BlockT *> BB1 = L1->getBlocks();
std::vector<BlockT *> BB2 = L2->getBlocks();
if (!compareVectors(BB1, BB2))
return false;
// Walk the top level loops and ensure there is a corresponding top-level
// loop in the computed version and then recursively compare those loop
// nests.
for (LoopT *L : *this) {
BlockT *Header = L->getHeader();
const LoopT *OtherL = OtherLoopHeaders.lookup(Header);
assert(OtherL && "Top level loop is missing in computed loop info!");
// Now that we've matched this loop, erase its header from the map.
OtherLoopHeaders.erase(Header);
// And recursively compare these loops.
compareLoops(L, OtherL, OtherLoopHeaders);
}
std::vector<BlockT *> SubLoopHeaders1;
std::vector<BlockT *> SubLoopHeaders2;
for (LoopT *L : *L1)
SubLoopHeaders1.push_back(L->getHeader());
for (LoopT *L : *L2)
SubLoopHeaders2.push_back(L->getHeader());
if (!compareVectors(SubLoopHeaders1, SubLoopHeaders2))
return false;
return true;
};
for (auto &I : LoopHeaders1) {
BlockT *H = I.first;
bool LoopsMatch = compareLoops(LoopHeaders1[H], LoopHeaders2[H]);
assert(LoopsMatch && "LoopInfo is incorrect.");
// Any remaining entries in the map are loops which were found when computing
// a fresh LoopInfo but not present in the current one.
if (!OtherLoopHeaders.empty()) {
for (const auto &HeaderAndLoop : OtherLoopHeaders)
dbgs() << "Found new loop: " << *HeaderAndLoop.second << "\n";
llvm_unreachable("Found new loops when recomputing LoopInfo!");
}
#endif
}

View File

@ -32,12 +32,6 @@ class TargetLibraryInfo;
class Type;
class Value;
enum class ObjSizeMode {
Exact = 0,
Min = 1,
Max = 2
};
/// \brief Tests if a value is a call or invoke to a library function that
/// allocates or reallocates memory (either malloc, calloc, realloc, or strdup
/// like).
@ -129,17 +123,36 @@ static inline CallInst *isFreeCall(Value *I, const TargetLibraryInfo *TLI) {
// Utility functions to compute size of objects.
//
/// Various options to control the behavior of getObjectSize.
struct ObjectSizeOpts {
/// Controls how we handle conditional statements with unknown conditions.
enum class Mode : uint8_t {
/// Fail to evaluate an unknown condition.
Exact,
/// Evaluate all branches of an unknown condition. If all evaluations
/// succeed, pick the minimum size.
Min,
/// Same as Min, except we pick the maximum size of all of the branches.
Max
};
/// How we want to evaluate this object's size.
Mode EvalMode = Mode::Exact;
/// Whether to round the result up to the alignment of allocas, byval
/// arguments, and global variables.
bool RoundToAlign = false;
/// If this is true, null pointers in address space 0 will be treated as
/// though they can't be evaluated. Otherwise, null is always considered to
/// point to a 0 byte region of memory.
bool NullIsUnknownSize = false;
};
/// \brief Compute the size of the object pointed by Ptr. Returns true and the
/// object size in Size if successful, and false otherwise. In this context, by
/// object we mean the region of memory starting at Ptr to the end of the
/// 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.
/// If Mode is Min or Max the size will be evaluated even if it depends on
/// a condition and corresponding value will be returned (min or max).
bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL,
const TargetLibraryInfo *TLI, bool RoundToAlign = false,
ObjSizeMode Mode = ObjSizeMode::Exact);
const TargetLibraryInfo *TLI, ObjectSizeOpts Opts = {});
/// Try to turn a call to @llvm.objectsize into an integer value of the given
/// Type. Returns null on failure.
@ -160,8 +173,7 @@ class ObjectSizeOffsetVisitor
const DataLayout &DL;
const TargetLibraryInfo *TLI;
bool RoundToAlign;
ObjSizeMode Mode;
ObjectSizeOpts Options;
unsigned IntTyBits;
APInt Zero;
SmallPtrSet<Instruction *, 8> SeenInsts;
@ -174,8 +186,7 @@ class ObjectSizeOffsetVisitor
public:
ObjectSizeOffsetVisitor(const DataLayout &DL, const TargetLibraryInfo *TLI,
LLVMContext &Context, bool RoundToAlign = false,
ObjSizeMode Mode = ObjSizeMode::Exact);
LLVMContext &Context, ObjectSizeOpts Options = {});
SizeOffsetType compute(Value *V);

View File

@ -6,71 +6,71 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// \file
// \brief This file exposes an interface to building/using memory SSA to
// walk memory instructions using a use/def graph.
//
// Memory SSA class builds an SSA form that links together memory access
// instructions such as loads, stores, atomics, and calls. Additionally, it does
// a trivial form of "heap versioning" Every time the memory state changes in
// the program, we generate a new heap version. It generates MemoryDef/Uses/Phis
// that are overlayed on top of the existing instructions.
//
// As a trivial example,
// define i32 @main() #0 {
// entry:
// %call = call noalias i8* @_Znwm(i64 4) #2
// %0 = bitcast i8* %call to i32*
// %call1 = call noalias i8* @_Znwm(i64 4) #2
// %1 = bitcast i8* %call1 to i32*
// store i32 5, i32* %0, align 4
// store i32 7, i32* %1, align 4
// %2 = load i32* %0, align 4
// %3 = load i32* %1, align 4
// %add = add nsw i32 %2, %3
// ret i32 %add
// }
//
// Will become
// define i32 @main() #0 {
// entry:
// ; 1 = MemoryDef(0)
// %call = call noalias i8* @_Znwm(i64 4) #3
// %2 = bitcast i8* %call to i32*
// ; 2 = MemoryDef(1)
// %call1 = call noalias i8* @_Znwm(i64 4) #3
// %4 = bitcast i8* %call1 to i32*
// ; 3 = MemoryDef(2)
// store i32 5, i32* %2, align 4
// ; 4 = MemoryDef(3)
// store i32 7, i32* %4, align 4
// ; MemoryUse(3)
// %7 = load i32* %2, align 4
// ; MemoryUse(4)
// %8 = load i32* %4, align 4
// %add = add nsw i32 %7, %8
// ret i32 %add
// }
//
// Given this form, all the stores that could ever effect the load at %8 can be
// gotten by using the MemoryUse associated with it, and walking from use to def
// until you hit the top of the function.
//
// Each def also has a list of users associated with it, so you can walk from
// both def to users, and users to defs. Note that we disambiguate MemoryUses,
// but not the RHS of MemoryDefs. You can see this above at %7, which would
// otherwise be a MemoryUse(4). Being disambiguated means that for a given
// store, all the MemoryUses on its use lists are may-aliases of that store (but
// the MemoryDefs on its use list may not be).
//
// MemoryDefs are not disambiguated because it would require multiple reaching
// definitions, which would require multiple phis, and multiple memoryaccesses
// per instruction.
///
/// \file
/// \brief This file exposes an interface to building/using memory SSA to
/// walk memory instructions using a use/def graph.
///
/// Memory SSA class builds an SSA form that links together memory access
/// instructions such as loads, stores, atomics, and calls. Additionally, it
/// does a trivial form of "heap versioning" Every time the memory state changes
/// in the program, we generate a new heap version. It generates
/// MemoryDef/Uses/Phis that are overlayed on top of the existing instructions.
///
/// As a trivial example,
/// define i32 @main() #0 {
/// entry:
/// %call = call noalias i8* @_Znwm(i64 4) #2
/// %0 = bitcast i8* %call to i32*
/// %call1 = call noalias i8* @_Znwm(i64 4) #2
/// %1 = bitcast i8* %call1 to i32*
/// store i32 5, i32* %0, align 4
/// store i32 7, i32* %1, align 4
/// %2 = load i32* %0, align 4
/// %3 = load i32* %1, align 4
/// %add = add nsw i32 %2, %3
/// ret i32 %add
/// }
///
/// Will become
/// define i32 @main() #0 {
/// entry:
/// ; 1 = MemoryDef(0)
/// %call = call noalias i8* @_Znwm(i64 4) #3
/// %2 = bitcast i8* %call to i32*
/// ; 2 = MemoryDef(1)
/// %call1 = call noalias i8* @_Znwm(i64 4) #3
/// %4 = bitcast i8* %call1 to i32*
/// ; 3 = MemoryDef(2)
/// store i32 5, i32* %2, align 4
/// ; 4 = MemoryDef(3)
/// store i32 7, i32* %4, align 4
/// ; MemoryUse(3)
/// %7 = load i32* %2, align 4
/// ; MemoryUse(4)
/// %8 = load i32* %4, align 4
/// %add = add nsw i32 %7, %8
/// ret i32 %add
/// }
///
/// Given this form, all the stores that could ever effect the load at %8 can be
/// gotten by using the MemoryUse associated with it, and walking from use to
/// def until you hit the top of the function.
///
/// Each def also has a list of users associated with it, so you can walk from
/// both def to users, and users to defs. Note that we disambiguate MemoryUses,
/// but not the RHS of MemoryDefs. You can see this above at %7, which would
/// otherwise be a MemoryUse(4). Being disambiguated means that for a given
/// store, all the MemoryUses on its use lists are may-aliases of that store
/// (but the MemoryDefs on its use list may not be).
///
/// MemoryDefs are not disambiguated because it would require multiple reaching
/// definitions, which would require multiple phis, and multiple memoryaccesses
/// per instruction.
//===----------------------------------------------------------------------===//
#ifndef LLVM_TRANSFORMS_UTILS_MEMORYSSA_H
#define LLVM_TRANSFORMS_UTILS_MEMORYSSA_H
#ifndef LLVM_ANALYSIS_MEMORYSSA_H
#define LLVM_ANALYSIS_MEMORYSSA_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/GraphTraits.h"
@ -79,6 +79,7 @@
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/ilist_node.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/MemoryLocation.h"
#include "llvm/Analysis/PHITransAddr.h"
@ -91,9 +92,7 @@
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
#include "llvm/Pass.h"
#include "llvm/PassAnalysisSupport.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
#include <cassert>
@ -104,12 +103,16 @@
namespace llvm {
class DominatorTree;
class Function;
class Instruction;
class MemoryAccess;
class LLVMContext;
class raw_ostream;
namespace MSSAHelpers {
struct AllAccessTag {};
struct DefsOnlyTag {};
}
enum {
// Used to signify what the default invalid ID is for MemoryAccess's
// getID()
@ -123,21 +126,30 @@ using const_memoryaccess_def_iterator =
// \brief The base for all memory accesses. All memory accesses in a block are
// linked together using an intrusive list.
class MemoryAccess : public User, public ilist_node<MemoryAccess> {
void *operator new(size_t, unsigned) = delete;
void *operator new(size_t) = delete;
class MemoryAccess
: public User,
public ilist_node<MemoryAccess, ilist_tag<MSSAHelpers::AllAccessTag>>,
public ilist_node<MemoryAccess, ilist_tag<MSSAHelpers::DefsOnlyTag>> {
public:
using AllAccessType =
ilist_node<MemoryAccess, ilist_tag<MSSAHelpers::AllAccessTag>>;
using DefsOnlyType =
ilist_node<MemoryAccess, ilist_tag<MSSAHelpers::DefsOnlyTag>>;
// Methods for support type inquiry through isa, cast, and
// dyn_cast
static inline bool classof(const MemoryAccess *) { return true; }
static inline bool classof(const Value *V) {
unsigned ID = V->getValueID();
return ID == MemoryUseVal || ID == MemoryPhiVal || ID == MemoryDefVal;
}
MemoryAccess(const MemoryAccess &) = delete;
MemoryAccess &operator=(const MemoryAccess &) = delete;
~MemoryAccess() override;
void *operator new(size_t, unsigned) = delete;
void *operator new(size_t) = delete;
BasicBlock *getBlock() const { return Block; }
virtual void print(raw_ostream &OS) const = 0;
@ -155,6 +167,33 @@ class MemoryAccess : public User, public ilist_node<MemoryAccess> {
memoryaccess_def_iterator defs_end();
const_memoryaccess_def_iterator defs_end() const;
/// \brief Get the iterators for the all access list and the defs only list
/// We default to the all access list.
AllAccessType::self_iterator getIterator() {
return this->AllAccessType::getIterator();
}
AllAccessType::const_self_iterator getIterator() const {
return this->AllAccessType::getIterator();
}
AllAccessType::reverse_self_iterator getReverseIterator() {
return this->AllAccessType::getReverseIterator();
}
AllAccessType::const_reverse_self_iterator getReverseIterator() const {
return this->AllAccessType::getReverseIterator();
}
DefsOnlyType::self_iterator getDefsIterator() {
return this->DefsOnlyType::getIterator();
}
DefsOnlyType::const_self_iterator getDefsIterator() const {
return this->DefsOnlyType::getIterator();
}
DefsOnlyType::reverse_self_iterator getReverseDefsIterator() {
return this->DefsOnlyType::getReverseIterator();
}
DefsOnlyType::const_reverse_self_iterator getReverseDefsIterator() const {
return this->DefsOnlyType::getReverseIterator();
}
protected:
friend class MemorySSA;
friend class MemoryUseOrDef;
@ -162,6 +201,10 @@ class MemoryAccess : public User, public ilist_node<MemoryAccess> {
friend class MemoryDef;
friend class MemoryPhi;
/// \brief Used by MemorySSA to change the block of a MemoryAccess when it is
/// moved.
void setBlock(BasicBlock *BB) { Block = BB; }
/// \brief Used for debugging and tracking things about MemoryAccesses.
/// Guaranteed unique among MemoryAccesses, no guarantees otherwise.
virtual unsigned getID() const = 0;
@ -171,8 +214,6 @@ class MemoryAccess : public User, public ilist_node<MemoryAccess> {
: User(Type::getVoidTy(C), Vty, nullptr, NumOperands), Block(BB) {}
private:
MemoryAccess(const MemoryAccess &);
void operator=(const MemoryAccess &);
BasicBlock *Block;
};
@ -189,10 +230,10 @@ inline raw_ostream &operator<<(raw_ostream &OS, const MemoryAccess &MA) {
/// This class should never be instantiated directly; make a MemoryUse or
/// MemoryDef instead.
class MemoryUseOrDef : public MemoryAccess {
public:
void *operator new(size_t, unsigned) = delete;
void *operator new(size_t) = delete;
public:
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess);
/// \brief Get the instruction that this MemoryUse represents.
@ -201,21 +242,36 @@ class MemoryUseOrDef : public MemoryAccess {
/// \brief Get the access that produces the memory state used by this Use.
MemoryAccess *getDefiningAccess() const { return getOperand(0); }
static inline bool classof(const MemoryUseOrDef *) { return true; }
static inline bool classof(const Value *MA) {
return MA->getValueID() == MemoryUseVal || MA->getValueID() == MemoryDefVal;
}
// Sadly, these have to be public because they are needed in some of the
// iterators.
virtual bool isOptimized() const = 0;
virtual MemoryAccess *getOptimized() const = 0;
virtual void setOptimized(MemoryAccess *) = 0;
/// \brief Reset the ID of what this MemoryUse was optimized to, causing it to
/// be rewalked by the walker if necessary.
/// This really should only be called by tests.
virtual void resetOptimized() = 0;
protected:
friend class MemorySSA;
friend class MemorySSAUpdater;
MemoryUseOrDef(LLVMContext &C, MemoryAccess *DMA, unsigned Vty,
Instruction *MI, BasicBlock *BB)
: MemoryAccess(C, Vty, BB, 1), MemoryInst(MI) {
setDefiningAccess(DMA);
}
void setDefiningAccess(MemoryAccess *DMA) { setOperand(0, DMA); }
void setDefiningAccess(MemoryAccess *DMA, bool Optimized = false) {
if (!Optimized) {
setOperand(0, DMA);
return;
}
setOptimized(DMA);
}
private:
Instruction *MemoryInst;
@ -232,35 +288,37 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryUseOrDef, MemoryAccess)
/// MemoryUse's is exactly the set of Instructions for which
/// AliasAnalysis::getModRefInfo returns "Ref".
class MemoryUse final : public MemoryUseOrDef {
void *operator new(size_t, unsigned) = delete;
public:
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess);
// allocate space for exactly one operand
void *operator new(size_t s) { return User::operator new(s, 1); }
MemoryUse(LLVMContext &C, MemoryAccess *DMA, Instruction *MI, BasicBlock *BB)
: MemoryUseOrDef(C, DMA, MemoryUseVal, MI, BB), OptimizedID(0) {}
static inline bool classof(const MemoryUse *) { return true; }
// allocate space for exactly one operand
void *operator new(size_t s) { return User::operator new(s, 1); }
void *operator new(size_t, unsigned) = delete;
static inline bool classof(const Value *MA) {
return MA->getValueID() == MemoryUseVal;
}
void print(raw_ostream &OS) const override;
void setDefiningAccess(MemoryAccess *DMA, bool Optimized = false) {
if (Optimized)
OptimizedID = DMA->getID();
MemoryUseOrDef::setDefiningAccess(DMA);
virtual void setOptimized(MemoryAccess *DMA) override {
OptimizedID = DMA->getID();
setOperand(0, DMA);
}
bool isOptimized() const {
virtual bool isOptimized() const override {
return getDefiningAccess() && OptimizedID == getDefiningAccess()->getID();
}
/// \brief Reset the ID of what this MemoryUse was optimized to, causing it to
/// be rewalked by the walker if necessary.
/// This really should only be called by tests.
void resetOptimized() { OptimizedID = INVALID_MEMORYACCESS_ID; }
virtual MemoryAccess *getOptimized() const override {
return getDefiningAccess();
}
virtual void resetOptimized() override {
OptimizedID = INVALID_MEMORYACCESS_ID;
}
protected:
friend class MemorySSA;
@ -287,23 +345,35 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryUse, MemoryAccess)
/// associated with them. This use points to the nearest reaching
/// MemoryDef/MemoryPhi.
class MemoryDef final : public MemoryUseOrDef {
void *operator new(size_t, unsigned) = delete;
public:
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess);
// allocate space for exactly one operand
void *operator new(size_t s) { return User::operator new(s, 1); }
MemoryDef(LLVMContext &C, MemoryAccess *DMA, Instruction *MI, BasicBlock *BB,
unsigned Ver)
: MemoryUseOrDef(C, DMA, MemoryDefVal, MI, BB), ID(Ver) {}
: MemoryUseOrDef(C, DMA, MemoryDefVal, MI, BB), ID(Ver),
Optimized(nullptr), OptimizedID(INVALID_MEMORYACCESS_ID) {}
// allocate space for exactly one operand
void *operator new(size_t s) { return User::operator new(s, 1); }
void *operator new(size_t, unsigned) = delete;
static inline bool classof(const MemoryDef *) { return true; }
static inline bool classof(const Value *MA) {
return MA->getValueID() == MemoryDefVal;
}
virtual void setOptimized(MemoryAccess *MA) override {
Optimized = MA;
OptimizedID = getDefiningAccess()->getID();
}
virtual MemoryAccess *getOptimized() const override { return Optimized; }
virtual bool isOptimized() const override {
return getOptimized() && getDefiningAccess() &&
OptimizedID == getDefiningAccess()->getID();
}
virtual void resetOptimized() override {
OptimizedID = INVALID_MEMORYACCESS_ID;
}
void print(raw_ostream &OS) const override;
protected:
@ -313,6 +383,8 @@ class MemoryDef final : public MemoryUseOrDef {
private:
const unsigned ID;
MemoryAccess *Optimized;
unsigned int OptimizedID;
};
template <>
@ -352,7 +424,6 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryDef, MemoryAccess)
/// Because MemoryUse's do not generate new definitions, they do not have this
/// issue.
class MemoryPhi final : public MemoryAccess {
void *operator new(size_t, unsigned) = delete;
// allocate space for exactly zero operands
void *operator new(size_t s) { return User::operator new(s); }
@ -365,6 +436,8 @@ class MemoryPhi final : public MemoryAccess {
allocHungoffUses(ReservedSpace);
}
void *operator new(size_t, unsigned) = delete;
// Block iterator interface. This provides access to the list of incoming
// basic blocks, which parallels the list of incoming values.
typedef BasicBlock **block_iterator;
@ -457,7 +530,6 @@ class MemoryPhi final : public MemoryAccess {
return getIncomingValue(Idx);
}
static inline bool classof(const MemoryPhi *) { return true; }
static inline bool classof(const Value *V) {
return V->getValueID() == MemoryPhiVal;
}
@ -466,6 +538,7 @@ class MemoryPhi final : public MemoryAccess {
protected:
friend class MemorySSA;
/// \brief this is more complicated than the generic
/// User::allocHungoffUses, because we have to allocate Uses for the incoming
/// values and pointers to the incoming blocks, all in one allocation.
@ -529,7 +602,14 @@ class MemorySSA {
return LiveOnEntryDef.get();
}
using AccessList = iplist<MemoryAccess>;
// Sadly, iplists, by default, owns and deletes pointers added to the
// list. It's not currently possible to have two iplists for the same type,
// where one owns the pointers, and one does not. This is because the traits
// are per-type, not per-tag. If this ever changes, we should make the
// DefList an iplist.
using AccessList = iplist<MemoryAccess, ilist_tag<MSSAHelpers::AllAccessTag>>;
using DefsList =
simple_ilist<MemoryAccess, ilist_tag<MSSAHelpers::DefsOnlyTag>>;
/// \brief Return the list of MemoryAccess's for a given basic block.
///
@ -538,62 +618,13 @@ class MemorySSA {
return getWritableBlockAccesses(BB);
}
/// \brief Create an empty MemoryPhi in MemorySSA for a given basic block.
/// Only one MemoryPhi for a block exists at a time, so this function will
/// assert if you try to create one where it already exists.
MemoryPhi *createMemoryPhi(BasicBlock *BB);
enum InsertionPlace { Beginning, End };
/// \brief Create a MemoryAccess in MemorySSA at a specified point in a block,
/// with a specified clobbering definition.
/// \brief Return the list of MemoryDef's and MemoryPhi's for a given basic
/// block.
///
/// Returns the new MemoryAccess.
/// This should be called when a memory instruction is created that is being
/// used to replace an existing memory instruction. It will *not* create PHI
/// nodes, or verify the clobbering definition. The insertion place is used
/// solely to determine where in the memoryssa access lists the instruction
/// will be placed. The caller is expected to keep ordering the same as
/// instructions.
/// It will return the new MemoryAccess.
/// Note: If a MemoryAccess already exists for I, this function will make it
/// inaccessible and it *must* have removeMemoryAccess called on it.
MemoryAccess *createMemoryAccessInBB(Instruction *I, MemoryAccess *Definition,
const BasicBlock *BB,
InsertionPlace Point);
/// \brief Create a MemoryAccess in MemorySSA before or after an existing
/// MemoryAccess.
///
/// Returns the new MemoryAccess.
/// This should be called when a memory instruction is created that is being
/// used to replace an existing memory instruction. It will *not* create PHI
/// nodes, or verify the clobbering definition. The clobbering definition
/// must be non-null.
/// Note: If a MemoryAccess already exists for I, this function will make it
/// inaccessible and it *must* have removeMemoryAccess called on it.
MemoryUseOrDef *createMemoryAccessBefore(Instruction *I,
MemoryAccess *Definition,
MemoryUseOrDef *InsertPt);
MemoryUseOrDef *createMemoryAccessAfter(Instruction *I,
MemoryAccess *Definition,
MemoryAccess *InsertPt);
// \brief Splice \p What to just before \p Where.
//
// In order to be efficient, the following conditions must be met:
// - \p Where dominates \p What,
// - All memory accesses in [\p Where, \p What) are no-alias with \p What.
//
// TODO: relax the MemoryDef requirement on Where.
void spliceMemoryAccessAbove(MemoryDef *Where, MemoryUseOrDef *What);
/// \brief Remove a MemoryAccess from MemorySSA, including updating all
/// definitions and uses.
/// This should be called when a memory instruction that has a MemoryAccess
/// associated with it is erased from the program. For example, if a store or
/// load is simply erased (not replaced), removeMemoryAccess should be called
/// on the MemoryAccess for that store/load.
void removeMemoryAccess(MemoryAccess *);
/// This list is not modifiable by the user.
const DefsList *getBlockDefs(const BasicBlock *BB) const {
return getWritableBlockDefs(BB);
}
/// \brief Given two memory accesses in the same basic block, determine
/// whether MemoryAccess \p A dominates MemoryAccess \p B.
@ -611,20 +642,51 @@ class MemorySSA {
/// all uses, uses appear in the right places). This is used by unit tests.
void verifyMemorySSA() const;
/// Used in various insertion functions to specify whether we are talking
/// about the beginning or end of a block.
enum InsertionPlace { Beginning, End };
protected:
// Used by Memory SSA annotater, dumpers, and wrapper pass
friend class MemorySSAAnnotatedWriter;
friend class MemorySSAPrinterLegacyPass;
friend class MemorySSAUpdater;
void verifyDefUses(Function &F) const;
void verifyDomination(Function &F) const;
void verifyOrdering(Function &F) const;
// This is used by the use optimizer class
// This is used by the use optimizer and updater.
AccessList *getWritableBlockAccesses(const BasicBlock *BB) const {
auto It = PerBlockAccesses.find(BB);
return It == PerBlockAccesses.end() ? nullptr : It->second.get();
}
// This is used by the use optimizer and updater.
DefsList *getWritableBlockDefs(const BasicBlock *BB) const {
auto It = PerBlockDefs.find(BB);
return It == PerBlockDefs.end() ? nullptr : It->second.get();
}
// These is used by the updater to perform various internal MemorySSA
// machinsations. They do not always leave the IR in a correct state, and
// relies on the updater to fixup what it breaks, so it is not public.
void moveTo(MemoryUseOrDef *What, BasicBlock *BB, AccessList::iterator Where);
void moveTo(MemoryUseOrDef *What, BasicBlock *BB, InsertionPlace Point);
// Rename the dominator tree branch rooted at BB.
void renamePass(BasicBlock *BB, MemoryAccess *IncomingVal,
SmallPtrSetImpl<BasicBlock *> &Visited) {
renamePass(DT->getNode(BB), IncomingVal, Visited, true, true);
}
void removeFromLookups(MemoryAccess *);
void removeFromLists(MemoryAccess *, bool ShouldDelete = true);
void insertIntoListsForBlock(MemoryAccess *, const BasicBlock *,
InsertionPlace);
void insertIntoListsBefore(MemoryAccess *, const BasicBlock *,
AccessList::iterator);
MemoryUseOrDef *createDefinedAccess(Instruction *, MemoryAccess *);
private:
class CachingWalker;
class OptimizeUses;
@ -635,32 +697,39 @@ class MemorySSA {
void verifyUseInDefs(MemoryAccess *, MemoryAccess *) const;
using AccessMap = DenseMap<const BasicBlock *, std::unique_ptr<AccessList>>;
using DefsMap = DenseMap<const BasicBlock *, std::unique_ptr<DefsList>>;
void
determineInsertionPoint(const SmallPtrSetImpl<BasicBlock *> &DefiningBlocks);
void computeDomLevels(DenseMap<DomTreeNode *, unsigned> &DomLevels);
void markUnreachableAsLiveOnEntry(BasicBlock *BB);
bool dominatesUse(const MemoryAccess *, const MemoryAccess *) const;
MemoryPhi *createMemoryPhi(BasicBlock *BB);
MemoryUseOrDef *createNewAccess(Instruction *);
MemoryUseOrDef *createDefinedAccess(Instruction *, MemoryAccess *);
MemoryAccess *findDominatingDef(BasicBlock *, enum InsertionPlace);
void removeFromLookups(MemoryAccess *);
void placePHINodes(const SmallPtrSetImpl<BasicBlock *> &,
const DenseMap<const BasicBlock *, unsigned int> &);
MemoryAccess *renameBlock(BasicBlock *, MemoryAccess *);
MemoryAccess *renameBlock(BasicBlock *, MemoryAccess *, bool);
void renameSuccessorPhis(BasicBlock *, MemoryAccess *, bool);
void renamePass(DomTreeNode *, MemoryAccess *IncomingVal,
SmallPtrSet<BasicBlock *, 16> &Visited);
SmallPtrSetImpl<BasicBlock *> &Visited,
bool SkipVisited = false, bool RenameAllUses = false);
AccessList *getOrCreateAccessList(const BasicBlock *);
DefsList *getOrCreateDefsList(const BasicBlock *);
void renumberBlock(const BasicBlock *) const;
AliasAnalysis *AA;
DominatorTree *DT;
Function &F;
// Memory SSA mappings
DenseMap<const Value *, MemoryAccess *> ValueToMemoryAccess;
// These two mappings contain the main block to access/def mappings for
// MemorySSA. The list contained in PerBlockAccesses really owns all the
// MemoryAccesses.
// Both maps maintain the invariant that if a block is found in them, the
// corresponding list is not empty, and if a block is not found in them, the
// corresponding list is empty.
AccessMap PerBlockAccesses;
DefsMap PerBlockDefs;
std::unique_ptr<MemoryAccess> LiveOnEntryDef;
// Domination mappings
@ -674,21 +743,33 @@ class MemorySSA {
unsigned NextID;
};
// Internal MemorySSA utils, for use by MemorySSA classes and walkers
class MemorySSAUtil {
protected:
friend class MemorySSAWalker;
friend class GVNHoist;
// This function should not be used by new passes.
static bool defClobbersUseOrDef(MemoryDef *MD, const MemoryUseOrDef *MU,
AliasAnalysis &AA);
};
// This pass does eager building and then printing of MemorySSA. It is used by
// the tests to be able to build, dump, and verify Memory SSA.
class MemorySSAPrinterLegacyPass : public FunctionPass {
public:
MemorySSAPrinterLegacyPass();
static char ID;
bool runOnFunction(Function &) override;
void getAnalysisUsage(AnalysisUsage &AU) const override;
static char ID;
};
/// An analysis that produces \c MemorySSA for a function.
///
class MemorySSAAnalysis : public AnalysisInfoMixin<MemorySSAAnalysis> {
friend AnalysisInfoMixin<MemorySSAAnalysis>;
static AnalysisKey Key;
public:
@ -711,6 +792,7 @@ class MemorySSAPrinterPass : public PassInfoMixin<MemorySSAPrinterPass> {
public:
explicit MemorySSAPrinterPass(raw_ostream &OS) : OS(OS) {}
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
@ -725,6 +807,7 @@ class MemorySSAWrapperPass : public FunctionPass {
MemorySSAWrapperPass();
static char ID;
bool runOnFunction(Function &) override;
void releaseMemory() override;
MemorySSA &getMSSA() { return *MSSA; }
@ -753,7 +836,7 @@ class MemorySSAWrapperPass : public FunctionPass {
class MemorySSAWalker {
public:
MemorySSAWalker(MemorySSA *);
virtual ~MemorySSAWalker() {}
virtual ~MemorySSAWalker() = default;
using MemoryAccessSet = SmallVector<MemoryAccess *, 8>;
@ -825,6 +908,7 @@ class DoNothingMemorySSAWalker final : public MemorySSAWalker {
// Keep the overrides below from hiding the Instruction overload of
// getClobberingMemoryAccess.
using MemorySSAWalker::getClobberingMemoryAccess;
MemoryAccess *getClobberingMemoryAccess(MemoryAccess *) override;
MemoryAccess *getClobberingMemoryAccess(MemoryAccess *,
const MemoryLocation &) override;
@ -843,8 +927,9 @@ class memoryaccess_def_iterator_base
using BaseT = typename memoryaccess_def_iterator_base::iterator_facade_base;
public:
memoryaccess_def_iterator_base(T *Start) : Access(Start), ArgNo(0) {}
memoryaccess_def_iterator_base() : Access(nullptr), ArgNo(0) {}
memoryaccess_def_iterator_base(T *Start) : Access(Start) {}
memoryaccess_def_iterator_base() = default;
bool operator==(const memoryaccess_def_iterator_base &Other) const {
return Access == Other.Access && (!Access || ArgNo == Other.ArgNo);
}
@ -883,8 +968,8 @@ class memoryaccess_def_iterator_base
}
private:
T *Access;
unsigned ArgNo;
T *Access = nullptr;
unsigned ArgNo = 0;
};
inline memoryaccess_def_iterator MemoryAccess::defs_begin() {
@ -947,10 +1032,7 @@ class upward_defs_iterator
fillInCurrentPair();
}
upward_defs_iterator()
: DefIterator(), Location(), OriginalAccess(), WalkingPhi(false) {
CurrentPair.first = nullptr;
}
upward_defs_iterator() { CurrentPair.first = nullptr; }
bool operator==(const upward_defs_iterator &Other) const {
return DefIterator == Other.DefIterator;
@ -995,8 +1077,8 @@ class upward_defs_iterator
MemoryAccessPair CurrentPair;
memoryaccess_def_iterator DefIterator;
MemoryLocation Location;
MemoryAccess *OriginalAccess;
bool WalkingPhi;
MemoryAccess *OriginalAccess = nullptr;
bool WalkingPhi = false;
};
inline upward_defs_iterator upward_defs_begin(const MemoryAccessPair &Pair) {
@ -1005,10 +1087,69 @@ inline upward_defs_iterator upward_defs_begin(const MemoryAccessPair &Pair) {
inline upward_defs_iterator upward_defs_end() { return upward_defs_iterator(); }
// Return true when MD may alias MU, return false otherwise.
bool defClobbersUseOrDef(MemoryDef *MD, const MemoryUseOrDef *MU,
AliasAnalysis &AA);
inline iterator_range<upward_defs_iterator>
upward_defs(const MemoryAccessPair &Pair) {
return make_range(upward_defs_begin(Pair), upward_defs_end());
}
/// Walks the defining accesses of MemoryDefs. Stops after we hit something that
/// has no defining use (e.g. a MemoryPhi or liveOnEntry). Note that, when
/// comparing against a null def_chain_iterator, this will compare equal only
/// after walking said Phi/liveOnEntry.
///
/// The UseOptimizedChain flag specifies whether to walk the clobbering
/// access chain, or all the accesses.
///
/// Normally, MemoryDef are all just def/use linked together, so a def_chain on
/// a MemoryDef will walk all MemoryDefs above it in the program until it hits
/// a phi node. The optimized chain walks the clobbering access of a store.
/// So if you are just trying to find, given a store, what the next
/// thing that would clobber the same memory is, you want the optimized chain.
template <class T, bool UseOptimizedChain = false>
struct def_chain_iterator
: public iterator_facade_base<def_chain_iterator<T, UseOptimizedChain>,
std::forward_iterator_tag, MemoryAccess *> {
def_chain_iterator() : MA(nullptr) {}
def_chain_iterator(T MA) : MA(MA) {}
T operator*() const { return MA; }
def_chain_iterator &operator++() {
// N.B. liveOnEntry has a null defining access.
if (auto *MUD = dyn_cast<MemoryUseOrDef>(MA)) {
if (UseOptimizedChain && MUD->isOptimized())
MA = MUD->getOptimized();
else
MA = MUD->getDefiningAccess();
} else {
MA = nullptr;
}
return *this;
}
bool operator==(const def_chain_iterator &O) const { return MA == O.MA; }
private:
T MA;
};
template <class T>
inline iterator_range<def_chain_iterator<T>>
def_chain(T MA, MemoryAccess *UpTo = nullptr) {
#ifdef EXPENSIVE_CHECKS
assert((!UpTo || find(def_chain(MA), UpTo) != def_chain_iterator<T>()) &&
"UpTo isn't in the def chain!");
#endif
return make_range(def_chain_iterator<T>(MA), def_chain_iterator<T>(UpTo));
}
template <class T>
inline iterator_range<def_chain_iterator<T, true>> optimized_def_chain(T MA) {
return make_range(def_chain_iterator<T, true>(MA),
def_chain_iterator<T, true>(nullptr));
}
} // end namespace llvm
#endif // LLVM_TRANSFORMS_UTILS_MEMORYSSA_H
#endif // LLVM_ANALYSIS_MEMORYSSA_H

View File

@ -0,0 +1,153 @@
//===- MemorySSAUpdater.h - Memory SSA Updater-------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// \file
// \brief An automatic updater for MemorySSA that handles arbitrary insertion,
// deletion, and moves. It performs phi insertion where necessary, and
// automatically updates the MemorySSA IR to be correct.
// While updating loads or removing instructions is often easy enough to not
// need this, updating stores should generally not be attemped outside this
// API.
//
// Basic API usage:
// Create the memory access you want for the instruction (this is mainly so
// we know where it is, without having to duplicate the entire set of create
// functions MemorySSA supports).
// Call insertDef or insertUse depending on whether it's a MemoryUse or a
// MemoryDef.
// That's it.
//
// For moving, first, move the instruction itself using the normal SSA
// instruction moving API, then just call moveBefore, moveAfter,or moveTo with
// the right arguments.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_MEMORYSSAUPDATER_H
#define LLVM_ANALYSIS_MEMORYSSAUPDATER_H
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/OperandTraits.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Use.h"
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
#include "llvm/Pass.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Analysis/MemorySSA.h"
namespace llvm {
class Function;
class Instruction;
class MemoryAccess;
class LLVMContext;
class raw_ostream;
class MemorySSAUpdater {
private:
MemorySSA *MSSA;
SmallVector<MemoryPhi *, 8> InsertedPHIs;
SmallPtrSet<BasicBlock *, 8> VisitedBlocks;
public:
MemorySSAUpdater(MemorySSA *MSSA) : MSSA(MSSA) {}
/// Insert a definition into the MemorySSA IR. RenameUses will rename any use
/// below the new def block (and any inserted phis). RenameUses should be set
/// to true if the definition may cause new aliases for loads below it. This
/// is not the case for hoisting or sinking or other forms of code *movement*.
/// It *is* the case for straight code insertion.
/// For example:
/// store a
/// if (foo) { }
/// load a
///
/// Moving the store into the if block, and calling insertDef, does not
/// require RenameUses.
/// However, changing it to:
/// store a
/// if (foo) { store b }
/// load a
/// Where a mayalias b, *does* require RenameUses be set to true.
void insertDef(MemoryDef *Def, bool RenameUses = false);
void insertUse(MemoryUse *Use);
void moveBefore(MemoryUseOrDef *What, MemoryUseOrDef *Where);
void moveAfter(MemoryUseOrDef *What, MemoryUseOrDef *Where);
void moveToPlace(MemoryUseOrDef *What, BasicBlock *BB,
MemorySSA::InsertionPlace Where);
// The below are utility functions. Other than creation of accesses to pass
// to insertDef, and removeAccess to remove accesses, you should generally
// not attempt to update memoryssa yourself. It is very non-trivial to get
// the edge cases right, and the above calls already operate in near-optimal
// time bounds.
/// \brief Create a MemoryAccess in MemorySSA at a specified point in a block,
/// with a specified clobbering definition.
///
/// Returns the new MemoryAccess.
/// This should be called when a memory instruction is created that is being
/// used to replace an existing memory instruction. It will *not* create PHI
/// nodes, or verify the clobbering definition. The insertion place is used
/// solely to determine where in the memoryssa access lists the instruction
/// will be placed. The caller is expected to keep ordering the same as
/// instructions.
/// It will return the new MemoryAccess.
/// Note: If a MemoryAccess already exists for I, this function will make it
/// inaccessible and it *must* have removeMemoryAccess called on it.
MemoryAccess *createMemoryAccessInBB(Instruction *I, MemoryAccess *Definition,
const BasicBlock *BB,
MemorySSA::InsertionPlace Point);
/// \brief Create a MemoryAccess in MemorySSA before or after an existing
/// MemoryAccess.
///
/// Returns the new MemoryAccess.
/// This should be called when a memory instruction is created that is being
/// used to replace an existing memory instruction. It will *not* create PHI
/// nodes, or verify the clobbering definition.
///
/// Note: If a MemoryAccess already exists for I, this function will make it
/// inaccessible and it *must* have removeMemoryAccess called on it.
MemoryUseOrDef *createMemoryAccessBefore(Instruction *I,
MemoryAccess *Definition,
MemoryUseOrDef *InsertPt);
MemoryUseOrDef *createMemoryAccessAfter(Instruction *I,
MemoryAccess *Definition,
MemoryAccess *InsertPt);
/// \brief Remove a MemoryAccess from MemorySSA, including updating all
/// definitions and uses.
/// This should be called when a memory instruction that has a MemoryAccess
/// associated with it is erased from the program. For example, if a store or
/// load is simply erased (not replaced), removeMemoryAccess should be called
/// on the MemoryAccess for that store/load.
void removeMemoryAccess(MemoryAccess *);
private:
// Move What before Where in the MemorySSA IR.
template <class WhereType>
void moveTo(MemoryUseOrDef *What, BasicBlock *BB, WhereType Where);
MemoryAccess *getPreviousDef(MemoryAccess *);
MemoryAccess *getPreviousDefInBlock(MemoryAccess *);
MemoryAccess *getPreviousDefFromEnd(BasicBlock *);
MemoryAccess *getPreviousDefRecursive(BasicBlock *);
MemoryAccess *recursePhi(MemoryAccess *Phi);
template <class RangeType>
MemoryAccess *tryRemoveTrivialPhi(MemoryPhi *Phi, RangeType &Operands);
void fixupDefs(const SmallVectorImpl<MemoryAccess *> &);
};
} // end namespace llvm
#endif // LLVM_ANALYSIS_MEMORYSSAUPDATER_H

View File

@ -0,0 +1,42 @@
//===- Analysis/ObjectUtils.h - analysis utils for object files -*- 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_OBJECT_UTILS_H
#define LLVM_ANALYSIS_OBJECT_UTILS_H
#include "llvm/IR/GlobalVariable.h"
namespace llvm {
/// True if GV can be left out of the object symbol table. This is the case
/// for linkonce_odr values whose address is not significant. While legal, it is
/// not normally profitable to omit them from the .o symbol table. Using this
/// analysis makes sense when the information can be passed down to the linker
/// or we are in LTO.
inline bool canBeOmittedFromSymbolTable(const GlobalValue *GV) {
if (!GV->hasLinkOnceODRLinkage())
return false;
// We assume that anyone who sets global unnamed_addr on a non-constant knows
// what they're doing.
if (GV->hasGlobalUnnamedAddr())
return true;
// If it is a non constant variable, it needs to be uniqued across shared
// objects.
if (auto *Var = dyn_cast<GlobalVariable>(GV))
if (!Var->isConstant())
return false;
return GV->hasAtLeastLocalUnnamedAddr();
}
}
#endif

View File

@ -38,7 +38,7 @@ class Value;
/// enabled in the LLVM context.
class OptimizationRemarkEmitter {
public:
OptimizationRemarkEmitter(Function *F, BlockFrequencyInfo *BFI)
OptimizationRemarkEmitter(const Function *F, BlockFrequencyInfo *BFI)
: F(F), BFI(BFI) {}
/// \brief This variant can be used to generate ORE on demand (without the
@ -52,7 +52,7 @@ class OptimizationRemarkEmitter {
/// operation since BFI and all its required analyses are computed. This is
/// for example useful for CGSCC passes that can't use function analyses
/// passes in the old PM.
OptimizationRemarkEmitter(Function *F);
OptimizationRemarkEmitter(const Function *F);
OptimizationRemarkEmitter(OptimizationRemarkEmitter &&Arg)
: F(Arg.F), BFI(Arg.BFI) {}
@ -63,137 +63,17 @@ class OptimizationRemarkEmitter {
return *this;
}
/// The new interface to emit remarks.
/// Handle invalidation events in the new pass manager.
bool invalidate(Function &F, const PreservedAnalyses &PA,
FunctionAnalysisManager::Invalidator &Inv);
/// \brief Output the remark via the diagnostic handler and to the
/// optimization record file.
///
/// This is the new interface that should be now used rather than the legacy
/// emit* APIs.
void emit(DiagnosticInfoOptimizationBase &OptDiag);
/// Emit an optimization-applied message.
///
/// \p PassName is the name of the pass emitting the message. If -Rpass= is
/// given and \p PassName matches the regular expression in -Rpass, then the
/// remark will be emitted. \p Fn is the function triggering the remark, \p
/// DLoc is the debug location where the diagnostic is generated. \p V is the
/// IR Value that identifies the code region. \p Msg is the message string to
/// use.
void emitOptimizationRemark(const char *PassName, const DebugLoc &DLoc,
const Value *V, const Twine &Msg);
/// \brief Same as above but derives the IR Value for the code region and the
/// debug location from the Loop parameter \p L.
void emitOptimizationRemark(const char *PassName, Loop *L, const Twine &Msg);
/// \brief Same as above but derives the debug location and the code region
/// from the debug location and the basic block of \p Inst, respectively.
void emitOptimizationRemark(const char *PassName, Instruction *Inst,
const Twine &Msg) {
emitOptimizationRemark(PassName, Inst->getDebugLoc(), Inst->getParent(),
Msg);
}
/// Emit an optimization-missed message.
///
/// \p PassName is the name of the pass emitting the message. If
/// -Rpass-missed= is given and the name matches the regular expression in
/// -Rpass, then the remark will be emitted. \p DLoc is the debug location
/// where the diagnostic is generated. \p V is the IR Value that identifies
/// the code region. \p Msg is the message string to use. If \p IsVerbose is
/// true, the message is considered verbose and will only be emitted when
/// verbose output is turned on.
void emitOptimizationRemarkMissed(const char *PassName, const DebugLoc &DLoc,
const Value *V, const Twine &Msg,
bool IsVerbose = false);
/// \brief Same as above but derives the IR Value for the code region and the
/// debug location from the Loop parameter \p L.
void emitOptimizationRemarkMissed(const char *PassName, Loop *L,
const Twine &Msg, bool IsVerbose = false);
/// \brief Same as above but derives the debug location and the code region
/// from the debug location and the basic block of \p Inst, respectively.
void emitOptimizationRemarkMissed(const char *PassName, Instruction *Inst,
const Twine &Msg, bool IsVerbose = false) {
emitOptimizationRemarkMissed(PassName, Inst->getDebugLoc(),
Inst->getParent(), Msg, IsVerbose);
}
/// Emit an optimization analysis remark message.
///
/// \p PassName is the name of the pass emitting the message. If
/// -Rpass-analysis= is given and \p PassName matches the regular expression
/// in -Rpass, then the remark will be emitted. \p DLoc is the debug location
/// where the diagnostic is generated. \p V is the IR Value that identifies
/// the code region. \p Msg is the message string to use. If \p IsVerbose is
/// true, the message is considered verbose and will only be emitted when
/// verbose output is turned on.
void emitOptimizationRemarkAnalysis(const char *PassName,
const DebugLoc &DLoc, const Value *V,
const Twine &Msg, bool IsVerbose = false);
/// \brief Same as above but derives the IR Value for the code region and the
/// debug location from the Loop parameter \p L.
void emitOptimizationRemarkAnalysis(const char *PassName, Loop *L,
const Twine &Msg, bool IsVerbose = false);
/// \brief Same as above but derives the debug location and the code region
/// from the debug location and the basic block of \p Inst, respectively.
void emitOptimizationRemarkAnalysis(const char *PassName, Instruction *Inst,
const Twine &Msg,
bool IsVerbose = false) {
emitOptimizationRemarkAnalysis(PassName, Inst->getDebugLoc(),
Inst->getParent(), Msg, IsVerbose);
}
/// \brief This variant allows specifying what should be emitted for missed
/// and analysis remarks in one call.
///
/// \p PassName is the name of the pass emitting the message. If
/// -Rpass-missed= is given and \p PassName matches the regular expression, \p
/// MsgForMissedRemark is emitted.
///
/// If -Rpass-analysis= is given and \p PassName matches the regular
/// expression, \p MsgForAnalysisRemark is emitted.
///
/// The debug location and the code region is derived from \p Inst. If \p
/// IsVerbose is true, the message is considered verbose and will only be
/// emitted when verbose output is turned on.
void emitOptimizationRemarkMissedAndAnalysis(
const char *PassName, Instruction *Inst, const Twine &MsgForMissedRemark,
const Twine &MsgForAnalysisRemark, bool IsVerbose = false) {
emitOptimizationRemarkAnalysis(PassName, Inst, MsgForAnalysisRemark,
IsVerbose);
emitOptimizationRemarkMissed(PassName, Inst, MsgForMissedRemark, IsVerbose);
}
/// \brief Emit an optimization analysis remark related to floating-point
/// non-commutativity.
///
/// \p PassName is the name of the pass emitting the message. If
/// -Rpass-analysis= is given and \p PassName matches the regular expression
/// in -Rpass, then the remark will be emitted. \p Fn is the function
/// triggering the remark, \p DLoc is the debug location where the diagnostic
/// is generated.\p V is the IR Value that identifies the code region. \p Msg
/// is the message string to use.
void emitOptimizationRemarkAnalysisFPCommute(const char *PassName,
const DebugLoc &DLoc,
const Value *V,
const Twine &Msg);
/// \brief Emit an optimization analysis remark related to pointer aliasing.
///
/// \p PassName is the name of the pass emitting the message. If
/// -Rpass-analysis= is given and \p PassName matches the regular expression
/// in -Rpass, then the remark will be emitted. \p Fn is the function
/// triggering the remark, \p DLoc is the debug location where the diagnostic
/// is generated.\p V is the IR Value that identifies the code region. \p Msg
/// is the message string to use.
void emitOptimizationRemarkAnalysisAliasing(const char *PassName,
const DebugLoc &DLoc,
const Value *V, const Twine &Msg);
/// \brief Same as above but derives the IR Value for the code region and the
/// debug location from the Loop parameter \p L.
void emitOptimizationRemarkAnalysisAliasing(const char *PassName, Loop *L,
const Twine &Msg);
/// \brief Whether we allow for extra compile-time budget to perform more
/// analysis to produce fewer false positives.
///
@ -208,7 +88,7 @@ class OptimizationRemarkEmitter {
}
private:
Function *F;
const Function *F;
BlockFrequencyInfo *BFI;
@ -220,7 +100,7 @@ class OptimizationRemarkEmitter {
Optional<uint64_t> computeHotness(const Value *V);
/// Similar but use value from \p OptDiag and update hotness there.
void computeHotness(DiagnosticInfoOptimizationBase &OptDiag);
void computeHotness(DiagnosticInfoIROptimization &OptDiag);
/// \brief Only allow verbose messages if we know we're filtering by hotness
/// (BFI is only set in this case).
@ -274,5 +154,11 @@ class OptimizationRemarkEmitterAnalysis
/// \brief Run the analysis pass over a function and produce BFI.
Result run(Function &F, FunctionAnalysisManager &AM);
};
namespace yaml {
template <> struct MappingTraits<DiagnosticInfoOptimizationBase *> {
static void mapping(IO &io, DiagnosticInfoOptimizationBase *&OptDiag);
};
}
}
#endif // LLVM_IR_OPTIMIZATIONDIAGNOSTICINFO_H

View File

@ -26,6 +26,10 @@ struct PostDominatorTree : public DominatorTreeBase<BasicBlock> {
typedef DominatorTreeBase<BasicBlock> Base;
PostDominatorTree() : DominatorTreeBase<BasicBlock>(true) {}
/// Handle invalidation explicitly.
bool invalidate(Function &F, const PreservedAnalyses &PA,
FunctionAnalysisManager::Invalidator &);
};
/// \brief Analysis pass which computes a \c PostDominatorTree.

View File

@ -29,6 +29,7 @@
namespace llvm {
class BasicBlock;
class BlockFrequencyInfo;
class CallSite;
class ProfileSummary;
/// \brief Analysis providing profile information.
///
@ -44,7 +45,7 @@ class ProfileSummaryInfo {
private:
Module &M;
std::unique_ptr<ProfileSummary> Summary;
void computeSummary();
bool computeSummary();
void computeThresholds();
// Count thresholds to answer isHotCount and isColdCount queries.
Optional<uint64_t> HotCountThreshold, ColdCountThreshold;
@ -53,16 +54,29 @@ class ProfileSummaryInfo {
ProfileSummaryInfo(Module &M) : M(M) {}
ProfileSummaryInfo(ProfileSummaryInfo &&Arg)
: M(Arg.M), Summary(std::move(Arg.Summary)) {}
/// Returns the profile count for \p CallInst.
static Optional<uint64_t> getProfileCount(const Instruction *CallInst,
BlockFrequencyInfo *BFI);
/// \brief Returns true if \p F has hot function entry.
bool isFunctionEntryHot(const Function *F);
/// Returns true if \p F has hot function entry or hot call edge.
bool isFunctionHotInCallGraph(const Function *F);
/// \brief Returns true if \p F has cold function entry.
bool isFunctionEntryCold(const Function *F);
/// Returns true if \p F has cold function entry or cold call edge.
bool isFunctionColdInCallGraph(const Function *F);
/// \brief Returns true if \p F is a hot function.
bool isHotCount(uint64_t C);
/// \brief Returns true if count \p C is considered cold.
bool isColdCount(uint64_t C);
/// \brief Returns true if BasicBlock \p B is considered hot.
bool isHotBB(const BasicBlock *B, BlockFrequencyInfo *BFI);
/// \brief Returns true if BasicBlock \p B is considered cold.
bool isColdBB(const BasicBlock *B, BlockFrequencyInfo *BFI);
/// \brief Returns true if CallSite \p CS is considered hot.
bool isHotCallSite(const CallSite &CS, BlockFrequencyInfo *BFI);
/// \brief Returns true if Callsite \p CS is considered cold.
bool isColdCallSite(const CallSite &CS, BlockFrequencyInfo *BFI);
};
/// An analysis pass based on legacy pass manager to deliver ProfileSummaryInfo.

View File

@ -196,7 +196,10 @@ class PtrUseVisitor : protected InstVisitor<DerivedT>,
typedef InstVisitor<DerivedT> Base;
public:
PtrUseVisitor(const DataLayout &DL) : PtrUseVisitorBase(DL) {}
PtrUseVisitor(const DataLayout &DL) : PtrUseVisitorBase(DL) {
static_assert(std::is_base_of<PtrUseVisitor, DerivedT>::value,
"Must pass the derived type to this template!");
}
/// \brief Recursively visit the uses of the given pointer.
/// \returns An info struct about the pointer. See \c PtrInfo for details.

View File

@ -886,6 +886,10 @@ class RegionInfo : public RegionInfoBase<RegionTraits<Function>> {
return *this;
}
/// Handle invalidation explicitly.
bool invalidate(Function &F, const PreservedAnalyses &PA,
FunctionAnalysisManager::Invalidator &);
// updateStatistics - Update statistic about created regions.
void updateStatistics(Region *R) final;

View File

@ -543,6 +543,12 @@ class ScalarEvolution {
/// predicate by splitting it into a set of independent predicates.
bool ProvingSplitPredicate;
/// Memoized values for the GetMinTrailingZeros
DenseMap<const SCEV *, uint32_t> MinTrailingZerosCache;
/// Private helper method for the GetMinTrailingZeros method
uint32_t GetMinTrailingZerosImpl(const SCEV *S);
/// 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 summarized in
@ -600,14 +606,14 @@ class ScalarEvolution {
/// Information about the number of times a particular loop exit may be
/// reached before exiting the loop.
struct ExitNotTakenInfo {
AssertingVH<BasicBlock> ExitingBlock;
PoisoningVH<BasicBlock> ExitingBlock;
const SCEV *ExactNotTaken;
std::unique_ptr<SCEVUnionPredicate> Predicate;
bool hasAlwaysTruePredicate() const {
return !Predicate || Predicate->isAlwaysTrue();
}
explicit ExitNotTakenInfo(AssertingVH<BasicBlock> ExitingBlock,
explicit ExitNotTakenInfo(PoisoningVH<BasicBlock> ExitingBlock,
const SCEV *ExactNotTaken,
std::unique_ptr<SCEVUnionPredicate> Predicate)
: ExitingBlock(ExitingBlock), ExactNotTaken(ExactNotTaken),
@ -970,6 +976,20 @@ class ScalarEvolution {
const SCEV *RHS, const SCEV *FoundLHS,
const SCEV *FoundRHS);
/// Test whether the condition described by Pred, LHS, and RHS is true
/// whenever the condition described by Pred, FoundLHS, and FoundRHS is
/// true. Here LHS is an operation that includes FoundLHS as one of its
/// arguments.
bool isImpliedViaOperations(ICmpInst::Predicate Pred,
const SCEV *LHS, const SCEV *RHS,
const SCEV *FoundLHS, const SCEV *FoundRHS,
unsigned Depth = 0);
/// Test whether the condition described by Pred, LHS, and RHS is true.
/// Use only simple non-recursive types of checks, such as range analysis etc.
bool isKnownViaSimpleReasoning(ICmpInst::Predicate Pred,
const SCEV *LHS, const SCEV *RHS);
/// Test whether the condition described by Pred, LHS, and RHS is true
/// whenever the condition described by Pred, FoundLHS, and FoundRHS is
/// true.
@ -1065,18 +1085,6 @@ class ScalarEvolution {
bool isMonotonicPredicateImpl(const SCEVAddRecExpr *LHS,
ICmpInst::Predicate Pred, bool &Increasing);
/// Return true if, for all loop invariant X, the predicate "LHS `Pred` X"
/// is monotonically increasing or decreasing. In the former case set
/// `Increasing` to true and in the latter case set `Increasing` to false.
///
/// A predicate is said to be monotonically increasing if may go from being
/// false to being true as the loop iterates, but never the other way
/// around. A predicate is said to be monotonically decreasing if may go
/// from being true to being false as the loop iterates, but never the other
/// way around.
bool isMonotonicPredicate(const SCEVAddRecExpr *LHS, ICmpInst::Predicate Pred,
bool &Increasing);
/// Return SCEV no-wrap flags that can be proven based on reasoning about
/// how poison produced from no-wrap flags on this value (e.g. a nuw add)
/// would trigger undefined behavior on overflow.
@ -1129,6 +1137,9 @@ class ScalarEvolution {
/// return true. For pointer types, this is the pointer-sized integer type.
Type *getEffectiveSCEVType(Type *Ty) const;
// Returns a wider type among {Ty1, Ty2}.
Type *getWiderType(Type *Ty1, Type *Ty2) const;
/// Return true if the SCEV is a scAddRecExpr or it contains
/// scAddRecExpr. The result will be cached in HasRecMap.
///
@ -1152,7 +1163,8 @@ class ScalarEvolution {
const SCEV *getSignExtendExpr(const SCEV *Op, Type *Ty);
const SCEV *getAnyExtendExpr(const SCEV *Op, Type *Ty);
const SCEV *getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap);
SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
unsigned Depth = 0);
const SCEV *getAddExpr(const SCEV *LHS, const SCEV *RHS,
SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap) {
SmallVector<const SCEV *, 2> Ops = {LHS, RHS};
@ -1301,7 +1313,7 @@ class ScalarEvolution {
///
/// Implemented in terms of the \c getSmallConstantTripCount overload with
/// the single exiting block passed to it. See that routine for details.
unsigned getSmallConstantTripCount(Loop *L);
unsigned getSmallConstantTripCount(const Loop *L);
/// Returns the maximum trip count of this loop as a normal unsigned
/// value. Returns 0 if the trip count is unknown or not constant. This
@ -1310,12 +1322,12 @@ class ScalarEvolution {
/// before taking the branch. For loops with multiple exits, it may not be
/// the number times that the loop header executes if the loop exits
/// prematurely via another branch.
unsigned getSmallConstantTripCount(Loop *L, BasicBlock *ExitingBlock);
unsigned getSmallConstantTripCount(const Loop *L, BasicBlock *ExitingBlock);
/// Returns the upper bound of the loop trip count as a normal unsigned
/// value.
/// Returns 0 if the trip count is unknown or not constant.
unsigned getSmallConstantMaxTripCount(Loop *L);
unsigned getSmallConstantMaxTripCount(const Loop *L);
/// Returns the largest constant divisor of the trip count of the
/// loop if it is a single-exit loop and we can compute a small maximum for
@ -1323,7 +1335,7 @@ class ScalarEvolution {
///
/// Implemented in terms of the \c getSmallConstantTripMultiple overload with
/// the single exiting block passed to it. See that routine for details.
unsigned getSmallConstantTripMultiple(Loop *L);
unsigned getSmallConstantTripMultiple(const Loop *L);
/// Returns the largest constant divisor of the trip count of this loop as a
/// normal unsigned value, if possible. This means that the actual trip
@ -1331,12 +1343,13 @@ class ScalarEvolution {
/// count could very well be zero as well!). As explained in the comments
/// for getSmallConstantTripCount, this assumes that control exits the loop
/// via ExitingBlock.
unsigned getSmallConstantTripMultiple(Loop *L, BasicBlock *ExitingBlock);
unsigned getSmallConstantTripMultiple(const Loop *L,
BasicBlock *ExitingBlock);
/// Get the expression for the number of loop iterations for which this loop
/// is guaranteed not to exit via ExitingBlock. Otherwise return
/// SCEVCouldNotCompute.
const SCEV *getExitCount(Loop *L, BasicBlock *ExitingBlock);
const SCEV *getExitCount(const Loop *L, BasicBlock *ExitingBlock);
/// If the specified loop has a predictable backedge-taken count, return it,
/// otherwise return a SCEVCouldNotCompute object. The backedge-taken count
@ -1432,6 +1445,18 @@ class ScalarEvolution {
bool isKnownPredicate(ICmpInst::Predicate Pred, const SCEV *LHS,
const SCEV *RHS);
/// Return true if, for all loop invariant X, the predicate "LHS `Pred` X"
/// is monotonically increasing or decreasing. In the former case set
/// `Increasing` to true and in the latter case set `Increasing` to false.
///
/// A predicate is said to be monotonically increasing if may go from being
/// false to being true as the loop iterates, but never the other way
/// around. A predicate is said to be monotonically decreasing if may go
/// from being true to being false as the loop iterates, but never the other
/// way around.
bool isMonotonicPredicate(const SCEVAddRecExpr *LHS, ICmpInst::Predicate Pred,
bool &Increasing);
/// Return true if the result of the predicate LHS `Pred` RHS is loop
/// invariant with respect to L. Set InvariantPred, InvariantLHS and
/// InvariantLHS so that InvariantLHS `InvariantPred` InvariantRHS is the
@ -1613,6 +1638,10 @@ class ScalarEvolution {
bool doesIVOverflowOnGT(const SCEV *RHS, const SCEV *Stride, bool IsSigned,
bool NoWrap);
/// Get add expr already created or create a new one
const SCEV *getOrCreateAddExpr(SmallVectorImpl<const SCEV *> &Ops,
SCEV::NoWrapFlags Flags);
private:
FoldingSet<SCEV> UniqueSCEVs;
FoldingSet<SCEVPredicate> UniquePreds;

View File

@ -595,58 +595,82 @@ namespace llvm {
const SCEV *visitTruncateExpr(const SCEVTruncateExpr *Expr) {
const SCEV *Operand = ((SC*)this)->visit(Expr->getOperand());
return SE.getTruncateExpr(Operand, Expr->getType());
return Operand == Expr->getOperand()
? Expr
: SE.getTruncateExpr(Operand, Expr->getType());
}
const SCEV *visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
const SCEV *Operand = ((SC*)this)->visit(Expr->getOperand());
return SE.getZeroExtendExpr(Operand, Expr->getType());
return Operand == Expr->getOperand()
? Expr
: SE.getZeroExtendExpr(Operand, Expr->getType());
}
const SCEV *visitSignExtendExpr(const SCEVSignExtendExpr *Expr) {
const SCEV *Operand = ((SC*)this)->visit(Expr->getOperand());
return SE.getSignExtendExpr(Operand, Expr->getType());
return Operand == Expr->getOperand()
? Expr
: SE.getSignExtendExpr(Operand, Expr->getType());
}
const SCEV *visitAddExpr(const SCEVAddExpr *Expr) {
SmallVector<const SCEV *, 2> Operands;
for (int i = 0, e = Expr->getNumOperands(); i < e; ++i)
Operands.push_back(((SC*)this)->visit(Expr->getOperand(i)));
return SE.getAddExpr(Operands);
bool Changed = false;
for (auto *Op : Expr->operands()) {
Operands.push_back(((SC*)this)->visit(Op));
Changed |= Op != Operands.back();
}
return !Changed ? Expr : SE.getAddExpr(Operands);
}
const SCEV *visitMulExpr(const SCEVMulExpr *Expr) {
SmallVector<const SCEV *, 2> Operands;
for (int i = 0, e = Expr->getNumOperands(); i < e; ++i)
Operands.push_back(((SC*)this)->visit(Expr->getOperand(i)));
return SE.getMulExpr(Operands);
bool Changed = false;
for (auto *Op : Expr->operands()) {
Operands.push_back(((SC*)this)->visit(Op));
Changed |= Op != Operands.back();
}
return !Changed ? Expr : SE.getMulExpr(Operands);
}
const SCEV *visitUDivExpr(const SCEVUDivExpr *Expr) {
return SE.getUDivExpr(((SC*)this)->visit(Expr->getLHS()),
((SC*)this)->visit(Expr->getRHS()));
auto *LHS = ((SC *)this)->visit(Expr->getLHS());
auto *RHS = ((SC *)this)->visit(Expr->getRHS());
bool Changed = LHS != Expr->getLHS() || RHS != Expr->getRHS();
return !Changed ? Expr : SE.getUDivExpr(LHS, RHS);
}
const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) {
SmallVector<const SCEV *, 2> Operands;
for (int i = 0, e = Expr->getNumOperands(); i < e; ++i)
Operands.push_back(((SC*)this)->visit(Expr->getOperand(i)));
return SE.getAddRecExpr(Operands, Expr->getLoop(),
Expr->getNoWrapFlags());
bool Changed = false;
for (auto *Op : Expr->operands()) {
Operands.push_back(((SC*)this)->visit(Op));
Changed |= Op != Operands.back();
}
return !Changed ? Expr
: SE.getAddRecExpr(Operands, Expr->getLoop(),
Expr->getNoWrapFlags());
}
const SCEV *visitSMaxExpr(const SCEVSMaxExpr *Expr) {
SmallVector<const SCEV *, 2> Operands;
for (int i = 0, e = Expr->getNumOperands(); i < e; ++i)
Operands.push_back(((SC*)this)->visit(Expr->getOperand(i)));
return SE.getSMaxExpr(Operands);
bool Changed = false;
for (auto *Op : Expr->operands()) {
Operands.push_back(((SC *)this)->visit(Op));
Changed |= Op != Operands.back();
}
return !Changed ? Expr : SE.getSMaxExpr(Operands);
}
const SCEV *visitUMaxExpr(const SCEVUMaxExpr *Expr) {
SmallVector<const SCEV *, 2> Operands;
for (int i = 0, e = Expr->getNumOperands(); i < e; ++i)
Operands.push_back(((SC*)this)->visit(Expr->getOperand(i)));
return SE.getUMaxExpr(Operands);
bool Changed = false;
for (auto *Op : Expr->operands()) {
Operands.push_back(((SC*)this)->visit(Op));
Changed |= Op != Operands.back();
}
return !Changed ? Expr : SE.getUMaxExpr(Operands);
}
const SCEV *visitUnknown(const SCEVUnknown *Expr) {

View File

@ -37,42 +37,33 @@
#define LLVM_ANALYSIS_SCALAREVOLUTIONNORMALIZATION_H
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
namespace llvm {
class Instruction;
class DominatorTree;
class Loop;
class ScalarEvolution;
class SCEV;
class Value;
/// TransformKind - Different types of transformations that
/// TransformForPostIncUse can do.
enum TransformKind {
/// Normalize - Normalize according to the given loops.
Normalize,
/// NormalizeAutodetect - Detect post-inc opportunities on new expressions,
/// update the given loop set, and normalize.
NormalizeAutodetect,
/// Denormalize - Perform the inverse transform on the expression with the
/// given loop set.
Denormalize
};
/// PostIncLoopSet - A set of loops.
typedef SmallPtrSet<const Loop *, 2> PostIncLoopSet;
/// TransformForPostIncUse - Transform the given expression according to the
/// given transformation kind.
const SCEV *TransformForPostIncUse(TransformKind Kind,
const SCEV *S,
Instruction *User,
Value *OperandValToReplace,
PostIncLoopSet &Loops,
ScalarEvolution &SE,
DominatorTree &DT);
typedef function_ref<bool(const SCEVAddRecExpr *)> NormalizePredTy;
}
/// Normalize \p S to be post-increment for all loops present in \p
/// Loops.
const SCEV *normalizeForPostIncUse(const SCEV *S, const PostIncLoopSet &Loops,
ScalarEvolution &SE);
/// Normalize \p S for all add recurrence sub-expressions for which \p
/// Pred returns true.
const SCEV *normalizeForPostIncUseIf(const SCEV *S, NormalizePredTy Pred,
ScalarEvolution &SE);
/// Denormalize \p S to be post-increment for all loops present in \p
/// Loops.
const SCEV *denormalizeForPostIncUse(const SCEV *S, const PostIncLoopSet &Loops,
ScalarEvolution &SE);
} // namespace llvm
#endif

View File

@ -20,7 +20,7 @@
// One of TLI_DEFINE_ENUM/STRING are defined.
#if defined(TLI_DEFINE_ENUM)
#define TLI_DEFINE_ENUM_INTERNAL(enum_variant) enum_variant,
#define TLI_DEFINE_ENUM_INTERNAL(enum_variant) LibFunc_##enum_variant,
#define TLI_DEFINE_STRING_INTERNAL(string_repr)
#else
#define TLI_DEFINE_ENUM_INTERNAL(enum_variant)

View File

@ -30,14 +30,12 @@ struct VecDesc {
unsigned VectorizationFactor;
};
namespace LibFunc {
enum Func {
enum LibFunc {
#define TLI_DEFINE_ENUM
#include "llvm/Analysis/TargetLibraryInfo.def"
NumLibFuncs
};
}
NumLibFuncs
};
/// Implementation of the target library information.
///
@ -48,9 +46,9 @@ struct VecDesc {
class TargetLibraryInfoImpl {
friend class TargetLibraryInfo;
unsigned char AvailableArray[(LibFunc::NumLibFuncs+3)/4];
unsigned char AvailableArray[(NumLibFuncs+3)/4];
llvm::DenseMap<unsigned, std::string> CustomNames;
static StringRef const StandardNames[LibFunc::NumLibFuncs];
static StringRef const StandardNames[NumLibFuncs];
bool ShouldExtI32Param, ShouldExtI32Return, ShouldSignExtI32Param;
enum AvailabilityState {
@ -58,11 +56,11 @@ class TargetLibraryInfoImpl {
CustomName = 1,
Unavailable = 0 // (memset to all zeros)
};
void setState(LibFunc::Func F, AvailabilityState State) {
void setState(LibFunc F, AvailabilityState State) {
AvailableArray[F/4] &= ~(3 << 2*(F&3));
AvailableArray[F/4] |= State << 2*(F&3);
}
AvailabilityState getState(LibFunc::Func F) const {
AvailabilityState getState(LibFunc F) const {
return static_cast<AvailabilityState>((AvailableArray[F/4] >> 2*(F&3)) & 3);
}
@ -74,7 +72,7 @@ class TargetLibraryInfoImpl {
/// Return true if the function type FTy is valid for the library function
/// F, regardless of whether the function is available.
bool isValidProtoForLibFunc(const FunctionType &FTy, LibFunc::Func F,
bool isValidProtoForLibFunc(const FunctionType &FTy, LibFunc F,
const DataLayout *DL) const;
public:
@ -104,28 +102,28 @@ class TargetLibraryInfoImpl {
///
/// 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;
bool getLibFunc(StringRef funcName, LibFunc &F) const;
/// Searches for a particular function name, also checking that its type is
/// valid for the library function matching that name.
///
/// If it is one of the known library functions, return true and set F to the
/// corresponding value.
bool getLibFunc(const Function &FDecl, LibFunc::Func &F) const;
bool getLibFunc(const Function &FDecl, LibFunc &F) const;
/// Forces a function to be marked as unavailable.
void setUnavailable(LibFunc::Func F) {
void setUnavailable(LibFunc F) {
setState(F, Unavailable);
}
/// Forces a function to be marked as available.
void setAvailable(LibFunc::Func F) {
void setAvailable(LibFunc F) {
setState(F, StandardName);
}
/// Forces a function to be marked as available and provide an alternate name
/// that must be used.
void setAvailableWithName(LibFunc::Func F, StringRef Name) {
void setAvailableWithName(LibFunc F, StringRef Name) {
if (StandardNames[F] != Name) {
setState(F, CustomName);
CustomNames[F] = Name;
@ -225,16 +223,16 @@ class TargetLibraryInfo {
///
/// 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 {
bool getLibFunc(StringRef funcName, LibFunc &F) const {
return Impl->getLibFunc(funcName, F);
}
bool getLibFunc(const Function &FDecl, LibFunc::Func &F) const {
bool getLibFunc(const Function &FDecl, LibFunc &F) const {
return Impl->getLibFunc(FDecl, F);
}
/// Tests whether a library function is available.
bool has(LibFunc::Func F) const {
bool has(LibFunc F) const {
return Impl->getState(F) != TargetLibraryInfoImpl::Unavailable;
}
bool isFunctionVectorizable(StringRef F, unsigned VF) const {
@ -249,37 +247,37 @@ class TargetLibraryInfo {
/// Tests if the function is both available and a candidate for optimized code
/// generation.
bool hasOptimizedCodeGen(LibFunc::Func F) const {
bool hasOptimizedCodeGen(LibFunc 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: case LibFunc::mempcpy:
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: case LibFunc_mempcpy:
return true;
}
return false;
}
StringRef getName(LibFunc::Func F) const {
StringRef getName(LibFunc F) const {
auto State = Impl->getState(F);
if (State == TargetLibraryInfoImpl::Unavailable)
return StringRef();

View File

@ -44,23 +44,26 @@ class Value;
/// \brief Information about a load/store intrinsic defined by the target.
struct MemIntrinsicInfo {
MemIntrinsicInfo()
: ReadMem(false), WriteMem(false), IsSimple(false), MatchingId(0),
NumMemRefs(0), PtrVal(nullptr) {}
bool ReadMem;
bool WriteMem;
/// True only if this memory operation is non-volatile, non-atomic, and
/// unordered. (See LoadInst/StoreInst for details on each)
bool IsSimple;
// Same Id is set by the target for corresponding load/store intrinsics.
unsigned short MatchingId;
int NumMemRefs;
/// This is the pointer that the intrinsic is loading from or storing to.
/// If this is non-null, then analysis/optimization passes can assume that
/// this intrinsic is functionally equivalent to a load/store from this
/// pointer.
Value *PtrVal;
Value *PtrVal = nullptr;
// Ordering for atomic operations.
AtomicOrdering Ordering = AtomicOrdering::NotAtomic;
// Same Id is set by the target for corresponding load/store intrinsics.
unsigned short MatchingId = 0;
bool ReadMem = false;
bool WriteMem = false;
bool IsVolatile = false;
bool isUnordered() const {
return (Ordering == AtomicOrdering::NotAtomic ||
Ordering == AtomicOrdering::Unordered) && !IsVolatile;
}
};
/// \brief This pass provides access to the codegen interfaces that are needed
@ -226,6 +229,24 @@ class TargetTransformInfo {
/// starting with the sources of divergence.
bool isSourceOfDivergence(const Value *V) const;
/// Returns the address space ID for a target's 'flat' address space. Note
/// this is not necessarily the same as addrspace(0), which LLVM sometimes
/// refers to as the generic address space. The flat address space is a
/// generic address space that can be used access multiple segments of memory
/// with different address spaces. Access of a memory location through a
/// pointer with this address space is expected to be legal but slower
/// compared to the same memory location accessed through a pointer with a
/// different address space.
//
/// This is for for targets with different pointer representations which can
/// be converted with the addrspacecast instruction. If a pointer is converted
/// to this address space, optimizations should attempt to replace the access
/// with the source address space.
///
/// \returns ~0u if the target does not have such a flat address space to
/// optimize away.
unsigned getFlatAddressSpace() const;
/// \brief Test whether calls to a function lower to actual program function
/// calls.
///
@ -411,6 +432,16 @@ class TargetTransformInfo {
/// containing this constant value for the target.
bool shouldBuildLookupTablesForConstant(Constant *C) const;
unsigned getScalarizationOverhead(Type *Ty, bool Insert, bool Extract) const;
unsigned getOperandsScalarizationOverhead(ArrayRef<const Value *> Args,
unsigned VF) const;
/// If target has efficient vector element load/store instructions, it can
/// return true here so that insertion/extraction costs are not added to
/// the scalarization cost of a load/store.
bool supportsEfficientVectorElementLoadStore() const;
/// \brief Don't restrict interleaved unrolling to small loops.
bool enableAggressiveInterleaving(bool LoopHasReductions) const;
@ -500,6 +531,12 @@ class TargetTransformInfo {
/// \return The width of the largest scalar or vector register type.
unsigned getRegisterBitWidth(bool Vector) const;
/// \return True if it should be considered for address type promotion.
/// \p AllowPromotionWithoutCommonHeader Set true if promoting \p I is
/// profitable without finding other extensions fed by the same input.
bool shouldConsiderAddressTypePromotion(
const Instruction &I, bool &AllowPromotionWithoutCommonHeader) const;
/// \return The size of a cache line in bytes.
unsigned getCacheLineSize() const;
@ -540,8 +577,10 @@ class TargetTransformInfo {
Type *SubTp = nullptr) const;
/// \return The expected cost of cast instructions, such as bitcast, trunc,
/// zext, etc.
int getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) const;
/// zext, etc. If there is an existing instruction that holds Opcode, it
/// may be passed in the 'I' parameter.
int getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src,
const Instruction *I = nullptr) const;
/// \return The expected cost of a sign- or zero-extended vector extract. Use
/// -1 to indicate that there is no information about the index value.
@ -552,9 +591,11 @@ class TargetTransformInfo {
/// Phi, Ret, Br.
int getCFInstrCost(unsigned Opcode) const;
/// \returns The expected cost of compare and select instructions.
/// \returns The expected cost of compare and select instructions. If there
/// is an existing instruction that holds Opcode, it may be passed in the
/// 'I' parameter.
int getCmpSelInstrCost(unsigned Opcode, Type *ValTy,
Type *CondTy = nullptr) const;
Type *CondTy = nullptr, const Instruction *I = nullptr) const;
/// \return The expected cost of vector Insert and Extract.
/// Use -1 to indicate that there is no information on the index value.
@ -562,7 +603,7 @@ class TargetTransformInfo {
/// \return The cost of Load and Store instructions.
int getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment,
unsigned AddressSpace) const;
unsigned AddressSpace, const Instruction *I = nullptr) const;
/// \return The cost of masked Load and Store instructions.
int getMaskedMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment,
@ -605,13 +646,19 @@ class TargetTransformInfo {
/// ((v0+v2), (v1+v3), undef, undef)
int getReductionCost(unsigned Opcode, Type *Ty, bool IsPairwiseForm) const;
/// \returns The cost of Intrinsic instructions. Types analysis only.
int getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
ArrayRef<Type *> Tys, FastMathFlags FMF) const;
/// \returns The cost of Intrinsic instructions. Analyses the real arguments.
/// Three cases are handled: 1. scalar instruction 2. vector instruction
/// 3. scalar instruction which is to be vectorized with VF.
int getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
ArrayRef<Value *> Args, FastMathFlags FMF) const;
ArrayRef<Value *> Args, FastMathFlags FMF,
unsigned VF = 1) const;
/// \returns The cost of Intrinsic instructions. Types analysis only.
/// If ScalarizationCostPassed is UINT_MAX, the cost of scalarizing the
/// arguments and the return value will be computed based on types.
int getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
ArrayRef<Type *> Tys, FastMathFlags FMF,
unsigned ScalarizationCostPassed = UINT_MAX) const;
/// \returns The cost of Call instructions.
int getCallInstrCost(Function *F, Type *RetTy, ArrayRef<Type *> Tys) const;
@ -720,6 +767,7 @@ class TargetTransformInfo::Concept {
virtual int getUserCost(const User *U) = 0;
virtual bool hasBranchDivergence() = 0;
virtual bool isSourceOfDivergence(const Value *V) = 0;
virtual unsigned getFlatAddressSpace() = 0;
virtual bool isLoweredToCall(const Function *F) = 0;
virtual void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) = 0;
virtual bool isLegalAddImmediate(int64_t Imm) = 0;
@ -743,6 +791,11 @@ class TargetTransformInfo::Concept {
virtual unsigned getJumpBufSize() = 0;
virtual bool shouldBuildLookupTables() = 0;
virtual bool shouldBuildLookupTablesForConstant(Constant *C) = 0;
virtual unsigned
getScalarizationOverhead(Type *Ty, bool Insert, bool Extract) = 0;
virtual unsigned getOperandsScalarizationOverhead(ArrayRef<const Value *> Args,
unsigned VF) = 0;
virtual bool supportsEfficientVectorElementLoadStore() = 0;
virtual bool enableAggressiveInterleaving(bool LoopHasReductions) = 0;
virtual bool enableInterleavedAccessVectorization() = 0;
virtual bool isFPVectorizationPotentiallyUnsafe() = 0;
@ -763,6 +816,8 @@ class TargetTransformInfo::Concept {
Type *Ty) = 0;
virtual unsigned getNumberOfRegisters(bool Vector) = 0;
virtual unsigned getRegisterBitWidth(bool Vector) = 0;
virtual bool shouldConsiderAddressTypePromotion(
const Instruction &I, bool &AllowPromotionWithoutCommonHeader) = 0;
virtual unsigned getCacheLineSize() = 0;
virtual unsigned getPrefetchDistance() = 0;
virtual unsigned getMinPrefetchStride() = 0;
@ -776,16 +831,17 @@ class TargetTransformInfo::Concept {
ArrayRef<const Value *> Args) = 0;
virtual int getShuffleCost(ShuffleKind Kind, Type *Tp, int Index,
Type *SubTp) = 0;
virtual int getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) = 0;
virtual int getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src,
const Instruction *I) = 0;
virtual int getExtractWithExtendCost(unsigned Opcode, Type *Dst,
VectorType *VecTy, unsigned Index) = 0;
virtual int getCFInstrCost(unsigned Opcode) = 0;
virtual int getCmpSelInstrCost(unsigned Opcode, Type *ValTy,
Type *CondTy) = 0;
Type *CondTy, const Instruction *I) = 0;
virtual int getVectorInstrCost(unsigned Opcode, Type *Val,
unsigned Index) = 0;
virtual int getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment,
unsigned AddressSpace) = 0;
unsigned AddressSpace, const Instruction *I) = 0;
virtual int getMaskedMemoryOpCost(unsigned Opcode, Type *Src,
unsigned Alignment,
unsigned AddressSpace) = 0;
@ -800,11 +856,10 @@ class TargetTransformInfo::Concept {
virtual int getReductionCost(unsigned Opcode, Type *Ty,
bool IsPairwiseForm) = 0;
virtual int getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
ArrayRef<Type *> Tys,
FastMathFlags FMF) = 0;
ArrayRef<Type *> Tys, FastMathFlags FMF,
unsigned ScalarizationCostPassed) = 0;
virtual int getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
ArrayRef<Value *> Args,
FastMathFlags FMF) = 0;
ArrayRef<Value *> Args, FastMathFlags FMF, unsigned VF) = 0;
virtual int getCallInstrCost(Function *F, Type *RetTy,
ArrayRef<Type *> Tys) = 0;
virtual unsigned getNumberOfParts(Type *Tp) = 0;
@ -879,6 +934,11 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
bool isSourceOfDivergence(const Value *V) override {
return Impl.isSourceOfDivergence(V);
}
unsigned getFlatAddressSpace() override {
return Impl.getFlatAddressSpace();
}
bool isLoweredToCall(const Function *F) override {
return Impl.isLoweredToCall(F);
}
@ -933,6 +993,19 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
bool shouldBuildLookupTablesForConstant(Constant *C) override {
return Impl.shouldBuildLookupTablesForConstant(C);
}
unsigned getScalarizationOverhead(Type *Ty, bool Insert,
bool Extract) override {
return Impl.getScalarizationOverhead(Ty, Insert, Extract);
}
unsigned getOperandsScalarizationOverhead(ArrayRef<const Value *> Args,
unsigned VF) override {
return Impl.getOperandsScalarizationOverhead(Args, VF);
}
bool supportsEfficientVectorElementLoadStore() override {
return Impl.supportsEfficientVectorElementLoadStore();
}
bool enableAggressiveInterleaving(bool LoopHasReductions) override {
return Impl.enableAggressiveInterleaving(LoopHasReductions);
}
@ -976,7 +1049,11 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
unsigned getRegisterBitWidth(bool Vector) override {
return Impl.getRegisterBitWidth(Vector);
}
bool shouldConsiderAddressTypePromotion(
const Instruction &I, bool &AllowPromotionWithoutCommonHeader) override {
return Impl.shouldConsiderAddressTypePromotion(
I, AllowPromotionWithoutCommonHeader);
}
unsigned getCacheLineSize() override {
return Impl.getCacheLineSize();
}
@ -1003,8 +1080,9 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
Type *SubTp) override {
return Impl.getShuffleCost(Kind, Tp, Index, SubTp);
}
int getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) override {
return Impl.getCastInstrCost(Opcode, Dst, Src);
int getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src,
const Instruction *I) override {
return Impl.getCastInstrCost(Opcode, Dst, Src, I);
}
int getExtractWithExtendCost(unsigned Opcode, Type *Dst, VectorType *VecTy,
unsigned Index) override {
@ -1013,15 +1091,16 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
int getCFInstrCost(unsigned Opcode) override {
return Impl.getCFInstrCost(Opcode);
}
int getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy) override {
return Impl.getCmpSelInstrCost(Opcode, ValTy, CondTy);
int getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy,
const Instruction *I) override {
return Impl.getCmpSelInstrCost(Opcode, ValTy, CondTy, I);
}
int getVectorInstrCost(unsigned Opcode, Type *Val, unsigned Index) override {
return Impl.getVectorInstrCost(Opcode, Val, Index);
}
int getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment,
unsigned AddressSpace) override {
return Impl.getMemoryOpCost(Opcode, Src, Alignment, AddressSpace);
unsigned AddressSpace, const Instruction *I) override {
return Impl.getMemoryOpCost(Opcode, Src, Alignment, AddressSpace, I);
}
int getMaskedMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment,
unsigned AddressSpace) override {
@ -1044,13 +1123,13 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
return Impl.getReductionCost(Opcode, Ty, IsPairwiseForm);
}
int getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, ArrayRef<Type *> Tys,
FastMathFlags FMF) override {
return Impl.getIntrinsicInstrCost(ID, RetTy, Tys, FMF);
FastMathFlags FMF, unsigned ScalarizationCostPassed) override {
return Impl.getIntrinsicInstrCost(ID, RetTy, Tys, FMF,
ScalarizationCostPassed);
}
int getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
ArrayRef<Value *> Args,
FastMathFlags FMF) override {
return Impl.getIntrinsicInstrCost(ID, RetTy, Args, FMF);
ArrayRef<Value *> Args, FastMathFlags FMF, unsigned VF) override {
return Impl.getIntrinsicInstrCost(ID, RetTy, Args, FMF, VF);
}
int getCallInstrCost(Function *F, Type *RetTy,
ArrayRef<Type *> Tys) override {

View File

@ -171,6 +171,10 @@ class TargetTransformInfoImplBase {
bool isSourceOfDivergence(const Value *V) { return false; }
unsigned getFlatAddressSpace () {
return -1;
}
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
@ -251,6 +255,15 @@ class TargetTransformInfoImplBase {
bool shouldBuildLookupTables() { return true; }
bool shouldBuildLookupTablesForConstant(Constant *C) { return true; }
unsigned getScalarizationOverhead(Type *Ty, bool Insert, bool Extract) {
return 0;
}
unsigned getOperandsScalarizationOverhead(ArrayRef<const Value *> Args,
unsigned VF) { return 0; }
bool supportsEfficientVectorElementLoadStore() { return false; }
bool enableAggressiveInterleaving(bool LoopHasReductions) { return false; }
bool enableInterleavedAccessVectorization() { return false; }
@ -292,6 +305,13 @@ class TargetTransformInfoImplBase {
unsigned getRegisterBitWidth(bool Vector) { return 32; }
bool
shouldConsiderAddressTypePromotion(const Instruction &I,
bool &AllowPromotionWithoutCommonHeader) {
AllowPromotionWithoutCommonHeader = false;
return false;
}
unsigned getCacheLineSize() { return 0; }
unsigned getPrefetchDistance() { return 0; }
@ -316,7 +336,8 @@ class TargetTransformInfoImplBase {
return 1;
}
unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) { return 1; }
unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src,
const Instruction *I) { return 1; }
unsigned getExtractWithExtendCost(unsigned Opcode, Type *Dst,
VectorType *VecTy, unsigned Index) {
@ -325,7 +346,8 @@ class TargetTransformInfoImplBase {
unsigned getCFInstrCost(unsigned Opcode) { return 1; }
unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy) {
unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy,
const Instruction *I) {
return 1;
}
@ -334,7 +356,7 @@ class TargetTransformInfoImplBase {
}
unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment,
unsigned AddressSpace) {
unsigned AddressSpace, const Instruction *I) {
return 1;
}
@ -358,11 +380,12 @@ class TargetTransformInfoImplBase {
}
unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
ArrayRef<Type *> Tys, FastMathFlags FMF) {
ArrayRef<Type *> Tys, FastMathFlags FMF,
unsigned ScalarizationCostPassed) {
return 1;
}
unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
ArrayRef<Value *> Args, FastMathFlags FMF) {
ArrayRef<Value *> Args, FastMathFlags FMF, unsigned VF) {
return 1;
}

View File

@ -32,14 +32,15 @@ struct DevirtCallSite {
/// call sites based on the call and return them in DevirtCalls.
void findDevirtualizableCallsForTypeTest(
SmallVectorImpl<DevirtCallSite> &DevirtCalls,
SmallVectorImpl<CallInst *> &Assumes, CallInst *CI);
SmallVectorImpl<CallInst *> &Assumes, const CallInst *CI);
/// Given a call to the intrinsic @llvm.type.checked.load, find all
/// devirtualizable call sites based on the call and return them in DevirtCalls.
void findDevirtualizableCallsForTypeCheckedLoad(
SmallVectorImpl<DevirtCallSite> &DevirtCalls,
SmallVectorImpl<Instruction *> &LoadedPtrs,
SmallVectorImpl<Instruction *> &Preds, bool &HasNonCallUses, CallInst *CI);
SmallVectorImpl<Instruction *> &Preds, bool &HasNonCallUses,
const CallInst *CI);
}
#endif

View File

@ -31,6 +31,7 @@ template <typename T> class ArrayRef;
class Instruction;
class Loop;
class LoopInfo;
class OptimizationRemarkEmitter;
class MDNode;
class StringRef;
class TargetLibraryInfo;
@ -52,7 +53,8 @@ template <typename T> class ArrayRef;
const DataLayout &DL, unsigned Depth = 0,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);
const DominatorTree *DT = nullptr,
OptimizationRemarkEmitter *ORE = nullptr);
/// Compute known bits from the range metadata.
/// \p KnownZero the set of bits that are known to be zero
/// \p KnownOne the set of bits that are known to be one
@ -86,8 +88,10 @@ template <typename T> class ArrayRef;
/// Return true if the given value is known to be non-zero 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.
/// defined. For pointers, if the context instruction and dominator tree are
/// specified, perform context-sensitive analysis and return true if the
/// pointer couldn't possibly be null at the specified instruction.
/// Supports values with integer or pointer type and vectors of integers.
bool isKnownNonZero(const Value *V, const DataLayout &DL, unsigned Depth = 0,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
@ -167,13 +171,25 @@ template <typename T> class ArrayRef;
bool CannotBeNegativeZero(const Value *V, const TargetLibraryInfo *TLI,
unsigned Depth = 0);
/// Return true if we can prove that the specified FP value is either a NaN or
/// never less than 0.0.
/// If \p IncludeNeg0 is false, -0.0 is considered less than 0.0.
/// Return true if we can prove that the specified FP value is either NaN or
/// never less than -0.0.
///
/// NaN --> true
/// +0 --> true
/// -0 --> true
/// x > +0 --> true
/// x < -0 --> false
///
bool CannotBeOrderedLessThanZero(const Value *V, const TargetLibraryInfo *TLI);
/// \returns true if we can prove that the specified FP value has a 0 sign
/// bit.
/// Return true if we can prove that the specified FP value's sign bit is 0.
///
/// NaN --> true/false (depending on the NaN's sign bit)
/// +0 --> true
/// -0 --> false
/// x > +0 --> true
/// x < -0 --> false
///
bool SignBitMustBeZero(const Value *V, const TargetLibraryInfo *TLI);
/// If the specified value can be set by repeating the same byte in memory,

View File

@ -1,4 +1,4 @@
//===- llvm/Transforms/Utils/VectorUtils.h - Vector utilities -*- C++ -*-=====//
//===- llvm/Analysis/VectorUtils.h - Vector utilities -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -11,11 +11,12 @@
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TRANSFORMS_UTILS_VECTORUTILS_H
#define LLVM_TRANSFORMS_UTILS_VECTORUTILS_H
#ifndef LLVM_ANALYSIS_VECTORUTILS_H
#define LLVM_ANALYSIS_VECTORUTILS_H
#include "llvm/ADT/MapVector.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/IRBuilder.h"
namespace llvm {
@ -123,6 +124,58 @@ computeMinimumValueSizes(ArrayRef<BasicBlock*> Blocks,
/// This function always sets a (possibly null) value for each K in Kinds.
Instruction *propagateMetadata(Instruction *I, ArrayRef<Value *> VL);
/// \brief Create an interleave shuffle mask.
///
/// This function creates a shuffle mask for interleaving \p NumVecs vectors of
/// vectorization factor \p VF into a single wide vector. The mask is of the
/// form:
///
/// <0, VF, VF * 2, ..., VF * (NumVecs - 1), 1, VF + 1, VF * 2 + 1, ...>
///
/// For example, the mask for VF = 4 and NumVecs = 2 is:
///
/// <0, 4, 1, 5, 2, 6, 3, 7>.
Constant *createInterleaveMask(IRBuilder<> &Builder, unsigned VF,
unsigned NumVecs);
/// \brief Create a stride shuffle mask.
///
/// This function creates a shuffle mask whose elements begin at \p Start and
/// are incremented by \p Stride. The mask can be used to deinterleave an
/// interleaved vector into separate vectors of vectorization factor \p VF. The
/// mask is of the form:
///
/// <Start, Start + Stride, ..., Start + Stride * (VF - 1)>
///
/// For example, the mask for Start = 0, Stride = 2, and VF = 4 is:
///
/// <0, 2, 4, 6>
Constant *createStrideMask(IRBuilder<> &Builder, unsigned Start,
unsigned Stride, unsigned VF);
/// \brief Create a sequential shuffle mask.
///
/// This function creates shuffle mask whose elements are sequential and begin
/// at \p Start. The mask contains \p NumInts integers and is padded with \p
/// NumUndefs undef values. The mask is of the form:
///
/// <Start, Start + 1, ... Start + NumInts - 1, undef_1, ... undef_NumUndefs>
///
/// For example, the mask for Start = 0, NumInsts = 4, and NumUndefs = 4 is:
///
/// <0, 1, 2, 3, undef, undef, undef, undef>
Constant *createSequentialMask(IRBuilder<> &Builder, unsigned Start,
unsigned NumInts, unsigned NumUndefs);
/// \brief Concatenate a list of vectors.
///
/// This function generates code that concatenate the vectors in \p Vecs into a
/// single large vector. The number of vectors should be greater than one, and
/// their element types should be the same. The number of elements in the
/// vectors should also be the same; however, if the last vector has fewer
/// elements, it will be padded with undefs.
Value *concatenateVectors(IRBuilder<> &Builder, ArrayRef<Value *> Vecs);
} // llvm namespace
#endif

View File

@ -43,9 +43,16 @@ namespace llvm {
///
/// \p GenerateHash enables hashing the Module and including the hash in the
/// bitcode (currently for use in ThinLTO incremental build).
///
/// If \p ModHash is non-null, when GenerateHash is true, the resulting
/// hash is written into ModHash. When GenerateHash is false, that value
/// is used as the hash instead of computing from the generated bitcode.
/// Can be used to produce the same module hash for a minimized bitcode
/// used just for the thin link as in the regular full bitcode that will
/// be used in the backend.
void writeModule(const Module *M, bool ShouldPreserveUseListOrder = false,
const ModuleSummaryIndex *Index = nullptr,
bool GenerateHash = false);
bool GenerateHash = false, ModuleHash *ModHash = nullptr);
};
/// \brief Write the specified module to the specified raw output stream.
@ -62,10 +69,18 @@ namespace llvm {
///
/// \p GenerateHash enables hashing the Module and including the hash in the
/// bitcode (currently for use in ThinLTO incremental build).
///
/// If \p ModHash is non-null, when GenerateHash is true, the resulting
/// hash is written into ModHash. When GenerateHash is false, that value
/// is used as the hash instead of computing from the generated bitcode.
/// Can be used to produce the same module hash for a minimized bitcode
/// used just for the thin link as in the regular full bitcode that will
/// be used in the backend.
void WriteBitcodeToFile(const Module *M, raw_ostream &Out,
bool ShouldPreserveUseListOrder = false,
const ModuleSummaryIndex *Index = nullptr,
bool GenerateHash = false);
bool GenerateHash = false,
ModuleHash *ModHash = nullptr);
/// Write the specified module summary index to the given raw output stream,
/// where it will be written in a new bitcode block. This is used when

View File

@ -92,9 +92,6 @@ enum ModuleCodes {
// ALIAS: [alias type, aliasee val#, linkage, visibility]
MODULE_CODE_ALIAS_OLD = 9,
// MODULE_CODE_PURGEVALS: [numvals]
MODULE_CODE_PURGEVALS = 10,
MODULE_CODE_GCNAME = 11, // GCNAME: [strchr x N]
MODULE_CODE_COMDAT = 12, // COMDAT: [selection_kind, name]
@ -213,8 +210,28 @@ enum GlobalValueSummarySymtabCodes {
FS_COMBINED_ORIGINAL_NAME = 9,
// VERSION of the summary, bumped when adding flags for instance.
FS_VERSION = 10,
// The list of llvm.type.test type identifiers used by the following function.
// The list of llvm.type.test type identifiers used by the following function
// that are used other than by an llvm.assume.
// [n x typeid]
FS_TYPE_TESTS = 11,
// The list of virtual calls made by this function using
// llvm.assume(llvm.type.test) intrinsics that do not have all constant
// integer arguments.
// [n x (typeid, offset)]
FS_TYPE_TEST_ASSUME_VCALLS = 12,
// The list of virtual calls made by this function using
// llvm.type.checked.load intrinsics that do not have all constant integer
// arguments.
// [n x (typeid, offset)]
FS_TYPE_CHECKED_LOAD_VCALLS = 13,
// Identifies a virtual call made by this function using an
// llvm.assume(llvm.type.test) intrinsic with all constant integer arguments.
// [typeid, offset, n x arg]
FS_TYPE_TEST_ASSUME_CONST_VCALL = 14,
// Identifies a virtual call made by this function using an
// llvm.type.checked.load intrinsic with all constant integer arguments.
// [typeid, offset, n x arg]
FS_TYPE_CHECKED_LOAD_CONST_VCALL = 15,
};
enum MetadataCodes {

View File

@ -123,13 +123,6 @@ bool returnTypeIsEligibleForTailCall(const Function *F, const Instruction *I,
const ReturnInst *Ret,
const TargetLoweringBase &TLI);
// True if GV can be left out of the object symbol table. This is the case
// for linkonce_odr values whose address is not significant. While legal, it is
// not normally profitable to omit them from the .o symbol table. Using this
// analysis makes sense when the information can be passed down to the linker
// or we are in LTO.
bool canBeOmittedFromSymbolTable(const GlobalValue *GV);
DenseMap<const MachineBasicBlock *, int>
getFuncletMembership(const MachineFunction &MF);

View File

@ -1,4 +1,4 @@
//===-- llvm/CodeGen/AsmPrinter.h - AsmPrinter Framework --------*- C++ -*-===//
//===- llvm/CodeGen/AsmPrinter.h - AsmPrinter Framework ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -17,35 +17,43 @@
#define LLVM_CODEGEN_ASMPRINTER_H
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/DwarfStringPoolEntry.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SourceMgr.h"
#include <cstdint>
#include <memory>
#include <utility>
#include <vector>
namespace llvm {
class AsmPrinterHandler;
class BlockAddress;
class ByteStreamer;
class GCStrategy;
class Constant;
class ConstantArray;
class DataLayout;
class DIE;
class DIEAbbrev;
class DwarfDebug;
class GCMetadataPrinter;
class GlobalIndirectSymbol;
class GlobalValue;
class GlobalVariable;
class GCStrategy;
class MachineBasicBlock;
class MachineConstantPoolValue;
class MachineFunction;
class MachineInstr;
class MachineLocation;
class MachineLoopInfo;
class MachineLoop;
class MachineConstantPoolValue;
class MachineJumpTableInfo;
class MachineLoopInfo;
class MachineModuleInfo;
class MachineOptimizationRemarkEmitter;
class MCAsmInfo;
class MCCFIInstruction;
class MCContext;
@ -57,10 +65,7 @@ class MCSubtargetInfo;
class MCSymbol;
class MCTargetOptions;
class MDNode;
class DwarfDebug;
class Mangler;
class TargetLoweringObjectFile;
class DataLayout;
class TargetMachine;
/// This class is intended to be used as a driving class for all asm writers.
@ -84,33 +89,39 @@ class AsmPrinter : public MachineFunctionPass {
std::unique_ptr<MCStreamer> OutStreamer;
/// The current machine function.
const MachineFunction *MF;
const MachineFunction *MF = nullptr;
/// This is a pointer to the current MachineModuleInfo.
MachineModuleInfo *MMI;
MachineModuleInfo *MMI = nullptr;
/// Optimization remark emitter.
MachineOptimizationRemarkEmitter *ORE;
/// The symbol for the current function. This is recalculated at the beginning
/// of each call to runOnMachineFunction().
///
MCSymbol *CurrentFnSym;
MCSymbol *CurrentFnSym = nullptr;
/// The symbol used to represent the start of the current function for the
/// purpose of calculating its size (e.g. using the .size directive). By
/// default, this is equal to CurrentFnSym.
MCSymbol *CurrentFnSymForSize;
MCSymbol *CurrentFnSymForSize = nullptr;
/// 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;
/// Enable print [latency:throughput] in output
bool EnablePrintSchedInfo = false;
private:
MCSymbol *CurrentFnBegin;
MCSymbol *CurrentFnEnd;
MCSymbol *CurExceptionSym;
MCSymbol *CurrentFnBegin = nullptr;
MCSymbol *CurrentFnEnd = nullptr;
MCSymbol *CurExceptionSym = nullptr;
// The garbage collection metadata printer table.
void *GCMetadataPrinters; // Really a DenseMap.
void *GCMetadataPrinters = nullptr; // Really a DenseMap.
/// Emit comments in assembly output if this is true.
///
@ -118,7 +129,7 @@ class AsmPrinter : public MachineFunctionPass {
static char ID;
/// If VerboseAsm is set, a pointer to the loop info for this function.
MachineLoopInfo *LI;
MachineLoopInfo *LI = nullptr;
struct HandlerInfo {
AsmPrinterHandler *Handler;
@ -126,6 +137,7 @@ class AsmPrinter : public MachineFunctionPass {
const char *TimerDescription;
const char *TimerGroupName;
const char *TimerGroupDescription;
HandlerInfo(AsmPrinterHandler *Handler, const char *TimerName,
const char *TimerDescription, const char *TimerGroupName,
const char *TimerGroupDescription)
@ -137,11 +149,24 @@ class AsmPrinter : public MachineFunctionPass {
/// maintains ownership of the emitters.
SmallVector<HandlerInfo, 1> Handlers;
public:
struct SrcMgrDiagInfo {
SourceMgr SrcMgr;
std::vector<const MDNode *> LocInfos;
LLVMContext::InlineAsmDiagHandlerTy DiagHandler;
void *DiagContext;
};
private:
/// Structure for generating diagnostics for inline assembly. Only initialised
/// when necessary.
mutable std::unique_ptr<SrcMgrDiagInfo> DiagInfo;
/// If the target supports dwarf debug info, this pointer is non-null.
DwarfDebug *DD;
DwarfDebug *DD = nullptr;
/// If the current module uses dwarf CFI annotations strictly for debugging.
bool isCFIMoveForDebugging;
bool isCFIMoveForDebugging = false;
protected:
explicit AsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer);
@ -200,6 +225,7 @@ class AsmPrinter : public MachineFunctionPass {
FUNCTION_ENTER = 0,
FUNCTION_EXIT = 1,
TAIL_CALL = 2,
LOG_ARGS_ENTER = 3,
};
// The table will contain these structs that point to the sled, the function
@ -381,7 +407,7 @@ class AsmPrinter : public MachineFunctionPass {
//===------------------------------------------------------------------===//
// Symbol Lowering Routines.
//===------------------------------------------------------------------===//
public:
MCSymbol *createTempSymbol(const Twine &Name) const;
/// Return the MCSymbol for a private symbol with global value name as its
@ -407,7 +433,7 @@ class AsmPrinter : public MachineFunctionPass {
//===------------------------------------------------------------------===//
// Emission Helper Routines.
//===------------------------------------------------------------------===//
public:
/// This is just convenient handler for printing offsets.
void printOffset(int64_t Offset, raw_ostream &OS) const;
@ -484,7 +510,7 @@ class AsmPrinter : public MachineFunctionPass {
///
/// \p Value - The value to emit.
/// \p Size - The size of the integer (in bytes) to emit.
virtual void EmitDebugValue(const MCExpr *Value, unsigned Size) const;
virtual void EmitDebugThreadLocal(const MCExpr *Value, unsigned Size) const;
//===------------------------------------------------------------------===//
// Dwarf Lowering Routines
@ -511,7 +537,7 @@ class AsmPrinter : public MachineFunctionPass {
//===------------------------------------------------------------------===//
// Inline Asm Support
//===------------------------------------------------------------------===//
public:
// These are hooks that targets can override to implement inline asm
// support. These should probably be moved out of AsmPrinter someday.
@ -555,9 +581,9 @@ class AsmPrinter : public MachineFunctionPass {
private:
/// Private state for PrintSpecial()
// Assign a unique ID to this machine instruction.
mutable const MachineInstr *LastMI;
mutable unsigned LastFn;
mutable unsigned Counter;
mutable const MachineInstr *LastMI = nullptr;
mutable unsigned LastFn = 0;
mutable unsigned Counter = ~0U;
/// This method emits the header for the current function.
virtual void EmitFunctionHeader();
@ -596,6 +622,7 @@ class AsmPrinter : public MachineFunctionPass {
void emitGlobalIndirectSymbol(Module &M,
const GlobalIndirectSymbol& GIS);
};
}
#endif
} // end namespace llvm
#endif // LLVM_CODEGEN_ASMPRINTER_H

View File

@ -42,24 +42,6 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
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 a cost of shuffle as a sequence of extract and insert
/// operations.
unsigned getPermuteShuffleOverhead(Type *Ty) {
@ -111,6 +93,11 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
bool isSourceOfDivergence(const Value *V) { return false; }
unsigned getFlatAddressSpace() {
// Return an invalid address space.
return -1;
}
bool isLegalAddImmediate(int64_t imm) {
return getTLI()->isLegalAddImmediate(imm);
}
@ -301,6 +288,67 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
unsigned getRegisterBitWidth(bool Vector) { return 32; }
/// 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 overhead of scalarizing an instructions unique
/// non-constant operands. The types of the arguments are ordinarily
/// scalar, in which case the costs are multiplied with VF.
unsigned getOperandsScalarizationOverhead(ArrayRef<const Value *> Args,
unsigned VF) {
unsigned Cost = 0;
SmallPtrSet<const Value*, 4> UniqueOperands;
for (const Value *A : Args) {
if (!isa<Constant>(A) && UniqueOperands.insert(A).second) {
Type *VecTy = nullptr;
if (A->getType()->isVectorTy()) {
VecTy = A->getType();
// If A is a vector operand, VF should be 1 or correspond to A.
assert ((VF == 1 || VF == VecTy->getVectorNumElements()) &&
"Vector argument does not match VF");
}
else
VecTy = VectorType::get(A->getType(), VF);
Cost += getScalarizationOverhead(VecTy, false, true);
}
}
return Cost;
}
unsigned getScalarizationOverhead(Type *VecTy, ArrayRef<const Value *> Args) {
assert (VecTy->isVectorTy());
unsigned Cost = 0;
Cost += getScalarizationOverhead(VecTy, true, false);
if (!Args.empty())
Cost += getOperandsScalarizationOverhead(Args,
VecTy->getVectorNumElements());
else
// When no information on arguments is provided, we add the cost
// associated with one argument as a heuristic.
Cost += getScalarizationOverhead(VecTy, false, true);
return Cost;
}
unsigned getMaxInterleaveFactor(unsigned VF) { return 1; }
unsigned getArithmeticInstrCost(
@ -341,10 +389,9 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
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;
// Return the cost of multiple scalar invocation plus the cost of
// inserting and extracting the values.
return getScalarizationOverhead(Ty, Args) + Num * Cost;
}
// We don't know anything about this scalar instruction.
@ -360,7 +407,8 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
return 1;
}
unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) {
unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src,
const Instruction *I = nullptr) {
const TargetLoweringBase *TLI = getTLI();
int ISD = TLI->InstructionOpcodeToISD(Opcode);
assert(ISD && "Invalid opcode");
@ -389,6 +437,18 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
Dst->getPointerAddressSpace()))
return 0;
// If this is a zext/sext of a load, return 0 if the corresponding
// extending load exists on target.
if ((Opcode == Instruction::ZExt || Opcode == Instruction::SExt) &&
I && isa<LoadInst>(I->getOperand(0))) {
EVT ExtVT = EVT::getEVT(Dst);
EVT LoadVT = EVT::getEVT(Src);
unsigned LType =
((Opcode == Instruction::ZExt) ? ISD::ZEXTLOAD : ISD::SEXTLOAD);
if (TLI->isLoadExtLegal(LType, ExtVT, LoadVT))
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))
@ -446,14 +506,14 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
Src->getVectorNumElements() / 2);
T *TTI = static_cast<T *>(this);
return TTI->getVectorSplitCost() +
(2 * TTI->getCastInstrCost(Opcode, SplitDst, SplitSrc));
(2 * TTI->getCastInstrCost(Opcode, SplitDst, SplitSrc, I));
}
// In other cases where the source or destination are illegal, assume
// the operation will get scalarized.
unsigned Num = Dst->getVectorNumElements();
unsigned Cost = static_cast<T *>(this)->getCastInstrCost(
Opcode, Dst->getScalarType(), Src->getScalarType());
Opcode, Dst->getScalarType(), Src->getScalarType(), I);
// Return the cost of multiple scalar invocation plus the cost of
// inserting and extracting the values.
@ -487,7 +547,8 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
return 0;
}
unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy) {
unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy,
const Instruction *I) {
const TargetLoweringBase *TLI = getTLI();
int ISD = TLI->InstructionOpcodeToISD(Opcode);
assert(ISD && "Invalid opcode");
@ -515,7 +576,7 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
if (CondTy)
CondTy = CondTy->getScalarType();
unsigned Cost = static_cast<T *>(this)->getCmpSelInstrCost(
Opcode, ValTy->getScalarType(), CondTy);
Opcode, ValTy->getScalarType(), CondTy, I);
// Return the cost of multiple scalar invocation plus the cost of
// inserting and extracting the values.
@ -534,7 +595,7 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
}
unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment,
unsigned AddressSpace) {
unsigned AddressSpace, const Instruction *I = nullptr) {
assert(!Src->isVoidTy() && "Invalid type");
std::pair<unsigned, MVT> LT = getTLI()->getTypeLegalizationCost(DL, Src);
@ -680,18 +741,42 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
return Cost;
}
/// Get intrinsic cost based on arguments
/// Get intrinsic cost based on arguments.
unsigned getIntrinsicInstrCost(Intrinsic::ID IID, Type *RetTy,
ArrayRef<Value *> Args, FastMathFlags FMF) {
ArrayRef<Value *> Args, FastMathFlags FMF,
unsigned VF = 1) {
unsigned RetVF = (RetTy->isVectorTy() ? RetTy->getVectorNumElements() : 1);
assert ((RetVF == 1 || VF == 1) && "VF > 1 and RetVF is a vector type");
switch (IID) {
default: {
// Assume that we need to scalarize this intrinsic.
SmallVector<Type *, 4> Types;
for (Value *Op : Args)
Types.push_back(Op->getType());
return static_cast<T *>(this)->getIntrinsicInstrCost(IID, RetTy, Types,
FMF);
for (Value *Op : Args) {
Type *OpTy = Op->getType();
assert (VF == 1 || !OpTy->isVectorTy());
Types.push_back(VF == 1 ? OpTy : VectorType::get(OpTy, VF));
}
if (VF > 1 && !RetTy->isVoidTy())
RetTy = VectorType::get(RetTy, VF);
// Compute the scalarization overhead based on Args for a vector
// intrinsic. A vectorizer will pass a scalar RetTy and VF > 1, while
// CostModel will pass a vector RetTy and VF is 1.
unsigned ScalarizationCost = UINT_MAX;
if (RetVF > 1 || VF > 1) {
ScalarizationCost = 0;
if (!RetTy->isVoidTy())
ScalarizationCost += getScalarizationOverhead(RetTy, true, false);
ScalarizationCost += getOperandsScalarizationOverhead(Args, VF);
}
return static_cast<T *>(this)->
getIntrinsicInstrCost(IID, RetTy, Types, FMF, ScalarizationCost);
}
case Intrinsic::masked_scatter: {
assert (VF == 1 && "Can't vectorize types here.");
Value *Mask = Args[3];
bool VarMask = !isa<Constant>(Mask);
unsigned Alignment = cast<ConstantInt>(Args[2])->getZExtValue();
@ -702,6 +787,7 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
Alignment);
}
case Intrinsic::masked_gather: {
assert (VF == 1 && "Can't vectorize types here.");
Value *Mask = Args[2];
bool VarMask = !isa<Constant>(Mask);
unsigned Alignment = cast<ConstantInt>(Args[1])->getZExtValue();
@ -713,19 +799,23 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
}
}
/// Get intrinsic cost based on argument types
/// Get intrinsic cost based on argument types.
/// If ScalarizationCostPassed is UINT_MAX, the cost of scalarizing the
/// arguments and the return value will be computed based on types.
unsigned getIntrinsicInstrCost(Intrinsic::ID IID, Type *RetTy,
ArrayRef<Type *> Tys, FastMathFlags FMF) {
ArrayRef<Type *> Tys, FastMathFlags FMF,
unsigned ScalarizationCostPassed = UINT_MAX) {
SmallVector<unsigned, 2> ISDs;
unsigned SingleCallCost = 10; // Library call cost. Make it expensive.
switch (IID) {
default: {
// Assume that we need to scalarize this intrinsic.
unsigned ScalarizationCost = 0;
unsigned ScalarizationCost = ScalarizationCostPassed;
unsigned ScalarCalls = 1;
Type *ScalarRetTy = RetTy;
if (RetTy->isVectorTy()) {
ScalarizationCost = getScalarizationOverhead(RetTy, true, false);
if (ScalarizationCostPassed == UINT_MAX)
ScalarizationCost = getScalarizationOverhead(RetTy, true, false);
ScalarCalls = std::max(ScalarCalls, RetTy->getVectorNumElements());
ScalarRetTy = RetTy->getScalarType();
}
@ -733,7 +823,8 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
for (unsigned i = 0, ie = Tys.size(); i != ie; ++i) {
Type *Ty = Tys[i];
if (Ty->isVectorTy()) {
ScalarizationCost += getScalarizationOverhead(Ty, false, true);
if (ScalarizationCostPassed == UINT_MAX)
ScalarizationCost += getScalarizationOverhead(Ty, false, true);
ScalarCalls = std::max(ScalarCalls, Ty->getVectorNumElements());
Ty = Ty->getScalarType();
}
@ -881,7 +972,8 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
// 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 ScalarizationCost = ((ScalarizationCostPassed != UINT_MAX) ?
ScalarizationCostPassed : getScalarizationOverhead(RetTy, true, false));
unsigned ScalarCalls = RetTy->getVectorNumElements();
SmallVector<Type *, 4> ScalarTys;
for (unsigned i = 0, ie = Tys.size(); i != ie; ++i) {
@ -894,7 +986,8 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
IID, RetTy->getScalarType(), ScalarTys, FMF);
for (unsigned i = 0, ie = Tys.size(); i != ie; ++i) {
if (Tys[i]->isVectorTy()) {
ScalarizationCost += getScalarizationOverhead(Tys[i], false, true);
if (ScalarizationCostPassed == UINT_MAX)
ScalarizationCost += getScalarizationOverhead(Tys[i], false, true);
ScalarCalls = std::max(ScalarCalls, Tys[i]->getVectorNumElements());
}
}

View File

@ -183,11 +183,6 @@ typedef bool CCCustomFn(unsigned &ValNo, MVT &ValVT,
MVT &LocVT, CCValAssign::LocInfo &LocInfo,
ISD::ArgFlagsTy &ArgFlags, CCState &State);
/// ParmContext - This enum tracks whether calling convention lowering is in
/// the context of prologue or call generation. Not all backends make use of
/// this information.
typedef enum { Unknown, Prologue, Call } ParmContext;
/// CCState - This class holds information needed while lowering arguments and
/// return values. It captures which registers are already assigned and which
/// stack slots are used. It provides accessors to allocate these values.
@ -256,9 +251,6 @@ class CCState {
// during argument analysis.
unsigned InRegsParamsProcessed;
protected:
ParmContext CallOrPrologue;
public:
CCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF,
SmallVectorImpl<CCValAssign> &locs, LLVMContext &C);
@ -510,8 +502,6 @@ class CCState {
InRegsParamsProcessed = 0;
}
ParmContext getCallOrPrologue() const { return CallOrPrologue; }
// Get list of pending assignments
SmallVectorImpl<llvm::CCValAssign> &getPendingLocs() {
return PendingLocs;

View File

@ -118,11 +118,6 @@ FileType("filetype", cl::init(TargetMachine::CGFT_AssemblyFile),
clEnumValN(TargetMachine::CGFT_Null, "null",
"Emit nothing, for performance testing")));
cl::opt<bool>
EnableFPMAD("enable-fp-mad",
cl::desc("Enable less precise MAD instructions to be generated"),
cl::init(false));
cl::opt<bool>
DisableFPElim("disable-fp-elim",
cl::desc("Disable frame pointer elimination optimization"),
@ -143,6 +138,12 @@ EnableNoNaNsFPMath("enable-no-nans-fp-math",
cl::desc("Enable FP math optimizations that assume no NaNs"),
cl::init(false));
cl::opt<bool>
EnableNoSignedZerosFPMath("enable-no-signed-zeros-fp-math",
cl::desc("Enable FP math optimizations that assume "
"the sign of 0 is insignificant"),
cl::init(false));
cl::opt<bool>
EnableNoTrappingFPMath("enable-no-trapping-fp-math",
cl::desc("Enable setting the FP exceptions build "
@ -277,11 +278,11 @@ DebuggerTuningOpt("debugger-tune",
// a TargetOptions object with CodeGen flags and returns it.
static inline TargetOptions InitTargetOptionsFromCodeGenFlags() {
TargetOptions Options;
Options.LessPreciseFPMADOption = EnableFPMAD;
Options.AllowFPOpFusion = FuseFPOps;
Options.UnsafeFPMath = EnableUnsafeFPMath;
Options.NoInfsFPMath = EnableNoInfsFPMath;
Options.NoNaNsFPMath = EnableNoNaNsFPMath;
Options.NoSignedZerosFPMath = EnableNoSignedZerosFPMath;
Options.NoTrappingFPMath = EnableNoTrappingFPMath;
Options.FPDenormalMode = DenormalMode;
Options.HonorSignDependentRoundingFPMathOption =
@ -345,28 +346,28 @@ static inline void setFunctionAttributes(StringRef CPU, StringRef Features,
Module &M) {
for (auto &F : M) {
auto &Ctx = F.getContext();
AttributeSet Attrs = F.getAttributes(), NewAttrs;
AttributeList Attrs = F.getAttributes(), NewAttrs;
if (!CPU.empty())
NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex,
NewAttrs = NewAttrs.addAttribute(Ctx, AttributeList::FunctionIndex,
"target-cpu", CPU);
if (!Features.empty())
NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex,
NewAttrs = NewAttrs.addAttribute(Ctx, AttributeList::FunctionIndex,
"target-features", Features);
if (DisableFPElim.getNumOccurrences() > 0)
NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex,
NewAttrs = NewAttrs.addAttribute(Ctx, AttributeList::FunctionIndex,
"no-frame-pointer-elim",
DisableFPElim ? "true" : "false");
if (DisableTailCalls.getNumOccurrences() > 0)
NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex,
NewAttrs = NewAttrs.addAttribute(Ctx, AttributeList::FunctionIndex,
"disable-tail-calls",
toStringRef(DisableTailCalls));
if (StackRealign)
NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex,
NewAttrs = NewAttrs.addAttribute(Ctx, AttributeList::FunctionIndex,
"stackrealign");
if (TrapFuncName.getNumOccurrences() > 0)
@ -376,12 +377,12 @@ static inline void setFunctionAttributes(StringRef CPU, StringRef Features,
if (const auto *F = Call->getCalledFunction())
if (F->getIntrinsicID() == Intrinsic::debugtrap ||
F->getIntrinsicID() == Intrinsic::trap)
Call->addAttribute(llvm::AttributeSet::FunctionIndex,
Attribute::get(Ctx, "trap-func-name",
TrapFuncName));
Call->addAttribute(
llvm::AttributeList::FunctionIndex,
Attribute::get(Ctx, "trap-func-name", TrapFuncName));
// Let NewAttrs override Attrs.
NewAttrs = Attrs.addAttributes(Ctx, AttributeSet::FunctionIndex, NewAttrs);
NewAttrs = Attrs.addAttributes(Ctx, AttributeList::FunctionIndex, NewAttrs);
F.setAttributes(NewAttrs);
}
}

View File

@ -0,0 +1,220 @@
//===- llvm/CodeGen/ExecutionDepsFix.h - Execution Dependency Fix -*- C++ -*-=//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
/// \file Execution Dependency Fix pass.
///
/// Some X86 SSE instructions like mov, and, or, xor are available in different
/// variants for different operand types. These variant instructions are
/// equivalent, but on Nehalem and newer cpus there is extra latency
/// transferring data between integer and floating point domains. ARM cores
/// have similar issues when they are configured with both VFP and NEON
/// pipelines.
///
/// This pass changes the variant instructions to minimize domain crossings.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_EXECUTIONDEPSFIX_H
#define LLVM_CODEGEN_EXECUTIONDEPSFIX_H
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/LivePhysRegs.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/RegisterClassInfo.h"
#include "llvm/Support/Allocator.h"
#include <vector>
namespace llvm {
/// A DomainValue is a bit like LiveIntervals' ValNo, but it also keeps track
/// of execution domains.
///
/// An open DomainValue represents a set of instructions that can still switch
/// execution domain. Multiple registers may refer to the same open
/// DomainValue - they will eventually be collapsed to the same execution
/// domain.
///
/// A collapsed DomainValue represents a single register that has been forced
/// into one of more execution domains. There is a separate collapsed
/// DomainValue for each register, but it may contain multiple execution
/// domains. A register value is initially created in a single execution
/// domain, but if we were forced to pay the penalty of a domain crossing, we
/// keep track of the fact that the register is now available in multiple
/// domains.
struct DomainValue {
// Basic reference counting.
unsigned Refs;
// Bitmask of available domains. For an open DomainValue, it is the still
// possible domains for collapsing. For a collapsed DomainValue it is the
// domains where the register is available for free.
unsigned AvailableDomains;
// Pointer to the next DomainValue in a chain. When two DomainValues are
// merged, Victim.Next is set to point to Victor, so old DomainValue
// references can be updated by following the chain.
DomainValue *Next;
// Twiddleable instructions using or defining these registers.
SmallVector<MachineInstr*, 8> Instrs;
// A collapsed DomainValue has no instructions to twiddle - it simply keeps
// track of the domains where the registers are already available.
bool isCollapsed() const { return Instrs.empty(); }
// Is domain available?
bool hasDomain(unsigned domain) const {
assert(domain <
static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
"undefined behavior");
return AvailableDomains & (1u << domain);
}
// Mark domain as available.
void addDomain(unsigned domain) {
AvailableDomains |= 1u << domain;
}
// Restrict to a single domain available.
void setSingleDomain(unsigned domain) {
AvailableDomains = 1u << domain;
}
// Return bitmask of domains that are available and in mask.
unsigned getCommonDomains(unsigned mask) const {
return AvailableDomains & mask;
}
// First domain available.
unsigned getFirstDomain() const {
return countTrailingZeros(AvailableDomains);
}
DomainValue() : Refs(0) { clear(); }
// Clear this DomainValue and point to next which has all its data.
void clear() {
AvailableDomains = 0;
Next = nullptr;
Instrs.clear();
}
};
/// Information about a live register.
struct LiveReg {
/// Value currently in this register, or NULL when no value is being tracked.
/// This counts as a DomainValue reference.
DomainValue *Value;
/// Instruction that defined this register, relative to the beginning of the
/// current basic block. When a LiveReg is used to represent a live-out
/// register, this value is relative to the end of the basic block, so it
/// will be a negative number.
int Def;
};
class ExecutionDepsFix : public MachineFunctionPass {
SpecificBumpPtrAllocator<DomainValue> Allocator;
SmallVector<DomainValue*,16> Avail;
const TargetRegisterClass *const RC;
MachineFunction *MF;
const TargetInstrInfo *TII;
const TargetRegisterInfo *TRI;
RegisterClassInfo RegClassInfo;
std::vector<SmallVector<int, 1>> AliasMap;
const unsigned NumRegs;
LiveReg *LiveRegs;
struct MBBInfo {
// Keeps clearance and domain information for all registers. Note that this
// is different from the usual definition notion of liveness. The CPU
// doesn't care whether or not we consider a register killed.
LiveReg *OutRegs;
// Whether we have gotten to this block in primary processing yet.
bool PrimaryCompleted;
// The number of predecessors for which primary processing has completed
unsigned IncomingProcessed;
// The value of `IncomingProcessed` at the start of primary processing
unsigned PrimaryIncoming;
// The number of predecessors for which all processing steps are done.
unsigned IncomingCompleted;
MBBInfo()
: OutRegs(nullptr), PrimaryCompleted(false), IncomingProcessed(0),
PrimaryIncoming(0), IncomingCompleted(0) {}
};
typedef DenseMap<MachineBasicBlock *, MBBInfo> MBBInfoMap;
MBBInfoMap MBBInfos;
/// List of undefined register reads in this block in forward order.
std::vector<std::pair<MachineInstr*, unsigned> > UndefReads;
/// Storage for register unit liveness.
LivePhysRegs LiveRegSet;
/// Current instruction number.
/// The first instruction in each basic block is 0.
int CurInstr;
public:
ExecutionDepsFix(char &PassID, const TargetRegisterClass &RC)
: MachineFunctionPass(PassID), RC(&RC), NumRegs(RC.getNumRegs()) {}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
MachineFunctionPass::getAnalysisUsage(AU);
}
bool runOnMachineFunction(MachineFunction &MF) override;
MachineFunctionProperties getRequiredProperties() const override {
return MachineFunctionProperties().set(
MachineFunctionProperties::Property::NoVRegs);
}
private:
iterator_range<SmallVectorImpl<int>::const_iterator>
regIndices(unsigned Reg) const;
// DomainValue allocation.
DomainValue *alloc(int domain = -1);
DomainValue *retain(DomainValue *DV) {
if (DV) ++DV->Refs;
return DV;
}
void release(DomainValue*);
DomainValue *resolve(DomainValue*&);
// LiveRegs manipulations.
void setLiveReg(int rx, DomainValue *DV);
void kill(int rx);
void force(int rx, unsigned domain);
void collapse(DomainValue *dv, unsigned domain);
bool merge(DomainValue *A, DomainValue *B);
void enterBasicBlock(MachineBasicBlock*);
void leaveBasicBlock(MachineBasicBlock*);
bool isBlockDone(MachineBasicBlock *);
void processBasicBlock(MachineBasicBlock *MBB, bool PrimaryPass);
bool visitInstr(MachineInstr *);
void processDefs(MachineInstr *, bool breakDependency, bool Kill);
void visitSoftInstr(MachineInstr*, unsigned mask);
void visitHardInstr(MachineInstr*, unsigned domain);
bool pickBestRegisterForUndef(MachineInstr *MI, unsigned OpIdx,
unsigned Pref);
bool shouldBreakDependence(MachineInstr*, unsigned OpIdx, unsigned Pref);
void processUndefReads(MachineBasicBlock*);
};
} // end namepsace llvm
#endif

View File

@ -1,4 +1,4 @@
//===-- FastISel.h - Definition of the FastISel class ---*- C++ -*---------===//
//===- FastISel.h - Definition of the FastISel class ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -16,10 +16,21 @@
#define LLVM_CODEGEN_FASTISEL_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineValueType.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/Target/TargetLowering.h"
#include <algorithm>
#include <cstdint>
#include <utility>
#include <vector>
namespace llvm {
@ -30,57 +41,31 @@ class MachineConstantPool;
/// quickly.
class FastISel {
public:
struct ArgListEntry {
Value *Val;
Type *Ty;
bool IsSExt : 1;
bool IsZExt : 1;
bool IsInReg : 1;
bool IsSRet : 1;
bool IsNest : 1;
bool IsByVal : 1;
bool IsInAlloca : 1;
bool IsReturned : 1;
bool IsSwiftSelf : 1;
bool IsSwiftError : 1;
uint16_t Alignment;
ArgListEntry()
: Val(nullptr), Ty(nullptr), IsSExt(false), IsZExt(false),
IsInReg(false), IsSRet(false), IsNest(false), IsByVal(false),
IsInAlloca(false), IsReturned(false), IsSwiftSelf(false),
IsSwiftError(false), Alignment(0) {}
/// \brief Set CallLoweringInfo attribute flags based on a call instruction
/// and called function attributes.
void setAttributes(ImmutableCallSite *CS, unsigned AttrIdx);
};
typedef std::vector<ArgListEntry> ArgListTy;
typedef TargetLoweringBase::ArgListEntry ArgListEntry;
typedef TargetLoweringBase::ArgListTy ArgListTy;
struct CallLoweringInfo {
Type *RetTy;
Type *RetTy = nullptr;
bool RetSExt : 1;
bool RetZExt : 1;
bool IsVarArg : 1;
bool IsInReg : 1;
bool DoesNotReturn : 1;
bool IsReturnValueUsed : 1;
bool IsPatchPoint : 1;
// \brief IsTailCall Should be modified by implementations of FastLowerCall
// that perform tail call conversions.
bool IsTailCall;
bool IsTailCall = false;
unsigned NumFixedArgs;
CallingConv::ID CallConv;
const Value *Callee;
MCSymbol *Symbol;
unsigned NumFixedArgs = -1;
CallingConv::ID CallConv = CallingConv::C;
const Value *Callee = nullptr;
MCSymbol *Symbol = nullptr;
ArgListTy Args;
ImmutableCallSite *CS;
MachineInstr *Call;
unsigned ResultReg;
unsigned NumResultRegs;
bool IsPatchPoint;
ImmutableCallSite *CS = nullptr;
MachineInstr *Call = nullptr;
unsigned ResultReg = 0;
unsigned NumResultRegs = 0;
SmallVector<Value *, 16> OutVals;
SmallVector<ISD::ArgFlagsTy, 16> OutFlags;
@ -89,11 +74,8 @@ class FastISel {
SmallVector<unsigned, 4> InRegs;
CallLoweringInfo()
: RetTy(nullptr), RetSExt(false), RetZExt(false), IsVarArg(false),
IsInReg(false), DoesNotReturn(false), IsReturnValueUsed(true),
IsTailCall(false), NumFixedArgs(-1), CallConv(CallingConv::C),
Callee(nullptr), Symbol(nullptr), CS(nullptr), Call(nullptr),
ResultReg(0), NumResultRegs(0), IsPatchPoint(false) {}
: RetSExt(false), RetZExt(false), IsVarArg(false), IsInReg(false),
DoesNotReturn(false), IsReturnValueUsed(true), IsPatchPoint(false) {}
CallLoweringInfo &setCallee(Type *ResultTy, FunctionType *FuncTy,
const Value *Target, ArgListTy &&ArgsList,
@ -101,12 +83,12 @@ class FastISel {
RetTy = ResultTy;
Callee = Target;
IsInReg = Call.paramHasAttr(0, Attribute::InReg);
IsInReg = Call.hasRetAttr(Attribute::InReg);
DoesNotReturn = Call.doesNotReturn();
IsVarArg = FuncTy->isVarArg();
IsReturnValueUsed = !Call.getInstruction()->use_empty();
RetSExt = Call.paramHasAttr(0, Attribute::SExt);
RetZExt = Call.paramHasAttr(0, Attribute::ZExt);
RetSExt = Call.hasRetAttr(Attribute::SExt);
RetZExt = Call.hasRetAttr(Attribute::ZExt);
CallConv = Call.getCallingConv();
Args = std::move(ArgsList);
@ -125,12 +107,12 @@ class FastISel {
Callee = Call.getCalledValue();
Symbol = Target;
IsInReg = Call.paramHasAttr(0, Attribute::InReg);
IsInReg = Call.hasRetAttr(Attribute::InReg);
DoesNotReturn = Call.doesNotReturn();
IsVarArg = FuncTy->isVarArg();
IsReturnValueUsed = !Call.getInstruction()->use_empty();
RetSExt = Call.paramHasAttr(0, Attribute::SExt);
RetZExt = Call.paramHasAttr(0, Attribute::ZExt);
RetSExt = Call.hasRetAttr(Attribute::SExt);
RetZExt = Call.hasRetAttr(Attribute::ZExt);
CallConv = Call.getCallingConv();
Args = std::move(ArgsList);
@ -510,7 +492,6 @@ class FastISel {
}
}
bool lowerCall(const CallInst *I);
/// \brief Select and emit code for a binary operator instruction, which has
/// an opcode which directly corresponds to the given ISD opcode.
@ -567,4 +548,4 @@ class FastISel {
} // end namespace llvm
#endif
#endif // LLVM_CODEGEN_FASTISEL_H

View File

@ -1,4 +1,4 @@
//===------------------- FaultMaps.h - The "FaultMaps" section --*- C++ -*-===//
//===- FaultMaps.h - The "FaultMaps" section --------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -12,26 +12,31 @@
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Format.h"
#include <vector>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <map>
#include <vector>
namespace llvm {
class AsmPrinter;
class MCExpr;
class MCSymbol;
class MCStreamer;
class raw_ostream;
class FaultMaps {
public:
enum FaultKind { FaultingLoad = 1, FaultKindMax };
static const char *faultTypeToString(FaultKind);
enum FaultKind {
FaultingLoad = 1,
FaultingLoadStore,
FaultingStore,
FaultKindMax
};
explicit FaultMaps(AsmPrinter &AP);
static const char *faultTypeToString(FaultKind);
void recordFaultingOp(FaultKind FaultTy, const MCSymbol *HandlerLabel);
void serializeToFaultMapSection();
@ -39,13 +44,11 @@ class FaultMaps {
static const char *WFMP;
struct FaultInfo {
FaultKind Kind;
const MCExpr *FaultingOffsetExpr;
const MCExpr *HandlerOffsetExpr;
FaultKind Kind = FaultKindMax;
const MCExpr *FaultingOffsetExpr = nullptr;
const MCExpr *HandlerOffsetExpr = nullptr;
FaultInfo()
: Kind(FaultKindMax), FaultingOffsetExpr(nullptr),
HandlerOffsetExpr(nullptr) {}
FaultInfo() = default;
explicit FaultInfo(FaultMaps::FaultKind Kind, const MCExpr *FaultingOffset,
const MCExpr *HandlerOffset)
@ -153,11 +156,11 @@ class FaultMapParser {
static const size_t FunctionInfoHeaderSize = FunctionFaultInfosOffset;
const uint8_t *P;
const uint8_t *E;
const uint8_t *P = nullptr;
const uint8_t *E = nullptr;
public:
FunctionInfoAccessor() : P(nullptr), E(nullptr) {}
FunctionInfoAccessor() = default;
explicit FunctionInfoAccessor(const uint8_t *P, const uint8_t *E)
: P(P), E(E) {}
@ -214,6 +217,6 @@ raw_ostream &operator<<(raw_ostream &OS,
raw_ostream &operator<<(raw_ostream &OS, const FaultMapParser &);
} // namespace llvm
} // end namespace llvm
#endif
#endif // LLVM_CODEGEN_FAULTMAPS_H

View File

@ -1,4 +1,4 @@
//===-- llvm/CodeGen/GCStrategy.h - Garbage collection ----------*- C++ -*-===//
//===- llvm/CodeGen/GCStrategy.h - Garbage collection -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -47,19 +47,20 @@
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_IR_GCSTRATEGY_H
#define LLVM_IR_GCSTRATEGY_H
#ifndef LLVM_CODEGEN_GCSTRATEGY_H
#define LLVM_CODEGEN_GCSTRATEGY_H
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Registry.h"
#include <string>
namespace llvm {
class Type;
namespace GC {
/// PointKind - Used to indicate whether the address of the call instruction
/// or the address after the call instruction is listed in the stackmap. For
/// most runtimes, PostCall safepoints are appropriate.
@ -68,7 +69,8 @@ enum PointKind {
PreCall, ///< Instr is a call instruction.
PostCall ///< Instr is the return address of a call.
};
}
} // end namespace GC
/// GCStrategy describes a garbage collector algorithm's code generation
/// requirements, and provides overridable hooks for those needs which cannot
@ -77,24 +79,25 @@ enum PointKind {
/// be immutable.
class GCStrategy {
private:
std::string Name;
friend class GCModuleInfo;
protected:
bool UseStatepoints; /// Uses gc.statepoints as opposed to gc.roots,
/// if set, none of the other options can be
/// anything but their default values.
std::string Name;
unsigned NeededSafePoints; ///< Bitmask of required safe points.
bool CustomReadBarriers; ///< Default is to insert loads.
bool CustomWriteBarriers; ///< Default is to insert stores.
bool CustomRoots; ///< Default is to pass through to backend.
bool InitRoots; ///< If set, roots are nulled during lowering.
bool UsesMetadata; ///< If set, backend must emit metadata tables.
protected:
bool UseStatepoints = false; /// Uses gc.statepoints as opposed to gc.roots,
/// if set, none of the other options can be
/// anything but their default values.
unsigned NeededSafePoints = 0; ///< Bitmask of required safe points.
bool CustomReadBarriers = false; ///< Default is to insert loads.
bool CustomWriteBarriers = false; ///< Default is to insert stores.
bool CustomRoots = false; ///< Default is to pass through to backend.
bool InitRoots= true; ///< If set, roots are nulled during lowering.
bool UsesMetadata = false; ///< If set, backend must emit metadata tables.
public:
GCStrategy();
virtual ~GCStrategy() {}
virtual ~GCStrategy() = default;
/// Return the name of the GC strategy. This is the value of the collector
/// name string specified on functions which use this strategy.
@ -172,6 +175,7 @@ class GCStrategy {
/// register your GCMetadataPrinter subclass with the
/// GCMetadataPrinterRegistery as well.
typedef Registry<GCStrategy> GCRegistry;
}
#endif
} // end namespace llvm
#endif // LLVM_CODEGEN_GCSTRATEGY_H

View File

@ -35,9 +35,11 @@ class CallLowering {
unsigned Reg;
Type *Ty;
ISD::ArgFlagsTy Flags;
bool IsFixed;
ArgInfo(unsigned Reg, Type *Ty, ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy{})
: Reg(Reg), Ty(Ty), Flags(Flags) {}
ArgInfo(unsigned Reg, Type *Ty, ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy{},
bool IsFixed = true)
: Reg(Reg), Ty(Ty), Flags(Flags), IsFixed(IsFixed) {}
};
/// Argument handling is mostly uniform between the four places that
@ -68,15 +70,34 @@ class CallLowering {
uint64_t Size, MachinePointerInfo &MPO,
CCValAssign &VA) = 0;
/// Handle custom values, which may be passed into one or more of \p VAs.
/// \return The number of \p VAs that have been assigned after the first
/// one, and which should therefore be skipped from further
/// processing.
virtual unsigned assignCustomValue(const ArgInfo &Arg,
ArrayRef<CCValAssign> VAs) {
// This is not a pure virtual method because not all targets need to worry
// about custom values.
llvm_unreachable("Custom values not supported");
}
unsigned extendRegister(unsigned ValReg, CCValAssign &VA);
ValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
: MIRBuilder(MIRBuilder), MRI(MRI) {}
virtual bool assignArg(unsigned ValNo, MVT ValVT, MVT LocVT,
CCValAssign::LocInfo LocInfo, const ArgInfo &Info,
CCState &State) {
return AssignFn(ValNo, ValVT, LocVT, LocInfo, Info.Flags, State);
}
ValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
CCAssignFn *AssignFn)
: MIRBuilder(MIRBuilder), MRI(MRI), AssignFn(AssignFn) {}
virtual ~ValueHandler() {}
MachineIRBuilder &MIRBuilder;
MachineRegisterInfo &MRI;
CCAssignFn *AssignFn;
};
protected:
@ -96,12 +117,12 @@ class CallLowering {
void setArgFlags(ArgInfo &Arg, unsigned OpNum, const DataLayout &DL,
const FuncInfoTy &FuncInfo) const;
/// Invoke the \p AssignFn on each of the given \p Args and then use
/// Invoke Handler::assignArg on each of the given \p Args and then use
/// \p Callback to move them to the assigned locations.
///
/// \return True if everything has succeeded, false otherwise.
bool handleAssignments(MachineIRBuilder &MIRBuilder, CCAssignFn *AssignFn,
ArrayRef<ArgInfo> Args, ValueHandler &Callback) const;
bool handleAssignments(MachineIRBuilder &MIRBuilder, ArrayRef<ArgInfo> Args,
ValueHandler &Callback) const;
public:
CallLowering(const TargetLowering *TLI) : TLI(TLI) {}
@ -135,6 +156,8 @@ class CallLowering {
/// This hook must be implemented to lower the given call instruction,
/// including argument and return value marshalling.
///
/// \p CallConv is the calling convention to be used for the call.
///
/// \p Callee is the destination of the call. It should be either a register,
/// globaladdress, or externalsymbol.
///
@ -150,14 +173,16 @@ class CallLowering {
/// needs to be passed.
///
/// \return true if the lowering succeeded, false otherwise.
virtual bool lowerCall(MachineIRBuilder &MIRBuilder,
virtual bool lowerCall(MachineIRBuilder &MIRBuilder, CallingConv::ID CallConv,
const MachineOperand &Callee, const ArgInfo &OrigRet,
ArrayRef<ArgInfo> OrigArgs) const {
return false;
}
/// This hook must be implemented to lower the given call instruction,
/// including argument and return value marshalling.
/// Lower the given call instruction, including argument and return value
/// marshalling.
///
/// \p CI is the call/invoke instruction.
///
/// \p ResReg is a register where the call's return value should be stored (or
/// 0 if there is no return value).
@ -171,9 +196,9 @@ class CallLowering {
/// range of an immediate jump.
///
/// \return true if the lowering succeeded, false otherwise.
virtual bool lowerCall(MachineIRBuilder &MIRBuilder, const CallInst &CI,
unsigned ResReg, ArrayRef<unsigned> ArgRegs,
std::function<unsigned()> GetCalleeReg) const;
bool lowerCall(MachineIRBuilder &MIRBuilder, ImmutableCallSite CS,
unsigned ResReg, ArrayRef<unsigned> ArgRegs,
std::function<unsigned()> GetCalleeReg) const;
};
} // End namespace llvm.

View File

@ -34,6 +34,7 @@ class Instruction;
class MachineBasicBlock;
class MachineFunction;
class MachineInstr;
class OptimizationRemarkEmitter;
class MachineRegisterInfo;
class TargetPassConfig;
@ -55,21 +56,20 @@ class IRTranslator : public MachineFunctionPass {
/// Mapping of the values of the current LLVM IR function
/// to the related virtual registers.
ValueToVReg ValToVReg;
// Constants are special because when we encounter one,
// we do not know at first where to insert the definition since
// this depends on all its uses.
// Thus, we will insert the sequences to materialize them when
// we know all their users.
// In the meantime, just keep it in a set.
// Note: Constants that end up as immediate in the related instructions,
// do not appear in that map.
SmallSetVector<const Constant *, 8> Constants;
// N.b. it's not completely obvious that this will be sufficient for every
// LLVM IR construct (with "invoke" being the obvious candidate to mess up our
// lives.
DenseMap<const BasicBlock *, MachineBasicBlock *> BBToMBB;
// One BasicBlock can be translated to multiple MachineBasicBlocks. For such
// BasicBlocks translated to multiple MachineBasicBlocks, MachinePreds retains
// a mapping between the edges arriving at the BasicBlock to the corresponding
// created MachineBasicBlocks. Some BasicBlocks that get translated to a
// single MachineBasicBlock may also end up in this Map.
typedef std::pair<const BasicBlock *, const BasicBlock *> CFGEdge;
DenseMap<CFGEdge, SmallVector<MachineBasicBlock *, 1>> MachinePreds;
// List of stubbed PHI instructions, for values and basic blocks to be filled
// in once all MachineBasicBlocks have been created.
SmallVector<std::pair<const PHINode *, MachineInstr *>, 4> PendingPHIs;
@ -122,7 +122,9 @@ class IRTranslator : public MachineFunctionPass {
/// Translate an LLVM store instruction into generic IR.
bool translateStore(const User &U, MachineIRBuilder &MIRBuilder);
bool translateMemcpy(const CallInst &CI, MachineIRBuilder &MIRBuilder);
/// Translate an LLVM string intrinsic (memcpy, memset, ...).
bool translateMemfunc(const CallInst &CI, MachineIRBuilder &MIRBuilder,
unsigned Intrinsic);
void getStackGuard(unsigned DstReg, MachineIRBuilder &MIRBuilder);
@ -132,6 +134,8 @@ class IRTranslator : public MachineFunctionPass {
bool translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
MachineIRBuilder &MIRBuilder);
bool translateInlineAsm(const CallInst &CI, MachineIRBuilder &MIRBuilder);
/// Translate call instruction.
/// \pre \p U is a call instruction.
bool translateCall(const User &U, MachineIRBuilder &MIRBuilder);
@ -145,11 +149,6 @@ class IRTranslator : public MachineFunctionPass {
bool translateCast(unsigned Opcode, const User &U,
MachineIRBuilder &MIRBuilder);
/// Translate static alloca instruction (i.e. one of constant size and in the
/// first basic block).
bool translateStaticAlloca(const AllocaInst &Inst,
MachineIRBuilder &MIRBuilder);
/// Translate a phi instruction.
bool translatePHI(const User &U, MachineIRBuilder &MIRBuilder);
@ -182,6 +181,8 @@ class IRTranslator : public MachineFunctionPass {
bool translateSwitch(const User &U, MachineIRBuilder &MIRBuilder);
bool translateIndirectBr(const User &U, MachineIRBuilder &MIRBuilder);
bool translateExtractValue(const User &U, MachineIRBuilder &MIRBuilder);
bool translateInsertValue(const User &U, MachineIRBuilder &MIRBuilder);
@ -190,12 +191,16 @@ class IRTranslator : public MachineFunctionPass {
bool translateGetElementPtr(const User &U, MachineIRBuilder &MIRBuilder);
bool translateAlloca(const User &U, MachineIRBuilder &MIRBuilder);
/// Translate return (ret) instruction.
/// The target needs to implement CallLowering::lowerReturn for
/// this to succeed.
/// \pre \p U is a return instruction.
bool translateRet(const User &U, MachineIRBuilder &MIRBuilder);
bool translateFSub(const User &U, MachineIRBuilder &MIRBuilder);
bool translateAdd(const User &U, MachineIRBuilder &MIRBuilder) {
return translateBinaryOp(TargetOpcode::G_ADD, U, MIRBuilder);
}
@ -227,9 +232,6 @@ class IRTranslator : public MachineFunctionPass {
bool translateSRem(const User &U, MachineIRBuilder &MIRBuilder) {
return translateBinaryOp(TargetOpcode::G_SREM, U, MIRBuilder);
}
bool translateAlloca(const User &U, MachineIRBuilder &MIRBuilder) {
return translateStaticAlloca(cast<AllocaInst>(U), MIRBuilder);
}
bool translateIntToPtr(const User &U, MachineIRBuilder &MIRBuilder) {
return translateCast(TargetOpcode::G_INTTOPTR, U, MIRBuilder);
}
@ -281,9 +283,6 @@ class IRTranslator : public MachineFunctionPass {
bool translateFAdd(const User &U, MachineIRBuilder &MIRBuilder) {
return translateBinaryOp(TargetOpcode::G_FADD, U, MIRBuilder);
}
bool translateFSub(const User &U, MachineIRBuilder &MIRBuilder) {
return translateBinaryOp(TargetOpcode::G_FSUB, U, MIRBuilder);
}
bool translateFMul(const User &U, MachineIRBuilder &MIRBuilder) {
return translateBinaryOp(TargetOpcode::G_FMUL, U, MIRBuilder);
}
@ -294,11 +293,16 @@ class IRTranslator : public MachineFunctionPass {
return translateBinaryOp(TargetOpcode::G_FREM, U, MIRBuilder);
}
bool translateVAArg(const User &U, MachineIRBuilder &MIRBuilder);
bool translateInsertElement(const User &U, MachineIRBuilder &MIRBuilder);
bool translateExtractElement(const User &U, MachineIRBuilder &MIRBuilder);
bool translateShuffleVector(const User &U, MachineIRBuilder &MIRBuilder);
// Stubs to keep the compiler happy while we implement the rest of the
// translation.
bool translateIndirectBr(const User &U, MachineIRBuilder &MIRBuilder) {
return false;
}
bool translateResume(const User &U, MachineIRBuilder &MIRBuilder) {
return false;
}
@ -335,18 +339,6 @@ class IRTranslator : public MachineFunctionPass {
bool translateUserOp2(const User &U, MachineIRBuilder &MIRBuilder) {
return false;
}
bool translateVAArg(const User &U, MachineIRBuilder &MIRBuilder) {
return false;
}
bool translateExtractElement(const User &U, MachineIRBuilder &MIRBuilder) {
return false;
}
bool translateInsertElement(const User &U, MachineIRBuilder &MIRBuilder) {
return false;
}
bool translateShuffleVector(const User &U, MachineIRBuilder &MIRBuilder) {
return false;
}
/// @}
@ -371,6 +363,9 @@ class IRTranslator : public MachineFunctionPass {
/// Current target configuration. Controls how the pass handles errors.
const TargetPassConfig *TPC;
/// Current optimization remark emitter. Used to report failures.
std::unique_ptr<OptimizationRemarkEmitter> ORE;
// * Insert all the code needed to materialize the constants
// at the proper place. E.g., Entry block or dominator block
// of each constant depending on how fancy we want to be.
@ -390,10 +385,27 @@ class IRTranslator : public MachineFunctionPass {
/// the type being accessed (according to the Module's DataLayout).
unsigned getMemOpAlignment(const Instruction &I);
/// Get the MachineBasicBlock that represents \p BB.
/// If such basic block does not exist, it is created.
MachineBasicBlock &getOrCreateBB(const BasicBlock &BB);
/// Get the MachineBasicBlock that represents \p BB. Specifically, the block
/// returned will be the head of the translated block (suitable for branch
/// destinations).
MachineBasicBlock &getMBB(const BasicBlock &BB);
/// Record \p NewPred as a Machine predecessor to `Edge.second`, corresponding
/// to `Edge.first` at the IR level. This is used when IRTranslation creates
/// multiple MachineBasicBlocks for a given IR block and the CFG is no longer
/// represented simply by the IR-level CFG.
void addMachineCFGPred(CFGEdge Edge, MachineBasicBlock *NewPred);
/// Returns the Machine IR predecessors for the given IR CFG edge. Usually
/// this is just the single MachineBasicBlock corresponding to the predecessor
/// in the IR. More complex lowering can result in multiple MachineBasicBlocks
/// preceding the original though (e.g. switch instructions).
SmallVector<MachineBasicBlock *, 1> getMachinePredBBs(CFGEdge Edge) {
auto RemappedEdge = MachinePreds.find(Edge);
if (RemappedEdge != MachinePreds.end())
return RemappedEdge->second;
return SmallVector<MachineBasicBlock *, 4>(1, &getMBB(*Edge.first));
}
public:
// Ctor, nothing fancy.
@ -407,13 +419,13 @@ class IRTranslator : public MachineFunctionPass {
// CallLowering = MF.subtarget.getCallLowering()
// F = MF.getParent()
// MIRBuilder.reset(MF)
// MIRBuilder.getOrCreateBB(F.getEntryBB())
// getMBB(F.getEntryBB())
// CallLowering->translateArguments(MIRBuilder, F, ValToVReg)
// for each bb in F
// MIRBuilder.getOrCreateBB(bb)
// getMBB(bb)
// for each inst in bb
// if (!translate(MIRBuilder, inst, ValToVReg, ConstantToSequence))
// report_fatal_error(“Dont know how to translate input");
// report_fatal_error("Don't know how to translate input");
// finalize()
bool runOnMachineFunction(MachineFunction &MF) override;
};

View File

@ -16,8 +16,13 @@
#ifndef LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTOR_H
#define LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTOR_H
#include "llvm/ADT/Optional.h"
#include <cstdint>
namespace llvm {
class MachineInstr;
class MachineOperand;
class MachineRegisterInfo;
class RegisterBankInfo;
class TargetInstrInfo;
class TargetRegisterInfo;
@ -56,6 +61,14 @@ class InstructionSelector {
const TargetInstrInfo &TII,
const TargetRegisterInfo &TRI,
const RegisterBankInfo &RBI) const;
Optional<int64_t> getConstantVRegVal(unsigned VReg,
const MachineRegisterInfo &MRI) const;
bool isOperandImmEqual(const MachineOperand &MO, int64_t Value,
const MachineRegisterInfo &MRI) const;
bool isObviouslySafeToFold(MachineInstr &MI) const;
};
} // End namespace llvm.

View File

@ -58,6 +58,9 @@ class Legalizer : public MachineFunctionPass {
bool combineExtracts(MachineInstr &MI, MachineRegisterInfo &MRI,
const TargetInstrInfo &TII);
bool combineMerges(MachineInstr &MI, MachineRegisterInfo &MRI,
const TargetInstrInfo &TII);
bool runOnMachineFunction(MachineFunction &MF) override;
};
} // End namespace llvm.

View File

@ -55,11 +55,7 @@ class LegalizerHelper {
///
/// Considered as an opaque blob, the legal code will use and define the same
/// registers as \p MI.
LegalizeResult legalizeInstrStep(MachineInstr &MI,
const LegalizerInfo &LegalizerInfo);
LegalizeResult legalizeInstr(MachineInstr &MI,
const LegalizerInfo &LegalizerInfo);
LegalizeResult legalizeInstrStep(MachineInstr &MI);
/// Legalize an instruction by emiting a runtime library call instead.
LegalizeResult libcall(MachineInstr &MI);
@ -87,6 +83,10 @@ class LegalizerHelper {
LegalizeResult moreElementsVector(MachineInstr &MI, unsigned TypeIdx,
LLT WideTy);
/// Expose MIRBuilder so clients can set their own RecordInsertInstruction
/// functions
MachineIRBuilder MIRBuilder;
private:
/// Helper function to split a wide generic register into bitwise blocks with
@ -95,8 +95,8 @@ class LegalizerHelper {
void extractParts(unsigned Reg, LLT Ty, int NumParts,
SmallVectorImpl<unsigned> &Ops);
MachineIRBuilder MIRBuilder;
MachineRegisterInfo &MRI;
const LegalizerInfo &LI;
};
} // End namespace llvm.

View File

@ -25,6 +25,7 @@
namespace llvm {
class LLVMContext;
class MachineInstr;
class MachineIRBuilder;
class MachineRegisterInfo;
class Type;
class VectorType;
@ -96,6 +97,7 @@ class LegalizerInfo {
};
LegalizerInfo();
virtual ~LegalizerInfo() = default;
/// Compute any ancillary tables needed to quickly decide how an operation
/// should be handled. This must be called after all "set*Action"methods but
@ -144,7 +146,7 @@ class LegalizerInfo {
/// Iterate the given function (typically something like doubling the width)
/// on Ty until we find a legal type for this operation.
LLT findLegalType(const InstrAspect &Aspect,
std::function<LLT(LLT)> NextType) const {
function_ref<LLT(LLT)> NextType) const {
LegalizeAction Action;
const TypeMap &Map = Actions[Aspect.Opcode - FirstOp][Aspect.Idx];
LLT Ty = Aspect.Type;
@ -186,6 +188,10 @@ class LegalizerInfo {
bool isLegal(const MachineInstr &MI, const MachineRegisterInfo &MRI) const;
virtual bool legalizeCustom(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &MIRBuilder) const;
private:
static const int FirstOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_START;
static const int LastOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_END;

View File

@ -108,6 +108,9 @@ class MachineIRBuilder {
/// Set the debug location to \p DL for all the next build instructions.
void setDebugLoc(const DebugLoc &DL) { this->DL = DL; }
/// Get the current instruction's debug location.
DebugLoc getDebugLoc() { return DL; }
/// Build and insert <empty> = \p Opcode <empty>.
/// The insertion point is the one set by the last call of either
/// setBasicBlock or setMI.
@ -127,6 +130,29 @@ class MachineIRBuilder {
/// Insert an existing instruction at the insertion point.
MachineInstrBuilder insertInstr(MachineInstrBuilder MIB);
/// Build and insert a DBG_VALUE instruction expressing the fact that the
/// associated \p Variable lives in \p Reg (suitably modified by \p Expr).
MachineInstrBuilder buildDirectDbgValue(unsigned Reg, const MDNode *Variable,
const MDNode *Expr);
/// Build and insert a DBG_VALUE instruction expressing the fact that the
/// associated \p Variable lives in memory at \p Reg + \p Offset (suitably
/// modified by \p Expr).
MachineInstrBuilder buildIndirectDbgValue(unsigned Reg, unsigned Offset,
const MDNode *Variable,
const MDNode *Expr);
/// Build and insert a DBG_VALUE instruction expressing the fact that the
/// associated \p Variable lives in the stack slot specified by \p FI
/// (suitably modified by \p Expr).
MachineInstrBuilder buildFIDbgValue(int FI, const MDNode *Variable,
const MDNode *Expr);
/// Build and insert a DBG_VALUE instructions specifying that \p Variable is
/// given by \p C (suitably modified by \p Expr).
MachineInstrBuilder buildConstDbgValue(const Constant &C, unsigned Offset,
const MDNode *Variable,
const MDNode *Expr);
/// Build and insert \p Res<def> = G_FRAME_INDEX \p Idx
///
/// G_FRAME_INDEX materializes the address of an alloca value or other
@ -203,6 +229,22 @@ class MachineIRBuilder {
MachineInstrBuilder buildGEP(unsigned Res, unsigned Op0,
unsigned Op1);
/// Build and insert \p Res<def> = G_PTR_MASK \p Op0, \p NumBits
///
/// G_PTR_MASK clears the low bits of a pointer operand without destroying its
/// pointer properties. This has the effect of rounding the address *down* to
/// a specified alignment in bits.
///
/// \pre setBasicBlock or setMI must have been called.
/// \pre \p Res and \p Op0 must be generic virtual registers with pointer
/// type.
/// \pre \p NumBits must be an integer representing the number of low bits to
/// be cleared in \p Op0.
///
/// \return a MachineInstrBuilder for the newly created instruction.
MachineInstrBuilder buildPtrMask(unsigned Res, unsigned Op0,
uint32_t NumBits);
/// Build and insert \p Res<def>, \p CarryOut<def> = G_UADDE \p Op0,
/// \p Op1, \p CarryIn
///
@ -220,6 +262,19 @@ class MachineIRBuilder {
MachineInstrBuilder buildUAdde(unsigned Res, unsigned CarryOut, unsigned Op0,
unsigned Op1, unsigned CarryIn);
/// Build and insert \p Res<def> = G_AND \p Op0, \p Op1
///
/// G_AND sets \p Res to the bitwise and of integer parameters \p Op0 and \p
/// Op1.
///
/// \pre setBasicBlock or setMI must have been called.
/// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers
/// with the same (scalar or vector) type).
///
/// \return a MachineInstrBuilder for the newly created instruction.
MachineInstrBuilder buildAnd(unsigned Res, unsigned Op0,
unsigned Op1);
/// Build and insert \p Res<def> = G_ANYEXT \p Op0
///
/// G_ANYEXT produces a register of the specified width, with bits 0 to
@ -273,6 +328,19 @@ class MachineIRBuilder {
/// \return The newly created instruction.
MachineInstrBuilder buildSExtOrTrunc(unsigned Res, unsigned Op);
/// Build and insert \p Res<def> = G_ZEXT \p Op, \p Res = G_TRUNC \p Op, or
/// \p Res = COPY \p Op depending on the differing sizes of \p Res and \p Op.
/// ///
/// \pre setBasicBlock or setMI must have been called.
/// \pre \p Res must be a generic virtual register with scalar or vector type.
/// \pre \p Op must be a generic virtual register with scalar or vector type.
///
/// \return The newly created instruction.
MachineInstrBuilder buildZExtOrTrunc(unsigned Res, unsigned Op);
/// Build and insert an appropriate cast between two registers of equal size.
MachineInstrBuilder buildCast(unsigned Dst, unsigned Src);
/// Build and insert G_BR \p Dest
///
/// G_BR is an unconditional branch to \p Dest.
@ -296,6 +364,16 @@ class MachineIRBuilder {
/// \return The newly created instruction.
MachineInstrBuilder buildBrCond(unsigned Tst, MachineBasicBlock &BB);
/// Build and insert G_BRINDIRECT \p Tgt
///
/// G_BRINDIRECT is an indirect branch to \p Tgt.
///
/// \pre setBasicBlock or setMI must have been called.
/// \pre \p Tgt must be a generic virtual register with pointer type.
///
/// \return a MachineInstrBuilder for the newly created instruction.
MachineInstrBuilder buildBrIndirect(unsigned Tgt);
/// Build and insert \p Res = G_CONSTANT \p Val
///
/// G_CONSTANT is an integer constant with the specified size and value. \p
@ -362,19 +440,16 @@ class MachineIRBuilder {
MachineInstrBuilder buildStore(unsigned Val, unsigned Addr,
MachineMemOperand &MMO);
/// Build and insert `Res0<def>, ... = G_EXTRACT Src, Idx0, ...`.
///
/// If \p Res[i] has size N bits, G_EXTRACT sets \p Res[i] to bits `[Idxs[i],
/// Idxs[i] + N)` of \p Src.
/// Build and insert `Res0<def>, ... = G_EXTRACT Src, Idx0`.
///
/// \pre setBasicBlock or setMI must have been called.
/// \pre Indices must be in ascending order of bit position.
/// \pre Each member of \p Results and \p Src must be a generic
/// virtual register.
/// \pre \p Res and \p Src must be generic virtual registers.
///
/// \return a MachineInstrBuilder for the newly created instruction.
MachineInstrBuilder buildExtract(ArrayRef<unsigned> Results,
ArrayRef<uint64_t> Indices, unsigned Src);
MachineInstrBuilder buildExtract(unsigned Res, unsigned Src, uint64_t Index);
/// Build and insert \p Res = IMPLICIT_DEF.
MachineInstrBuilder buildUndef(unsigned Dst);
/// Build and insert \p Res<def> = G_SEQUENCE \p Op0, \p Idx0...
///
@ -393,6 +468,31 @@ class MachineIRBuilder {
ArrayRef<unsigned> Ops,
ArrayRef<uint64_t> Indices);
/// Build and insert \p Res<def> = G_MERGE_VALUES \p Op0, ...
///
/// G_MERGE_VALUES combines the input elements contiguously into a larger
/// register.
///
/// \pre setBasicBlock or setMI must have been called.
/// \pre The entire register \p Res (and no more) must be covered by the input
/// registers.
/// \pre The type of all \p Ops registers must be identical.
///
/// \return a MachineInstrBuilder for the newly created instruction.
MachineInstrBuilder buildMerge(unsigned Res, ArrayRef<unsigned> Ops);
/// Build and insert \p Res0<def>, ... = G_UNMERGE_VALUES \p Op
///
/// G_UNMERGE_VALUES splits contiguous bits of the input into multiple
///
/// \pre setBasicBlock or setMI must have been called.
/// \pre The entire register \p Res (and no more) must be covered by the input
/// registers.
/// \pre The type of all \p Res registers must be identical.
///
/// \return a MachineInstrBuilder for the newly created instruction.
MachineInstrBuilder buildUnmerge(ArrayRef<unsigned> Res, unsigned Op);
void addUsesWithIndices(MachineInstrBuilder MIB) {}
template <typename... ArgTys>
@ -411,14 +511,8 @@ class MachineIRBuilder {
return MIB;
}
template <typename... ArgTys>
MachineInstrBuilder buildInsert(unsigned Res, unsigned Src,
unsigned Op, unsigned Index, ArgTys... Args) {
MachineInstrBuilder MIB =
buildInstr(TargetOpcode::G_INSERT).addDef(Res).addUse(Src);
addUsesWithIndices(MIB, Op, Index, Args...);
return MIB;
}
unsigned Op, unsigned Index);
/// Build and insert either a G_INTRINSIC (if \p HasSideEffects is false) or
/// G_INTRINSIC_W_SIDE_EFFECTS instruction. Its first operand will be the
@ -500,6 +594,30 @@ class MachineIRBuilder {
/// \return a MachineInstrBuilder for the newly created instruction.
MachineInstrBuilder buildSelect(unsigned Res, unsigned Tst,
unsigned Op0, unsigned Op1);
/// Build and insert \p Res<def> = G_INSERT_VECTOR_ELT \p Val,
/// \p Elt, \p Idx
///
/// \pre setBasicBlock or setMI must have been called.
/// \pre \p Res and \p Val must be a generic virtual register
// with the same vector type.
/// \pre \p Elt and \p Idx must be a generic virtual register
/// with scalar type.
///
/// \return The newly created instruction.
MachineInstrBuilder buildInsertVectorElement(unsigned Res, unsigned Val,
unsigned Elt, unsigned Idx);
/// Build and insert \p Res<def> = G_EXTRACT_VECTOR_ELT \p Val, \p Idx
///
/// \pre setBasicBlock or setMI must have been called.
/// \pre \p Res must be a generic virtual register with scalar type.
/// \pre \p Val must be a generic virtual register with vector type.
/// \pre \p Idx must be a generic virtual register with scalar type.
///
/// \return The newly created instruction.
MachineInstrBuilder buildExtractVectorElement(unsigned Res, unsigned Val,
unsigned Idx);
};
} // End namespace llvm.

View File

@ -67,6 +67,7 @@
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
namespace llvm {
// Forward declarations.
@ -484,6 +485,9 @@ class RegBankSelect : public MachineFunctionPass {
/// This is required for non-fast mode.
MachineBranchProbabilityInfo *MBPI;
/// Current optimization remark emitter. Used to report failures.
std::unique_ptr<MachineOptimizationRemarkEmitter> MORE;
/// Helper class used for every code morphing.
MachineIRBuilder MIRBuilder;

View File

@ -42,7 +42,7 @@ class RegisterBank {
public:
RegisterBank(unsigned ID, const char *Name, unsigned Size,
const uint32_t *ContainedRegClasses);
const uint32_t *ContainedRegClasses, unsigned NumRegClasses);
/// Get the identifier of this register bank.
unsigned getID() const { return ID; }

View File

@ -317,12 +317,18 @@ class RegisterBankInfo {
/// The final mapping of the instruction.
const InstructionMapping &getInstrMapping() const { return InstrMapping; }
/// The MachineRegisterInfo we used to realize the mapping.
MachineRegisterInfo &getMRI() const { return MRI; }
/// @}
/// Create as many new virtual registers as needed for the mapping of the \p
/// OpIdx-th operand.
/// The number of registers is determined by the number of breakdown for the
/// related operand in the instruction mapping.
/// The type of the new registers is a plain scalar of the right size.
/// The proper type is expected to be set when the mapping is applied to
/// the instruction(s) that realizes the mapping.
///
/// \pre getMI().getOperand(OpIdx).isReg()
///
@ -372,15 +378,15 @@ class RegisterBankInfo {
/// Keep dynamically allocated PartialMapping in a separate map.
/// This shouldn't be needed when everything gets TableGen'ed.
mutable DenseMap<unsigned, const PartialMapping *> MapOfPartialMappings;
mutable DenseMap<unsigned, std::unique_ptr<const PartialMapping>> MapOfPartialMappings;
/// Keep dynamically allocated ValueMapping in a separate map.
/// This shouldn't be needed when everything gets TableGen'ed.
mutable DenseMap<unsigned, const ValueMapping *> MapOfValueMappings;
mutable DenseMap<unsigned, std::unique_ptr<const ValueMapping> > MapOfValueMappings;
/// Keep dynamically allocated array of ValueMapping in a separate map.
/// This shouldn't be needed when everything gets TableGen'ed.
mutable DenseMap<unsigned, ValueMapping *> MapOfOperandsMappings;
mutable DenseMap<unsigned, std::unique_ptr<ValueMapping[]>> MapOfOperandsMappings;
/// Create a RegisterBankInfo that can accomodate up to \p NumRegBanks
/// RegisterBank instances.
@ -487,6 +493,12 @@ class RegisterBankInfo {
/// Basically, that means that \p OpdMapper.getMI() is left untouched
/// aside from the reassignment of the register operand that have been
/// remapped.
///
/// The type of all the new registers that have been created by the
/// mapper are properly remapped to the type of the original registers
/// they replace. In other words, the semantic of the instruction does
/// not change, only the register banks.
///
/// If the mapping of one of the operand spans several registers, this
/// method will abort as this is not like a default mapping anymore.
///
@ -500,7 +512,7 @@ class RegisterBankInfo {
}
public:
virtual ~RegisterBankInfo();
virtual ~RegisterBankInfo() = default;
/// Get the register bank identified by \p ID.
const RegisterBank &getRegBank(unsigned ID) const {

View File

@ -15,15 +15,21 @@
#ifndef LLVM_CODEGEN_GLOBALISEL_UTILS_H
#define LLVM_CODEGEN_GLOBALISEL_UTILS_H
#include "llvm/ADT/StringRef.h"
namespace llvm {
class MachineFunction;
class MachineInstr;
class MachineOptimizationRemarkEmitter;
class MachineOptimizationRemarkMissed;
class MachineRegisterInfo;
class MCInstrDesc;
class RegisterBankInfo;
class TargetInstrInfo;
class TargetPassConfig;
class TargetRegisterInfo;
class Twine;
/// Try to constrain Reg so that it is usable by argument OpIdx of the
/// provided MCInstrDesc \p II. If this fails, create a new virtual
@ -39,5 +45,20 @@ unsigned constrainOperandRegClass(const MachineFunction &MF,
MachineInstr &InsertPt, const MCInstrDesc &II,
unsigned Reg, unsigned OpIdx);
/// Check whether an instruction \p MI is dead: it only defines dead virtual
/// registers, and doesn't have other side effects.
bool isTriviallyDead(const MachineInstr &MI, const MachineRegisterInfo &MRI);
/// Report an ISel error as a missed optimization remark to the LLVMContext's
/// diagnostic stream. Set the FailedISel MachineFunction property.
void reportGISelFailure(MachineFunction &MF, const TargetPassConfig &TPC,
MachineOptimizationRemarkEmitter &MORE,
MachineOptimizationRemarkMissed &R);
void reportGISelFailure(MachineFunction &MF, const TargetPassConfig &TPC,
MachineOptimizationRemarkEmitter &MORE,
const char *PassName, StringRef Msg,
const MachineInstr &MI);
} // End namespace llvm.
#endif

View File

@ -245,6 +245,12 @@ namespace ISD {
/// Simple binary floating point operators.
FADD, FSUB, FMUL, FDIV, FREM,
/// Constrained versions of the binary floating point operators.
/// These will be lowered to the simple operators before final selection.
/// They are used to limit optimizations while the DAG is being
/// optimized.
STRICT_FADD, STRICT_FSUB, STRICT_FMUL, STRICT_FDIV, STRICT_FREM,
/// FMA - Perform a * b + c with no intermediate rounding step.
FMA,
@ -281,7 +287,8 @@ namespace ISD {
/// EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR
/// identified by the (potentially variable) element number IDX. If the
/// return type is an integer type larger than the element type of the
/// vector, the result is extended to the width of the return type.
/// vector, the result is extended to the width of the return type. In
/// that case, the high bits are undefined.
EXTRACT_VECTOR_ELT,
/// CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of
@ -332,6 +339,12 @@ namespace ISD {
/// Bitwise operators - logical and, logical or, logical xor.
AND, OR, XOR,
/// ABS - Determine the unsigned absolute value of a signed integer value of
/// the same bitwidth.
/// Note: A value of INT_MIN will return INT_MIN, no saturation or overflow
/// is performed.
ABS,
/// Shift and rotation operations. After legalization, the type of the
/// shift amount is known to be TLI.getShiftAmountTy(). Before legalization
/// the shift amount can be any type, but care must be taken to ensure it is
@ -801,10 +814,11 @@ namespace ISD {
PRE_INC,
PRE_DEC,
POST_INC,
POST_DEC,
LAST_INDEXED_MODE
POST_DEC
};
static const int LAST_INDEXED_MODE = POST_DEC + 1;
//===--------------------------------------------------------------------===//
/// LoadExtType enum - This enum defines the three variants of LOADEXT
/// (load with extension).
@ -819,10 +833,11 @@ namespace ISD {
NON_EXTLOAD = 0,
EXTLOAD,
SEXTLOAD,
ZEXTLOAD,
LAST_LOADEXT_TYPE
ZEXTLOAD
};
static const int LAST_LOADEXT_TYPE = ZEXTLOAD + 1;
NodeType getExtForLoadExtType(bool IsFP, LoadExtType);
//===--------------------------------------------------------------------===//

View File

@ -0,0 +1,76 @@
///===- LazyMachineBlockFrequencyInfo.h - Lazy Block Frequency -*- C++ -*--===//
///
/// The LLVM Compiler Infrastructure
///
/// This file is distributed under the University of Illinois Open Source
/// License. See LICENSE.TXT for details.
///
///===---------------------------------------------------------------------===//
/// \file
/// This is an alternative analysis pass to MachineBlockFrequencyInfo. The
/// difference is that with this pass the block frequencies are not computed
/// when the analysis pass is executed but rather when the BFI result is
/// explicitly requested by the analysis client.
///
///===---------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_LAZYMACHINEBLOCKFREQUENCYINFO_H
#define LLVM_ANALYSIS_LAZYMACHINEBLOCKFREQUENCYINFO_H
#include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
namespace llvm {
/// \brief This is an alternative analysis pass to MachineBlockFrequencyInfo.
/// The difference is that with this pass, the block frequencies are not
/// computed when the analysis pass is executed but rather when the BFI result
/// is explicitly requested by the analysis client.
///
/// This works by checking querying if MBFI is available and otherwise
/// generating MBFI on the fly. In this case the passes required for (LI, DT)
/// are also queried before being computed on the fly.
///
/// Note that it is expected that we wouldn't need this functionality for the
/// new PM since with the new PM, analyses are executed on demand.
class LazyMachineBlockFrequencyInfoPass : public MachineFunctionPass {
private:
/// If generated on the fly this own the instance.
mutable std::unique_ptr<MachineBlockFrequencyInfo> OwnedMBFI;
/// If generated on the fly this own the instance.
mutable std::unique_ptr<MachineLoopInfo> OwnedMLI;
/// If generated on the fly this own the instance.
mutable std::unique_ptr<MachineDominatorTree> OwnedMDT;
/// The function.
MachineFunction *MF = nullptr;
/// \brief Calculate MBFI and all other analyses that's not available and
/// required by BFI.
MachineBlockFrequencyInfo &calculateIfNotAvailable() const;
public:
static char ID;
LazyMachineBlockFrequencyInfoPass();
/// \brief Compute and return the block frequencies.
MachineBlockFrequencyInfo &getBFI() { return calculateIfNotAvailable(); }
/// \brief Compute and return the block frequencies.
const MachineBlockFrequencyInfo &getBFI() const {
return calculateIfNotAvailable();
}
void getAnalysisUsage(AnalysisUsage &AU) const override;
bool runOnMachineFunction(MachineFunction &F) override;
void releaseMemory() override;
void print(raw_ostream &OS, const Module *M) const override;
};
}
#endif

View File

@ -1,4 +1,4 @@
//===- LexicalScopes.cpp - Collecting lexical scope info -*- C++ -*--------===//
//===- LexicalScopes.cpp - Collecting lexical scope info --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -19,19 +19,18 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/ValueHandle.h"
#include <cassert>
#include <unordered_map>
#include <utility>
namespace llvm {
class MachineInstr;
class MachineBasicBlock;
class MachineFunction;
class MachineInstr;
//===----------------------------------------------------------------------===//
/// InsnRange - This is used to track range of instructions with identical
@ -43,13 +42,15 @@ typedef std::pair<const MachineInstr *, const MachineInstr *> InsnRange;
/// LexicalScope - This class is used to track scope information.
///
class LexicalScope {
public:
LexicalScope(LexicalScope *P, const DILocalScope *D, const DILocation *I,
bool A)
: Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(A),
LastInsn(nullptr), FirstInsn(nullptr), DFSIn(0), DFSOut(0) {
assert((!D || D->isResolved()) && "Expected resolved node");
: Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(A) {
assert(D);
assert(D->getSubprogram()->getUnit()->getEmissionKind() !=
DICompileUnit::NoDebug &&
"Don't build lexical scopes for non-debug locations");
assert(D->isResolved() && "Expected resolved node");
assert((!I || I->isResolved()) && "Expected resolved node");
if (Parent)
Parent->addChild(this);
@ -127,10 +128,10 @@ class LexicalScope {
// Contents not owned.
SmallVector<InsnRange, 4> Ranges;
const MachineInstr *LastInsn; // Last instruction of this scope.
const MachineInstr *FirstInsn; // First instruction of this scope.
unsigned DFSIn, DFSOut; // In & Out Depth use to determine
// scope nesting.
const MachineInstr *LastInsn = nullptr; // Last instruction of this scope.
const MachineInstr *FirstInsn = nullptr; // First instruction of this scope.
unsigned DFSIn = 0; // In & Out Depth use to determine scope nesting.
unsigned DFSOut = 0;
};
//===----------------------------------------------------------------------===//
@ -139,7 +140,7 @@ class LexicalScope {
///
class LexicalScopes {
public:
LexicalScopes() : MF(nullptr), CurrentFnLexicalScope(nullptr) {}
LexicalScopes() = default;
/// initialize - Scan machine function and constuct lexical scope nest, resets
/// the instance if necessary.
@ -225,8 +226,7 @@ class LexicalScopes {
assignInstructionRanges(SmallVectorImpl<InsnRange> &MIRanges,
DenseMap<const MachineInstr *, LexicalScope *> &M);
private:
const MachineFunction *MF;
const MachineFunction *MF = nullptr;
/// LexicalScopeMap - Tracks the scopes in the current function.
// Use an unordered_map to ensure value pointer validity over insertion.
@ -249,9 +249,9 @@ class LexicalScopes {
/// CurrentFnLexicalScope - Top level scope for the current function.
///
LexicalScope *CurrentFnLexicalScope;
LexicalScope *CurrentFnLexicalScope = nullptr;
};
} // end llvm namespace
} // end namespace llvm
#endif
#endif // LLVM_CODEGEN_LEXICALSCOPES_H

View File

@ -227,15 +227,22 @@ namespace llvm {
LiveRange(const LiveRange &Other, BumpPtrAllocator &Allocator) {
assert(Other.segmentSet == nullptr &&
"Copying of LiveRanges with active SegmentSets is not supported");
assign(Other, Allocator);
}
/// Copies values numbers and live segments from \p Other into this range.
void assign(const LiveRange &Other, BumpPtrAllocator &Allocator) {
if (this == &Other)
return;
assert(Other.segmentSet == nullptr &&
"Copying of LiveRanges with active SegmentSets is not supported");
// Duplicate valnos.
for (const VNInfo *VNI : Other.valnos) {
for (const VNInfo *VNI : Other.valnos)
createValueCopy(VNI, Allocator);
}
// Now we can copy segments and remap their valnos.
for (const Segment &S : Other.segments) {
for (const Segment &S : Other.segments)
segments.push_back(Segment(S.start, S.end, valnos[S.valno->id]));
}
}
/// advanceTo - Advance the specified iterator to point to the Segment
@ -767,6 +774,19 @@ namespace llvm {
const MachineRegisterInfo &MRI,
const SlotIndexes &Indexes) const;
/// Refines the subranges to support \p LaneMask. This may only be called
/// for LI.hasSubrange()==true. Subregister ranges are split or created
/// until \p LaneMask can be matched exactly. \p Mod is executed on the
/// matching subranges.
///
/// Example:
/// Given an interval with subranges with lanemasks L0F00, L00F0 and
/// L000F, refining for mask L0018. Will split the L00F0 lane into
/// L00E0 and L0010 and the L000F lane into L0007 and L0008. The Mod
/// function will be applied to the L0010 and L0008 subranges.
void refineSubRanges(BumpPtrAllocator &Allocator, LaneBitmask LaneMask,
std::function<void(LiveInterval::SubRange&)> Mod);
bool operator<(const LiveInterval& other) const {
const SlotIndex &thisIndex = beginIndex();
const SlotIndex &otherIndex = other.beginIndex();

View File

@ -7,13 +7,13 @@
//
//===----------------------------------------------------------------------===//
//
// This file implements the LiveInterval analysis pass. Given some numbering of
// each the machine instructions (in this implemention depth-first order) an
// interval [i, j) is said to be a live interval for register v if there is no
// instruction with number j' > j such that v is live at j' and there is no
// instruction with number i' < i such that v is live at i'. In this
// implementation intervals can have holes, i.e. an interval might look like
// [1,20), [50,65), [1000,1001).
/// \file This file implements the LiveInterval analysis pass. Given some
/// numbering of each the machine instructions (in this implemention depth-first
/// order) an interval [i, j) is said to be a live interval for register v if
/// there is no instruction with number j' > j such that v is live at j' and
/// there is no instruction with number i' < i such that v is live at i'. In
/// this implementation intervals can have holes, i.e. an interval might look
/// like [1,20), [50,65), [1000,1001).
//
//===----------------------------------------------------------------------===//
@ -60,20 +60,17 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
LiveRangeCalc *LRCalc;
/// Special pool allocator for VNInfo's (LiveInterval val#).
///
VNInfo::Allocator VNInfoAllocator;
/// Live interval pointers for all the virtual registers.
IndexedMap<LiveInterval*, VirtReg2IndexFunctor> VirtRegIntervals;
/// RegMaskSlots - Sorted list of instructions with register mask operands.
/// Always use the 'r' slot, RegMasks are normal clobbers, not early
/// clobbers.
/// Sorted list of instructions with register mask operands. Always use the
/// 'r' slot, RegMasks are normal clobbers, not early clobbers.
SmallVector<SlotIndex, 8> RegMaskSlots;
/// RegMaskBits - This vector is parallel to RegMaskSlots, it holds a
/// pointer to the corresponding register mask. This pointer can be
/// recomputed as:
/// This vector is parallel to RegMaskSlots, it holds a pointer to the
/// corresponding register mask. This pointer can be recomputed as:
///
/// MI = Indexes->getInstructionFromIndex(RegMaskSlot[N]);
/// unsigned OpNum = findRegMaskOperand(MI);
@ -97,11 +94,11 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
SmallVector<LiveRange*, 0> RegUnitRanges;
public:
static char ID; // Pass identification, replacement for typeid
static char ID;
LiveIntervals();
~LiveIntervals() override;
// Calculate the spill weight to assign to a single instruction.
/// Calculate the spill weight to assign to a single instruction.
static float getSpillWeight(bool isDef, bool isUse,
const MachineBlockFrequencyInfo *MBFI,
const MachineInstr &Instr);
@ -121,7 +118,7 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
return VirtRegIntervals.inBounds(Reg) && VirtRegIntervals[Reg];
}
// Interval creation.
/// Interval creation.
LiveInterval &createEmptyInterval(unsigned Reg) {
assert(!hasInterval(Reg) && "Interval already exists!");
VirtRegIntervals.grow(Reg);
@ -135,7 +132,7 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
return LI;
}
// Interval removal.
/// Interval removal.
void removeInterval(unsigned Reg) {
delete VirtRegIntervals[Reg];
VirtRegIntervals[Reg] = nullptr;
@ -163,16 +160,16 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
/// LiveInterval::removeEmptySubranges() afterwards.
void shrinkToUses(LiveInterval::SubRange &SR, unsigned Reg);
/// Extend the live range @p LR to reach all points in @p Indices. The
/// points in the @p Indices array must be jointly dominated by the union
/// of the existing defs in @p LR and points in @p Undefs.
/// Extend the live range \p LR to reach all points in \p Indices. The
/// points in the \p Indices array must be jointly dominated by the union
/// of the existing defs in \p LR and points in \p Undefs.
///
/// PHI-defs are added as needed to maintain SSA form.
///
/// If a SlotIndex in @p Indices is the end index of a basic block, @p LR
/// If a SlotIndex in \p Indices is the end index of a basic block, \p LR
/// will be extended to be live out of the basic block.
/// If a SlotIndex in @p Indices is jointy dominated only by points in
/// @p Undefs, the live range will not be extended to that point.
/// If a SlotIndex in \p Indices is jointy dominated only by points in
/// \p Undefs, the live range will not be extended to that point.
///
/// See also LiveRangeCalc::extend().
void extendToIndices(LiveRange &LR, ArrayRef<SlotIndex> Indices,
@ -182,7 +179,7 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
extendToIndices(LR, Indices, /*Undefs=*/{});
}
/// If @p LR has a live value at @p Kill, prune its live range by removing
/// If \p LR has a live value at \p Kill, prune its live range by removing
/// any liveness reachable from Kill. Add live range end points to
/// EndPoints such that extendToIndices(LI, EndPoints) will reconstruct the
/// value's live range.
@ -192,6 +189,16 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
void pruneValue(LiveRange &LR, SlotIndex Kill,
SmallVectorImpl<SlotIndex> *EndPoints);
/// This function should be used. Its intend is to tell you that
/// you are doing something wrong if you call pruveValue directly on a
/// LiveInterval. Indeed, you are supposed to call pruneValue on the main
/// LiveRange and all the LiveRange of the subranges if any.
LLVM_ATTRIBUTE_UNUSED void pruneValue(LiveInterval &, SlotIndex,
SmallVectorImpl<SlotIndex> *) {
llvm_unreachable(
"Use pruneValue on the main LiveRange and on each subrange");
}
SlotIndexes *getSlotIndexes() const {
return Indexes;
}
@ -200,8 +207,8 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
return AA;
}
/// isNotInMIMap - returns true if the specified machine instr has been
/// removed or was never entered in the map.
/// Returns true if the specified machine instr has been removed or was
/// never entered in the map.
bool isNotInMIMap(const MachineInstr &Instr) const {
return !Indexes->hasIndex(Instr);
}
@ -270,35 +277,32 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
void getAnalysisUsage(AnalysisUsage &AU) const override;
void releaseMemory() override;
/// runOnMachineFunction - pass entry point
/// Pass entry point; Calculates LiveIntervals.
bool runOnMachineFunction(MachineFunction&) override;
/// print - Implement the dump method.
/// Implement the dump method.
void print(raw_ostream &O, const Module* = nullptr) const override;
/// intervalIsInOneMBB - If LI is confined to a single basic block, return
/// a pointer to that block. If LI is live in to or out of any block,
/// return NULL.
/// If LI is confined to a single basic block, return a pointer to that
/// block. If LI is live in to or out of any block, return NULL.
MachineBasicBlock *intervalIsInOneMBB(const LiveInterval &LI) const;
/// Returns true if VNI is killed by any PHI-def values in LI.
/// This may conservatively return true to avoid expensive computations.
bool hasPHIKill(const LiveInterval &LI, const VNInfo *VNI) const;
/// addKillFlags - Add kill flags to any instruction that kills a virtual
/// register.
/// Add kill flags to any instruction that kills a virtual register.
void addKillFlags(const VirtRegMap*);
/// handleMove - call this method to notify LiveIntervals that
/// instruction 'mi' has been moved within a basic block. This will update
/// the live intervals for all operands of mi. Moves between basic blocks
/// are not supported.
/// Call this method to notify LiveIntervals that instruction \p MI has been
/// moved within a basic block. This will update the live intervals for all
/// operands of \p MI. Moves between basic blocks are not supported.
///
/// \param UpdateFlags Update live intervals for nonallocatable physregs.
void handleMove(MachineInstr &MI, bool UpdateFlags = false);
/// moveIntoBundle - Update intervals for operands of MI so that they
/// begin/end on the SlotIndex for BundleStart.
/// Update intervals for operands of \p MI so that they begin/end on the
/// SlotIndex for \p BundleStart.
///
/// \param UpdateFlags Update live intervals for nonallocatable physregs.
///
@ -308,10 +312,9 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
void handleMoveIntoBundle(MachineInstr &MI, MachineInstr &BundleStart,
bool UpdateFlags = false);
/// repairIntervalsInRange - Update live intervals for instructions in a
/// range of iterators. It is intended for use after target hooks that may
/// insert or remove instructions, and is only efficient for a small number
/// of instructions.
/// Update live intervals for instructions in a range of iterators. It is
/// intended for use after target hooks that may insert or remove
/// instructions, and is only efficient for a small number of instructions.
///
/// OrigRegs is a vector of registers that were originally used by the
/// instructions in the range between the two iterators.
@ -334,34 +337,33 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
// LiveIntervalAnalysis maintains a sorted list of instructions with
// register mask operands.
/// getRegMaskSlots - Returns a sorted array of slot indices of all
/// instructions with register mask operands.
/// Returns a sorted array of slot indices of all instructions with
/// register mask operands.
ArrayRef<SlotIndex> getRegMaskSlots() const { return RegMaskSlots; }
/// getRegMaskSlotsInBlock - Returns a sorted array of slot indices of all
/// instructions with register mask operands in the basic block numbered
/// MBBNum.
/// Returns a sorted array of slot indices of all instructions with register
/// mask operands in the basic block numbered \p MBBNum.
ArrayRef<SlotIndex> getRegMaskSlotsInBlock(unsigned MBBNum) const {
std::pair<unsigned, unsigned> P = RegMaskBlocks[MBBNum];
return getRegMaskSlots().slice(P.first, P.second);
}
/// getRegMaskBits() - Returns an array of register mask pointers
/// corresponding to getRegMaskSlots().
/// Returns an array of register mask pointers corresponding to
/// getRegMaskSlots().
ArrayRef<const uint32_t*> getRegMaskBits() const { return RegMaskBits; }
/// getRegMaskBitsInBlock - Returns an array of mask pointers corresponding
/// to getRegMaskSlotsInBlock(MBBNum).
/// Returns an array of mask pointers corresponding to
/// getRegMaskSlotsInBlock(MBBNum).
ArrayRef<const uint32_t*> getRegMaskBitsInBlock(unsigned MBBNum) const {
std::pair<unsigned, unsigned> P = RegMaskBlocks[MBBNum];
return getRegMaskBits().slice(P.first, P.second);
}
/// checkRegMaskInterference - Test if LI is live across any register mask
/// instructions, and compute a bit mask of physical registers that are not
/// clobbered by any of them.
/// Test if \p LI is live across any register mask instructions, and
/// compute a bit mask of physical registers that are not clobbered by any
/// of them.
///
/// Returns false if LI doesn't cross any register mask instructions. In
/// Returns false if \p LI doesn't cross any register mask instructions. In
/// that case, the bit vector is not filled in.
bool checkRegMaskInterference(LiveInterval &LI,
BitVector &UsableRegs);
@ -377,8 +379,8 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
// track liveness per register unit to handle aliasing registers more
// efficiently.
/// getRegUnit - Return the live range for Unit.
/// It will be computed if it doesn't exist.
/// Return the live range for register unit \p Unit. It will be computed if
/// it doesn't exist.
LiveRange &getRegUnit(unsigned Unit) {
LiveRange *LR = RegUnitRanges[Unit];
if (!LR) {
@ -390,8 +392,8 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
return *LR;
}
/// getCachedRegUnit - Return the live range for Unit if it has already
/// been computed, or NULL if it hasn't been computed yet.
/// Return the live range for register unit \p Unit if it has already been
/// computed, or nullptr if it hasn't been computed yet.
LiveRange *getCachedRegUnit(unsigned Unit) {
return RegUnitRanges[Unit];
}
@ -400,7 +402,7 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
return RegUnitRanges[Unit];
}
/// removeRegUnit - Remove computed live range for Unit. Subsequent uses
/// Remove computed live range for register unit \p Unit. Subsequent uses
/// should rely on on-demand recomputation.
void removeRegUnit(unsigned Unit) {
delete RegUnitRanges[Unit];
@ -408,12 +410,12 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
}
/// Remove value numbers and related live segments starting at position
/// @p Pos that are part of any liverange of physical register @p Reg or one
/// \p Pos that are part of any liverange of physical register \p Reg or one
/// of its subregisters.
void removePhysRegDefAt(unsigned Reg, SlotIndex Pos);
/// Remove value number and related live segments of @p LI and its subranges
/// that start at position @p Pos.
/// Remove value number and related live segments of \p LI and its subranges
/// that start at position \p Pos.
void removeVRegDefAt(LiveInterval &LI, SlotIndex Pos);
/// Split separate components in LiveInterval \p LI into separate intervals.
@ -432,10 +434,10 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
/// Compute RegMaskSlots and RegMaskBits.
void computeRegMasks();
/// Walk the values in @p LI and check for dead values:
/// Walk the values in \p LI and check for dead values:
/// - Dead PHIDef values are marked as unused.
/// - Dead operands are marked as such.
/// - Completely dead machine instructions are added to the @p dead vector
/// - Completely dead machine instructions are added to the \p dead vector
/// if it is not nullptr.
/// Returns true if any PHI value numbers have been removed which may
/// have separated the interval into multiple connected components.
@ -453,8 +455,8 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
/// Helper function for repairIntervalsInRange(), walks backwards and
/// creates/modifies live segments in @p LR to match the operands found.
/// Only full operands or operands with subregisters matching @p LaneMask
/// creates/modifies live segments in \p LR to match the operands found.
/// Only full operands or operands with subregisters matching \p LaneMask
/// are considered.
void repairOldRegInRange(MachineBasicBlock::iterator Begin,
MachineBasicBlock::iterator End,

View File

@ -1,4 +1,4 @@
//===-- LiveIntervalUnion.h - Live interval union data struct --*- C++ -*--===//
//===- LiveIntervalUnion.h - Live interval union data struct ---*- C++ -*--===//
//
// The LLVM Compiler Infrastructure
//
@ -18,7 +18,11 @@
#define LLVM_CODEGEN_LIVEINTERVALUNION_H
#include "llvm/ADT/IntervalMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/LiveInterval.h"
#include "llvm/CodeGen/SlotIndexes.h"
#include <cassert>
#include <limits>
namespace llvm {
@ -30,13 +34,6 @@ template <unsigned Element> class SparseBitVector;
typedef SparseBitVector<128> LiveVirtRegBitSet;
#endif
/// Compare a live virtual register segment to a LiveIntervalUnion segment.
inline bool
overlap(const LiveInterval::Segment &VRSeg,
const IntervalMap<SlotIndex, LiveInterval*>::const_iterator &LUSeg) {
return VRSeg.start < LUSeg.stop() && LUSeg.start() < VRSeg.end;
}
/// Union of live intervals that are strong candidates for coalescing into a
/// single register (either physical or virtual depending on the context). We
/// expect the constituent live intervals to be disjoint, although we may
@ -53,29 +50,34 @@ class LiveIntervalUnion {
// to reach the current segment's containing virtual register.
typedef LiveSegments::iterator SegmentIter;
/// Const version of SegmentIter.
typedef LiveSegments::const_iterator ConstSegmentIter;
// LiveIntervalUnions share an external allocator.
typedef LiveSegments::Allocator Allocator;
class Query;
private:
unsigned Tag; // unique tag for current contents.
unsigned Tag = 0; // unique tag for current contents.
LiveSegments Segments; // union of virtual reg segments
public:
explicit LiveIntervalUnion(Allocator &a) : Tag(0), Segments(a) {}
explicit LiveIntervalUnion(Allocator &a) : Segments(a) {}
// Iterate over all segments in the union of live virtual registers ordered
// by their starting position.
SegmentIter begin() { return Segments.begin(); }
SegmentIter end() { return Segments.end(); }
SegmentIter find(SlotIndex x) { return Segments.find(x); }
ConstSegmentIter begin() const { return Segments.begin(); }
ConstSegmentIter end() const { return Segments.end(); }
ConstSegmentIter find(SlotIndex x) const { return Segments.find(x); }
bool empty() const { return Segments.empty(); }
SlotIndex startIndex() const { return Segments.start(); }
// Provide public access to the underlying map to allow overlap iteration.
typedef LiveSegments Map;
const Map &getMap() { return Segments; }
const Map &getMap() const { return Segments; }
/// getTag - Return an opaque tag representing the current state of the union.
unsigned getTag() const { return Tag; }
@ -85,15 +87,9 @@ class LiveIntervalUnion {
// Add a live virtual register to this union and merge its segments.
void unify(LiveInterval &VirtReg, const LiveRange &Range);
void unify(LiveInterval &VirtReg) {
unify(VirtReg, VirtReg);
}
// Remove a live virtual register's segments from this union.
void extract(LiveInterval &VirtReg, const LiveRange &Range);
void extract(LiveInterval &VirtReg) {
extract(VirtReg, VirtReg);
}
// Remove all inserted virtual registers.
void clear() { Segments.clear(); ++Tag; }
@ -109,52 +105,42 @@ class LiveIntervalUnion {
/// Query interferences between a single live virtual register and a live
/// interval union.
class Query {
LiveIntervalUnion *LiveUnion;
LiveInterval *VirtReg;
LiveInterval::iterator VirtRegI; // current position in VirtReg
SegmentIter LiveUnionI; // current position in LiveUnion
const LiveIntervalUnion *LiveUnion = nullptr;
const LiveRange *LR = nullptr;
LiveRange::const_iterator LRI; ///< current position in LR
ConstSegmentIter LiveUnionI; ///< current position in LiveUnion
SmallVector<LiveInterval*,4> InterferingVRegs;
bool CheckedFirstInterference;
bool SeenAllInterferences;
bool SeenUnspillableVReg;
unsigned Tag, UserTag;
bool CheckedFirstInterference = false;
bool SeenAllInterferences = false;
unsigned Tag = 0;
unsigned UserTag = 0;
public:
Query(): LiveUnion(), VirtReg(), Tag(0), UserTag(0) {}
Query(LiveInterval *VReg, LiveIntervalUnion *LIU):
LiveUnion(LIU), VirtReg(VReg), CheckedFirstInterference(false),
SeenAllInterferences(false), SeenUnspillableVReg(false)
{}
void clear() {
LiveUnion = nullptr;
VirtReg = nullptr;
void reset(unsigned NewUserTag, const LiveRange &NewLR,
const LiveIntervalUnion &NewLiveUnion) {
LiveUnion = &NewLiveUnion;
LR = &NewLR;
InterferingVRegs.clear();
CheckedFirstInterference = false;
SeenAllInterferences = false;
SeenUnspillableVReg = false;
Tag = 0;
UserTag = 0;
Tag = NewLiveUnion.getTag();
UserTag = NewUserTag;
}
void init(unsigned UTag, LiveInterval *VReg, LiveIntervalUnion *LIU) {
assert(VReg && LIU && "Invalid arguments");
if (UserTag == UTag && VirtReg == VReg &&
LiveUnion == LIU && !LIU->changedSince(Tag)) {
public:
Query() = default;
Query(const LiveRange &LR, const LiveIntervalUnion &LIU):
LiveUnion(&LIU), LR(&LR) {}
Query(const Query &) = delete;
Query &operator=(const Query &) = delete;
void init(unsigned NewUserTag, const LiveRange &NewLR,
const LiveIntervalUnion &NewLiveUnion) {
if (UserTag == NewUserTag && LR == &NewLR && LiveUnion == &NewLiveUnion &&
!NewLiveUnion.changedSince(Tag)) {
// Retain cached results, e.g. firstInterference.
return;
}
clear();
LiveUnion = LIU;
VirtReg = VReg;
Tag = LIU->getTag();
UserTag = UTag;
}
LiveInterval &virtReg() const {
assert(VirtReg && "uninitialized");
return *VirtReg;
reset(NewUserTag, NewLR, NewLiveUnion);
}
// Does this live virtual register interfere with the union?
@ -162,7 +148,8 @@ class LiveIntervalUnion {
// Count the virtual registers in this union that interfere with this
// query's live virtual register, up to maxInterferingRegs.
unsigned collectInterferingVRegs(unsigned MaxInterferingRegs = UINT_MAX);
unsigned collectInterferingVRegs(
unsigned MaxInterferingRegs = std::numeric_limits<unsigned>::max());
// Was this virtual register visited during collectInterferingVRegs?
bool isSeenInterference(LiveInterval *VReg) const;
@ -170,25 +157,19 @@ class LiveIntervalUnion {
// Did collectInterferingVRegs collect all interferences?
bool seenAllInterferences() const { return SeenAllInterferences; }
// Did collectInterferingVRegs encounter an unspillable vreg?
bool seenUnspillableVReg() const { return SeenUnspillableVReg; }
// Vector generated by collectInterferingVRegs.
const SmallVectorImpl<LiveInterval*> &interferingVRegs() const {
return InterferingVRegs;
}
private:
Query(const Query&) = delete;
void operator=(const Query&) = delete;
};
// Array of LiveIntervalUnions.
class Array {
unsigned Size;
LiveIntervalUnion *LIUs;
unsigned Size = 0;
LiveIntervalUnion *LIUs = nullptr;
public:
Array() : Size(0), LIUs(nullptr) {}
Array() = default;
~Array() { clear(); }
// Initialize the array to have Size entries.
@ -213,4 +194,4 @@ class LiveIntervalUnion {
} // end namespace llvm
#endif // !defined(LLVM_CODEGEN_LIVEINTERVALUNION_H)
#endif // LLVM_CODEGEN_LIVEINTERVALUNION_H

View File

@ -1,4 +1,4 @@
//===-- LiveRegMatrix.h - Track register interference ---------*- C++ -*---===//
//===- LiveRegMatrix.h - Track register interference ----------*- C++ -*---===//
//
// The LLVM Compiler Infrastructure
//
@ -27,11 +27,14 @@
#include "llvm/ADT/BitVector.h"
#include "llvm/CodeGen/LiveIntervalUnion.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include <memory>
namespace llvm {
class AnalysisUsage;
class LiveInterval;
class LiveIntervalAnalysis;
class LiveIntervals;
class MachineFunction;
class TargetRegisterInfo;
class VirtRegMap;
@ -41,7 +44,7 @@ class LiveRegMatrix : public MachineFunctionPass {
VirtRegMap *VRM;
// UserTag changes whenever virtual registers have been modified.
unsigned UserTag;
unsigned UserTag = 0;
// The matrix is represented as a LiveIntervalUnion per register unit.
LiveIntervalUnion::Allocator LIUAlloc;
@ -51,16 +54,18 @@ class LiveRegMatrix : public MachineFunctionPass {
std::unique_ptr<LiveIntervalUnion::Query[]> Queries;
// Cached register mask interference info.
unsigned RegMaskTag;
unsigned RegMaskVirtReg;
unsigned RegMaskTag = 0;
unsigned RegMaskVirtReg = 0;
BitVector RegMaskUsable;
// MachineFunctionPass boilerplate.
void getAnalysisUsage(AnalysisUsage&) const override;
bool runOnMachineFunction(MachineFunction&) override;
void getAnalysisUsage(AnalysisUsage &) const override;
bool runOnMachineFunction(MachineFunction &) override;
void releaseMemory() override;
public:
static char ID;
LiveRegMatrix();
//===--------------------------------------------------------------------===//
@ -136,7 +141,7 @@ class LiveRegMatrix : public MachineFunctionPass {
/// Use MCRegUnitIterator to enumerate all regunits in the desired PhysReg.
/// This returns a reference to an internal Query data structure that is only
/// valid until the next query() call.
LiveIntervalUnion::Query &query(LiveInterval &VirtReg, unsigned RegUnit);
LiveIntervalUnion::Query &query(const LiveRange &LR, unsigned RegUnit);
/// Directly access the live interval unions per regunit.
/// This returns an array indexed by the regunit number.

View File

@ -0,0 +1,128 @@
//===- llvm/CodeGen/LiveRegUnits.h - Register Unit Set ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
/// \file
/// A set of register units. It is intended for register liveness tracking.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_LIVEREGUNITS_H
#define LLVM_CODEGEN_LIVEREGUNITS_H
#include "llvm/ADT/BitVector.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/MC/LaneBitmask.h"
#include "llvm/MC/MCRegisterInfo.h"
#include <cstdint>
namespace llvm {
class MachineInstr;
class MachineBasicBlock;
/// A set of register units used to track register liveness.
class LiveRegUnits {
const TargetRegisterInfo *TRI = nullptr;
BitVector Units;
public:
/// Constructs a new empty LiveRegUnits set.
LiveRegUnits() = default;
/// Constructs and initialize an empty LiveRegUnits set.
LiveRegUnits(const TargetRegisterInfo &TRI) {
init(TRI);
}
/// Initialize and clear the set.
void init(const TargetRegisterInfo &TRI) {
this->TRI = &TRI;
Units.reset();
Units.resize(TRI.getNumRegUnits());
}
/// Clears the set.
void clear() { Units.reset(); }
/// Returns true if the set is empty.
bool empty() const { return Units.empty(); }
/// Adds register units covered by physical register \p Reg.
void addReg(unsigned Reg) {
for (MCRegUnitIterator Unit(Reg, TRI); Unit.isValid(); ++Unit)
Units.set(*Unit);
}
/// \brief Adds register units covered by physical register \p Reg that are
/// part of the lanemask \p Mask.
void addRegMasked(unsigned Reg, LaneBitmask Mask) {
for (MCRegUnitMaskIterator Unit(Reg, TRI); Unit.isValid(); ++Unit) {
LaneBitmask UnitMask = (*Unit).second;
if (UnitMask.none() || (UnitMask & Mask).any())
Units.set((*Unit).first);
}
}
/// Removes all register units covered by physical register \p Reg.
void removeReg(unsigned Reg) {
for (MCRegUnitIterator Unit(Reg, TRI); Unit.isValid(); ++Unit)
Units.reset(*Unit);
}
/// Removes register units not preserved by the regmask \p RegMask.
/// The regmask has the same format as the one in the RegMask machine operand.
void removeRegsNotPreserved(const uint32_t *RegMask);
/// Adds register units not preserved by the regmask \p RegMask.
/// The regmask has the same format as the one in the RegMask machine operand.
void addRegsInMask(const uint32_t *RegMask);
/// Returns true if no part of physical register \p Reg is live.
bool available(unsigned Reg) const {
for (MCRegUnitIterator Unit(Reg, TRI); Unit.isValid(); ++Unit) {
if (Units.test(*Unit))
return false;
}
return true;
}
/// Updates liveness when stepping backwards over the instruction \p MI.
void stepBackward(const MachineInstr &MI);
/// Mark all register units live during instruction \p MI.
/// This can be used to accumulate live/unoccupied registers over a range of
/// instructions.
void accumulateBackward(const MachineInstr &MI);
/// Adds registers living out of block \p MBB.
/// Live out registers are the union of the live-in registers of the successor
/// blocks and pristine registers. Live out registers of the end block are the
/// callee saved registers.
void addLiveOuts(const MachineBasicBlock &MBB);
/// Adds registers living into block \p MBB.
void addLiveIns(const MachineBasicBlock &MBB);
/// Adds all register units marked in the bitvector \p RegUnits.
void addUnits(const BitVector &RegUnits) {
Units |= RegUnits;
}
/// Removes all register units marked in the bitvector \p RegUnits.
void removeUnits(const BitVector &RegUnits) {
Units.reset(RegUnits);
}
/// Return the internal bitvector representation of the set.
const BitVector &getBitVector() const {
return Units;
}
};
} // end namespace llvm
#endif // LLVM_CODEGEN_LIVEREGUNITS_H

View File

@ -1,4 +1,4 @@
//== llvm/CodeGen/GlobalISel/LowLevelType.h -------------------- -*- C++ -*-==//
//== llvm/CodeGen/LowLevelType.h ------------------------------- -*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
@ -10,197 +10,23 @@
/// Implement a low-level type suitable for MachineInstr level instruction
/// selection.
///
/// For a type attached to a MachineInstr, we only care about 2 details: total
/// size and the number of vector lanes (if any). Accordingly, there are 4
/// possible valid type-kinds:
///
/// * `sN` for scalars and aggregates
/// * `<N x sM>` for vectors, which must have at least 2 elements.
/// * `pN` for pointers
///
/// Other information required for correct selection is expected to be carried
/// by the opcode, or non-type flags. For example the distinction between G_ADD
/// and G_FADD for int/float or fast-math flags.
/// This provides the CodeGen aspects of LowLevelType, such as Type conversion.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_GLOBALISEL_LOWLEVELTYPE_H
#define LLVM_CODEGEN_GLOBALISEL_LOWLEVELTYPE_H
#ifndef LLVM_CODEGEN_LOWLEVELTYPE_H
#define LLVM_CODEGEN_LOWLEVELTYPE_H
#include <cassert>
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/Support/LowLevelTypeImpl.h"
namespace llvm {
class DataLayout;
class LLVMContext;
class Type;
class raw_ostream;
class LLT {
public:
enum TypeKind : uint16_t {
Invalid,
Scalar,
Pointer,
Vector,
};
/// Get a low-level scalar or aggregate "bag of bits".
static LLT scalar(unsigned SizeInBits) {
assert(SizeInBits > 0 && "invalid scalar size");
return LLT{Scalar, 1, SizeInBits};
}
/// Get a low-level pointer in the given address space (defaulting to 0).
static LLT pointer(uint16_t AddressSpace, unsigned SizeInBits) {
return LLT{Pointer, AddressSpace, SizeInBits};
}
/// Get a low-level vector of some number of elements and element width.
/// \p NumElements must be at least 2.
static LLT vector(uint16_t NumElements, unsigned ScalarSizeInBits) {
assert(NumElements > 1 && "invalid number of vector elements");
return LLT{Vector, NumElements, ScalarSizeInBits};
}
/// Get a low-level vector of some number of elements and element type.
static LLT vector(uint16_t NumElements, LLT ScalarTy) {
assert(NumElements > 1 && "invalid number of vector elements");
assert(ScalarTy.isScalar() && "invalid vector element type");
return LLT{Vector, NumElements, ScalarTy.getSizeInBits()};
}
explicit LLT(TypeKind Kind, uint16_t NumElements, unsigned SizeInBits)
: SizeInBits(SizeInBits), ElementsOrAddrSpace(NumElements), Kind(Kind) {
assert((Kind != Vector || ElementsOrAddrSpace > 1) &&
"invalid number of vector elements");
}
explicit LLT() : SizeInBits(0), ElementsOrAddrSpace(0), Kind(Invalid) {}
/// Construct a low-level type based on an LLVM type.
explicit LLT(Type &Ty, const DataLayout &DL);
explicit LLT(MVT VT);
bool isValid() const { return Kind != Invalid; }
bool isScalar() const { return Kind == Scalar; }
bool isPointer() const { return Kind == Pointer; }
bool isVector() const { return Kind == Vector; }
/// Returns the number of elements in a vector LLT. Must only be called on
/// vector types.
uint16_t getNumElements() const {
assert(isVector() && "cannot get number of elements on scalar/aggregate");
return ElementsOrAddrSpace;
}
/// Returns the total size of the type. Must only be called on sized types.
unsigned getSizeInBits() const {
if (isPointer() || isScalar())
return SizeInBits;
return SizeInBits * ElementsOrAddrSpace;
}
unsigned getScalarSizeInBits() const {
return SizeInBits;
}
unsigned getAddressSpace() const {
assert(isPointer() && "cannot get address space of non-pointer type");
return ElementsOrAddrSpace;
}
/// Returns the vector's element type. Only valid for vector types.
LLT getElementType() const {
assert(isVector() && "cannot get element type of scalar/aggregate");
return scalar(SizeInBits);
}
/// Get a low-level type with half the size of the original, by halving the
/// size of the scalar type involved. For example `s32` will become `s16`,
/// `<2 x s32>` will become `<2 x s16>`.
LLT halfScalarSize() const {
assert(!isPointer() && getScalarSizeInBits() > 1 &&
getScalarSizeInBits() % 2 == 0 && "cannot half size of this type");
return LLT{Kind, ElementsOrAddrSpace, SizeInBits / 2};
}
/// Get a low-level type with twice the size of the original, by doubling the
/// size of the scalar type involved. For example `s32` will become `s64`,
/// `<2 x s32>` will become `<2 x s64>`.
LLT doubleScalarSize() const {
assert(!isPointer() && "cannot change size of this type");
return LLT{Kind, ElementsOrAddrSpace, SizeInBits * 2};
}
/// Get a low-level type with half the size of the original, by halving the
/// number of vector elements of the scalar type involved. The source must be
/// a vector type with an even number of elements. For example `<4 x s32>`
/// will become `<2 x s32>`, `<2 x s32>` will become `s32`.
LLT halfElements() const {
assert(isVector() && ElementsOrAddrSpace % 2 == 0 &&
"cannot half odd vector");
if (ElementsOrAddrSpace == 2)
return scalar(SizeInBits);
return LLT{Vector, static_cast<uint16_t>(ElementsOrAddrSpace / 2),
SizeInBits};
}
/// Get a low-level type with twice the size of the original, by doubling the
/// number of vector elements of the scalar type involved. The source must be
/// a vector type. For example `<2 x s32>` will become `<4 x s32>`. Doubling
/// the number of elements in sN produces <2 x sN>.
LLT doubleElements() const {
assert(!isPointer() && "cannot double elements in pointer");
return LLT{Vector, static_cast<uint16_t>(ElementsOrAddrSpace * 2),
SizeInBits};
}
void print(raw_ostream &OS) const;
bool operator==(const LLT &RHS) const {
return Kind == RHS.Kind && SizeInBits == RHS.SizeInBits &&
ElementsOrAddrSpace == RHS.ElementsOrAddrSpace;
}
bool operator!=(const LLT &RHS) const { return !(*this == RHS); }
friend struct DenseMapInfo<LLT>;
private:
unsigned SizeInBits;
uint16_t ElementsOrAddrSpace;
TypeKind Kind;
};
inline raw_ostream& operator<<(raw_ostream &OS, const LLT &Ty) {
Ty.print(OS);
return OS;
}
template<> struct DenseMapInfo<LLT> {
static inline LLT getEmptyKey() {
return LLT{LLT::Invalid, 0, -1u};
}
static inline LLT getTombstoneKey() {
return LLT{LLT::Invalid, 0, -2u};
}
static inline unsigned getHashValue(const LLT &Ty) {
uint64_t Val = ((uint64_t)Ty.SizeInBits << 32) |
((uint64_t)Ty.ElementsOrAddrSpace << 16) | (uint64_t)Ty.Kind;
return DenseMapInfo<uint64_t>::getHashValue(Val);
}
static bool isEqual(const LLT &LHS, const LLT &RHS) {
return LHS == RHS;
}
};
/// Construct a low-level type based on an LLVM type.
LLT getLLTForType(Type &Ty, const DataLayout &DL);
}
#endif
#endif // LLVM_CODEGEN_LOWLEVELTYPE_H

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