Upgrade our copy of llvm/clang to r126079, from upstream's trunk.

This contains many improvements, primarily better C++ support, an
integrated assembler for x86 and support for -pg.
This commit is contained in:
dim 2011-02-20 19:33:47 +00:00
commit a0b20b5d1f
1959 changed files with 228380 additions and 124333 deletions

View File

@ -974,7 +974,6 @@ _crunchgen= usr.sbin/crunch/crunchgen
# with different per-architecture default values. Always build tblgen.
_clang_tblgen= \
lib/clang/libllvmsupport \
lib/clang/libllvmsystem \
usr.bin/clang/tblgen
.if ${MK_CDDL} != "no"

View File

@ -38,6 +38,14 @@
# xargs -n1 | sort | uniq -d;
# done
# 20110220: new clang import which bumps version from 2.8 to 2.9
OLD_FILES+=usr/include/clang/2.8/emmintrin.h
OLD_FILES+=usr/include/clang/2.8/mm_malloc.h
OLD_FILES+=usr/include/clang/2.8/mmintrin.h
OLD_FILES+=usr/include/clang/2.8/pmmintrin.h
OLD_FILES+=usr/include/clang/2.8/tmmintrin.h
OLD_FILES+=usr/include/clang/2.8/xmmintrin.h
OLD_DIRS+=usr/include/clang/2.8
# 20110119: Remove SYSCTL_*X* sysctl additions.
OLD_FILES+=usr/share/man/man9/SYSCTL_XINT.9.gz \
usr/share/man/man9/SYSCTL_XLONG.9.gz

View File

