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:
commit
a0b20b5d1f
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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" {
|
||||
|
40
contrib/llvm/include/llvm-c/Initialization.h
Normal file
40
contrib/llvm/include/llvm-c/Initialization.h
Normal 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
|
@ -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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
@ -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) {
|
||||
|
121
contrib/llvm/include/llvm/ADT/ArrayRef.h
Normal file
121
contrib/llvm/include/llvm/ADT/ArrayRef.h
Normal 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
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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; }
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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; }
|
||||
|
||||
|
@ -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
|
||||
|
77
contrib/llvm/include/llvm/ADT/InMemoryStruct.h
Normal file
77
contrib/llvm/include/llvm/ADT/InMemoryStruct.h
Normal 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
|
@ -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 {
|
||||
|
88
contrib/llvm/include/llvm/ADT/IntEqClasses.h
Normal file
88
contrib/llvm/include/llvm/ADT/IntEqClasses.h
Normal 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
|
2139
contrib/llvm/include/llvm/ADT/IntervalMap.h
Normal file
2139
contrib/llvm/include/llvm/ADT/IntervalMap.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
@ -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);}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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())
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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.
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
/// @{
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
||||
|
@ -38,6 +38,7 @@
|
||||
#ifndef LLVM_ADT_ILIST_H
|
||||
#define LLVM_ADT_ILIST_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
459
contrib/llvm/include/llvm/Analysis/DIBuilder.h
Normal file
459
contrib/llvm/include/llvm/Analysis/DIBuilder.h
Normal 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
|
@ -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";
|
||||
|
@ -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
|
||||
|
189
contrib/llvm/include/llvm/Analysis/DominanceFrontier.h
Normal file
189
contrib/llvm/include/llvm/Analysis/DominanceFrontier.h
Normal 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
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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()));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
304
contrib/llvm/include/llvm/Analysis/PathNumbering.h
Normal file
304
contrib/llvm/include/llvm/Analysis/PathNumbering.h
Normal 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
|
113
contrib/llvm/include/llvm/Analysis/PathProfileInfo.h
Normal file
113
contrib/llvm/include/llvm/Analysis/PathProfileInfo.h
Normal 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
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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 */
|
||||
|
@ -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()
|
||||
|
126
contrib/llvm/include/llvm/Analysis/RegionPass.h
Normal file
126
contrib/llvm/include/llvm/Analysis/RegionPass.h
Normal 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
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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; }
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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?
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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:
|
||||
|
61
contrib/llvm/include/llvm/CodeGen/EdgeBundles.h
Normal file
61
contrib/llvm/include/llvm/CodeGen/EdgeBundles.h
Normal 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
|
@ -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();
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user