@ -33,13 +33,14 @@
#ifndef LLVM_C_CORE_H
#define LLVM_C_CORE_H
#include "llvm/System/DataTypes.h"
#include "llvm/Support/DataTypes.h"
#ifdef __cplusplus
/* Need these includes to support the LLVM 'cast' template for the C++ 'wrap'
and 'unwrap' conversion functions. */
#include "llvm/Module.h"
#include "llvm/PassRegistry.h"
#include "llvm/Support/IRBuilder.h"
extern "C" {
@ -92,6 +93,9 @@ typedef struct LLVMOpaqueMemoryBuffer *LLVMMemoryBufferRef;
/** See the llvm::PassManagerBase class. */
typedef struct LLVMOpaquePassManager *LLVMPassManagerRef;
/** See the llvm::PassRegistry class. */
typedef struct LLVMOpaquePassRegistry *LLVMPassRegistryRef;
/** Used to get the users and usees of a Value. See the llvm::Use class. */
typedef struct LLVMOpaqueUse *LLVMUseRef;
@ -204,7 +208,8 @@ typedef enum {
LLVMPointerTypeKind, /**< Pointers */
LLVMOpaqueTypeKind, /**< Opaque: type with unknown structure */
LLVMVectorTypeKind, /**< SIMD 'packed' format, or other vector type */
LLVMMetadataTypeKind /**< Metadata */
LLVMMetadataTypeKind, /**< Metadata */
LLVMX86_MMXTypeKind /**< X86 MMX */
} LLVMTypeKind;
typedef enum {
@ -317,6 +322,7 @@ void LLVMSetTarget(LLVMModuleRef M, const char *Triple);
LLVMBool LLVMAddTypeName(LLVMModuleRef M, const char *Name, LLVMTypeRef Ty);
void LLVMDeleteTypeName(LLVMModuleRef M, const char *Name);
LLVMTypeRef LLVMGetTypeByName(LLVMModuleRef M, const char *Name);
const char *LLVMGetTypeName(LLVMModuleRef M, LLVMTypeRef Ty);
/** See Module::dump. */
void LLVMDumpModule(LLVMModuleRef M);
@ -324,6 +330,9 @@ void LLVMDumpModule(LLVMModuleRef M);
/** See Module::setModuleInlineAsm. */
void LLVMSetModuleInlineAsm(LLVMModuleRef M, const char *Asm);
/** See Module::getContext. */
LLVMContextRef LLVMGetModuleContext(LLVMModuleRef M);
/*===-- Types -------------------------------------------------------------===*/
/* LLVM types conform to the following hierarchy:
@ -408,10 +417,12 @@ unsigned LLVMGetVectorSize(LLVMTypeRef VectorTy);
LLVMTypeRef LLVMVoidTypeInContext(LLVMContextRef C);
LLVMTypeRef LLVMLabelTypeInContext(LLVMContextRef C);
LLVMTypeRef LLVMOpaqueTypeInContext(LLVMContextRef C);
LLVMTypeRef LLVMX86MMXTypeInContext(LLVMContextRef C);
LLVMTypeRef LLVMVoidType(void);
LLVMTypeRef LLVMLabelType(void);
LLVMTypeRef LLVMOpaqueType(void);
LLVMTypeRef LLVMX86MMXType(void);
/* Operations on type handles */
LLVMTypeHandleRef LLVMCreateTypeHandle(LLVMTypeRef PotentiallyAbstractTy);
@ -540,6 +551,9 @@ LLVMValueRef LLVMMDNode(LLVMValueRef *Vals, unsigned Count);
/* Operations on scalar constants */
LLVMValueRef LLVMConstInt(LLVMTypeRef IntTy, unsigned long long N,
LLVMBool SignExtend);
LLVMValueRef LLVMConstIntOfArbitraryPrecision(LLVMTypeRef IntTy,
unsigned NumWords,
const uint64_t Words[]);
LLVMValueRef LLVMConstIntOfString(LLVMTypeRef IntTy, const char *Text,
uint8_t Radix);
LLVMValueRef LLVMConstIntOfStringAndSize(LLVMTypeRef IntTy, const char *Text,
@ -1013,6 +1027,11 @@ LLVMBool LLVMCreateMemoryBufferWithSTDIN(LLVMMemoryBufferRef *OutMemBuf,
char **OutMessage);
void LLVMDisposeMemoryBuffer(LLVMMemoryBufferRef MemBuf);
/*===-- Pass Registry -----------------------------------------------------===*/
/** Return the global pass registry, for use with initialization functions.
See llvm::PassRegistry::getPassRegistry. */
LLVMPassRegistryRef LLVMGetGlobalPassRegistry(void);
/*===-- Pass Managers -----------------------------------------------------===*/
@ -1101,6 +1120,7 @@ namespace llvm {
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLVMContext, LLVMContextRef )
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Use, LLVMUseRef )
DEFINE_STDCXX_CONVERSION_FUNCTIONS(PassManagerBase, LLVMPassManagerRef )
DEFINE_STDCXX_CONVERSION_FUNCTIONS(PassRegistry, LLVMPassRegistryRef )
/* LLVMModuleProviderRef exists for historical reasons, but now just holds a
* Module.
*/

View File

@ -19,7 +19,7 @@
#ifndef LLVM_C_ENHANCEDDISASSEMBLY_H
#define LLVM_C_ENHANCEDDISASSEMBLY_H
#include "llvm/System/DataTypes.h"
#include "llvm/Support/DataTypes.h"
#ifdef __cplusplus
extern "C" {

View File

@ -0,0 +1,40 @@
/*===-- llvm-c/Initialization.h - Initialization C Interface ------*- C -*-===*\
|* *|
|* The LLVM Compiler Infrastructure *|
|* *|
|* This file is distributed under the University of Illinois Open Source *|
|* License. See LICENSE.TXT for details. *|
|* *|
|*===----------------------------------------------------------------------===*|
|* *|
|* This header declares the C interface to LLVM initialization routines, *|
|* which must be called before you can use the functionality provided by *|
|* the corresponding LLVM library. *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef LLVM_C_INITIALIZEPASSES_H
#define LLVM_C_INITIALIZEPASSES_H
#include "llvm-c/Core.h"
#ifdef __cplusplus
extern "C" {
#endif
void LLVMInitializeCore(LLVMPassRegistryRef R);
void LLVMInitializeTransformUtils(LLVMPassRegistryRef R);
void LLVMInitializeScalarOpts(LLVMPassRegistryRef R);
void LLVMInitializeInstCombine(LLVMPassRegistryRef R);
void LLVMInitializeIPO(LLVMPassRegistryRef R);
void LLVMInitializeInstrumentation(LLVMPassRegistryRef R);
void LLVMInitializeAnalysis(LLVMPassRegistryRef R);
void LLVMInitializeIPA(LLVMPassRegistryRef R);
void LLVMInitializeCodeGen(LLVMPassRegistryRef R);
void LLVMInitializeTarget(LLVMPassRegistryRef R);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
// This header provides a C API to use the LLVM link time optimization
// library. This is inteded to be used by linkers which are C-only in
// library. This is intended to be used by linkers which are C-only in
// their implementation for performing LTO.
//
//===----------------------------------------------------------------------===//

View File

@ -52,9 +52,6 @@ void LLVMAddLICMPass(LLVMPassManagerRef PM);
/** See llvm::createLoopDeletionPass function. */
void LLVMAddLoopDeletionPass(LLVMPassManagerRef PM);
/** See llvm::createLoopIndexSplitPass function. */
void LLVMAddLoopIndexSplitPass(LLVMPassManagerRef PM);
/** See llvm::createLoopRotatePass function. */
void LLVMAddLoopRotatePass(LLVMPassManagerRef PM);

View File

@ -18,27 +18,28 @@
#include <stdbool.h>
#include <stddef.h>
#include "llvm/System/DataTypes.h"
#include <unistd.h>
#define LTO_API_VERSION 3
#define LTO_API_VERSION 4
typedef enum {
LTO_SYMBOL_ALIGNMENT_MASK = 0x0000001F, /* log2 of alignment */
LTO_SYMBOL_PERMISSIONS_MASK = 0x000000E0,
LTO_SYMBOL_PERMISSIONS_CODE = 0x000000A0,
LTO_SYMBOL_PERMISSIONS_DATA = 0x000000C0,
LTO_SYMBOL_PERMISSIONS_RODATA = 0x00000080,
LTO_SYMBOL_DEFINITION_MASK = 0x00000700,
LTO_SYMBOL_DEFINITION_REGULAR = 0x00000100,
LTO_SYMBOL_DEFINITION_TENTATIVE = 0x00000200,
LTO_SYMBOL_DEFINITION_WEAK = 0x00000300,
LTO_SYMBOL_DEFINITION_UNDEFINED = 0x00000400,
LTO_SYMBOL_DEFINITION_WEAKUNDEF = 0x00000500,
LTO_SYMBOL_SCOPE_MASK = 0x00003800,
LTO_SYMBOL_SCOPE_INTERNAL = 0x00000800,
LTO_SYMBOL_SCOPE_HIDDEN = 0x00001000,
LTO_SYMBOL_SCOPE_PROTECTED = 0x00002000,
LTO_SYMBOL_SCOPE_DEFAULT = 0x00001800
LTO_SYMBOL_ALIGNMENT_MASK = 0x0000001F, /* log2 of alignment */
LTO_SYMBOL_PERMISSIONS_MASK = 0x000000E0,
LTO_SYMBOL_PERMISSIONS_CODE = 0x000000A0,
LTO_SYMBOL_PERMISSIONS_DATA = 0x000000C0,
LTO_SYMBOL_PERMISSIONS_RODATA = 0x00000080,
LTO_SYMBOL_DEFINITION_MASK = 0x00000700,
LTO_SYMBOL_DEFINITION_REGULAR = 0x00000100,
LTO_SYMBOL_DEFINITION_TENTATIVE = 0x00000200,
LTO_SYMBOL_DEFINITION_WEAK = 0x00000300,
LTO_SYMBOL_DEFINITION_UNDEFINED = 0x00000400,
LTO_SYMBOL_DEFINITION_WEAKUNDEF = 0x00000500,
LTO_SYMBOL_SCOPE_MASK = 0x00003800,
LTO_SYMBOL_SCOPE_INTERNAL = 0x00000800,
LTO_SYMBOL_SCOPE_HIDDEN = 0x00001000,
LTO_SYMBOL_SCOPE_PROTECTED = 0x00002000,
LTO_SYMBOL_SCOPE_DEFAULT = 0x00001800,
LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN = 0x00002800
} lto_symbol_attributes;
typedef enum {
@ -121,6 +122,13 @@ lto_module_create(const char* path);
extern lto_module_t
lto_module_create_from_memory(const void* mem, size_t length);
/**
* Loads an object file from disk. The seek point of fd is not preserved.
* Returns NULL on error (check lto_get_error_message() for details).
*/
extern lto_module_t
lto_module_create_from_fd(int fd, const char *path, off_t size);
/**
* Frees all memory internally allocated by the module.
@ -146,7 +154,7 @@ lto_module_set_target_triple(lto_module_t mod, const char *triple);
/**
* Returns the number of symbols in the object module.
*/
extern uint32_t
extern unsigned int
lto_module_get_num_symbols(lto_module_t mod);
@ -154,14 +162,14 @@ lto_module_get_num_symbols(lto_module_t mod);
* Returns the name of the ith symbol in the object module.
*/
extern const char*
lto_module_get_symbol_name(lto_module_t mod, uint32_t index);
lto_module_get_symbol_name(lto_module_t mod, unsigned int index);
/**
* Returns the attributes of the ith symbol in the object module.
*/
extern lto_symbol_attributes
lto_module_get_symbol_attribute(lto_module_t mod, uint32_t index);
lto_module_get_symbol_attribute(lto_module_t mod, unsigned int index);
/**

View File

@ -246,6 +246,13 @@ namespace llvm {
static APFloat getSmallestNormalized(const fltSemantics &Sem,
bool Negative = false);
/// getAllOnesValue - Returns a float which is bitcasted from
/// an all one value int.
///
/// \param BitWidth - Select float type
/// \param isIEEE - If 128 bit number, select between PPC and IEEE
static APFloat getAllOnesValue(unsigned BitWidth, bool isIEEE = false);
/// Profile - Used to insert APFloat objects, or objects that contain
/// APFloat objects, into FoldingSets.
void Profile(FoldingSetNodeID& NID) const;

View File

@ -275,12 +275,6 @@ public:
/// objects, into FoldingSets.
void Profile(FoldingSetNodeID& id) const;
/// @brief Used by the Bitcode serializer to emit APInts to Bitcode.
void Emit(Serializer& S) const;
/// @brief Used by the Bitcode deserializer to deserialize APInts.
void Read(Deserializer& D);
/// @}
/// @name Value Tests
/// @{
@ -302,7 +296,7 @@ public:
/// @returns true if this APInt is positive.
/// @brief Determine if this APInt Value is positive.
bool isStrictlyPositive() const {
return isNonNegative() && (*this) != 0;
return isNonNegative() && !!*this;
}
/// This checks to see if the value has all bits of the APInt are set or not.
@ -330,15 +324,14 @@ public:
/// value for the APInt's bit width.
/// @brief Determine if this is the smallest unsigned value.
bool isMinValue() const {
return countPopulation() == 0;
return !*this;
}
/// This checks to see if the value of this APInt is the minimum signed
/// value for the APInt's bit width.
/// @brief Determine if this is the smallest signed value.
bool isMinSignedValue() const {
return BitWidth == 1 ? VAL == 1 :
isNegative() && countPopulation() == 1;
return BitWidth == 1 ? VAL == 1 : isNegative() && isPowerOf2();
}
/// @brief Check if this APInt has an N-bits unsigned integer value.
@ -348,10 +341,8 @@ public:
return true;
if (isSingleWord())
return VAL == (VAL & (~0ULL >> (64 - N)));
APInt Tmp(N, getNumWords(), pVal);
Tmp.zext(getBitWidth());
return Tmp == (*this);
return isUIntN(N, VAL);
return APInt(N, getNumWords(), pVal).zext(getBitWidth()) == (*this);
}
/// @brief Check if this APInt has an N-bits signed integer value.
@ -361,7 +352,11 @@ public:
}
/// @returns true if the argument APInt value is a power of two > 0.
bool isPowerOf2() const;
bool isPowerOf2() const {
if (isSingleWord())
return isPowerOf2_64(VAL);
return countPopulationSlowCase() == 1;
}
/// isSignBit - Return true if this is the value returned by getSignBit.
bool isSignBit() const { return isMinSignedValue(); }
@ -369,7 +364,7 @@ public:
/// This converts the APInt to a boolean value as a test against zero.
/// @brief Boolean conversion function.
bool getBoolValue() const {
return *this != 0;
return !!*this;
}
/// getLimitedValue - If this value is smaller than the specified limit,
@ -385,12 +380,14 @@ public:
/// @{
/// @brief Gets maximum unsigned value of APInt for specific bit width.
static APInt getMaxValue(unsigned numBits) {
return APInt(numBits, 0).set();
return getAllOnesValue(numBits);
}
/// @brief Gets maximum signed value of APInt for a specific bit width.
static APInt getSignedMaxValue(unsigned numBits) {
return APInt(numBits, 0).set().clear(numBits - 1);
APInt API = getAllOnesValue(numBits);
API.clearBit(numBits - 1);
return API;
}
/// @brief Gets minimum unsigned value of APInt for a specific bit width.
@ -400,7 +397,9 @@ public:
/// @brief Gets minimum signed value of APInt for a specific bit width.
static APInt getSignedMinValue(unsigned numBits) {
return APInt(numBits, 0).set(numBits - 1);
APInt API(numBits, 0);
API.setBit(numBits - 1);
return API;
}
/// getSignBit - This is just a wrapper function of getSignedMinValue(), and
@ -413,7 +412,7 @@ public:
/// @returns the all-ones value for an APInt of the specified bit-width.
/// @brief Get the all-ones value.
static APInt getAllOnesValue(unsigned numBits) {
return APInt(numBits, 0).set();
return APInt(numBits, -1ULL, true);
}
/// @returns the '0' value for an APInt of the specified bit-width.
@ -432,6 +431,13 @@ public:
/// @returns the low "numBits" bits of this APInt.
APInt getLoBits(unsigned numBits) const;
/// getOneBitSet - Return an APInt with exactly one bit set in the result.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo) {
APInt Res(numBits, 0);
Res.setBit(BitNo);
return Res;
}
/// Constructs an APInt value that has a contiguous range of bits set. The
/// bits from loBit (inclusive) to hiBit (exclusive) will be set. All other
/// bits will be zero. For example, with parameters(32, 0, 16) you would get
@ -530,7 +536,7 @@ public:
/// @brief Unary bitwise complement operator.
APInt operator~() const {
APInt Result(*this);
Result.flip();
Result.flipAllBits();
return Result;
}
@ -741,11 +747,11 @@ public:
/// RHS are treated as unsigned quantities for purposes of this division.
/// @returns a new APInt value containing the division result
/// @brief Unsigned division operation.
APInt udiv(const APInt& RHS) const;
APInt udiv(const APInt &RHS) const;
/// Signed divide this APInt by APInt RHS.
/// @brief Signed division function for APInt.
APInt sdiv(const APInt& RHS) const {
APInt sdiv(const APInt &RHS) const {
if (isNegative())
if (RHS.isNegative())
return (-(*this)).udiv(-RHS);
@ -763,11 +769,11 @@ public:
/// which is *this.
/// @returns a new APInt value containing the remainder result
/// @brief Unsigned remainder operation.
APInt urem(const APInt& RHS) const;
APInt urem(const APInt &RHS) const;
/// Signed remainder operation on APInt.
/// @brief Function for signed remainder operation.
APInt srem(const APInt& RHS) const {
APInt srem(const APInt &RHS) const {
if (isNegative())
if (RHS.isNegative())
return -((-(*this)).urem(-RHS));
@ -788,8 +794,7 @@ public:
APInt &Quotient, APInt &Remainder);
static void sdivrem(const APInt &LHS, const APInt &RHS,
APInt &Quotient, APInt &Remainder)
{
APInt &Quotient, APInt &Remainder) {
if (LHS.isNegative()) {
if (RHS.isNegative())
APInt::udivrem(-LHS, -RHS, Quotient, Remainder);
@ -804,6 +809,16 @@ public:
APInt::udivrem(LHS, RHS, Quotient, Remainder);
}
}
// Operations that return overflow indicators.
APInt sadd_ov(const APInt &RHS, bool &Overflow) const;
APInt uadd_ov(const APInt &RHS, bool &Overflow) const;
APInt ssub_ov(const APInt &RHS, bool &Overflow) const;
APInt usub_ov(const APInt &RHS, bool &Overflow) const;
APInt sdiv_ov(const APInt &RHS, bool &Overflow) const;
APInt smul_ov(const APInt &RHS, bool &Overflow) const;
APInt sshl_ov(unsigned Amt, bool &Overflow) const;
/// @returns the bit value at bitPosition
/// @brief Array-indexing support.
@ -868,7 +883,7 @@ public:
/// the validity of the less-than relationship.
/// @returns true if *this < RHS when both are considered unsigned.
/// @brief Unsigned less than comparison
bool ult(const APInt& RHS) const;
bool ult(const APInt &RHS) const;
/// Regards both *this as an unsigned quantity and compares it with RHS for
/// the validity of the less-than relationship.
@ -988,6 +1003,9 @@ public:
return sge(APInt(getBitWidth(), RHS));
}
/// 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 {
@ -1000,80 +1018,78 @@ public:
/// Truncate the APInt to a specified width. It is an error to specify a width
/// that is greater than or equal to the current width.
/// @brief Truncate to new width.
APInt &trunc(unsigned width);
APInt trunc(unsigned width) const;
/// This operation sign extends the APInt to a new width. If the high order
/// bit is set, the fill on the left will be done with 1 bits, otherwise zero.
/// It is an error to specify a width that is less than or equal to the
/// current width.
/// @brief Sign extend to a new width.
APInt &sext(unsigned width);
APInt sext(unsigned width) const;
/// This operation zero extends the APInt to a new width. The high order bits
/// are filled with 0 bits. It is an error to specify a width that is less
/// than or equal to the current width.
/// @brief Zero extend to a new width.
APInt &zext(unsigned width);
APInt zext(unsigned width) const;
/// Make this APInt have the bit width given by \p width. The value is sign
/// extended, truncated, or left alone to make it that width.
/// @brief Sign extend or truncate to width
APInt &sextOrTrunc(unsigned width);
APInt sextOrTrunc(unsigned width) const;
/// Make this APInt have the bit width given by \p width. The value is zero
/// extended, truncated, or left alone to make it that width.
/// @brief Zero extend or truncate to width
APInt &zextOrTrunc(unsigned width);
APInt zextOrTrunc(unsigned width) const;
/// @}
/// @name Bit Manipulation Operators
/// @{
/// @brief Set every bit to 1.
APInt& set() {
if (isSingleWord()) {
void setAllBits() {
if (isSingleWord())
VAL = -1ULL;
return clearUnusedBits();
else {
// Set all the bits in all the words.
for (unsigned i = 0; i < getNumWords(); ++i)
pVal[i] = -1ULL;
}
// Set all the bits in all the words.
for (unsigned i = 0; i < getNumWords(); ++i)
pVal[i] = -1ULL;
// Clear the unused ones
return clearUnusedBits();
clearUnusedBits();
}
/// Set the given bit to 1 whose position is given as "bitPosition".
/// @brief Set a given bit to 1.
APInt& set(unsigned bitPosition);
void setBit(unsigned bitPosition);
/// @brief Set every bit to 0.
APInt& clear() {
void clearAllBits() {
if (isSingleWord())
VAL = 0;
else
memset(pVal, 0, getNumWords() * APINT_WORD_SIZE);
return *this;
}
/// Set the given bit to 0 whose position is given as "bitPosition".
/// @brief Set a given bit to 0.
APInt& clear(unsigned bitPosition);
void clearBit(unsigned bitPosition);
/// @brief Toggle every bit to its opposite value.
APInt& flip() {
if (isSingleWord()) {
void flipAllBits() {
if (isSingleWord())
VAL ^= -1ULL;
return clearUnusedBits();
else {
for (unsigned i = 0; i < getNumWords(); ++i)
pVal[i] ^= -1ULL;
}
for (unsigned i = 0; i < getNumWords(); ++i)
pVal[i] ^= -1ULL;
return clearUnusedBits();
clearUnusedBits();
}
/// Toggle a given bit to its opposite value whose position is given
/// as "bitPosition".
/// @brief Toggles a given bit to its opposite value.
APInt& flip(unsigned bitPosition);
void flipBit(unsigned bitPosition);
/// @}
/// @name Value Characterization Functions
@ -1281,37 +1297,27 @@ public:
}
/// The conversion does not do a translation from double to integer, it just
/// re-interprets the bits of the double. Note that it is valid to do this on
/// any bit width but bits from V may get truncated.
/// re-interprets the bits of the double.
/// @brief Converts a double to APInt bits.
APInt& doubleToBits(double V) {
static APInt doubleToBits(double V) {
union {
uint64_t I;
double D;
} T;
T.D = V;
if (isSingleWord())
VAL = T.I;
else
pVal[0] = T.I;
return clearUnusedBits();
return APInt(sizeof T * CHAR_BIT, T.I);
}
/// The conversion does not do a translation from float to integer, it just
/// re-interprets the bits of the float. Note that it is valid to do this on
/// any bit width but bits from V may get truncated.
/// re-interprets the bits of the float.
/// @brief Converts a float to APInt bits.
APInt& floatToBits(float V) {
static APInt floatToBits(float V) {
union {
unsigned I;
float F;
} T;
T.F = V;
if (isSingleWord())
VAL = T.I;
else
pVal[0] = T.I;
return clearUnusedBits();
return APInt(sizeof T * CHAR_BIT, T.I);
}
/// @}

View File

@ -68,20 +68,22 @@ public:
}
using APInt::toString;
APSInt& extend(uint32_t width) {
if (IsUnsigned)
zext(width);
else
sext(width);
return *this;
APSInt trunc(uint32_t width) const {
return APSInt(APInt::trunc(width), IsUnsigned);
}
APSInt& extOrTrunc(uint32_t width) {
APSInt extend(uint32_t width) const {
if (IsUnsigned)
return APSInt(zext(width), IsUnsigned);
else
return APSInt(sext(width), IsUnsigned);
}
APSInt extOrTrunc(uint32_t width) const {
if (IsUnsigned)
zextOrTrunc(width);
return APSInt(zextOrTrunc(width), IsUnsigned);
else
sextOrTrunc(width);
return *this;
return APSInt(sextOrTrunc(width), IsUnsigned);
}
const APSInt &operator%=(const APSInt &RHS) {

View File

@ -0,0 +1,121 @@
//===--- ArrayRef.h - Array Reference Wrapper -------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ADT_ARRAYREF_H
#define LLVM_ADT_ARRAYREF_H
#include "llvm/ADT/SmallVector.h"
#include <vector>
namespace llvm {
class APInt;
/// ArrayRef - Represent a constant reference to an array (0 or more elements
/// consecutively in memory), i.e. a start pointer and a length. It allows
/// various APIs to take consecutive elements easily and conveniently.
///
/// This class does not own the underlying data, it is expected to be used in
/// situations where the data resides in some other buffer, whose lifetime
/// extends past that of the StringRef. For this reason, it is not in general
/// safe to store a ArrayRef.
///
/// This is intended to be trivially copyable, so it should be passed by
/// value.
template<typename T>
class ArrayRef {
public:
typedef const T *iterator;
typedef const T *const_iterator;
typedef size_t size_type;
private:
/// The start of the array, in an external buffer.
const T *Data;
/// The number of elements.
size_t Length;
public:
/// @name Constructors
/// @{
/// Construct an empty ArrayRef.
/*implicit*/ ArrayRef() : Data(0), Length(0) {}
/// Construct an ArrayRef from a single element.
/*implicit*/ ArrayRef(const T &OneElt)
: Data(&OneElt), Length(1) {}
/// Construct an ArrayRef from a pointer and length.
/*implicit*/ ArrayRef(const T *data, size_t length)
: Data(data), Length(length) {}
/// Construct an ArrayRef from a SmallVector.
/*implicit*/ ArrayRef(const SmallVectorImpl<T> &Vec)
: Data(Vec.data()), Length(Vec.size()) {}
/// Construct an ArrayRef from a std::vector.
/*implicit*/ ArrayRef(const std::vector<T> &Vec)
: Data(Vec.empty() ? (T*)0 : &Vec[0]), Length(Vec.size()) {}
// TODO: C arrays.
/// @}
/// @name Simple Operations
/// @{
iterator begin() const { return Data; }
iterator end() const { return Data + Length; }
/// empty - Check if the array is empty.
bool empty() const { return Length == 0; }
/// size - Get the array size.
size_t size() const { return Length; }
/// front - Get the first element.
const T &front() const {
assert(!empty());
return Data[0];
}
/// back - Get the last element.
const T &back() const {
assert(!empty());
return Data[Length-1];
}
/// @}
/// @name Operator Overloads
/// @{
const T &operator[](size_t Index) const {
assert(Index < Length && "Invalid index!");
return Data[Index];
}
/// @}
/// @name Expensive Operations
/// @{
std::vector<T> vec() const {
return std::vector<T>(Data, Data+Length);
}
/// @}
};
// ArrayRefs can be treated like a POD type.
template <typename T> struct isPodLike;
template <typename T> struct isPodLike<ArrayRef<T> > {
static const bool value = true;
};
}
#endif

View File

@ -18,6 +18,7 @@
#include <algorithm>
#include <cassert>
#include <climits>
#include <cstdlib>
#include <cstring>
namespace llvm {
@ -77,7 +78,7 @@ public:
/// bits are initialized to the specified value.
explicit BitVector(unsigned s, bool t = false) : Size(s) {
Capacity = NumBitWords(s);
Bits = new BitWord[Capacity];
Bits = (BitWord *)std::malloc(Capacity * sizeof(BitWord));
init_words(Bits, Capacity, t);
if (t)
clear_unused_bits();
@ -92,12 +93,12 @@ public:
}
Capacity = NumBitWords(RHS.size());
Bits = new BitWord[Capacity];
std::copy(RHS.Bits, &RHS.Bits[Capacity], Bits);
Bits = (BitWord *)std::malloc(Capacity * sizeof(BitWord));
std::memcpy(Bits, RHS.Bits, Capacity * sizeof(BitWord));
}
~BitVector() {
delete[] Bits;
std::free(Bits);
}
/// empty - Tests whether there are no bits in this bitvector.
@ -127,6 +128,12 @@ public:
return false;
}
/// all - Returns true if all bits are set.
bool all() const {
// TODO: Optimize this.
return count() == size();
}
/// none - Returns true if none of the bits are set.
bool none() const {
return !any();
@ -335,18 +342,18 @@ public:
unsigned RHSWords = NumBitWords(Size);
if (Size <= Capacity * BITWORD_SIZE) {
if (Size)
std::copy(RHS.Bits, &RHS.Bits[RHSWords], Bits);
std::memcpy(Bits, RHS.Bits, RHSWords * sizeof(BitWord));
clear_unused_bits();
return *this;
}
// Grow the bitvector to have enough elements.
Capacity = RHSWords;
BitWord *NewBits = new BitWord[Capacity];
std::copy(RHS.Bits, &RHS.Bits[RHSWords], NewBits);
BitWord *NewBits = (BitWord *)std::malloc(Capacity * sizeof(BitWord));
std::memcpy(NewBits, RHS.Bits, Capacity * sizeof(BitWord));
// Destroy the old bits.
delete[] Bits;
std::free(Bits);
Bits = NewBits;
return *this;
@ -384,17 +391,8 @@ private:
}
void grow(unsigned NewSize) {
unsigned OldCapacity = Capacity;
Capacity = NumBitWords(NewSize);
BitWord *NewBits = new BitWord[Capacity];
// Copy the old bits over.
if (OldCapacity != 0)
std::copy(Bits, &Bits[OldCapacity], NewBits);
// Destroy the old bits.
delete[] Bits;
Bits = NewBits;
Capacity = std::max(NumBitWords(NewSize), Capacity * 2);
Bits = (BitWord *)std::realloc(Bits, Capacity * sizeof(BitWord));
clear_unused_bits();
}

View File

@ -18,6 +18,7 @@
#include "llvm/Support/PointerLikeTypeTraits.h"
#include "llvm/Support/type_traits.h"
#include "llvm/ADT/DenseMapInfo.h"
#include <algorithm>
#include <iterator>
#include <new>
#include <utility>
@ -385,7 +386,7 @@ private:
// Insert the key/value into the new table.
BucketT *DestBucket;
bool FoundVal = LookupBucketFor(B->first, DestBucket);
FoundVal = FoundVal; // silence warning.
(void)FoundVal; // silence warning.
assert(!FoundVal && "Key already in new map?");
DestBucket->first = B->first;
new (&DestBucket->second) ValueT(B->second);

View File

@ -102,6 +102,20 @@ template<> struct DenseMapInfo<int> {
}
};
// Provide DenseMapInfo for longs.
template<> struct DenseMapInfo<long> {
static inline long getEmptyKey() {
return (1UL << (sizeof(long) * 8 - 1)) - 1L;
}
static inline long getTombstoneKey() { return getEmptyKey() - 1L; }
static unsigned getHashValue(const long& Val) {
return (unsigned)(Val * 37L);
}
static bool isEqual(const long& LHS, const long& RHS) {
return LHS == RHS;
}
};
// Provide DenseMapInfo for long longs.
template<> struct DenseMapInfo<long long> {
static inline long long getEmptyKey() { return 0x7fffffffffffffffLL; }

View File

@ -33,6 +33,9 @@ public:
bool empty() const { return TheMap.empty(); }
unsigned size() const { return TheMap.size(); }
/// Grow the denseset so that it has at least Size buckets. Does not shrink
void resize(size_t Size) { TheMap.resize(Size); }
void clear() {
TheMap.clear();
}

View File

@ -15,7 +15,7 @@
#ifndef LLVM_ADT_EQUIVALENCECLASSES_H
#define LLVM_ADT_EQUIVALENCECLASSES_H
#include "llvm/System/DataTypes.h"
#include "llvm/Support/DataTypes.h"
#include <cassert>
#include <set>

View File

@ -16,7 +16,7 @@
#ifndef LLVM_ADT_FOLDINGSET_H
#define LLVM_ADT_FOLDINGSET_H
#include "llvm/System/DataTypes.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"

View File

@ -94,7 +94,7 @@ public:
: ImutAVLFactory<ImutInfo>(Alloc) {}
TreeTy *Add(TreeTy *T, value_type_ref V) {
T = Add_internal(V,T);
T = add_internal(V,T);
this->MarkImmutable(T);
return T;
}
@ -103,20 +103,20 @@ public:
if (!T)
return NULL;
key_type_ref CurrentKey = ImutInfo::KeyOfValue(this->Value(T));
key_type_ref CurrentKey = ImutInfo::KeyOfValue(this->getValue(T));
if (ImutInfo::isContainedIn(K, CurrentKey))
return T;
else if (ImutInfo::isLess(K, CurrentKey))
return Find(this->Left(T), K);
return Find(this->getLeft(T), K);
else
return Find(this->Right(T), K);
return Find(this->getRight(T), K);
}
private:
TreeTy *Add_internal(value_type_ref V, TreeTy *T) {
TreeTy *add_internal(value_type_ref V, TreeTy *T) {
key_type_ref K = ImutInfo::KeyOfValue(V);
T = RemoveAllOverlaps(T, K);
T = removeAllOverlaps(T, K);
if (this->isEmpty(T))
return this->CreateNode(NULL, V, NULL);
@ -125,38 +125,38 @@ private:
key_type_ref KCurrent = ImutInfo::KeyOfValue(this->Value(T));
if (ImutInfo::isLess(K, KCurrent))
return this->Balance(Add_internal(V, this->Left(T)), this->Value(T),
return this->Balance(add_internal(V, this->Left(T)), this->Value(T),
this->Right(T));
else
return this->Balance(this->Left(T), this->Value(T),
Add_internal(V, this->Right(T)));
add_internal(V, this->Right(T)));
}
// Remove all overlaps from T.
TreeTy *RemoveAllOverlaps(TreeTy *T, key_type_ref K) {
TreeTy *removeAllOverlaps(TreeTy *T, key_type_ref K) {
bool Changed;
do {
Changed = false;
T = RemoveOverlap(T, K, Changed);
this->MarkImmutable(T);
T = removeOverlap(T, K, Changed);
this->markImmutable(T);
} while (Changed);
return T;
}
// Remove one overlap from T.
TreeTy *RemoveOverlap(TreeTy *T, key_type_ref K, bool &Changed) {
TreeTy *removeOverlap(TreeTy *T, key_type_ref K, bool &Changed) {
if (!T)
return NULL;
Interval CurrentK = ImutInfo::KeyOfValue(this->Value(T));
// If current key does not overlap the inserted key.
if (CurrentK.getStart() > K.getEnd())
return this->Balance(RemoveOverlap(this->Left(T), K, Changed),
return this->Balance(removeOverlap(this->Left(T), K, Changed),
this->Value(T), this->Right(T));
else if (CurrentK.getEnd() < K.getStart())
return this->Balance(this->Left(T), this->Value(T),
RemoveOverlap(this->Right(T), K, Changed));
removeOverlap(this->Right(T), K, Changed));
// Current key overlaps with the inserted key.
// Remove the current key.
@ -167,18 +167,18 @@ private:
if (CurrentK.getStart() < K.getStart()) {
if (CurrentK.getEnd() <= K.getEnd()) {
Interval NewK(CurrentK.getStart(), K.getStart()-1);
return Add_internal(std::make_pair(NewK, OldData), T);
return add_internal(std::make_pair(NewK, OldData), T);
} else {
Interval NewK1(CurrentK.getStart(), K.getStart()-1);
T = Add_internal(std::make_pair(NewK1, OldData), T);
T = add_internal(std::make_pair(NewK1, OldData), T);
Interval NewK2(K.getEnd()+1, CurrentK.getEnd());
return Add_internal(std::make_pair(NewK2, OldData), T);
return add_internal(std::make_pair(NewK2, OldData), T);
}
} else {
if (CurrentK.getEnd() > K.getEnd()) {
Interval NewK(K.getEnd()+1, CurrentK.getEnd());
return Add_internal(std::make_pair(NewK, OldData), T);
return add_internal(std::make_pair(NewK, OldData), T);
} else
return T;
}
@ -209,22 +209,22 @@ public:
public:
Factory(BumpPtrAllocator& Alloc) : F(Alloc) {}
ImmutableIntervalMap GetEmptyMap() {
return ImmutableIntervalMap(F.GetEmptyTree());
ImmutableIntervalMap getEmptyMap() {
return ImmutableIntervalMap(F.getEmptyTree());
}
ImmutableIntervalMap Add(ImmutableIntervalMap Old,
ImmutableIntervalMap add(ImmutableIntervalMap Old,
key_type_ref K, data_type_ref D) {
TreeTy *T = F.Add(Old.Root, std::make_pair<key_type, data_type>(K, D));
return ImmutableIntervalMap(F.GetCanonicalTree(T));
TreeTy *T = F.add(Old.Root, std::make_pair<key_type, data_type>(K, D));
return ImmutableIntervalMap(F.getCanonicalTree(T));
}
ImmutableIntervalMap Remove(ImmutableIntervalMap Old, key_type_ref K) {
TreeTy *T = F.Remove(Old.Root, K);
return ImmutableIntervalMap(F.GetCanonicalTree(T));
ImmutableIntervalMap remove(ImmutableIntervalMap Old, key_type_ref K) {
TreeTy *T = F.remove(Old.Root, K);
return ImmutableIntervalMap(F.getCanonicalTree(T));
}
data_type *Lookup(ImmutableIntervalMap M, key_type_ref K) {
data_type *lookup(ImmutableIntervalMap M, key_type_ref K) {
TreeTy *T = F.Find(M.getRoot(), K);
if (T)
return &T->getValue().second;

View File

@ -16,7 +16,7 @@
#include "llvm/Support/Allocator.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/System/DataTypes.h"
#include "llvm/Support/DataTypes.h"
#include <cassert>
namespace llvm {
@ -156,7 +156,7 @@ public:
if (ownsAllocator()) delete &getAllocator();
}
ImmutableList<T> Concat(const T& Head, ImmutableList<T> Tail) {
ImmutableList<T> concat(const T& Head, ImmutableList<T> Tail) {
// Profile the new list to see if it already exists in our cache.
FoldingSetNodeID ID;
void* InsertPos;
@ -178,16 +178,16 @@ public:
return L;
}
ImmutableList<T> Add(const T& D, ImmutableList<T> L) {
return Concat(D, L);
ImmutableList<T> add(const T& D, ImmutableList<T> L) {
return concat(D, L);
}
ImmutableList<T> GetEmptyList() const {
ImmutableList<T> getEmptyList() const {
return ImmutableList<T>(0);
}
ImmutableList<T> Create(const T& X) {
return Concat(X, GetEmptyList());
ImmutableList<T> create(const T& X) {
return Concat(X, getEmptyList());
}
};

View File

@ -76,7 +76,23 @@ public:
/// should use a Factory object to create maps instead of directly
/// invoking the constructor, but there are cases where make this
/// constructor public is useful.
explicit ImmutableMap(const TreeTy* R) : Root(const_cast<TreeTy*>(R)) {}
explicit ImmutableMap(const TreeTy* R) : Root(const_cast<TreeTy*>(R)) {
if (Root) { Root->retain(); }
}
ImmutableMap(const ImmutableMap &X) : Root(X.Root) {
if (Root) { Root->retain(); }
}
ImmutableMap &operator=(const ImmutableMap &X) {
if (Root != X.Root) {
if (X.Root) { X.Root->retain(); }
if (Root) { Root->release(); }
Root = X.Root;
}
return *this;
}
~ImmutableMap() {
if (Root) { Root->release(); }
}
class Factory {
typename TreeTy::Factory F;
@ -89,16 +105,16 @@ public:
Factory(BumpPtrAllocator& Alloc, bool canonicalize = true)
: F(Alloc), Canonicalize(canonicalize) {}
ImmutableMap GetEmptyMap() { return ImmutableMap(F.GetEmptyTree()); }
ImmutableMap getEmptyMap() { return ImmutableMap(F.getEmptyTree()); }
ImmutableMap Add(ImmutableMap Old, key_type_ref K, data_type_ref D) {
TreeTy *T = F.Add(Old.Root, std::make_pair<key_type,data_type>(K,D));
return ImmutableMap(Canonicalize ? F.GetCanonicalTree(T): T);
ImmutableMap add(ImmutableMap Old, key_type_ref K, data_type_ref D) {
TreeTy *T = F.add(Old.Root, std::make_pair<key_type,data_type>(K,D));
return ImmutableMap(Canonicalize ? F.getCanonicalTree(T): T);
}
ImmutableMap Remove(ImmutableMap Old, key_type_ref K) {
TreeTy *T = F.Remove(Old.Root,K);
return ImmutableMap(Canonicalize ? F.GetCanonicalTree(T): T);
ImmutableMap remove(ImmutableMap Old, key_type_ref K) {
TreeTy *T = F.remove(Old.Root,K);
return ImmutableMap(Canonicalize ? F.getCanonicalTree(T): T);
}
private:
@ -110,15 +126,30 @@ public:
return Root ? Root->contains(K) : false;
}
bool operator==(ImmutableMap RHS) const {
bool operator==(const ImmutableMap &RHS) const {
return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root;
}
bool operator!=(ImmutableMap RHS) const {
bool operator!=(const ImmutableMap &RHS) const {
return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root;
}
TreeTy* getRoot() const { return Root; }
TreeTy *getRoot() const {
if (Root) { Root->retain(); }
return Root;
}
TreeTy *getRootWithoutRetain() const {
return Root;
}
void manualRetain() {
if (Root) Root->retain();
}
void manualRelease() {
if (Root) Root->release();
}
bool isEmpty() const { return !Root; }

View File

@ -15,10 +15,13 @@
#define LLVM_ADT_IMSET_H
#include "llvm/Support/Allocator.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/System/DataTypes.h"
#include "llvm/Support/DataTypes.h"
#include <cassert>
#include <functional>
#include <vector>
#include <stdio.h>
namespace llvm {
@ -32,7 +35,7 @@ template <typename ImutInfo> class ImutAVLTreeInOrderIterator;
template <typename ImutInfo> class ImutAVLTreeGenericIterator;
template <typename ImutInfo >
class ImutAVLTree : public FoldingSetNode {
class ImutAVLTree {
public:
typedef typename ImutInfo::key_type_ref key_type_ref;
typedef typename ImutInfo::value_type value_type;
@ -43,7 +46,6 @@ public:
friend class ImutIntervalAVLFactory<ImutInfo>;
friend class ImutAVLTreeGenericIterator<ImutInfo>;
friend class FoldingSet<ImutAVLTree>;
typedef ImutAVLTreeInOrderIterator<ImutInfo> iterator;
@ -51,29 +53,27 @@ public:
// Public Interface.
//===----------------------------------------------------===//
/// getLeft - Returns a pointer to the left subtree. This value
/// Return a pointer to the left subtree. This value
/// is NULL if there is no left subtree.
ImutAVLTree *getLeft() const { return Left; }
ImutAVLTree *getLeft() const { return left; }
/// getRight - Returns a pointer to the right subtree. This value is
/// Return a pointer to the right subtree. This value is
/// NULL if there is no right subtree.
ImutAVLTree *getRight() const { return Right; }
ImutAVLTree *getRight() const { return right; }
/// getHeight - Returns the height of the tree. A tree with no subtrees
/// has a height of 1.
unsigned getHeight() const { return Height; }
unsigned getHeight() const { return height; }
/// getValue - Returns the data value associated with the tree node.
const value_type& getValue() const { return Value; }
const value_type& getValue() const { return value; }
/// find - Finds the subtree associated with the specified key value.
/// This method returns NULL if no matching subtree is found.
ImutAVLTree* find(key_type_ref K) {
ImutAVLTree *T = this;
while (T) {
key_type_ref CurrentKey = ImutInfo::KeyOfValue(T->getValue());
if (ImutInfo::isEqual(K,CurrentKey))
return T;
else if (ImutInfo::isLess(K,CurrentKey))
@ -81,7 +81,6 @@ public:
else
T = T->getRight();
}
return NULL;
}
@ -90,7 +89,7 @@ public:
ImutAVLTree* getMaxElement() {
ImutAVLTree *T = this;
ImutAVLTree *Right = T->getRight();
while (Right) { T = Right; Right = T->getRight(); }
while (Right) { T = right; right = T->getRight(); }
return T;
}
@ -98,10 +97,10 @@ public:
/// both leaves and non-leaf nodes.
unsigned size() const {
unsigned n = 1;
if (const ImutAVLTree* L = getLeft()) n += L->size();
if (const ImutAVLTree* R = getRight()) n += R->size();
if (const ImutAVLTree* L = getLeft())
n += L->size();
if (const ImutAVLTree* R = getRight())
n += R->size();
return n;
}
@ -114,7 +113,7 @@ public:
/// inorder traversal.
iterator end() const { return iterator(); }
bool ElementEqual(value_type_ref V) const {
bool isElementEqual(value_type_ref V) const {
// Compare the keys.
if (!ImutInfo::isEqual(ImutInfo::KeyOfValue(getValue()),
ImutInfo::KeyOfValue(V)))
@ -128,8 +127,8 @@ public:
return true;
}
bool ElementEqual(const ImutAVLTree* RHS) const {
return ElementEqual(RHS->getValue());
bool isElementEqual(const ImutAVLTree* RHS) const {
return isElementEqual(RHS->getValue());
}
/// isEqual - Compares two trees for structural equality and returns true
@ -144,12 +143,12 @@ public:
while (LItr != LEnd && RItr != REnd) {
if (*LItr == *RItr) {
LItr.SkipSubTree();
RItr.SkipSubTree();
LItr.skipSubTree();
RItr.skipSubTree();
continue;
}
if (!LItr->ElementEqual(*RItr))
if (!LItr->isElementEqual(*RItr))
return false;
++LItr;
@ -173,22 +172,24 @@ public:
/// Nodes are visited using an inorder traversal.
template <typename Callback>
void foreach(Callback& C) {
if (ImutAVLTree* L = getLeft()) L->foreach(C);
if (ImutAVLTree* L = getLeft())
L->foreach(C);
C(Value);
C(value);
if (ImutAVLTree* R = getRight()) R->foreach(C);
if (ImutAVLTree* R = getRight())
R->foreach(C);
}
/// verify - A utility method that checks that the balancing and
/// validateTree - A utility method that checks that the balancing and
/// ordering invariants of the tree are satisifed. It is a recursive
/// method that returns the height of the tree, which is then consumed
/// by the enclosing verify call. External callers should ignore the
/// by the enclosing validateTree call. External callers should ignore the
/// return value. An invalid tree will cause an assertion to fire in
/// a debug build.
unsigned verify() const {
unsigned HL = getLeft() ? getLeft()->verify() : 0;
unsigned HR = getRight() ? getRight()->verify() : 0;
unsigned validateTree() const {
unsigned HL = getLeft() ? getLeft()->validateTree() : 0;
unsigned HR = getRight() ? getRight()->validateTree() : 0;
(void) HL;
(void) HR;
@ -198,37 +199,39 @@ public:
assert((HL > HR ? HL-HR : HR-HL) <= 2
&& "Balancing invariant violated");
assert(!getLeft()
|| ImutInfo::isLess(ImutInfo::KeyOfValue(getLeft()->getValue()),
ImutInfo::KeyOfValue(getValue()))
&& "Value in left child is not less that current value");
assert((!getLeft() ||
ImutInfo::isLess(ImutInfo::KeyOfValue(getLeft()->getValue()),
ImutInfo::KeyOfValue(getValue()))) &&
"Value in left child is not less that current value");
assert(!getRight()
|| ImutInfo::isLess(ImutInfo::KeyOfValue(getValue()),
ImutInfo::KeyOfValue(getRight()->getValue()))
&& "Current value is not less that value of right child");
assert(!(getRight() ||
ImutInfo::isLess(ImutInfo::KeyOfValue(getValue()),
ImutInfo::KeyOfValue(getRight()->getValue()))) &&
"Current value is not less that value of right child");
return getHeight();
}
/// Profile - Profiling for ImutAVLTree.
void Profile(llvm::FoldingSetNodeID& ID) {
ID.AddInteger(ComputeDigest());
}
//===----------------------------------------------------===//
// Internal Values.
// Internal values.
//===----------------------------------------------------===//
private:
ImutAVLTree* Left;
ImutAVLTree* Right;
unsigned Height : 28;
unsigned Mutable : 1;
unsigned CachedDigest : 1;
value_type Value;
uint32_t Digest;
Factory *factory;
ImutAVLTree *left;
ImutAVLTree *right;
ImutAVLTree *prev;
ImutAVLTree *next;
unsigned height : 28;
unsigned IsMutable : 1;
unsigned IsDigestCached : 1;
unsigned IsCanonicalized : 1;
value_type value;
uint32_t digest;
uint32_t refCount;
//===----------------------------------------------------===//
// Internal methods (node manipulation; used by Factory).
@ -237,10 +240,15 @@ private:
private:
/// ImutAVLTree - Internal constructor that is only called by
/// ImutAVLFactory.
ImutAVLTree(ImutAVLTree* l, ImutAVLTree* r, value_type_ref v,
ImutAVLTree(Factory *f, ImutAVLTree* l, ImutAVLTree* r, value_type_ref v,
unsigned height)
: Left(l), Right(r), Height(height), Mutable(true), CachedDigest(false),
Value(v), Digest(0) {}
: factory(f), left(l), right(r), prev(0), next(0), height(height),
IsMutable(true), IsDigestCached(false), IsCanonicalized(0),
value(v), digest(0), refCount(0)
{
if (left) left->retain();
if (right) right->retain();
}
/// isMutable - Returns true if the left and right subtree references
/// (as well as height) can be changed. If this method returns false,
@ -248,11 +256,11 @@ private:
/// object should always have this method return true. Further, if this
/// method returns false for an instance of ImutAVLTree, all subtrees
/// will also have this method return false. The converse is not true.
bool isMutable() const { return Mutable; }
bool isMutable() const { return IsMutable; }
/// hasCachedDigest - Returns true if the digest for this tree is cached.
/// This can only be true if the tree is immutable.
bool hasCachedDigest() const { return CachedDigest; }
bool hasCachedDigest() const { return IsDigestCached; }
//===----------------------------------------------------===//
// Mutating operations. A tree root can be manipulated as
@ -265,51 +273,32 @@ private:
// immutable.
//===----------------------------------------------------===//
/// MarkImmutable - Clears the mutable flag for a tree. After this happens,
/// markImmutable - Clears the mutable flag for a tree. After this happens,
/// it is an error to call setLeft(), setRight(), and setHeight().
void MarkImmutable() {
void markImmutable() {
assert(isMutable() && "Mutable flag already removed.");
Mutable = false;
IsMutable = false;
}
/// MarkedCachedDigest - Clears the NoCachedDigest flag for a tree.
void MarkedCachedDigest() {
/// markedCachedDigest - Clears the NoCachedDigest flag for a tree.
void markedCachedDigest() {
assert(!hasCachedDigest() && "NoCachedDigest flag already removed.");
CachedDigest = true;
}
/// setLeft - Changes the reference of the left subtree. Used internally
/// by ImutAVLFactory.
void setLeft(ImutAVLTree* NewLeft) {
assert(isMutable() &&
"Only a mutable tree can have its left subtree changed.");
Left = NewLeft;
CachedDigest = false;
}
/// setRight - Changes the reference of the right subtree. Used internally
/// by ImutAVLFactory.
void setRight(ImutAVLTree* NewRight) {
assert(isMutable() &&
"Only a mutable tree can have its right subtree changed.");
Right = NewRight;
CachedDigest = false;
IsDigestCached = true;
}
/// setHeight - Changes the height of the tree. Used internally by
/// ImutAVLFactory.
void setHeight(unsigned h) {
assert(isMutable() && "Only a mutable tree can have its height changed.");
Height = h;
height = h;
}
static inline
uint32_t ComputeDigest(ImutAVLTree* L, ImutAVLTree* R, value_type_ref V) {
uint32_t computeDigest(ImutAVLTree* L, ImutAVLTree* R, value_type_ref V) {
uint32_t digest = 0;
if (L)
digest += L->ComputeDigest();
digest += L->computeDigest();
// Compute digest of stored data.
FoldingSetNodeID ID;
@ -317,22 +306,54 @@ private:
digest += ID.ComputeHash();
if (R)
digest += R->ComputeDigest();
digest += R->computeDigest();
return digest;
}
inline uint32_t ComputeDigest() {
inline uint32_t computeDigest() {
// Check the lowest bit to determine if digest has actually been
// pre-computed.
if (hasCachedDigest())
return Digest;
return digest;
uint32_t X = ComputeDigest(getLeft(), getRight(), getValue());
Digest = X;
MarkedCachedDigest();
uint32_t X = computeDigest(getLeft(), getRight(), getValue());
digest = X;
markedCachedDigest();
return X;
}
//===----------------------------------------------------===//
// Reference count operations.
//===----------------------------------------------------===//
public:
void retain() { ++refCount; }
void release() {
assert(refCount > 0);
if (--refCount == 0)
destroy();
}
void destroy() {
if (left)
left->release();
if (right)
right->release();
if (IsCanonicalized) {
if (next)
next->prev = prev;
if (prev)
prev->next = next;
else
factory->Cache[computeDigest()] = next;
}
// We need to clear the mutability bit in case we are
// destroying the node as part of a sweep in ImutAVLFactory::recoverNodes().
IsMutable = false;
factory->freeNodes.push_back(this);
}
};
//===----------------------------------------------------------------------===//
@ -341,14 +362,17 @@ private:
template <typename ImutInfo >
class ImutAVLFactory {
friend class ImutAVLTree<ImutInfo>;
typedef ImutAVLTree<ImutInfo> TreeTy;
typedef typename TreeTy::value_type_ref value_type_ref;
typedef typename TreeTy::key_type_ref key_type_ref;
typedef FoldingSet<TreeTy> CacheTy;
typedef DenseMap<unsigned, TreeTy*> CacheTy;
CacheTy Cache;
uintptr_t Allocator;
std::vector<TreeTy*> createdNodes;
std::vector<TreeTy*> freeNodes;
bool ownsAllocator() const {
return Allocator & 0x1 ? false : true;
@ -373,55 +397,56 @@ public:
if (ownsAllocator()) delete &getAllocator();
}
TreeTy* Add(TreeTy* T, value_type_ref V) {
T = Add_internal(V,T);
MarkImmutable(T);
TreeTy* add(TreeTy* T, value_type_ref V) {
T = add_internal(V,T);
markImmutable(T);
recoverNodes();
return T;
}
TreeTy* Remove(TreeTy* T, key_type_ref V) {
T = Remove_internal(V,T);
MarkImmutable(T);
TreeTy* remove(TreeTy* T, key_type_ref V) {
T = remove_internal(V,T);
markImmutable(T);
recoverNodes();
return T;
}
TreeTy* GetEmptyTree() const { return NULL; }
TreeTy* getEmptyTree() const { return NULL; }
protected:
//===--------------------------------------------------===//
// A bunch of quick helper functions used for reasoning
// about the properties of trees and their children.
// These have succinct names so that the balancing code
// is as terse (and readable) as possible.
//===--------------------------------------------------===//
protected:
bool isEmpty(TreeTy* T) const { return !T; }
unsigned Height(TreeTy* T) const { return T ? T->getHeight() : 0; }
TreeTy* Left(TreeTy* T) const { return T->getLeft(); }
TreeTy* Right(TreeTy* T) const { return T->getRight(); }
value_type_ref Value(TreeTy* T) const { return T->Value; }
bool isEmpty(TreeTy* T) const { return !T; }
unsigned getHeight(TreeTy* T) const { return T ? T->getHeight() : 0; }
TreeTy* getLeft(TreeTy* T) const { return T->getLeft(); }
TreeTy* getRight(TreeTy* T) const { return T->getRight(); }
value_type_ref getValue(TreeTy* T) const { return T->value; }
unsigned IncrementHeight(TreeTy* L, TreeTy* R) const {
unsigned hl = Height(L);
unsigned hr = Height(R);
unsigned incrementHeight(TreeTy* L, TreeTy* R) const {
unsigned hl = getHeight(L);
unsigned hr = getHeight(R);
return (hl > hr ? hl : hr) + 1;
}
static bool CompareTreeWithSection(TreeTy* T,
static bool compareTreeWithSection(TreeTy* T,
typename TreeTy::iterator& TI,
typename TreeTy::iterator& TE) {
typename TreeTy::iterator I = T->begin(), E = T->end();
for ( ; I!=E ; ++I, ++TI)
if (TI == TE || !I->ElementEqual(*TI))
for ( ; I!=E ; ++I, ++TI) {
if (TI == TE || !I->isElementEqual(*TI))
return false;
}
return true;
}
//===--------------------------------------------------===//
// "CreateNode" is used to generate new tree roots that link
// "createNode" is used to generate new tree roots that link
// to other trees. The functon may also simply move links
// in an existing root if that root is still marked mutable.
// This is necessary because otherwise our balancing code
@ -430,181 +455,188 @@ protected:
// returned to the caller.
//===--------------------------------------------------===//
TreeTy* CreateNode(TreeTy* L, value_type_ref V, TreeTy* R) {
TreeTy* createNode(TreeTy* L, value_type_ref V, TreeTy* R) {
BumpPtrAllocator& A = getAllocator();
TreeTy* T = (TreeTy*) A.Allocate<TreeTy>();
new (T) TreeTy(L, R, V, IncrementHeight(L,R));
TreeTy* T;
if (!freeNodes.empty()) {
T = freeNodes.back();
freeNodes.pop_back();
assert(T != L);
assert(T != R);
}
else {
T = (TreeTy*) A.Allocate<TreeTy>();
}
new (T) TreeTy(this, L, R, V, incrementHeight(L,R));
createdNodes.push_back(T);
return T;
}
TreeTy* CreateNode(TreeTy* L, TreeTy* OldTree, TreeTy* R) {
assert(!isEmpty(OldTree));
if (OldTree->isMutable()) {
OldTree->setLeft(L);
OldTree->setRight(R);
OldTree->setHeight(IncrementHeight(L, R));
return OldTree;
}
else
return CreateNode(L, Value(OldTree), R);
TreeTy* createNode(TreeTy* newLeft, TreeTy* oldTree, TreeTy* newRight) {
return createNode(newLeft, getValue(oldTree), newRight);
}
/// Balance - Used by Add_internal and Remove_internal to
/// balance a newly created tree.
TreeTy* Balance(TreeTy* L, value_type_ref V, TreeTy* R) {
void recoverNodes() {
for (unsigned i = 0, n = createdNodes.size(); i < n; ++i) {
TreeTy *N = createdNodes[i];
if (N->isMutable() && N->refCount == 0)
N->destroy();
}
createdNodes.clear();
}
unsigned hl = Height(L);
unsigned hr = Height(R);
/// balanceTree - Used by add_internal and remove_internal to
/// balance a newly created tree.
TreeTy* balanceTree(TreeTy* L, value_type_ref V, TreeTy* R) {
unsigned hl = getHeight(L);
unsigned hr = getHeight(R);
if (hl > hr + 2) {
assert(!isEmpty(L) && "Left tree cannot be empty to have a height >= 2");
TreeTy* LL = Left(L);
TreeTy* LR = Right(L);
TreeTy *LL = getLeft(L);
TreeTy *LR = getRight(L);
if (Height(LL) >= Height(LR))
return CreateNode(LL, L, CreateNode(LR,V,R));
if (getHeight(LL) >= getHeight(LR))
return createNode(LL, L, createNode(LR,V,R));
assert(!isEmpty(LR) && "LR cannot be empty because it has a height >= 1");
TreeTy* LRL = Left(LR);
TreeTy* LRR = Right(LR);
TreeTy *LRL = getLeft(LR);
TreeTy *LRR = getRight(LR);
return CreateNode(CreateNode(LL,L,LRL), LR, CreateNode(LRR,V,R));
return createNode(createNode(LL,L,LRL), LR, createNode(LRR,V,R));
}
else if (hr > hl + 2) {
assert(!isEmpty(R) && "Right tree cannot be empty to have a height >= 2");
TreeTy* RL = Left(R);
TreeTy* RR = Right(R);
TreeTy *RL = getLeft(R);
TreeTy *RR = getRight(R);
if (Height(RR) >= Height(RL))
return CreateNode(CreateNode(L,V,RL), R, RR);
if (getHeight(RR) >= getHeight(RL))
return createNode(createNode(L,V,RL), R, RR);
assert(!isEmpty(RL) && "RL cannot be empty because it has a height >= 1");
TreeTy* RLL = Left(RL);
TreeTy* RLR = Right(RL);
TreeTy *RLL = getLeft(RL);
TreeTy *RLR = getRight(RL);
return CreateNode(CreateNode(L,V,RLL), RL, CreateNode(RLR,R,RR));
return createNode(createNode(L,V,RLL), RL, createNode(RLR,R,RR));
}
else
return CreateNode(L,V,R);
return createNode(L,V,R);
}
/// Add_internal - Creates a new tree that includes the specified
/// add_internal - Creates a new tree that includes the specified
/// data and the data from the original tree. If the original tree
/// already contained the data item, the original tree is returned.
TreeTy* Add_internal(value_type_ref V, TreeTy* T) {
TreeTy* add_internal(value_type_ref V, TreeTy* T) {
if (isEmpty(T))
return CreateNode(T, V, T);
return createNode(T, V, T);
assert(!T->isMutable());
key_type_ref K = ImutInfo::KeyOfValue(V);
key_type_ref KCurrent = ImutInfo::KeyOfValue(Value(T));
key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T));
if (ImutInfo::isEqual(K,KCurrent))
return CreateNode(Left(T), V, Right(T));
return createNode(getLeft(T), V, getRight(T));
else if (ImutInfo::isLess(K,KCurrent))
return Balance(Add_internal(V,Left(T)), Value(T), Right(T));
return balanceTree(add_internal(V, getLeft(T)), getValue(T), getRight(T));
else
return Balance(Left(T), Value(T), Add_internal(V,Right(T)));
return balanceTree(getLeft(T), getValue(T), add_internal(V, getRight(T)));
}
/// Remove_internal - Creates a new tree that includes all the data
/// remove_internal - Creates a new tree that includes all the data
/// from the original tree except the specified data. If the
/// specified data did not exist in the original tree, the original
/// tree is returned.
TreeTy* Remove_internal(key_type_ref K, TreeTy* T) {
TreeTy* remove_internal(key_type_ref K, TreeTy* T) {
if (isEmpty(T))
return T;
assert(!T->isMutable());
key_type_ref KCurrent = ImutInfo::KeyOfValue(Value(T));
key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T));
if (ImutInfo::isEqual(K,KCurrent))
return CombineLeftRightTrees(Left(T),Right(T));
else if (ImutInfo::isLess(K,KCurrent))
return Balance(Remove_internal(K,Left(T)), Value(T), Right(T));
else
return Balance(Left(T), Value(T), Remove_internal(K,Right(T)));
}
TreeTy* CombineLeftRightTrees(TreeTy* L, TreeTy* R) {
if (isEmpty(L)) return R;
if (isEmpty(R)) return L;
TreeTy* OldNode;
TreeTy* NewRight = RemoveMinBinding(R,OldNode);
return Balance(L,Value(OldNode),NewRight);
}
TreeTy* RemoveMinBinding(TreeTy* T, TreeTy*& NodeRemoved) {
assert(!isEmpty(T));
if (isEmpty(Left(T))) {
NodeRemoved = T;
return Right(T);
if (ImutInfo::isEqual(K,KCurrent)) {
return combineTrees(getLeft(T), getRight(T));
} else if (ImutInfo::isLess(K,KCurrent)) {
return balanceTree(remove_internal(K, getLeft(T)),
getValue(T), getRight(T));
} else {
return balanceTree(getLeft(T), getValue(T),
remove_internal(K, getRight(T)));
}
return Balance(RemoveMinBinding(Left(T),NodeRemoved),Value(T),Right(T));
}
/// MarkImmutable - Clears the mutable bits of a root and all of its
TreeTy* combineTrees(TreeTy* L, TreeTy* R) {
if (isEmpty(L))
return R;
if (isEmpty(R))
return L;
TreeTy* OldNode;
TreeTy* newRight = removeMinBinding(R,OldNode);
return balanceTree(L, getValue(OldNode), newRight);
}
TreeTy* removeMinBinding(TreeTy* T, TreeTy*& Noderemoved) {
assert(!isEmpty(T));
if (isEmpty(getLeft(T))) {
Noderemoved = T;
return getRight(T);
}
return balanceTree(removeMinBinding(getLeft(T), Noderemoved),
getValue(T), getRight(T));
}
/// markImmutable - Clears the mutable bits of a root and all of its
/// descendants.
void MarkImmutable(TreeTy* T) {
void markImmutable(TreeTy* T) {
if (!T || !T->isMutable())
return;
T->MarkImmutable();
MarkImmutable(Left(T));
MarkImmutable(Right(T));
T->markImmutable();
markImmutable(getLeft(T));
markImmutable(getRight(T));
}
public:
TreeTy *GetCanonicalTree(TreeTy *TNew) {
TreeTy *getCanonicalTree(TreeTy *TNew) {
if (!TNew)
return NULL;
// Search the FoldingSet bucket for a Tree with the same digest.
FoldingSetNodeID ID;
unsigned digest = TNew->ComputeDigest();
ID.AddInteger(digest);
unsigned hash = ID.ComputeHash();
typename CacheTy::bucket_iterator I = Cache.bucket_begin(hash);
typename CacheTy::bucket_iterator E = Cache.bucket_end(hash);
for (; I != E; ++I) {
TreeTy *T = &*I;
if (T->ComputeDigest() != digest)
continue;
// We found a collision. Perform a comparison of Contents('T')
// with Contents('TNew')
typename TreeTy::iterator TI = T->begin(), TE = T->end();
if (!CompareTreeWithSection(TNew, TI, TE))
continue;
if (TI != TE)
continue; // T has more contents than TNew.
// Trees did match! Return 'T'.
return T;
}
return 0;
// 'TNew' is the only tree of its kind. Return it.
Cache.InsertNode(TNew, (void*) &*Cache.bucket_end(hash));
if (TNew->IsCanonicalized)
return TNew;
// Search the hashtable for another tree with the same digest, and
// if find a collision compare those trees by their contents.
unsigned digest = TNew->computeDigest();
TreeTy *&entry = Cache[digest];
do {
if (!entry)
break;
for (TreeTy *T = entry ; T != 0; T = T->next) {
// Compare the Contents('T') with Contents('TNew')
typename TreeTy::iterator TI = T->begin(), TE = T->end();
if (!compareTreeWithSection(TNew, TI, TE))
continue;
if (TI != TE)
continue; // T has more contents than TNew.
// Trees did match! Return 'T'.
if (TNew->refCount == 0)
TNew->destroy();
return T;
}
entry->prev = TNew;
TNew->next = entry;
}
while (false);
entry = TNew;
TNew->IsCanonicalized = true;
return TNew;
}
};
//===----------------------------------------------------------------------===//
// Immutable AVL-Tree Iterators.
//===----------------------------------------------------------------------===//
@ -635,19 +667,17 @@ public:
}
bool AtEnd() const { return stack.empty(); }
bool atEnd() const { return stack.empty(); }
bool AtBeginning() const {
bool atBeginning() const {
return stack.size() == 1 && getVisitState() == VisitedNone;
}
void SkipToParent() {
void skipToParent() {
assert(!stack.empty());
stack.pop_back();
if (stack.empty())
return;
switch (getVisitState()) {
case VisitedNone:
stack.back() |= VisitedLeft;
@ -663,11 +693,9 @@ public:
inline bool operator==(const _Self& x) const {
if (stack.size() != x.stack.size())
return false;
for (unsigned i = 0 ; i < stack.size(); i++)
if (stack[i] != x.stack[i])
return false;
return true;
}
@ -675,70 +703,52 @@ public:
_Self& operator++() {
assert(!stack.empty());
TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags);
assert(Current);
switch (getVisitState()) {
case VisitedNone:
if (TreeTy* L = Current->getLeft())
stack.push_back(reinterpret_cast<uintptr_t>(L));
else
stack.back() |= VisitedLeft;
break;
case VisitedLeft:
if (TreeTy* R = Current->getRight())
stack.push_back(reinterpret_cast<uintptr_t>(R));
else
stack.back() |= VisitedRight;
break;
case VisitedRight:
SkipToParent();
skipToParent();
break;
default:
assert(false && "Unreachable.");
}
return *this;
}
_Self& operator--() {
assert(!stack.empty());
TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags);
assert(Current);
switch (getVisitState()) {
case VisitedNone:
stack.pop_back();
break;
case VisitedLeft:
stack.back() &= ~Flags; // Set state to "VisitedNone."
if (TreeTy* L = Current->getLeft())
stack.push_back(reinterpret_cast<uintptr_t>(L) | VisitedRight);
break;
case VisitedRight:
stack.back() &= ~Flags;
stack.back() |= VisitedLeft;
if (TreeTy* R = Current->getRight())
stack.push_back(reinterpret_cast<uintptr_t>(R) | VisitedRight);
break;
default:
assert(false && "Unreachable.");
}
return *this;
}
};
@ -769,7 +779,7 @@ public:
inline _Self& operator++() {
do ++InternalItr;
while (!InternalItr.AtEnd() &&
while (!InternalItr.atEnd() &&
InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft);
return *this;
@ -777,16 +787,16 @@ public:
inline _Self& operator--() {
do --InternalItr;
while (!InternalItr.AtBeginning() &&
while (!InternalItr.atBeginning() &&
InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft);
return *this;
}
inline void SkipSubTree() {
InternalItr.SkipToParent();
inline void skipSubTree() {
InternalItr.skipToParent();
while (!InternalItr.AtEnd() &&
while (!InternalItr.atEnd() &&
InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft)
++InternalItr;
}
@ -927,7 +937,23 @@ public:
/// should use a Factory object to create sets instead of directly
/// invoking the constructor, but there are cases where make this
/// constructor public is useful.
explicit ImmutableSet(TreeTy* R) : Root(R) {}
explicit ImmutableSet(TreeTy* R) : Root(R) {
if (Root) { Root->retain(); }
}
ImmutableSet(const ImmutableSet &X) : Root(X.Root) {
if (Root) { Root->retain(); }
}
ImmutableSet &operator=(const ImmutableSet &X) {
if (Root != X.Root) {
if (X.Root) { X.Root->retain(); }
if (Root) { Root->release(); }
Root = X.Root;
}
return *this;
}
~ImmutableSet() {
if (Root) { Root->release(); }
}
class Factory {
typename TreeTy::Factory F;
@ -940,33 +966,33 @@ public:
Factory(BumpPtrAllocator& Alloc, bool canonicalize = true)
: F(Alloc), Canonicalize(canonicalize) {}
/// GetEmptySet - Returns an immutable set that contains no elements.
ImmutableSet GetEmptySet() {
return ImmutableSet(F.GetEmptyTree());
/// getEmptySet - Returns an immutable set that contains no elements.
ImmutableSet getEmptySet() {
return ImmutableSet(F.getEmptyTree());
}
/// Add - Creates a new immutable set that contains all of the values
/// add - Creates a new immutable set that contains all of the values
/// of the original set with the addition of the specified value. If
/// the original set already included the value, then the original set is
/// returned and no memory is allocated. The time and space complexity
/// of this operation is logarithmic in the size of the original set.
/// The memory allocated to represent the set is released when the
/// factory object that created the set is destroyed.
ImmutableSet Add(ImmutableSet Old, value_type_ref V) {
TreeTy *NewT = F.Add(Old.Root, V);
return ImmutableSet(Canonicalize ? F.GetCanonicalTree(NewT) : NewT);
ImmutableSet add(ImmutableSet Old, value_type_ref V) {
TreeTy *NewT = F.add(Old.Root, V);
return ImmutableSet(Canonicalize ? F.getCanonicalTree(NewT) : NewT);
}
/// Remove - Creates a new immutable set that contains all of the values
/// remove - Creates a new immutable set that contains all of the values
/// of the original set with the exception of the specified value. If
/// the original set did not contain the value, the original set is
/// returned and no memory is allocated. The time and space complexity
/// of this operation is logarithmic in the size of the original set.
/// The memory allocated to represent the set is released when the
/// factory object that created the set is destroyed.
ImmutableSet Remove(ImmutableSet Old, value_type_ref V) {
TreeTy *NewT = F.Remove(Old.Root, V);
return ImmutableSet(Canonicalize ? F.GetCanonicalTree(NewT) : NewT);
ImmutableSet remove(ImmutableSet Old, value_type_ref V) {
TreeTy *NewT = F.remove(Old.Root, V);
return ImmutableSet(Canonicalize ? F.getCanonicalTree(NewT) : NewT);
}
BumpPtrAllocator& getAllocator() { return F.getAllocator(); }
@ -978,20 +1004,21 @@ public:
friend class Factory;
/// contains - Returns true if the set contains the specified value.
/// Returns true if the set contains the specified value.
bool contains(value_type_ref V) const {
return Root ? Root->contains(V) : false;
}
bool operator==(ImmutableSet RHS) const {
bool operator==(const ImmutableSet &RHS) const {
return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root;
}
bool operator!=(ImmutableSet RHS) const {
bool operator!=(const ImmutableSet &RHS) const {
return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root;
}
TreeTy *getRoot() {
if (Root) { Root->retain(); }
return Root;
}
@ -1049,7 +1076,7 @@ public:
// For testing.
//===--------------------------------------------------===//
void verify() const { if (Root) Root->verify(); }
void validateTree() const { if (Root) Root->validateTree(); }
};
} // end namespace llvm

View File

@ -0,0 +1,77 @@
//===- InMemoryStruct.h - Indirect Struct Access Smart Pointer --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ADT_INMEMORYSTRUCT_H
#define LLVM_ADT_INMEMORYSTRUCT_H
#include <cassert>
namespace llvm {
/// \brief Helper object for abstracting access to an in-memory structure which
/// may require some kind of temporary storage.
///
/// This class is designed to be used for accessing file data structures which
/// in the common case can be accessed from a direct pointer to a memory mapped
/// object, but which in some cases may require indirect access to a temporary
/// structure (which, for example, may have undergone endianness translation).
template<typename T>
class InMemoryStruct {
typedef T value_type;
typedef value_type &reference;
typedef value_type *pointer;
typedef const value_type &const_reference;
typedef const value_type *const_pointer;
/// \brief The smart pointer target.
value_type *Target;
/// \brief A temporary object which can be used as a target of the smart
/// pointer.
value_type Contents;
private:
public:
InMemoryStruct() : Target(0) {}
InMemoryStruct(reference Value) : Target(&Contents), Contents(Value) {}
InMemoryStruct(pointer Value) : Target(Value) {}
InMemoryStruct(const InMemoryStruct<T> &Value) { *this = Value; }
void operator=(const InMemoryStruct<T> &Value) {
if (Value.Target != &Value.Contents) {
Target = Value.Target;
} else {
Target = &Contents;
Contents = Value.Contents;
}
}
const_reference operator*() const {
assert(Target && "Cannot dereference null pointer");
return *Target;
}
reference operator*() {
assert(Target && "Cannot dereference null pointer");
return *Target;
}
const_pointer operator->() const {
return Target;
}
pointer operator->() {
return Target;
}
operator bool() const { return Target != 0; }
};
}
#endif

View File

@ -55,6 +55,14 @@ namespace llvm {
return storage_[toIndex_(n)];
}
void reserve(typename StorageT::size_type s) {
storage_.reserve(s);
}
void resize(typename StorageT::size_type s) {
storage_.resize(s, nullVal_);
}
void clear() {
storage_.clear();
}
@ -62,7 +70,11 @@ namespace llvm {
void grow(IndexT n) {
unsigned NewSize = toIndex_(n) + 1;
if (NewSize > storage_.size())
storage_.resize(NewSize, nullVal_);
resize(NewSize);
}
bool inBounds(IndexT n) const {
return toIndex_(n) < storage_.size();
}
typename StorageT::size_type size() const {

View File

@ -0,0 +1,88 @@
//===-- llvm/ADT/IntEqClasses.h - Equiv. Classes of Integers ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Equivalence classes for small integers. This is a mapping of the integers
// 0 .. N-1 into M equivalence classes numbered 0 .. M-1.
//
// Initially each integer has its own equivalence class. Classes are joined by
// passing a representative member of each class to join().
//
// Once the classes are built, compress() will number them 0 .. M-1 and prevent
// further changes.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ADT_INTEQCLASSES_H
#define LLVM_ADT_INTEQCLASSES_H
#include "llvm/ADT/SmallVector.h"
namespace llvm {
class IntEqClasses {
/// EC - When uncompressed, map each integer to a smaller member of its
/// equivalence class. The class leader is the smallest member and maps to
/// itself.
///
/// When compressed, EC[i] is the equivalence class of i.
SmallVector<unsigned, 8> EC;
/// NumClasses - The number of equivalence classes when compressed, or 0 when
/// uncompressed.
unsigned NumClasses;
public:
/// IntEqClasses - Create an equivalence class mapping for 0 .. N-1.
IntEqClasses(unsigned N = 0) : NumClasses(0) { grow(N); }
/// grow - Increase capacity to hold 0 .. N-1, putting new integers in unique
/// equivalence classes.
/// This requires an uncompressed map.
void grow(unsigned N);
/// clear - Clear all classes so that grow() will assign a unique class to
/// every integer.
void clear() {
EC.clear();
NumClasses = 0;
}
/// join - Join the equivalence classes of a and b. After joining classes,
/// findLeader(a) == findLeader(b).
/// This requires an uncompressed map.
void join(unsigned a, unsigned b);
/// findLeader - Compute the leader of a's equivalence class. This is the
/// smallest member of the class.
/// This requires an uncompressed map.
unsigned findLeader(unsigned a) const;
/// compress - Compress equivalence classes by numbering them 0 .. M.
/// This makes the equivalence class map immutable.
void compress();
/// getNumClasses - Return the number of equivalence classes after compress()
/// was called.
unsigned getNumClasses() const { return NumClasses; }
/// operator[] - Return a's equivalence class number, 0 .. getNumClasses()-1.
/// This requires a compressed map.
unsigned operator[](unsigned a) const {
assert(NumClasses && "operator[] called before compress()");
return EC[a];
}
/// uncompress - Change back to the uncompressed representation that allows
/// editing.
void uncompress();
};
} // End llvm namespace
#endif

File diff suppressed because it is too large Load Diff

View File

@ -61,6 +61,60 @@ template <typename T>
struct simplify_type<Optional<T> >
: public simplify_type<const Optional<T> > {};
/// \brief Poison comparison between two \c Optional objects. Clients needs to
/// explicitly compare the underlying values and account for empty \c Optional
/// objects.
///
/// This routine will never be defined. It returns \c void to help diagnose
/// errors at compile time.
template<typename T, typename U>
void operator==(const Optional<T> &X, const Optional<U> &Y);
/// \brief Poison comparison between two \c Optional objects. Clients needs to
/// explicitly compare the underlying values and account for empty \c Optional
/// objects.
///
/// This routine will never be defined. It returns \c void to help diagnose
/// errors at compile time.
template<typename T, typename U>
void operator!=(const Optional<T> &X, const Optional<U> &Y);
/// \brief Poison comparison between two \c Optional objects. Clients needs to
/// explicitly compare the underlying values and account for empty \c Optional
/// objects.
///
/// This routine will never be defined. It returns \c void to help diagnose
/// errors at compile time.
template<typename T, typename U>
void operator<(const Optional<T> &X, const Optional<U> &Y);
/// \brief Poison comparison between two \c Optional objects. Clients needs to
/// explicitly compare the underlying values and account for empty \c Optional
/// objects.
///
/// This routine will never be defined. It returns \c void to help diagnose
/// errors at compile time.
template<typename T, typename U>
void operator<=(const Optional<T> &X, const Optional<U> &Y);
/// \brief Poison comparison between two \c Optional objects. Clients needs to
/// explicitly compare the underlying values and account for empty \c Optional
/// objects.
///
/// This routine will never be defined. It returns \c void to help diagnose
/// errors at compile time.
template<typename T, typename U>
void operator>=(const Optional<T> &X, const Optional<U> &Y);
/// \brief Poison comparison between two \c Optional objects. Clients needs to
/// explicitly compare the underlying values and account for empty \c Optional
/// objects.
///
/// This routine will never be defined. It returns \c void to help diagnose
/// errors at compile time.
template<typename T, typename U>
void operator>(const Optional<T> &X, const Optional<U> &Y);
} // end llvm namespace
#endif

View File

@ -91,6 +91,13 @@ public:
Value |= IntVal << IntShift; // Set new integer.
}
PointerTy const *getAddrOfPointer() const {
assert(Value == reinterpret_cast<intptr_t>(getPointer()) &&
"Can only return the address if IntBits is cleared and "
"PtrTraits doesn't change the pointer");
return reinterpret_cast<PointerTy const *>(&Value);
}
void *getOpaqueValue() const { return reinterpret_cast<void*>(Value); }
void setFromOpaqueValue(void *Val) { Value = reinterpret_cast<intptr_t>(Val);}

View File

@ -107,6 +107,18 @@ namespace llvm {
if (is<T>()) return get<T>();
return T();
}
/// \brief If the union is set to the first pointer type we can get an
/// address pointing to it.
template <typename T>
PT1 const *getAddrOf() const {
assert(is<PT1>() && "Val is not the first pointer");
assert(get<PT1>() == Val.getPointer() &&
"Can't get the address because PointerLikeTypeTraits changes the ptr");
T const *can_only_get_address_of_first_pointer_type
= reinterpret_cast<PT1 const *>(Val.getAddrOfPointer());
return can_only_get_address_of_first_pointer_type;
}
/// Assignment operators - Allow assigning into this union from either
/// pointer type, setting the discriminator to remember what it came from.

View File

@ -56,8 +56,7 @@ class po_iterator : public std::iterator<std::forward_iterator_tag,
void traverseChild() {
while (VisitStack.back().second != GT::child_end(VisitStack.back().first)) {
NodeType *BB = *VisitStack.back().second++;
if (!this->Visited.count(BB)) { // If the block is not visited...
this->Visited.insert(BB);
if (this->Visited.insert(BB)) { // If the block is not visited...
VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB)));
}
}
@ -72,8 +71,7 @@ class po_iterator : public std::iterator<std::forward_iterator_tag,
inline po_iterator(NodeType *BB, SetType &S) :
po_iterator_storage<SetType, ExtStorage>(S) {
if(!S.count(BB)) {
this->Visited.insert(BB);
if (this->Visited.insert(BB)) {
VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB)));
traverseChild();
}

View File

@ -60,7 +60,7 @@ class scc_iterator
// First element is basic block pointer, second is the 'next child' to visit
std::vector<std::pair<NodeType *, ChildItTy> > VisitStack;
// MinVistNumStack - Stack holding the "min" values for each node in the DFS.
// MinVisitNumStack - Stack holding the "min" values for each node in the DFS.
// This is used to track the minimum uplink values for all children of
// the corresponding node on the VisitStack.
std::vector<unsigned> MinVisitNumStack;

View File

@ -31,25 +31,23 @@
#ifndef LLVM_ADT_SCOPEDHASHTABLE_H
#define LLVM_ADT_SCOPEDHASHTABLE_H
#include <cassert>
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/Allocator.h"
namespace llvm {
template <typename K, typename V, typename KInfo = DenseMapInfo<K> >
template <typename K, typename V, typename KInfo = DenseMapInfo<K>,
typename AllocatorTy = MallocAllocator>
class ScopedHashTable;
template <typename K, typename V, typename KInfo = DenseMapInfo<K> >
template <typename K, typename V>
class ScopedHashTableVal {
ScopedHashTableVal *NextInScope;
ScopedHashTableVal *NextForKey;
K Key;
V Val;
ScopedHashTableVal(const K &key, const V &val) : Key(key), Val(val) {}
public:
ScopedHashTableVal(ScopedHashTableVal *nextInScope,
ScopedHashTableVal *nextForKey, const K &key, const V &val)
: NextInScope(nextInScope), NextForKey(nextForKey), Key(key), Val(val) {
}
const K &getKey() const { return Key; }
const V &getValue() const { return Val; }
@ -57,33 +55,53 @@ public:
ScopedHashTableVal *getNextForKey() { return NextForKey; }
const ScopedHashTableVal *getNextForKey() const { return NextForKey; }
public:
ScopedHashTableVal *getNextInScope() { return NextInScope; }
template <typename AllocatorTy>
static ScopedHashTableVal *Create(ScopedHashTableVal *nextInScope,
ScopedHashTableVal *nextForKey,
const K &key, const V &val,
AllocatorTy &Allocator) {
ScopedHashTableVal *New = Allocator.template Allocate<ScopedHashTableVal>();
// Set up the value.
new (New) ScopedHashTableVal(key, val);
New->NextInScope = nextInScope;
New->NextForKey = nextForKey;
return New;
}
template <typename AllocatorTy>
void Destroy(AllocatorTy &Allocator) {
// Free memory referenced by the item.
this->~ScopedHashTableVal();
Allocator.Deallocate(this);
}
};
template <typename K, typename V, typename KInfo = DenseMapInfo<K> >
template <typename K, typename V, typename KInfo = DenseMapInfo<K>,
typename AllocatorTy = MallocAllocator>
class ScopedHashTableScope {
/// HT - The hashtable that we are active for.
ScopedHashTable<K, V, KInfo> &HT;
ScopedHashTable<K, V, KInfo, AllocatorTy> &HT;
/// PrevScope - This is the scope that we are shadowing in HT.
ScopedHashTableScope *PrevScope;
/// LastValInScope - This is the last value that was inserted for this scope
/// or null if none have been inserted yet.
ScopedHashTableVal<K, V, KInfo> *LastValInScope;
ScopedHashTableVal<K, V> *LastValInScope;
void operator=(ScopedHashTableScope&); // DO NOT IMPLEMENT
ScopedHashTableScope(ScopedHashTableScope&); // DO NOT IMPLEMENT
public:
ScopedHashTableScope(ScopedHashTable<K, V, KInfo> &HT);
ScopedHashTableScope(ScopedHashTable<K, V, KInfo, AllocatorTy> &HT);
~ScopedHashTableScope();
private:
friend class ScopedHashTable<K, V, KInfo>;
ScopedHashTableVal<K, V, KInfo> *getLastValInScope() {
friend class ScopedHashTable<K, V, KInfo, AllocatorTy>;
ScopedHashTableVal<K, V> *getLastValInScope() {
return LastValInScope;
}
void setLastValInScope(ScopedHashTableVal<K, V, KInfo> *Val) {
void setLastValInScope(ScopedHashTableVal<K, V> *Val) {
LastValInScope = Val;
}
};
@ -91,9 +109,9 @@ private:
template <typename K, typename V, typename KInfo = DenseMapInfo<K> >
class ScopedHashTableIterator {
ScopedHashTableVal<K, V, KInfo> *Node;
ScopedHashTableVal<K, V> *Node;
public:
ScopedHashTableIterator(ScopedHashTableVal<K, V, KInfo> *node) : Node(node) {}
ScopedHashTableIterator(ScopedHashTableVal<K, V> *node) : Node(node) {}
V &operator*() const {
assert(Node && "Dereference end()");
@ -121,26 +139,40 @@ public:
};
template <typename K, typename V, typename KInfo>
template <typename K, typename V, typename KInfo, typename AllocatorTy>
class ScopedHashTable {
DenseMap<K, ScopedHashTableVal<K, V, KInfo>*, KInfo> TopLevelMap;
ScopedHashTableScope<K, V, KInfo> *CurScope;
typedef ScopedHashTableVal<K, V> ValTy;
DenseMap<K, ValTy*, KInfo> TopLevelMap;
ScopedHashTableScope<K, V, KInfo, AllocatorTy> *CurScope;
AllocatorTy Allocator;
ScopedHashTable(const ScopedHashTable&); // NOT YET IMPLEMENTED
void operator=(const ScopedHashTable&); // NOT YET IMPLEMENTED
friend class ScopedHashTableScope<K, V, KInfo>;
friend class ScopedHashTableScope<K, V, KInfo, AllocatorTy>;
public:
ScopedHashTable() : CurScope(0) {}
ScopedHashTable(AllocatorTy A) : CurScope(0), Allocator(A) {}
~ScopedHashTable() {
assert(CurScope == 0 && TopLevelMap.empty() && "Scope imbalance!");
}
/// ScopeTy - This is a helpful typedef that allows clients to get easy access
/// to the name of the scope for this hash table.
typedef ScopedHashTableScope<K, V, KInfo, AllocatorTy> ScopeTy;
/// Access to the allocator.
typedef typename ReferenceAdder<AllocatorTy>::result AllocatorRefTy;
typedef typename ReferenceAdder<const AllocatorTy>::result AllocatorCRefTy;
AllocatorRefTy getAllocator() { return Allocator; }
AllocatorCRefTy getAllocator() const { return Allocator; }
bool count(const K &Key) const {
return TopLevelMap.count(Key);
}
V lookup(const K &Key) {
typename DenseMap<K, ScopedHashTableVal<K, V, KInfo>*, KInfo>::iterator
I = TopLevelMap.find(Key);
typename DenseMap<K, ValTy*, KInfo>::iterator I = TopLevelMap.find(Key);
if (I != TopLevelMap.end())
return I->second->getValue();
@ -150,10 +182,10 @@ public:
void insert(const K &Key, const V &Val) {
assert(CurScope && "No scope active!");
ScopedHashTableVal<K, V, KInfo> *&KeyEntry = TopLevelMap[Key];
ScopedHashTableVal<K, V> *&KeyEntry = TopLevelMap[Key];
KeyEntry= new ScopedHashTableVal<K, V, KInfo>(CurScope->getLastValInScope(),
KeyEntry, Key, Val);
KeyEntry = ValTy::Create(CurScope->getLastValInScope(), KeyEntry, Key, Val,
Allocator);
CurScope->setLastValInScope(KeyEntry);
}
@ -162,7 +194,7 @@ public:
iterator end() { return iterator(0); }
iterator begin(const K &Key) {
typename DenseMap<K, ScopedHashTableVal<K, V, KInfo>*, KInfo>::iterator I =
typename DenseMap<K, ValTy*, KInfo>::iterator I =
TopLevelMap.find(Key);
if (I == TopLevelMap.end()) return end();
return iterator(I->second);
@ -171,29 +203,28 @@ public:
/// ScopedHashTableScope ctor - Install this as the current scope for the hash
/// table.
template <typename K, typename V, typename KInfo>
ScopedHashTableScope<K, V, KInfo>::
ScopedHashTableScope(ScopedHashTable<K, V, KInfo> &ht) : HT(ht) {
template <typename K, typename V, typename KInfo, typename Allocator>
ScopedHashTableScope<K, V, KInfo, Allocator>::
ScopedHashTableScope(ScopedHashTable<K, V, KInfo, Allocator> &ht) : HT(ht) {
PrevScope = HT.CurScope;
HT.CurScope = this;
LastValInScope = 0;
}
template <typename K, typename V, typename KInfo>
ScopedHashTableScope<K, V, KInfo>::~ScopedHashTableScope() {
template <typename K, typename V, typename KInfo, typename Allocator>
ScopedHashTableScope<K, V, KInfo, Allocator>::~ScopedHashTableScope() {
assert(HT.CurScope == this && "Scope imbalance!");
HT.CurScope = PrevScope;
// Pop and delete all values corresponding to this scope.
while (ScopedHashTableVal<K, V, KInfo> *ThisEntry = LastValInScope) {
while (ScopedHashTableVal<K, V> *ThisEntry = LastValInScope) {
// Pop this value out of the TopLevelMap.
if (ThisEntry->getNextForKey() == 0) {
assert(HT.TopLevelMap[ThisEntry->getKey()] == ThisEntry &&
"Scope imbalance!");
HT.TopLevelMap.erase(ThisEntry->getKey());
} else {
ScopedHashTableVal<K, V, KInfo> *&KeyEntry =
HT.TopLevelMap[ThisEntry->getKey()];
ScopedHashTableVal<K, V> *&KeyEntry = HT.TopLevelMap[ThisEntry->getKey()];
assert(KeyEntry == ThisEntry && "Scope imbalance!");
KeyEntry = ThisEntry->getNextForKey();
}
@ -202,7 +233,7 @@ ScopedHashTableScope<K, V, KInfo>::~ScopedHashTableScope() {
LastValInScope = ThisEntry->getNextInScope();
// Delete this entry.
delete ThisEntry;
ThisEntry->Destroy(HT.getAllocator());
}
}

View File

@ -114,13 +114,15 @@ public:
}
/// @brief Remove an item from the set vector.
void remove(const value_type& X) {
bool remove(const value_type& X) {
if (set_.erase(X)) {
typename vector_type::iterator I =
std::find(vector_.begin(), vector_.end(), X);
assert(I != vector_.end() && "Corrupted SetVector instances!");
vector_.erase(I);
return true;
}
return false;
}

View File

@ -187,6 +187,13 @@ public:
return getPointer()->any();
}
/// all - Returns true if all bits are set.
bool all() const {
if (isSmall())
return getSmallBits() == (uintptr_t(1) << getSmallSize()) - 1;
return getPointer()->all();
}
/// none - Returns true if none of the bits are set.
bool none() const {
if (isSmall())

View File

@ -16,9 +16,10 @@
#define LLVM_ADT_SMALLPTRSET_H
#include <cassert>
#include <cstddef>
#include <cstring>
#include <iterator>
#include "llvm/System/DataTypes.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
namespace llvm {
@ -56,7 +57,7 @@ protected:
/// it, so that the end iterator actually points to valid memory.
unsigned CurArraySize;
// If small, this is # elts allocated consequtively
// If small, this is # elts allocated consecutively
unsigned NumElements;
unsigned NumTombstones;

View File

@ -27,6 +27,9 @@ public:
// Default ctor - Initialize to empty.
SmallString() {}
// Initialize from a StringRef.
SmallString(StringRef S) : SmallVector<char, InternalLen>(S.begin(), S.end()) {}
// Initialize with a range.
template<typename ItTy>
SmallString(ItTy S, ItTy E) : SmallVector<char, InternalLen>(S, E) {}
@ -38,15 +41,16 @@ public:
// Extra methods.
StringRef str() const { return StringRef(this->begin(), this->size()); }
// Implicit conversion to StringRef.
operator StringRef() const { return str(); }
const char *c_str() {
// TODO: Make this const, if it's safe...
const char* c_str() {
this->push_back(0);
this->pop_back();
return this->data();
}
// Implicit conversion to StringRef.
operator StringRef() const { return str(); }
// Extra operators.
const SmallString &operator=(StringRef RHS) {
this->clear();

View File

@ -20,6 +20,7 @@
#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <iterator>
#include <memory>
#ifdef _MSC_VER
@ -57,19 +58,13 @@ protected:
// Allocate raw space for N elements of type T. If T has a ctor or dtor, we
// don't want it to be automatically run, so we need to represent the space as
// something else. An array of char would work great, but might not be
// aligned sufficiently. Instead, we either use GCC extensions, or some
// number of union instances for the space, which guarantee maximal alignment.
struct U {
#ifdef __GNUC__
char X __attribute__((aligned));
#else
union {
double D;
long double LD;
long long L;
void *P;
} X;
#endif
// aligned sufficiently. Instead we use some number of union instances for
// the space, which guarantee maximal alignment.
union U {
double D;
long double LD;
long long L;
void *P;
} FirstEl;
// Space after 'FirstEl' is clobbered, do not add any instance vars after it.
@ -94,7 +89,7 @@ protected:
}
/// grow_pod - This is an implementation of the grow() method which only works
/// on POD-like datatypes and is out of line to reduce code duplication.
/// on POD-like data types and is out of line to reduce code duplication.
void grow_pod(size_t MinSizeInBytes, size_t TSize);
public:
@ -269,7 +264,7 @@ public:
template <typename T>
class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
typedef SmallVectorTemplateBase<T, isPodLike<T>::value > SuperClass;
SmallVectorImpl(const SmallVectorImpl&); // DISABLED.
public:
typedef typename SuperClass::iterator iterator;
@ -346,7 +341,6 @@ public:
return Result;
}
void swap(SmallVectorImpl &RHS);
/// append - Add the specified range to the end of the SmallVector.

View File

@ -17,7 +17,7 @@
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/ilist_node.h"
#include "llvm/System/DataTypes.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>

View File

@ -26,7 +26,7 @@
#ifndef LLVM_ADT_STATISTIC_H
#define LLVM_ADT_STATISTIC_H
#include "llvm/System/Atomic.h"
#include "llvm/Support/Atomic.h"
namespace llvm {
class raw_ostream;

View File

@ -14,7 +14,7 @@
#ifndef LLVM_ADT_STRINGEXTRAS_H
#define LLVM_ADT_STRINGEXTRAS_H
#include "llvm/System/DataTypes.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/StringRef.h"
#include <cctype>
@ -25,10 +25,11 @@
namespace llvm {
template<typename T> class SmallVectorImpl;
/// hexdigit - Return the (uppercase) hexadecimal character for the
/// hexdigit - Return the hexadecimal character for the
/// given number \arg X (which should be less than 16).
static inline char hexdigit(unsigned X) {
return X < 10 ? '0' + X : 'A' + X - 10;
static inline char hexdigit(unsigned X, bool LowerCase = false) {
const char HexChar = LowerCase ? 'a' : 'A';
return X < 10 ? '0' + X : HexChar + X - 10;
}
/// utohex_buffer - Emit the specified number into the buffer specified by

View File

@ -137,8 +137,8 @@ public:
StringMapEntry(unsigned strLen, const ValueTy &V)
: StringMapEntryBase(strLen), second(V) {}
StringRef getKey() const {
return StringRef(getKeyData(), getKeyLength());
StringRef getKey() const {
return StringRef(getKeyData(), getKeyLength());
}
const ValueTy &getValue() const { return second; }
@ -167,7 +167,7 @@ public:
unsigned AllocSize = static_cast<unsigned>(sizeof(StringMapEntry))+
KeyLength+1;
unsigned Alignment = alignof<StringMapEntry>();
unsigned Alignment = alignOf<StringMapEntry>();
StringMapEntry *NewItem =
static_cast<StringMapEntry*>(Allocator.Allocate(AllocSize,Alignment));
@ -216,14 +216,14 @@ public:
static const StringMapEntry &GetStringMapEntryFromValue(const ValueTy &V) {
return GetStringMapEntryFromValue(const_cast<ValueTy&>(V));
}
/// GetStringMapEntryFromKeyData - Given key data that is known to be embedded
/// into a StringMapEntry, return the StringMapEntry itself.
static StringMapEntry &GetStringMapEntryFromKeyData(const char *KeyData) {
char *Ptr = const_cast<char*>(KeyData) - sizeof(StringMapEntry<ValueTy>);
return *reinterpret_cast<StringMapEntry*>(Ptr);
}
/// Destroy - Destroy this StringMapEntry, releasing memory back to the
/// specified allocator.
@ -254,7 +254,7 @@ public:
StringMap() : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) {}
explicit StringMap(unsigned InitialSize)
: StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))) {}
explicit StringMap(AllocatorTy A)
: StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))), Allocator(A) {}
@ -262,16 +262,19 @@ public:
: StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) {
assert(RHS.empty() &&
"Copy ctor from non-empty stringmap not implemented yet!");
(void)RHS;
}
void operator=(const StringMap &RHS) {
assert(RHS.empty() &&
"assignment from non-empty stringmap not implemented yet!");
(void)RHS;
clear();
}
AllocatorTy &getAllocator() { return Allocator; }
const AllocatorTy &getAllocator() const { return Allocator; }
typedef typename ReferenceAdder<AllocatorTy>::result AllocatorRefTy;
typedef typename ReferenceAdder<const AllocatorTy>::result AllocatorCRefTy;
AllocatorRefTy getAllocator() { return Allocator; }
AllocatorCRefTy getAllocator() const { return Allocator; }
typedef const char* key_type;
typedef ValueTy mapped_type;

View File

@ -132,7 +132,7 @@ namespace llvm {
/// numbers.
int compare_numeric(StringRef RHS) const;
/// \brief Determine the edit distance between this string and another
/// \brief Determine the edit distance between this string and another
/// string.
///
/// \param Other the string to compare this string against.
@ -142,11 +142,16 @@ namespace llvm {
/// operation, rather than as two operations (an insertion and a
/// removal).
///
/// \param MaxEditDistance If non-zero, the maximum edit distance that
/// this routine is allowed to compute. If the edit distance will exceed
/// that maximum, returns \c MaxEditDistance+1.
///
/// \returns the minimum number of character insertions, removals,
/// or (if \p AllowReplacements is \c true) replacements needed to
/// transform one of the given strings into the other. If zero,
/// the strings are identical.
unsigned edit_distance(StringRef Other, bool AllowReplacements = true);
unsigned edit_distance(StringRef Other, bool AllowReplacements = true,
unsigned MaxEditDistance = 0);
/// str - Get the contents as an std::string.
std::string str() const {
@ -251,6 +256,18 @@ namespace llvm {
/// Note: O(size() + Chars.size())
size_type find_first_not_of(StringRef Chars, size_t From = 0) const;
/// find_last_of - Find the last character in the string that is \arg C, or
/// npos if not found.
size_type find_last_of(char C, size_t From = npos) const {
return rfind(C, From);
}
/// find_last_of - Find the last character in the string that is in \arg C,
/// or npos if not found.
///
/// Note: O(size() + Chars.size())
size_type find_last_of(StringRef Chars, size_t From = npos) const;
/// @}
/// @name Helpful Algorithms
/// @{
@ -432,6 +449,10 @@ namespace llvm {
/// @}
// StringRefs can be treated like a POD type.
template <typename T> struct isPodLike;
template <> struct isPodLike<StringRef> { static const bool value = true; };
}
#endif

View File

@ -45,7 +45,7 @@ class Triple {
public:
enum ArchType {
UnknownArch,
alpha, // Alpha: alpha
arm, // ARM; arm, armv.*, xscale
bfin, // Blackfin: bfin
@ -53,7 +53,6 @@ public:
mips, // MIPS: mips, mipsallegrex
mipsel, // MIPSEL: mipsel, mipsallegrexel, psp
msp430, // MSP430: msp430
pic16, // PIC16: pic16
ppc, // PPC: powerpc
ppc64, // PPC64: powerpc64, ppu
sparc, // Sparc: sparc
@ -65,13 +64,14 @@ public:
x86_64, // X86-64: amd64, x86_64
xcore, // XCore: xcore
mblaze, // MBlaze: mblaze
ptx, // PTX: ptx
InvalidArch
};
enum VendorType {
UnknownVendor,
Apple,
Apple,
PC
};
enum OSType {
@ -84,8 +84,7 @@ public:
FreeBSD,
Linux,
Lv2, // PS3
MinGW32,
MinGW64,
MinGW32, // i*86-pc-mingw32, *-w64-mingw32
NetBSD,
OpenBSD,
Psp,
@ -94,7 +93,15 @@ public:
Haiku,
Minix
};
enum EnvironmentType {
UnknownEnvironment,
GNU,
GNUEABI,
EABI,
MachO
};
private:
std::string Data;
@ -107,16 +114,20 @@ private:
/// The parsed OS type.
mutable OSType OS;
/// The parsed Environment type.
mutable EnvironmentType Environment;
bool isInitialized() const { return Arch != InvalidArch; }
static ArchType ParseArch(StringRef ArchName);
static VendorType ParseVendor(StringRef VendorName);
static OSType ParseOS(StringRef OSName);
static EnvironmentType ParseEnvironment(StringRef EnvironmentName);
void Parse() const;
public:
/// @name Constructors
/// @{
Triple() : Data(), Arch(InvalidArch) {}
explicit Triple(StringRef Str) : Data(Str), Arch(InvalidArch) {}
explicit Triple(StringRef ArchStr, StringRef VendorStr, StringRef OSStr)
@ -127,6 +138,17 @@ public:
Data += OSStr;
}
explicit Triple(StringRef ArchStr, StringRef VendorStr, StringRef OSStr,
StringRef EnvironmentStr)
: Data(ArchStr), Arch(InvalidArch) {
Data += '-';
Data += VendorStr;
Data += '-';
Data += OSStr;
Data += '-';
Data += EnvironmentStr;
}
/// @}
/// @name Normalization
/// @{
@ -140,22 +162,22 @@ public:
/// @}
/// @name Typed Component Access
/// @{
/// getArch - Get the parsed architecture type of this triple.
ArchType getArch() const {
if (!isInitialized()) Parse();
ArchType getArch() const {
if (!isInitialized()) Parse();
return Arch;
}
/// getVendor - Get the parsed vendor type of this triple.
VendorType getVendor() const {
if (!isInitialized()) Parse();
VendorType getVendor() const {
if (!isInitialized()) Parse();
return Vendor;
}
/// getOS - Get the parsed operating system type of this triple.
OSType getOS() const {
if (!isInitialized()) Parse();
OSType getOS() const {
if (!isInitialized()) Parse();
return OS;
}
@ -165,6 +187,12 @@ public:
return getEnvironmentName() != "";
}
/// getEnvironment - Get the parsed environment type of this triple.
EnvironmentType getEnvironment() const {
if (!isInitialized()) Parse();
return Environment;
}
/// @}
/// @name Direct Component Access
/// @{
@ -193,13 +221,13 @@ public:
/// if the environment component is present).
StringRef getOSAndEnvironmentName() const;
/// getDarwinNumber - Parse the 'darwin number' out of the specific target
/// triple. For example, if we have darwin8.5 return 8,5,0. If any entry is
/// not defined, return 0's. This requires that the triple have an OSType of
/// darwin before it is called.
void getDarwinNumber(unsigned &Maj, unsigned &Min, unsigned &Revision) const;
/// getDarwinMajorNumber - Return just the major version number, this is
/// specialized because it is a common query.
unsigned getDarwinMajorNumber() const {
@ -207,7 +235,7 @@ public:
getDarwinNumber(Maj, Min, Rev);
return Maj;
}
/// @}
/// @name Mutators
/// @{
@ -224,6 +252,10 @@ public:
/// to a known type.
void setOS(OSType Kind);
/// setEnvironment - Set the environment (fourth) component of the triple
/// to a known type.
void setEnvironment(EnvironmentType Kind);
/// setTriple - Set all components to the new triple \arg Str.
void setTriple(const Twine &Str);
@ -271,9 +303,14 @@ public:
/// vendor.
static const char *getVendorTypeName(VendorType Kind);
/// getOSTypeName - Get the canonical name for the \arg Kind vendor.
/// getOSTypeName - Get the canonical name for the \arg Kind operating
/// system.
static const char *getOSTypeName(OSType Kind);
/// getEnvironmentTypeName - Get the canonical name for the \arg Kind
/// environment.
static const char *getEnvironmentTypeName(EnvironmentType Kind);
/// @}
/// @name Static helpers for converting alternate architecture names.
/// @{

View File

@ -11,7 +11,7 @@
#define LLVM_ADT_TWINE_H
#include "llvm/ADT/StringRef.h"
#include "llvm/System/DataTypes.h"
#include "llvm/Support/DataTypes.h"
#include <cassert>
#include <string>
@ -42,7 +42,7 @@ namespace llvm {
/// Twines support a special 'null' value, which always concatenates to form
/// itself, and renders as an empty string. This can be returned from APIs to
/// effectively nullify any concatenations performed on the result.
///
///
/// \b Implementation \n
///
/// Given the nature of a Twine, it is not possible for the Twine's
@ -99,7 +99,7 @@ namespace llvm {
/// A pointer to a StringRef instance.
StringRefKind,
/// An unsigned int value reinterpreted as a pointer, to render as an
/// An unsigned int value reinterpreted as a pointer, to render as an
/// unsigned decimal integer.
DecUIKind,
@ -260,32 +260,32 @@ namespace llvm {
}
/// Construct a twine to print \arg Val as an unsigned decimal integer.
explicit Twine(unsigned Val)
explicit Twine(unsigned Val)
: LHS((void*)(intptr_t)Val), LHSKind(DecUIKind), RHSKind(EmptyKind) {
}
/// Construct a twine to print \arg Val as a signed decimal integer.
explicit Twine(int Val)
explicit Twine(int Val)
: LHS((void*)(intptr_t)Val), LHSKind(DecIKind), RHSKind(EmptyKind) {
}
/// Construct a twine to print \arg Val as an unsigned decimal integer.
explicit Twine(const unsigned long &Val)
explicit Twine(const unsigned long &Val)
: LHS(&Val), LHSKind(DecULKind), RHSKind(EmptyKind) {
}
/// Construct a twine to print \arg Val as a signed decimal integer.
explicit Twine(const long &Val)
explicit Twine(const long &Val)
: LHS(&Val), LHSKind(DecLKind), RHSKind(EmptyKind) {
}
/// Construct a twine to print \arg Val as an unsigned decimal integer.
explicit Twine(const unsigned long long &Val)
explicit Twine(const unsigned long long &Val)
: LHS(&Val), LHSKind(DecULLKind), RHSKind(EmptyKind) {
}
/// Construct a twine to print \arg Val as a signed decimal integer.
explicit Twine(const long long &Val)
explicit Twine(const long long &Val)
: LHS(&Val), LHSKind(DecLLKind), RHSKind(EmptyKind) {
}
@ -330,12 +330,12 @@ namespace llvm {
bool isTriviallyEmpty() const {
return isNullary();
}
/// isSingleStringRef - Return true if this twine can be dynamically
/// accessed as a single StringRef value with getSingleStringRef().
bool isSingleStringRef() const {
if (getRHSKind() != EmptyKind) return false;
switch (getLHSKind()) {
case EmptyKind:
case CStringKind:
@ -382,6 +382,14 @@ namespace llvm {
/// SmallVector and a StringRef to the SmallVector's data is returned.
StringRef toStringRef(SmallVectorImpl<char> &Out) const;
/// toNullTerminatedStringRef - This returns the twine as a single null
/// terminated StringRef if it can be represented as such. Otherwise the
/// twine is written into the given SmallVector and a StringRef to the
/// SmallVector's data is returned.
///
/// The returned StringRef's size does not include the null terminator.
StringRef toNullTerminatedStringRef(SmallVectorImpl<char> &Out) const;
/// print - Write the concatenated string represented by this twine to the
/// stream \arg OS.
void print(raw_ostream &OS) const;

View File

@ -29,7 +29,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/ValueHandle.h"
#include "llvm/Support/type_traits.h"
#include "llvm/System/Mutex.h"
#include "llvm/Support/Mutex.h"
#include <iterator>

View File

@ -38,6 +38,7 @@
#ifndef LLVM_ADT_ILIST_H
#define LLVM_ADT_ILIST_H
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <iterator>

View File

@ -16,11 +16,21 @@
// which automatically provides functionality for the entire suite of client
// APIs.
//
// This API represents memory as a (Pointer, Size) pair. The Pointer component
// specifies the base memory address of the region, the Size specifies how large
// of an area is being queried, or UnknownSize if the size is not known.
// Pointers that point to two completely different objects in memory never
// alias, regardless of the value of the Size component.
// This API identifies memory regions with the Location class. The pointer
// component specifies the base memory address of the region. The Size specifies
// the maximum size (in address units) of the memory region, or UnknownSize if
// the size is not known. The TBAA tag identifies the "type" of the memory
// reference; see the TypeBasedAliasAnalysis class for details.
//
// Some non-obvious details include:
// - Pointers that point to two completely different objects in memory never
// alias, regardless of the value of the Size component.
// - NoAlias doesn't imply inequal pointers. The most obvious example of this
// is two pointers to constant memory. Even if they are equal, constant
// memory is never stored to, so there will never be any dependencies.
// In this and other situations, the pointers may be both NoAlias and
// MustAlias at the same time. The current API can only return one result,
// though this is rarely a problem in practice.
//
//===----------------------------------------------------------------------===//
@ -28,7 +38,6 @@
#define LLVM_ANALYSIS_ALIAS_ANALYSIS_H
#include "llvm/Support/CallSite.h"
#include "llvm/System/IncludeFile.h"
#include <vector>
namespace llvm {
@ -39,6 +48,8 @@ class VAArgInst;
class TargetData;
class Pass;
class AnalysisUsage;
class MemTransferInst;
class MemIntrinsic;
class AliasAnalysis {
protected:
@ -67,7 +78,7 @@ public:
/// UnknownSize - This is a special value which can be used with the
/// size arguments in alias queries to indicate that the caller does not
/// know the sizes of the potential memory references.
static unsigned const UnknownSize = ~0u;
static uint64_t const UnknownSize = ~UINT64_C(0);
/// getTargetData - Return a pointer to the current TargetData object, or
/// null if no TargetData object is available.
@ -77,12 +88,57 @@ public:
/// getTypeStoreSize - Return the TargetData store size for the given type,
/// if known, or a conservative value otherwise.
///
unsigned getTypeStoreSize(const Type *Ty);
uint64_t getTypeStoreSize(const Type *Ty);
//===--------------------------------------------------------------------===//
/// Alias Queries...
///
/// Location - A description of a memory location.
struct Location {
/// Ptr - The address of the start of the location.
const Value *Ptr;
/// Size - The maximum size of the location, in address-units, or
/// UnknownSize if the size is not known. Note that an unknown size does
/// not mean the pointer aliases the entire virtual address space, because
/// there are restrictions on stepping out of one object and into another.
/// See http://llvm.org/docs/LangRef.html#pointeraliasing
uint64_t Size;
/// TBAATag - The metadata node which describes the TBAA type of
/// the location, or null if there is no known unique tag.
const MDNode *TBAATag;
explicit Location(const Value *P = 0, uint64_t S = UnknownSize,
const MDNode *N = 0)
: Ptr(P), Size(S), TBAATag(N) {}
Location getWithNewPtr(const Value *NewPtr) const {
Location Copy(*this);
Copy.Ptr = NewPtr;
return Copy;
}
Location getWithNewSize(uint64_t NewSize) const {
Location Copy(*this);
Copy.Size = NewSize;
return Copy;
}
Location getWithoutTBAATag() const {
Location Copy(*this);
Copy.TBAATag = 0;
return Copy;
}
};
/// getLocation - Fill in Loc with information about the memory reference by
/// the given instruction.
Location getLocation(const LoadInst *LI);
Location getLocation(const StoreInst *SI);
Location getLocation(const VAArgInst *VI);
static Location getLocationForSource(const MemTransferInst *MTI);
static Location getLocationForDest(const MemIntrinsic *MI);
/// Alias analysis result - Either we know for sure that it does not alias, we
/// know for sure it must alias, or we don't know anything: The two pointers
/// _might_ alias. This enum is designed so you can do things like:
@ -92,33 +148,63 @@ public:
/// See docs/AliasAnalysis.html for more information on the specific meanings
/// of these values.
///
enum AliasResult { NoAlias = 0, MayAlias = 1, MustAlias = 2 };
enum AliasResult {
NoAlias = 0, ///< No dependencies.
MayAlias, ///< Anything goes.
PartialAlias, ///< Pointers differ, but pointees overlap.
MustAlias ///< Pointers are equal.
};
/// alias - The main low level interface to the alias analysis implementation.
/// Returns a Result indicating whether the two pointers are aliased to each
/// other. This is the interface that must be implemented by specific alias
/// analysis implementations.
///
virtual AliasResult alias(const Value *V1, unsigned V1Size,
const Value *V2, unsigned V2Size);
/// Returns an AliasResult indicating whether the two pointers are aliased to
/// each other. This is the interface that must be implemented by specific
/// alias analysis implementations.
virtual AliasResult alias(const Location &LocA, const Location &LocB);
/// alias - A convenience wrapper for the case where the sizes are unknown.
/// alias - A convenience wrapper.
AliasResult alias(const Value *V1, uint64_t V1Size,
const Value *V2, uint64_t V2Size) {
return alias(Location(V1, V1Size), Location(V2, V2Size));
}
/// alias - A convenience wrapper.
AliasResult alias(const Value *V1, const Value *V2) {
return alias(V1, UnknownSize, V2, UnknownSize);
}
/// isNoAlias - A trivial helper function to check to see if the specified
/// pointers are no-alias.
bool isNoAlias(const Value *V1, unsigned V1Size,
const Value *V2, unsigned V2Size) {
return alias(V1, V1Size, V2, V2Size) == NoAlias;
bool isNoAlias(const Location &LocA, const Location &LocB) {
return alias(LocA, LocB) == NoAlias;
}
/// pointsToConstantMemory - If the specified pointer is known to point into
/// constant global memory, return true. This allows disambiguation of store
/// instructions from constant pointers.
///
virtual bool pointsToConstantMemory(const Value *P);
/// isNoAlias - A convenience wrapper.
bool isNoAlias(const Value *V1, uint64_t V1Size,
const Value *V2, uint64_t V2Size) {
return isNoAlias(Location(V1, V1Size), Location(V2, V2Size));
}
/// isMustAlias - A convenience wrapper.
bool isMustAlias(const Location &LocA, const Location &LocB) {
return alias(LocA, LocB) == MustAlias;
}
/// isMustAlias - A convenience wrapper.
bool isMustAlias(const Value *V1, const Value *V2) {
return alias(V1, 1, V2, 1) == MustAlias;
}
/// pointsToConstantMemory - If the specified memory location is
/// known to be constant, return true. If OrLocal is true and the
/// specified memory location is known to be "local" (derived from
/// an alloca), return true. Otherwise return false.
virtual bool pointsToConstantMemory(const Location &Loc,
bool OrLocal = false);
/// pointsToConstantMemory - A convenient wrapper.
bool pointsToConstantMemory(const Value *P, bool OrLocal = false) {
return pointsToConstantMemory(Location(P), OrLocal);
}
//===--------------------------------------------------------------------===//
/// Simple mod/ref information...
@ -129,36 +215,48 @@ public:
///
enum ModRefResult { NoModRef = 0, Ref = 1, Mod = 2, ModRef = 3 };
/// These values define additional bits used to define the
/// ModRefBehavior values.
enum { Nowhere = 0, ArgumentPointees = 4, Anywhere = 8 | ArgumentPointees };
/// ModRefBehavior - Summary of how a function affects memory in the program.
/// Loads from constant globals are not considered memory accesses for this
/// interface. Also, functions may freely modify stack space local to their
/// invocation without having to report it through these interfaces.
enum ModRefBehavior {
// DoesNotAccessMemory - This function does not perform any non-local loads
// or stores to memory.
//
// This property corresponds to the GCC 'const' attribute.
DoesNotAccessMemory,
/// DoesNotAccessMemory - This function does not perform any non-local loads
/// or stores to memory.
///
/// This property corresponds to the GCC 'const' attribute.
/// This property corresponds to the LLVM IR 'readnone' attribute.
/// This property corresponds to the IntrNoMem LLVM intrinsic flag.
DoesNotAccessMemory = Nowhere | NoModRef,
// AccessesArguments - This function accesses function arguments in well
// known (possibly volatile) ways, but does not access any other memory.
AccessesArguments,
/// OnlyReadsArgumentPointees - The only memory references in this function
/// (if it has any) are non-volatile loads from objects pointed to by its
/// pointer-typed arguments, with arbitrary offsets.
///
/// This property corresponds to the IntrReadArgMem LLVM intrinsic flag.
OnlyReadsArgumentPointees = ArgumentPointees | Ref,
// AccessesArgumentsAndGlobals - This function has accesses function
// arguments and global variables well known (possibly volatile) ways, but
// does not access any other memory.
AccessesArgumentsAndGlobals,
/// OnlyAccessesArgumentPointees - The only memory references in this
/// function (if it has any) are non-volatile loads and stores from objects
/// pointed to by its pointer-typed arguments, with arbitrary offsets.
///
/// This property corresponds to the IntrReadWriteArgMem LLVM intrinsic flag.
OnlyAccessesArgumentPointees = ArgumentPointees | ModRef,
// OnlyReadsMemory - This function does not perform any non-local stores or
// volatile loads, but may read from any memory location.
//
// This property corresponds to the GCC 'pure' attribute.
OnlyReadsMemory,
/// OnlyReadsMemory - This function does not perform any non-local stores or
/// volatile loads, but may read from any memory location.
///
/// This property corresponds to the GCC 'pure' attribute.
/// This property corresponds to the LLVM IR 'readonly' attribute.
/// This property corresponds to the IntrReadMem LLVM intrinsic flag.
OnlyReadsMemory = Anywhere | Ref,
// UnknownModRefBehavior - This indicates that the function could not be
// classified into one of the behaviors above.
UnknownModRefBehavior
/// UnknownModRefBehavior - This indicates that the function could not be
/// classified into one of the behaviors above.
UnknownModRefBehavior = Anywhere | ModRef
};
/// getModRefBehavior - Return the behavior when calling the given call site.
@ -168,11 +266,6 @@ public:
/// For use when the call site is not known.
virtual ModRefBehavior getModRefBehavior(const Function *F);
/// getIntrinsicModRefBehavior - Return the modref behavior of the intrinsic
/// with the given id. Most clients won't need this, because the regular
/// getModRefBehavior incorporates this information.
static ModRefBehavior getIntrinsicModRefBehavior(unsigned iid);
/// doesNotAccessMemory - If the specified call is known to never read or
/// write memory, return true. If the call only reads from known-constant
/// memory, it is also legal to return true. Calls that unwind the stack
@ -205,8 +298,7 @@ public:
/// This property corresponds to the GCC 'pure' attribute.
///
bool onlyReadsMemory(ImmutableCallSite CS) {
ModRefBehavior MRB = getModRefBehavior(CS);
return MRB == DoesNotAccessMemory || MRB == OnlyReadsMemory;
return onlyReadsMemory(getModRefBehavior(CS));
}
/// onlyReadsMemory - If the specified function is known to only read from
@ -214,21 +306,114 @@ public:
/// when the call site is not known.
///
bool onlyReadsMemory(const Function *F) {
ModRefBehavior MRB = getModRefBehavior(F);
return MRB == DoesNotAccessMemory || MRB == OnlyReadsMemory;
return onlyReadsMemory(getModRefBehavior(F));
}
/// onlyReadsMemory - Return true if functions with the specified behavior are
/// known to only read from non-volatile memory (or not access memory at all).
///
static bool onlyReadsMemory(ModRefBehavior MRB) {
return !(MRB & Mod);
}
/// onlyAccessesArgPointees - Return true if functions with the specified
/// behavior are known to read and write at most from objects pointed to by
/// their pointer-typed arguments (with arbitrary offsets).
///
static bool onlyAccessesArgPointees(ModRefBehavior MRB) {
return !(MRB & Anywhere & ~ArgumentPointees);
}
/// doesAccessArgPointees - Return true if functions with the specified
/// behavior are known to potentially read or write from objects pointed
/// to be their pointer-typed arguments (with arbitrary offsets).
///
static bool doesAccessArgPointees(ModRefBehavior MRB) {
return (MRB & ModRef) && (MRB & ArgumentPointees);
}
/// getModRefInfo - Return information about whether or not an instruction may
/// read or write memory specified by the pointer operand. An instruction
/// read or write the specified memory location. An instruction
/// that doesn't read or write memory may be trivially LICM'd for example.
ModRefResult getModRefInfo(const Instruction *I,
const Location &Loc) {
switch (I->getOpcode()) {
case Instruction::VAArg: return getModRefInfo((const VAArgInst*)I, Loc);
case Instruction::Load: return getModRefInfo((const LoadInst*)I, Loc);
case Instruction::Store: return getModRefInfo((const StoreInst*)I, Loc);
case Instruction::Call: return getModRefInfo((const CallInst*)I, Loc);
case Instruction::Invoke: return getModRefInfo((const InvokeInst*)I,Loc);
default: return NoModRef;
}
}
/// getModRefInfo - A convenience wrapper.
ModRefResult getModRefInfo(const Instruction *I,
const Value *P, uint64_t Size) {
return getModRefInfo(I, Location(P, Size));
}
/// getModRefInfo (for call sites) - Return whether information about whether
/// a particular call site modifies or reads the memory specified by the
/// pointer.
///
/// a particular call site modifies or reads the specified memory location.
virtual ModRefResult getModRefInfo(ImmutableCallSite CS,
const Value *P, unsigned Size);
const Location &Loc);
/// getModRefInfo (for call sites) - A convenience wrapper.
ModRefResult getModRefInfo(ImmutableCallSite CS,
const Value *P, uint64_t Size) {
return getModRefInfo(CS, Location(P, Size));
}
/// getModRefInfo (for calls) - Return whether information about whether
/// a particular call modifies or reads the specified memory location.
ModRefResult getModRefInfo(const CallInst *C, const Location &Loc) {
return getModRefInfo(ImmutableCallSite(C), Loc);
}
/// getModRefInfo (for calls) - A convenience wrapper.
ModRefResult getModRefInfo(const CallInst *C, const Value *P, uint64_t Size) {
return getModRefInfo(C, Location(P, Size));
}
/// getModRefInfo (for invokes) - Return whether information about whether
/// a particular invoke modifies or reads the specified memory location.
ModRefResult getModRefInfo(const InvokeInst *I,
const Location &Loc) {
return getModRefInfo(ImmutableCallSite(I), Loc);
}
/// getModRefInfo (for invokes) - A convenience wrapper.
ModRefResult getModRefInfo(const InvokeInst *I,
const Value *P, uint64_t Size) {
return getModRefInfo(I, Location(P, Size));
}
/// getModRefInfo (for loads) - Return whether information about whether
/// a particular load modifies or reads the specified memory location.
ModRefResult getModRefInfo(const LoadInst *L, const Location &Loc);
/// getModRefInfo (for loads) - A convenience wrapper.
ModRefResult getModRefInfo(const LoadInst *L, const Value *P, uint64_t Size) {
return getModRefInfo(L, Location(P, Size));
}
/// getModRefInfo (for stores) - Return whether information about whether
/// a particular store modifies or reads the specified memory location.
ModRefResult getModRefInfo(const StoreInst *S, const Location &Loc);
/// getModRefInfo (for stores) - A convenience wrapper.
ModRefResult getModRefInfo(const StoreInst *S, const Value *P, uint64_t Size){
return getModRefInfo(S, Location(P, Size));
}
/// getModRefInfo (for va_args) - Return whether information about whether
/// a particular va_arg modifies or reads the specified memory location.
ModRefResult getModRefInfo(const VAArgInst* I, const Location &Loc);
/// getModRefInfo (for va_args) - A convenience wrapper.
ModRefResult getModRefInfo(const VAArgInst* I, const Value* P, uint64_t Size){
return getModRefInfo(I, Location(P, Size));
}
/// getModRefInfo - Return information about whether two call sites may refer
/// to the same set of memory locations. See
@ -237,46 +422,31 @@ public:
virtual ModRefResult getModRefInfo(ImmutableCallSite CS1,
ImmutableCallSite CS2);
public:
/// Convenience functions...
ModRefResult getModRefInfo(const LoadInst *L, const Value *P, unsigned Size);
ModRefResult getModRefInfo(const StoreInst *S, const Value *P, unsigned Size);
ModRefResult getModRefInfo(const VAArgInst* I, const Value* P, unsigned Size);
ModRefResult getModRefInfo(const CallInst *C, const Value *P, unsigned Size) {
return getModRefInfo(ImmutableCallSite(C), P, Size);
}
ModRefResult getModRefInfo(const InvokeInst *I,
const Value *P, unsigned Size) {
return getModRefInfo(ImmutableCallSite(I), P, Size);
}
ModRefResult getModRefInfo(const Instruction *I,
const Value *P, unsigned Size) {
switch (I->getOpcode()) {
case Instruction::VAArg: return getModRefInfo((const VAArgInst*)I, P,Size);
case Instruction::Load: return getModRefInfo((const LoadInst*)I, P, Size);
case Instruction::Store: return getModRefInfo((const StoreInst*)I, P,Size);
case Instruction::Call: return getModRefInfo((const CallInst*)I, P, Size);
case Instruction::Invoke: return getModRefInfo((const InvokeInst*)I,P,Size);
default: return NoModRef;
}
}
//===--------------------------------------------------------------------===//
/// Higher level methods for querying mod/ref information.
///
/// canBasicBlockModify - Return true if it is possible for execution of the
/// specified basic block to modify the value pointed to by Ptr.
///
bool canBasicBlockModify(const BasicBlock &BB, const Value *P, unsigned Size);
bool canBasicBlockModify(const BasicBlock &BB, const Location &Loc);
/// canBasicBlockModify - A convenience wrapper.
bool canBasicBlockModify(const BasicBlock &BB, const Value *P, uint64_t Size){
return canBasicBlockModify(BB, Location(P, Size));
}
/// canInstructionRangeModify - Return true if it is possible for the
/// execution of the specified instructions to modify the value pointed to by
/// Ptr. The instructions to consider are all of the instructions in the
/// range of [I1,I2] INCLUSIVE. I1 and I2 must be in the same basic block.
///
bool canInstructionRangeModify(const Instruction &I1, const Instruction &I2,
const Value *Ptr, unsigned Size);
const Location &Loc);
/// canInstructionRangeModify - A convenience wrapper.
bool canInstructionRangeModify(const Instruction &I1, const Instruction &I2,
const Value *Ptr, uint64_t Size) {
return canInstructionRangeModify(I1, I2, Location(Ptr, Size));
}
//===--------------------------------------------------------------------===//
/// Methods that clients should call when they transform the program to allow
@ -299,6 +469,17 @@ public:
///
virtual void copyValue(Value *From, Value *To);
/// addEscapingUse - This method should be used whenever an escaping use is
/// added to a pointer value. Analysis implementations may either return
/// conservative responses for that value in the future, or may recompute
/// some or all internal state to continue providing precise responses.
///
/// Escaping uses are considered by anything _except_ the following:
/// - GEPs or bitcasts of the pointer
/// - Loads through the pointer
/// - Stores through (but not of) the pointer
virtual void addEscapingUse(Use &U);
/// replaceWithNewValue - This method is the obvious combination of the two
/// above, and it provided as a helper to simplify client code.
///
@ -323,11 +504,4 @@ bool isIdentifiedObject(const Value *V);
} // End llvm namespace
// Because of the way .a files work, we must force the BasicAA implementation to
// be pulled in if the AliasAnalysis header is included. Otherwise we run
// the risk of AliasAnalysis being used, but the default implementation not
// being linked into the tool that uses it.
FORCE_DEFINING_FILE_TO_BE_LINKED(AliasAnalysis)
FORCE_DEFINING_FILE_TO_BE_LINKED(BasicAliasAnalysis)
#endif

View File

@ -40,10 +40,12 @@ class AliasSet : public ilist_node<AliasSet> {
Value *Val; // The pointer this record corresponds to.
PointerRec **PrevInList, *NextInList;
AliasSet *AS;
unsigned Size;
uint64_t Size;
const MDNode *TBAAInfo;
public:
PointerRec(Value *V)
: Val(V), PrevInList(0), NextInList(0), AS(0), Size(0) {}
: Val(V), PrevInList(0), NextInList(0), AS(0), Size(0),
TBAAInfo(DenseMapInfo<const MDNode *>::getEmptyKey()) {}
Value *getValue() const { return Val; }
@ -55,11 +57,28 @@ class AliasSet : public ilist_node<AliasSet> {
return &NextInList;
}
void updateSize(unsigned NewSize) {
void updateSizeAndTBAAInfo(uint64_t NewSize, const MDNode *NewTBAAInfo) {
if (NewSize > Size) Size = NewSize;
if (TBAAInfo == DenseMapInfo<const MDNode *>::getEmptyKey())
// We don't have a TBAAInfo yet. Set it to NewTBAAInfo.
TBAAInfo = NewTBAAInfo;
else if (TBAAInfo != NewTBAAInfo)
// NewTBAAInfo conflicts with TBAAInfo.
TBAAInfo = DenseMapInfo<const MDNode *>::getTombstoneKey();
}
unsigned getSize() const { return Size; }
uint64_t getSize() const { return Size; }
/// getTBAAInfo - Return the TBAAInfo, or null if there is no
/// information or conflicting information.
const MDNode *getTBAAInfo() const {
// If we have missing or conflicting TBAAInfo, return null.
if (TBAAInfo == DenseMapInfo<const MDNode *>::getEmptyKey() ||
TBAAInfo == DenseMapInfo<const MDNode *>::getTombstoneKey())
return 0;
return TBAAInfo;
}
AliasSet *getAliasSet(AliasSetTracker &AST) {
assert(AS && "No AliasSet yet!");
@ -186,7 +205,8 @@ public:
value_type *operator->() const { return &operator*(); }
Value *getPointer() const { return CurNode->getValue(); }
unsigned getSize() const { return CurNode->getSize(); }
uint64_t getSize() const { return CurNode->getSize(); }
const MDNode *getTBAAInfo() const { return CurNode->getTBAAInfo(); }
iterator& operator++() { // Preincrement
assert(CurNode && "Advancing past AliasSet.end()!");
@ -230,7 +250,8 @@ private:
void removeFromTracker(AliasSetTracker &AST);
void addPointer(AliasSetTracker &AST, PointerRec &Entry, unsigned Size,
void addPointer(AliasSetTracker &AST, PointerRec &Entry, uint64_t Size,
const MDNode *TBAAInfo,
bool KnownMustAlias = false);
void addCallSite(CallSite CS, AliasAnalysis &AA);
void removeCallSite(CallSite CS) {
@ -245,7 +266,8 @@ private:
/// aliasesPointer - Return true if the specified pointer "may" (or must)
/// alias one of the members in the set.
///
bool aliasesPointer(const Value *Ptr, unsigned Size, AliasAnalysis &AA) const;
bool aliasesPointer(const Value *Ptr, uint64_t Size, const MDNode *TBAAInfo,
AliasAnalysis &AA) const;
bool aliasesCallSite(CallSite CS, AliasAnalysis &AA) const;
};
@ -298,7 +320,7 @@ public:
/// These methods return true if inserting the instruction resulted in the
/// addition of a new alias set (i.e., the pointer did not alias anything).
///
bool add(Value *Ptr, unsigned Size); // Add a location
bool add(Value *Ptr, uint64_t Size, const MDNode *TBAAInfo); // Add a location
bool add(LoadInst *LI);
bool add(StoreInst *SI);
bool add(VAArgInst *VAAI);
@ -312,7 +334,8 @@ public:
/// remove methods - These methods are used to remove all entries that might
/// be aliased by the specified instruction. These methods return true if any
/// alias sets were eliminated.
bool remove(Value *Ptr, unsigned Size); // Remove a location
// Remove a location
bool remove(Value *Ptr, uint64_t Size, const MDNode *TBAAInfo);
bool remove(LoadInst *LI);
bool remove(StoreInst *SI);
bool remove(VAArgInst *VAAI);
@ -332,18 +355,21 @@ public:
/// lives in. If the New argument is non-null, this method sets the value to
/// true if a new alias set is created to contain the pointer (because the
/// pointer didn't alias anything).
AliasSet &getAliasSetForPointer(Value *P, unsigned Size, bool *New = 0);
AliasSet &getAliasSetForPointer(Value *P, uint64_t Size,
const MDNode *TBAAInfo,
bool *New = 0);
/// getAliasSetForPointerIfExists - Return the alias set containing the
/// location specified if one exists, otherwise return null.
AliasSet *getAliasSetForPointerIfExists(Value *P, unsigned Size) {
return findAliasSetForPointer(P, Size);
AliasSet *getAliasSetForPointerIfExists(Value *P, uint64_t Size,
const MDNode *TBAAInfo) {
return findAliasSetForPointer(P, Size, TBAAInfo);
}
/// containsPointer - Return true if the specified location is represented by
/// this alias set, false otherwise. This does not modify the AST object or
/// alias sets.
bool containsPointer(Value *P, unsigned Size) const;
bool containsPointer(Value *P, uint64_t Size, const MDNode *TBAAInfo) const;
/// getAliasAnalysis - Return the underlying alias analysis object used by
/// this tracker.
@ -390,14 +416,16 @@ private:
return *Entry;
}
AliasSet &addPointer(Value *P, unsigned Size, AliasSet::AccessType E,
AliasSet &addPointer(Value *P, uint64_t Size, const MDNode *TBAAInfo,
AliasSet::AccessType E,
bool &NewSet) {
NewSet = false;
AliasSet &AS = getAliasSetForPointer(P, Size, &NewSet);
AliasSet &AS = getAliasSetForPointer(P, Size, TBAAInfo, &NewSet);
AS.AccessTy |= E;
return AS;
}
AliasSet *findAliasSetForPointer(const Value *Ptr, unsigned Size);
AliasSet *findAliasSetForPointer(const Value *Ptr, uint64_t Size,
const MDNode *TBAAInfo);
AliasSet *findAliasSetForCallSite(CallSite CS);
};

View File

@ -57,7 +57,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Support/ValueHandle.h"
#include "llvm/System/IncludeFile.h"
#include "llvm/Support/IncludeFile.h"
#include <map>
namespace llvm {
@ -138,6 +138,13 @@ public:
/// not already exist.
CallGraphNode *getOrInsertFunction(const Function *F);
/// spliceFunction - Replace the function represented by this node by another.
/// This does not rescan the body of the function, so it is suitable when
/// splicing the body of one function to another while also updating all
/// callers from the old function to the new.
///
void spliceFunction(const Function *From, const Function *To);
//===---------------------------------------------------------------------
// Pass infrastructure interface glue code.
//
@ -163,8 +170,10 @@ protected:
// CallGraphNode class definition.
//
class CallGraphNode {
AssertingVH<Function> F;
friend class CallGraph;
AssertingVH<Function> F;
// CallRecord - This is a pair of the calling instruction (a call or invoke)
// and the callgraph node being called.
public:

View File

@ -7,15 +7,16 @@
//
//===----------------------------------------------------------------------===//
//
// This file implements various weight measurements for a function, helping
// the Inliner and PartialSpecialization decide whether to duplicate its
// contents.
// This file implements various weight measurements for code, helping
// the Inliner and other passes decide whether to duplicate its contents.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_CODEMETRICS_H
#define LLVM_ANALYSIS_CODEMETRICS_H
#include "llvm/ADT/DenseMap.h"
namespace llvm {
// CodeMetrics - Calculate size and a few similar metrics for a set of
// basic blocks.
@ -45,6 +46,11 @@ namespace llvm {
/// NumCalls - Keep track of the number of calls to 'big' functions.
unsigned NumCalls;
/// NumInlineCandidates - Keep track of the number of calls to internal
/// functions with only a single caller. These are likely targets for
/// future inlining, likely exposed by interleaved devirtualization.
unsigned NumInlineCandidates;
/// NumVectorInsts - Keep track of how many instructions produce vector
/// values. The inliner is being more aggressive with inlining vector
@ -56,7 +62,8 @@ namespace llvm {
CodeMetrics() : callsSetJmp(false), isRecursive(false),
containsIndirectBr(false), usesDynamicAlloca(false),
NumInsts(0), NumBlocks(0), NumCalls(0), NumVectorInsts(0),
NumInsts(0), NumBlocks(0), NumCalls(0),
NumInlineCandidates(0), NumVectorInsts(0),
NumRets(0) {}
/// analyzeBasicBlock - Add information about the specified basic block
@ -66,6 +73,22 @@ namespace llvm {
/// analyzeFunction - Add information about the specified function
/// to the current structure.
void analyzeFunction(Function *F);
/// CountCodeReductionForConstant - Figure out an approximation for how
/// many instructions will be constant folded if the specified value is
/// constant.
unsigned CountCodeReductionForConstant(Value *V);
/// CountBonusForConstant - Figure out an approximation for how much
/// per-call performance boost we can expect if the specified value is
/// constant.
unsigned CountBonusForConstant(Value *V);
/// CountCodeReductionForAlloca - Figure out an approximation of how much
/// smaller the function will be if it is inlined into a context where an
/// argument becomes an alloca.
///
unsigned CountCodeReductionForAlloca(Value *V);
};
}

View File

@ -7,7 +7,8 @@
//
//===----------------------------------------------------------------------===//
//
// This file declares routines for folding instructions into constants.
// This file declares routines for folding instructions into constants when all
// operands are constants, for example "sub i32 1, 0" -> "1".
//
// Also, to supplement the basic VMCore ConstantExpr simplifications,
// this file declares some additional folding routines that can make use of
@ -27,11 +28,11 @@ namespace llvm {
class Function;
class Type;
/// ConstantFoldInstruction - Attempt to constant fold the specified
/// instruction. If successful, the constant result is returned, if not, null
/// is returned. Note that this function can only fail when attempting to fold
/// instructions like loads and stores, which have no constant expression form.
///
/// ConstantFoldInstruction - Try to constant fold the specified instruction.
/// If successful, the constant result is returned, if not, null is returned.
/// Note that this fails if not all of the operands are constant. Otherwise,
/// this function can only fail when attempting to fold instructions like loads
/// and stores, which have no constant expression form.
Constant *ConstantFoldInstruction(Instruction *I, const TargetData *TD = 0);
/// ConstantFoldConstantExpression - Attempt to fold the constant expression

View File

@ -0,0 +1,459 @@
//===--- llvm/Analysis/DIBuilder.h - Debug Information Builder --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines a DIBuilder that is useful for creating debugging
// information entries in LLVM IR form.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_DIBUILDER_H
#define LLVM_ANALYSIS_DIBUILDER_H
#include "llvm/Support/DataTypes.h"
#include "llvm/ADT/StringRef.h"
namespace llvm {
class BasicBlock;
class Instruction;
class Function;
class Module;
class Value;
class LLVMContext;
class MDNode;
class StringRef;
class DIDescriptor;
class DIFile;
class DIEnumerator;
class DIType;
class DIArray;
class DIGlobalVariable;
class DINameSpace;
class DIVariable;
class DISubrange;
class DILexicalBlock;
class DISubprogram;
class DITemplateTypeParameter;
class DITemplateValueParameter;
class DIBuilder {
private:
Module &M;
LLVMContext & VMContext;
MDNode *TheCU;
Function *DeclareFn; // llvm.dbg.declare
Function *ValueFn; // llvm.dbg.value
DIBuilder(const DIBuilder &); // DO NOT IMPLEMENT
void operator=(const DIBuilder &); // DO NOT IMPLEMENT
public:
explicit DIBuilder(Module &M);
const MDNode *getCU() { return TheCU; }
enum ComplexAddrKind { OpPlus=1, OpDeref };
/// CreateCompileUnit - A CompileUnit provides an anchor for all debugging
/// information generated during this instance of compilation.
/// @param Lang Source programming language, eg. dwarf::DW_LANG_C99
/// @param File File name
/// @param Dir Directory
/// @param Producer String identify producer of debugging information.
/// Usuall this is a compiler version string.
/// @param isOptimized A boolean flag which indicates whether optimization
/// is ON or not.
/// @param Flags This string lists command line options. This string is
/// directly embedded in debug info output which may be used
/// by a tool analyzing generated debugging information.
/// @param RV This indicates runtime version for languages like
/// Objective-C.
void CreateCompileUnit(unsigned Lang, StringRef File, StringRef Dir,
StringRef Producer,
bool isOptimized, StringRef Flags, unsigned RV);
/// CreateFile - Create a file descriptor to hold debugging information
/// for a file.
DIFile CreateFile(StringRef Filename, StringRef Directory);
/// CreateEnumerator - Create a single enumerator value.
DIEnumerator CreateEnumerator(StringRef Name, uint64_t Val);
/// CreateBasicType - Create debugging information entry for a basic
/// type.
/// @param Name Type name.
/// @param SizeInBits Size of the type.
/// @param AlignInBits Type alignment.
/// @param Encoding DWARF encoding code, e.g. dwarf::DW_ATE_float.
DIType CreateBasicType(StringRef Name, uint64_t SizeInBits,
uint64_t AlignInBits, unsigned Encoding);
/// CreateQualifiedType - Create debugging information entry for a qualified
/// type, e.g. 'const int'.
/// @param Tag Tag identifing type, e.g. dwarf::TAG_volatile_type
/// @param FromTy Base Type.
DIType CreateQualifiedType(unsigned Tag, DIType FromTy);
/// CreatePointerType - Create debugging information entry for a pointer.
/// @param PointeeTy Type pointed by this pointer.
/// @param SizeInBits Size.
/// @param AlignInBits Alignment. (optional)
/// @param Name Pointer type name. (optional)
DIType CreatePointerType(DIType PointeeTy, uint64_t SizeInBits,
uint64_t AlignInBits = 0,
StringRef Name = StringRef());
/// CreateReferenceType - Create debugging information entry for a c++
/// style reference.
DIType CreateReferenceType(DIType RTy);
/// CreateTypedef - Create debugging information entry for a typedef.
/// @param Ty Original type.
/// @param Name Typedef name.
/// @param File File where this type is defined.
/// @param LineNo Line number.
DIType CreateTypedef(DIType Ty, StringRef Name, DIFile File,
unsigned LineNo);
/// CreateFriend - Create debugging information entry for a 'friend'.
DIType CreateFriend(DIType Ty, DIType FriendTy);
/// CreateInheritance - Create debugging information entry to establish
/// inheritance relationship between two types.
/// @param Ty Original type.
/// @param BaseTy Base type. Ty is inherits from base.
/// @param BaseOffset Base offset.
/// @param Flags Flags to describe inheritance attribute,
/// e.g. private
DIType CreateInheritance(DIType Ty, DIType BaseTy, uint64_t BaseOffset,
unsigned Flags);
/// CreateMemberType - Create debugging information entry for a member.
/// @param Name Member name.
/// @param File File where this member is defined.
/// @param LineNo Line number.
/// @param SizeInBits Member size.
/// @param AlignInBits Member alignment.
/// @param OffsetInBits Member offset.
/// @param Flags Flags to encode member attribute, e.g. private
/// @param Ty Parent type.
DIType CreateMemberType(StringRef Name, DIFile File,
unsigned LineNo, uint64_t SizeInBits,
uint64_t AlignInBits, uint64_t OffsetInBits,
unsigned Flags, DIType Ty);
/// CreateClassType - Create debugging information entry for a class.
/// @param Scope Scope in which this class is defined.
/// @param Name class name.
/// @param File File where this member is defined.
/// @param LineNo Line number.
/// @param SizeInBits Member size.
/// @param AlignInBits Member alignment.
/// @param OffsetInBits Member offset.
/// @param Flags Flags to encode member attribute, e.g. private
/// @param Elements class members.
/// @param VTableHolder Debug info of the base class that contains vtable
/// for this type. This is used in
/// DW_AT_containing_type. See DWARF documentation
/// for more info.
/// @param TemplateParms Template type parameters.
DIType CreateClassType(DIDescriptor Scope, StringRef Name, DIFile File,
unsigned LineNumber, uint64_t SizeInBits,
uint64_t AlignInBits, uint64_t OffsetInBits,
unsigned Flags, DIType DerivedFrom,
DIArray Elements, MDNode *VTableHolder = 0,
MDNode *TemplateParms = 0);
/// CreateStructType - Create debugging information entry for a struct.
/// @param Scope Scope in which this struct is defined.
/// @param Name Struct name.
/// @param File File where this member is defined.
/// @param LineNo Line number.
/// @param SizeInBits Member size.
/// @param AlignInBits Member alignment.
/// @param Flags Flags to encode member attribute, e.g. private
/// @param Elements Struct elements.
/// @param RunTimeLang Optional parameter, Objective-C runtime version.
DIType CreateStructType(DIDescriptor Scope, StringRef Name, DIFile File,
unsigned LineNumber, uint64_t SizeInBits,
uint64_t AlignInBits, unsigned Flags,
DIArray Elements, unsigned RunTimeLang = 0);
/// CreateUnionType - Create debugging information entry for an union.
/// @param Scope Scope in which this union is defined.
/// @param Name Union name.
/// @param File File where this member is defined.
/// @param LineNo Line number.
/// @param SizeInBits Member size.
/// @param AlignInBits Member alignment.
/// @param Flags Flags to encode member attribute, e.g. private
/// @param Elements Union elements.
/// @param RunTimeLang Optional parameter, Objective-C runtime version.
DIType CreateUnionType(DIDescriptor Scope, StringRef Name, DIFile File,
unsigned LineNumber, uint64_t SizeInBits,
uint64_t AlignInBits, unsigned Flags,
DIArray Elements, unsigned RunTimeLang = 0);
/// CreateTemplateTypeParameter - Create debugging information for template
/// type parameter.
/// @param Scope Scope in which this type is defined.
/// @param Name Type parameter name.
/// @param Ty Parameter type.
/// @param File File where this type parameter is defined.
/// @param LineNo Line number.
/// @param ColumnNo Column Number.
DITemplateTypeParameter
CreateTemplateTypeParameter(DIDescriptor Scope, StringRef Name, DIType Ty,
MDNode *File = 0, unsigned LineNo = 0,
unsigned ColumnNo = 0);
/// CreateTemplateValueParameter - Create debugging information for template
/// value parameter.
/// @param Scope Scope in which this type is defined.
/// @param Name Value parameter name.
/// @param Ty Parameter type.
/// @param Value Constant parameter value.
/// @param File File where this type parameter is defined.
/// @param LineNo Line number.
/// @param ColumnNo Column Number.
DITemplateValueParameter
CreateTemplateValueParameter(DIDescriptor Scope, StringRef Name, DIType Ty,
uint64_t Value,
MDNode *File = 0, unsigned LineNo = 0,
unsigned ColumnNo = 0);
/// CreateArrayType - Create debugging information entry for an array.
/// @param Size Array size.
/// @param AlignInBits Alignment.
/// @param Ty Element type.
/// @param Subscripts Subscripts.
DIType CreateArrayType(uint64_t Size, uint64_t AlignInBits,
DIType Ty, DIArray Subscripts);
/// CreateVectorType - Create debugging information entry for a vector type.
/// @param Size Array size.
/// @param AlignInBits Alignment.
/// @param Ty Element type.
/// @param Subscripts Subscripts.
DIType CreateVectorType(uint64_t Size, uint64_t AlignInBits,
DIType Ty, DIArray Subscripts);
/// CreateEnumerationType - Create debugging information entry for an
/// enumeration.
/// @param Scope Scope in which this enumeration is defined.
/// @param Name Union name.
/// @param File File where this member is defined.
/// @param LineNo Line number.
/// @param SizeInBits Member size.
/// @param AlignInBits Member alignment.
/// @param Elements Enumeration elements.
DIType CreateEnumerationType(DIDescriptor Scope, StringRef Name,
DIFile File, unsigned LineNumber,
uint64_t SizeInBits,
uint64_t AlignInBits, DIArray Elements);
/// CreateSubroutineType - Create subroutine type.
/// @param File File in which this subroutine is defined.
/// @param ParamterTypes An array of subroutine parameter types. This
/// includes return type at 0th index.
DIType CreateSubroutineType(DIFile File, DIArray ParameterTypes);
/// CreateArtificialType - Create a new DIType with "artificial" flag set.
DIType CreateArtificialType(DIType Ty);
/// CreateTemporaryType - Create a temporary forward-declared type.
DIType CreateTemporaryType();
DIType CreateTemporaryType(DIFile F);
/// RetainType - Retain DIType in a module even if it is not referenced
/// through debug info anchors.
void RetainType(DIType T);
/// CreateUnspecifiedParameter - Create unspeicified type descriptor
/// for a subroutine type.
DIDescriptor CreateUnspecifiedParameter();
/// GetOrCreateArray - Get a DIArray, create one if required.
DIArray GetOrCreateArray(Value *const *Elements, unsigned NumElements);
/// GetOrCreateSubrange - Create a descriptor for a value range. This
/// implicitly uniques the values returned.
DISubrange GetOrCreateSubrange(int64_t Lo, int64_t Hi);
/// CreateGlobalVariable - Create a new descriptor for the specified global.
/// @param Name Name of the variable.
/// @param File File where this variable is defined.
/// @param LineNo Line number.
/// @param Ty Variable Type.
/// @param isLocalToUnit Boolean flag indicate whether this variable is
/// externally visible or not.
/// @param Val llvm::Value of the variable.
DIGlobalVariable
CreateGlobalVariable(StringRef Name, DIFile File, unsigned LineNo,
DIType Ty, bool isLocalToUnit, llvm::Value *Val);
/// CreateStaticVariable - Create a new descriptor for the specified
/// variable.
/// @param Conext Variable scope.
/// @param Name Name of the variable.
/// @param LinakgeName Mangled name of the variable.
/// @param File File where this variable is defined.
/// @param LineNo Line number.
/// @param Ty Variable Type.
/// @param isLocalToUnit Boolean flag indicate whether this variable is
/// externally visible or not.
/// @param Val llvm::Value of the variable.
DIGlobalVariable
CreateStaticVariable(DIDescriptor Context, StringRef Name,
StringRef LinkageName, DIFile File, unsigned LineNo,
DIType Ty, bool isLocalToUnit, llvm::Value *Val);
/// CreateLocalVariable - Create a new descriptor for the specified
/// local variable.
/// @param Tag Dwarf TAG. Usually DW_TAG_auto_variable or
/// DW_TAG_arg_variable.
/// @param Scope Variable scope.
/// @param Name Variable name.
/// @param File File where this variable is defined.
/// @param LineNo Line number.
/// @param Ty Variable Type
/// @param AlwaysPreserve Boolean. Set to true if debug info for this
/// variable should be preserved in optimized build.
/// @param Flags Flags, e.g. artificial variable.
DIVariable CreateLocalVariable(unsigned Tag, DIDescriptor Scope,
StringRef Name,
DIFile File, unsigned LineNo,
DIType Ty, bool AlwaysPreserve = false,
unsigned Flags = 0);
/// CreateComplexVariable - Create a new descriptor for the specified
/// variable which has a complex address expression for its address.
/// @param Tag Dwarf TAG. Usually DW_TAG_auto_variable or
/// DW_TAG_arg_variable.
/// @param Scope Variable scope.
/// @param Name Variable name.
/// @param File File where this variable is defined.
/// @param LineNo Line number.
/// @param Ty Variable Type
/// @param Addr A pointer to a vector of complex address operations.
/// @param NumAddr Num of address operations in the vector.
DIVariable CreateComplexVariable(unsigned Tag, DIDescriptor Scope,
StringRef Name, DIFile F, unsigned LineNo,
DIType Ty, Value *const *Addr,
unsigned NumAddr);
/// CreateFunction - Create a new descriptor for the specified subprogram.
/// See comments in DISubprogram for descriptions of these fields.
/// @param Scope Function scope.
/// @param Name Function name.
/// @param LinkageName Mangled function name.
/// @param File File where this variable is defined.
/// @param LineNo Line number.
/// @param Ty Function type.
/// @param isLocalToUnit True if this function is not externally visible..
/// @param isDefinition True if this is a function definition.
/// @param Flags e.g. is this function prototyped or not.
/// This flags are used to emit dwarf attributes.
/// @param isOptimized True if optimization is ON.
/// @param Fn llvm::Function pointer.
DISubprogram CreateFunction(DIDescriptor Scope, StringRef Name,
StringRef LinkageName,
DIFile File, unsigned LineNo,
DIType Ty, bool isLocalToUnit,
bool isDefinition,
unsigned Flags = 0,
bool isOptimized = false,
Function *Fn = 0);
/// CreateMethod - Create a new descriptor for the specified C++ method.
/// See comments in DISubprogram for descriptions of these fields.
/// @param Scope Function scope.
/// @param Name Function name.
/// @param LinkageName Mangled function name.
/// @param File File where this variable is defined.
/// @param LineNo Line number.
/// @param Ty Function type.
/// @param isLocalToUnit True if this function is not externally visible..
/// @param isDefinition True if this is a function definition.
/// @param Virtuality Attributes describing virutallness. e.g. pure
/// virtual function.
/// @param VTableIndex Index no of this method in virtual table.
/// @param VTableHolder Type that holds vtable.
/// @param Flags e.g. is this function prototyped or not.
/// This flags are used to emit dwarf attributes.
/// @param isOptimized True if optimization is ON.
/// @param Fn llvm::Function pointer.
DISubprogram CreateMethod(DIDescriptor Scope, StringRef Name,
StringRef LinkageName,
DIFile File, unsigned LineNo,
DIType Ty, bool isLocalToUnit,
bool isDefinition,
unsigned Virtuality = 0, unsigned VTableIndex = 0,
MDNode *VTableHolder = 0,
unsigned Flags = 0,
bool isOptimized = false,
Function *Fn = 0);
/// CreateNameSpace - This creates new descriptor for a namespace
/// with the specified parent scope.
/// @param Scope Namespace scope
/// @param Name Name of this namespace
/// @param File Source file
/// @param LineNo Line number
DINameSpace CreateNameSpace(DIDescriptor Scope, StringRef Name,
DIFile File, unsigned LineNo);
/// CreateLexicalBlock - This creates a descriptor for a lexical block
/// with the specified parent context.
/// @param Scope Parent lexical scope.
/// @param File Source file
/// @param Line Line number
/// @param Col Column number
DILexicalBlock CreateLexicalBlock(DIDescriptor Scope, DIFile File,
unsigned Line, unsigned Col);
/// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call.
/// @param Storage llvm::Value of the variable
/// @param VarInfo Variable's debug info descriptor.
/// @param InsertAtEnd Location for the new intrinsic.
Instruction *InsertDeclare(llvm::Value *Storage, DIVariable VarInfo,
BasicBlock *InsertAtEnd);
/// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call.
/// @param Storage llvm::Value of the variable
/// @param VarInfo Variable's debug info descriptor.
/// @param InsertBefore Location for the new intrinsic.
Instruction *InsertDeclare(llvm::Value *Storage, DIVariable VarInfo,
Instruction *InsertBefore);
/// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
/// @param Val llvm::Value of the variable
/// @param Offset Offset
/// @param VarInfo Variable's debug info descriptor.
/// @param InsertAtEnd Location for the new intrinsic.
Instruction *InsertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset,
DIVariable VarInfo,
BasicBlock *InsertAtEnd);
/// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
/// @param Val llvm::Value of the variable
/// @param Offset Offset
/// @param VarInfo Variable's debug info descriptor.
/// @param InsertBefore Location for the new intrinsic.
Instruction *InsertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset,
DIVariable VarInfo,
Instruction *InsertBefore);
};
} // end namespace llvm
#endif

View File

@ -67,7 +67,7 @@ struct DOTGraphTraitsPrinter : public FunctionPass {
Title = GraphName + " for '" + F.getNameStr() + "' function";
if (ErrorInfo.empty())
WriteGraph(File, Graph, Simple, Name, Title);
WriteGraph(File, Graph, Simple, Title);
else
errs() << " error opening file for writing!";
errs() << "\n";

View File

@ -33,6 +33,7 @@ namespace llvm {
class DbgDeclareInst;
class Instruction;
class MDNode;
class NamedMDNode;
class LLVMContext;
class raw_ostream;
@ -46,6 +47,18 @@ namespace llvm {
/// This should not be stored in a container, because underly MDNode may
/// change in certain situations.
class DIDescriptor {
public:
enum {
FlagPrivate = 1 << 0,
FlagProtected = 1 << 1,
FlagFwdDecl = 1 << 2,
FlagAppleBlock = 1 << 3,
FlagBlockByrefStruct = 1 << 4,
FlagVirtual = 1 << 5,
FlagArtificial = 1 << 6,
FlagExplicit = 1 << 7,
FlagPrototyped = 1 << 8
};
protected:
const MDNode *DbgNode;
@ -108,6 +121,9 @@ namespace llvm {
bool isEnumerator() const;
bool isType() const;
bool isGlobal() const;
bool isUnspecifiedParameter() const;
bool isTemplateTypeParameter() const;
bool isTemplateValueParameter() const;
};
/// DISubrange - This is used to represent ranges, for array bounds.
@ -160,8 +176,8 @@ namespace llvm {
/// module does not contain any main compile unit then the code generator
/// will emit multiple compile units in the output object file.
bool isMain() const { return getUnsignedField(6); }
bool isOptimized() const { return getUnsignedField(7); }
bool isMain() const { return getUnsignedField(6) != 0; }
bool isOptimized() const { return getUnsignedField(7) != 0; }
StringRef getFlags() const { return getStringField(8); }
unsigned getRunTimeVersion() const { return getUnsignedField(9); }
@ -203,17 +219,6 @@ namespace llvm {
/// others do not require a huge and empty descriptor full of zeros.
class DIType : public DIScope {
public:
enum {
FlagPrivate = 1 << 0,
FlagProtected = 1 << 1,
FlagFwdDecl = 1 << 2,
FlagAppleBlock = 1 << 3,
FlagBlockByrefStruct = 1 << 4,
FlagVirtual = 1 << 5,
FlagArtificial = 1 << 6 // To identify artificial arguments in
// a subroutine type. e.g. "this" in c++.
};
protected:
// This ctor is used when the Tag has already been validated by a derived
// ctor.
@ -231,12 +236,12 @@ namespace llvm {
DIScope getContext() const { return getFieldAs<DIScope>(1); }
StringRef getName() const { return getStringField(2); }
DICompileUnit getCompileUnit() const{
if (getVersion() == llvm::LLVMDebugVersion7)
return getFieldAs<DICompileUnit>(3);
DIFile F = getFieldAs<DIFile>(3);
return F.getCompileUnit();
if (getVersion() == llvm::LLVMDebugVersion7)
return getFieldAs<DICompileUnit>(3);
return getFieldAs<DIFile>(3).getCompileUnit();
}
DIFile getFile() const { return getFieldAs<DIFile>(3); }
unsigned getLineNumber() const { return getUnsignedField(4); }
uint64_t getSizeInBits() const { return getUInt64Field(5); }
uint64_t getAlignInBits() const { return getUInt64Field(6); }
@ -269,12 +274,23 @@ namespace llvm {
bool isValid() const {
return DbgNode && (isBasicType() || isDerivedType() || isCompositeType());
}
StringRef getFilename() const { return getCompileUnit().getFilename();}
StringRef getDirectory() const { return getCompileUnit().getDirectory();}
StringRef getDirectory() const {
if (getVersion() == llvm::LLVMDebugVersion7)
return getCompileUnit().getDirectory();
return getFieldAs<DIFile>(3).getDirectory();
}
StringRef getFilename() const {
if (getVersion() == llvm::LLVMDebugVersion7)
return getCompileUnit().getFilename();
return getFieldAs<DIFile>(3).getFilename();
}
/// replaceAllUsesWith - Replace all uses of debug info referenced by
/// this descriptor.
void replaceAllUsesWith(DIDescriptor &D);
void replaceAllUsesWith(MDNode *D);
/// print - print type.
void print(raw_ostream &OS) const;
@ -342,6 +358,7 @@ namespace llvm {
DICompositeType getContainingType() const {
return getFieldAs<DICompositeType>(12);
}
DIArray getTemplateParams() const { return getFieldAs<DIArray>(13); }
/// Verify - Verify that a composite type descriptor is well formed.
bool Verify() const;
@ -353,6 +370,43 @@ namespace llvm {
void dump() const;
};
/// DITemplateTypeParameter - This is a wrapper for template type parameter.
class DITemplateTypeParameter : public DIDescriptor {
public:
explicit DITemplateTypeParameter(const MDNode *N = 0) : DIDescriptor(N) {}
DIScope getContext() const { return getFieldAs<DIScope>(1); }
StringRef getName() const { return getStringField(2); }
DIType getType() const { return getFieldAs<DIType>(3); }
StringRef getFilename() const {
return getFieldAs<DIFile>(4).getFilename();
}
StringRef getDirectory() const {
return getFieldAs<DIFile>(4).getDirectory();
}
unsigned getLineNumber() const { return getUnsignedField(5); }
unsigned getColumnNumber() const { return getUnsignedField(6); }
};
/// DITemplateValueParameter - This is a wrapper for template value parameter.
class DITemplateValueParameter : public DIDescriptor {
public:
explicit DITemplateValueParameter(const MDNode *N = 0) : DIDescriptor(N) {}
DIScope getContext() const { return getFieldAs<DIScope>(1); }
StringRef getName() const { return getStringField(2); }
DIType getType() const { return getFieldAs<DIType>(3); }
uint64_t getValue() const { return getUInt64Field(4); }
StringRef getFilename() const {
return getFieldAs<DIFile>(5).getFilename();
}
StringRef getDirectory() const {
return getFieldAs<DIFile>(5).getDirectory();
}
unsigned getLineNumber() const { return getUnsignedField(6); }
unsigned getColumnNumber() const { return getUnsignedField(7); }
};
/// DISubprogram - This is a wrapper for a subprogram (e.g. a function).
class DISubprogram : public DIScope {
public:
@ -366,8 +420,7 @@ namespace llvm {
if (getVersion() == llvm::LLVMDebugVersion7)
return getFieldAs<DICompileUnit>(6);
DIFile F = getFieldAs<DIFile>(6);
return F.getCompileUnit();
return getFieldAs<DIFile>(6).getCompileUnit();
}
unsigned getLineNumber() const { return getUnsignedField(7); }
DICompositeType getType() const { return getFieldAs<DICompositeType>(8); }
@ -396,23 +449,52 @@ namespace llvm {
DICompositeType getContainingType() const {
return getFieldAs<DICompositeType>(13);
}
unsigned isArtificial() const { return getUnsignedField(14); }
unsigned isArtificial() const {
if (getVersion() <= llvm::LLVMDebugVersion8)
return getUnsignedField(14);
return (getUnsignedField(14) & FlagArtificial) != 0;
}
/// isPrivate - Return true if this subprogram has "private"
/// access specifier.
bool isPrivate() const {
if (getVersion() <= llvm::LLVMDebugVersion8)
return false;
return (getUnsignedField(14) & FlagPrivate) != 0;
}
/// isProtected - Return true if this subprogram has "protected"
/// access specifier.
bool isProtected() const {
if (getVersion() <= llvm::LLVMDebugVersion8)
return false;
return (getUnsignedField(14) & FlagProtected) != 0;
}
/// isExplicit - Return true if this subprogram is marked as explicit.
bool isExplicit() const {
if (getVersion() <= llvm::LLVMDebugVersion8)
return false;
return (getUnsignedField(14) & FlagExplicit) != 0;
}
/// isPrototyped - Return true if this subprogram is prototyped.
bool isPrototyped() const {
if (getVersion() <= llvm::LLVMDebugVersion8)
return false;
return (getUnsignedField(14) & FlagPrototyped) != 0;
}
unsigned isOptimized() const;
StringRef getFilename() const {
if (getVersion() == llvm::LLVMDebugVersion7)
return getCompileUnit().getFilename();
DIFile F = getFieldAs<DIFile>(6);
return F.getFilename();
return getFieldAs<DIFile>(6).getFilename();
}
StringRef getDirectory() const {
if (getVersion() == llvm::LLVMDebugVersion7)
return getCompileUnit().getFilename();
DIFile F = getFieldAs<DIFile>(6);
return F.getDirectory();
return getFieldAs<DIFile>(6).getDirectory();
}
/// Verify - Verify that a subprogram descriptor is well formed.
@ -484,6 +566,13 @@ namespace llvm {
}
unsigned getLineNumber() const { return getUnsignedField(4); }
DIType getType() const { return getFieldAs<DIType>(5); }
/// isArtificial - Return true if this variable is marked as "artificial".
bool isArtificial() const {
if (getVersion() <= llvm::LLVMDebugVersion8)
return false;
return (getUnsignedField(6) & FlagArtificial) != 0;
}
/// Verify - Verify that a variable descriptor is well formed.
@ -525,13 +614,11 @@ namespace llvm {
unsigned getLineNumber() const { return getUnsignedField(2); }
unsigned getColumnNumber() const { return getUnsignedField(3); }
StringRef getDirectory() const {
DIFile F = getFieldAs<DIFile>(4);
StringRef dir = F.getDirectory();
StringRef dir = getFieldAs<DIFile>(4).getDirectory();
return !dir.empty() ? dir : getContext().getDirectory();
}
StringRef getFilename() const {
DIFile F = getFieldAs<DIFile>(4);
StringRef filename = F.getFilename();
StringRef filename = getFieldAs<DIFile>(4).getFilename();
return !filename.empty() ? filename : getContext().getFilename();
}
};
@ -542,14 +629,17 @@ namespace llvm {
explicit DINameSpace(const MDNode *N = 0) : DIScope(N) {}
DIScope getContext() const { return getFieldAs<DIScope>(1); }
StringRef getName() const { return getStringField(2); }
StringRef getDirectory() const { return getContext().getDirectory(); }
StringRef getFilename() const { return getContext().getFilename(); }
StringRef getDirectory() const {
return getFieldAs<DIFile>(3).getDirectory();
}
StringRef getFilename() const {
return getFieldAs<DIFile>(3).getFilename();
}
DICompileUnit getCompileUnit() const{
if (getVersion() == llvm::LLVMDebugVersion7)
return getFieldAs<DICompileUnit>(3);
DIFile F = getFieldAs<DIFile>(3);
return F.getCompileUnit();
return getFieldAs<DIFile>(3).getCompileUnit();
}
unsigned getLineNumber() const { return getUnsignedField(4); }
bool Verify() const;
@ -594,6 +684,10 @@ namespace llvm {
/// implicitly uniques the values returned.
DISubrange GetOrCreateSubrange(int64_t Lo, int64_t Hi);
/// CreateUnspecifiedParameter - Create unspeicified type descriptor
/// for a subroutine type.
DIDescriptor CreateUnspecifiedParameter();
/// CreateCompileUnit - Create a new descriptor for the specified compile
/// unit.
DICompileUnit CreateCompileUnit(unsigned LangID,
@ -662,6 +756,7 @@ namespace llvm {
/// CreateTemporaryType - Create a temporary forward-declared type.
DIType CreateTemporaryType();
DIType CreateTemporaryType(DIFile F);
/// CreateArtificialType - Create a new DIType with "artificial" flag set.
DIType CreateArtificialType(DIType Ty);
@ -690,8 +785,8 @@ namespace llvm {
bool isDefinition,
unsigned VK = 0,
unsigned VIndex = 0,
DIType = DIType(),
bool isArtificial = 0,
DIType ContainingType = DIType(),
unsigned Flags = 0,
bool isOptimized = false,
Function *Fn = 0);
@ -721,15 +816,15 @@ namespace llvm {
DIVariable CreateVariable(unsigned Tag, DIDescriptor Context,
StringRef Name,
DIFile F, unsigned LineNo,
DIType Ty, bool AlwaysPreserve = false);
DIType Ty, bool AlwaysPreserve = false,
unsigned Flags = 0);
/// CreateComplexVariable - Create a new descriptor for the specified
/// variable which has a complex address expression for its address.
DIVariable CreateComplexVariable(unsigned Tag, DIDescriptor Context,
const std::string &Name,
DIFile F, unsigned LineNo,
DIType Ty,
SmallVector<Value *, 9> &addr);
StringRef Name, DIFile F, unsigned LineNo,
DIType Ty, Value *const *Addr,
unsigned NumAddr);
/// CreateLexicalBlock - This creates a descriptor for a lexical block
/// with the specified parent context.
@ -764,20 +859,29 @@ namespace llvm {
/// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
Instruction *InsertDbgValueIntrinsic(llvm::Value *V, uint64_t Offset,
DIVariable D, Instruction *InsertBefore);
// RecordType - Record DIType in a module such that it is not lost even if
// it is not referenced through debug info anchors.
void RecordType(DIType T);
private:
Constant *GetTagConstant(unsigned TAG);
};
bool getLocationInfo(const Value *V, std::string &DisplayName,
std::string &Type, unsigned &LineNo, std::string &File,
std::string &Dir);
/// getDISubprogram - Find subprogram that is enclosing this scope.
DISubprogram getDISubprogram(const MDNode *Scope);
/// getDICompositeType - Find underlying composite type.
DICompositeType getDICompositeType(DIType T);
/// getOrInsertFnSpecificMDNode - Return a NameMDNode that is suitable
/// to hold function specific information.
NamedMDNode *getOrInsertFnSpecificMDNode(Module &M, StringRef Name);
/// getFnSpecificMDNode - Return a NameMDNode, if available, that is
/// suitable to hold function specific information.
NamedMDNode *getFnSpecificMDNode(const Module &M, StringRef Name);
class DebugInfoFinder {
public:
/// processModule - Process entire module and collect debug info

View File

@ -0,0 +1,189 @@
//===- llvm/Analysis/DominanceFrontier.h - Dominator Frontiers --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the DominanceFrontier class, which calculate and holds the
// dominance frontier for a function.
//
// This should be considered deprecated, don't add any more uses of this data
// structure.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_DOMINANCEFRONTIER_H
#define LLVM_ANALYSIS_DOMINANCEFRONTIER_H
#include "llvm/Analysis/Dominators.h"
#include <map>
#include <set>
namespace llvm {
//===----------------------------------------------------------------------===//
/// DominanceFrontierBase - Common base class for computing forward and inverse
/// dominance frontiers for a function.
///
class DominanceFrontierBase : public FunctionPass {
public:
typedef std::set<BasicBlock*> DomSetType; // Dom set for a bb
typedef std::map<BasicBlock*, DomSetType> DomSetMapType; // Dom set map
protected:
DomSetMapType Frontiers;
std::vector<BasicBlock*> Roots;
const bool IsPostDominators;
public:
DominanceFrontierBase(char &ID, bool isPostDom)
: FunctionPass(ID), IsPostDominators(isPostDom) {}
/// getRoots - Return the root blocks of the current CFG. This may include
/// multiple blocks if we are computing post dominators. For forward
/// dominators, this will always be a single block (the entry node).
///
inline const std::vector<BasicBlock*> &getRoots() const { return Roots; }
/// isPostDominator - Returns true if analysis based of postdoms
///
bool isPostDominator() const { return IsPostDominators; }
virtual void releaseMemory() { Frontiers.clear(); }
// Accessor interface:
typedef DomSetMapType::iterator iterator;
typedef DomSetMapType::const_iterator const_iterator;
iterator begin() { return Frontiers.begin(); }
const_iterator begin() const { return Frontiers.begin(); }
iterator end() { return Frontiers.end(); }
const_iterator end() const { return Frontiers.end(); }
iterator find(BasicBlock *B) { return Frontiers.find(B); }
const_iterator find(BasicBlock *B) const { return Frontiers.find(B); }
iterator addBasicBlock(BasicBlock *BB, const DomSetType &frontier) {
assert(find(BB) == end() && "Block already in DominanceFrontier!");
return Frontiers.insert(std::make_pair(BB, frontier)).first;
}
/// removeBlock - Remove basic block BB's frontier.
void removeBlock(BasicBlock *BB) {
assert(find(BB) != end() && "Block is not in DominanceFrontier!");
for (iterator I = begin(), E = end(); I != E; ++I)
I->second.erase(BB);
Frontiers.erase(BB);
}
void addToFrontier(iterator I, BasicBlock *Node) {
assert(I != end() && "BB is not in DominanceFrontier!");
I->second.insert(Node);
}
void removeFromFrontier(iterator I, BasicBlock *Node) {
assert(I != end() && "BB is not in DominanceFrontier!");
assert(I->second.count(Node) && "Node is not in DominanceFrontier of BB");
I->second.erase(Node);
}
/// compareDomSet - Return false if two domsets match. Otherwise
/// return true;
bool compareDomSet(DomSetType &DS1, const DomSetType &DS2) const {
std::set<BasicBlock *> tmpSet;
for (DomSetType::const_iterator I = DS2.begin(),
E = DS2.end(); I != E; ++I)
tmpSet.insert(*I);
for (DomSetType::const_iterator I = DS1.begin(),
E = DS1.end(); I != E; ) {
BasicBlock *Node = *I++;
if (tmpSet.erase(Node) == 0)
// Node is in DS1 but not in DS2.
return true;
}
if (!tmpSet.empty())
// There are nodes that are in DS2 but not in DS1.
return true;
// DS1 and DS2 matches.
return false;
}
/// compare - Return true if the other dominance frontier base matches
/// this dominance frontier base. Otherwise return false.
bool compare(DominanceFrontierBase &Other) const {
DomSetMapType tmpFrontiers;
for (DomSetMapType::const_iterator I = Other.begin(),
E = Other.end(); I != E; ++I)
tmpFrontiers.insert(std::make_pair(I->first, I->second));
for (DomSetMapType::iterator I = tmpFrontiers.begin(),
E = tmpFrontiers.end(); I != E; ) {
BasicBlock *Node = I->first;
const_iterator DFI = find(Node);
if (DFI == end())
return true;
if (compareDomSet(I->second, DFI->second))
return true;
++I;
tmpFrontiers.erase(Node);
}
if (!tmpFrontiers.empty())
return true;
return false;
}
/// print - Convert to human readable form
///
virtual void print(raw_ostream &OS, const Module* = 0) const;
/// dump - Dump the dominance frontier to dbgs().
void dump() const;
};
//===-------------------------------------
/// DominanceFrontier Class - Concrete subclass of DominanceFrontierBase that is
/// used to compute a forward dominator frontiers.
///
class DominanceFrontier : public DominanceFrontierBase {
public:
static char ID; // Pass ID, replacement for typeid
DominanceFrontier() :
DominanceFrontierBase(ID, false) {
initializeDominanceFrontierPass(*PassRegistry::getPassRegistry());
}
BasicBlock *getRoot() const {
assert(Roots.size() == 1 && "Should always have entry node!");
return Roots[0];
}
virtual bool runOnFunction(Function &) {
Frontiers.clear();
DominatorTree &DT = getAnalysis<DominatorTree>();
Roots = DT.getRoots();
assert(Roots.size() == 1 && "Only one entry block for forward domfronts!");
calculate(DT, DT[Roots[0]]);
return false;
}
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
AU.addRequired<DominatorTree>();
}
const DomSetType &calculate(const DominatorTree &DT,
const DomTreeNode *Node);
};
} // End llvm namespace
#endif

View File

@ -22,13 +22,9 @@
// A Fast Algorithm for Finding Dominators in a Flowgraph
// T. Lengauer & R. Tarjan, ACM TOPLAS July 1979, pgs 121-141.
//
// This implements both the O(n*ack(n)) and the O(n*log(n)) versions of EVAL and
// LINK, but it turns out that the theoretically slower O(n*log(n))
// implementation is actually faster than the "efficient" algorithm (even for
// large CFGs) because the constant overheads are substantially smaller. The
// lower-complexity version can be enabled with the following #define:
//
#define BALANCE_IDOM_TREE 0
// This implements the O(n*log(n)) versions of EVAL and LINK, because it turns
// out that the theoretically slower O(n*log(n)) implementation is actually
// faster than the almost-linear O(n*alpha(n)) version, even for large CFGs.
//
//===----------------------------------------------------------------------===//
@ -46,9 +42,6 @@ unsigned DFSPass(DominatorTreeBase<typename GraphT::NodeType>& DT,
VInfo.Label = V;
Vertex.push_back(V); // Vertex[n] = V;
//Info[V].Ancestor = 0; // Ancestor[n] = 0
//Info[V].Child = 0; // Child[v] = 0
VInfo.Size = 1; // Size[v] = 1
for (succ_iterator SI = succ_begin(V), E = succ_end(V); SI != E; ++SI) {
InfoRec &SuccVInfo = DT.Info[*SI];
@ -58,10 +51,10 @@ unsigned DFSPass(DominatorTreeBase<typename GraphT::NodeType>& DT,
}
}
#else
bool IsChilOfArtificialExit = (N != 0);
bool IsChildOfArtificialExit = (N != 0);
std::vector<std::pair<typename GraphT::NodeType*,
typename GraphT::ChildIteratorType> > Worklist;
SmallVector<std::pair<typename GraphT::NodeType*,
typename GraphT::ChildIteratorType>, 32> Worklist;
Worklist.push_back(std::make_pair(V, GraphT::child_begin(V)));
while (!Worklist.empty()) {
typename GraphT::NodeType* BB = Worklist.back().first;
@ -76,14 +69,11 @@ unsigned DFSPass(DominatorTreeBase<typename GraphT::NodeType>& DT,
BBInfo.Label = BB;
DT.Vertex.push_back(BB); // Vertex[n] = V;
//BBInfo[V].Ancestor = 0; // Ancestor[n] = 0
//BBInfo[V].Child = 0; // Child[v] = 0
BBInfo.Size = 1; // Size[v] = 1
if (IsChilOfArtificialExit)
if (IsChildOfArtificialExit)
BBInfo.Parent = 1;
IsChilOfArtificialExit = false;
IsChildOfArtificialExit = false;
}
// store the DFS number of the current BB - the reference to BBInfo might
@ -114,118 +104,47 @@ unsigned DFSPass(DominatorTreeBase<typename GraphT::NodeType>& DT,
}
template<class GraphT>
void Compress(DominatorTreeBase<typename GraphT::NodeType>& DT,
typename GraphT::NodeType *VIn) {
std::vector<typename GraphT::NodeType*> Work;
SmallPtrSet<typename GraphT::NodeType*, 32> Visited;
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &VInVAInfo =
DT.Info[DT.Vertex[DT.Info[VIn].Ancestor]];
typename GraphT::NodeType*
Eval(DominatorTreeBase<typename GraphT::NodeType>& DT,
typename GraphT::NodeType *VIn, unsigned LastLinked) {
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &VInInfo =
DT.Info[VIn];
if (VInInfo.DFSNum < LastLinked)
return VIn;
if (VInVAInfo.Ancestor != 0)
SmallVector<typename GraphT::NodeType*, 32> Work;
SmallPtrSet<typename GraphT::NodeType*, 32> Visited;
if (VInInfo.Parent >= LastLinked)
Work.push_back(VIn);
while (!Work.empty()) {
typename GraphT::NodeType* V = Work.back();
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &VInfo =
DT.Info[V];
typename GraphT::NodeType* VAncestor = DT.Vertex[VInfo.Ancestor];
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &VAInfo =
DT.Info[VAncestor];
typename GraphT::NodeType* VAncestor = DT.Vertex[VInfo.Parent];
// Process Ancestor first
if (Visited.insert(VAncestor) &&
VAInfo.Ancestor != 0) {
if (Visited.insert(VAncestor) && VInfo.Parent >= LastLinked) {
Work.push_back(VAncestor);
continue;
}
Work.pop_back();
// Update VInfo based on Ancestor info
if (VAInfo.Ancestor == 0)
if (VInfo.Parent < LastLinked)
continue;
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &VAInfo =
DT.Info[VAncestor];
typename GraphT::NodeType* VAncestorLabel = VAInfo.Label;
typename GraphT::NodeType* VLabel = VInfo.Label;
if (DT.Info[VAncestorLabel].Semi < DT.Info[VLabel].Semi)
VInfo.Label = VAncestorLabel;
VInfo.Ancestor = VAInfo.Ancestor;
}
}
template<class GraphT>
typename GraphT::NodeType*
Eval(DominatorTreeBase<typename GraphT::NodeType>& DT,
typename GraphT::NodeType *V) {
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &VInfo =
DT.Info[V];
#if !BALANCE_IDOM_TREE
// Higher-complexity but faster implementation
if (VInfo.Ancestor == 0)
return V;
Compress<GraphT>(DT, V);
return VInfo.Label;
#else
// Lower-complexity but slower implementation
if (VInfo.Ancestor == 0)
return VInfo.Label;
Compress<GraphT>(DT, V);
GraphT::NodeType* VLabel = VInfo.Label;
GraphT::NodeType* VAncestorLabel = DT.Info[VInfo.Ancestor].Label;
if (DT.Info[VAncestorLabel].Semi >= DT.Info[VLabel].Semi)
return VLabel;
else
return VAncestorLabel;
#endif
}
template<class GraphT>
void Link(DominatorTreeBase<typename GraphT::NodeType>& DT,
unsigned DFSNumV, typename GraphT::NodeType* W,
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &WInfo) {
#if !BALANCE_IDOM_TREE
// Higher-complexity but faster implementation
WInfo.Ancestor = DFSNumV;
#else
// Lower-complexity but slower implementation
GraphT::NodeType* WLabel = WInfo.Label;
unsigned WLabelSemi = DT.Info[WLabel].Semi;
GraphT::NodeType* S = W;
InfoRec *SInfo = &DT.Info[S];
GraphT::NodeType* SChild = SInfo->Child;
InfoRec *SChildInfo = &DT.Info[SChild];
while (WLabelSemi < DT.Info[SChildInfo->Label].Semi) {
GraphT::NodeType* SChildChild = SChildInfo->Child;
if (SInfo->Size+DT.Info[SChildChild].Size >= 2*SChildInfo->Size) {
SChildInfo->Ancestor = S;
SInfo->Child = SChild = SChildChild;
SChildInfo = &DT.Info[SChild];
} else {
SChildInfo->Size = SInfo->Size;
S = SInfo->Ancestor = SChild;
SInfo = SChildInfo;
SChild = SChildChild;
SChildInfo = &DT.Info[SChild];
}
VInfo.Parent = VAInfo.Parent;
}
DominatorTreeBase::InfoRec &VInfo = DT.Info[V];
SInfo->Label = WLabel;
assert(V != W && "The optimization here will not work in this case!");
unsigned WSize = WInfo.Size;
unsigned VSize = (VInfo.Size += WSize);
if (VSize < 2*WSize)
std::swap(S, VInfo.Child);
while (S) {
SInfo = &DT.Info[S];
SInfo->Ancestor = V;
S = SInfo->Child;
}
#endif
return VInInfo.Label;
}
template<class FuncT, class NodeT>
@ -242,9 +161,6 @@ void Calculate(DominatorTreeBase<typename GraphTraits<NodeT>::NodeType>& DT,
BBInfo.Label = NULL;
DT.Vertex.push_back(NULL); // Vertex[n] = V;
//BBInfo[V].Ancestor = 0; // Ancestor[n] = 0
//BBInfo[V].Child = 0; // Child[v] = 0
BBInfo.Size = 1; // Size[v] = 1
}
// Step #1: Number blocks in depth-first order and initialize variables used
@ -257,12 +173,34 @@ void Calculate(DominatorTreeBase<typename GraphTraits<NodeT>::NodeType>& DT,
// infinite loops). In these cases an artificial exit node is required.
MultipleRoots |= (DT.isPostDominator() && N != F.size());
// When naively implemented, the Lengauer-Tarjan algorithm requires a separate
// bucket for each vertex. However, this is unnecessary, because each vertex
// is only placed into a single bucket (that of its semidominator), and each
// vertex's bucket is processed before it is added to any bucket itself.
//
// Instead of using a bucket per vertex, we use a single array Buckets that
// has two purposes. Before the vertex V with preorder number i is processed,
// Buckets[i] stores the index of the first element in V's bucket. After V's
// bucket is processed, Buckets[i] stores the index of the next element in the
// bucket containing V, if any.
SmallVector<unsigned, 32> Buckets;
Buckets.resize(N + 1);
for (unsigned i = 1; i <= N; ++i)
Buckets[i] = i;
for (unsigned i = N; i >= 2; --i) {
typename GraphT::NodeType* W = DT.Vertex[i];
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &WInfo =
DT.Info[W];
// Step #2: Calculate the semidominators of all vertices
// Step #2: Implicitly define the immediate dominator of vertices
for (unsigned j = i; Buckets[j] != i; j = Buckets[j]) {
typename GraphT::NodeType* V = DT.Vertex[Buckets[j]];
typename GraphT::NodeType* U = Eval<GraphT>(DT, V, i + 1);
DT.IDoms[V] = DT.Info[U].Semi < i ? U : W;
}
// Step #3: Calculate the semidominators of all vertices
// initialize the semi dominator to point to the parent node
WInfo.Semi = WInfo.Parent;
@ -272,25 +210,28 @@ void Calculate(DominatorTreeBase<typename GraphTraits<NodeT>::NodeType>& DT,
E = InvTraits::child_end(W); CI != E; ++CI) {
typename InvTraits::NodeType *N = *CI;
if (DT.Info.count(N)) { // Only if this predecessor is reachable!
unsigned SemiU = DT.Info[Eval<GraphT>(DT, N)].Semi;
unsigned SemiU = DT.Info[Eval<GraphT>(DT, N, i + 1)].Semi;
if (SemiU < WInfo.Semi)
WInfo.Semi = SemiU;
}
}
DT.Info[DT.Vertex[WInfo.Semi]].Bucket.push_back(W);
// If V is a non-root vertex and sdom(V) = parent(V), then idom(V) is
// necessarily parent(V). In this case, set idom(V) here and avoid placing
// V into a bucket.
if (WInfo.Semi == WInfo.Parent) {
DT.IDoms[W] = DT.Vertex[WInfo.Parent];
} else {
Buckets[i] = Buckets[WInfo.Semi];
Buckets[WInfo.Semi] = i;
}
}
typename GraphT::NodeType* WParent = DT.Vertex[WInfo.Parent];
Link<GraphT>(DT, WInfo.Parent, W, WInfo);
// Step #3: Implicitly define the immediate dominator of vertices
std::vector<typename GraphT::NodeType*> &WParentBucket =
DT.Info[WParent].Bucket;
while (!WParentBucket.empty()) {
typename GraphT::NodeType* V = WParentBucket.back();
WParentBucket.pop_back();
typename GraphT::NodeType* U = Eval<GraphT>(DT, V);
DT.IDoms[V] = DT.Info[U].Semi < DT.Info[V].Semi ? U : WParent;
if (N >= 1) {
typename GraphT::NodeType* Root = DT.Vertex[1];
for (unsigned j = 1; Buckets[j] != 1; j = Buckets[j]) {
typename GraphT::NodeType* V = DT.Vertex[Buckets[j]];
DT.IDoms[V] = Root;
}
}

View File

@ -7,14 +7,8 @@
//
//===----------------------------------------------------------------------===//
//
// This file defines the following classes:
// 1. DominatorTree: Represent dominators as an explicit tree structure.
// 2. DominanceFrontier: Calculate and hold the dominance frontier for a
// function.
//
// These data structures are listed in increasing order of complexity. It
// takes longer to calculate the dominator frontier, for example, than the
// DominatorTree mapping.
// This file defines the DominatorTree class, which provides fast and efficient
// dominance queries.
//
//===----------------------------------------------------------------------===//
@ -23,19 +17,15 @@
#include "llvm/Pass.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <map>
#include <set>
namespace llvm {
@ -205,15 +195,11 @@ protected:
// Information record used during immediate dominators computation.
struct InfoRec {
unsigned DFSNum;
unsigned Parent;
unsigned Semi;
unsigned Size;
NodeT *Label, *Child;
unsigned Parent, Ancestor;
NodeT *Label;
std::vector<NodeT*> Bucket;
InfoRec() : DFSNum(0), Semi(0), Size(0), Label(0), Child(0), Parent(0),
Ancestor(0) {}
InfoRec() : DFSNum(0), Parent(0), Semi(0), Label(0) {}
};
DenseMap<NodeT*, NodeT*> IDoms;
@ -303,9 +289,6 @@ public:
: DominatorBase<NodeT>(isPostDom), DFSInfoValid(false), SlowQueries(0) {}
virtual ~DominatorTreeBase() { reset(); }
// FIXME: Should remove this
virtual bool runOnFunction(Function &F) { return false; }
/// compare - Return false if the other dominator tree base matches this
/// dominator tree base. Otherwise return true.
bool compare(DominatorTreeBase &Other) const {
@ -361,8 +344,15 @@ public:
return dominatedBySlowTreeWalk(A, B);
}
inline bool properlyDominates(NodeT *A, NodeT *B) {
return properlyDominates(getNode(A), getNode(B));
inline bool properlyDominates(const NodeT *A, const NodeT *B) {
if (A == B)
return false;
// Cast away the const qualifiers here. This is ok since
// this function doesn't actually return the values returned
// from getNode.
return properlyDominates(getNode(const_cast<NodeT *>(A)),
getNode(const_cast<NodeT *>(B)));
}
bool dominatedBySlowTreeWalk(const DomTreeNodeBase<NodeT> *A,
@ -377,7 +367,7 @@ public:
/// isReachableFromEntry - Return true if A is dominated by the entry
/// block of the function containing it.
bool isReachableFromEntry(NodeT* A) {
bool isReachableFromEntry(const NodeT* A) {
assert(!this->isPostDominator() &&
"This is not implemented for post dominators");
return dominates(&A->getParent()->front(), A);
@ -478,6 +468,13 @@ public:
return NULL;
}
const NodeT *findNearestCommonDominator(const NodeT *A, const NodeT *B) {
// Cast away the const qualifiers here. This is ok since
// const is re-introduced on the return type.
return findNearestCommonDominator(const_cast<NodeT *>(A),
const_cast<NodeT *>(B));
}
//===--------------------------------------------------------------------===//
// API to update (Post)DominatorTree information based on modifications to
// the CFG...
@ -509,7 +506,7 @@ public:
}
/// eraseNode - Removes a node from the dominator tree. Block must not
/// domiante any other blocks. Removes node from its immediate dominator's
/// dominate any other blocks. Removes node from its immediate dominator's
/// children list. Deletes dominator node associated with basic block BB.
void eraseNode(NodeT *BB) {
DomTreeNodeBase<NodeT> *Node = getNode(BB);
@ -556,7 +553,7 @@ public:
o << "Inorder PostDominator Tree: ";
else
o << "Inorder Dominator Tree: ";
if (this->DFSInfoValid)
if (!this->DFSInfoValid)
o << "DFSNumbers invalid: " << SlowQueries << " slow queries.";
o << "\n";
@ -566,19 +563,11 @@ public:
}
protected:
template<class GraphT>
friend void Compress(DominatorTreeBase<typename GraphT::NodeType>& DT,
typename GraphT::NodeType* VIn);
template<class GraphT>
friend typename GraphT::NodeType* Eval(
DominatorTreeBase<typename GraphT::NodeType>& DT,
typename GraphT::NodeType* V);
template<class GraphT>
friend void Link(DominatorTreeBase<typename GraphT::NodeType>& DT,
unsigned DFSNumV, typename GraphT::NodeType* W,
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &WInfo);
typename GraphT::NodeType* V,
unsigned LastLinked);
template<class GraphT>
friend unsigned DFSPass(DominatorTreeBase<typename GraphT::NodeType>& DT,
@ -703,6 +692,7 @@ public:
DominatorTreeBase<BasicBlock>* DT;
DominatorTree() : FunctionPass(ID) {
initializeDominatorTreePass(*PassRegistry::getPassRegistry());
DT = new DominatorTreeBase<BasicBlock>(false);
}
@ -751,7 +741,7 @@ public:
AU.setPreservesAll();
}
inline bool dominates(DomTreeNode* A, DomTreeNode* B) const {
inline bool dominates(const DomTreeNode* A, const DomTreeNode* B) const {
return DT->dominates(A, B);
}
@ -767,7 +757,7 @@ public:
return DT->properlyDominates(A, B);
}
bool properlyDominates(BasicBlock *A, BasicBlock *B) const {
bool properlyDominates(const BasicBlock *A, const BasicBlock *B) const {
return DT->properlyDominates(A, B);
}
@ -777,6 +767,11 @@ public:
return DT->findNearestCommonDominator(A, B);
}
inline const BasicBlock *findNearestCommonDominator(const BasicBlock *A,
const BasicBlock *B) {
return DT->findNearestCommonDominator(A, B);
}
inline DomTreeNode *operator[](BasicBlock *BB) const {
return DT->getNode(BB);
}
@ -807,7 +802,7 @@ public:
}
/// eraseNode - Removes a node from the dominator tree. Block must not
/// domiante any other blocks. Removes node from its immediate dominator's
/// dominate any other blocks. Removes node from its immediate dominator's
/// children list. Deletes dominator node associated with basic block BB.
inline void eraseNode(BasicBlock *BB) {
DT->eraseNode(BB);
@ -819,7 +814,7 @@ public:
DT->splitBlock(NewBB);
}
bool isReachableFromEntry(BasicBlock* A) {
bool isReachableFromEntry(const BasicBlock* A) {
return DT->isReachableFromEntry(A);
}
@ -876,194 +871,6 @@ template <> struct GraphTraits<DominatorTree*>
};
//===----------------------------------------------------------------------===//
/// DominanceFrontierBase - Common base class for computing forward and inverse
/// dominance frontiers for a function.
///
class DominanceFrontierBase : public FunctionPass {
public:
typedef std::set<BasicBlock*> DomSetType; // Dom set for a bb
typedef std::map<BasicBlock*, DomSetType> DomSetMapType; // Dom set map
protected:
DomSetMapType Frontiers;
std::vector<BasicBlock*> Roots;
const bool IsPostDominators;
public:
DominanceFrontierBase(char &ID, bool isPostDom)
: FunctionPass(ID), IsPostDominators(isPostDom) {}
/// getRoots - Return the root blocks of the current CFG. This may include
/// multiple blocks if we are computing post dominators. For forward
/// dominators, this will always be a single block (the entry node).
///
inline const std::vector<BasicBlock*> &getRoots() const { return Roots; }
/// isPostDominator - Returns true if analysis based of postdoms
///
bool isPostDominator() const { return IsPostDominators; }
virtual void releaseMemory() { Frontiers.clear(); }
// Accessor interface:
typedef DomSetMapType::iterator iterator;
typedef DomSetMapType::const_iterator const_iterator;
iterator begin() { return Frontiers.begin(); }
const_iterator begin() const { return Frontiers.begin(); }
iterator end() { return Frontiers.end(); }
const_iterator end() const { return Frontiers.end(); }
iterator find(BasicBlock *B) { return Frontiers.find(B); }
const_iterator find(BasicBlock *B) const { return Frontiers.find(B); }
iterator addBasicBlock(BasicBlock *BB, const DomSetType &frontier) {
assert(find(BB) == end() && "Block already in DominanceFrontier!");
return Frontiers.insert(std::make_pair(BB, frontier)).first;
}
/// removeBlock - Remove basic block BB's frontier.
void removeBlock(BasicBlock *BB) {
assert(find(BB) != end() && "Block is not in DominanceFrontier!");
for (iterator I = begin(), E = end(); I != E; ++I)
I->second.erase(BB);
Frontiers.erase(BB);
}
void addToFrontier(iterator I, BasicBlock *Node) {
assert(I != end() && "BB is not in DominanceFrontier!");
I->second.insert(Node);
}
void removeFromFrontier(iterator I, BasicBlock *Node) {
assert(I != end() && "BB is not in DominanceFrontier!");
assert(I->second.count(Node) && "Node is not in DominanceFrontier of BB");
I->second.erase(Node);
}
/// compareDomSet - Return false if two domsets match. Otherwise
/// return true;
bool compareDomSet(DomSetType &DS1, const DomSetType &DS2) const {
std::set<BasicBlock *> tmpSet;
for (DomSetType::const_iterator I = DS2.begin(),
E = DS2.end(); I != E; ++I)
tmpSet.insert(*I);
for (DomSetType::const_iterator I = DS1.begin(),
E = DS1.end(); I != E; ) {
BasicBlock *Node = *I++;
if (tmpSet.erase(Node) == 0)
// Node is in DS1 but not in DS2.
return true;
}
if (!tmpSet.empty())
// There are nodes that are in DS2 but not in DS1.
return true;
// DS1 and DS2 matches.
return false;
}
/// compare - Return true if the other dominance frontier base matches
/// this dominance frontier base. Otherwise return false.
bool compare(DominanceFrontierBase &Other) const {
DomSetMapType tmpFrontiers;
for (DomSetMapType::const_iterator I = Other.begin(),
E = Other.end(); I != E; ++I)
tmpFrontiers.insert(std::make_pair(I->first, I->second));
for (DomSetMapType::iterator I = tmpFrontiers.begin(),
E = tmpFrontiers.end(); I != E; ) {
BasicBlock *Node = I->first;
const_iterator DFI = find(Node);
if (DFI == end())
return true;
if (compareDomSet(I->second, DFI->second))
return true;
++I;
tmpFrontiers.erase(Node);
}
if (!tmpFrontiers.empty())
return true;
return false;
}
/// print - Convert to human readable form
///
virtual void print(raw_ostream &OS, const Module* = 0) const;
/// dump - Dump the dominance frontier to dbgs().
void dump() const;
};
//===-------------------------------------
/// DominanceFrontier Class - Concrete subclass of DominanceFrontierBase that is
/// used to compute a forward dominator frontiers.
///
class DominanceFrontier : public DominanceFrontierBase {
public:
static char ID; // Pass ID, replacement for typeid
DominanceFrontier() :
DominanceFrontierBase(ID, false) {}
BasicBlock *getRoot() const {
assert(Roots.size() == 1 && "Should always have entry node!");
return Roots[0];
}
virtual bool runOnFunction(Function &) {
Frontiers.clear();
DominatorTree &DT = getAnalysis<DominatorTree>();
Roots = DT.getRoots();
assert(Roots.size() == 1 && "Only one entry block for forward domfronts!");
calculate(DT, DT[Roots[0]]);
return false;
}
virtual void verifyAnalysis() const;
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
AU.addRequired<DominatorTree>();
}
/// splitBlock - BB is split and now it has one successor. Update dominance
/// frontier to reflect this change.
void splitBlock(BasicBlock *BB);
/// BasicBlock BB's new dominator is NewBB. Update BB's dominance frontier
/// to reflect this change.
void changeImmediateDominator(BasicBlock *BB, BasicBlock *NewBB,
DominatorTree *DT) {
// NewBB is now dominating BB. Which means BB's dominance
// frontier is now part of NewBB's dominance frontier. However, BB
// itself is not member of NewBB's dominance frontier.
DominanceFrontier::iterator NewDFI = find(NewBB);
DominanceFrontier::iterator DFI = find(BB);
// If BB was an entry block then its frontier is empty.
if (DFI == end())
return;
DominanceFrontier::DomSetType BBSet = DFI->second;
for (DominanceFrontier::DomSetType::iterator BBSetI = BBSet.begin(),
BBSetE = BBSet.end(); BBSetI != BBSetE; ++BBSetI) {
BasicBlock *DFMember = *BBSetI;
// Insert only if NewBB dominates DFMember.
if (!DT->dominates(NewBB, DFMember))
NewDFI->second.insert(DFMember);
}
NewDFI->second.erase(BB);
}
const DomSetType &calculate(const DominatorTree &DT,
const DomTreeNode *Node);
};
} // End llvm namespace
#endif

View File

@ -26,7 +26,9 @@ class FindUsedTypes : public ModulePass {
std::set<const Type *> UsedTypes;
public:
static char ID; // Pass identification, replacement for typeid
FindUsedTypes() : ModulePass(ID) {}
FindUsedTypes() : ModulePass(ID) {
initializeFindUsedTypesPass(*PassRegistry::getPassRegistry());
}
/// getTypes - After the pass has been run, return the set containing all of
/// the types used in the module.

View File

@ -33,7 +33,7 @@ namespace llvm {
namespace InlineConstants {
// Various magic constants used to adjust heuristics.
const int InstrCost = 5;
const int IndirectCallBonus = 500;
const int IndirectCallBonus = -100;
const int CallPenalty = 25;
const int LastCallToStaticBonus = -15000;
const int ColdccPenalty = 2000;
@ -98,7 +98,8 @@ namespace llvm {
unsigned AllocaWeight;
ArgInfo(unsigned CWeight, unsigned AWeight)
: ConstantWeight(CWeight), AllocaWeight(AWeight) {}
: ConstantWeight(CWeight), AllocaWeight(AWeight)
{}
};
struct FunctionInfo {
@ -110,17 +111,6 @@ namespace llvm {
/// entry here.
std::vector<ArgInfo> ArgumentWeights;
/// CountCodeReductionForConstant - Figure out an approximation for how
/// many instructions will be constant folded if the specified value is
/// constant.
unsigned CountCodeReductionForConstant(Value *V);
/// CountCodeReductionForAlloca - Figure out an approximation of how much
/// smaller the function will be if it is inlined into a context where an
/// argument becomes an alloca.
///
unsigned CountCodeReductionForAlloca(Value *V);
/// analyzeFunction - Add information about the specified function
/// to the current structure.
void analyzeFunction(Function *F);
@ -134,6 +124,10 @@ namespace llvm {
// the ValueMap will update itself when this happens.
ValueMap<const Function *, FunctionInfo> CachedFunctionInfo;
int CountBonusForConstant(Value *V, Constant *C = NULL);
int ConstantFunctionBonus(CallSite CS, Constant *C);
int getInlineSize(CallSite CS, Function *Callee);
int getInlineBonuses(CallSite CS, Function *Callee);
public:
/// getInlineCost - The heuristic used to determine if we should inline the
@ -150,6 +144,18 @@ namespace llvm {
Function *Callee,
SmallPtrSet<const Function *, 16> &NeverInline);
/// getSpecializationBonus - The heuristic used to determine the per-call
/// performance boost for using a specialization of Callee with argument
/// SpecializedArgNos replaced by a constant.
int getSpecializationBonus(Function *Callee,
SmallVectorImpl<unsigned> &SpecializedArgNo);
/// getSpecializationCost - The heuristic used to determine the code-size
/// impact of creating a specialized version of Callee with argument
/// SpecializedArgNo replaced by a constant.
InlineCost getSpecializationCost(Function *Callee,
SmallVectorImpl<unsigned> &SpecializedArgNo);
/// getInlineFudgeFactor - Return a > 1.0 factor if the inliner should use a
/// higher threshold to determine if the function call should be inlined.
float getInlineFudgeFactor(CallSite CS);

View File

@ -7,9 +7,12 @@
//
//===----------------------------------------------------------------------===//
//
// This file declares routines for folding instructions into simpler forms that
// do not require creating new instructions. For example, this does constant
// folding, and can handle identities like (X&0)->0.
// This file declares routines for folding instructions into simpler forms
// that do not require creating new instructions. This does constant folding
// ("add i32 1, 1" -> "2") but can also handle non-constant operands, either
// returning a constant ("and i32 %x, 0" -> "0") or an already existing value
// ("and i32 %x, %x" -> "%x"). If the simplification is also an instruction
// then it dominates the original instruction.
//
//===----------------------------------------------------------------------===//
@ -17,6 +20,7 @@
#define LLVM_ANALYSIS_INSTRUCTIONSIMPLIFY_H
namespace llvm {
class DominatorTree;
class Instruction;
class Value;
class TargetData;
@ -24,56 +28,106 @@ namespace llvm {
/// SimplifyAddInst - Given operands for an Add, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyAddInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW,
const TargetData *TD = 0);
const TargetData *TD = 0, const DominatorTree *DT = 0);
/// SimplifySubInst - Given operands for a Sub, see if we can
/// fold the result. If not, this returns null.
Value *SimplifySubInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW,
const TargetData *TD = 0, const DominatorTree *DT = 0);
/// SimplifyMulInst - Given operands for a Mul, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyMulInst(Value *LHS, Value *RHS, const TargetData *TD = 0,
const DominatorTree *DT = 0);
/// SimplifySDivInst - Given operands for an SDiv, see if we can
/// fold the result. If not, this returns null.
Value *SimplifySDivInst(Value *LHS, Value *RHS, const TargetData *TD = 0,
const DominatorTree *DT = 0);
/// SimplifyUDivInst - Given operands for a UDiv, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyUDivInst(Value *LHS, Value *RHS, const TargetData *TD = 0,
const DominatorTree *DT = 0);
/// SimplifyFDivInst - Given operands for an FDiv, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyFDivInst(Value *LHS, Value *RHS, const TargetData *TD = 0,
const DominatorTree *DT = 0);
/// SimplifyShlInst - Given operands for a Shl, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
const TargetData *TD = 0, const DominatorTree *DT = 0);
/// SimplifyLShrInst - Given operands for a LShr, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact,
const TargetData *TD = 0, const DominatorTree *DT=0);
/// SimplifyAShrInst - Given operands for a AShr, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact,
const TargetData *TD = 0,
const DominatorTree *DT = 0);
/// SimplifyAndInst - Given operands for an And, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyAndInst(Value *LHS, Value *RHS,
const TargetData *TD = 0);
Value *SimplifyAndInst(Value *LHS, Value *RHS, const TargetData *TD = 0,
const DominatorTree *DT = 0);
/// SimplifyOrInst - Given operands for an Or, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyOrInst(Value *LHS, Value *RHS,
const TargetData *TD = 0);
Value *SimplifyOrInst(Value *LHS, Value *RHS, const TargetData *TD = 0,
const DominatorTree *DT = 0);
/// SimplifyXorInst - Given operands for a Xor, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyXorInst(Value *LHS, Value *RHS, const TargetData *TD = 0,
const DominatorTree *DT = 0);
/// SimplifyICmpInst - Given operands for an ICmpInst, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
const TargetData *TD = 0);
const TargetData *TD = 0,
const DominatorTree *DT = 0);
/// SimplifyFCmpInst - Given operands for an FCmpInst, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
const TargetData *TD = 0);
const TargetData *TD = 0,
const DominatorTree *DT = 0);
/// SimplifySelectInst - Given operands for a SelectInst, see if we can fold
/// the result. If not, this returns null.
Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
const TargetData *TD = 0);
const TargetData *TD = 0,
const DominatorTree *DT = 0);
/// SimplifyGEPInst - Given operands for an GetElementPtrInst, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyGEPInst(Value * const *Ops, unsigned NumOps,
const TargetData *TD = 0);
const TargetData *TD = 0, const DominatorTree *DT = 0);
//=== Helper functions for higher up the class hierarchy.
/// SimplifyCmpInst - Given operands for a CmpInst, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
const TargetData *TD = 0);
const TargetData *TD = 0, const DominatorTree *DT = 0);
/// SimplifyBinOp - Given operands for a BinaryOperator, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS,
const TargetData *TD = 0);
Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS,
const TargetData *TD = 0, const DominatorTree *DT = 0);
/// SimplifyInstruction - See if we can compute a simplified version of this
/// instruction. If not, this returns null.
Value *SimplifyInstruction(Instruction *I, const TargetData *TD = 0);
Value *SimplifyInstruction(Instruction *I, const TargetData *TD = 0,
const DominatorTree *DT = 0);
/// ReplaceAndSimplifyAllUses - Perform From->replaceAllUsesWith(To) and then
/// delete the From instruction. In addition to a basic RAUW, this does a
/// recursive simplification of the updated instructions. This catches
@ -81,7 +135,8 @@ namespace llvm {
/// simplifies and deletes scalar operations, it does not change the CFG.
///
void ReplaceAndSimplifyAllUses(Instruction *From, Value *To,
const TargetData *TD = 0);
const TargetData *TD = 0,
const DominatorTree *DT = 0);
} // end namespace llvm
#endif

View File

@ -48,7 +48,9 @@ class IntervalPartition : public FunctionPass {
public:
static char ID; // Pass identification, replacement for typeid
IntervalPartition() : FunctionPass(ID), RootInterval(0) {}
IntervalPartition() : FunctionPass(ID), RootInterval(0) {
initializeIntervalPartitionPass(*PassRegistry::getPassRegistry());
}
// run - Calculate the interval partition for this function
virtual bool runOnFunction(Function &F);

View File

@ -31,7 +31,9 @@ class LazyValueInfo : public FunctionPass {
void operator=(const LazyValueInfo&); // DO NOT IMPLEMENT.
public:
static char ID;
LazyValueInfo() : FunctionPass(ID), PImpl(0) {}
LazyValueInfo() : FunctionPass(ID), PImpl(0) {
initializeLazyValueInfoPass(*PassRegistry::getPassRegistry());
}
~LazyValueInfo() { assert(PImpl == 0 && "releaseMemory not called"); }
/// Tristate - This is used to return true/false/dunno results.

View File

@ -28,15 +28,17 @@ namespace llvm {
LibCallInfo *LCI;
explicit LibCallAliasAnalysis(LibCallInfo *LC = 0)
: FunctionPass(ID), LCI(LC) {
: FunctionPass(ID), LCI(LC) {
initializeLibCallAliasAnalysisPass(*PassRegistry::getPassRegistry());
}
explicit LibCallAliasAnalysis(char &ID, LibCallInfo *LC)
: FunctionPass(ID), LCI(LC) {
: FunctionPass(ID), LCI(LC) {
initializeLibCallAliasAnalysisPass(*PassRegistry::getPassRegistry());
}
~LibCallAliasAnalysis();
ModRefResult getModRefInfo(ImmutableCallSite CS,
const Value *P, unsigned Size);
const Location &Loc);
ModRefResult getModRefInfo(ImmutableCallSite CS1,
ImmutableCallSite CS2) {
@ -64,7 +66,7 @@ namespace llvm {
private:
ModRefResult AnalyzeLibCallDetails(const LibCallFunctionInfo *FI,
ImmutableCallSite CS,
const Value *P, unsigned Size);
const Location &Loc);
};
} // End of llvm namespace

View File

@ -48,7 +48,7 @@ namespace llvm {
Yes, No, Unknown
};
LocResult (*isLocation)(ImmutableCallSite CS,
const Value *Ptr, unsigned Size);
const AliasAnalysis::Location &Loc);
};
/// LibCallFunctionInfo - Each record in the array of FunctionInfo structs

View File

@ -91,7 +91,9 @@ class LoopDependenceAnalysis : public LoopPass {
public:
static char ID; // Class identification, replacement for typeinfo
LoopDependenceAnalysis() : LoopPass(ID) {}
LoopDependenceAnalysis() : LoopPass(ID) {
initializeLoopDependenceAnalysisPass(*PassRegistry::getPassRegistry());
}
/// isDependencePair - Check whether two values can possibly give rise to
/// a data dependence: that is the case if both are instructions accessing

View File

@ -32,6 +32,7 @@
#define LLVM_ANALYSIS_LOOP_INFO_H
#include "llvm/Pass.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/SmallVector.h"
@ -40,6 +41,7 @@
#include "llvm/Support/CFG.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <map>
namespace llvm {
@ -53,6 +55,7 @@ static void RemoveFromVector(std::vector<T*> &V, T *N) {
class DominatorTree;
class LoopInfo;
class Loop;
class PHINode;
template<class N, class M> class LoopInfoBase;
template<class N, class M> class LoopBase;
@ -523,10 +526,9 @@ public:
///
bool isLoopInvariant(Value *V) const;
/// isLoopInvariant - Return true if the specified instruction is
/// loop-invariant.
///
bool isLoopInvariant(Instruction *I) const;
/// hasLoopInvariantOperands - Return true if all the operands of the
/// specified instruction are loop invariant.
bool hasLoopInvariantOperands(Instruction *I) const;
/// makeLoopInvariant - If the given value is an instruction inside of the
/// loop and it can be hoisted, do so to make it trivially loop-invariant.
@ -630,7 +632,7 @@ private:
template<class BlockT, class LoopT>
class LoopInfoBase {
// BBMap - Mapping of basic blocks to the inner most loop they occur in
std::map<BlockT *, LoopT *> BBMap;
DenseMap<BlockT *, LoopT *> BBMap;
std::vector<LoopT *> TopLevelLoops;
friend class LoopBase<BlockT, LoopT>;
@ -661,7 +663,7 @@ public:
/// block is in no loop (for example the entry node), null is returned.
///
LoopT *getLoopFor(const BlockT *BB) const {
typename std::map<BlockT *, LoopT *>::const_iterator I=
typename DenseMap<BlockT *, LoopT *>::const_iterator I=
BBMap.find(const_cast<BlockT*>(BB));
return I != BBMap.end() ? I->second : 0;
}
@ -729,7 +731,7 @@ public:
/// including all of the Loop objects it is nested in and our mapping from
/// BasicBlocks to loops.
void removeBlock(BlockT *BB) {
typename std::map<BlockT *, LoopT *>::iterator I = BBMap.find(BB);
typename DenseMap<BlockT *, LoopT *>::iterator I = BBMap.find(BB);
if (I != BBMap.end()) {
for (LoopT *L = I->second; L; L = L->getParentLoop())
L->removeBlockFromLoop(BB);
@ -923,7 +925,7 @@ public:
for (unsigned i = 0; i < TopLevelLoops.size(); ++i)
TopLevelLoops[i]->print(OS);
#if 0
for (std::map<BasicBlock*, LoopT*>::const_iterator I = BBMap.begin(),
for (DenseMap<BasicBlock*, LoopT*>::const_iterator I = BBMap.begin(),
E = BBMap.end(); I != E; ++I)
OS << "BB '" << I->first->getName() << "' level = "
<< I->second->getLoopDepth() << "\n";
@ -940,7 +942,9 @@ class LoopInfo : public FunctionPass {
public:
static char ID; // Pass identification, replacement for typeid
LoopInfo() : FunctionPass(ID) {}
LoopInfo() : FunctionPass(ID) {
initializeLoopInfoPass(*PassRegistry::getPassRegistry());
}
LoopInfoBase<BasicBlock, Loop>& getBase() { return LI; }
@ -1019,6 +1023,27 @@ public:
void removeBlock(BasicBlock *BB) {
LI.removeBlock(BB);
}
/// replacementPreservesLCSSAForm - Returns true if replacing From with To
/// everywhere is guaranteed to preserve LCSSA form.
bool replacementPreservesLCSSAForm(Instruction *From, Value *To) {
// Preserving LCSSA form is only problematic if the replacing value is an
// instruction.
Instruction *I = dyn_cast<Instruction>(To);
if (!I) return true;
// If both instructions are defined in the same basic block then replacement
// cannot break LCSSA form.
if (I->getParent() == From->getParent())
return true;
// If the instruction is not defined in a loop then it can safely replace
// anything.
Loop *ToLoop = getLoopFor(I->getParent());
if (!ToLoop) return true;
// If the replacing instruction is defined in the same loop as the original
// instruction, or in a loop that contains it as an inner loop, then using
// it as a replacement will not break LCSSA form.
return ToLoop->contains(getLoopFor(From->getParent()));
}
};

View File

@ -74,6 +74,10 @@ Value *getMallocArraySize(CallInst *CI, const TargetData *TD,
/// isFreeCall - Returns non-null if the value is a call to the builtin free()
const CallInst *isFreeCall(const Value *I);
static inline CallInst *isFreeCall(Value *I) {
return const_cast<CallInst*>(isFreeCall((const Value*)I));
}
} // End llvm namespace

View File

@ -17,6 +17,7 @@
#include "llvm/BasicBlock.h"
#include "llvm/Pass.h"
#include "llvm/Support/ValueHandle.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/OwningPtr.h"
@ -46,6 +47,9 @@ namespace llvm {
/// pair holds the instruction that clobbers the memory. For example,
/// this occurs when we see a may-aliased store to the memory location we
/// care about.
///
/// A dependence query on the first instruction of the entry block will
/// return a clobber(self) result.
Clobber,
/// Def - This is a dependence on the specified instruction which
@ -132,37 +136,6 @@ namespace llvm {
}
};
/// NonLocalDepResult - This is a result from a NonLocal dependence query.
/// For each BasicBlock (the BB entry) it keeps a MemDepResult and the
/// (potentially phi translated) address that was live in the block.
class NonLocalDepResult {
BasicBlock *BB;
MemDepResult Result;
Value *Address;
public:
NonLocalDepResult(BasicBlock *bb, MemDepResult result, Value *address)
: BB(bb), Result(result), Address(address) {}
// BB is the sort key, it can't be changed.
BasicBlock *getBB() const { return BB; }
void setResult(const MemDepResult &R, Value *Addr) {
Result = R;
Address = Addr;
}
const MemDepResult &getResult() const { return Result; }
/// getAddress - Return the address of this pointer in this block. This can
/// be different than the address queried for the non-local result because
/// of phi translation. This returns null if the address was not available
/// in a block (i.e. because phi translation failed) or if this is a cached
/// result and that address was deleted.
///
/// The address is always null for a non-local 'call' dependence.
Value *getAddress() const { return Address; }
};
/// NonLocalDepEntry - This is an entry in the NonLocalDepInfo cache. For
/// each BasicBlock (the BB entry) it keeps a MemDepResult.
class NonLocalDepEntry {
@ -187,6 +160,36 @@ namespace llvm {
}
};
/// NonLocalDepResult - This is a result from a NonLocal dependence query.
/// For each BasicBlock (the BB entry) it keeps a MemDepResult and the
/// (potentially phi translated) address that was live in the block.
class NonLocalDepResult {
NonLocalDepEntry Entry;
Value *Address;
public:
NonLocalDepResult(BasicBlock *bb, MemDepResult result, Value *address)
: Entry(bb, result), Address(address) {}
// BB is the sort key, it can't be changed.
BasicBlock *getBB() const { return Entry.getBB(); }
void setResult(const MemDepResult &R, Value *Addr) {
Entry.setResult(R);
Address = Addr;
}
const MemDepResult &getResult() const { return Entry.getResult(); }
/// getAddress - Return the address of this pointer in this block. This can
/// be different than the address queried for the non-local result because
/// of phi translation. This returns null if the address was not available
/// in a block (i.e. because phi translation failed) or if this is a cached
/// result and that address was deleted.
///
/// The address is always null for a non-local 'call' dependence.
Value *getAddress() const { return Address; }
};
/// MemoryDependenceAnalysis - This is an analysis that determines, for a
/// given memory operation, what preceding memory operations it depends on.
/// It builds on alias analysis information, and tries to provide a lazy,
@ -212,7 +215,7 @@ namespace llvm {
private:
/// ValueIsLoadPair - This is a pair<Value*, bool> where the bool is true if
/// the dependence is a read only dependence, false if read/write.
typedef PointerIntPair<Value*, 1, bool> ValueIsLoadPair;
typedef PointerIntPair<const Value*, 1, bool> ValueIsLoadPair;
/// BBSkipFirstBlockPair - This pair is used when caching information for a
/// block. If the pointer is null, the cache value is not a full query that
@ -220,11 +223,28 @@ namespace llvm {
/// or not the contents of the block was skipped.
typedef PointerIntPair<BasicBlock*, 1, bool> BBSkipFirstBlockPair;
/// NonLocalPointerInfo - This record is the information kept for each
/// (value, is load) pair.
struct NonLocalPointerInfo {
/// Pair - The pair of the block and the skip-first-block flag.
BBSkipFirstBlockPair Pair;
/// NonLocalDeps - The results of the query for each relevant block.
NonLocalDepInfo NonLocalDeps;
/// Size - The maximum size of the dereferences of the
/// pointer. May be UnknownSize if the sizes are unknown.
uint64_t Size;
/// TBAATag - The TBAA tag associated with dereferences of the
/// pointer. May be null if there are no tags or conflicting tags.
const MDNode *TBAATag;
NonLocalPointerInfo() : Size(AliasAnalysis::UnknownSize), TBAATag(0) {}
};
/// CachedNonLocalPointerInfo - This map stores the cached results of doing
/// a pointer lookup at the bottom of a block. The key of this map is the
/// pointer+isload bit, the value is a list of <bb->result> mappings.
typedef DenseMap<ValueIsLoadPair, std::pair<BBSkipFirstBlockPair,
NonLocalDepInfo> > CachedNonLocalPointerInfo;
typedef DenseMap<ValueIsLoadPair,
NonLocalPointerInfo> CachedNonLocalPointerInfo;
CachedNonLocalPointerInfo NonLocalPointerDeps;
// A map from instructions to their non-local pointer dependencies.
@ -297,10 +317,10 @@ namespace llvm {
/// set of instructions that either define or clobber the value.
///
/// This method assumes the pointer has a "NonLocal" dependency within BB.
void getNonLocalPointerDependency(Value *Pointer, bool isLoad,
BasicBlock *BB,
void getNonLocalPointerDependency(const AliasAnalysis::Location &Loc,
bool isLoad, BasicBlock *BB,
SmallVectorImpl<NonLocalDepResult> &Result);
/// removeInstruction - Remove an instruction from the dependence analysis,
/// updating the dependence of instructions that previously depended on it.
void removeInstruction(Instruction *InstToRemove);
@ -318,20 +338,29 @@ namespace llvm {
/// critical edges.
void invalidateCachedPredecessors();
private:
MemDepResult getPointerDependencyFrom(Value *Pointer, uint64_t MemSize,
/// getPointerDependencyFrom - Return the instruction on which a memory
/// location depends. If isLoad is true, this routine ignores may-aliases
/// with read-only operations. If isLoad is false, this routine ignores
/// may-aliases with reads from read-only locations.
///
/// Note that this is an uncached query, and thus may be inefficient.
///
MemDepResult getPointerDependencyFrom(const AliasAnalysis::Location &Loc,
bool isLoad,
BasicBlock::iterator ScanIt,
BasicBlock *BB);
private:
MemDepResult getCallSiteDependencyFrom(CallSite C, bool isReadOnlyCall,
BasicBlock::iterator ScanIt,
BasicBlock *BB);
bool getNonLocalPointerDepFromBB(const PHITransAddr &Pointer, uint64_t Size,
bool getNonLocalPointerDepFromBB(const PHITransAddr &Pointer,
const AliasAnalysis::Location &Loc,
bool isLoad, BasicBlock *BB,
SmallVectorImpl<NonLocalDepResult> &Result,
DenseMap<BasicBlock*, Value*> &Visited,
bool SkipFirstBlock = false);
MemDepResult GetNonLocalInfoForBlock(Value *Pointer, uint64_t PointeeSize,
MemDepResult GetNonLocalInfoForBlock(const AliasAnalysis::Location &Loc,
bool isLoad, BasicBlock *BB,
NonLocalDepInfo *Cache,
unsigned NumSortedEntries);

View File

@ -59,7 +59,7 @@ namespace llvm {
//===--------------------------------------------------------------------===//
//
// createBasicAliasAnalysisPass - This pass implements the default alias
// createBasicAliasAnalysisPass - This pass implements the stateless alias
// analysis.
//
ImmutablePass *createBasicAliasAnalysisPass();
@ -114,6 +114,28 @@ namespace llvm {
//
FunctionPass *createProfileVerifierPass();
//===--------------------------------------------------------------------===//
//
// createPathProfileLoaderPass - This pass loads information from a path
// profile dump file.
//
ModulePass *createPathProfileLoaderPass();
extern char &PathProfileLoaderPassID;
//===--------------------------------------------------------------------===//
//
// createNoPathProfileInfoPass - This pass implements the default
// "no path profile".
//
ImmutablePass *createNoPathProfileInfoPass();
//===--------------------------------------------------------------------===//
//
// createPathProfileVerifierPass - This pass verifies path profiling
// information.
//
ModulePass *createPathProfileVerifierPass();
//===--------------------------------------------------------------------===//
//
// createDSAAPass - This pass implements simple context sensitive alias
@ -140,7 +162,7 @@ namespace llvm {
// createLiveValuesPass - This creates an instance of the LiveValues pass.
//
FunctionPass *createLiveValuesPass();
//===--------------------------------------------------------------------===//
//
/// createLazyValueInfoPass - This creates an instance of the LazyValueInfo
@ -153,7 +175,7 @@ namespace llvm {
// LoopDependenceAnalysis pass.
//
LoopPass *createLoopDependenceAnalysisPass();
// Minor pass prototypes, allowing us to expose them through bugpoint and
// analyze.
FunctionPass *createInstCountPass();
@ -170,6 +192,13 @@ namespace llvm {
// Print module-level debug info metadata in human-readable form.
ModulePass *createModuleDebugInfoPrinterPass();
//===--------------------------------------------------------------------===//
//
// createMemDepPrinter - This pass exhaustively collects all memdep
// information and prints it with -analyze.
//
FunctionPass *createMemDepPrinter();
}
#endif

View File

@ -0,0 +1,304 @@
//===- PathNumbering.h ----------------------------------------*- C++ -*---===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Ball-Larus path numbers uniquely identify paths through a directed acyclic
// graph (DAG) [Ball96]. For a CFG backedges are removed and replaced by phony
// edges to obtain a DAG, and thus the unique path numbers [Ball96].
//
// The purpose of this analysis is to enumerate the edges in a CFG in order
// to obtain paths from path numbers in a convenient manner. As described in
// [Ball96] edges can be enumerated such that given a path number by following
// the CFG and updating the path number, the path is obtained.
//
// [Ball96]
// T. Ball and J. R. Larus. "Efficient Path Profiling."
// International Symposium on Microarchitecture, pages 46-57, 1996.
// http://portal.acm.org/citation.cfm?id=243857
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_PATH_NUMBERING_H
#define LLVM_PATH_NUMBERING_H
#include "llvm/BasicBlock.h"
#include "llvm/Instructions.h"
#include "llvm/Pass.h"
#include "llvm/Support/CFG.h"
#include "llvm/Analysis/ProfileInfoTypes.h"
#include <map>
#include <stack>
#include <vector>
namespace llvm {
class BallLarusNode;
class BallLarusEdge;
class BallLarusDag;
// typedefs for storage/ interators of various DAG components
typedef std::vector<BallLarusNode*> BLNodeVector;
typedef std::vector<BallLarusNode*>::iterator BLNodeIterator;
typedef std::vector<BallLarusEdge*> BLEdgeVector;
typedef std::vector<BallLarusEdge*>::iterator BLEdgeIterator;
typedef std::map<BasicBlock*, BallLarusNode*> BLBlockNodeMap;
typedef std::stack<BallLarusNode*> BLNodeStack;
// Represents a basic block with information necessary for the BallLarus
// algorithms.
class BallLarusNode {
public:
enum NodeColor { WHITE, GRAY, BLACK };
// Constructor: Initializes a new Node for the given BasicBlock
BallLarusNode(BasicBlock* BB) :
_basicBlock(BB), _numberPaths(0), _color(WHITE) {
static unsigned nextUID = 0;
_uid = nextUID++;
}
// Returns the basic block for the BallLarusNode
BasicBlock* getBlock();
// Get/set the number of paths to the exit starting at the node.
unsigned getNumberPaths();
void setNumberPaths(unsigned numberPaths);
// Get/set the NodeColor used in graph algorithms.
NodeColor getColor();
void setColor(NodeColor color);
// Iterator information for predecessor edges. Includes phony and
// backedges.
BLEdgeIterator predBegin();
BLEdgeIterator predEnd();
unsigned getNumberPredEdges();
// Iterator information for successor edges. Includes phony and
// backedges.
BLEdgeIterator succBegin();
BLEdgeIterator succEnd();
unsigned getNumberSuccEdges();
// Add an edge to the predecessor list.
void addPredEdge(BallLarusEdge* edge);
// Remove an edge from the predecessor list.
void removePredEdge(BallLarusEdge* edge);
// Add an edge to the successor list.
void addSuccEdge(BallLarusEdge* edge);
// Remove an edge from the successor list.
void removeSuccEdge(BallLarusEdge* edge);
// Returns the name of the BasicBlock being represented. If BasicBlock
// is null then returns "<null>". If BasicBlock has no name, then
// "<unnamed>" is returned. Intended for use with debug output.
std::string getName();
private:
// The corresponding underlying BB.
BasicBlock* _basicBlock;
// Holds the predecessor edges of this node.
BLEdgeVector _predEdges;
// Holds the successor edges of this node.
BLEdgeVector _succEdges;
// The number of paths from the node to the exit.
unsigned _numberPaths;
// 'Color' used by graph algorithms to mark the node.
NodeColor _color;
// Unique ID to ensure naming difference with dotgraphs
unsigned _uid;
// Removes an edge from an edgeVector. Used by removePredEdge and
// removeSuccEdge.
void removeEdge(BLEdgeVector& v, BallLarusEdge* e);
};
// Represents an edge in the Dag. For an edge, v -> w, v is the source, and
// w is the target.
class BallLarusEdge {
public:
enum EdgeType { NORMAL, BACKEDGE, SPLITEDGE,
BACKEDGE_PHONY, SPLITEDGE_PHONY, CALLEDGE_PHONY };
// Constructor: Initializes an BallLarusEdge with a source and target.
BallLarusEdge(BallLarusNode* source, BallLarusNode* target,
unsigned duplicateNumber)
: _source(source), _target(target), _weight(0), _edgeType(NORMAL),
_realEdge(NULL), _duplicateNumber(duplicateNumber) {}
// Returns the source/ target node of this edge.
BallLarusNode* getSource() const;
BallLarusNode* getTarget() const;
// Sets the type of the edge.
EdgeType getType() const;
// Gets the type of the edge.
void setType(EdgeType type);
// Returns the weight of this edge. Used to decode path numbers to
// sequences of basic blocks.
unsigned getWeight();
// Sets the weight of the edge. Used during path numbering.
void setWeight(unsigned weight);
// Gets/sets the phony edge originating at the root.
BallLarusEdge* getPhonyRoot();
void setPhonyRoot(BallLarusEdge* phonyRoot);
// Gets/sets the phony edge terminating at the exit.
BallLarusEdge* getPhonyExit();
void setPhonyExit(BallLarusEdge* phonyExit);
// Gets/sets the associated real edge if this is a phony edge.
BallLarusEdge* getRealEdge();
void setRealEdge(BallLarusEdge* realEdge);
// Returns the duplicate number of the edge.
unsigned getDuplicateNumber();
protected:
// Source node for this edge.
BallLarusNode* _source;
// Target node for this edge.
BallLarusNode* _target;
private:
// Edge weight cooresponding to path number increments before removing
// increments along a spanning tree. The sum over the edge weights gives
// the path number.
unsigned _weight;
// Type to represent for what this edge is intended
EdgeType _edgeType;
// For backedges and split-edges, the phony edge which is linked to the
// root node of the DAG. This contains a path number initialization.
BallLarusEdge* _phonyRoot;
// For backedges and split-edges, the phony edge which is linked to the
// exit node of the DAG. This contains a path counter increment, and
// potentially a path number increment.
BallLarusEdge* _phonyExit;
// If this is a phony edge, _realEdge is a link to the back or split
// edge. Otherwise, this is null.
BallLarusEdge* _realEdge;
// An ID to differentiate between those edges which have the same source
// and destination blocks.
unsigned _duplicateNumber;
};
// Represents the Ball Larus DAG for a given Function. Can calculate
// various properties required for instrumentation or analysis. E.g. the
// edge weights that determine the path number.
class BallLarusDag {
public:
// Initializes a BallLarusDag from the CFG of a given function. Must
// call init() after creation, since some initialization requires
// virtual functions.
BallLarusDag(Function &F)
: _root(NULL), _exit(NULL), _function(F) {}
// Initialization that requires virtual functions which are not fully
// functional in the constructor.
void init();
// Frees all memory associated with the DAG.
virtual ~BallLarusDag();
// Calculate the path numbers by assigning edge increments as prescribed
// in Ball-Larus path profiling.
void calculatePathNumbers();
// Returns the number of paths for the DAG.
unsigned getNumberOfPaths();
// Returns the root (i.e. entry) node for the DAG.
BallLarusNode* getRoot();
// Returns the exit node for the DAG.
BallLarusNode* getExit();
// Returns the function for the DAG.
Function& getFunction();
// Clears the node colors.
void clearColors(BallLarusNode::NodeColor color);
protected:
// All nodes in the DAG.
BLNodeVector _nodes;
// All edges in the DAG.
BLEdgeVector _edges;
// All backedges in the DAG.
BLEdgeVector _backEdges;
// Allows subclasses to determine which type of Node is created.
// Override this method to produce subclasses of BallLarusNode if
// necessary. The destructor of BallLarusDag will call free on each pointer
// created.
virtual BallLarusNode* createNode(BasicBlock* BB);
// Allows subclasses to determine which type of Edge is created.
// Override this method to produce subclasses of BallLarusEdge if
// necessary. Parameters source and target will have been created by
// createNode and can be cast to the subclass of BallLarusNode*
// returned by createNode. The destructor of BallLarusDag will call free
// on each pointer created.
virtual BallLarusEdge* createEdge(BallLarusNode* source, BallLarusNode*
target, unsigned duplicateNumber);
// Proxy to node's constructor. Updates the DAG state.
BallLarusNode* addNode(BasicBlock* BB);
// Proxy to edge's constructor. Updates the DAG state.
BallLarusEdge* addEdge(BallLarusNode* source, BallLarusNode* target,
unsigned duplicateNumber);
private:
// The root (i.e. entry) node for this DAG.
BallLarusNode* _root;
// The exit node for this DAG.
BallLarusNode* _exit;
// The function represented by this DAG.
Function& _function;
// Processes one node and its imediate edges for building the DAG.
void buildNode(BLBlockNodeMap& inDag, std::stack<BallLarusNode*>& dfsStack);
// Process an edge in the CFG for DAG building.
void buildEdge(BLBlockNodeMap& inDag, std::stack<BallLarusNode*>& dfsStack,
BallLarusNode* currentNode, BasicBlock* succBB,
unsigned duplicateNumber);
// The weight on each edge is the increment required along any path that
// contains that edge.
void calculatePathNumbersFrom(BallLarusNode* node);
// Adds a backedge with its phony edges. Updates the DAG state.
void addBackedge(BallLarusNode* source, BallLarusNode* target,
unsigned duplicateCount);
};
} // end namespace llvm
#endif

View File

@ -0,0 +1,113 @@
//===- PathProfileInfo.h --------------------------------------*- C++ -*---===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file outlines the interface used by optimizers to load path profiles.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_PATHPROFILEINFO_H
#define LLVM_PATHPROFILEINFO_H
#include "llvm/BasicBlock.h"
#include "llvm/Analysis/PathNumbering.h"
#include <stack>
namespace llvm {
class ProfilePath;
class ProfilePathEdge;
class PathProfileInfo;
typedef std::vector<ProfilePathEdge> ProfilePathEdgeVector;
typedef std::vector<ProfilePathEdge>::iterator ProfilePathEdgeIterator;
typedef std::vector<BasicBlock*> ProfilePathBlockVector;
typedef std::vector<BasicBlock*>::iterator ProfilePathBlockIterator;
typedef std::map<unsigned int,ProfilePath*> ProfilePathMap;
typedef std::map<unsigned int,ProfilePath*>::iterator ProfilePathIterator;
typedef std::map<Function*,unsigned int> FunctionPathCountMap;
typedef std::map<Function*,ProfilePathMap> FunctionPathMap;
typedef std::map<Function*,ProfilePathMap>::iterator FunctionPathIterator;
class ProfilePathEdge {
public:
ProfilePathEdge(BasicBlock* source, BasicBlock* target,
unsigned duplicateNumber);
inline unsigned getDuplicateNumber() { return _duplicateNumber; }
inline BasicBlock* getSource() { return _source; }
inline BasicBlock* getTarget() { return _target; }
protected:
BasicBlock* _source;
BasicBlock* _target;
unsigned _duplicateNumber;
};
class ProfilePath {
public:
ProfilePath(unsigned int number, unsigned int count,
double countStdDev, PathProfileInfo* ppi);
double getFrequency() const;
inline unsigned int getNumber() const { return _number; }
inline unsigned int getCount() const { return _count; }
inline double getCountStdDev() const { return _countStdDev; }
ProfilePathEdgeVector* getPathEdges() const;
ProfilePathBlockVector* getPathBlocks() const;
BasicBlock* getFirstBlockInPath() const;
private:
unsigned int _number;
unsigned int _count;
double _countStdDev;
// double pointer back to the profiling info
PathProfileInfo* _ppi;
};
// TODO: overload [] operator for getting path
// Add: getFunctionCallCount()
class PathProfileInfo {
public:
PathProfileInfo();
~PathProfileInfo();
void setCurrentFunction(Function* F);
Function* getCurrentFunction() const;
BasicBlock* getCurrentFunctionEntry();
ProfilePath* getPath(unsigned int number);
unsigned int getPotentialPathCount();
ProfilePathIterator pathBegin();
ProfilePathIterator pathEnd();
unsigned int pathsRun();
static char ID; // Pass identification
std::string argList;
protected:
FunctionPathMap _functionPaths;
FunctionPathCountMap _functionPathCounts;
private:
BallLarusDag* _currentDag;
Function* _currentFunction;
friend class ProfilePath;
};
} // end namespace llvm
#endif

View File

@ -1,132 +0,0 @@
//===- PointerTracking.h - Pointer Bounds Tracking --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements tracking of pointer bounds.
// It knows that the libc functions "calloc" and "realloc" allocate memory, thus
// you should avoid using this pass if they mean something else for your
// language.
//
// All methods assume that the pointer is not NULL, if it is then the returned
// allocation size is wrong, and the result from checkLimits is wrong too.
// It also assumes that pointers are valid, and that it is not analyzing a
// use-after-free scenario.
// Due to these limitations the "size" returned by these methods should be
// considered as either 0 or the returned size.
//
// Another analysis pass should be used to find use-after-free/NULL dereference
// bugs.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_POINTERTRACKING_H
#define LLVM_ANALYSIS_POINTERTRACKING_H
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Instructions.h"
#include "llvm/Pass.h"
#include "llvm/Support/PredIteratorCache.h"
namespace llvm {
class DominatorTree;
class ScalarEvolution;
class SCEV;
class Loop;
class LoopInfo;
class TargetData;
// Result from solver, assuming pointer is not NULL,
// and it is not a use-after-free situation.
enum SolverResult {
AlwaysFalse,// always false with above constraints
AlwaysTrue,// always true with above constraints
Unknown // it can sometimes be true, sometimes false, or it is undecided
};
class PointerTracking : public FunctionPass {
public:
typedef ICmpInst::Predicate Predicate;
static char ID;
PointerTracking();
virtual bool doInitialization(Module &M);
// If this pointer directly points to an allocation, return
// the number of elements of type Ty allocated.
// Otherwise return CouldNotCompute.
// Since allocations can fail by returning NULL, the real element count
// for every allocation is either 0 or the value returned by this function.
const SCEV *getAllocationElementCount(Value *P) const;
// Same as getAllocationSize() but returns size in bytes.
// We consider one byte as 8 bits.
const SCEV *getAllocationSizeInBytes(Value *V) const;
// Given a Pointer, determine a base pointer of known size, and an offset
// therefrom.
// When unable to determine, sets Base to NULL, and Limit/Offset to
// CouldNotCompute.
// BaseSize, and Offset are in bytes: Pointer == Base + Offset
void getPointerOffset(Value *Pointer, Value *&Base, const SCEV *& BaseSize,
const SCEV *&Offset) const;
// Compares the 2 scalar evolution expressions according to predicate,
// and if it can prove that the result is always true or always false
// return AlwaysTrue/AlwaysFalse. Otherwise it returns Unknown.
enum SolverResult compareSCEV(const SCEV *A, Predicate Pred, const SCEV *B,
const Loop *L);
// Determines whether the condition LHS <Pred> RHS is sufficient
// for the condition A <Pred> B to hold.
// Currently only ULT/ULE is supported.
// This errs on the side of returning false.
bool conditionSufficient(const SCEV *LHS, Predicate Pred1, const SCEV *RHS,
const SCEV *A, Predicate Pred2, const SCEV *B,
const Loop *L);
// Determines whether Offset is known to be always in [0, Limit) bounds.
// This errs on the side of returning Unknown.
enum SolverResult checkLimits(const SCEV *Offset, const SCEV *Limit,
BasicBlock *BB);
virtual bool runOnFunction(Function &F);
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
void print(raw_ostream &OS, const Module* = 0) const;
Value *computeAllocationCountValue(Value *P, const Type *&Ty) const;
private:
Function *FF;
TargetData *TD;
ScalarEvolution *SE;
LoopInfo *LI;
DominatorTree *DT;
Function *callocFunc;
Function *reallocFunc;
PredIteratorCache predCache;
SmallPtrSet<const SCEV*, 1> analyzing;
enum SolverResult isLoopGuardedBy(const Loop *L, Predicate Pred,
const SCEV *A, const SCEV *B) const;
static bool isMonotonic(const SCEV *S);
bool scevPositive(const SCEV *A, const Loop *L, bool strict=true) const;
bool conditionSufficient(Value *Cond, bool negated,
const SCEV *A, Predicate Pred, const SCEV *B);
Value *getConditionToReach(BasicBlock *A,
DomTreeNodeBase<BasicBlock> *B,
bool &negated);
Value *getConditionToReach(BasicBlock *A,
BasicBlock *B,
bool &negated);
const SCEV *computeAllocationCount(Value *P, const Type *&Ty) const;
const SCEV *computeAllocationCountForType(Value *P, const Type *Ty) const;
};
}
#endif

View File

@ -14,7 +14,7 @@
#ifndef LLVM_ANALYSIS_POST_DOMINATORS_H
#define LLVM_ANALYSIS_POST_DOMINATORS_H
#include "llvm/Analysis/Dominators.h"
#include "llvm/Analysis/DominanceFrontier.h"
namespace llvm {
@ -26,6 +26,7 @@ struct PostDominatorTree : public FunctionPass {
DominatorTreeBase<BasicBlock>* DT;
PostDominatorTree() : FunctionPass(ID) {
initializePostDominatorTreePass(*PassRegistry::getPassRegistry());
DT = new DominatorTreeBase<BasicBlock>(true);
}
@ -106,7 +107,9 @@ template <> struct GraphTraits<PostDominatorTree*>
struct PostDominanceFrontier : public DominanceFrontierBase {
static char ID;
PostDominanceFrontier()
: DominanceFrontierBase(ID, true) {}
: DominanceFrontierBase(ID, true) {
initializePostDominanceFrontierPass(*PassRegistry::getPassRegistry());
}
virtual bool runOnFunction(Function &) {
Frontiers.clear();

View File

@ -1,4 +1,4 @@
/*===-- ProfileInfoTypes.h - Profiling info shared constants ------*- C -*-===*\
/*===-- ProfileInfoTypes.h - Profiling info shared constants --------------===*\
|*
|* The LLVM Compiler Infrastructure
|*
@ -16,6 +16,17 @@
#ifndef LLVM_ANALYSIS_PROFILEINFOTYPES_H
#define LLVM_ANALYSIS_PROFILEINFOTYPES_H
/* Included by libprofile. */
#if defined(__cplusplus)
extern "C" {
#endif
/* IDs to distinguish between those path counters stored in hashses vs arrays */
enum ProfilingStorageType {
ProfilingArray = 1,
ProfilingHash = 2
};
enum ProfilingType {
ArgumentInfo = 1, /* The command line argument block */
FunctionInfo = 2, /* Function profiling information */
@ -26,4 +37,24 @@ enum ProfilingType {
OptEdgeInfo = 7 /* Edge profiling information, optimal version */
};
/*
* The header for tables that map path numbers to path counters.
*/
typedef struct {
unsigned fnNumber; /* function number for these counters */
unsigned numEntries; /* number of entries stored */
} PathProfileHeader;
/*
* Describes an entry in a tagged table for path counters.
*/
typedef struct {
unsigned pathNumber;
unsigned pathCounter;
} PathProfileTableEntry;
#if defined(__cplusplus)
}
#endif
#endif /* LLVM_ANALYSIS_PROFILEINFOTYPES_H */

View File

@ -58,6 +58,7 @@ class RegionNode {
// DO NOT IMPLEMENT
const RegionNode &operator=(const RegionNode &);
protected:
/// This is the entry basic block that starts this region node. If this is a
/// BasicBlock RegionNode, then entry is just the basic block, that this
/// RegionNode represents. Otherwise it is the entry of this (Sub)RegionNode.
@ -70,7 +71,6 @@ class RegionNode {
/// RegionNode.
PointerIntPair<BasicBlock*, 1, bool> entry;
protected:
/// @brief The parent Region of this RegionNode.
/// @see getParent()
Region* parent;
@ -257,6 +257,18 @@ public:
/// @return The entry BasicBlock of the region.
BasicBlock *getEntry() const { return RegionNode::getEntry(); }
/// @brief Replace the entry basic block of the region with the new basic
/// block.
///
/// @param BB The new entry basic block of the region.
void replaceEntry(BasicBlock *BB);
/// @brief Replace the exit basic block of the region with the new basic
/// block.
///
/// @param BB The new exit basic block of the region.
void replaceExit(BasicBlock *BB);
/// @brief Get the exit BasicBlock of the Region.
/// @return The exit BasicBlock of the Region, NULL if this is the TopLevel
/// Region.
@ -280,6 +292,33 @@ public:
/// @return The depth of the region.
unsigned getDepth() const;
/// @brief Check if a Region is the TopLevel region.
///
/// The toplevel region represents the whole function.
bool isTopLevelRegion() const { return exit == NULL; }
/// @brief Return a new (non canonical) region, that is obtained by joining
/// this region with its predecessors.
///
/// @return A region also starting at getEntry(), but reaching to the next
/// basic block that forms with getEntry() a (non canonical) region.
/// NULL if such a basic block does not exist.
Region *getExpandedRegion() const;
/// @brief Return the first block of this region's single entry edge,
/// if existing.
///
/// @return The BasicBlock starting this region's single entry edge,
/// else NULL.
BasicBlock *getEnteringBlock() const;
/// @brief Return the first block of this region's single exit edge,
/// if existing.
///
/// @return The BasicBlock starting this region's single exit edge,
/// else NULL.
BasicBlock *getExitingBlock() const;
/// @brief Is this a simple region?
///
/// A region is simple if it has exactly one exit and one entry edge.
@ -386,7 +425,9 @@ public:
/// @brief Add a new subregion to this Region.
///
/// @param SubRegion The new subregion that will be added.
void addSubRegion(Region *SubRegion);
/// @param moveChildren Move the children of this region, that are also
/// contained in SubRegion into SubRegion.
void addSubRegion(Region *SubRegion, bool moveChildren = false);
/// @brief Remove a subregion from this Region.
///
@ -565,6 +606,12 @@ public:
/// region containing BB.
Region *getRegionFor(BasicBlock *BB) const;
/// @brief Set the smallest region that surrounds a basic block.
///
/// @param BB The basic block surrounded by a region.
/// @param R The smallest region that surrounds BB.
void setRegionFor(BasicBlock *BB, Region *R);
/// @brief A shortcut for getRegionFor().
///
/// @param BB The basic block.
@ -610,6 +657,12 @@ public:
return TopLevelRegion;
}
/// @brief Update RegionInfo after a basic block was split.
///
/// @param NewBB The basic block that was created before OldBB.
/// @param OldBB The old basic block.
void splitBlock(BasicBlock* NewBB, BasicBlock *OldBB);
/// @brief Clear the Node Cache for all Regions.
///
/// @see Region::clearNodeCache()

View File

@ -0,0 +1,126 @@
//===- RegionPass.h - RegionPass class ------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the RegionPass class. All region based analysis,
// optimization and transformation passes are derived from RegionPass.
// This class is implemented following the some ideas of the LoopPass.h class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_REGION_PASS_H
#define LLVM_REGION_PASS_H
#include "llvm/Analysis/RegionInfo.h"
#include "llvm/Pass.h"
#include "llvm/PassManagers.h"
#include "llvm/Function.h"
#include <deque>
namespace llvm {
class RGPassManager;
class Function;
//===----------------------------------------------------------------------===//
/// @brief A pass that runs on each Region in a function.
///
/// RegionPass is managed by RGPassManager.
class RegionPass : public Pass {
public:
explicit RegionPass(char &pid) : Pass(PT_Region, pid) {}
//===--------------------------------------------------------------------===//
/// @name To be implemented by every RegionPass
///
//@{
/// @brief Run the pass on a specific Region
///
/// Accessing regions not contained in the current region is not allowed.
///
/// @param R The region this pass is run on.
/// @param RGM The RegionPassManager that manages this Pass.
///
/// @return True if the pass modifies this Region.
virtual bool runOnRegion(Region *R, RGPassManager &RGM) = 0;
/// @brief Get a pass to print the LLVM IR in the region.
///
/// @param O The ouput stream to print the Region.
/// @param Banner The banner to seperate different printed passes.
///
/// @return The pass to print the LLVM IR in the region.
Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const;
virtual bool doInitialization(Region *R, RGPassManager &RGM) { return false; }
virtual bool doFinalization() { return false; }
//@}
//===--------------------------------------------------------------------===//
/// @name PassManager API
///
//@{
void preparePassManager(PMStack &PMS);
virtual void assignPassManager(PMStack &PMS,
PassManagerType PMT = PMT_RegionPassManager);
virtual PassManagerType getPotentialPassManagerType() const {
return PMT_RegionPassManager;
}
//@}
};
/// @brief The pass manager to schedule RegionPasses.
class RGPassManager : public FunctionPass, public PMDataManager {
std::deque<Region*> RQ;
bool skipThisRegion;
bool redoThisRegion;
RegionInfo *RI;
Region *CurrentRegion;
public:
static char ID;
explicit RGPassManager(int Depth);
/// @brief Execute all of the passes scheduled for execution.
///
/// @return True if any of the passes modifies the function.
bool runOnFunction(Function &F);
/// Pass Manager itself does not invalidate any analysis info.
/// RGPassManager needs RegionInfo.
void getAnalysisUsage(AnalysisUsage &Info) const;
virtual const char *getPassName() const {
return "Region Pass Manager";
}
virtual PMDataManager *getAsPMDataManager() { return this; }
virtual Pass *getAsPass() { return this; }
/// @brief Print passes managed by this manager.
void dumpPassStructure(unsigned Offset);
/// @brief Print passes contained by this manager.
Pass *getContainedPass(unsigned N) {
assert(N < PassVector.size() && "Pass number out of range!");
Pass *FP = static_cast<Pass *>(PassVector[N]);
return FP;
}
virtual PassManagerType getPassManagerType() const {
return PMT_RegionPassManager;
}
};
} // End llvm namespace
#endif

View File

@ -24,7 +24,7 @@
#include "llvm/Pass.h"
#include "llvm/Instructions.h"
#include "llvm/Function.h"
#include "llvm/System/DataTypes.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/ValueHandle.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/ConstantRange.h"
@ -70,27 +70,16 @@ namespace llvm {
private:
SCEV(const SCEV &); // DO NOT IMPLEMENT
void operator=(const SCEV &); // DO NOT IMPLEMENT
protected:
virtual ~SCEV();
public:
explicit SCEV(const FoldingSetNodeIDRef ID, unsigned SCEVTy) :
FastID(ID), SCEVType(SCEVTy), SubclassData(0) {}
unsigned getSCEVType() const { return SCEVType; }
/// isLoopInvariant - Return true if the value of this SCEV is unchanging in
/// the specified loop.
virtual bool isLoopInvariant(const Loop *L) const = 0;
/// hasComputableLoopEvolution - Return true if this SCEV changes value in a
/// known way in the specified loop. This property being true implies that
/// the value is variant in the loop AND that we can emit an expression to
/// compute the value of the expression at any particular loop iteration.
virtual bool hasComputableLoopEvolution(const Loop *L) const = 0;
/// getType - Return the LLVM type of this SCEV expression.
///
virtual const Type *getType() const = 0;
const Type *getType() const;
/// isZero - Return true if the expression is a constant zero.
///
@ -105,22 +94,10 @@ namespace llvm {
///
bool isAllOnesValue() const;
/// hasOperand - Test whether this SCEV has Op as a direct or
/// indirect operand.
virtual bool hasOperand(const SCEV *Op) const = 0;
/// dominates - Return true if elements that makes up this SCEV dominates
/// the specified basic block.
virtual bool dominates(BasicBlock *BB, DominatorTree *DT) const = 0;
/// properlyDominates - Return true if elements that makes up this SCEV
/// properly dominate the specified basic block.
virtual bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const = 0;
/// print - Print out the internal representation of this scalar to the
/// specified stream. This should really only be used for debugging
/// purposes.
virtual void print(raw_ostream &OS) const = 0;
void print(raw_ostream &OS) const;
/// dump - This method is used for debugging.
///
@ -155,21 +132,6 @@ namespace llvm {
struct SCEVCouldNotCompute : public SCEV {
SCEVCouldNotCompute();
// None of these methods are valid for this object.
virtual bool isLoopInvariant(const Loop *L) const;
virtual const Type *getType() const;
virtual bool hasComputableLoopEvolution(const Loop *L) const;
virtual void print(raw_ostream &OS) const;
virtual bool hasOperand(const SCEV *Op) const;
virtual bool dominates(BasicBlock *BB, DominatorTree *DT) const {
return true;
}
virtual bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const {
return true;
}
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVCouldNotCompute *S) { return true; }
static bool classof(const SCEV *S);
@ -180,6 +142,24 @@ namespace llvm {
/// they must ask this class for services.
///
class ScalarEvolution : public FunctionPass {
public:
/// LoopDisposition - An enum describing the relationship between a
/// SCEV and a loop.
enum LoopDisposition {
LoopVariant, ///< The SCEV is loop-variant (unknown).
LoopInvariant, ///< The SCEV is loop-invariant.
LoopComputable ///< The SCEV varies predictably with the loop.
};
/// BlockDisposition - An enum describing the relationship between a
/// SCEV and a basic block.
enum BlockDisposition {
DoesNotDominateBlock, ///< The SCEV does not dominate the block.
DominatesBlock, ///< The SCEV dominates the block.
ProperlyDominatesBlock ///< The SCEV properly dominates the block.
};
private:
/// SCEVCallbackVH - A CallbackVH to arrange for ScalarEvolution to be
/// notified whenever a Value is deleted.
class SCEVCallbackVH : public CallbackVH {
@ -267,6 +247,46 @@ namespace llvm {
std::map<const SCEV *,
std::map<const Loop *, const SCEV *> > ValuesAtScopes;
/// LoopDispositions - Memoized computeLoopDisposition results.
std::map<const SCEV *,
std::map<const Loop *, LoopDisposition> > LoopDispositions;
/// computeLoopDisposition - Compute a LoopDisposition value.
LoopDisposition computeLoopDisposition(const SCEV *S, const Loop *L);
/// BlockDispositions - Memoized computeBlockDisposition results.
std::map<const SCEV *,
std::map<const BasicBlock *, BlockDisposition> > BlockDispositions;
/// computeBlockDisposition - Compute a BlockDisposition value.
BlockDisposition computeBlockDisposition(const SCEV *S, const BasicBlock *BB);
/// UnsignedRanges - Memoized results from getUnsignedRange
DenseMap<const SCEV *, ConstantRange> UnsignedRanges;
/// SignedRanges - Memoized results from getSignedRange
DenseMap<const SCEV *, ConstantRange> SignedRanges;
/// setUnsignedRange - Set the memoized unsigned range for the given SCEV.
const ConstantRange &setUnsignedRange(const SCEV *S,
const ConstantRange &CR) {
std::pair<DenseMap<const SCEV *, ConstantRange>::iterator, bool> Pair =
UnsignedRanges.insert(std::make_pair(S, CR));
if (!Pair.second)
Pair.first->second = CR;
return Pair.first->second;
}
/// setUnsignedRange - Set the memoized signed range for the given SCEV.
const ConstantRange &setSignedRange(const SCEV *S,
const ConstantRange &CR) {
std::pair<DenseMap<const SCEV *, ConstantRange>::iterator, bool> Pair =
SignedRanges.insert(std::make_pair(S, CR));
if (!Pair.second)
Pair.first->second = CR;
return Pair.first->second;
}
/// createSCEV - We know that there is no SCEV for the specified value.
/// Analyze the expression.
const SCEV *createSCEV(Value *V);
@ -408,6 +428,9 @@ namespace llvm {
bool isKnownPredicateWithRanges(ICmpInst::Predicate Pred,
const SCEV *LHS, const SCEV *RHS);
/// forgetMemoizedResults - Drop memoized information computed for S.
void forgetMemoizedResults(const SCEV *S);
public:
static char ID; // Pass identification, replacement for typeid
ScalarEvolution();
@ -514,10 +537,11 @@ namespace llvm {
///
const SCEV *getNotSCEV(const SCEV *V);
/// getMinusSCEV - Return LHS-RHS.
///
const SCEV *getMinusSCEV(const SCEV *LHS,
const SCEV *RHS);
/// getMinusSCEV - Return LHS-RHS. Minus is represented in SCEV as A+B*-1,
/// and thus the HasNUW and HasNSW bits apply to the resultant add, not
/// whether the sub would have overflowed.
const SCEV *getMinusSCEV(const SCEV *LHS, const SCEV *RHS,
bool HasNUW = false, bool HasNSW = false);
/// getTruncateOrZeroExtend - Return a SCEV corresponding to a conversion
/// of the input value to the specified type. If the type must be
@ -675,6 +699,36 @@ namespace llvm {
const SCEV *&LHS,
const SCEV *&RHS);
/// getLoopDisposition - Return the "disposition" of the given SCEV with
/// respect to the given loop.
LoopDisposition getLoopDisposition(const SCEV *S, const Loop *L);
/// isLoopInvariant - Return true if the value of the given SCEV is
/// unchanging in the specified loop.
bool isLoopInvariant(const SCEV *S, const Loop *L);
/// hasComputableLoopEvolution - Return true if the given SCEV changes value
/// in a known way in the specified loop. This property being true implies
/// that the value is variant in the loop AND that we can emit an expression
/// to compute the value of the expression at any particular loop iteration.
bool hasComputableLoopEvolution(const SCEV *S, const Loop *L);
/// getLoopDisposition - Return the "disposition" of the given SCEV with
/// respect to the given block.
BlockDisposition getBlockDisposition(const SCEV *S, const BasicBlock *BB);
/// dominates - Return true if elements that makes up the given SCEV
/// dominate the specified basic block.
bool dominates(const SCEV *S, const BasicBlock *BB);
/// properlyDominates - Return true if elements that makes up the given SCEV
/// properly dominate the specified basic block.
bool properlyDominates(const SCEV *S, const BasicBlock *BB);
/// hasOperand - Test whether the given SCEV has Op as a direct or
/// indirect operand.
bool hasOperand(const SCEV *S, const SCEV *Op) const;
virtual bool runOnFunction(Function &F);
virtual void releaseMemory();
virtual void getAnalysisUsage(AnalysisUsage &AU) const;

View File

@ -35,6 +35,9 @@ namespace llvm {
std::set<AssertingVH<Value> > InsertedValues;
std::set<AssertingVH<Value> > InsertedPostIncValues;
/// RelevantLoops - A memoization of the "relevant" loop for a given SCEV.
DenseMap<const SCEV *, const Loop *> RelevantLoops;
/// PostIncLoops - Addrecs referring to any of the given loops are expanded
/// in post-inc mode. For example, expanding {1,+,1}<L> in post-inc mode
/// returns the add instruction that adds one to the phi for {0,+,1}<L>,
@ -168,6 +171,9 @@ namespace llvm {
return InsertedValues.count(I) || InsertedPostIncValues.count(I);
}
/// getRelevantLoop - Determine the most "relevant" loop for the given SCEV.
const Loop *getRelevantLoop(const SCEV *);
Value *visitConstant(const SCEVConstant *S) {
return S->getValue();
}

View File

@ -42,29 +42,7 @@ namespace llvm {
public:
ConstantInt *getValue() const { return V; }
virtual bool isLoopInvariant(const Loop *L) const {
return true;
}
virtual bool hasComputableLoopEvolution(const Loop *L) const {
return false; // Not loop variant
}
virtual const Type *getType() const;
virtual bool hasOperand(const SCEV *) const {
return false;
}
bool dominates(BasicBlock *BB, DominatorTree *DT) const {
return true;
}
bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const {
return true;
}
virtual void print(raw_ostream &OS) const;
const Type *getType() const { return V->getType(); }
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVConstant *S) { return true; }
@ -86,23 +64,7 @@ namespace llvm {
public:
const SCEV *getOperand() const { return Op; }
virtual const Type *getType() const { return Ty; }
virtual bool isLoopInvariant(const Loop *L) const {
return Op->isLoopInvariant(L);
}
virtual bool hasComputableLoopEvolution(const Loop *L) const {
return Op->hasComputableLoopEvolution(L);
}
virtual bool hasOperand(const SCEV *O) const {
return Op == O || Op->hasOperand(O);
}
virtual bool dominates(BasicBlock *BB, DominatorTree *DT) const;
virtual bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const;
const Type *getType() const { return Ty; }
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVCastExpr *S) { return true; }
@ -124,8 +86,6 @@ namespace llvm {
const SCEV *op, const Type *ty);
public:
virtual void print(raw_ostream &OS) const;
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVTruncateExpr *S) { return true; }
static inline bool classof(const SCEV *S) {
@ -144,8 +104,6 @@ namespace llvm {
const SCEV *op, const Type *ty);
public:
virtual void print(raw_ostream &OS) const;
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVZeroExtendExpr *S) { return true; }
static inline bool classof(const SCEV *S) {
@ -164,8 +122,6 @@ namespace llvm {
const SCEV *op, const Type *ty);
public:
virtual void print(raw_ostream &OS) const;
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVSignExtendExpr *S) { return true; }
static inline bool classof(const SCEV *S) {
@ -202,20 +158,7 @@ namespace llvm {
op_iterator op_begin() const { return Operands; }
op_iterator op_end() const { return Operands + NumOperands; }
virtual bool isLoopInvariant(const Loop *L) const;
// hasComputableLoopEvolution - N-ary expressions have computable loop
// evolutions iff they have at least one operand that varies with the loop,
// but that all varying operands are computable.
virtual bool hasComputableLoopEvolution(const Loop *L) const;
virtual bool hasOperand(const SCEV *O) const;
bool dominates(BasicBlock *BB, DominatorTree *DT) const;
bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const;
virtual const Type *getType() const { return getOperand(0)->getType(); }
const Type *getType() const { return getOperand(0)->getType(); }
bool hasNoUnsignedWrap() const { return SubclassData & (1 << 0); }
void setHasNoUnsignedWrap(bool B) {
@ -248,10 +191,6 @@ namespace llvm {
: SCEVNAryExpr(ID, T, O, N) {}
public:
virtual const char *getOperationStr() const = 0;
virtual void print(raw_ostream &OS) const;
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVCommutativeExpr *S) { return true; }
static inline bool classof(const SCEV *S) {
@ -275,9 +214,7 @@ namespace llvm {
}
public:
virtual const char *getOperationStr() const { return " + "; }
virtual const Type *getType() const {
const Type *getType() const {
// Use the type of the last operand, which is likely to be a pointer
// type, if there is one. This doesn't usually matter, but it can help
// reduce casts when the expressions are expanded.
@ -303,8 +240,6 @@ namespace llvm {
}
public:
virtual const char *getOperationStr() const { return " * "; }
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVMulExpr *S) { return true; }
static inline bool classof(const SCEV *S) {
@ -328,27 +263,15 @@ namespace llvm {
const SCEV *getLHS() const { return LHS; }
const SCEV *getRHS() const { return RHS; }
virtual bool isLoopInvariant(const Loop *L) const {
return LHS->isLoopInvariant(L) && RHS->isLoopInvariant(L);
const Type *getType() const {
// In most cases the types of LHS and RHS will be the same, but in some
// crazy cases one or the other may be a pointer. ScalarEvolution doesn't
// depend on the type for correctness, but handling types carefully can
// avoid extra casts in the SCEVExpander. The LHS is more likely to be
// a pointer type than the RHS, so use the RHS' type here.
return getRHS()->getType();
}
virtual bool hasComputableLoopEvolution(const Loop *L) const {
return LHS->hasComputableLoopEvolution(L) &&
RHS->hasComputableLoopEvolution(L);
}
virtual bool hasOperand(const SCEV *O) const {
return O == LHS || O == RHS || LHS->hasOperand(O) || RHS->hasOperand(O);
}
bool dominates(BasicBlock *BB, DominatorTree *DT) const;
bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const;
virtual const Type *getType() const;
void print(raw_ostream &OS) const;
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVUDivExpr *S) { return true; }
static inline bool classof(const SCEV *S) {
@ -373,11 +296,7 @@ namespace llvm {
SCEVAddRecExpr(const FoldingSetNodeIDRef ID,
const SCEV *const *O, size_t N, const Loop *l)
: SCEVNAryExpr(ID, scAddRecExpr, O, N), L(l) {
for (size_t i = 0, e = NumOperands; i != e; ++i)
assert(Operands[i]->isLoopInvariant(l) &&
"Operands of AddRec must be loop-invariant!");
}
: SCEVNAryExpr(ID, scAddRecExpr, O, N), L(l) {}
public:
const SCEV *getStart() const { return Operands[0]; }
@ -393,16 +312,6 @@ namespace llvm {
getLoop());
}
virtual bool hasComputableLoopEvolution(const Loop *QL) const {
return L == QL;
}
virtual bool isLoopInvariant(const Loop *QueryLoop) const;
bool dominates(BasicBlock *BB, DominatorTree *DT) const;
bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const;
/// isAffine - Return true if this is an affine AddRec (i.e., it represents
/// an expressions A+B*x where A and B are loop invariant values.
bool isAffine() const {
@ -437,8 +346,6 @@ namespace llvm {
return cast<SCEVAddRecExpr>(SE.getAddExpr(this, getStepRecurrence(SE)));
}
virtual void print(raw_ostream &OS) const;
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVAddRecExpr *S) { return true; }
static inline bool classof(const SCEV *S) {
@ -462,8 +369,6 @@ namespace llvm {
}
public:
virtual const char *getOperationStr() const { return " smax "; }
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVSMaxExpr *S) { return true; }
static inline bool classof(const SCEV *S) {
@ -487,8 +392,6 @@ namespace llvm {
}
public:
virtual const char *getOperationStr() const { return " umax "; }
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVUMaxExpr *S) { return true; }
static inline bool classof(const SCEV *S) {
@ -534,22 +437,7 @@ namespace llvm {
bool isAlignOf(const Type *&AllocTy) const;
bool isOffsetOf(const Type *&STy, Constant *&FieldNo) const;
virtual bool isLoopInvariant(const Loop *L) const;
virtual bool hasComputableLoopEvolution(const Loop *QL) const {
return false; // not computable
}
virtual bool hasOperand(const SCEV *) const {
return false;
}
bool dominates(BasicBlock *BB, DominatorTree *DT) const;
bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const;
virtual const Type *getType() const;
virtual void print(raw_ostream &OS) const;
const Type *getType() const { return getValPtr()->getType(); }
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVUnknown *S) { return true; }

View File

@ -15,7 +15,7 @@
#ifndef LLVM_ANALYSIS_VALUETRACKING_H
#define LLVM_ANALYSIS_VALUETRACKING_H
#include "llvm/System/DataTypes.h"
#include "llvm/Support/DataTypes.h"
#include <string>
namespace llvm {
@ -39,6 +39,23 @@ namespace llvm {
APInt &KnownOne, const TargetData *TD = 0,
unsigned Depth = 0);
/// ComputeSignBit - Determine whether the sign bit is known to be zero or
/// one. Convenience wrapper around ComputeMaskedBits.
void ComputeSignBit(Value *V, bool &KnownZero, bool &KnownOne,
const TargetData *TD = 0, unsigned Depth = 0);
/// isPowerOfTwo - Return true if the given value is known to have exactly one
/// bit set when defined. For vectors return true if every element is known to
/// be a power of two when defined. Supports values with integer or pointer
/// type and vectors of integers.
bool isPowerOfTwo(Value *V, const TargetData *TD = 0, unsigned Depth = 0);
/// isKnownNonZero - 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.
bool isKnownNonZero(Value *V, const TargetData *TD = 0, unsigned Depth = 0);
/// MaskedValueIsZero - Return true if 'V & Mask' is known to be zero. We use
/// this predicate to simplify operations downstream. Mask is known to be
/// zero for bits that V cannot have.
@ -77,7 +94,13 @@ namespace llvm {
///
bool CannotBeNegativeZero(const Value *V, unsigned Depth = 0);
/// isBytewiseValue - If the specified value can be set by repeating the same
/// byte in memory, return the i8 value that it is represented with. This is
/// true for all i8 values obviously, but is also true for i32 0, i32 -1,
/// i16 0xF0F0, double 0.0 etc. If the value can't be handled with a repeated
/// byte store (e.g. i16 0x1234), return null.
Value *isBytewiseValue(Value *V);
/// FindInsertedValue - Given an aggregrate and an sequence of indices, see if
/// the scalar value indexed is already around as a register, for example if
/// it were inserted directly into the aggregrate.
@ -97,6 +120,17 @@ namespace llvm {
return FindInsertedValue(V, &Idxs[0], &Idxs[1], InsertBefore);
}
/// GetPointerBaseWithConstantOffset - Analyze the specified pointer to see if
/// it can be expressed as a base pointer plus a constant offset. Return the
/// base and offset to the caller.
Value *GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset,
const TargetData &TD);
static inline const Value *
GetPointerBaseWithConstantOffset(const Value *Ptr, int64_t &Offset,
const TargetData &TD) {
return GetPointerBaseWithConstantOffset(const_cast<Value*>(Ptr), Offset,TD);
}
/// GetConstantStringInfo - This function computes the length of a
/// null-terminated C string pointed to by V. If successful, it returns true
/// and returns the string in Str. If unsuccessful, it returns false. If
@ -110,6 +144,20 @@ namespace llvm {
/// GetStringLength - If we can compute the length of the string pointed to by
/// the specified pointer, return 'len+1'. If we can't, return 0.
uint64_t GetStringLength(Value *V);
/// GetUnderlyingObject - This method strips off any GEP address adjustments
/// and pointer casts from the specified value, returning the original object
/// being addressed. Note that the returned value has pointer type if the
/// specified value does. If the MaxLookup value is non-zero, it limits the
/// number of instructions to be stripped off.
Value *GetUnderlyingObject(Value *V, const TargetData *TD = 0,
unsigned MaxLookup = 6);
static inline const Value *
GetUnderlyingObject(const Value *V, const TargetData *TD = 0,
unsigned MaxLookup = 6) {
return GetUnderlyingObject(const_cast<Value *>(V), TD, MaxLookup);
}
} // end namespace llvm
#endif

View File

@ -65,6 +65,8 @@ const Attributes StackAlignment = 7<<26; ///< Alignment of stack for
///of alignment with +1 bias
///0 means unaligned (different from
///alignstack(1))
const Attributes Hotpatch = 1<<29; ///< Function should have special
///'hotpatch' sequence in prologue
/// @brief Attributes that only apply to function parameters.
const Attributes ParameterOnly = ByVal | Nest | StructRet | NoCapture;
@ -73,7 +75,8 @@ const Attributes ParameterOnly = ByVal | Nest | StructRet | NoCapture;
/// be used on return values or function parameters.
const Attributes FunctionOnly = NoReturn | NoUnwind | ReadNone | ReadOnly |
NoInline | AlwaysInline | OptimizeForSize | StackProtect | StackProtectReq |
NoRedZone | NoImplicitFloat | Naked | InlineHint | StackAlignment;
NoRedZone | NoImplicitFloat | Naked | InlineHint | StackAlignment |
Hotpatch;
/// @brief Parameter attributes that do not apply to vararg call arguments.
const Attributes VarArgsIncompatible = StructRet;
@ -223,7 +226,7 @@ public:
/// paramHasAttr - Return true if the specified parameter index has the
/// specified attribute set.
bool paramHasAttr(unsigned Idx, Attributes Attr) const {
return getAttributes(Idx) & Attr;
return (getAttributes(Idx) & Attr) != 0;
}
/// getParamAlignment - Return the alignment for the specified function

View File

@ -18,7 +18,7 @@
#include "llvm/SymbolTableListTraits.h"
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/Twine.h"
#include "llvm/System/DataTypes.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
@ -58,9 +58,9 @@ private:
/// tables. The type of a BasicBlock is "Type::LabelTy" because the basic block
/// represents a label to which a branch can jump.
///
/// A well formed basic block is formed of a list of non-terminating
/// instructions followed by a single TerminatorInst instruction.
/// TerminatorInst's may not occur in the middle of basic blocks, and must
/// A well formed basic block is formed of a list of non-terminating
/// instructions followed by a single TerminatorInst instruction.
/// TerminatorInst's may not occur in the middle of basic blocks, and must
/// terminate the blocks. The BasicBlock class allows malformed basic blocks to
/// occur because it may be useful in the intermediate stage of constructing or
/// modifying a program. However, the verifier will ensure that basic blocks
@ -90,7 +90,7 @@ private:
public:
/// getContext - Get the context in which this basic block lives.
LLVMContext &getContext() const;
/// Instruction iterators...
typedef InstListType::iterator iterator;
typedef InstListType::const_iterator const_iterator;
@ -98,7 +98,7 @@ public:
/// Create - Creates a new BasicBlock. If the Parent parameter is specified,
/// the basic block is automatically inserted at either the end of the
/// function (if InsertBefore is 0), or before the specified basic block.
static BasicBlock *Create(LLVMContext &Context, const Twine &Name = "",
static BasicBlock *Create(LLVMContext &Context, const Twine &Name = "",
Function *Parent = 0,BasicBlock *InsertBefore = 0) {
return new BasicBlock(Context, Name, Parent, InsertBefore);
}
@ -114,15 +114,15 @@ public:
/// and BlockAddress's).
User *use_back() { return cast<User>(*use_begin());}
const User *use_back() const { return cast<User>(*use_begin());}
/// getTerminator() - If this is a well formed basic block, then this returns
/// a pointer to the terminator instruction. If it is not, then you get a
/// null pointer back.
///
TerminatorInst *getTerminator();
const TerminatorInst *getTerminator() const;
/// Returns a pointer to the first instructon in this block that is not a
/// Returns a pointer to the first instructon in this block that is not a
/// PHINode instruction. When adding instruction to the beginning of the
/// basic block, they should be added before the returned value, not before
/// the first instruction, which might be PHI.
@ -137,7 +137,7 @@ public:
const Instruction* getFirstNonPHIOrDbg() const {
return const_cast<BasicBlock*>(this)->getFirstNonPHIOrDbg();
}
/// removeFromParent - This method unlinks 'this' from the containing
/// function, but does not delete it.
///
@ -147,15 +147,15 @@ public:
/// and deletes it.
///
void eraseFromParent();
/// moveBefore - Unlink this basic block from its current function and
/// insert it into the function that MovePos lives in, right before MovePos.
void moveBefore(BasicBlock *MovePos);
/// moveAfter - Unlink this basic block from its current function and
/// insert it into the function that MovePos lives in, right after MovePos.
void moveAfter(BasicBlock *MovePos);
/// getSinglePredecessor - If this basic block has a single predecessor block,
/// return the block, otherwise return a null pointer.
@ -166,8 +166,8 @@ public:
/// getUniquePredecessor - If this basic block has a unique predecessor block,
/// return the block, otherwise return a null pointer.
/// Note that unique predecessor doesn't mean single edge, there can be
/// multiple edges from the unique predecessor to this block (for example
/// Note that unique predecessor doesn't mean single edge, there can be
/// multiple edges from the unique predecessor to this block (for example
/// a switch statement with multiple cases having the same destination).
BasicBlock *getUniquePredecessor();
const BasicBlock *getUniquePredecessor() const {
@ -247,7 +247,7 @@ public:
/// hasAddressTaken - returns true if there are any uses of this basic block
/// other than direct branches, switches, etc. to it.
bool hasAddressTaken() const { return getSubclassDataFromValue() != 0; }
private:
/// AdjustBlockAddressRefCount - BasicBlock stores the number of BlockAddress
/// objects using it. This is almost always 0, sometimes one, possibly but

View File

@ -19,12 +19,13 @@
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/ilist_node.h"
#include "llvm/System/Path.h"
#include "llvm/Support/Path.h"
#include <map>
#include <set>
namespace llvm {
class MemoryBuffer;
class raw_ostream;
// Forward declare classes
class Module; // From VMCore
@ -82,7 +83,7 @@ class ArchiveMember : public ilist_node<ArchiveMember> {
unsigned getGroup() const { return info.getGroup(); }
/// The "mode" specifies the access permissions for the file per Unix
/// security. This may not have any applicabiity on non-Unix systems but is
/// security. This may not have any applicability on non-Unix systems but is
/// a required component of the "ar" file format.
/// @brief Get the permission mode associated with this archive member.
unsigned getMode() const { return info.getMode(); }
@ -144,7 +145,7 @@ class ArchiveMember : public ilist_node<ArchiveMember> {
/// allowed that doesn't have this restriction. This method determines if
/// that "long format" is used for this member.
/// @returns true iff the file name uses the long form
/// @brief Determin if the member has a long file name
/// @brief Determine if the member has a long file name
bool hasLongFilename() const { return flags&HasLongFilenameFlag; }
/// This method returns the status info (like Unix stat(2)) for the archive
@ -402,7 +403,7 @@ class Archive {
/// bitcode archive. It first makes sure the symbol table has been loaded
/// and has a non-zero size. If it does, then it is an archive. If not,
/// then it tries to load all the bitcode modules of the archive. Finally,
/// it returns whether it was successfull.
/// it returns whether it was successful.
/// @returns true if the archive is a proper llvm bitcode archive
/// @brief Determine whether the archive is a proper llvm bitcode archive.
bool isBitcodeArchive();
@ -482,7 +483,7 @@ class Archive {
bool loadSymbolTable(std::string* ErrMessage);
/// @brief Write the symbol table to an ofstream.
void writeSymbolTable(std::ofstream& ARFile);
void writeSymbolTable(raw_ostream& ARFile);
/// Writes one ArchiveMember to an ofstream. If an error occurs, returns
/// false, otherwise true. If an error occurs and error is non-null then
@ -491,7 +492,7 @@ class Archive {
/// @returns true Writing member failed, \p error set to error message
bool writeMember(
const ArchiveMember& member, ///< The member to be written
std::ofstream& ARFile, ///< The file to write member onto
raw_ostream& ARFile, ///< The file to write member onto
bool CreateSymbolTable, ///< Should symbol table be created?
bool TruncateNames, ///< Should names be truncated to 11 chars?
bool ShouldCompress, ///< Should the member be compressed?

View File

@ -19,7 +19,7 @@
#define LLVM_BITCODE_BITCODES_H
#include "llvm/ADT/SmallVector.h"
#include "llvm/System/DataTypes.h"
#include "llvm/Support/DataTypes.h"
#include <cassert>
namespace llvm {

View File

@ -94,7 +94,9 @@ namespace bitc {
TYPE_CODE_FP128 = 14, // LONG DOUBLE (112 bit mantissa)
TYPE_CODE_PPC_FP128= 15, // PPC LONG DOUBLE (2 doubles)
TYPE_CODE_METADATA = 16 // METADATA
TYPE_CODE_METADATA = 16, // METADATA
TYPE_CODE_X86_MMX = 17 // X86 MMX
};
// The type symbol table only has one code (TST_ENTRY_CODE).
@ -197,10 +199,10 @@ namespace bitc {
OBO_NO_SIGNED_WRAP = 1
};
/// SDivOperatorOptionalFlags - Flags for serializing SDivOperator's
/// SubclassOptionalData contents.
enum SDivOperatorOptionalFlags {
SDIV_EXACT = 0
/// PossiblyExactOperatorOptionalFlags - Flags for serializing
/// PossiblyExactOperator's SubclassOptionalData contents.
enum PossiblyExactOperatorOptionalFlags {
PEO_EXACT = 0
};
// The function body block (FUNCTION_BLOCK_ID) describes function bodies. It

View File

@ -33,6 +33,15 @@ namespace llvm {
LLVMContext& Context,
std::string *ErrMsg = 0);
/// getBitcodeTargetTriple - Read the header of the specified bitcode
/// buffer and extract just the triple information. If successful,
/// this returns a string and *does not* take ownership
/// of 'buffer'. On error, this returns "", and fills in *ErrMsg
/// if ErrMsg is non-null.
std::string getBitcodeTargetTriple(MemoryBuffer *Buffer,
LLVMContext& Context,
std::string *ErrMsg = 0);
/// ParseBitcodeFile - Read the specified bitcode file, returning the module.
/// If an error occurs, this returns null and fills in *ErrMsg if it is
/// non-null. This method *never* takes ownership of Buffer.

View File

@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
// This file defines LLVM's set of calling conventions.
// This file defines LLVM's set of calling conventions.
//
//===----------------------------------------------------------------------===//
@ -20,21 +20,21 @@ namespace llvm {
/// the well-known calling conventions.
///
namespace CallingConv {
/// A set of enums which specify the assigned numeric values for known llvm
/// A set of enums which specify the assigned numeric values for known llvm
/// calling conventions.
/// @brief LLVM Calling Convention Representation
enum ID {
/// C - The default llvm calling convention, compatible with C. This
/// convention is the only calling convention that supports varargs calls.
/// As with typical C calling conventions, the callee/caller have to
/// As with typical C calling conventions, the callee/caller have to
/// tolerate certain amounts of prototype mismatch.
C = 0,
// Generic LLVM calling conventions. None of these calling conventions
// support varargs calls, and all assume that the caller and callee
// prototype exactly match.
/// Fast - This calling convention attempts to make calls as fast as
/// Fast - This calling convention attempts to make calls as fast as
/// possible (e.g. by passing things in registers).
Fast = 8,
@ -79,7 +79,22 @@ namespace CallingConv {
/// X86_ThisCall - Similar to X86_StdCall. Passes first argument in ECX,
/// others via stack. Callee is responsible for stack cleaning. MSVC uses
/// this by default for methods in its ABI.
X86_ThisCall = 70
X86_ThisCall = 70,
/// PTX_Kernel - Call to a PTX kernel.
/// Passes all arguments in parameter space.
PTX_Kernel = 71,
/// PTX_Device - Call to a PTX device function.
/// Passes all arguments in register or parameter space.
PTX_Device = 72,
/// MBLAZE_INTR - Calling convention used for MBlaze interrupt routines.
MBLAZE_INTR = 73,
/// MBLAZE_INTR - Calling convention used for MBlaze interrupt support
/// routines (i.e. GCC's save_volatiles attribute).
MBLAZE_SVOL = 74
};
} // End CallingConv namespace

View File

@ -23,14 +23,16 @@
namespace llvm {
class TargetLowering;
class GlobalVariable;
class TargetLowering;
class SDNode;
class SelectionDAG;
/// ComputeLinearIndex - Given an LLVM IR aggregate type and a sequence
/// of insertvalue or extractvalue indices that identify a member, return
/// the linearized index of the start of the member.
///
unsigned ComputeLinearIndex(const TargetLowering &TLI, const Type *Ty,
unsigned ComputeLinearIndex(const Type *Ty,
const unsigned *Indices,
const unsigned *IndicesEnd,
unsigned CurIndex = 0);
@ -52,7 +54,7 @@ GlobalVariable *ExtractTypeInfo(Value *V);
/// hasInlineAsmMemConstraint - Return true if the inline asm instruction being
/// processed uses a memory 'm' constraint.
bool hasInlineAsmMemConstraint(std::vector<InlineAsm::ConstraintInfo> &CInfos,
bool hasInlineAsmMemConstraint(InlineAsm::ConstraintInfoVector &CInfos,
const TargetLowering &TLI);
/// getFCmpCondCode - Return the ISD condition code corresponding to
@ -75,6 +77,9 @@ ISD::CondCode getICmpCondCode(ICmpInst::Predicate Pred);
bool isInTailCallPosition(ImmutableCallSite CS, Attributes CalleeRetAttr,
const TargetLowering &TLI);
bool isInTailCallPosition(SelectionDAG &DAG, SDNode *Node,
const TargetLowering &TLI);
} // End llvm namespace
#endif

View File

@ -17,7 +17,7 @@
#define LLVM_CODEGEN_ASMPRINTER_H
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/Support/DebugLoc.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
class BlockAddress;
@ -49,6 +49,7 @@ namespace llvm {
class MCSection;
class MCStreamer;
class MCSymbol;
class MDNode;
class DwarfDebug;
class DwarfException;
class Mangler;
@ -388,7 +389,7 @@ namespace llvm {
/// frame.
void EmitFrameMoves(const std::vector<MachineMove> &Moves,
MCSymbol *BaseLabel, bool isEH) const;
void EmitCFIFrameMoves(const std::vector<MachineMove> &Moves) const;
//===------------------------------------------------------------------===//
// Inline Asm Support
@ -432,7 +433,7 @@ namespace llvm {
mutable unsigned SetCounter;
/// EmitInlineAsm - Emit a blob of inline asm to the output streamer.
void EmitInlineAsm(StringRef Str, unsigned LocCookie) const;
void EmitInlineAsm(StringRef Str, const MDNode *LocMDNode = 0) const;
/// EmitInlineAsm - This method formats and emits the specified machine
/// instruction that is an inline asm.

View File

@ -16,7 +16,7 @@
#define LLVM_CODEGEN_BINARYOBJECT_H
#include "llvm/CodeGen/MachineRelocation.h"
#include "llvm/System/DataTypes.h"
#include "llvm/Support/DataTypes.h"
#include <string>
#include <vector>

View File

@ -20,6 +20,26 @@ namespace llvm {
class LiveIntervals;
class MachineLoopInfo;
/// normalizeSpillWeight - The spill weight of a live interval is computed as:
///
/// (sum(use freq) + sum(def freq)) / (K + size)
///
/// @param UseDefFreq Expected number of executed use and def instructions
/// per function call. Derived from block frequencies.
/// @param Size Size of live interval as returnexd by getSize()
///
static inline float normalizeSpillWeight(float UseDefFreq, unsigned Size) {
// The magic constant 200 corresponds to approx. 25 instructions since
// SlotIndexes allocate 8 slots per instruction.
//
// The constant is added to avoid depending too much on accidental SlotIndex
// gaps for small intervals. The effect is that small intervals have a spill
// weight that is mostly proportional to the number of uses, while large
// intervals get a spill weight that is closer to a use density.
//
return UseDefFreq / (Size + 200);
}
/// VirtRegAuxInfo - Calculate auxiliary information for a virtual
/// register such as its spill weight and allocation hint.
class VirtRegAuxInfo {
@ -48,7 +68,9 @@ namespace llvm {
public:
static char ID;
CalculateSpillWeights() : MachineFunctionPass(ID) {}
CalculateSpillWeights() : MachineFunctionPass(ID) {
initializeCalculateSpillWeightsPass(*PassRegistry::getPassRegistry());
}
virtual void getAnalysisUsage(AnalysisUsage &au) const;

View File

@ -57,14 +57,14 @@ private:
LocInfo HTP : 6;
/// ValVT - The type of the value being assigned.
EVT ValVT;
MVT ValVT;
/// LocVT - The type of the location being assigned to.
EVT LocVT;
MVT LocVT;
public:
static CCValAssign getReg(unsigned ValNo, EVT ValVT,
unsigned RegNo, EVT LocVT,
static CCValAssign getReg(unsigned ValNo, MVT ValVT,
unsigned RegNo, MVT LocVT,
LocInfo HTP) {
CCValAssign Ret;
Ret.ValNo = ValNo;
@ -77,8 +77,8 @@ public:
return Ret;
}
static CCValAssign getCustomReg(unsigned ValNo, EVT ValVT,
unsigned RegNo, EVT LocVT,
static CCValAssign getCustomReg(unsigned ValNo, MVT ValVT,
unsigned RegNo, MVT LocVT,
LocInfo HTP) {
CCValAssign Ret;
Ret = getReg(ValNo, ValVT, RegNo, LocVT, HTP);
@ -86,8 +86,8 @@ public:
return Ret;
}
static CCValAssign getMem(unsigned ValNo, EVT ValVT,
unsigned Offset, EVT LocVT,
static CCValAssign getMem(unsigned ValNo, MVT ValVT,
unsigned Offset, MVT LocVT,
LocInfo HTP) {
CCValAssign Ret;
Ret.ValNo = ValNo;
@ -100,8 +100,8 @@ public:
return Ret;
}
static CCValAssign getCustomMem(unsigned ValNo, EVT ValVT,
unsigned Offset, EVT LocVT,
static CCValAssign getCustomMem(unsigned ValNo, MVT ValVT,
unsigned Offset, MVT LocVT,
LocInfo HTP) {
CCValAssign Ret;
Ret = getMem(ValNo, ValVT, Offset, LocVT, HTP);
@ -110,7 +110,7 @@ public:
}
unsigned getValNo() const { return ValNo; }
EVT getValVT() const { return ValVT; }
MVT getValVT() const { return ValVT; }
bool isRegLoc() const { return !isMem; }
bool isMemLoc() const { return isMem; }
@ -119,7 +119,7 @@ public:
unsigned getLocReg() const { assert(isRegLoc()); return Loc; }
unsigned getLocMemOffset() const { assert(isMemLoc()); return Loc; }
EVT getLocVT() const { return LocVT; }
MVT getLocVT() const { return LocVT; }
LocInfo getLocInfo() const { return HTP; }
bool isExtInLoc() const {
@ -129,16 +129,16 @@ public:
};
/// CCAssignFn - This function assigns a location for Val, updating State to
/// reflect the change.
typedef bool CCAssignFn(unsigned ValNo, EVT ValVT,
EVT LocVT, CCValAssign::LocInfo LocInfo,
/// reflect the change. It returns 'true' if it failed to handle Val.
typedef bool CCAssignFn(unsigned ValNo, MVT ValVT,
MVT LocVT, CCValAssign::LocInfo LocInfo,
ISD::ArgFlagsTy ArgFlags, CCState &State);
/// CCCustomFn - This function assigns a location for Val, possibly updating
/// all args to reflect changes and indicates if it handled it. It must set
/// isCustom if it handles the arg and returns true.
typedef bool CCCustomFn(unsigned &ValNo, EVT &ValVT,
EVT &LocVT, CCValAssign::LocInfo &LocInfo,
typedef bool CCCustomFn(unsigned &ValNo, MVT &ValVT,
MVT &LocVT, CCValAssign::LocInfo &LocInfo,
ISD::ArgFlagsTy &ArgFlags, CCState &State);
/// CCState - This class holds information needed while lowering arguments and
@ -198,7 +198,7 @@ public:
/// AnalyzeCallOperands - Same as above except it takes vectors of types
/// and argument flags.
void AnalyzeCallOperands(SmallVectorImpl<EVT> &ArgVTs,
void AnalyzeCallOperands(SmallVectorImpl<MVT> &ArgVTs,
SmallVectorImpl<ISD::ArgFlagsTy> &Flags,
CCAssignFn Fn);
@ -209,7 +209,7 @@ public:
/// AnalyzeCallResult - Same as above except it's specialized for calls which
/// produce a single value.
void AnalyzeCallResult(EVT VT, CCAssignFn Fn);
void AnalyzeCallResult(MVT VT, CCAssignFn Fn);
/// getFirstUnallocated - Return the first unallocated register in the set, or
/// NumRegs if they are all allocated.
@ -284,8 +284,8 @@ public:
// HandleByVal - Allocate a stack slot large enough to pass an argument by
// value. The size and alignment information of the argument is encoded in its
// parameter attribute.
void HandleByVal(unsigned ValNo, EVT ValVT,
EVT LocVT, CCValAssign::LocInfo LocInfo,
void HandleByVal(unsigned ValNo, MVT ValVT,
MVT LocVT, CCValAssign::LocInfo LocInfo,
int MinSize, int MinAlign, ISD::ArgFlagsTy ArgFlags);
private:

View File

@ -0,0 +1,61 @@
//===-------- EdgeBundles.h - Bundles of CFG edges --------------*- c++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// The EdgeBundles analysis forms equivalence classes of CFG edges such that all
// edges leaving a machine basic block are in the same bundle, and all edges
// leaving a basic block are in the same bundle.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_EDGEBUNDLES_H
#define LLVM_CODEGEN_EDGEBUNDLES_H
#include "llvm/ADT/IntEqClasses.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
namespace llvm {
class EdgeBundles : public MachineFunctionPass {
const MachineFunction *MF;
/// EC - Each edge bundle is an equivalence class. The keys are:
/// 2*BB->getNumber() -> Ingoing bundle.
/// 2*BB->getNumber()+1 -> Outgoing bundle.
IntEqClasses EC;
public:
static char ID;
EdgeBundles() : MachineFunctionPass(ID) {}
/// getBundle - Return the ingoing (Out = false) or outgoing (Out = true)
/// bundle number for basic block #N
unsigned getBundle(unsigned N, bool Out) const { return EC[2 * N + Out]; }
/// getNumBundles - Return the total number of bundles in the CFG.
unsigned getNumBundles() const { return EC.getNumClasses(); }
/// getMachineFunction - Return the last machine function computed.
const MachineFunction *getMachineFunction() const { return MF; }
/// view - Visualize the annotated bipartite CFG with Graphviz.
void view() const;
private:
virtual bool runOnMachineFunction(MachineFunction&);
virtual void getAnalysisUsage(AnalysisUsage&) const;
};
/// Specialize WriteGraph, the standard implementation won't work.
raw_ostream &WriteGraph(raw_ostream &O, const EdgeBundles &G,
bool ShortNames = false,
const std::string &Title = "");
} // end namespace llvm
#endif

View File

@ -15,9 +15,6 @@
#define LLVM_CODEGEN_FASTISEL_H
#include "llvm/ADT/DenseMap.h"
#ifndef NDEBUG
#include "llvm/ADT/SmallSet.h"
#endif
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
@ -39,6 +36,7 @@ class TargetLowering;
class TargetMachine;
class TargetRegisterClass;
class TargetRegisterInfo;
class LoadInst;
/// FastISel - This is a fast-path instruction selection class that
/// generates poor code and doesn't support illegal types or non-trivial
@ -102,7 +100,16 @@ public:
/// index value.
std::pair<unsigned, bool> getRegForGEPIndex(const Value *V);
/// recomputeInsertPt - Reset InsertPt to prepare for insterting instructions
/// TryToFoldLoad - The specified machine instr operand is a vreg, and that
/// vreg is being provided by the specified load instruction. If possible,
/// try to fold the load as an operand to the instruction, returning true if
/// possible.
virtual bool TryToFoldLoad(MachineInstr * /*MI*/, unsigned /*OpNo*/,
const LoadInst * /*LI*/) {
return false;
}
/// recomputeInsertPt - Reset InsertPt to prepare for inserting instructions
/// into the current block.
void recomputeInsertPt();

View File

@ -19,6 +19,7 @@
#include "llvm/Instructions.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IndexedMap.h"
#include "llvm/ADT/SmallVector.h"
#ifndef NDEBUG
#include "llvm/ADT/SmallSet.h"
@ -27,6 +28,7 @@
#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include <vector>
namespace llvm {
@ -104,9 +106,8 @@ public:
LiveOutInfo() : NumSignBits(0), KnownOne(1, 0), KnownZero(1, 0) {}
};
/// LiveOutRegInfo - Information about live out vregs, indexed by their
/// register number offset by 'FirstVirtualRegister'.
std::vector<LiveOutInfo> LiveOutRegInfo;
/// LiveOutRegInfo - Information about live out vregs.
IndexedMap<LiveOutInfo, VirtReg2IndexFunctor> LiveOutRegInfo;
/// PHINodesToUpdate - A list of phi instructions whose operand list will
/// be updated after processing the current basic block.

View File

@ -36,6 +36,7 @@
#include "llvm/Pass.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/DebugLoc.h"
namespace llvm {
class AsmPrinter;
@ -59,8 +60,10 @@ namespace llvm {
struct GCPoint {
GC::PointKind Kind; //< The kind of the safe point.
MCSymbol *Label; //< A label.
DebugLoc Loc;
GCPoint(GC::PointKind K, MCSymbol *L) : Kind(K), Label(L) {}
GCPoint(GC::PointKind K, MCSymbol *L, DebugLoc DL)
: Kind(K), Label(L), Loc(DL) {}
};
/// GCRoot - Metadata for a pointer to an object managed by the garbage
@ -121,8 +124,8 @@ namespace llvm {
/// addSafePoint - Notes the existence of a safe point. Num is the ID of the
/// label just prior to the safe point (if the code generator is using
/// MachineModuleInfo).
void addSafePoint(GC::PointKind Kind, MCSymbol *Label) {
SafePoints.push_back(GCPoint(Kind, Label));
void addSafePoint(GC::PointKind Kind, MCSymbol *Label, DebugLoc DL) {
SafePoints.push_back(GCPoint(Kind, Label, DL));
}
/// getFrameSize/setFrameSize - Records the function's frame size.

View File

@ -107,6 +107,13 @@ namespace ISD {
// and returns an outchain.
EH_SJLJ_LONGJMP,
// OUTCHAIN = EH_SJLJ_DISPATCHSETUP(INCHAIN, context)
// This corresponds to the eh.sjlj.dispatchsetup intrinsic. It takes an
// input chain and a pointer to the sjlj function context as inputs and
// returns an outchain. By default, this does nothing. Targets can lower
// this to unwind setup code if needed.
EH_SJLJ_DISPATCHSETUP,
// TargetConstant* - Like Constant*, but the DAG does not do any folding,
// simplification, or lowering of the constant. They are used for constants
// which are known to fit in the immediate fields of their users, or for
@ -262,16 +269,24 @@ namespace ISD {
/// lengths of the input vectors.
CONCAT_VECTORS,
/// INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector
/// with VECTOR2 inserted into VECTOR1 at the (potentially
/// variable) element number IDX, which must be a multiple of the
/// VECTOR2 vector length. The elements of VECTOR1 starting at
/// IDX are overwritten with VECTOR2. Elements IDX through
/// vector_length(VECTOR2) must be valid VECTOR1 indices.
INSERT_SUBVECTOR,
/// EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR (an
/// vector value) starting with the (potentially variable) element number
/// IDX, which must be a multiple of the result vector length.
/// vector value) starting with the element number IDX, which must be a
/// constant multiple of the result vector length.
EXTRACT_SUBVECTOR,
/// VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as
/// VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as
/// VEC1/VEC2. A VECTOR_SHUFFLE node also contains an array of constant int
/// values that indicate which value (or undef) each result element will
/// get. These constant ints are accessible through the
/// ShuffleVectorSDNode class. This is quite similar to the Altivec
/// get. These constant ints are accessible through the
/// ShuffleVectorSDNode class. This is quite similar to the Altivec
/// 'vperm' instruction, except that the indices must be constants and are
/// in terms of the element size of VEC1/VEC2, not in terms of bytes.
VECTOR_SHUFFLE,
@ -288,13 +303,21 @@ namespace ISD {
// an unsigned/signed value of type i[2*N], then return the top part.
MULHU, MULHS,
// Bitwise operators - logical and, logical or, logical xor, shift left,
// shift right algebraic (shift in sign bits), shift right logical (shift in
// zeroes), rotate left, rotate right, and byteswap.
AND, OR, XOR, SHL, SRA, SRL, ROTL, ROTR, BSWAP,
/// Bitwise operators - logical and, logical or, logical xor.
AND, OR, XOR,
/// Shift and rotation operations. After legalization, the type of the
/// shift amount is known to be TLI.getShiftAmountTy(). Before legalization
/// the shift amount can be any type, but care must be taken to ensure it is
/// large enough. TLI.getShiftAmountTy() is i8 on some targets, but before
/// legalization, types like i1024 can occur and i8 doesn't have enough bits
/// to represent the shift amount. By convention, DAGCombine and
/// SelectionDAGBuilder forces these shift amounts to i32 for simplicity.
///
SHL, SRA, SRL, ROTL, ROTR,
// Counting operators
CTTZ, CTLZ, CTPOP,
/// Byte Swap and Counting operators.
BSWAP, CTTZ, CTLZ, CTPOP,
// Select(COND, TRUEVAL, FALSEVAL). If the type of the boolean COND is not
// i1 then the high bits must conform to getBooleanContents.
@ -392,14 +415,14 @@ namespace ISD {
/// X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
FP_EXTEND,
// BIT_CONVERT - This operator converts between integer, vector and FP
// BITCAST - This operator converts between integer, vector and FP
// values, as if the value was stored to memory with one type and loaded
// from the same address with the other type (or equivalently for vector
// format conversions, etc). The source and result are required to have
// the same bit size (e.g. f32 <-> i32). This can also be used for
// int-to-int or fp-to-fp conversions, but that is a noop, deleted by
// getNode().
BIT_CONVERT,
BITCAST,
// CONVERT_RNDSAT - This operator is used to support various conversions
// between various types (float, signed, unsigned and vectors of those
@ -475,6 +498,7 @@ namespace ISD {
// Operand #0 : Input chain.
// Operand #1 : a ExternalSymbolSDNode with a pointer to the asm string.
// Operand #2 : a MDNodeSDNode with the !srcloc metadata.
// Operand #3 : HasSideEffect, IsAlignStack bits.
// After this, it is followed by a list of operands with this format:
// ConstantSDNode: Flags that encode whether it is a mem or not, the
// of operands that follow, etc. See InlineAsm.h.
@ -525,7 +549,7 @@ namespace ISD {
// SRCVALUE - This is a node type that holds a Value* that is used to
// make reference to a value in the LLVM IR.
SRCVALUE,
// MDNODE_SDNODE - This is a node that holdes an MDNode*, which is used to
// reference metadata in the IR.
MDNODE_SDNODE,

View File

@ -48,6 +48,11 @@ namespace llvm {
/// be capable of handling this kind of change.
///
void LowerIntrinsicCall(CallInst *CI);
/// LowerToByteSwap - Replace a call instruction into a call to bswap
/// intrinsic. Return false if it has determined the call is not a
/// simple integer bswap.
static bool LowerToByteSwap(CallInst *CI);
};
}

View File

@ -18,7 +18,7 @@
#define LLVM_CODEGEN_JITCODEEMITTER_H
#include <string>
#include "llvm/System/DataTypes.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/CodeGen/MachineCodeEmitter.h"
#include "llvm/ADT/DenseMap.h"

View File

@ -20,25 +20,25 @@
namespace llvm {
class LatencyPriorityQueue;
/// Sorting functions for the Available queue.
struct latency_sort : public std::binary_function<SUnit*, SUnit*, bool> {
LatencyPriorityQueue *PQ;
explicit latency_sort(LatencyPriorityQueue *pq) : PQ(pq) {}
bool operator()(const SUnit* left, const SUnit* right) const;
};
class LatencyPriorityQueue : public SchedulingPriorityQueue {
// SUnits - The SUnits for the current graph.
std::vector<SUnit> *SUnits;
/// NumNodesSolelyBlocking - This vector contains, for every node in the
/// Queue, the number of nodes that the node is the sole unscheduled
/// predecessor for. This is used as a tie-breaker heuristic for better
/// mobility.
std::vector<unsigned> NumNodesSolelyBlocking;
/// Queue - The queue.
std::vector<SUnit*> Queue;
latency_sort Picker;
@ -47,6 +47,8 @@ namespace llvm {
LatencyPriorityQueue() : Picker(this) {
}
bool isBottomUp() const { return false; }
void initNodes(std::vector<SUnit> &sunits) {
SUnits = &sunits;
NumNodesSolelyBlocking.resize(SUnits->size(), 0);
@ -62,25 +64,27 @@ namespace llvm {
void releaseState() {
SUnits = 0;
}
unsigned getLatency(unsigned NodeNum) const {
assert(NodeNum < (*SUnits).size());
return (*SUnits)[NodeNum].getHeight();
}
unsigned getNumSolelyBlockNodes(unsigned NodeNum) const {
assert(NodeNum < NumNodesSolelyBlocking.size());
return NumNodesSolelyBlocking[NodeNum];
}
bool empty() const { return Queue.empty(); }
virtual void push(SUnit *U);
virtual SUnit *pop();
virtual void remove(SUnit *SU);
virtual void dump(ScheduleDAG* DAG) const;
// ScheduledNode - As nodes are scheduled, we look to see if there are any
// successor nodes that have a single unscheduled predecessor. If so, that
// single predecessor has a higher priority, since scheduling it will make

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