Merge llvm 3.5.0 release from ^/vendor/llvm/dist, resolve conflicts, and

preserve our customizations, where necessary.
This commit is contained in:
Dimitry Andric 2014-11-24 17:02:24 +00:00
commit 91bc56ed82
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/clang350-import/; revision=274968
2134 changed files with 257653 additions and 130928 deletions

View File

@ -4,7 +4,7 @@ LLVM Release License
University of Illinois/NCSA
Open Source License
Copyright (c) 2003-2013 University of Illinois at Urbana-Champaign.
Copyright (c) 2003-2014 University of Illinois at Urbana-Champaign.
All rights reserved.
Developed by:
@ -63,7 +63,6 @@ Program Directory
------- ---------
Autoconf llvm/autoconf
llvm/projects/ModuleMaker/autoconf
llvm/projects/sample/autoconf
Google Test llvm/utils/unittest/googletest
OpenBSD regex llvm/lib/Support/{reg*, COPYRIGHT.regex}
pyyaml tests llvm/test/YAMLParser/{*.data, LICENSE.TXT}

View File

@ -15,7 +15,7 @@
#ifndef LLVM_C_CORE_H
#define LLVM_C_CORE_H
#include "llvm/Support/DataTypes.h"
#include "llvm-c/Support.h"
#ifdef __cplusplus
extern "C" {
@ -62,8 +62,6 @@ extern "C" {
* @{
*/
typedef int LLVMBool;
/* Opaque types. */
/**
@ -114,13 +112,6 @@ typedef struct LLVMOpaqueBuilder *LLVMBuilderRef;
*/
typedef struct LLVMOpaqueModuleProvider *LLVMModuleProviderRef;
/**
* Used to provide a module to JIT or interpreter.
*
* @see llvm::MemoryBuffer
*/
typedef struct LLVMOpaqueMemoryBuffer *LLVMMemoryBufferRef;
/** @see llvm::PassManagerBase */
typedef struct LLVMOpaquePassManager *LLVMPassManagerRef;
@ -133,6 +124,12 @@ typedef struct LLVMOpaquePassRegistry *LLVMPassRegistryRef;
* @see llvm::Use */
typedef struct LLVMOpaqueUse *LLVMUseRef;
/**
* @see llvm::DiagnosticInfo
*/
typedef struct LLVMOpaqueDiagnosticInfo *LLVMDiagnosticInfoRef;
typedef enum {
LLVMZExtAttribute = 1<<0,
LLVMSExtAttribute = 1<<1,
@ -167,7 +164,11 @@ typedef enum {
LLVMAddressSafety = 1ULL << 32,
LLVMStackProtectStrongAttribute = 1ULL<<33,
LLVMCold = 1ULL << 34,
LLVMOptimizeNone = 1ULL << 35
LLVMOptimizeNone = 1ULL << 35,
LLVMInAllocaAttribute = 1ULL << 36,
LLVMNonNullAttribute = 1ULL << 37,
LLVMJumpTableAttribute = 1ULL << 38,
LLVMDereferenceableAttribute = 1ULL << 39,
*/
} LLVMAttribute;
@ -283,8 +284,8 @@ typedef enum {
LLVMInternalLinkage, /**< Rename collisions when linking (static
functions) */
LLVMPrivateLinkage, /**< Like Internal, but omit from symbol table */
LLVMDLLImportLinkage, /**< Function to be imported from DLL */
LLVMDLLExportLinkage, /**< Function to be accessible from DLL */
LLVMDLLImportLinkage, /**< Obsolete */
LLVMDLLExportLinkage, /**< Obsolete */
LLVMExternalWeakLinkage,/**< ExternalWeak linkage description */
LLVMGhostLinkage, /**< Obsolete */
LLVMCommonLinkage, /**< Tentative definitions */
@ -298,6 +299,12 @@ typedef enum {
LLVMProtectedVisibility /**< The GV is protected */
} LLVMVisibility;
typedef enum {
LLVMDefaultStorageClass = 0,
LLVMDLLImportStorageClass = 1, /**< Function to be imported from DLL. */
LLVMDLLExportStorageClass = 2 /**< Function to be accessible from DLL. */
} LLVMDLLStorageClass;
typedef enum {
LLVMCCallConv = 0,
LLVMFastCallConv = 8,
@ -402,6 +409,13 @@ typedef enum {
the old one */
} LLVMAtomicRMWBinOp;
typedef enum {
LLVMDSError,
LLVMDSWarning,
LLVMDSRemark,
LLVMDSNote
} LLVMDiagnosticSeverity;
/**
* @}
*/
@ -455,6 +469,9 @@ void LLVMEnablePrettyStackTrace(void);
* @{
*/
typedef void (*LLVMDiagnosticHandler)(LLVMDiagnosticInfoRef, void *);
typedef void (*LLVMYieldCallback)(LLVMContextRef, void *);
/**
* Create a new context.
*
@ -468,6 +485,21 @@ LLVMContextRef LLVMContextCreate(void);
*/
LLVMContextRef LLVMGetGlobalContext(void);
/**
* Set the diagnostic handler for this context.
*/
void LLVMContextSetDiagnosticHandler(LLVMContextRef C,
LLVMDiagnosticHandler Handler,
void *DiagnosticContext);
/**
* Set the yield callback function for this context.
*
* @see LLVMContext::setYieldCallback()
*/
void LLVMContextSetYieldCallback(LLVMContextRef C, LLVMYieldCallback Callback,
void *OpaqueHandle);
/**
* Destroy a context instance.
*
@ -476,6 +508,21 @@ LLVMContextRef LLVMGetGlobalContext(void);
*/
void LLVMContextDispose(LLVMContextRef C);
/**
* Return a string representation of the DiagnosticInfo. Use
* LLVMDisposeMessage to free the string.
*
* @see DiagnosticInfo::print()
*/
char *LLVMGetDiagInfoDescription(LLVMDiagnosticInfoRef DI);
/**
* Return an enum LLVMDiagnosticSeverity.
*
* @see DiagnosticInfo::getSeverity()
*/
LLVMDiagnosticSeverity LLVMGetDiagInfoSeverity(LLVMDiagnosticInfoRef DI);
unsigned LLVMGetMDKindIDInContext(LLVMContextRef C, const char* Name,
unsigned SLen);
unsigned LLVMGetMDKindID(const char* Name, unsigned SLen);
@ -1123,9 +1170,10 @@ LLVMTypeRef LLVMX86MMXType(void);
macro(ConstantStruct) \
macro(ConstantVector) \
macro(GlobalValue) \
macro(Function) \
macro(GlobalAlias) \
macro(GlobalVariable) \
macro(GlobalObject) \
macro(Function) \
macro(GlobalVariable) \
macro(UndefValue) \
macro(Instruction) \
macro(BinaryOperator) \
@ -1688,6 +1736,10 @@ const char *LLVMGetSection(LLVMValueRef Global);
void LLVMSetSection(LLVMValueRef Global, const char *Section);
LLVMVisibility LLVMGetVisibility(LLVMValueRef Global);
void LLVMSetVisibility(LLVMValueRef Global, LLVMVisibility Viz);
LLVMDLLStorageClass LLVMGetDLLStorageClass(LLVMValueRef Global);
void LLVMSetDLLStorageClass(LLVMValueRef Global, LLVMDLLStorageClass Class);
LLVMBool LLVMHasUnnamedAddr(LLVMValueRef Global);
void LLVMSetUnnamedAddr(LLVMValueRef Global, LLVMBool HasUnnamedAddr);
/**
* @defgroup LLVMCCoreValueWithAlignment Values with alignment
@ -1698,6 +1750,7 @@ void LLVMSetVisibility(LLVMValueRef Global, LLVMVisibility Viz);
/**
* Obtain the preferred alignment of the value.
* @see llvm::AllocaInst::getAlignment()
* @see llvm::LoadInst::getAlignment()
* @see llvm::StoreInst::getAlignment()
* @see llvm::GlobalValue::getAlignment()
@ -1706,6 +1759,7 @@ unsigned LLVMGetAlignment(LLVMValueRef V);
/**
* Set the preferred alignment of the value.
* @see llvm::AllocaInst::setAlignment()
* @see llvm::LoadInst::setAlignment()
* @see llvm::StoreInst::setAlignment()
* @see llvm::GlobalValue::setAlignment()
@ -2663,7 +2717,9 @@ LLVMValueRef LLVMBuildIsNotNull(LLVMBuilderRef, LLVMValueRef Val,
const char *Name);
LLVMValueRef LLVMBuildPtrDiff(LLVMBuilderRef, LLVMValueRef LHS,
LLVMValueRef RHS, const char *Name);
LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B,LLVMAtomicRMWBinOp op,
LLVMValueRef LLVMBuildFence(LLVMBuilderRef B, LLVMAtomicOrdering ordering,
LLVMBool singleThread, const char *Name);
LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B, LLVMAtomicRMWBinOp op,
LLVMValueRef PTR, LLVMValueRef Val,
LLVMAtomicOrdering ordering,
LLVMBool singleThread);
@ -2793,16 +2849,13 @@ void LLVMDisposePassManager(LLVMPassManagerRef PM);
* @{
*/
/** Allocate and initialize structures needed to make LLVM safe for
multithreading. The return value indicates whether multithreaded
initialization succeeded. Must be executed in isolation from all
other LLVM api calls.
@see llvm::llvm_start_multithreaded */
/** Deprecated: Multi-threading can only be enabled/disabled with the compile
time define LLVM_ENABLE_THREADS. This function always returns
LLVMIsMultithreaded(). */
LLVMBool LLVMStartMultithreaded(void);
/** Deallocate structures necessary to make LLVM safe for multithreading.
Must be executed in isolation from all other LLVM api calls.
@see llvm::llvm_stop_multithreaded */
/** Deprecated: Multi-threading can only be enabled/disabled with the compile
time define LLVM_ENABLE_THREADS. */
void LLVMStopMultithreaded(void);
/** Check whether LLVM is executing in thread-safe mode or not.

View File

@ -95,6 +95,16 @@ struct LLVMOpInfo1 {
#define LLVMDisassembler_VariantKind_ARM_HI16 1 /* :upper16: */
#define LLVMDisassembler_VariantKind_ARM_LO16 2 /* :lower16: */
/**
* The ARM64 target VariantKinds.
*/
#define LLVMDisassembler_VariantKind_ARM64_PAGE 1 /* @page */
#define LLVMDisassembler_VariantKind_ARM64_PAGEOFF 2 /* @pageoff */
#define LLVMDisassembler_VariantKind_ARM64_GOTPAGE 3 /* @gotpage */
#define LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF 4 /* @gotpageoff */
#define LLVMDisassembler_VariantKind_ARM64_TLVP 5 /* @tvlppage */
#define LLVMDisassembler_VariantKind_ARM64_TLVOFF 6 /* @tvlppageoff */
/**
* The type for the symbol lookup function. This may be called by the
* disassembler for things like adding a comment for a PC plus a constant
@ -123,6 +133,17 @@ typedef const char *(*LLVMSymbolLookupCallback)(void *DisInfo,
/* The input reference is from a PC relative load instruction. */
#define LLVMDisassembler_ReferenceType_In_PCrel_Load 2
/* The input reference is from an ARM64::ADRP instruction. */
#define LLVMDisassembler_ReferenceType_In_ARM64_ADRP 0x100000001
/* The input reference is from an ARM64::ADDXri instruction. */
#define LLVMDisassembler_ReferenceType_In_ARM64_ADDXri 0x100000002
/* The input reference is from an ARM64::LDRXui instruction. */
#define LLVMDisassembler_ReferenceType_In_ARM64_LDRXui 0x100000003
/* The input reference is from an ARM64::LDRXl instruction. */
#define LLVMDisassembler_ReferenceType_In_ARM64_LDRXl 0x100000004
/* The input reference is from an ARM64::ADR instruction. */
#define LLVMDisassembler_ReferenceType_In_ARM64_ADR 0x100000005
/* The output reference is to as symbol stub. */
#define LLVMDisassembler_ReferenceType_Out_SymbolStub 1
/* The output reference is to a symbol address in a literal pool. */
@ -141,6 +162,9 @@ typedef const char *(*LLVMSymbolLookupCallback)(void *DisInfo,
/* The output reference is to a Objective-C class ref. */
#define LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref 8
/* The output reference is to a C++ symbol name. */
#define LLVMDisassembler_ReferenceType_DeMangled_Name 9
#ifdef __cplusplus
extern "C" {
#endif /* !defined(__cplusplus) */

View File

@ -163,6 +163,8 @@ void *LLVMRecompileAndRelinkFunction(LLVMExecutionEngineRef EE,
LLVMValueRef Fn);
LLVMTargetDataRef LLVMGetExecutionEngineTargetData(LLVMExecutionEngineRef EE);
LLVMTargetMachineRef
LLVMGetExecutionEngineTargetMachine(LLVMExecutionEngineRef EE);
void LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global,
void* Addr);

View File

@ -24,7 +24,7 @@ extern "C" {
* Read LLVM IR from a memory buffer and convert it into an in-memory Module
* object. Returns 0 on success.
* Optionally returns a human-readable description of any errors that
* occured during parsing IR. OutMessage must be disposed with
* occurred during parsing IR. OutMessage must be disposed with
* LLVMDisposeMessage.
*
* @see llvm::ParseIR()

View File

@ -78,7 +78,6 @@ void LLVMMoveToNextRelocation(LLVMRelocationIteratorRef RI);
// SymbolRef accessors
const char *LLVMGetSymbolName(LLVMSymbolIteratorRef SI);
uint64_t LLVMGetSymbolAddress(LLVMSymbolIteratorRef SI);
uint64_t LLVMGetSymbolFileOffset(LLVMSymbolIteratorRef SI);
uint64_t LLVMGetSymbolSize(LLVMSymbolIteratorRef SI);
// RelocationRef accessors

View File

@ -14,12 +14,31 @@
#ifndef LLVM_C_SUPPORT_H
#define LLVM_C_SUPPORT_H
#include "llvm-c/Core.h"
#include "llvm/Support/DataTypes.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup LLVMCSupportTypes Types and Enumerations
*
* @{
*/
typedef int LLVMBool;
/**
* Used to pass regions of memory through LLVM interfaces.
*
* @see llvm::MemoryBuffer
*/
typedef struct LLVMOpaqueMemoryBuffer *LLVMMemoryBufferRef;
/**
* @}
*/
/**
* This function permanently loads the dynamic library at the given path.
* It is safe to call this function multiple times for the same library.

View File

@ -62,7 +62,7 @@ LLVMTargetRef LLVMGetFirstTarget(void);
LLVMTargetRef LLVMGetNextTarget(LLVMTargetRef T);
/*===-- Target ------------------------------------------------------------===*/
/** Finds the target corresponding to the given name and stores it in \p T.
/** Finds the target corresponding to the given name and stores it in \p T.
Returns 0 on success. */
LLVMTargetRef LLVMGetTargetFromName(const char *Name);
@ -137,6 +137,9 @@ LLVMBool LLVMTargetMachineEmitToMemoryBuffer(LLVMTargetMachineRef T, LLVMModuleR
disposed with LLVMDisposeMessage. */
char* LLVMGetDefaultTargetTriple(void);
/** Adds the target-specific analysis passes to the pass manager. */
void LLVMAddAnalysisPasses(LLVMTargetMachineRef T, LLVMPassManagerRef PM);
#ifdef __cplusplus
}
#endif

View File

@ -19,7 +19,6 @@
typedef struct LLVMOpaquePassManagerBuilder *LLVMPassManagerBuilderRef;
#ifdef __cplusplus
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
extern "C" {
#endif

View File

@ -41,6 +41,12 @@ void LLVMAddCFGSimplificationPass(LLVMPassManagerRef PM);
/** See llvm::createDeadStoreEliminationPass function. */
void LLVMAddDeadStoreEliminationPass(LLVMPassManagerRef PM);
/** See llvm::createScalarizerPass function. */
void LLVMAddScalarizerPass(LLVMPassManagerRef PM);
/** See llvm::createMergedLoadStoreMotionPass function. */
void LLVMAddMergedLoadStoreMotionPass(LLVMPassManagerRef PM);
/** See llvm::createGVNPass function. */
void LLVMAddGVNPass(LLVMPassManagerRef PM);

View File

@ -40,8 +40,11 @@ typedef bool lto_bool_t;
* @{
*/
#define LTO_API_VERSION 5
#define LTO_API_VERSION 10
/**
* \since prior to LTO_API_VERSION=3
*/
typedef enum {
LTO_SYMBOL_ALIGNMENT_MASK = 0x0000001F, /* log2 of alignment */
LTO_SYMBOL_PERMISSIONS_MASK = 0x000000E0,
@ -62,23 +65,29 @@ typedef enum {
LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN = 0x00002800
} lto_symbol_attributes;
/**
* \since prior to LTO_API_VERSION=3
*/
typedef enum {
LTO_DEBUG_MODEL_NONE = 0,
LTO_DEBUG_MODEL_DWARF = 1
} lto_debug_model;
/**
* \since prior to LTO_API_VERSION=3
*/
typedef enum {
LTO_CODEGEN_PIC_MODEL_STATIC = 0,
LTO_CODEGEN_PIC_MODEL_DYNAMIC = 1,
LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC = 2
LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC = 2,
LTO_CODEGEN_PIC_MODEL_DEFAULT = 3
} lto_codegen_model;
/** opaque reference to a loaded object module */
typedef struct LTOModule* lto_module_t;
typedef struct LLVMOpaqueLTOModule *lto_module_t;
/** opaque reference to a code generator */
typedef struct LTOCodeGenerator* lto_code_gen_t;
typedef struct LLVMOpaqueLTOCodeGenerator *lto_code_gen_t;
#ifdef __cplusplus
extern "C" {
@ -86,6 +95,8 @@ extern "C" {
/**
* Returns a printable string.
*
* \since prior to LTO_API_VERSION=3
*/
extern const char*
lto_get_version(void);
@ -93,12 +104,16 @@ lto_get_version(void);
/**
* Returns the last error string or NULL if last operation was successful.
*
* \since prior to LTO_API_VERSION=3
*/
extern const char*
lto_get_error_message(void);
/**
* Checks if a file is a loadable object file.
*
* \since prior to LTO_API_VERSION=3
*/
extern lto_bool_t
lto_module_is_object_file(const char* path);
@ -106,6 +121,8 @@ lto_module_is_object_file(const char* path);
/**
* Checks if a file is a loadable object compiled for requested target.
*
* \since prior to LTO_API_VERSION=3
*/
extern lto_bool_t
lto_module_is_object_file_for_target(const char* path,
@ -114,6 +131,8 @@ lto_module_is_object_file_for_target(const char* path,
/**
* Checks if a buffer is a loadable object file.
*
* \since prior to LTO_API_VERSION=3
*/
extern lto_bool_t
lto_module_is_object_file_in_memory(const void* mem, size_t length);
@ -121,6 +140,8 @@ lto_module_is_object_file_in_memory(const void* mem, size_t length);
/**
* Checks if a buffer is a loadable object compiled for requested target.
*
* \since prior to LTO_API_VERSION=3
*/
extern lto_bool_t
lto_module_is_object_file_in_memory_for_target(const void* mem, size_t length,
@ -130,6 +151,8 @@ lto_module_is_object_file_in_memory_for_target(const void* mem, size_t length,
/**
* Loads an object file from disk.
* Returns NULL on error (check lto_get_error_message() for details).
*
* \since prior to LTO_API_VERSION=3
*/
extern lto_module_t
lto_module_create(const char* path);
@ -138,13 +161,27 @@ lto_module_create(const char* path);
/**
* Loads an object file from memory.
* Returns NULL on error (check lto_get_error_message() for details).
*
* \since prior to LTO_API_VERSION=3
*/
extern lto_module_t
lto_module_create_from_memory(const void* mem, size_t length);
/**
* Loads an object file from memory with an extra path argument.
* Returns NULL on error (check lto_get_error_message() for details).
*
* \since prior to LTO_API_VERSION=9
*/
extern lto_module_t
lto_module_create_from_memory_with_path(const void* mem, size_t length,
const char *path);
/**
* 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).
*
* \since LTO_API_VERSION=5
*/
extern lto_module_t
lto_module_create_from_fd(int fd, const char *path, size_t file_size);
@ -152,28 +189,34 @@ lto_module_create_from_fd(int fd, const char *path, size_t file_size);
/**
* 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).
*
* \since LTO_API_VERSION=5
*/
extern lto_module_t
lto_module_create_from_fd_at_offset(int fd, const char *path, size_t file_size,
size_t map_size, off_t offset);
/**
* Frees all memory internally allocated by the module.
* Upon return the lto_module_t is no longer valid.
*
* \since prior to LTO_API_VERSION=3
*/
extern void
lto_module_dispose(lto_module_t mod);
/**
* Returns triple string which the object module was compiled under.
*
* \since prior to LTO_API_VERSION=3
*/
extern const char*
lto_module_get_target_triple(lto_module_t mod);
/**
* Sets triple string with which the object will be codegened.
*
* \since LTO_API_VERSION=4
*/
extern void
lto_module_set_target_triple(lto_module_t mod, const char *triple);
@ -181,6 +224,8 @@ lto_module_set_target_triple(lto_module_t mod, const char *triple);
/**
* Returns the number of symbols in the object module.
*
* \since prior to LTO_API_VERSION=3
*/
extern unsigned int
lto_module_get_num_symbols(lto_module_t mod);
@ -188,6 +233,8 @@ lto_module_get_num_symbols(lto_module_t mod);
/**
* Returns the name of the ith symbol in the object module.
*
* \since prior to LTO_API_VERSION=3
*/
extern const char*
lto_module_get_symbol_name(lto_module_t mod, unsigned int index);
@ -195,40 +242,116 @@ lto_module_get_symbol_name(lto_module_t mod, unsigned int index);
/**
* Returns the attributes of the ith symbol in the object module.
*
* \since prior to LTO_API_VERSION=3
*/
extern lto_symbol_attributes
lto_module_get_symbol_attribute(lto_module_t mod, unsigned int index);
/**
* Returns the number of dependent libraries in the object module.
*
* \since LTO_API_VERSION=8
*/
extern unsigned int
lto_module_get_num_deplibs(lto_module_t mod);
/**
* Returns the ith dependent library in the module.
*
* \since LTO_API_VERSION=8
*/
extern const char*
lto_module_get_deplib(lto_module_t mod, unsigned int index);
/**
* Returns the number of linker options in the object module.
*
* \since LTO_API_VERSION=8
*/
extern unsigned int
lto_module_get_num_linkeropts(lto_module_t mod);
/**
* Returns the ith linker option in the module.
*
* \since LTO_API_VERSION=8
*/
extern const char*
lto_module_get_linkeropt(lto_module_t mod, unsigned int index);
/**
* Diagnostic severity.
*
* \since LTO_API_VERSION=7
*/
typedef enum {
LTO_DS_ERROR = 0,
LTO_DS_WARNING = 1,
LTO_DS_REMARK = 3, // Added in LTO_API_VERSION=10.
LTO_DS_NOTE = 2
} lto_codegen_diagnostic_severity_t;
/**
* Diagnostic handler type.
* \p severity defines the severity.
* \p diag is the actual diagnostic.
* The diagnostic is not prefixed by any of severity keyword, e.g., 'error: '.
* \p ctxt is used to pass the context set with the diagnostic handler.
*
* \since LTO_API_VERSION=7
*/
typedef void (*lto_diagnostic_handler_t)(
lto_codegen_diagnostic_severity_t severity, const char *diag, void *ctxt);
/**
* Set a diagnostic handler and the related context (void *).
* This is more general than lto_get_error_message, as the diagnostic handler
* can be called at anytime within lto.
*
* \since LTO_API_VERSION=7
*/
extern void lto_codegen_set_diagnostic_handler(lto_code_gen_t,
lto_diagnostic_handler_t,
void *);
/**
* Instantiates a code generator.
* Returns NULL on error (check lto_get_error_message() for details).
*
* \since prior to LTO_API_VERSION=3
*/
extern lto_code_gen_t
lto_codegen_create(void);
/**
* Frees all code generator and all memory it internally allocated.
* Upon return the lto_code_gen_t is no longer valid.
*
* \since prior to LTO_API_VERSION=3
*/
extern void
lto_codegen_dispose(lto_code_gen_t);
/**
* Add an object module to the set of modules for which code will be generated.
* Returns true on error (check lto_get_error_message() for details).
*
* \since prior to LTO_API_VERSION=3
*/
extern lto_bool_t
lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod);
/**
* Sets if debug info should be generated.
* Returns true on error (check lto_get_error_message() for details).
*
* \since prior to LTO_API_VERSION=3
*/
extern lto_bool_t
lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model);
@ -237,6 +360,8 @@ lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model);
/**
* Sets which PIC code model to generated.
* Returns true on error (check lto_get_error_message() for details).
*
* \since prior to LTO_API_VERSION=3
*/
extern lto_bool_t
lto_codegen_set_pic_model(lto_code_gen_t cg, lto_codegen_model);
@ -244,6 +369,8 @@ lto_codegen_set_pic_model(lto_code_gen_t cg, lto_codegen_model);
/**
* Sets the cpu to generate code for.
*
* \since LTO_API_VERSION=4
*/
extern void
lto_codegen_set_cpu(lto_code_gen_t cg, const char *cpu);
@ -252,20 +379,27 @@ lto_codegen_set_cpu(lto_code_gen_t cg, const char *cpu);
/**
* Sets the location of the assembler tool to run. If not set, libLTO
* will use gcc to invoke the assembler.
*
* \since LTO_API_VERSION=3
*/
extern void
lto_codegen_set_assembler_path(lto_code_gen_t cg, const char* path);
/**
* Sets extra arguments that libLTO should pass to the assembler.
*
* \since LTO_API_VERSION=4
*/
extern void
lto_codegen_set_assembler_args(lto_code_gen_t cg, const char **args,
int nargs);
/**
* Tells LTO optimization passes that this symbol must be preserved
* because it is referenced by native code or a command line option.
* Adds to a list of all global symbols that must exist in the final generated
* code. If a function is not listed there, it might be inlined into every usage
* and optimized away.
*
* \since prior to LTO_API_VERSION=3
*/
extern void
lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg, const char* symbol);
@ -274,6 +408,8 @@ lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg, const char* symbol);
* Writes a new object file at the specified path that contains the
* merged contents of all modules added so far.
* Returns true on error (check lto_get_error_message() for details).
*
* \since LTO_API_VERSION=5
*/
extern lto_bool_t
lto_codegen_write_merged_modules(lto_code_gen_t cg, const char* path);
@ -285,6 +421,8 @@ lto_codegen_write_merged_modules(lto_code_gen_t cg, const char* path);
* lto_code_gen_t and will be freed when lto_codegen_dispose()
* is called, or lto_codegen_compile() is called again.
* On failure, returns NULL (check lto_get_error_message() for details).
*
* \since prior to LTO_API_VERSION=3
*/
extern const void*
lto_codegen_compile(lto_code_gen_t cg, size_t* length);
@ -292,6 +430,8 @@ lto_codegen_compile(lto_code_gen_t cg, size_t* length);
/**
* Generates code for all added modules into one native object file.
* The name of the file is written to name. Returns true on error.
*
* \since LTO_API_VERSION=5
*/
extern lto_bool_t
lto_codegen_compile_to_file(lto_code_gen_t cg, const char** name);
@ -299,6 +439,8 @@ lto_codegen_compile_to_file(lto_code_gen_t cg, const char** name);
/**
* Sets options to help debug codegen bugs.
*
* \since prior to LTO_API_VERSION=3
*/
extern void
lto_codegen_debug_options(lto_code_gen_t cg, const char *);
@ -306,6 +448,8 @@ lto_codegen_debug_options(lto_code_gen_t cg, const char *);
/**
* Initializes LLVM disassemblers.
* FIXME: This doesn't really belong here.
*
* \since LTO_API_VERSION=5
*/
extern void
lto_initialize_disassembler(void);

View File

@ -0,0 +1,4 @@
module LLVM_C {
umbrella "."
module * { export * }
}

View File

@ -1,4 +1,4 @@
//== llvm/Support/APFloat.h - Arbitrary Precision Floating Point -*- C++ -*-==//
//===- llvm/ADT/APFloat.h - Arbitrary Precision Floating Point ---*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
@ -196,6 +196,7 @@ class APFloat {
explicit APFloat(double d);
explicit APFloat(float f);
APFloat(const APFloat &);
APFloat(APFloat &&);
~APFloat();
/// @}
@ -235,19 +236,19 @@ class APFloat {
APInt fill(64, type);
return getQNaN(Sem, Negative, &fill);
} else {
return getQNaN(Sem, Negative, 0);
return getQNaN(Sem, Negative, nullptr);
}
}
/// Factory for QNaN values.
static APFloat getQNaN(const fltSemantics &Sem, bool Negative = false,
const APInt *payload = 0) {
const APInt *payload = nullptr) {
return makeNaN(Sem, false, Negative, payload);
}
/// Factory for SNaN values.
static APFloat getSNaN(const fltSemantics &Sem, bool Negative = false,
const APInt *payload = 0) {
const APInt *payload = nullptr) {
return makeNaN(Sem, true, Negative, payload);
}
@ -411,6 +412,7 @@ class APFloat {
/// @}
APFloat &operator=(const APFloat &);
APFloat &operator=(APFloat &&);
/// \brief Overload to compute a hash code for an APFloat value.
///
@ -498,7 +500,8 @@ class APFloat {
void makeLargest(bool Neg = false);
void makeSmallest(bool Neg = false);
void makeNaN(bool SNaN = false, bool Neg = false, const APInt *fill = 0);
void makeNaN(bool SNaN = false, bool Neg = false,
const APInt *fill = nullptr);
static APFloat makeNaN(const fltSemantics &Sem, bool SNaN, bool Negative,
const APInt *fill);
void makeInf(bool Neg = false);

View File

@ -284,12 +284,10 @@ class APInt {
initSlowCase(that);
}
#if LLVM_HAS_RVALUE_REFERENCES
/// \brief Move Constructor.
APInt(APInt &&that) : BitWidth(that.BitWidth), VAL(that.VAL) {
that.BitWidth = 0;
}
#endif
/// \brief Destructor.
~APInt() {
@ -656,7 +654,6 @@ class APInt {
return AssignSlowCase(RHS);
}
#if LLVM_HAS_RVALUE_REFERENCES
/// @brief Move assignment operator.
APInt &operator=(APInt &&that) {
if (!isSingleWord())
@ -669,7 +666,6 @@ class APInt {
return *this;
}
#endif
/// \brief Assignment operator.
///
@ -1265,7 +1261,7 @@ class APInt {
/// \returns the number of words to hold the integer value with a given bit
/// width.
static unsigned getNumWords(unsigned BitWidth) {
return (BitWidth + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD;
return ((uint64_t)BitWidth + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD;
}
/// \brief Compute the number of active bits in the value
@ -1504,6 +1500,35 @@ class APInt {
return BitWidth - (*this - 1).countLeadingZeros();
}
/// \returns the nearest log base 2 of this APInt. Ties round up.
///
/// NOTE: When we have a BitWidth of 1, we define:
///
/// log2(0) = UINT32_MAX
/// log2(1) = 0
///
/// to get around any mathematical concerns resulting from
/// referencing 2 in a space where 2 does no exist.
unsigned nearestLogBase2() const {
// Special case when we have a bitwidth of 1. If VAL is 1, then we
// get 0. If VAL is 0, we get UINT64_MAX which gets truncated to
// UINT32_MAX.
if (BitWidth == 1)
return VAL - 1;
// Handle the zero case.
if (!getBoolValue())
return UINT32_MAX;
// The non-zero case is handled by computing:
//
// nearestLogBase2(x) = logBase2(x) + x[logBase2(x)-1].
//
// where x[i] is referring to the value of the ith bit of x.
unsigned lg = logBase2();
return lg + unsigned((*this)[lg - 1]);
}
/// \returns the log base 2 of this APInt if its an exact power of two, -1
/// otherwise
int32_t exactLogBase2() const {

View File

@ -30,18 +30,12 @@ class APSInt : public APInt {
explicit APSInt(uint32_t BitWidth, bool isUnsigned = true)
: APInt(BitWidth, 0), IsUnsigned(isUnsigned) {}
explicit APSInt(const APInt &I, bool isUnsigned = true)
: APInt(I), IsUnsigned(isUnsigned) {}
explicit APSInt(APInt I, bool isUnsigned = true)
: APInt(std::move(I)), IsUnsigned(isUnsigned) {}
APSInt &operator=(const APSInt &RHS) {
APInt::operator=(RHS);
IsUnsigned = RHS.IsUnsigned;
return *this;
}
APSInt &operator=(const APInt &RHS) {
APSInt &operator=(APInt RHS) {
// Retain our current sign.
APInt::operator=(RHS);
APInt::operator=(std::move(RHS));
return *this;
}
@ -62,7 +56,7 @@ class APSInt : public APInt {
APInt::toString(Str, Radix, isSigned());
}
/// toString - Converts an APInt to a std::string. This is an inefficient
/// method, your should prefer passing in a SmallString instead.
/// method; you should prefer passing in a SmallString instead.
std::string toString(unsigned Radix) const {
return APInt::toString(Radix, isSigned());
}

View File

@ -48,10 +48,10 @@ namespace llvm {
/// @{
/// Construct an empty ArrayRef.
/*implicit*/ ArrayRef() : Data(0), Length(0) {}
/*implicit*/ ArrayRef() : Data(nullptr), Length(0) {}
/// Construct an empty ArrayRef from None.
/*implicit*/ ArrayRef(NoneType) : Data(0), Length(0) {}
/*implicit*/ ArrayRef(NoneType) : Data(nullptr), Length(0) {}
/// Construct an ArrayRef from a single element.
/*implicit*/ ArrayRef(const T &OneElt)
@ -76,7 +76,7 @@ namespace llvm {
/// Construct an ArrayRef from a std::vector.
template<typename A>
/*implicit*/ ArrayRef(const std::vector<T, A> &Vec)
: Data(Vec.empty() ? (T*)0 : &Vec[0]), Length(Vec.size()) {}
: Data(Vec.data()), Length(Vec.size()) {}
/// Construct an ArrayRef from a C array.
template <size_t N>
@ -120,14 +120,18 @@ namespace llvm {
return Data[Length-1];
}
// copy - Allocate copy in Allocator and return ArrayRef<T> to it.
template <typename Allocator> ArrayRef<T> copy(Allocator &A) {
T *Buff = A.template Allocate<T>(Length);
std::copy(begin(), end(), Buff);
return ArrayRef<T>(Buff, Length);
}
/// equals - Check for element-wise equality.
bool equals(ArrayRef RHS) const {
if (Length != RHS.Length)
return false;
for (size_type i = 0; i != Length; i++)
if (Data[i] != RHS.Data[i])
return false;
return true;
return std::equal(begin(), end(), RHS.begin());
}
/// slice(n) - Chop off the first N elements of the array.
@ -143,6 +147,12 @@ namespace llvm {
return ArrayRef<T>(data()+N, M);
}
// \brief Drop the last \p N elements of the array.
ArrayRef<T> drop_back(unsigned N = 1) const {
assert(size() >= N && "Dropping more elements than exist");
return slice(0, size() - N);
}
/// @}
/// @name Operator Overloads
/// @{
@ -213,7 +223,7 @@ namespace llvm {
/// Construct an MutableArrayRef from a C array.
template <size_t N>
/*implicit*/ MutableArrayRef(T (&Arr)[N])
/*implicit*/ LLVM_CONSTEXPR MutableArrayRef(T (&Arr)[N])
: ArrayRef<T>(Arr) {}
T *data() const { return const_cast<T*>(ArrayRef<T>::data()); }

View File

@ -34,6 +34,7 @@ class BitVector {
unsigned Capacity; // Size of allocated memory in BitWord.
public:
typedef unsigned size_type;
// Encapsulation of a single bit.
class reference {
friend class BitVector;
@ -58,21 +59,21 @@ class BitVector {
reference& operator=(bool t) {
if (t)
*WordRef |= 1L << BitPos;
*WordRef |= BitWord(1) << BitPos;
else
*WordRef &= ~(1L << BitPos);
*WordRef &= ~(BitWord(1) << BitPos);
return *this;
}
operator bool() const {
return ((*WordRef) & (1L << BitPos)) ? true : false;
return ((*WordRef) & (BitWord(1) << BitPos)) ? true : false;
}
};
/// BitVector default ctor - Creates an empty bitvector.
BitVector() : Size(0), Capacity(0) {
Bits = 0;
Bits = nullptr;
}
/// BitVector ctor - Creates a bitvector of specified number of bits. All
@ -88,7 +89,7 @@ class BitVector {
/// BitVector copy ctor.
BitVector(const BitVector &RHS) : Size(RHS.size()) {
if (Size == 0) {
Bits = 0;
Bits = nullptr;
Capacity = 0;
return;
}
@ -98,12 +99,10 @@ class BitVector {
std::memcpy(Bits, RHS.Bits, Capacity * sizeof(BitWord));
}
#if LLVM_HAS_RVALUE_REFERENCES
BitVector(BitVector &&RHS)
: Bits(RHS.Bits), Size(RHS.Size), Capacity(RHS.Capacity) {
RHS.Bits = 0;
RHS.Bits = nullptr;
}
#endif
~BitVector() {
std::free(Bits);
@ -113,10 +112,10 @@ class BitVector {
bool empty() const { return Size == 0; }
/// size - Returns the number of bits in this bitvector.
unsigned size() const { return Size; }
size_type size() const { return Size; }
/// count - Returns the number of bits which are set.
unsigned count() const {
size_type count() const {
unsigned NumBits = 0;
for (unsigned i = 0; i < NumBitWords(size()); ++i)
if (sizeof(BitWord) == 4)
@ -240,7 +239,7 @@ class BitVector {
}
BitVector &set(unsigned Idx) {
Bits[Idx / BITWORD_SIZE] |= 1L << (Idx % BITWORD_SIZE);
Bits[Idx / BITWORD_SIZE] |= BitWord(1) << (Idx % BITWORD_SIZE);
return *this;
}
@ -267,7 +266,8 @@ class BitVector {
Bits[I / BITWORD_SIZE] = ~0UL;
BitWord PostfixMask = (1UL << (E % BITWORD_SIZE)) - 1;
Bits[I / BITWORD_SIZE] |= PostfixMask;
if (I < E)
Bits[I / BITWORD_SIZE] |= PostfixMask;
return *this;
}
@ -278,7 +278,7 @@ class BitVector {
}
BitVector &reset(unsigned Idx) {
Bits[Idx / BITWORD_SIZE] &= ~(1L << (Idx % BITWORD_SIZE));
Bits[Idx / BITWORD_SIZE] &= ~(BitWord(1) << (Idx % BITWORD_SIZE));
return *this;
}
@ -305,7 +305,8 @@ class BitVector {
Bits[I / BITWORD_SIZE] = 0UL;
BitWord PostfixMask = (1UL << (E % BITWORD_SIZE)) - 1;
Bits[I / BITWORD_SIZE] &= ~PostfixMask;
if (I < E)
Bits[I / BITWORD_SIZE] &= ~PostfixMask;
return *this;
}
@ -318,7 +319,7 @@ class BitVector {
}
BitVector &flip(unsigned Idx) {
Bits[Idx / BITWORD_SIZE] ^= 1L << (Idx % BITWORD_SIZE);
Bits[Idx / BITWORD_SIZE] ^= BitWord(1) << (Idx % BITWORD_SIZE);
return *this;
}
@ -330,7 +331,7 @@ class BitVector {
bool operator[](unsigned Idx) const {
assert (Idx < Size && "Out-of-bounds Bit access.");
BitWord Mask = 1L << (Idx % BITWORD_SIZE);
BitWord Mask = BitWord(1) << (Idx % BITWORD_SIZE);
return (Bits[Idx / BITWORD_SIZE] & Mask) != 0;
}
@ -459,7 +460,6 @@ class BitVector {
return *this;
}
#if LLVM_HAS_RVALUE_REFERENCES
const BitVector &operator=(BitVector &&RHS) {
if (this == &RHS) return *this;
@ -468,11 +468,10 @@ class BitVector {
Size = RHS.Size;
Capacity = RHS.Capacity;
RHS.Bits = 0;
RHS.Bits = nullptr;
return *this;
}
#endif
void swap(BitVector &RHS) {
std::swap(Bits, RHS.Bits);

View File

@ -43,6 +43,7 @@ class DenseMapBase {
typedef std::pair<KeyT, ValueT> BucketT;
public:
typedef unsigned size_type;
typedef KeyT key_type;
typedef ValueT mapped_type;
typedef BucketT value_type;
@ -70,7 +71,7 @@ class DenseMapBase {
unsigned size() const { return getNumEntries(); }
/// Grow the densemap so that it has at least Size buckets. Does not shrink
void resize(size_t Size) {
void resize(size_type Size) {
if (Size > getNumBuckets())
grow(Size);
}
@ -99,10 +100,10 @@ class DenseMapBase {
setNumTombstones(0);
}
/// count - Return true if the specified key is in the map.
bool count(const KeyT &Val) const {
/// Return 1 if the specified key is in the map, 0 otherwise.
size_type count(const KeyT &Val) const {
const BucketT *TheBucket;
return LookupBucketFor(Val, TheBucket);
return LookupBucketFor(Val, TheBucket) ? 1 : 0;
}
iterator find(const KeyT &Val) {
@ -161,7 +162,6 @@ class DenseMapBase {
return std::make_pair(iterator(TheBucket, getBucketsEnd(), true), true);
}
#if LLVM_HAS_RVALUE_REFERENCES
// Inserts key,value pair into the map if the key isn't already in the map.
// If the key is already in the map, it returns false and doesn't update the
// value.
@ -177,8 +177,7 @@ class DenseMapBase {
TheBucket);
return std::make_pair(iterator(TheBucket, getBucketsEnd(), true), true);
}
#endif
/// insert - Range insertion of pairs.
template<typename InputIt>
void insert(InputIt I, InputIt E) {
@ -218,7 +217,6 @@ class DenseMapBase {
return FindAndConstruct(Key).second;
}
#if LLVM_HAS_RVALUE_REFERENCES
value_type& FindAndConstruct(KeyT &&Key) {
BucketT *TheBucket;
if (LookupBucketFor(Key, TheBucket))
@ -230,7 +228,6 @@ class DenseMapBase {
ValueT &operator[](KeyT &&Key) {
return FindAndConstruct(std::move(Key)).second;
}
#endif
/// isPointerIntoBucketsArray - Return true if the specified pointer points
/// somewhere into the DenseMap's array of buckets (i.e. either to a key or
@ -289,8 +286,8 @@ class DenseMapBase {
bool FoundVal = LookupBucketFor(B->first, DestBucket);
(void)FoundVal; // silence warning.
assert(!FoundVal && "Key already in new map?");
DestBucket->first = llvm_move(B->first);
new (&DestBucket->second) ValueT(llvm_move(B->second));
DestBucket->first = std::move(B->first);
new (&DestBucket->second) ValueT(std::move(B->second));
incrementNumEntries();
// Free the value.
@ -403,7 +400,6 @@ class DenseMapBase {
return TheBucket;
}
#if LLVM_HAS_RVALUE_REFERENCES
BucketT *InsertIntoBucket(const KeyT &Key, ValueT &&Value,
BucketT *TheBucket) {
TheBucket = InsertIntoBucketImpl(Key, TheBucket);
@ -420,7 +416,6 @@ class DenseMapBase {
new (&TheBucket->second) ValueT(std::move(Value));
return TheBucket;
}
#endif
BucketT *InsertIntoBucketImpl(const KeyT &Key, BucketT *TheBucket) {
// If the load of the hash table is more than 3/4, or if fewer than 1/8 of
@ -467,12 +462,12 @@ class DenseMapBase {
const unsigned NumBuckets = getNumBuckets();
if (NumBuckets == 0) {
FoundBucket = 0;
FoundBucket = nullptr;
return false;
}
// FoundTombstone - Keep track of whether we find a tombstone while probing.
const BucketT *FoundTombstone = 0;
const BucketT *FoundTombstone = nullptr;
const KeyT EmptyKey = getEmptyKey();
const KeyT TombstoneKey = getTombstoneKey();
assert(!KeyInfoT::isEqual(Val, EmptyKey) &&
@ -555,12 +550,10 @@ class DenseMap
copyFrom(other);
}
#if LLVM_HAS_RVALUE_REFERENCES
DenseMap(DenseMap &&other) : BaseT() {
init(0);
swap(other);
}
#endif
template<typename InputIt>
DenseMap(const InputIt &I, const InputIt &E) {
@ -585,7 +578,6 @@ class DenseMap
return *this;
}
#if LLVM_HAS_RVALUE_REFERENCES
DenseMap& operator=(DenseMap &&other) {
this->destroyAll();
operator delete(Buckets);
@ -593,7 +585,6 @@ class DenseMap
swap(other);
return *this;
}
#endif
void copyFrom(const DenseMap& other) {
this->destroyAll();
@ -675,7 +666,7 @@ class DenseMap
bool allocateBuckets(unsigned Num) {
NumBuckets = Num;
if (NumBuckets == 0) {
Buckets = 0;
Buckets = nullptr;
return false;
}
@ -719,12 +710,10 @@ class SmallDenseMap
copyFrom(other);
}
#if LLVM_HAS_RVALUE_REFERENCES
SmallDenseMap(SmallDenseMap &&other) : BaseT() {
init(0);
swap(other);
}
#endif
template<typename InputIt>
SmallDenseMap(const InputIt &I, const InputIt &E) {
@ -765,10 +754,10 @@ class SmallDenseMap
// Swap separately and handle any assymetry.
std::swap(LHSB->first, RHSB->first);
if (hasLHSValue) {
new (&RHSB->second) ValueT(llvm_move(LHSB->second));
new (&RHSB->second) ValueT(std::move(LHSB->second));
LHSB->second.~ValueT();
} else if (hasRHSValue) {
new (&LHSB->second) ValueT(llvm_move(RHSB->second));
new (&LHSB->second) ValueT(std::move(RHSB->second));
RHSB->second.~ValueT();
}
}
@ -784,7 +773,7 @@ class SmallDenseMap
SmallDenseMap &LargeSide = Small ? RHS : *this;
// First stash the large side's rep and move the small side across.
LargeRep TmpRep = llvm_move(*LargeSide.getLargeRep());
LargeRep TmpRep = std::move(*LargeSide.getLargeRep());
LargeSide.getLargeRep()->~LargeRep();
LargeSide.Small = true;
// This is similar to the standard move-from-old-buckets, but the bucket
@ -794,11 +783,11 @@ class SmallDenseMap
for (unsigned i = 0, e = InlineBuckets; i != e; ++i) {
BucketT *NewB = &LargeSide.getInlineBuckets()[i],
*OldB = &SmallSide.getInlineBuckets()[i];
new (&NewB->first) KeyT(llvm_move(OldB->first));
new (&NewB->first) KeyT(std::move(OldB->first));
OldB->first.~KeyT();
if (!KeyInfoT::isEqual(NewB->first, EmptyKey) &&
!KeyInfoT::isEqual(NewB->first, TombstoneKey)) {
new (&NewB->second) ValueT(llvm_move(OldB->second));
new (&NewB->second) ValueT(std::move(OldB->second));
OldB->second.~ValueT();
}
}
@ -806,7 +795,7 @@ class SmallDenseMap
// The hard part of moving the small buckets across is done, just move
// the TmpRep into its new home.
SmallSide.Small = false;
new (SmallSide.getLargeRep()) LargeRep(llvm_move(TmpRep));
new (SmallSide.getLargeRep()) LargeRep(std::move(TmpRep));
}
SmallDenseMap& operator=(const SmallDenseMap& other) {
@ -814,7 +803,6 @@ class SmallDenseMap
return *this;
}
#if LLVM_HAS_RVALUE_REFERENCES
SmallDenseMap& operator=(SmallDenseMap &&other) {
this->destroyAll();
deallocateBuckets();
@ -822,7 +810,6 @@ class SmallDenseMap
swap(other);
return *this;
}
#endif
void copyFrom(const SmallDenseMap& other) {
this->destroyAll();
@ -830,7 +817,7 @@ class SmallDenseMap
Small = true;
if (other.getNumBuckets() > InlineBuckets) {
Small = false;
allocateBuckets(other.getNumBuckets());
new (getLargeRep()) LargeRep(allocateBuckets(other.getNumBuckets()));
}
this->BaseT::copyFrom(other);
}
@ -866,8 +853,8 @@ class SmallDenseMap
!KeyInfoT::isEqual(P->first, TombstoneKey)) {
assert(size_t(TmpEnd - TmpBegin) < InlineBuckets &&
"Too many inline buckets!");
new (&TmpEnd->first) KeyT(llvm_move(P->first));
new (&TmpEnd->second) ValueT(llvm_move(P->second));
new (&TmpEnd->first) KeyT(std::move(P->first));
new (&TmpEnd->second) ValueT(std::move(P->second));
++TmpEnd;
P->second.~ValueT();
}
@ -882,7 +869,7 @@ class SmallDenseMap
return;
}
LargeRep OldRep = llvm_move(*getLargeRep());
LargeRep OldRep = std::move(*getLargeRep());
getLargeRep()->~LargeRep();
if (AtLeast <= InlineBuckets) {
Small = true;
@ -991,14 +978,15 @@ class DenseMapIterator {
friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, true>;
public:
typedef ptrdiff_t difference_type;
typedef typename conditional<IsConst, const Bucket, Bucket>::type value_type;
typedef typename std::conditional<IsConst, const Bucket, Bucket>::type
value_type;
typedef value_type *pointer;
typedef value_type &reference;
typedef std::forward_iterator_tag iterator_category;
private:
pointer Ptr, End;
public:
DenseMapIterator() : Ptr(0), End(0) {}
DenseMapIterator() : Ptr(nullptr), End(nullptr) {}
DenseMapIterator(pointer Pos, pointer E, bool NoAdvance = false)
: Ptr(Pos), End(E) {

View File

@ -27,11 +27,14 @@ class DenseSet {
typedef DenseMap<ValueT, char, ValueInfoT> MapTy;
MapTy TheMap;
public:
DenseSet(const DenseSet &Other) : TheMap(Other.TheMap) {}
typedef ValueT key_type;
typedef ValueT value_type;
typedef unsigned size_type;
explicit DenseSet(unsigned NumInitBuckets = 0) : TheMap(NumInitBuckets) {}
bool empty() const { return TheMap.empty(); }
unsigned size() const { return TheMap.size(); }
size_type size() const { return TheMap.size(); }
size_t getMemorySize() const { return TheMap.getMemorySize(); }
/// Grow the DenseSet so that it has at least Size buckets. Will not shrink
@ -42,7 +45,8 @@ class DenseSet {
TheMap.clear();
}
bool count(const ValueT &V) const {
/// Return 1 if the specified key is in the set, 0 otherwise.
size_type count(const ValueT &V) const {
return TheMap.count(V);
}
@ -54,11 +58,6 @@ class DenseSet {
TheMap.swap(RHS.TheMap);
}
DenseSet &operator=(const DenseSet &RHS) {
TheMap = RHS.TheMap;
return *this;
}
// Iterators.
class Iterator {

View File

@ -33,6 +33,7 @@
#ifndef LLVM_ADT_DEPTHFIRSTITERATOR_H
#define LLVM_ADT_DEPTHFIRSTITERATOR_H
#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallPtrSet.h"
@ -207,6 +208,12 @@ df_iterator<T> df_end(const T& G) {
return df_iterator<T>::end(G);
}
// Provide an accessor method to use them in range-based patterns.
template <class T>
iterator_range<df_iterator<T>> depth_first(const T& G) {
return iterator_range<df_iterator<T>>(df_begin(G), df_end(G));
}
// Provide global definitions of external depth first iterators...
template <class T, class SetTy = std::set<typename GraphTraits<T>::NodeType*> >
struct df_ext_iterator : public df_iterator<T, SetTy, true> {
@ -244,6 +251,12 @@ idf_iterator<T> idf_end(const T& G){
return idf_iterator<T>::end(Inverse<T>(G));
}
// Provide an accessor method to use them in range-based patterns.
template <class T>
iterator_range<idf_iterator<T>> inverse_depth_first(const T& G) {
return iterator_range<idf_iterator<T>>(idf_begin(G), idf_end(G));
}
// Provide global definitions of external inverse depth first iterators...
template <class T, class SetTy = std::set<typename GraphTraits<T>::NodeType*> >
struct idf_ext_iterator : public idf_iterator<T, SetTy, true> {

View File

@ -86,14 +86,14 @@ class EquivalenceClasses {
}
void setNext(const ECValue *NewNext) const {
assert(getNext() == 0 && "Already has a next pointer!");
assert(getNext() == nullptr && "Already has a next pointer!");
Next = (const ECValue*)((intptr_t)NewNext | (intptr_t)isLeader());
}
public:
ECValue(const ECValue &RHS) : Leader(this), Next((ECValue*)(intptr_t)1),
Data(RHS.Data) {
// Only support copying of singleton nodes.
assert(RHS.isLeader() && RHS.getNext() == 0 && "Not a singleton!");
assert(RHS.isLeader() && RHS.getNext() == nullptr && "Not a singleton!");
}
bool operator<(const ECValue &UFN) const { return Data < UFN.Data; }
@ -147,10 +147,10 @@ class EquivalenceClasses {
class member_iterator;
member_iterator member_begin(iterator I) const {
// Only leaders provide anything to iterate over.
return member_iterator(I->isLeader() ? &*I : 0);
return member_iterator(I->isLeader() ? &*I : nullptr);
}
member_iterator member_end() const {
return member_iterator(0);
return member_iterator(nullptr);
}
/// findValue - Return an iterator to the specified value. If it does not
@ -249,16 +249,15 @@ class EquivalenceClasses {
explicit member_iterator() {}
explicit member_iterator(const ECValue *N) : Node(N) {}
member_iterator(const member_iterator &I) : Node(I.Node) {}
reference operator*() const {
assert(Node != 0 && "Dereferencing end()!");
assert(Node != nullptr && "Dereferencing end()!");
return Node->getData();
}
reference operator->() const { return operator*(); }
member_iterator &operator++() {
assert(Node != 0 && "++'d off the end of the list!");
assert(Node != nullptr && "++'d off the end of the list!");
Node = Node->getNext();
return *this;
}

View File

@ -18,12 +18,12 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
class APFloat;
class APInt;
class BumpPtrAllocator;
/// This folding set used for two purposes:
/// 1. Given information about a node we want to create, look up the unique
@ -137,7 +137,7 @@ class FoldingSetImpl {
public:
Node() : NextInFoldingSetBucket(0) {}
Node() : NextInFoldingSetBucket(nullptr) {}
// Accessors
void *getNextInBucket() const { return NextInFoldingSetBucket; }
@ -269,7 +269,7 @@ class FoldingSetNodeIDRef {
const unsigned *Data;
size_t Size;
public:
FoldingSetNodeIDRef() : Data(0), Size(0) {}
FoldingSetNodeIDRef() : Data(nullptr), Size(0) {}
FoldingSetNodeIDRef(const unsigned *D, size_t S) : Data(D), Size(S) {}
/// ComputeHash - Compute a strong hash value for this FoldingSetNodeIDRef,
@ -278,6 +278,8 @@ class FoldingSetNodeIDRef {
bool operator==(FoldingSetNodeIDRef) const;
bool operator!=(FoldingSetNodeIDRef RHS) const { return !(*this == RHS); }
/// Used to compare the "ordering" of two nodes as defined by the
/// profiled bits and their ordering defined by memcmp().
bool operator<(FoldingSetNodeIDRef) const;
@ -331,6 +333,9 @@ class FoldingSetNodeID {
bool operator==(const FoldingSetNodeID &RHS) const;
bool operator==(const FoldingSetNodeIDRef RHS) const;
bool operator!=(const FoldingSetNodeID &RHS) const { return !(*this == RHS); }
bool operator!=(const FoldingSetNodeIDRef RHS) const { return !(*this ==RHS);}
/// Used to compare the "ordering" of two nodes as defined by the
/// profiled bits and their ordering defined by memcmp().
bool operator<(const FoldingSetNodeID &RHS) const;
@ -391,20 +396,20 @@ template<class T> class FoldingSet : public FoldingSetImpl {
private:
/// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a
/// way to convert nodes into a unique specifier.
virtual void GetNodeProfile(Node *N, FoldingSetNodeID &ID) const {
void GetNodeProfile(Node *N, FoldingSetNodeID &ID) const override {
T *TN = static_cast<T *>(N);
FoldingSetTrait<T>::Profile(*TN, ID);
}
/// NodeEquals - Instantiations may optionally provide a way to compare a
/// node with a specified ID.
virtual bool NodeEquals(Node *N, const FoldingSetNodeID &ID, unsigned IDHash,
FoldingSetNodeID &TempID) const {
bool NodeEquals(Node *N, const FoldingSetNodeID &ID, unsigned IDHash,
FoldingSetNodeID &TempID) const override {
T *TN = static_cast<T *>(N);
return FoldingSetTrait<T>::Equals(*TN, ID, IDHash, TempID);
}
/// ComputeNodeHash - Instantiations may optionally provide a way to compute a
/// hash value directly from a node.
virtual unsigned ComputeNodeHash(Node *N, FoldingSetNodeID &TempID) const {
unsigned ComputeNodeHash(Node *N, FoldingSetNodeID &TempID) const override {
T *TN = static_cast<T *>(N);
return FoldingSetTrait<T>::ComputeHash(*TN, TempID);
}
@ -468,20 +473,19 @@ class ContextualFoldingSet : public FoldingSetImpl {
/// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a
/// way to convert nodes into a unique specifier.
virtual void GetNodeProfile(FoldingSetImpl::Node *N,
FoldingSetNodeID &ID) const {
void GetNodeProfile(FoldingSetImpl::Node *N,
FoldingSetNodeID &ID) const override {
T *TN = static_cast<T *>(N);
ContextualFoldingSetTrait<T, Ctx>::Profile(*TN, ID, Context);
}
virtual bool NodeEquals(FoldingSetImpl::Node *N,
const FoldingSetNodeID &ID, unsigned IDHash,
FoldingSetNodeID &TempID) const {
bool NodeEquals(FoldingSetImpl::Node *N, const FoldingSetNodeID &ID,
unsigned IDHash, FoldingSetNodeID &TempID) const override {
T *TN = static_cast<T *>(N);
return ContextualFoldingSetTrait<T, Ctx>::Equals(*TN, ID, IDHash, TempID,
Context);
}
virtual unsigned ComputeNodeHash(FoldingSetImpl::Node *N,
FoldingSetNodeID &TempID) const {
unsigned ComputeNodeHash(FoldingSetImpl::Node *N,
FoldingSetNodeID &TempID) const override {
T *TN = static_cast<T *>(N);
return ContextualFoldingSetTrait<T, Ctx>::ComputeHash(*TN, TempID, Context);
}
@ -790,6 +794,14 @@ template<typename T> struct FoldingSetTrait<T*> {
ID.AddPointer(X);
}
};
template <typename T1, typename T2>
struct FoldingSetTrait<std::pair<T1, T2>> {
static inline void Profile(const std::pair<T1, T2> &P,
llvm::FoldingSetNodeID &ID) {
ID.Add(P.first);
ID.Add(P.second);
}
};
} // End of namespace llvm.
#endif

View File

@ -45,7 +45,6 @@
#ifndef LLVM_ADT_HASHING_H
#define LLVM_ADT_HASHING_H
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/SwapByteOrder.h"
@ -109,7 +108,8 @@ class hash_code {
/// differing argument types even if they would implicit promote to a common
/// type without changing the value.
template <typename T>
typename enable_if<is_integral_or_enum<T>, hash_code>::type hash_value(T value);
typename std::enable_if<is_integral_or_enum<T>::value, hash_code>::type
hash_value(T value);
/// \brief Compute a hash_code for a pointer's address.
///
@ -152,7 +152,7 @@ inline uint64_t fetch64(const char *p) {
uint64_t result;
memcpy(&result, p, sizeof(result));
if (sys::IsBigEndianHost)
return sys::SwapByteOrder(result);
sys::swapByteOrder(result);
return result;
}
@ -160,7 +160,7 @@ inline uint32_t fetch32(const char *p) {
uint32_t result;
memcpy(&result, p, sizeof(result));
if (sys::IsBigEndianHost)
return sys::SwapByteOrder(result);
sys::swapByteOrder(result);
return result;
}
@ -265,7 +265,6 @@ inline uint64_t hash_short(const char *s, size_t length, uint64_t seed) {
/// keeps 56 bytes of arbitrary state.
struct hash_state {
uint64_t h0, h1, h2, h3, h4, h5, h6;
uint64_t seed;
/// \brief Create a new hash_state structure and initialize it based on the
/// seed and the first 64-byte chunk.
@ -273,7 +272,7 @@ struct hash_state {
static hash_state create(const char *s, uint64_t seed) {
hash_state state = {
0, seed, hash_16_bytes(seed, k1), rotate(seed ^ k1, 49),
seed * k1, shift_mix(seed), 0, seed };
seed * k1, shift_mix(seed), 0 };
state.h6 = hash_16_bytes(state.h4, state.h5);
state.mix(s);
return state;
@ -352,24 +351,24 @@ inline size_t get_execution_seed() {
// and pointers, but there are platforms where it doesn't and we would like to
// support user-defined types which happen to satisfy this property.
template <typename T> struct is_hashable_data
: integral_constant<bool, ((is_integral_or_enum<T>::value ||
is_pointer<T>::value) &&
64 % sizeof(T) == 0)> {};
: std::integral_constant<bool, ((is_integral_or_enum<T>::value ||
std::is_pointer<T>::value) &&
64 % sizeof(T) == 0)> {};
// Special case std::pair to detect when both types are viable and when there
// is no alignment-derived padding in the pair. This is a bit of a lie because
// std::pair isn't truly POD, but it's close enough in all reasonable
// implementations for our use case of hashing the underlying data.
template <typename T, typename U> struct is_hashable_data<std::pair<T, U> >
: integral_constant<bool, (is_hashable_data<T>::value &&
is_hashable_data<U>::value &&
(sizeof(T) + sizeof(U)) ==
sizeof(std::pair<T, U>))> {};
: std::integral_constant<bool, (is_hashable_data<T>::value &&
is_hashable_data<U>::value &&
(sizeof(T) + sizeof(U)) ==
sizeof(std::pair<T, U>))> {};
/// \brief Helper to get the hashable data representation for a type.
/// This variant is enabled when the type itself can be used.
template <typename T>
typename enable_if<is_hashable_data<T>, T>::type
typename std::enable_if<is_hashable_data<T>::value, T>::type
get_hashable_data(const T &value) {
return value;
}
@ -377,7 +376,7 @@ get_hashable_data(const T &value) {
/// This variant is enabled when we must first call hash_value and use the
/// result as our data.
template <typename T>
typename enable_if_c<!is_hashable_data<T>::value, size_t>::type
typename std::enable_if<!is_hashable_data<T>::value, size_t>::type
get_hashable_data(const T &value) {
using ::llvm::hash_value;
return hash_value(value);
@ -411,7 +410,7 @@ template <typename InputIteratorT>
hash_code hash_combine_range_impl(InputIteratorT first, InputIteratorT last) {
const size_t seed = get_execution_seed();
char buffer[64], *buffer_ptr = buffer;
char *const buffer_end = buffer_ptr + array_lengthof(buffer);
char *const buffer_end = std::end(buffer);
while (first != last && store_and_advance(buffer_ptr, buffer_end,
get_hashable_data(*first)))
++first;
@ -451,7 +450,7 @@ hash_code hash_combine_range_impl(InputIteratorT first, InputIteratorT last) {
/// are stored in contiguous memory, this routine avoids copying each value
/// and directly reads from the underlying memory.
template <typename ValueT>
typename enable_if<is_hashable_data<ValueT>, hash_code>::type
typename std::enable_if<is_hashable_data<ValueT>::value, hash_code>::type
hash_combine_range_impl(ValueT *first, ValueT *last) {
const size_t seed = get_execution_seed();
const char *s_begin = reinterpret_cast<const char *>(first);
@ -734,7 +733,7 @@ inline hash_code hash_integer_value(uint64_t value) {
// Declared and documented above, but defined here so that any of the hashing
// infrastructure is available.
template <typename T>
typename enable_if<is_integral_or_enum<T>, hash_code>::type
typename std::enable_if<is_integral_or_enum<T>::value, hash_code>::type
hash_value(T value) {
return ::llvm::hashing::detail::hash_integer_value(value);
}

View File

@ -1,248 +0,0 @@
//===--- ImmutableIntervalMap.h - Immutable (functional) map ---*- 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 ImmutableIntervalMap class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ADT_IMMUTABLEINTERVALMAP_H
#define LLVM_ADT_IMMUTABLEINTERVALMAP_H
#include "llvm/ADT/ImmutableMap.h"
namespace llvm {
class Interval {
private:
int64_t Start;
int64_t End;
public:
Interval(int64_t S, int64_t E) : Start(S), End(E) {}
int64_t getStart() const { return Start; }
int64_t getEnd() const { return End; }
};
template <typename T>
struct ImutIntervalInfo {
typedef const std::pair<Interval, T> value_type;
typedef const value_type &value_type_ref;
typedef const Interval key_type;
typedef const Interval &key_type_ref;
typedef const T data_type;
typedef const T &data_type_ref;
static key_type_ref KeyOfValue(value_type_ref V) {
return V.first;
}
static data_type_ref DataOfValue(value_type_ref V) {
return V.second;
}
static bool isEqual(key_type_ref L, key_type_ref R) {
return L.getStart() == R.getStart() && L.getEnd() == R.getEnd();
}
static bool isDataEqual(data_type_ref L, data_type_ref R) {
return ImutContainerInfo<T>::isEqual(L,R);
}
static bool isLess(key_type_ref L, key_type_ref R) {
// Assume L and R does not overlap.
if (L.getStart() < R.getStart()) {
assert(L.getEnd() < R.getStart());
return true;
} else if (L.getStart() == R.getStart()) {
assert(L.getEnd() == R.getEnd());
return false;
} else {
assert(L.getStart() > R.getEnd());
return false;
}
}
static bool isContainedIn(key_type_ref K, key_type_ref L) {
if (K.getStart() >= L.getStart() && K.getEnd() <= L.getEnd())
return true;
else
return false;
}
static void Profile(FoldingSetNodeID &ID, value_type_ref V) {
ID.AddInteger(V.first.getStart());
ID.AddInteger(V.first.getEnd());
ImutProfileInfo<T>::Profile(ID, V.second);
}
};
template <typename ImutInfo>
class ImutIntervalAVLFactory : public ImutAVLFactory<ImutInfo> {
typedef ImutAVLTree<ImutInfo> TreeTy;
typedef typename ImutInfo::value_type value_type;
typedef typename ImutInfo::value_type_ref value_type_ref;
typedef typename ImutInfo::key_type key_type;
typedef typename ImutInfo::key_type_ref key_type_ref;
typedef typename ImutInfo::data_type data_type;
typedef typename ImutInfo::data_type_ref data_type_ref;
public:
ImutIntervalAVLFactory(BumpPtrAllocator &Alloc)
: ImutAVLFactory<ImutInfo>(Alloc) {}
TreeTy *Add(TreeTy *T, value_type_ref V) {
T = add_internal(V,T);
this->MarkImmutable(T);
return T;
}
TreeTy *Find(TreeTy *T, key_type_ref K) {
if (!T)
return NULL;
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->getLeft(T), K);
else
return Find(this->getRight(T), K);
}
private:
TreeTy *add_internal(value_type_ref V, TreeTy *T) {
key_type_ref K = ImutInfo::KeyOfValue(V);
T = removeAllOverlaps(T, K);
if (this->isEmpty(T))
return this->CreateNode(NULL, V, NULL);
assert(!T->isMutable());
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),
this->Right(T));
else
return this->Balance(this->Left(T), this->Value(T),
add_internal(V, this->Right(T)));
}
// Remove all overlaps from T.
TreeTy *removeAllOverlaps(TreeTy *T, key_type_ref K) {
bool Changed;
do {
Changed = false;
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) {
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),
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));
// Current key overlaps with the inserted key.
// Remove the current key.
Changed = true;
data_type_ref OldData = ImutInfo::DataOfValue(this->Value(T));
T = this->Remove_internal(CurrentK, T);
// Add back the unoverlapped part of the current key.
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);
} else {
Interval NewK1(CurrentK.getStart(), K.getStart()-1);
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);
}
} else {
if (CurrentK.getEnd() > K.getEnd()) {
Interval NewK(K.getEnd()+1, CurrentK.getEnd());
return add_internal(std::make_pair(NewK, OldData), T);
} else
return T;
}
}
};
/// ImmutableIntervalMap maps an interval [start, end] to a value. The intervals
/// in the map are guaranteed to be disjoint.
template <typename ValT>
class ImmutableIntervalMap
: public ImmutableMap<Interval, ValT, ImutIntervalInfo<ValT> > {
typedef typename ImutIntervalInfo<ValT>::value_type value_type;
typedef typename ImutIntervalInfo<ValT>::value_type_ref value_type_ref;
typedef typename ImutIntervalInfo<ValT>::key_type key_type;
typedef typename ImutIntervalInfo<ValT>::key_type_ref key_type_ref;
typedef typename ImutIntervalInfo<ValT>::data_type data_type;
typedef typename ImutIntervalInfo<ValT>::data_type_ref data_type_ref;
typedef ImutAVLTree<ImutIntervalInfo<ValT> > TreeTy;
public:
explicit ImmutableIntervalMap(TreeTy *R)
: ImmutableMap<Interval, ValT, ImutIntervalInfo<ValT> >(R) {}
class Factory {
ImutIntervalAVLFactory<ImutIntervalInfo<ValT> > F;
public:
Factory(BumpPtrAllocator& Alloc) : F(Alloc) {}
ImmutableIntervalMap getEmptyMap() {
return ImmutableIntervalMap(F.getEmptyTree());
}
ImmutableIntervalMap add(ImmutableIntervalMap Old,
key_type_ref K, data_type_ref D) {
TreeTy *T = F.add(Old.Root, std::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));
}
data_type *lookup(ImmutableIntervalMap M, key_type_ref K) {
TreeTy *T = F.Find(M.getRoot(), K);
if (T)
return &T->getValue().second;
else
return 0;
}
};
private:
// For ImmutableIntervalMap, the lookup operation has to be done by the
// factory.
data_type* lookup(key_type_ref K) const;
};
} // end namespace llvm
#endif

View File

@ -241,14 +241,14 @@ class ImmutableMap {
if (T) return &T->getValue().second;
}
return 0;
return nullptr;
}
/// getMaxElement - Returns the <key,value> pair in the ImmutableMap for
/// which key is the highest in the ordering of keys in the map. This
/// method returns NULL if the map is empty.
value_type* getMaxElement() const {
return Root ? &(Root->getMaxElement()->getValue()) : 0;
return Root ? &(Root->getMaxElement()->getValue()) : nullptr;
}
//===--------------------------------------------------===//

View File

@ -81,7 +81,7 @@ class ImutAVLTree {
else
T = T->getRight();
}
return NULL;
return nullptr;
}
/// getMaxElement - Find the subtree associated with the highest ranged
@ -242,9 +242,9 @@ class ImutAVLTree {
/// ImutAVLFactory.
ImutAVLTree(Factory *f, ImutAVLTree* l, ImutAVLTree* r, value_type_ref v,
unsigned height)
: factory(f), left(l), right(r), prev(0), next(0), height(height),
IsMutable(true), IsDigestCached(false), IsCanonicalized(0),
value(v), digest(0), refCount(0)
: factory(f), left(l), right(r), prev(nullptr), next(nullptr),
height(height), IsMutable(true), IsDigestCached(false),
IsCanonicalized(0), value(v), digest(0), refCount(0)
{
if (left) left->retain();
if (right) right->retain();
@ -411,7 +411,7 @@ class ImutAVLFactory {
return T;
}
TreeTy* getEmptyTree() const { return NULL; }
TreeTy* getEmptyTree() const { return nullptr; }
protected:
@ -607,7 +607,7 @@ class ImutAVLFactory {
public:
TreeTy *getCanonicalTree(TreeTy *TNew) {
if (!TNew)
return 0;
return nullptr;
if (TNew->IsCanonicalized)
return TNew;
@ -619,7 +619,7 @@ class ImutAVLFactory {
do {
if (!entry)
break;
for (TreeTy *T = entry ; T != 0; T = T->next) {
for (TreeTy *T = entry ; T != nullptr; T = T->next) {
// Compare the Contents('T') with Contents('TNew')
typename TreeTy::iterator TI = T->begin(), TE = T->end();
if (!compareTreeWithSection(TNew, TI, TE))
@ -696,12 +696,7 @@ class ImutAVLTreeGenericIterator {
}
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;
return stack == x.stack;
}
inline bool operator!=(const _Self& x) const { return !operator==(x); }

View File

@ -1177,7 +1177,7 @@ branchRoot(unsigned Position) {
if (Nodes == 1)
size[0] = rootSize;
else
NewOffset = distribute(Nodes, rootSize, Leaf::Capacity, NULL, size,
NewOffset = distribute(Nodes, rootSize, Leaf::Capacity, nullptr, size,
Position, true);
// Allocate new nodes.
@ -1218,7 +1218,7 @@ splitRoot(unsigned Position) {
if (Nodes == 1)
Size[0] = rootSize;
else
NewOffset = distribute(Nodes, rootSize, Leaf::Capacity, NULL, Size,
NewOffset = distribute(Nodes, rootSize, Leaf::Capacity, nullptr, Size,
Position, true);
// Allocate new nodes.
@ -1346,7 +1346,7 @@ class IntervalMap<KeyT, ValT, N, Traits>::const_iterator :
public:
/// const_iterator - Create an iterator that isn't pointing anywhere.
const_iterator() : map(0) {}
const_iterator() : map(nullptr) {}
/// setMap - Change the map iterated over. This call must be followed by a
/// call to goToBegin(), goToEnd(), or find()

View File

@ -23,6 +23,7 @@
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include <atomic>
#include <memory>
namespace llvm {
@ -88,6 +89,31 @@ namespace llvm {
static void retain(T *obj) { obj->Retain(); }
static void release(T *obj) { obj->Release(); }
};
/// \brief A thread-safe version of \c llvm::RefCountedBase.
///
/// A generic base class for objects that wish to have their lifetimes managed
/// using reference counts. Classes subclass \c ThreadSafeRefCountedBase to
/// obtain such functionality, and are typically handled with
/// \c IntrusiveRefCntPtr "smart pointers" which automatically handle the
/// management of reference counts.
template <class Derived>
class ThreadSafeRefCountedBase {
mutable std::atomic<int> RefCount;
protected:
ThreadSafeRefCountedBase() : RefCount(0) {}
public:
void Retain() const { ++RefCount; }
void Release() const {
int NewRefCount = --RefCount;
assert(NewRefCount >= 0 && "Reference count was already zero.");
if (NewRefCount == 0)
delete static_cast<const Derived*>(this);
}
};
//===----------------------------------------------------------------------===//
/// IntrusiveRefCntPtr - A template class that implements a "smart pointer"
@ -109,11 +135,11 @@ namespace llvm {
template <typename T>
class IntrusiveRefCntPtr {
T* Obj;
typedef IntrusiveRefCntPtr this_type;
public:
typedef T element_type;
explicit IntrusiveRefCntPtr() : Obj(0) {}
explicit IntrusiveRefCntPtr() : Obj(nullptr) {}
IntrusiveRefCntPtr(T* obj) : Obj(obj) {
retain();
@ -123,20 +149,18 @@ namespace llvm {
retain();
}
#if LLVM_HAS_RVALUE_REFERENCES
IntrusiveRefCntPtr(IntrusiveRefCntPtr&& S) : Obj(S.Obj) {
S.Obj = 0;
S.Obj = nullptr;
}
template <class X>
IntrusiveRefCntPtr(IntrusiveRefCntPtr<X>&& S) : Obj(S.getPtr()) {
IntrusiveRefCntPtr(IntrusiveRefCntPtr<X>&& S) : Obj(S.get()) {
S.Obj = 0;
}
#endif
template <class X>
IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X>& S)
: Obj(S.getPtr()) {
: Obj(S.get()) {
retain();
}
@ -151,12 +175,9 @@ namespace llvm {
T* operator->() const { return Obj; }
T* getPtr() const { return Obj; }
T* get() const { return Obj; }
typedef T* (IntrusiveRefCntPtr::*unspecified_bool_type) () const;
operator unspecified_bool_type() const {
return Obj == 0 ? 0 : &IntrusiveRefCntPtr::getPtr;
}
LLVM_EXPLICIT operator bool() const { return Obj; }
void swap(IntrusiveRefCntPtr& other) {
T* tmp = other.Obj;
@ -166,7 +187,7 @@ namespace llvm {
void reset() {
release();
Obj = 0;
Obj = nullptr;
}
void resetWithoutRelease() {
@ -182,42 +203,62 @@ namespace llvm {
inline bool operator==(const IntrusiveRefCntPtr<T>& A,
const IntrusiveRefCntPtr<U>& B)
{
return A.getPtr() == B.getPtr();
return A.get() == B.get();
}
template<class T, class U>
inline bool operator!=(const IntrusiveRefCntPtr<T>& A,
const IntrusiveRefCntPtr<U>& B)
{
return A.getPtr() != B.getPtr();
return A.get() != B.get();
}
template<class T, class U>
inline bool operator==(const IntrusiveRefCntPtr<T>& A,
U* B)
{
return A.getPtr() == B;
return A.get() == B;
}
template<class T, class U>
inline bool operator!=(const IntrusiveRefCntPtr<T>& A,
U* B)
{
return A.getPtr() != B;
return A.get() != B;
}
template<class T, class U>
inline bool operator==(T* A,
const IntrusiveRefCntPtr<U>& B)
{
return A == B.getPtr();
return A == B.get();
}
template<class T, class U>
inline bool operator!=(T* A,
const IntrusiveRefCntPtr<U>& B)
{
return A != B.getPtr();
return A != B.get();
}
template <class T>
bool operator==(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) {
return !B;
}
template <class T>
bool operator==(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) {
return B == A;
}
template <class T>
bool operator!=(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) {
return !(A == B);
}
template <class T>
bool operator!=(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) {
return !(A == B);
}
//===----------------------------------------------------------------------===//
@ -227,14 +268,14 @@ namespace llvm {
template<class T> struct simplify_type<IntrusiveRefCntPtr<T> > {
typedef T* SimpleType;
static SimpleType getSimplifiedValue(IntrusiveRefCntPtr<T>& Val) {
return Val.getPtr();
return Val.get();
}
};
template<class T> struct simplify_type<const IntrusiveRefCntPtr<T> > {
typedef /*const*/ T* SimpleType;
static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) {
return Val.getPtr();
return Val.get();
}
};

View File

@ -1,4 +1,4 @@
//===- llvm/ADT/MapVector.h - Map with deterministic value order *- C++ -*-===//
//===- llvm/ADT/MapVector.h - Map w/ deterministic value order --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -17,9 +17,7 @@
#ifndef LLVM_ADT_MAPVECTOR_H
#define LLVM_ADT_MAPVECTOR_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include <vector>
namespace llvm {
@ -31,7 +29,7 @@ template<typename KeyT, typename ValueT,
typename MapType = llvm::DenseMap<KeyT, unsigned>,
typename VectorType = std::vector<std::pair<KeyT, ValueT> > >
class MapVector {
typedef typename VectorType::size_type SizeType;
typedef typename VectorType::size_type size_type;
MapType Map;
VectorType Vector;
@ -40,7 +38,7 @@ class MapVector {
typedef typename VectorType::iterator iterator;
typedef typename VectorType::const_iterator const_iterator;
SizeType size() const {
size_type size() const {
return Vector.size();
}
@ -97,12 +95,12 @@ class MapVector {
if (Result.second) {
Vector.push_back(std::make_pair(KV.first, KV.second));
I = Vector.size() - 1;
return std::make_pair(llvm::prior(end()), true);
return std::make_pair(std::prev(end()), true);
}
return std::make_pair(begin() + I, false);
}
unsigned count(const KeyT &Key) const {
size_type count(const KeyT &Key) const {
typename MapType::const_iterator Pos = Map.find(Key);
return Pos == Map.end()? 0 : 1;
}
@ -125,8 +123,59 @@ class MapVector {
Map.erase(Pos);
Vector.pop_back();
}
/// \brief Remove the element given by Iterator.
///
/// Returns an iterator to the element following the one which was removed,
/// which may be end().
///
/// \note This is a deceivingly expensive operation (linear time). It's
/// usually better to use \a remove_if() if possible.
typename VectorType::iterator erase(typename VectorType::iterator Iterator) {
Map.erase(Iterator->first);
auto Next = Vector.erase(Iterator);
if (Next == Vector.end())
return Next;
// Update indices in the map.
size_t Index = Next - Vector.begin();
for (auto &I : Map) {
assert(I.second != Index && "Index was already erased!");
if (I.second > Index)
--I.second;
}
return Next;
}
/// \brief Remove the elements that match the predicate.
///
/// Erase all elements that match \c Pred in a single pass. Takes linear
/// time.
template <class Predicate> void remove_if(Predicate Pred);
};
template <typename KeyT, typename ValueT, typename MapType, typename VectorType>
template <class Function>
void MapVector<KeyT, ValueT, MapType, VectorType>::remove_if(Function Pred) {
auto O = Vector.begin();
for (auto I = O, E = Vector.end(); I != E; ++I) {
if (Pred(*I)) {
// Erase from the map.
Map.erase(I->first);
continue;
}
if (I != O) {
// Move the value and update the index in the map.
*O = std::move(*I);
Map[O->first] = O - Vector.begin();
}
++O;
}
// Erase trailing entries in the vector.
Vector.erase(O, Vector.end());
}
} // end namespace llvm
#endif

View File

@ -17,13 +17,10 @@
#define LLVM_ADT_OPTIONAL_H
#include "llvm/ADT/None.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/AlignOf.h"
#include "llvm/Support/Compiler.h"
#include <cassert>
#if LLVM_HAS_RVALUE_REFERENCES
#include <utility>
#endif
namespace llvm {
@ -42,7 +39,6 @@ class Optional {
new (storage.buffer) T(*O);
}
#if LLVM_HAS_RVALUE_REFERENCES
Optional(T &&y) : hasVal(true) {
new (storage.buffer) T(std::forward<T>(y));
}
@ -70,7 +66,6 @@ class Optional {
}
return *this;
}
#endif
static inline Optional create(const T* y) {
return y ? Optional(*y) : Optional();

View File

@ -1,153 +0,0 @@
//===- llvm/ADT/OwningPtr.h - Smart ptr that owns the pointee ---*- 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 and implements the OwningPtr class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ADT_OWNINGPTR_H
#define LLVM_ADT_OWNINGPTR_H
#include "llvm/Support/Compiler.h"
#include <cassert>
#include <cstddef>
namespace llvm {
/// OwningPtr smart pointer - OwningPtr mimics a built-in pointer except that it
/// guarantees deletion of the object pointed to, either on destruction of the
/// OwningPtr or via an explicit reset(). Once created, ownership of the
/// pointee object can be taken away from OwningPtr by using the take method.
template<class T>
class OwningPtr {
OwningPtr(OwningPtr const &) LLVM_DELETED_FUNCTION;
OwningPtr &operator=(OwningPtr const &) LLVM_DELETED_FUNCTION;
T *Ptr;
public:
explicit OwningPtr(T *P = 0) : Ptr(P) {}
#if LLVM_HAS_RVALUE_REFERENCES
OwningPtr(OwningPtr &&Other) : Ptr(Other.take()) {}
OwningPtr &operator=(OwningPtr &&Other) {
reset(Other.take());
return *this;
}
#endif
~OwningPtr() {
delete Ptr;
}
/// reset - Change the current pointee to the specified pointer. Note that
/// calling this with any pointer (including a null pointer) deletes the
/// current pointer.
void reset(T *P = 0) {
if (P == Ptr) return;
T *Tmp = Ptr;
Ptr = P;
delete Tmp;
}
/// take - Reset the owning pointer to null and return its pointer. This does
/// not delete the pointer before returning it.
T *take() {
T *Tmp = Ptr;
Ptr = 0;
return Tmp;
}
T &operator*() const {
assert(Ptr && "Cannot dereference null pointer");
return *Ptr;
}
T *operator->() const { return Ptr; }
T *get() const { return Ptr; }
LLVM_EXPLICIT operator bool() const { return Ptr != 0; }
bool operator!() const { return Ptr == 0; }
bool isValid() const { return Ptr != 0; }
void swap(OwningPtr &RHS) {
T *Tmp = RHS.Ptr;
RHS.Ptr = Ptr;
Ptr = Tmp;
}
};
template<class T>
inline void swap(OwningPtr<T> &a, OwningPtr<T> &b) {
a.swap(b);
}
/// OwningArrayPtr smart pointer - OwningArrayPtr provides the same
/// functionality as OwningPtr, except that it works for array types.
template<class T>
class OwningArrayPtr {
OwningArrayPtr(OwningArrayPtr const &) LLVM_DELETED_FUNCTION;
OwningArrayPtr &operator=(OwningArrayPtr const &) LLVM_DELETED_FUNCTION;
T *Ptr;
public:
explicit OwningArrayPtr(T *P = 0) : Ptr(P) {}
#if LLVM_HAS_RVALUE_REFERENCES
OwningArrayPtr(OwningArrayPtr &&Other) : Ptr(Other.take()) {}
OwningArrayPtr &operator=(OwningArrayPtr &&Other) {
reset(Other.take());
return *this;
}
#endif
~OwningArrayPtr() {
delete [] Ptr;
}
/// reset - Change the current pointee to the specified pointer. Note that
/// calling this with any pointer (including a null pointer) deletes the
/// current pointer.
void reset(T *P = 0) {
if (P == Ptr) return;
T *Tmp = Ptr;
Ptr = P;
delete [] Tmp;
}
/// take - Reset the owning pointer to null and return its pointer. This does
/// not delete the pointer before returning it.
T *take() {
T *Tmp = Ptr;
Ptr = 0;
return Tmp;
}
T &operator[](std::ptrdiff_t i) const {
assert(Ptr && "Cannot dereference null pointer");
return Ptr[i];
}
T *get() const { return Ptr; }
LLVM_EXPLICIT operator bool() const { return Ptr != 0; }
bool operator!() const { return Ptr == 0; }
void swap(OwningArrayPtr &RHS) {
T *Tmp = RHS.Ptr;
RHS.Ptr = Ptr;
Ptr = Tmp;
}
};
template<class T>
inline void swap(OwningArrayPtr<T> &a, OwningArrayPtr<T> &b) {
a.swap(b);
}
} // end namespace llvm
#endif

View File

@ -17,6 +17,7 @@
#include "llvm/Support/Compiler.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
#include <cassert>
#include <limits>
namespace llvm {
@ -41,7 +42,12 @@ template <typename PointerTy, unsigned IntBits, typename IntType=unsigned,
typename PtrTraits = PointerLikeTypeTraits<PointerTy> >
class PointerIntPair {
intptr_t Value;
enum LLVM_ENUM_INT_TYPE(uintptr_t) {
static_assert(PtrTraits::NumLowBitsAvailable <
std::numeric_limits<uintptr_t>::digits,
"cannot use a pointer type that has all bits free");
static_assert(IntBits <= PtrTraits::NumLowBitsAvailable,
"PointerIntPair with integer size too large for pointer");
enum : uintptr_t {
/// PointerBitMask - The bits that come from the pointer.
PointerBitMask =
~(uintptr_t)(((intptr_t)1 << PtrTraits::NumLowBitsAvailable)-1),
@ -59,8 +65,6 @@ class PointerIntPair {
public:
PointerIntPair() : Value(0) {}
PointerIntPair(PointerTy PtrVal, IntType IntVal) {
assert(IntBits <= PtrTraits::NumLowBitsAvailable &&
"PointerIntPair formed with integer size too large for pointer");
setPointerAndInt(PtrVal, IntVal);
}
explicit PointerIntPair(PointerTy PtrVal) {
@ -79,7 +83,7 @@ class PointerIntPair {
void setPointer(PointerTy PtrVal) {
intptr_t PtrWord
= reinterpret_cast<intptr_t>(PtrTraits::getAsVoidPointer(PtrVal));
assert((PtrWord & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 &&
assert((PtrWord & ~PointerBitMask) == 0 &&
"Pointer is not sufficiently aligned");
// Preserve all low bits, just update the pointer.
Value = PtrWord | (Value & ~PointerBitMask);
@ -87,7 +91,7 @@ class PointerIntPair {
void setInt(IntType IntVal) {
intptr_t IntWord = static_cast<intptr_t>(IntVal);
assert(IntWord < (1 << IntBits) && "Integer too large for field");
assert((IntWord & ~IntMask) == 0 && "Integer too large for field");
// Preserve all bits other than the ones we are updating.
Value &= ~ShiftedIntMask; // Remove integer field.
@ -97,7 +101,7 @@ class PointerIntPair {
void initWithPointer(PointerTy PtrVal) {
intptr_t PtrWord
= reinterpret_cast<intptr_t>(PtrTraits::getAsVoidPointer(PtrVal));
assert((PtrWord & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 &&
assert((PtrWord & ~PointerBitMask) == 0 &&
"Pointer is not sufficiently aligned");
Value = PtrWord;
}
@ -105,10 +109,10 @@ class PointerIntPair {
void setPointerAndInt(PointerTy PtrVal, IntType IntVal) {
intptr_t PtrWord
= reinterpret_cast<intptr_t>(PtrTraits::getAsVoidPointer(PtrVal));
assert((PtrWord & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 &&
assert((PtrWord & ~PointerBitMask) == 0 &&
"Pointer is not sufficiently aligned");
intptr_t IntWord = static_cast<intptr_t>(IntVal);
assert(IntWord < (1 << IntBits) && "Integer too large for field");
assert((IntWord & ~IntMask) == 0 && "Integer too large for field");
Value = PtrWord | (IntWord << IntShift);
}
@ -158,13 +162,13 @@ struct DenseMapInfo<PointerIntPair<PointerTy, IntBits, IntType> > {
typedef PointerIntPair<PointerTy, IntBits, IntType> Ty;
static Ty getEmptyKey() {
uintptr_t Val = static_cast<uintptr_t>(-1);
Val <<= PointerLikeTypeTraits<PointerTy>::NumLowBitsAvailable;
return Ty(reinterpret_cast<PointerTy>(Val), IntType((1 << IntBits)-1));
Val <<= PointerLikeTypeTraits<Ty>::NumLowBitsAvailable;
return Ty::getFromOpaqueValue(reinterpret_cast<void *>(Val));
}
static Ty getTombstoneKey() {
uintptr_t Val = static_cast<uintptr_t>(-2);
Val <<= PointerLikeTypeTraits<PointerTy>::NumLowBitsAvailable;
return Ty(reinterpret_cast<PointerTy>(Val), IntType(0));
return Ty::getFromOpaqueValue(reinterpret_cast<void *>(Val));
}
static unsigned getHashValue(Ty V) {
uintptr_t IV = reinterpret_cast<uintptr_t>(V.getOpaqueValue());

View File

@ -15,8 +15,9 @@
#ifndef LLVM_ADT_POINTERUNION_H
#define LLVM_ADT_POINTERUNION_H
#include "llvm/Support/Compiler.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/Support/Compiler.h"
namespace llvm {
@ -153,6 +154,12 @@ namespace llvm {
"Can't get the address because PointerLikeTypeTraits changes the ptr");
return (PT1 *)Val.getAddrOfPointer();
}
/// \brief Assignment from nullptr which just clears the union.
const PointerUnion &operator=(std::nullptr_t) {
Val.initWithPointer(nullptr);
return *this;
}
/// Assignment operators - Allow assigning into this union from either
/// pointer type, setting the discriminator to remember what it came from.
@ -297,6 +304,12 @@ namespace llvm {
if (is<T>()) return get<T>();
return T();
}
/// \brief Assignment from nullptr which just clears the union.
const PointerUnion3 &operator=(std::nullptr_t) {
Val = nullptr;
return *this;
}
/// Assignment operators - Allow assigning into this union from either
/// pointer type, setting the discriminator to remember what it came from.
@ -406,6 +419,12 @@ namespace llvm {
if (is<T>()) return get<T>();
return T();
}
/// \brief Assignment from nullptr which just clears the union.
const PointerUnion4 &operator=(std::nullptr_t) {
Val = nullptr;
return *this;
}
/// Assignment operators - Allow assigning into this union from either
/// pointer type, setting the discriminator to remember what it came from.
@ -455,6 +474,33 @@ namespace llvm {
::NumLowBitsAvailable
};
};
// Teach DenseMap how to use PointerUnions as keys.
template<typename T, typename U>
struct DenseMapInfo<PointerUnion<T, U> > {
typedef PointerUnion<T, U> Pair;
typedef DenseMapInfo<T> FirstInfo;
typedef DenseMapInfo<U> SecondInfo;
static inline Pair getEmptyKey() {
return Pair(FirstInfo::getEmptyKey());
}
static inline Pair getTombstoneKey() {
return Pair(FirstInfo::getTombstoneKey());
}
static unsigned getHashValue(const Pair &PairVal) {
intptr_t key = (intptr_t)PairVal.getOpaqueValue();
return DenseMapInfo<intptr_t>::getHashValue(key);
}
static bool isEqual(const Pair &LHS, const Pair &RHS) {
return LHS.template is<T>() == RHS.template is<T>() &&
(LHS.template is<T>() ?
FirstInfo::isEqual(LHS.template get<T>(),
RHS.template get<T>()) :
SecondInfo::isEqual(LHS.template get<U>(),
RHS.template get<U>()));
}
};
}
#endif

View File

@ -111,7 +111,7 @@ class po_iterator : public std::iterator<std::forward_iterator_tag,
}
inline po_iterator(NodeType *BB) {
this->insertEdge((NodeType*)0, BB);
this->insertEdge((NodeType*)nullptr, BB);
VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB)));
traverseChild();
}
@ -119,7 +119,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 (this->insertEdge((NodeType*)0, BB)) {
if (this->insertEdge((NodeType*)nullptr, BB)) {
VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB)));
traverseChild();
}

View File

@ -6,16 +6,18 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected
// components (SCCs) of a graph in O(N+E) time using Tarjan's DFS algorithm.
//
// The SCC iterator has the important property that if a node in SCC S1 has an
// edge to a node in SCC S2, then it visits S1 *after* S2.
//
// To visit S1 *before* S2, use the scc_iterator on the Inverse graph.
// (NOTE: This requires some simple wrappers and is not supported yet.)
//
/// \file
///
/// This builds on the llvm/ADT/GraphTraits.h file to find the strongly
/// connected components (SCCs) of a graph in O(N+E) time using Tarjan's DFS
/// algorithm.
///
/// The SCC iterator has the important property that if a node in SCC S1 has an
/// edge to a node in SCC S2, then it visits S1 *after* S2.
///
/// To visit S1 *before* S2, use the scc_iterator on the Inverse graph. (NOTE:
/// This requires some simple wrappers and is not supported yet.)
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_ADT_SCCITERATOR_H
@ -23,169 +25,112 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/iterator.h"
#include <vector>
namespace llvm {
//===----------------------------------------------------------------------===//
/// \brief Enumerate the SCCs of a directed graph in reverse topological order
/// of the SCC DAG.
///
/// scc_iterator - Enumerate the SCCs of a directed graph, in
/// reverse topological order of the SCC DAG.
///
template<class GraphT, class GT = GraphTraits<GraphT> >
/// This is implemented using Tarjan's DFS algorithm using an internal stack to
/// build up a vector of nodes in a particular SCC. Note that it is a forward
/// iterator and thus you cannot backtrack or re-visit nodes.
template <class GraphT, class GT = GraphTraits<GraphT>>
class scc_iterator
: public std::iterator<std::forward_iterator_tag,
std::vector<typename GT::NodeType>, ptrdiff_t> {
typedef typename GT::NodeType NodeType;
: public iterator_facade_base<
scc_iterator<GraphT, GT>, std::forward_iterator_tag,
const std::vector<typename GT::NodeType *>, ptrdiff_t> {
typedef typename GT::NodeType NodeType;
typedef typename GT::ChildIteratorType ChildItTy;
typedef std::vector<NodeType*> SccTy;
typedef std::iterator<std::forward_iterator_tag,
std::vector<typename GT::NodeType>, ptrdiff_t> super;
typedef typename super::reference reference;
typedef typename super::pointer pointer;
typedef std::vector<NodeType *> SccTy;
typedef typename scc_iterator::reference reference;
// The visit counters used to detect when a complete SCC is on the stack.
// visitNum is the global counter.
// nodeVisitNumbers are per-node visit numbers, also used as DFS flags.
/// Element of VisitStack during DFS.
struct StackElement {
NodeType *Node; ///< The current node pointer.
ChildItTy NextChild; ///< The next child, modified inplace during DFS.
unsigned MinVisited; ///< Minimum uplink value of all children of Node.
StackElement(NodeType *Node, const ChildItTy &Child, unsigned Min)
: Node(Node), NextChild(Child), MinVisited(Min) {}
bool operator==(const StackElement &Other) const {
return Node == Other.Node &&
NextChild == Other.NextChild &&
MinVisited == Other.MinVisited;
}
};
/// The visit counters used to detect when a complete SCC is on the stack.
/// visitNum is the global counter.
///
/// nodeVisitNumbers are per-node visit numbers, also used as DFS flags.
unsigned visitNum;
DenseMap<NodeType *, unsigned> nodeVisitNumbers;
// SCCNodeStack - Stack holding nodes of the SCC.
/// Stack holding nodes of the SCC.
std::vector<NodeType *> SCCNodeStack;
// CurrentSCC - The current SCC, retrieved using operator*().
/// The current SCC, retrieved using operator*().
SccTy CurrentSCC;
// VisitStack - Used to maintain the ordering. Top = current block
// First element is basic block pointer, second is the 'next child' to visit
std::vector<std::pair<NodeType *, ChildItTy> > VisitStack;
/// DFS stack, Used to maintain the ordering. The top contains the current
/// node, the next child to visit, and the minimum uplink value of all child
std::vector<StackElement> VisitStack;
// 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;
/// A single "visit" within the non-recursive DFS traversal.
void DFSVisitOne(NodeType *N);
// A single "visit" within the non-recursive DFS traversal.
void DFSVisitOne(NodeType *N) {
++visitNum; // Global counter for the visit order
nodeVisitNumbers[N] = visitNum;
SCCNodeStack.push_back(N);
MinVisitNumStack.push_back(visitNum);
VisitStack.push_back(std::make_pair(N, GT::child_begin(N)));
//dbgs() << "TarjanSCC: Node " << N <<
// " : visitNum = " << visitNum << "\n";
}
/// The stack-based DFS traversal; defined below.
void DFSVisitChildren();
// The stack-based DFS traversal; defined below.
void DFSVisitChildren() {
assert(!VisitStack.empty());
while (VisitStack.back().second != GT::child_end(VisitStack.back().first)) {
// TOS has at least one more child so continue DFS
NodeType *childN = *VisitStack.back().second++;
if (!nodeVisitNumbers.count(childN)) {
// this node has never been seen.
DFSVisitOne(childN);
continue;
}
/// Compute the next SCC using the DFS traversal.
void GetNextSCC();
unsigned childNum = nodeVisitNumbers[childN];
if (MinVisitNumStack.back() > childNum)
MinVisitNumStack.back() = childNum;
}
}
// Compute the next SCC using the DFS traversal.
void GetNextSCC() {
assert(VisitStack.size() == MinVisitNumStack.size());
CurrentSCC.clear(); // Prepare to compute the next SCC
while (!VisitStack.empty()) {
DFSVisitChildren();
assert(VisitStack.back().second ==GT::child_end(VisitStack.back().first));
NodeType *visitingN = VisitStack.back().first;
unsigned minVisitNum = MinVisitNumStack.back();
VisitStack.pop_back();
MinVisitNumStack.pop_back();
if (!MinVisitNumStack.empty() && MinVisitNumStack.back() > minVisitNum)
MinVisitNumStack.back() = minVisitNum;
//dbgs() << "TarjanSCC: Popped node " << visitingN <<
// " : minVisitNum = " << minVisitNum << "; Node visit num = " <<
// nodeVisitNumbers[visitingN] << "\n";
if (minVisitNum != nodeVisitNumbers[visitingN])
continue;
// A full SCC is on the SCCNodeStack! It includes all nodes below
// visitingN on the stack. Copy those nodes to CurrentSCC,
// reset their minVisit values, and return (this suspends
// the DFS traversal till the next ++).
do {
CurrentSCC.push_back(SCCNodeStack.back());
SCCNodeStack.pop_back();
nodeVisitNumbers[CurrentSCC.back()] = ~0U;
} while (CurrentSCC.back() != visitingN);
return;
}
}
inline scc_iterator(NodeType *entryN) : visitNum(0) {
scc_iterator(NodeType *entryN) : visitNum(0) {
DFSVisitOne(entryN);
GetNextSCC();
}
inline scc_iterator() { /* End is when DFS stack is empty */ }
/// End is when the DFS stack is empty.
scc_iterator() {}
public:
typedef scc_iterator<GraphT, GT> _Self;
static scc_iterator begin(const GraphT &G) {
return scc_iterator(GT::getEntryNode(G));
}
static scc_iterator end(const GraphT &) { return scc_iterator(); }
// Provide static "constructors"...
static inline _Self begin(const GraphT &G){return _Self(GT::getEntryNode(G));}
static inline _Self end (const GraphT &) { return _Self(); }
// Direct loop termination test: I.isAtEnd() is more efficient than I == end()
inline bool isAtEnd() const {
/// \brief Direct loop termination test which is more efficient than
/// comparison with \c end().
bool isAtEnd() const {
assert(!CurrentSCC.empty() || VisitStack.empty());
return CurrentSCC.empty();
}
inline bool operator==(const _Self& x) const {
bool operator==(const scc_iterator &x) const {
return VisitStack == x.VisitStack && CurrentSCC == x.CurrentSCC;
}
inline bool operator!=(const _Self& x) const { return !operator==(x); }
// Iterator traversal: forward iteration only
inline _Self& operator++() { // Preincrement
scc_iterator &operator++() {
GetNextSCC();
return *this;
}
inline _Self operator++(int) { // Postincrement
_Self tmp = *this; ++*this; return tmp;
}
// Retrieve a reference to the current SCC
inline const SccTy &operator*() const {
assert(!CurrentSCC.empty() && "Dereferencing END SCC iterator!");
return CurrentSCC;
}
inline SccTy &operator*() {
reference operator*() const {
assert(!CurrentSCC.empty() && "Dereferencing END SCC iterator!");
return CurrentSCC;
}
// hasLoop() -- Test if the current SCC has a loop. If it has more than one
// node, this is trivially true. If not, it may still contain a loop if the
// node has an edge back to itself.
bool hasLoop() const {
assert(!CurrentSCC.empty() && "Dereferencing END SCC iterator!");
if (CurrentSCC.size() > 1) return true;
NodeType *N = CurrentSCC.front();
for (ChildItTy CI = GT::child_begin(N), CE=GT::child_end(N); CI != CE; ++CI)
if (*CI == N)
return true;
return false;
}
/// \brief Test if the current SCC has a loop.
///
/// If the SCC has more than one node, this is trivially true. If not, it may
/// still contain a loop if the node has an edge back to itself.
bool hasLoop() const;
/// ReplaceNode - This informs the scc_iterator that the specified Old node
/// has been deleted, and New is to be used in its place.
/// This informs the \c scc_iterator that the specified \c Old node
/// has been deleted, and \c New is to be used in its place.
void ReplaceNode(NodeType *Old, NodeType *New) {
assert(nodeVisitNumbers.count(Old) && "Old not in scc_iterator?");
nodeVisitNumbers[New] = nodeVisitNumbers[Old];
@ -193,25 +138,105 @@ class scc_iterator
}
};
template <class GraphT, class GT>
void scc_iterator<GraphT, GT>::DFSVisitOne(NodeType *N) {
++visitNum;
nodeVisitNumbers[N] = visitNum;
SCCNodeStack.push_back(N);
VisitStack.push_back(StackElement(N, GT::child_begin(N), visitNum));
#if 0 // Enable if needed when debugging.
dbgs() << "TarjanSCC: Node " << N <<
" : visitNum = " << visitNum << "\n";
#endif
}
// Global constructor for the SCC iterator.
template <class T>
scc_iterator<T> scc_begin(const T &G) {
template <class GraphT, class GT>
void scc_iterator<GraphT, GT>::DFSVisitChildren() {
assert(!VisitStack.empty());
while (VisitStack.back().NextChild != GT::child_end(VisitStack.back().Node)) {
// TOS has at least one more child so continue DFS
NodeType *childN = *VisitStack.back().NextChild++;
typename DenseMap<NodeType *, unsigned>::iterator Visited =
nodeVisitNumbers.find(childN);
if (Visited == nodeVisitNumbers.end()) {
// this node has never been seen.
DFSVisitOne(childN);
continue;
}
unsigned childNum = Visited->second;
if (VisitStack.back().MinVisited > childNum)
VisitStack.back().MinVisited = childNum;
}
}
template <class GraphT, class GT> void scc_iterator<GraphT, GT>::GetNextSCC() {
CurrentSCC.clear(); // Prepare to compute the next SCC
while (!VisitStack.empty()) {
DFSVisitChildren();
// Pop the leaf on top of the VisitStack.
NodeType *visitingN = VisitStack.back().Node;
unsigned minVisitNum = VisitStack.back().MinVisited;
assert(VisitStack.back().NextChild == GT::child_end(visitingN));
VisitStack.pop_back();
// Propagate MinVisitNum to parent so we can detect the SCC starting node.
if (!VisitStack.empty() && VisitStack.back().MinVisited > minVisitNum)
VisitStack.back().MinVisited = minVisitNum;
#if 0 // Enable if needed when debugging.
dbgs() << "TarjanSCC: Popped node " << visitingN <<
" : minVisitNum = " << minVisitNum << "; Node visit num = " <<
nodeVisitNumbers[visitingN] << "\n";
#endif
if (minVisitNum != nodeVisitNumbers[visitingN])
continue;
// A full SCC is on the SCCNodeStack! It includes all nodes below
// visitingN on the stack. Copy those nodes to CurrentSCC,
// reset their minVisit values, and return (this suspends
// the DFS traversal till the next ++).
do {
CurrentSCC.push_back(SCCNodeStack.back());
SCCNodeStack.pop_back();
nodeVisitNumbers[CurrentSCC.back()] = ~0U;
} while (CurrentSCC.back() != visitingN);
return;
}
}
template <class GraphT, class GT>
bool scc_iterator<GraphT, GT>::hasLoop() const {
assert(!CurrentSCC.empty() && "Dereferencing END SCC iterator!");
if (CurrentSCC.size() > 1)
return true;
NodeType *N = CurrentSCC.front();
for (ChildItTy CI = GT::child_begin(N), CE = GT::child_end(N); CI != CE;
++CI)
if (*CI == N)
return true;
return false;
}
/// \brief Construct the begin iterator for a deduced graph type T.
template <class T> scc_iterator<T> scc_begin(const T &G) {
return scc_iterator<T>::begin(G);
}
template <class T>
scc_iterator<T> scc_end(const T &G) {
/// \brief Construct the end iterator for a deduced graph type T.
template <class T> scc_iterator<T> scc_end(const T &G) {
return scc_iterator<T>::end(G);
}
template <class T>
scc_iterator<Inverse<T> > scc_begin(const Inverse<T> &G) {
/// \brief Construct the begin iterator for a deduced graph type T's Inverse<T>.
template <class T> scc_iterator<Inverse<T> > scc_begin(const Inverse<T> &G) {
return scc_iterator<Inverse<T> >::begin(G);
}
template <class T>
scc_iterator<Inverse<T> > scc_end(const Inverse<T> &G) {
/// \brief Construct the end iterator for a deduced graph type T's Inverse<T>.
template <class T> scc_iterator<Inverse<T> > scc_end(const Inverse<T> &G) {
return scc_iterator<Inverse<T> >::end(G);
}

View File

@ -17,10 +17,12 @@
#ifndef LLVM_ADT_STLEXTRAS_H
#define LLVM_ADT_STLEXTRAS_H
#include "llvm/Support/Compiler.h"
#include <cstddef> // for std::size_t
#include <cstdlib> // for qsort
#include <functional>
#include <iterator>
#include <memory>
#include <utility> // for std::pair
namespace llvm {
@ -53,6 +55,131 @@ struct greater_ptr : public std::binary_function<Ty, Ty, bool> {
}
};
/// An efficient, type-erasing, non-owning reference to a callable. This is
/// intended for use as the type of a function parameter that is not used
/// after the function in question returns.
///
/// This class does not own the callable, so it is not in general safe to store
/// a function_ref.
template<typename Fn> class function_ref;
#if LLVM_HAS_VARIADIC_TEMPLATES
template<typename Ret, typename ...Params>
class function_ref<Ret(Params...)> {
Ret (*callback)(intptr_t callable, Params ...params);
intptr_t callable;
template<typename Callable>
static Ret callback_fn(intptr_t callable, Params ...params) {
return (*reinterpret_cast<Callable*>(callable))(
std::forward<Params>(params)...);
}
public:
template<typename Callable>
function_ref(Callable &&callable)
: callback(callback_fn<typename std::remove_reference<Callable>::type>),
callable(reinterpret_cast<intptr_t>(&callable)) {}
Ret operator()(Params ...params) const {
return callback(callable, std::forward<Params>(params)...);
}
};
#else
template<typename Ret>
class function_ref<Ret()> {
Ret (*callback)(intptr_t callable);
intptr_t callable;
template<typename Callable>
static Ret callback_fn(intptr_t callable) {
return (*reinterpret_cast<Callable*>(callable))();
}
public:
template<typename Callable>
function_ref(Callable &&callable)
: callback(callback_fn<typename std::remove_reference<Callable>::type>),
callable(reinterpret_cast<intptr_t>(&callable)) {}
Ret operator()() const { return callback(callable); }
};
template<typename Ret, typename Param1>
class function_ref<Ret(Param1)> {
Ret (*callback)(intptr_t callable, Param1 param1);
intptr_t callable;
template<typename Callable>
static Ret callback_fn(intptr_t callable, Param1 param1) {
return (*reinterpret_cast<Callable*>(callable))(
std::forward<Param1>(param1));
}
public:
template<typename Callable>
function_ref(Callable &&callable)
: callback(callback_fn<typename std::remove_reference<Callable>::type>),
callable(reinterpret_cast<intptr_t>(&callable)) {}
Ret operator()(Param1 param1) {
return callback(callable, std::forward<Param1>(param1));
}
};
template<typename Ret, typename Param1, typename Param2>
class function_ref<Ret(Param1, Param2)> {
Ret (*callback)(intptr_t callable, Param1 param1, Param2 param2);
intptr_t callable;
template<typename Callable>
static Ret callback_fn(intptr_t callable, Param1 param1, Param2 param2) {
return (*reinterpret_cast<Callable*>(callable))(
std::forward<Param1>(param1),
std::forward<Param2>(param2));
}
public:
template<typename Callable>
function_ref(Callable &&callable)
: callback(callback_fn<typename std::remove_reference<Callable>::type>),
callable(reinterpret_cast<intptr_t>(&callable)) {}
Ret operator()(Param1 param1, Param2 param2) {
return callback(callable,
std::forward<Param1>(param1),
std::forward<Param2>(param2));
}
};
template<typename Ret, typename Param1, typename Param2, typename Param3>
class function_ref<Ret(Param1, Param2, Param3)> {
Ret (*callback)(intptr_t callable, Param1 param1, Param2 param2, Param3 param3);
intptr_t callable;
template<typename Callable>
static Ret callback_fn(intptr_t callable, Param1 param1, Param2 param2,
Param3 param3) {
return (*reinterpret_cast<Callable*>(callable))(
std::forward<Param1>(param1),
std::forward<Param2>(param2),
std::forward<Param3>(param3));
}
public:
template<typename Callable>
function_ref(Callable &&callable)
: callback(callback_fn<typename std::remove_reference<Callable>::type>),
callable(reinterpret_cast<intptr_t>(&callable)) {}
Ret operator()(Param1 param1, Param2 param2, Param3 param3) {
return callback(callable,
std::forward<Param1>(param1),
std::forward<Param2>(param2),
std::forward<Param3>(param3));
}
};
#endif
// deleter - Very very very simple method that is used to invoke operator
// delete on something. It is used like this:
//
@ -95,8 +222,6 @@ class mapped_iterator {
inline explicit mapped_iterator(const RootIt &I, UnaryFunc F)
: current(I), Fn(F) {}
inline mapped_iterator(const mapped_iterator &It)
: current(It.current), Fn(It.Fn) {}
inline value_type operator*() const { // All this work to do this
return Fn(*current); // little change
@ -141,82 +266,10 @@ inline mapped_iterator<ItTy, FuncTy> map_iterator(const ItTy &I, FuncTy F) {
return mapped_iterator<ItTy, FuncTy>(I, F);
}
// next/prior - These functions unlike std::advance do not modify the
// passed iterator but return a copy.
//
// next(myIt) returns copy of myIt incremented once
// next(myIt, n) returns copy of myIt incremented n times
// prior(myIt) returns copy of myIt decremented once
// prior(myIt, n) returns copy of myIt decremented n times
template <typename ItTy, typename Dist>
inline ItTy next(ItTy it, Dist n)
{
std::advance(it, n);
return it;
}
template <typename ItTy>
inline ItTy next(ItTy it)
{
return ++it;
}
template <typename ItTy, typename Dist>
inline ItTy prior(ItTy it, Dist n)
{
std::advance(it, -n);
return it;
}
template <typename ItTy>
inline ItTy prior(ItTy it)
{
return --it;
}
//===----------------------------------------------------------------------===//
// Extra additions to <utility>
//===----------------------------------------------------------------------===//
// tie - this function ties two objects and returns a temporary object
// that is assignable from a std::pair. This can be used to make code
// more readable when using values returned from functions bundled in
// a std::pair. Since an example is worth 1000 words:
//
// typedef std::map<int, int> Int2IntMap;
//
// Int2IntMap myMap;
// Int2IntMap::iterator where;
// bool inserted;
// tie(where, inserted) = myMap.insert(std::make_pair(123,456));
//
// if (inserted)
// // do stuff
// else
// // do other stuff
template <typename T1, typename T2>
struct tier {
typedef T1 &first_type;
typedef T2 &second_type;
first_type first;
second_type second;
tier(first_type f, second_type s) : first(f), second(s) { }
tier& operator=(const std::pair<T1, T2>& p) {
first = p.first;
second = p.second;
return *this;
}
};
template <typename T1, typename T2>
inline tier<T1, T2> tie(T1& f, T2& s) {
return tier<T1, T2>(f, s);
}
/// \brief Function object to check whether the first component of a std::pair
/// compares less than the first component of another std::pair.
struct less_first {
@ -237,27 +290,20 @@ struct less_second {
// Extra additions for arrays
//===----------------------------------------------------------------------===//
/// Find where an array ends (for ending iterators)
/// This returns a pointer to the byte immediately
/// after the end of an array.
template<class T, std::size_t N>
inline T *array_endof(T (&x)[N]) {
return x+N;
}
/// Find the length of an array.
template<class T, std::size_t N>
inline size_t array_lengthof(T (&)[N]) {
template <class T, std::size_t N>
LLVM_CONSTEXPR inline size_t array_lengthof(T (&)[N]) {
return N;
}
/// array_pod_sort_comparator - This is helper function for array_pod_sort,
/// which just uses operator< on T.
/// Adapt std::less<T> for array_pod_sort.
template<typename T>
inline int array_pod_sort_comparator(const void *P1, const void *P2) {
if (*reinterpret_cast<const T*>(P1) < *reinterpret_cast<const T*>(P2))
if (std::less<T>()(*reinterpret_cast<const T*>(P1),
*reinterpret_cast<const T*>(P2)))
return -1;
if (*reinterpret_cast<const T*>(P2) < *reinterpret_cast<const T*>(P1))
if (std::less<T>()(*reinterpret_cast<const T*>(P2),
*reinterpret_cast<const T*>(P1)))
return 1;
return 0;
}
@ -280,7 +326,7 @@ inline int (*get_array_pod_sort_comparator(const T &))
/// possible.
///
/// This function assumes that you have simple POD-like types that can be
/// compared with operator< and can be moved with memcpy. If this isn't true,
/// compared with std::less and can be moved with memcpy. If this isn't true,
/// you should use std::sort.
///
/// NOTE: If qsort_r were portable, we could allow a custom comparator and
@ -327,6 +373,170 @@ void DeleteContainerSeconds(Container &C) {
C.clear();
}
//===----------------------------------------------------------------------===//
// Extra additions to <memory>
//===----------------------------------------------------------------------===//
#if LLVM_HAS_VARIADIC_TEMPLATES
// Implement make_unique according to N3656.
/// \brief Constructs a `new T()` with the given args and returns a
/// `unique_ptr<T>` which owns the object.
///
/// Example:
///
/// auto p = make_unique<int>();
/// auto p = make_unique<std::tuple<int, int>>(0, 1);
template <class T, class... Args>
typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(Args &&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
/// \brief Constructs a `new T[n]` with the given args and returns a
/// `unique_ptr<T[]>` which owns the object.
///
/// \param n size of the new array.
///
/// Example:
///
/// auto p = make_unique<int[]>(2); // value-initializes the array with 0's.
template <class T>
typename std::enable_if<std::is_array<T>::value && std::extent<T>::value == 0,
std::unique_ptr<T>>::type
make_unique(size_t n) {
return std::unique_ptr<T>(new typename std::remove_extent<T>::type[n]());
}
/// This function isn't used and is only here to provide better compile errors.
template <class T, class... Args>
typename std::enable_if<std::extent<T>::value != 0>::type
make_unique(Args &&...) LLVM_DELETED_FUNCTION;
#else
template <class T>
typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique() {
return std::unique_ptr<T>(new T());
}
template <class T, class Arg1>
typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(Arg1 &&arg1) {
return std::unique_ptr<T>(new T(std::forward<Arg1>(arg1)));
}
template <class T, class Arg1, class Arg2>
typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(Arg1 &&arg1, Arg2 &&arg2) {
return std::unique_ptr<T>(
new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2)));
}
template <class T, class Arg1, class Arg2, class Arg3>
typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3) {
return std::unique_ptr<T>(new T(std::forward<Arg1>(arg1),
std::forward<Arg2>(arg2),
std::forward<Arg3>(arg3)));
}
template <class T, class Arg1, class Arg2, class Arg3, class Arg4>
typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4) {
return std::unique_ptr<T>(
new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
std::forward<Arg3>(arg3), std::forward<Arg4>(arg4)));
}
template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5>
typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5) {
return std::unique_ptr<T>(
new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
std::forward<Arg3>(arg3), std::forward<Arg4>(arg4),
std::forward<Arg5>(arg5)));
}
template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5,
class Arg6>
typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5,
Arg6 &&arg6) {
return std::unique_ptr<T>(
new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
std::forward<Arg3>(arg3), std::forward<Arg4>(arg4),
std::forward<Arg5>(arg5), std::forward<Arg6>(arg6)));
}
template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5,
class Arg6, class Arg7>
typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5,
Arg6 &&arg6, Arg7 &&arg7) {
return std::unique_ptr<T>(
new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
std::forward<Arg3>(arg3), std::forward<Arg4>(arg4),
std::forward<Arg5>(arg5), std::forward<Arg6>(arg6),
std::forward<Arg7>(arg7)));
}
template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5,
class Arg6, class Arg7, class Arg8>
typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5,
Arg6 &&arg6, Arg7 &&arg7, Arg8 &&arg8) {
return std::unique_ptr<T>(
new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
std::forward<Arg3>(arg3), std::forward<Arg4>(arg4),
std::forward<Arg5>(arg5), std::forward<Arg6>(arg6),
std::forward<Arg7>(arg7), std::forward<Arg8>(arg8)));
}
template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5,
class Arg6, class Arg7, class Arg8, class Arg9>
typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5,
Arg6 &&arg6, Arg7 &&arg7, Arg8 &&arg8, Arg9 &&arg9) {
return std::unique_ptr<T>(
new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
std::forward<Arg3>(arg3), std::forward<Arg4>(arg4),
std::forward<Arg5>(arg5), std::forward<Arg6>(arg6),
std::forward<Arg7>(arg7), std::forward<Arg8>(arg8),
std::forward<Arg9>(arg9)));
}
template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5,
class Arg6, class Arg7, class Arg8, class Arg9, class Arg10>
typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5,
Arg6 &&arg6, Arg7 &&arg7, Arg8 &&arg8, Arg9 &&arg9, Arg10 &&arg10) {
return std::unique_ptr<T>(
new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
std::forward<Arg3>(arg3), std::forward<Arg4>(arg4),
std::forward<Arg5>(arg5), std::forward<Arg6>(arg6),
std::forward<Arg7>(arg7), std::forward<Arg8>(arg8),
std::forward<Arg9>(arg9), std::forward<Arg10>(arg10)));
}
template <class T>
typename std::enable_if<std::is_array<T>::value &&std::extent<T>::value == 0,
std::unique_ptr<T>>::type
make_unique(size_t n) {
return std::unique_ptr<T>(new typename std::remove_extent<T>::type[n]());
}
#endif
template<typename First, typename Second>
struct pair_hash {
size_t operator()(const std::pair<First, Second> &P) const {
return std::hash<First>()(P.first) * 31 + std::hash<Second>()(P.second);
}
};
} // End llvm namespace
#endif

View File

@ -148,6 +148,7 @@ class ScopedHashTable {
/// 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;
typedef unsigned size_type;
private:
typedef ScopedHashTableVal<K, V> ValTy;
DenseMap<K, ValTy*, KInfo> TopLevelMap;
@ -159,20 +160,19 @@ class ScopedHashTable {
void operator=(const ScopedHashTable&); // NOT YET IMPLEMENTED
friend class ScopedHashTableScope<K, V, KInfo, AllocatorTy>;
public:
ScopedHashTable() : CurScope(0) {}
ScopedHashTable() : CurScope(nullptr) {}
ScopedHashTable(AllocatorTy A) : CurScope(0), Allocator(A) {}
~ScopedHashTable() {
assert(CurScope == 0 && TopLevelMap.empty() && "Scope imbalance!");
assert(!CurScope && TopLevelMap.empty() && "Scope imbalance!");
}
/// 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; }
AllocatorTy &getAllocator() { return Allocator; }
const AllocatorTy &getAllocator() const { return Allocator; }
bool count(const K &Key) const {
/// Return 1 if the specified key is in the table, 0 otherwise.
size_type count(const K &Key) const {
return TopLevelMap.count(Key);
}
@ -222,7 +222,7 @@ ScopedHashTableScope<K, V, KInfo, Allocator>::
ScopedHashTableScope(ScopedHashTable<K, V, KInfo, Allocator> &ht) : HT(ht) {
PrevScope = HT.CurScope;
HT.CurScope = this;
LastValInScope = 0;
LastValInScope = nullptr;
}
template <typename K, typename V, typename KInfo, typename Allocator>
@ -233,7 +233,7 @@ ScopedHashTableScope<K, V, KInfo, Allocator>::~ScopedHashTableScope() {
// Pop and delete all values corresponding to this scope.
while (ScopedHashTableVal<K, V> *ThisEntry = LastValInScope) {
// Pop this value out of the TopLevelMap.
if (ThisEntry->getNextForKey() == 0) {
if (!ThisEntry->getNextForKey()) {
assert(HT.TopLevelMap[ThisEntry->getKey()] == ThisEntry &&
"Scope imbalance!");
HT.TopLevelMap.erase(ThisEntry->getKey());

View File

@ -195,11 +195,10 @@ class SetVector {
set_type &set_;
public:
typedef typename UnaryPredicate::argument_type argument_type;
TestAndEraseFromSet(UnaryPredicate P, set_type &set_) : P(P), set_(set_) {}
bool operator()(argument_type Arg) {
template <typename ArgumentT>
bool operator()(const ArgumentT &Arg) {
if (P(Arg)) {
set_.erase(Arg);
return true;

View File

@ -54,6 +54,7 @@ class SmallBitVector {
};
public:
typedef unsigned size_type;
// Encapsulation of a single bit.
class reference {
SmallBitVector &TheVector;
@ -153,11 +154,9 @@ class SmallBitVector {
switchToLarge(new BitVector(*RHS.getPointer()));
}
#if LLVM_HAS_RVALUE_REFERENCES
SmallBitVector(SmallBitVector &&RHS) : X(RHS.X) {
RHS.X = 1;
}
#endif
~SmallBitVector() {
if (!isSmall())
@ -175,7 +174,7 @@ class SmallBitVector {
}
/// count - Returns the number of bits which are set.
unsigned count() const {
size_type count() const {
if (isSmall()) {
uintptr_t Bits = getSmallBits();
if (NumBaseBits == 32)
@ -506,7 +505,6 @@ class SmallBitVector {
return *this;
}
#if LLVM_HAS_RVALUE_REFERENCES
const SmallBitVector &operator=(SmallBitVector &&RHS) {
if (this != &RHS) {
clear();
@ -514,7 +512,6 @@ class SmallBitVector {
}
return *this;
}
#endif
void swap(SmallBitVector &RHS) {
std::swap(X, RHS.X);

View File

@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
// This file defines the SmallPtrSet class. See the doxygen comment for
// SmallPtrSetImpl for more details on the algorithm used.
// SmallPtrSetImplBase for more details on the algorithm used.
//
//===----------------------------------------------------------------------===//
@ -27,7 +27,7 @@ namespace llvm {
class SmallPtrSetIteratorImpl;
/// SmallPtrSetImpl - This is the common code shared among all the
/// SmallPtrSetImplBase - This is the common code shared among all the
/// SmallPtrSet<>'s, which is almost everything. SmallPtrSet has two modes, one
/// for small and one for large sets.
///
@ -45,7 +45,7 @@ class SmallPtrSetIteratorImpl;
/// (-2), to allow deletion. The hash table is resized when the table is 3/4 or
/// more. When this happens, the table is doubled in size.
///
class SmallPtrSetImpl {
class SmallPtrSetImplBase {
friend class SmallPtrSetIteratorImpl;
protected:
/// SmallArray - Points to a fixed size set of buckets, used in 'small mode'.
@ -60,19 +60,22 @@ class SmallPtrSetImpl {
unsigned NumElements;
unsigned NumTombstones;
// Helper to copy construct a SmallPtrSet.
SmallPtrSetImpl(const void **SmallStorage, const SmallPtrSetImpl& that);
explicit SmallPtrSetImpl(const void **SmallStorage, unsigned SmallSize) :
// Helpers to copy and move construct a SmallPtrSet.
SmallPtrSetImplBase(const void **SmallStorage, const SmallPtrSetImplBase &that);
SmallPtrSetImplBase(const void **SmallStorage, unsigned SmallSize,
SmallPtrSetImplBase &&that);
explicit SmallPtrSetImplBase(const void **SmallStorage, unsigned SmallSize) :
SmallArray(SmallStorage), CurArray(SmallStorage), CurArraySize(SmallSize) {
assert(SmallSize && (SmallSize & (SmallSize-1)) == 0 &&
"Initial size must be a power of two!");
clear();
}
~SmallPtrSetImpl();
~SmallPtrSetImplBase();
public:
typedef unsigned size_type;
bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { return size() == 0; }
unsigned size() const { return NumElements; }
size_type size() const { return NumElements; }
void clear() {
// If the capacity of the array is huge, and the # elements used is small,
@ -128,13 +131,14 @@ class SmallPtrSetImpl {
/// Grow - Allocate a larger backing store for the buckets and move it over.
void Grow(unsigned NewSize);
void operator=(const SmallPtrSetImpl &RHS) LLVM_DELETED_FUNCTION;
void operator=(const SmallPtrSetImplBase &RHS) LLVM_DELETED_FUNCTION;
protected:
/// swap - Swaps the elements of two sets.
/// Note: This method assumes that both sets have the same small size.
void swap(SmallPtrSetImpl &RHS);
void swap(SmallPtrSetImplBase &RHS);
void CopyFrom(const SmallPtrSetImpl &RHS);
void CopyFrom(const SmallPtrSetImplBase &RHS);
void MoveFrom(unsigned SmallSize, SmallPtrSetImplBase &&RHS);
};
/// SmallPtrSetIteratorImpl - This is the common base class shared between all
@ -163,8 +167,8 @@ class SmallPtrSetIteratorImpl {
void AdvanceIfNotValid() {
assert(Bucket <= End);
while (Bucket != End &&
(*Bucket == SmallPtrSetImpl::getEmptyMarker() ||
*Bucket == SmallPtrSetImpl::getTombstoneMarker()))
(*Bucket == SmallPtrSetImplBase::getEmptyMarker() ||
*Bucket == SmallPtrSetImplBase::getTombstoneMarker()))
++Bucket;
}
};
@ -228,26 +232,25 @@ struct RoundUpToPowerOfTwo {
};
/// SmallPtrSet - This class implements a set which is optimized for holding
/// SmallSize or less elements. This internally rounds up SmallSize to the next
/// power of two if it is not already a power of two. See the comments above
/// SmallPtrSetImpl for details of the algorithm.
template<class PtrType, unsigned SmallSize>
class SmallPtrSet : public SmallPtrSetImpl {
// Make sure that SmallSize is a power of two, round up if not.
enum { SmallSizePowTwo = RoundUpToPowerOfTwo<SmallSize>::Val };
/// SmallStorage - Fixed size storage used in 'small mode'.
const void *SmallStorage[SmallSizePowTwo];
/// \brief A templated base class for \c SmallPtrSet which provides the
/// typesafe interface that is common across all small sizes.
///
/// This is particularly useful for passing around between interface boundaries
/// to avoid encoding a particular small size in the interface boundary.
template <typename PtrType>
class SmallPtrSetImpl : public SmallPtrSetImplBase {
typedef PointerLikeTypeTraits<PtrType> PtrTraits;
protected:
// Constructors that forward to the base.
SmallPtrSetImpl(const void **SmallStorage, const SmallPtrSetImpl &that)
: SmallPtrSetImplBase(SmallStorage, that) {}
SmallPtrSetImpl(const void **SmallStorage, unsigned SmallSize,
SmallPtrSetImpl &&that)
: SmallPtrSetImplBase(SmallStorage, SmallSize, std::move(that)) {}
explicit SmallPtrSetImpl(const void **SmallStorage, unsigned SmallSize)
: SmallPtrSetImplBase(SmallStorage, SmallSize) {}
public:
SmallPtrSet() : SmallPtrSetImpl(SmallStorage, SmallSizePowTwo) {}
SmallPtrSet(const SmallPtrSet &that) : SmallPtrSetImpl(SmallStorage, that) {}
template<typename It>
SmallPtrSet(It I, It E) : SmallPtrSetImpl(SmallStorage, SmallSizePowTwo) {
insert(I, E);
}
/// insert - This returns true if the pointer was new to the set, false if it
/// was already in the set.
bool insert(PtrType Ptr) {
@ -260,9 +263,9 @@ class SmallPtrSet : public SmallPtrSetImpl {
return erase_imp(PtrTraits::getAsVoidPointer(Ptr));
}
/// count - Return true if the specified pointer is in the set.
bool count(PtrType Ptr) const {
return count_imp(PtrTraits::getAsVoidPointer(Ptr));
/// count - Return 1 if the specified pointer is in the set, 0 otherwise.
size_type count(PtrType Ptr) const {
return count_imp(PtrTraits::getAsVoidPointer(Ptr)) ? 1 : 0;
}
template <typename IterT>
@ -279,18 +282,48 @@ class SmallPtrSet : public SmallPtrSetImpl {
inline iterator end() const {
return iterator(CurArray+CurArraySize, CurArray+CurArraySize);
}
};
// Allow assignment from any smallptrset with the same element type even if it
// doesn't have the same smallsize.
const SmallPtrSet<PtrType, SmallSize>&
/// SmallPtrSet - This class implements a set which is optimized for holding
/// SmallSize or less elements. This internally rounds up SmallSize to the next
/// power of two if it is not already a power of two. See the comments above
/// SmallPtrSetImplBase for details of the algorithm.
template<class PtrType, unsigned SmallSize>
class SmallPtrSet : public SmallPtrSetImpl<PtrType> {
typedef SmallPtrSetImpl<PtrType> BaseT;
// Make sure that SmallSize is a power of two, round up if not.
enum { SmallSizePowTwo = RoundUpToPowerOfTwo<SmallSize>::Val };
/// SmallStorage - Fixed size storage used in 'small mode'.
const void *SmallStorage[SmallSizePowTwo];
public:
SmallPtrSet() : BaseT(SmallStorage, SmallSizePowTwo) {}
SmallPtrSet(const SmallPtrSet &that) : BaseT(SmallStorage, that) {}
SmallPtrSet(SmallPtrSet &&that)
: BaseT(SmallStorage, SmallSizePowTwo, std::move(that)) {}
template<typename It>
SmallPtrSet(It I, It E) : BaseT(SmallStorage, SmallSizePowTwo) {
this->insert(I, E);
}
SmallPtrSet<PtrType, SmallSize> &
operator=(const SmallPtrSet<PtrType, SmallSize> &RHS) {
CopyFrom(RHS);
if (&RHS != this)
this->CopyFrom(RHS);
return *this;
}
SmallPtrSet<PtrType, SmallSize>&
operator=(SmallPtrSet<PtrType, SmallSize> &&RHS) {
if (&RHS != this)
this->MoveFrom(SmallSizePowTwo, std::move(RHS));
return *this;
}
/// swap - Swaps the elements of two sets.
void swap(SmallPtrSet<PtrType, SmallSize> &RHS) {
SmallPtrSetImpl::swap(RHS);
SmallPtrSetImplBase::swap(RHS);
}
};

View File

@ -37,18 +37,22 @@ class SmallSet {
typedef typename SmallVector<T, N>::const_iterator VIterator;
typedef typename SmallVector<T, N>::iterator mutable_iterator;
public:
typedef size_t size_type;
SmallSet() {}
bool empty() const { return Vector.empty() && Set.empty(); }
unsigned size() const {
bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const {
return Vector.empty() && Set.empty();
}
size_type size() const {
return isSmall() ? Vector.size() : Set.size();
}
/// count - Return true if the element is in the set.
bool count(const T &V) const {
/// count - Return 1 if the element is in the set, 0 otherwise.
size_type count(const T &V) const {
if (isSmall()) {
// Since the collection is small, just do a linear search.
return vfind(V) != Vector.end();
return vfind(V) == Vector.end() ? 0 : 1;
} else {
return Set.count(V);
}

View File

@ -34,9 +34,6 @@ class SmallString : public SmallVector<char, InternalLen> {
template<typename ItTy>
SmallString(ItTy S, ItTy E) : SmallVector<char, InternalLen>(S, E) {}
/// Copy ctor.
SmallString(const SmallString &RHS) : SmallVector<char, InternalLen>(RHS) {}
// Note that in order to add new overloads for append & assign, we have to
// duplicate the inherited versions so as not to inadvertently hide them.

View File

@ -14,6 +14,7 @@
#ifndef LLVM_ADT_SMALLVECTOR_H
#define LLVM_ADT_SMALLVECTOR_H
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/AlignOf.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MathExtras.h"
@ -183,13 +184,9 @@ class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T> {
/// std::move, but not all stdlibs actually provide that.
template<typename It1, typename It2>
static It2 move(It1 I, It1 E, It2 Dest) {
#if LLVM_HAS_RVALUE_REFERENCES
for (; I != E; ++I, ++Dest)
*Dest = ::std::move(*I);
return Dest;
#else
return ::std::copy(I, E, Dest);
#endif
}
/// move_backward - Use move-assignment to move the range
@ -198,25 +195,17 @@ class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T> {
/// std::move_backward, but not all stdlibs actually provide that.
template<typename It1, typename It2>
static It2 move_backward(It1 I, It1 E, It2 Dest) {
#if LLVM_HAS_RVALUE_REFERENCES
while (I != E)
*--Dest = ::std::move(*--E);
return Dest;
#else
return ::std::copy_backward(I, E, Dest);
#endif
}
/// uninitialized_move - Move the range [I, E) into the uninitialized
/// memory starting with "Dest", constructing elements as needed.
template<typename It1, typename It2>
static void uninitialized_move(It1 I, It1 E, It2 Dest) {
#if LLVM_HAS_RVALUE_REFERENCES
for (; I != E; ++I, ++Dest)
::new ((void*) &*Dest) T(::std::move(*I));
#else
::std::uninitialized_copy(I, E, Dest);
#endif
}
/// uninitialized_copy - Copy the range [I, E) onto the uninitialized
@ -231,32 +220,22 @@ class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T> {
/// Guarantees space for at least one more element, or MinSize more
/// elements if specified.
void grow(size_t MinSize = 0);
public:
void push_back(const T &Elt) {
if (this->EndX < this->CapacityX) {
Retry:
::new ((void*) this->end()) T(Elt);
this->setEnd(this->end()+1);
return;
}
this->grow();
goto Retry;
if (LLVM_UNLIKELY(this->EndX >= this->CapacityX))
this->grow();
::new ((void*) this->end()) T(Elt);
this->setEnd(this->end()+1);
}
#if LLVM_HAS_RVALUE_REFERENCES
void push_back(T &&Elt) {
if (this->EndX < this->CapacityX) {
Retry:
::new ((void*) this->end()) T(::std::move(Elt));
this->setEnd(this->end()+1);
return;
}
this->grow();
goto Retry;
if (LLVM_UNLIKELY(this->EndX >= this->CapacityX))
this->grow();
::new ((void*) this->end()) T(::std::move(Elt));
this->setEnd(this->end()+1);
}
#endif
void pop_back() {
this->setEnd(this->end()-1);
this->end()->~T();
@ -268,7 +247,7 @@ template <typename T, bool isPodLike>
void SmallVectorTemplateBase<T, isPodLike>::grow(size_t MinSize) {
size_t CurCapacity = this->capacity();
size_t CurSize = this->size();
// Always grow, even from zero.
// Always grow, even from zero.
size_t NewCapacity = size_t(NextPowerOf2(CurCapacity+2));
if (NewCapacity < MinSize)
NewCapacity = MinSize;
@ -348,16 +327,12 @@ class SmallVectorTemplateBase<T, true> : public SmallVectorTemplateCommon<T> {
}
public:
void push_back(const T &Elt) {
if (this->EndX < this->CapacityX) {
Retry:
memcpy(this->end(), &Elt, sizeof(T));
this->setEnd(this->end()+1);
return;
}
this->grow();
goto Retry;
if (LLVM_UNLIKELY(this->EndX >= this->CapacityX))
this->grow();
memcpy(this->end(), &Elt, sizeof(T));
this->setEnd(this->end()+1);
}
void pop_back() {
this->setEnd(this->end()-1);
}
@ -405,7 +380,8 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
} else if (N > this->size()) {
if (this->capacity() < N)
this->grow(N);
std::uninitialized_fill(this->end(), this->begin()+N, T());
for (auto I = this->end(), E = this->begin() + N; I != E; ++I)
new (&*I) T();
this->setEnd(this->begin()+N);
}
}
@ -428,11 +404,7 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
}
T LLVM_ATTRIBUTE_UNUSED_RESULT pop_back_val() {
#if LLVM_HAS_RVALUE_REFERENCES
T Result = ::std::move(this->back());
#else
T Result = this->back();
#endif
this->pop_back();
return Result;
}
@ -501,7 +473,6 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
return(N);
}
#if LLVM_HAS_RVALUE_REFERENCES
iterator insert(iterator I, T &&Elt) {
if (I == this->end()) { // Important special case for empty vector.
this->push_back(::std::move(Elt));
@ -511,28 +482,26 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
assert(I >= this->begin() && "Insertion iterator is out of bounds.");
assert(I <= this->end() && "Inserting past the end of the vector.");
if (this->EndX < this->CapacityX) {
Retry:
::new ((void*) this->end()) T(::std::move(this->back()));
this->setEnd(this->end()+1);
// Push everything else over.
this->move_backward(I, this->end()-1, this->end());
// If we just moved the element we're inserting, be sure to update
// the reference.
T *EltPtr = &Elt;
if (I <= EltPtr && EltPtr < this->EndX)
++EltPtr;
*I = ::std::move(*EltPtr);
return I;
if (this->EndX >= this->CapacityX) {
size_t EltNo = I-this->begin();
this->grow();
I = this->begin()+EltNo;
}
size_t EltNo = I-this->begin();
this->grow();
I = this->begin()+EltNo;
goto Retry;
::new ((void*) this->end()) T(::std::move(this->back()));
// Push everything else over.
this->move_backward(I, this->end()-1, this->end());
this->setEnd(this->end()+1);
// If we just moved the element we're inserting, be sure to update
// the reference.
T *EltPtr = &Elt;
if (I <= EltPtr && EltPtr < this->EndX)
++EltPtr;
*I = ::std::move(*EltPtr);
return I;
}
#endif
iterator insert(iterator I, const T &Elt) {
if (I == this->end()) { // Important special case for empty vector.
@ -543,26 +512,24 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
assert(I >= this->begin() && "Insertion iterator is out of bounds.");
assert(I <= this->end() && "Inserting past the end of the vector.");
if (this->EndX < this->CapacityX) {
Retry:
::new ((void*) this->end()) T(this->back());
this->setEnd(this->end()+1);
// Push everything else over.
this->move_backward(I, this->end()-1, this->end());
// If we just moved the element we're inserting, be sure to update
// the reference.
const T *EltPtr = &Elt;
if (I <= EltPtr && EltPtr < this->EndX)
++EltPtr;
*I = *EltPtr;
return I;
if (this->EndX >= this->CapacityX) {
size_t EltNo = I-this->begin();
this->grow();
I = this->begin()+EltNo;
}
size_t EltNo = I-this->begin();
this->grow();
I = this->begin()+EltNo;
goto Retry;
::new ((void*) this->end()) T(std::move(this->back()));
// Push everything else over.
this->move_backward(I, this->end()-1, this->end());
this->setEnd(this->end()+1);
// If we just moved the element we're inserting, be sure to update
// the reference.
const T *EltPtr = &Elt;
if (I <= EltPtr && EltPtr < this->EndX)
++EltPtr;
*I = *EltPtr;
return I;
}
iterator insert(iterator I, size_type NumToInsert, const T &Elt) {
@ -589,7 +556,8 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
// reallocate the vector.
if (size_t(this->end()-I) >= NumToInsert) {
T *OldEnd = this->end();
append(this->end()-NumToInsert, this->end());
append(std::move_iterator<iterator>(this->end() - NumToInsert),
std::move_iterator<iterator>(this->end()));
// Copy the existing elements that get replaced.
this->move_backward(I, OldEnd-NumToInsert, OldEnd);
@ -642,7 +610,8 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
// reallocate the vector.
if (size_t(this->end()-I) >= NumToInsert) {
T *OldEnd = this->end();
append(this->end()-NumToInsert, this->end());
append(std::move_iterator<iterator>(this->end() - NumToInsert),
std::move_iterator<iterator>(this->end()));
// Copy the existing elements that get replaced.
this->move_backward(I, OldEnd-NumToInsert, OldEnd);
@ -673,9 +642,7 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
SmallVectorImpl &operator=(const SmallVectorImpl &RHS);
#if LLVM_HAS_RVALUE_REFERENCES
SmallVectorImpl &operator=(SmallVectorImpl &&RHS);
#endif
bool operator==(const SmallVectorImpl &RHS) const {
if (this->size() != RHS.size()) return false;
@ -793,7 +760,6 @@ SmallVectorImpl<T> &SmallVectorImpl<T>::
return *this;
}
#if LLVM_HAS_RVALUE_REFERENCES
template <typename T>
SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) {
// Avoid self-assignment.
@ -842,7 +808,7 @@ SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) {
this->grow(RHSSize);
} else if (CurSize) {
// Otherwise, use assignment for the already-constructed elements.
this->move(RHS.begin(), RHS.end(), this->begin());
this->move(RHS.begin(), RHS.begin()+CurSize, this->begin());
}
// Move-construct the new elements in place.
@ -855,7 +821,6 @@ SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) {
RHS.clear();
return *this;
}
#endif
/// Storage for the SmallVector elements which aren't contained in
/// SmallVectorTemplateCommon. There are 'N-1' elements here. The remaining '1'
@ -894,6 +859,12 @@ class SmallVector : public SmallVectorImpl<T> {
this->append(S, E);
}
template <typename RangeTy>
explicit SmallVector(const llvm::iterator_range<RangeTy> R)
: SmallVectorImpl<T>(N) {
this->append(R.begin(), R.end());
}
SmallVector(const SmallVector &RHS) : SmallVectorImpl<T>(N) {
if (!RHS.empty())
SmallVectorImpl<T>::operator=(RHS);
@ -904,7 +875,6 @@ class SmallVector : public SmallVectorImpl<T> {
return *this;
}
#if LLVM_HAS_RVALUE_REFERENCES
SmallVector(SmallVector &&RHS) : SmallVectorImpl<T>(N) {
if (!RHS.empty())
SmallVectorImpl<T>::operator=(::std::move(RHS));
@ -914,8 +884,6 @@ class SmallVector : public SmallVectorImpl<T> {
SmallVectorImpl<T>::operator=(::std::move(RHS));
return *this;
}
#endif
};
template<typename T, unsigned N>

View File

@ -45,6 +45,7 @@ struct SparseBitVectorElement
: public ilist_node<SparseBitVectorElement<ElementSize> > {
public:
typedef unsigned long BitWord;
typedef unsigned size_type;
enum {
BITWORD_SIZE = sizeof(BitWord) * CHAR_BIT,
BITWORDS_PER_ELEMENT = (ElementSize + BITWORD_SIZE - 1) / BITWORD_SIZE,
@ -120,7 +121,7 @@ struct SparseBitVectorElement
return Bits[Idx / BITWORD_SIZE] & (1L << (Idx % BITWORD_SIZE));
}
unsigned count() const {
size_type count() const {
unsigned NumBits = 0;
for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i)
if (sizeof(BitWord) == 4)
@ -382,7 +383,7 @@ class SparseBitVector {
AtEnd = true;
return;
}
// Set up for next non zero word in bitmap.
// Set up for next non-zero word in bitmap.
BitNumber = Iter->index() * ElementSize;
NextSetBitNumber = Iter->find_first();
BitNumber += NextSetBitNumber;

View File

@ -76,6 +76,10 @@ template<typename ValueT,
typename KeyFunctorT = llvm::identity<unsigned>,
typename SparseT = uint8_t>
class SparseMultiSet {
static_assert(std::numeric_limits<SparseT>::is_integer &&
!std::numeric_limits<SparseT>::is_signed,
"SparseT must be an unsigned integer type");
/// The actual data that's stored, as a doubly-linked list implemented via
/// indices into the DenseVector. The doubly linked list is implemented
/// circular in Prev indices, and INVALID-terminated in Next indices. This
@ -181,9 +185,10 @@ class SparseMultiSet {
typedef const ValueT &const_reference;
typedef ValueT *pointer;
typedef const ValueT *const_pointer;
typedef unsigned size_type;
SparseMultiSet()
: Sparse(0), Universe(0), FreelistIdx(SMSNode::INVALID), NumFree(0) { }
: Sparse(nullptr), Universe(0), FreelistIdx(SMSNode::INVALID), NumFree(0) {}
~SparseMultiSet() { free(Sparse); }
@ -245,16 +250,6 @@ class SparseMultiSet {
typedef typename super::pointer pointer;
typedef typename super::reference reference;
iterator_base(const iterator_base &RHS)
: SMS(RHS.SMS), Idx(RHS.Idx), SparseIdx(RHS.SparseIdx) { }
const iterator_base &operator=(const iterator_base &RHS) {
SMS = RHS.SMS;
Idx = RHS.Idx;
SparseIdx = RHS.SparseIdx;
return *this;
}
reference operator*() const {
assert(isKeyed() && SMS->sparseIndex(SMS->Dense[Idx].Data) == SparseIdx &&
"Dereferencing iterator of invalid key or index");
@ -333,7 +328,7 @@ class SparseMultiSet {
/// This is not the same as BitVector::size() which returns the size of the
/// universe.
///
unsigned size() const {
size_type size() const {
assert(NumFree <= Dense.size() && "Out-of-bounds free entries");
return Dense.size() - NumFree;
}
@ -354,9 +349,6 @@ class SparseMultiSet {
///
iterator findIndex(unsigned Idx) {
assert(Idx < Universe && "Key out of range");
assert(std::numeric_limits<SparseT>::is_integer &&
!std::numeric_limits<SparseT>::is_signed &&
"SparseT must be an unsigned integer type");
const unsigned Stride = std::numeric_limits<SparseT>::max() + 1u;
for (unsigned i = Sparse[Idx], e = Dense.size(); i < e; i += Stride) {
const unsigned FoundIdx = sparseIndex(Dense[i]);
@ -387,7 +379,7 @@ class SparseMultiSet {
/// Returns the number of elements identified by Key. This will be linear in
/// the number of elements of that key.
unsigned count(const KeyT &Key) const {
size_type count(const KeyT &Key) const {
unsigned Ret = 0;
for (const_iterator It = find(Key); It != end(); ++It)
++Ret;

View File

@ -118,8 +118,13 @@ template<typename ValueT,
typename KeyFunctorT = llvm::identity<unsigned>,
typename SparseT = uint8_t>
class SparseSet {
static_assert(std::numeric_limits<SparseT>::is_integer &&
!std::numeric_limits<SparseT>::is_signed,
"SparseT must be an unsigned integer type");
typedef typename KeyFunctorT::argument_type KeyT;
typedef SmallVector<ValueT, 8> DenseT;
typedef unsigned size_type;
DenseT Dense;
SparseT *Sparse;
unsigned Universe;
@ -138,7 +143,7 @@ class SparseSet {
typedef ValueT *pointer;
typedef const ValueT *const_pointer;
SparseSet() : Sparse(0), Universe(0) {}
SparseSet() : Sparse(nullptr), Universe(0) {}
~SparseSet() { free(Sparse); }
/// setUniverse - Set the universe size which determines the largest key the
@ -182,7 +187,7 @@ class SparseSet {
/// This is not the same as BitVector::size() which returns the size of the
/// universe.
///
unsigned size() const { return Dense.size(); }
size_type size() const { return Dense.size(); }
/// clear - Clears the set. This is a very fast constant time operation.
///
@ -198,9 +203,6 @@ class SparseSet {
///
iterator findIndex(unsigned Idx) {
assert(Idx < Universe && "Key out of range");
assert(std::numeric_limits<SparseT>::is_integer &&
!std::numeric_limits<SparseT>::is_signed &&
"SparseT must be an unsigned integer type");
const unsigned Stride = std::numeric_limits<SparseT>::max() + 1u;
for (unsigned i = Sparse[Idx], e = size(); i < e; i += Stride) {
const unsigned FoundIdx = ValIndexOf(Dense[i]);
@ -227,10 +229,11 @@ class SparseSet {
return const_cast<SparseSet*>(this)->findIndex(KeyIndexOf(Key));
}
/// count - Returns true if this set contains an element identified by Key.
/// count - Returns 1 if this set contains an element identified by Key,
/// 0 otherwise.
///
bool count(const KeyT &Key) const {
return find(Key) != end();
size_type count(const KeyT &Key) const {
return find(Key) == end() ? 0 : 1;
}
/// insert - Attempts to insert a new element.

View File

@ -46,7 +46,7 @@ class Statistic {
/// construct - This should only be called for non-global statistics.
void construct(const char *name, const char *desc) {
Name = name; Desc = desc;
Value = 0; Initialized = 0;
Value = 0; Initialized = false;
}
// Allow use of this class as the value itself.

View File

@ -14,9 +14,9 @@
#ifndef LLVM_ADT_STRINGEXTRAS_H
#define LLVM_ADT_STRINGEXTRAS_H
#include <iterator>
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DataTypes.h"
#include <iterator>
namespace llvm {
template<typename T> class SmallVectorImpl;
@ -28,6 +28,11 @@ static inline char hexdigit(unsigned X, bool LowerCase = false) {
return X < 10 ? '0' + X : HexChar + X - 10;
}
/// Construct a string ref from a boolean.
static inline StringRef toStringRef(bool B) {
return StringRef(B ? "true" : "false");
}
/// Interpret the given character \p C as a hexadecimal digit and return its
/// value.
///
@ -48,7 +53,7 @@ static inline unsigned hexDigitValue(char C) {
/// This should only be used with unsigned types.
///
template<typename IntTy>
static inline char *utohex_buffer(IntTy X, char *BufferEnd) {
static inline char *utohex_buffer(IntTy X, char *BufferEnd, bool LowerCase = false) {
char *BufPtr = BufferEnd;
*--BufPtr = 0; // Null terminate buffer.
if (X == 0) {
@ -58,15 +63,15 @@ static inline char *utohex_buffer(IntTy X, char *BufferEnd) {
while (X) {
unsigned char Mod = static_cast<unsigned char>(X) & 15;
*--BufPtr = hexdigit(Mod);
*--BufPtr = hexdigit(Mod, LowerCase);
X >>= 4;
}
return BufPtr;
}
static inline std::string utohexstr(uint64_t X) {
static inline std::string utohexstr(uint64_t X, bool LowerCase = false) {
char Buffer[17];
return utohex_buffer(X, Buffer+17);
return utohex_buffer(X, Buffer+17, LowerCase);
}
static inline std::string utostr_32(uint32_t X, bool isNeg = false) {
@ -136,7 +141,7 @@ void SplitString(StringRef Source,
// better: http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
// X*33+c -> X*33^c
static inline unsigned HashString(StringRef Str, unsigned Result = 0) {
for (unsigned i = 0, e = Str.size(); i != e; ++i)
for (StringRef::size_type i = 0, e = Str.size(); i != e; ++i)
Result = Result * 33 + (unsigned char)Str[i];
return Result;
}

View File

@ -17,6 +17,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
#include <cstring>
#include <utility>
namespace llvm {
template<typename ValueT>
@ -26,19 +27,6 @@ namespace llvm {
template<typename ValueTy>
class StringMapEntry;
/// StringMapEntryInitializer - This datatype can be partially specialized for
/// various datatypes in a stringmap to allow them to be initialized when an
/// entry is default constructed for the map.
template<typename ValueTy>
class StringMapEntryInitializer {
public:
template <typename InitTy>
static void Initialize(StringMapEntry<ValueTy> &T, InitTy InitVal) {
T.second = InitVal;
}
};
/// StringMapEntryBase - Shared base class of StringMapEntry instances.
class StringMapEntryBase {
unsigned StrLen;
@ -61,15 +49,22 @@ class StringMapImpl {
unsigned NumTombstones;
unsigned ItemSize;
protected:
explicit StringMapImpl(unsigned itemSize) : ItemSize(itemSize) {
// Initialize the map with zero buckets to allocation.
TheTable = 0;
NumBuckets = 0;
NumItems = 0;
NumTombstones = 0;
explicit StringMapImpl(unsigned itemSize)
: TheTable(nullptr),
// Initialize the map with zero buckets to allocation.
NumBuckets(0), NumItems(0), NumTombstones(0), ItemSize(itemSize) {}
StringMapImpl(StringMapImpl &&RHS)
: TheTable(RHS.TheTable), NumBuckets(RHS.NumBuckets),
NumItems(RHS.NumItems), NumTombstones(RHS.NumTombstones),
ItemSize(RHS.ItemSize) {
RHS.TheTable = nullptr;
RHS.NumBuckets = 0;
RHS.NumItems = 0;
RHS.NumTombstones = 0;
}
StringMapImpl(unsigned InitSize, unsigned ItemSize);
void RehashTable();
unsigned RehashTable(unsigned BucketNo = 0);
/// LookupBucketFor - Look up the bucket that the specified string should end
/// up in. If it already exists as a key in the map, the Item pointer for the
@ -122,8 +117,8 @@ class StringMapEntry : public StringMapEntryBase {
explicit StringMapEntry(unsigned strLen)
: StringMapEntryBase(strLen), second() {}
StringMapEntry(unsigned strLen, const ValueTy &V)
: StringMapEntryBase(strLen), second(V) {}
StringMapEntry(unsigned strLen, ValueTy V)
: StringMapEntryBase(strLen), second(std::move(V)) {}
StringRef getKey() const {
return StringRef(getKeyData(), getKeyLength());
@ -144,15 +139,13 @@ class StringMapEntry : public StringMapEntryBase {
/// Create - Create a StringMapEntry for the specified key and default
/// construct the value.
template<typename AllocatorTy, typename InitType>
static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd,
static StringMapEntry *Create(StringRef Key,
AllocatorTy &Allocator,
InitType InitVal) {
unsigned KeyLength = static_cast<unsigned>(KeyEnd-KeyStart);
unsigned KeyLength = Key.size();
// Okay, the item doesn't already exist, and 'Bucket' is the bucket to fill
// in. Allocate a new item with space for the string at the end and a null
// Allocate a new item with space for the string at the end and a null
// terminator.
unsigned AllocSize = static_cast<unsigned>(sizeof(StringMapEntry))+
KeyLength+1;
unsigned Alignment = alignOf<StringMapEntry>();
@ -161,34 +154,29 @@ class StringMapEntry : public StringMapEntryBase {
static_cast<StringMapEntry*>(Allocator.Allocate(AllocSize,Alignment));
// Default construct the value.
new (NewItem) StringMapEntry(KeyLength);
new (NewItem) StringMapEntry(KeyLength, std::move(InitVal));
// Copy the string information.
char *StrBuffer = const_cast<char*>(NewItem->getKeyData());
memcpy(StrBuffer, KeyStart, KeyLength);
memcpy(StrBuffer, Key.data(), KeyLength);
StrBuffer[KeyLength] = 0; // Null terminate for convenience of clients.
// Initialize the value if the client wants to.
StringMapEntryInitializer<ValueTy>::Initialize(*NewItem, InitVal);
return NewItem;
}
template<typename AllocatorTy>
static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd,
AllocatorTy &Allocator) {
return Create(KeyStart, KeyEnd, Allocator, 0);
static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator) {
return Create(Key, Allocator, ValueTy());
}
/// Create - Create a StringMapEntry with normal malloc/free.
template<typename InitType>
static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd,
InitType InitVal) {
static StringMapEntry *Create(StringRef Key, InitType InitVal) {
MallocAllocator A;
return Create(KeyStart, KeyEnd, A, InitVal);
return Create(Key, A, std::move(InitVal));
}
static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd) {
return Create(KeyStart, KeyEnd, ValueTy());
static StringMapEntry *Create(StringRef Key) {
return Create(Key, ValueTy());
}
/// GetStringMapEntryFromValue - Given a value that is known to be embedded
@ -216,8 +204,10 @@ class StringMapEntry : public StringMapEntryBase {
template<typename AllocatorTy>
void Destroy(AllocatorTy &Allocator) {
// Free memory referenced by the item.
unsigned AllocSize =
static_cast<unsigned>(sizeof(StringMapEntry)) + getKeyLength() + 1;
this->~StringMapEntry();
Allocator.Deallocate(this);
Allocator.Deallocate(static_cast<void *>(this), AllocSize);
}
/// Destroy this object, releasing memory back to the malloc allocator.
@ -249,23 +239,19 @@ class StringMap : public StringMapImpl {
: StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))),
Allocator(A) {}
StringMap(const StringMap &RHS)
: 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();
StringMap(StringMap &&RHS)
: StringMapImpl(std::move(RHS)), Allocator(std::move(RHS.Allocator)) {}
StringMap &operator=(StringMap RHS) {
StringMapImpl::swap(RHS);
std::swap(Allocator, RHS.Allocator);
return *this;
}
typedef typename ReferenceAdder<AllocatorTy>::result AllocatorRefTy;
typedef typename ReferenceAdder<const AllocatorTy>::result AllocatorCRefTy;
AllocatorRefTy getAllocator() { return Allocator; }
AllocatorCRefTy getAllocator() const { return Allocator; }
// FIXME: Implement copy operations if/when they're needed.
AllocatorTy &getAllocator() { return Allocator; }
const AllocatorTy &getAllocator() const { return Allocator; }
typedef const char* key_type;
typedef ValueTy mapped_type;
@ -313,6 +299,7 @@ class StringMap : public StringMapImpl {
return GetOrCreateValue(Key).getValue();
}
/// count - Return 1 if the element is in the map, 0 otherwise.
size_type count(StringRef Key) const {
return find(Key) == end() ? 0 : 1;
}
@ -336,6 +323,28 @@ class StringMap : public StringMapImpl {
return true;
}
/// insert - Inserts the specified key/value pair into the map if the key
/// isn't already in the map. The bool component of the returned pair is true
/// if and only if the insertion takes place, and the iterator component of
/// the pair points to the element with key equivalent to the key of the pair.
std::pair<iterator, bool> insert(std::pair<StringRef, ValueTy> KV) {
unsigned BucketNo = LookupBucketFor(KV.first);
StringMapEntryBase *&Bucket = TheTable[BucketNo];
if (Bucket && Bucket != getTombstoneVal())
return std::make_pair(iterator(TheTable + BucketNo, false),
false); // Already exists in map.
if (Bucket == getTombstoneVal())
--NumTombstones;
Bucket =
MapEntryTy::Create(KV.first, Allocator, std::move(KV.second));
++NumItems;
assert(NumItems + NumTombstones <= NumBuckets);
BucketNo = RehashTable(BucketNo);
return std::make_pair(iterator(TheTable + BucketNo, false), true);
}
// clear - Empties out the StringMap
void clear() {
if (empty()) return;
@ -347,7 +356,7 @@ class StringMap : public StringMapImpl {
if (Bucket && Bucket != getTombstoneVal()) {
static_cast<MapEntryTy*>(Bucket)->Destroy(Allocator);
}
Bucket = 0;
Bucket = nullptr;
}
NumItems = 0;
@ -359,25 +368,7 @@ class StringMap : public StringMapImpl {
/// return.
template <typename InitTy>
MapEntryTy &GetOrCreateValue(StringRef Key, InitTy Val) {
unsigned BucketNo = LookupBucketFor(Key);
StringMapEntryBase *&Bucket = TheTable[BucketNo];
if (Bucket && Bucket != getTombstoneVal())
return *static_cast<MapEntryTy*>(Bucket);
MapEntryTy *NewItem =
MapEntryTy::Create(Key.begin(), Key.end(), Allocator, Val);
if (Bucket == getTombstoneVal())
--NumTombstones;
++NumItems;
assert(NumItems + NumTombstones <= NumBuckets);
// Fill in the bucket for the hash table. The FullHashValue was already
// filled in by LookupBucketFor.
Bucket = NewItem;
RehashTable();
return *NewItem;
return *insert(std::make_pair(Key, std::move(Val))).first;
}
MapEntryTy &GetOrCreateValue(StringRef Key) {
@ -404,7 +395,17 @@ class StringMap : public StringMapImpl {
}
~StringMap() {
clear();
// Delete all the elements in the map, but don't reset the elements
// to default values. This is a copy of clear(), but avoids unnecessary
// work not required in the destructor.
if (!empty()) {
for (unsigned I = 0, E = NumBuckets; I != E; ++I) {
StringMapEntryBase *Bucket = TheTable[I];
if (Bucket && Bucket != getTombstoneVal()) {
static_cast<MapEntryTy*>(Bucket)->Destroy(Allocator);
}
}
}
free(TheTable);
}
};
@ -417,7 +418,7 @@ class StringMapConstIterator {
public:
typedef StringMapEntry<ValueTy> value_type;
StringMapConstIterator() : Ptr(0) { }
StringMapConstIterator() : Ptr(nullptr) { }
explicit StringMapConstIterator(StringMapEntryBase **Bucket,
bool NoAdvance = false)
@ -450,7 +451,7 @@ class StringMapConstIterator {
private:
void AdvancePastEmptyBuckets() {
while (*Ptr == 0 || *Ptr == StringMapImpl::getTombstoneVal())
while (*Ptr == nullptr || *Ptr == StringMapImpl::getTombstoneVal())
++Ptr;
}
};

View File

@ -10,7 +10,6 @@
#ifndef LLVM_ADT_STRINGREF_H
#define LLVM_ADT_STRINGREF_H
#include "llvm/Support/type_traits.h"
#include <algorithm>
#include <cassert>
#include <cstring>
@ -70,7 +69,7 @@ namespace llvm {
/// @{
/// Construct an empty string ref.
/*implicit*/ StringRef() : Data(0), Length(0) {}
/*implicit*/ StringRef() : Data(nullptr), Length(0) {}
/// Construct a string ref from a cstring.
/*implicit*/ StringRef(const char *Str)
@ -124,6 +123,13 @@ namespace llvm {
return Data[Length-1];
}
// copy - Allocate copy in Allocator and return StringRef to it.
template <typename Allocator> StringRef copy(Allocator &A) {
char *S = A.template Allocate<char>(Length);
std::copy(begin(), end(), S);
return StringRef(S, Length);
}
/// equals - Check for string equality, this is more efficient than
/// compare() when the relative ordering of inequal strings isn't needed.
bool equals(StringRef RHS) const {
@ -179,7 +185,7 @@ namespace llvm {
/// str - Get the contents as an std::string.
std::string str() const {
if (Data == 0) return std::string();
if (!Data) return std::string();
return std::string(Data, Length);
}
@ -333,7 +339,7 @@ namespace llvm {
/// this returns true to signify the error. The string is considered
/// erroneous if empty or if it overflows T.
template <typename T>
typename enable_if_c<std::numeric_limits<T>::is_signed, bool>::type
typename std::enable_if<std::numeric_limits<T>::is_signed, bool>::type
getAsInteger(unsigned Radix, T &Result) const {
long long LLVal;
if (getAsSignedInteger(*this, Radix, LLVal) ||
@ -344,7 +350,7 @@ namespace llvm {
}
template <typename T>
typename enable_if_c<!std::numeric_limits<T>::is_signed, bool>::type
typename std::enable_if<!std::numeric_limits<T>::is_signed, bool>::type
getAsInteger(unsigned Radix, T &Result) const {
unsigned long long ULLVal;
if (getAsUnsignedInteger(*this, Radix, ULLVal) ||
@ -553,11 +559,6 @@ namespace llvm {
// StringRefs can be treated like a POD type.
template <typename T> struct isPodLike;
template <> struct isPodLike<StringRef> { static const bool value = true; };
/// Construct a string ref from a boolean.
inline StringRef toStringRef(bool B) {
return StringRef(B ? "true" : "false");
}
}
#endif

View File

@ -49,7 +49,7 @@ class StringSwitch {
public:
explicit StringSwitch(StringRef S)
: Str(S), Result(0) { }
: Str(S), Result(nullptr) { }
template<unsigned N>
StringSwitch& Case(const char (&S)[N], const T& Value) {

View File

@ -12,9 +12,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Compiler.h"
namespace llvm {
@ -70,9 +68,8 @@ class TinyPtrVector {
return *this;
}
#if LLVM_HAS_RVALUE_REFERENCES
TinyPtrVector(TinyPtrVector &&RHS) : Val(RHS.Val) {
RHS.Val = (EltTy)0;
RHS.Val = (EltTy)nullptr;
}
TinyPtrVector &operator=(TinyPtrVector &&RHS) {
if (this == &RHS)
@ -95,10 +92,9 @@ class TinyPtrVector {
}
Val = RHS.Val;
RHS.Val = (EltTy)0;
RHS.Val = (EltTy)nullptr;
return *this;
}
#endif
// implicit conversion operator to ArrayRef.
operator ArrayRef<EltTy>() const {
@ -178,7 +174,7 @@ class TinyPtrVector {
}
void push_back(EltTy NewVal) {
assert(NewVal != 0 && "Can't add a null value");
assert(NewVal && "Can't add a null value");
// If we have nothing, add something.
if (Val.isNull()) {
@ -199,7 +195,7 @@ class TinyPtrVector {
void pop_back() {
// If we have a single value, convert to empty.
if (Val.template is<EltTy>())
Val = (EltTy)0;
Val = (EltTy)nullptr;
else if (VecTy *Vec = Val.template get<VecTy*>())
Vec->pop_back();
}
@ -207,7 +203,7 @@ class TinyPtrVector {
void clear() {
// If we have a single value, convert to empty.
if (Val.template is<EltTy>()) {
Val = (EltTy)0;
Val = (EltTy)nullptr;
} else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) {
// If we have a vector form, just clear it.
Vec->clear();
@ -222,7 +218,7 @@ class TinyPtrVector {
// If we have a single value, convert to empty.
if (Val.template is<EltTy>()) {
if (I == begin())
Val = (EltTy)0;
Val = (EltTy)nullptr;
} else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) {
// multiple items in a vector; just do the erase, there is no
// benefit to collapsing back to a pointer
@ -238,7 +234,7 @@ class TinyPtrVector {
if (Val.template is<EltTy>()) {
if (S == begin() && S != E)
Val = (EltTy)0;
Val = (EltTy)nullptr;
} else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) {
return Vec->erase(S, E);
}
@ -250,7 +246,7 @@ class TinyPtrVector {
assert(I <= this->end() && "Inserting past the end of the vector.");
if (I == end()) {
push_back(Elt);
return llvm::prior(end());
return std::prev(end());
}
assert(!Val.isNull() && "Null value with non-end insert iterator.");
if (EltTy V = Val.template dyn_cast<EltTy>()) {
@ -273,7 +269,7 @@ class TinyPtrVector {
// If we have a single value, convert to a vector.
ptrdiff_t Offset = I - begin();
if (Val.isNull()) {
if (llvm::next(From) == To) {
if (std::next(From) == To) {
Val = *From;
return begin();
}

View File

@ -46,32 +46,53 @@ class Triple {
enum ArchType {
UnknownArch,
arm, // ARM: arm, armv.*, xscale
aarch64, // AArch64: aarch64
hexagon, // Hexagon: hexagon
mips, // MIPS: mips, mipsallegrex
mipsel, // MIPSEL: mipsel, mipsallegrexel
mips64, // MIPS64: mips64
mips64el,// MIPS64EL: mips64el
msp430, // MSP430: msp430
ppc, // PPC: powerpc
ppc64, // PPC64: powerpc64, ppu
ppc64le, // PPC64LE: powerpc64le
r600, // R600: AMD GPUs HD2XXX - HD6XXX
sparc, // Sparc: sparc
sparcv9, // Sparcv9: Sparcv9
systemz, // SystemZ: s390x
tce, // TCE (http://tce.cs.tut.fi/): tce
thumb, // Thumb: thumb, thumbv.*
x86, // X86: i[3-9]86
x86_64, // X86-64: amd64, x86_64
xcore, // XCore: xcore
nvptx, // NVPTX: 32-bit
nvptx64, // NVPTX: 64-bit
le32, // le32: generic little-endian 32-bit CPU (PNaCl / Emscripten)
amdil, // amdil: amd IL
spir, // SPIR: standard portable IR for OpenCL 32-bit version
spir64 // SPIR: standard portable IR for OpenCL 64-bit version
arm, // ARM (little endian): arm, armv.*, xscale
armeb, // ARM (big endian): armeb
arm64, // ARM64 (little endian): arm64
arm64_be, // ARM64 (big endian): arm64_be
aarch64, // AArch64 (little endian): aarch64
aarch64_be, // AArch64 (big endian): aarch64_be
hexagon, // Hexagon: hexagon
mips, // MIPS: mips, mipsallegrex
mipsel, // MIPSEL: mipsel, mipsallegrexel
mips64, // MIPS64: mips64
mips64el, // MIPS64EL: mips64el
msp430, // MSP430: msp430
ppc, // PPC: powerpc
ppc64, // PPC64: powerpc64, ppu
ppc64le, // PPC64LE: powerpc64le
r600, // R600: AMD GPUs HD2XXX - HD6XXX
sparc, // Sparc: sparc
sparcv9, // Sparcv9: Sparcv9
systemz, // SystemZ: s390x
tce, // TCE (http://tce.cs.tut.fi/): tce
thumb, // Thumb (little endian): thumb, thumbv.*
thumbeb, // Thumb (big endian): thumbeb
x86, // X86: i[3-9]86
x86_64, // X86-64: amd64, x86_64
xcore, // XCore: xcore
nvptx, // NVPTX: 32-bit
nvptx64, // NVPTX: 64-bit
le32, // le32: generic little-endian 32-bit CPU (PNaCl / Emscripten)
amdil, // amdil: amd IL
spir, // SPIR: standard portable IR for OpenCL 32-bit version
spir64, // SPIR: standard portable IR for OpenCL 64-bit version
kalimba // Kalimba: generic kalimba
};
enum SubArchType {
NoSubArch,
ARMSubArch_v8,
ARMSubArch_v7,
ARMSubArch_v7em,
ARMSubArch_v7m,
ARMSubArch_v7s,
ARMSubArch_v6,
ARMSubArch_v6m,
ARMSubArch_v6t2,
ARMSubArch_v5,
ARMSubArch_v5te,
ARMSubArch_v4t
};
enum VendorType {
UnknownVendor,
@ -83,7 +104,10 @@ class Triple {
BGQ,
Freescale,
IBM,
NVIDIA
ImaginationTechnologies,
MipsTechnologies,
NVIDIA,
CSR
};
enum OSType {
UnknownOS,
@ -120,10 +144,21 @@ class Triple {
GNUEABI,
GNUEABIHF,
GNUX32,
CODE16,
EABI,
MachO,
EABIHF,
Android,
ELF
MSVC,
Itanium,
Cygnus,
};
enum ObjectFormatType {
UnknownObjectFormat,
COFF,
ELF,
MachO,
};
private:
@ -132,6 +167,9 @@ class Triple {
/// The parsed arch type.
ArchType Arch;
/// The parsed subarchitecture type.
SubArchType SubArch;
/// The parsed vendor type.
VendorType Vendor;
@ -141,13 +179,16 @@ class Triple {
/// The parsed Environment type.
EnvironmentType Environment;
/// The object format type.
ObjectFormatType ObjectFormat;
public:
/// @name Constructors
/// @{
/// \brief Default constructor is the same as an empty string and leaves all
/// triple fields unknown.
Triple() : Data(), Arch(), Vendor(), OS(), Environment() {}
Triple() : Data(), Arch(), Vendor(), OS(), Environment(), ObjectFormat() {}
explicit Triple(const Twine &Str);
Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr);
@ -171,6 +212,9 @@ class Triple {
/// getArch - Get the parsed architecture type of this triple.
ArchType getArch() const { return Arch; }
/// getSubArch - get the parsed subarchitecture type for this triple.
SubArchType getSubArch() const { return SubArch; }
/// getVendor - Get the parsed vendor type of this triple.
VendorType getVendor() const { return Vendor; }
@ -186,6 +230,9 @@ class Triple {
/// getEnvironment - Get the parsed environment type of this triple.
EnvironmentType getEnvironment() const { return Environment; }
/// getFormat - Get the object format for this triple.
ObjectFormatType getObjectFormat() const { return ObjectFormat; }
/// getOSVersion - Parse the version number from the OS name component of the
/// triple, if present.
///
@ -314,14 +361,42 @@ class Triple {
return isMacOSX() || isiOS();
}
bool isOSFreeBSD() const {
return getOS() == Triple::FreeBSD;
}
bool isWindowsMSVCEnvironment() const {
return getOS() == Triple::Win32 &&
(getEnvironment() == Triple::UnknownEnvironment ||
getEnvironment() == Triple::MSVC);
}
bool isKnownWindowsMSVCEnvironment() const {
return getOS() == Triple::Win32 && getEnvironment() == Triple::MSVC;
}
bool isWindowsItaniumEnvironment() const {
return getOS() == Triple::Win32 && getEnvironment() == Triple::Itanium;
}
bool isWindowsCygwinEnvironment() const {
return getOS() == Triple::Cygwin ||
(getOS() == Triple::Win32 && getEnvironment() == Triple::Cygnus);
}
bool isWindowsGNUEnvironment() const {
return getOS() == Triple::MinGW32 ||
(getOS() == Triple::Win32 && getEnvironment() == Triple::GNU);
}
/// \brief Tests for either Cygwin or MinGW OS
bool isOSCygMing() const {
return getOS() == Triple::Cygwin || getOS() == Triple::MinGW32;
return isWindowsCygwinEnvironment() || isWindowsGNUEnvironment();
}
/// \brief Is this a "Windows" OS targeting a "MSVCRT.dll" environment.
bool isOSMSVCRT() const {
return getOS() == Triple::Win32 || getOS() == Triple::MinGW32;
return isWindowsMSVCEnvironment() || isWindowsGNUEnvironment();
}
/// \brief Tests whether the OS is Windows.
@ -341,18 +416,17 @@ class Triple {
/// \brief Tests whether the OS uses the ELF binary format.
bool isOSBinFormatELF() const {
return !isOSDarwin() && !isOSWindows();
return getObjectFormat() == Triple::ELF;
}
/// \brief Tests whether the OS uses the COFF binary format.
bool isOSBinFormatCOFF() const {
return isOSWindows();
return getObjectFormat() == Triple::COFF;
}
/// \brief Tests whether the environment is MachO.
// FIXME: Should this be an OSBinFormat predicate?
bool isEnvironmentMachO() const {
return getEnvironment() == Triple::MachO || isOSDarwin();
bool isOSBinFormatMachO() const {
return getObjectFormat() == Triple::MachO;
}
/// @}
@ -375,6 +449,9 @@ class Triple {
/// to a known type.
void setEnvironment(EnvironmentType Kind);
/// setObjectFormat - Set the object file format
void setObjectFormat(ObjectFormatType Kind);
/// setTriple - Set all components to the new triple \p Str.
void setTriple(const Twine &Str);
@ -422,6 +499,12 @@ class Triple {
/// architecture if no such variant can be found.
llvm::Triple get64BitArchVariant() const;
/// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting.
///
/// \param Arch the architecture name (e.g., "armv7s"). If it is an empty
/// string then the triple's arch name is used.
const char* getARMCPUForArch(StringRef Arch = StringRef()) const;
/// @}
/// @name Static helpers for IDs.
/// @{

View File

@ -182,6 +182,10 @@ namespace llvm {
assert(isValid() && "Invalid twine!");
}
/// Since the intended use of twines is as temporary objects, assignments
/// when concatenating might cause undefined behavior or stack corruptions
Twine &operator=(const Twine &Other) LLVM_DELETED_FUNCTION;
/// isNull - Check for the null twine.
bool isNull() const {
return getLHSKind() == NullKind;
@ -374,7 +378,7 @@ namespace llvm {
static Twine utohexstr(const uint64_t &Val) {
Child LHS, RHS;
LHS.uHex = &Val;
RHS.twine = 0;
RHS.twine = nullptr;
return Twine(LHS, UHexKind, RHS, EmptyKind);
}

View File

@ -22,13 +22,18 @@ namespace llvm {
/// class should have an implementation of operator== and of operator<.
/// Entries can be fetched using operator[] with the entry ID.
template<class T> class UniqueVector {
public:
typedef typename std::vector<T> VectorType;
typedef typename VectorType::iterator iterator;
typedef typename VectorType::const_iterator const_iterator;
private:
// Map - Used to handle the correspondence of entry to ID.
std::map<T, unsigned> Map;
// Vector - ID ordered vector of entries. Entries can be indexed by ID - 1.
//
std::vector<T> Vector;
VectorType Vector;
public:
/// insert - Append entry to the vector if it doesn't already exist. Returns
@ -68,6 +73,18 @@ template<class T> class UniqueVector {
return Vector[ID - 1];
}
/// \brief Return an iterator to the start of the vector.
iterator begin() { return Vector.begin(); }
/// \brief Return an iterator to the start of the vector.
const_iterator begin() const { return Vector.begin(); }
/// \brief Return an iterator to the end of the vector.
iterator end() { return Vector.end(); }
/// \brief Return an iterator to the end of the vector.
const_iterator end() const { return Vector.end(); }
/// size - Returns the number of entries in the vector.
///
size_t size() const { return Vector.size(); }

View File

@ -17,8 +17,8 @@
#define LLVM_ADT_EDIT_DISTANCE_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/OwningPtr.h"
#include <algorithm>
#include <memory>
namespace llvm {
@ -57,7 +57,7 @@ unsigned ComputeEditDistance(ArrayRef<T> FromArray, ArrayRef<T> ToArray,
const unsigned SmallBufferSize = 64;
unsigned SmallBuffer[SmallBufferSize];
llvm::OwningArrayPtr<unsigned> Allocated;
std::unique_ptr<unsigned[]> Allocated;
unsigned *Previous = SmallBuffer;
if (2*(n + 1) > SmallBufferSize) {
Previous = new unsigned [2*(n+1)];

View File

@ -83,7 +83,7 @@ struct ilist_sentinel_traits {
/// provideInitialHead - when constructing an ilist, provide a starting
/// value for its Head
/// @return null node to indicate that it needs to be allocated later
static NodeTy *provideInitialHead() { return 0; }
static NodeTy *provideInitialHead() { return nullptr; }
/// ensureHead - make sure that Head is either already
/// initialized or assigned a fresh sentinel
@ -92,7 +92,7 @@ struct ilist_sentinel_traits {
if (!Head) {
Head = ilist_traits<NodeTy>::createSentinel();
ilist_traits<NodeTy>::noteHead(Head, Head);
ilist_traits<NodeTy>::setNext(Head, 0);
ilist_traits<NodeTy>::setNext(Head, nullptr);
return Head;
}
return ilist_traits<NodeTy>::getPrev(Head);
@ -175,7 +175,7 @@ class ilist_iterator
ilist_iterator(pointer NP) : NodePtr(NP) {}
ilist_iterator(reference NR) : NodePtr(&NR) {}
ilist_iterator() : NodePtr(0) {}
ilist_iterator() : NodePtr(nullptr) {}
// This is templated so that we can allow constructing a const iterator from
// a nonconst iterator...
@ -383,7 +383,7 @@ class iplist : public Traits {
// Miscellaneous inspection routines.
size_type max_size() const { return size_type(-1); }
bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const {
return Head == 0 || Head == getTail();
return !Head || Head == getTail();
}
// Front and back accessor functions...
@ -451,8 +451,8 @@ class iplist : public Traits {
// an ilist (and potentially deleted) with iterators still pointing at it.
// When those iterators are incremented or decremented, they will assert on
// the null next/prev pointer instead of "usually working".
this->setNext(Node, 0);
this->setPrev(Node, 0);
this->setNext(Node, nullptr);
this->setPrev(Node, nullptr);
return Node;
}
@ -494,9 +494,9 @@ class iplist : public Traits {
// Note: we have to be careful about the case when we move the first node
// in the list. This node is the list sentinel node and we can't move it.
NodeTy *ThisSentinel = getTail();
setTail(0);
setTail(nullptr);
NodeTy *L2Sentinel = L2.getTail();
L2.setTail(0);
L2.setTail(nullptr);
// Remove [first, last) from its old position.
NodeTy *First = &*first, *Prev = this->getPrev(First);
@ -537,7 +537,7 @@ class iplist : public Traits {
//
size_type LLVM_ATTRIBUTE_UNUSED_RESULT size() const {
if (Head == 0) return 0; // Don't require construction of sentinel if empty.
if (!Head) return 0; // Don't require construction of sentinel if empty.
return std::distance(begin(), end());
}

View File

@ -30,7 +30,7 @@ class ilist_half_node {
NodeTy *getPrev() { return Prev; }
const NodeTy *getPrev() const { return Prev; }
void setPrev(NodeTy *P) { Prev = P; }
ilist_half_node() : Prev(0) {}
ilist_half_node() : Prev(nullptr) {}
};
template<typename NodeTy>
@ -48,7 +48,7 @@ class ilist_node : private ilist_half_node<NodeTy> {
const NodeTy *getNext() const { return Next; }
void setNext(NodeTy *N) { Next = N; }
protected:
ilist_node() : Next(0) {}
ilist_node() : Next(nullptr) {}
public:
/// @name Adjacent Node Accessors
@ -60,7 +60,7 @@ class ilist_node : private ilist_half_node<NodeTy> {
// Check for sentinel.
if (!Prev->getNext())
return 0;
return nullptr;
return Prev;
}
@ -71,7 +71,7 @@ class ilist_node : private ilist_half_node<NodeTy> {
// Check for sentinel.
if (!Prev->getNext())
return 0;
return nullptr;
return Prev;
}
@ -82,7 +82,7 @@ class ilist_node : private ilist_half_node<NodeTy> {
// Check for sentinel.
if (!Next->getNext())
return 0;
return nullptr;
return Next;
}
@ -93,7 +93,7 @@ class ilist_node : private ilist_half_node<NodeTy> {
// Check for sentinel.
if (!Next->getNext())
return 0;
return nullptr;
return Next;
}

View File

@ -0,0 +1,244 @@
//===- iterator.h - Utilities for using and defining iterators --*- 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_ITERATOR_H
#define LLVM_ADT_ITERATOR_H
#include <iterator>
#include <cstddef>
namespace llvm {
/// \brief CRTP base class which implements the entire standard iterator facade
/// in terms of a minimal subset of the interface.
///
/// Use this when it is reasonable to implement most of the iterator
/// functionality in terms of a core subset. If you need special behavior or
/// there are performance implications for this, you may want to override the
/// relevant members instead.
///
/// Note, one abstraction that this does *not* provide is implementing
/// subtraction in terms of addition by negating the difference. Negation isn't
/// always information preserving, and I can see very reasonable iterator
/// designs where this doesn't work well. It doesn't really force much added
/// boilerplate anyways.
///
/// Another abstraction that this doesn't provide is implementing increment in
/// terms of addition of one. These aren't equivalent for all iterator
/// categories, and respecting that adds a lot of complexity for little gain.
template <typename DerivedT, typename IteratorCategoryT, typename T,
typename DifferenceTypeT = std::ptrdiff_t, typename PointerT = T *,
typename ReferenceT = T &>
class iterator_facade_base
: public std::iterator<IteratorCategoryT, T, DifferenceTypeT, PointerT,
ReferenceT> {
protected:
enum {
IsRandomAccess =
std::is_base_of<std::random_access_iterator_tag, IteratorCategoryT>::value,
IsBidirectional =
std::is_base_of<std::bidirectional_iterator_tag, IteratorCategoryT>::value,
};
public:
DerivedT operator+(DifferenceTypeT n) const {
static_assert(
IsRandomAccess,
"The '+' operator is only defined for random access iterators.");
DerivedT tmp = *static_cast<const DerivedT *>(this);
tmp += n;
return tmp;
}
friend DerivedT operator+(DifferenceTypeT n, const DerivedT &i) {
static_assert(
IsRandomAccess,
"The '+' operator is only defined for random access iterators.");
return i + n;
}
DerivedT operator-(DifferenceTypeT n) const {
static_assert(
IsRandomAccess,
"The '-' operator is only defined for random access iterators.");
DerivedT tmp = *static_cast<const DerivedT *>(this);
tmp -= n;
return tmp;
}
DerivedT &operator++() {
return static_cast<DerivedT *>(this)->operator+=(1);
}
DerivedT operator++(int) {
DerivedT tmp = *static_cast<DerivedT *>(this);
++*static_cast<DerivedT *>(this);
return tmp;
}
DerivedT &operator--() {
static_assert(
IsBidirectional,
"The decrement operator is only defined for bidirectional iterators.");
return static_cast<DerivedT *>(this)->operator-=(1);
}
DerivedT operator--(int) {
static_assert(
IsBidirectional,
"The decrement operator is only defined for bidirectional iterators.");
DerivedT tmp = *static_cast<DerivedT *>(this);
--*static_cast<DerivedT *>(this);
return tmp;
}
bool operator!=(const DerivedT &RHS) const {
return !static_cast<const DerivedT *>(this)->operator==(RHS);
}
bool operator>(const DerivedT &RHS) const {
static_assert(
IsRandomAccess,
"Relational operators are only defined for random access iterators.");
return !static_cast<const DerivedT *>(this)->operator<(RHS) &&
!static_cast<const DerivedT *>(this)->operator==(RHS);
}
bool operator<=(const DerivedT &RHS) const {
static_assert(
IsRandomAccess,
"Relational operators are only defined for random access iterators.");
return !static_cast<const DerivedT *>(this)->operator>(RHS);
}
bool operator>=(const DerivedT &RHS) const {
static_assert(
IsRandomAccess,
"Relational operators are only defined for random access iterators.");
return !static_cast<const DerivedT *>(this)->operator<(RHS);
}
PointerT operator->() const {
return &static_cast<const DerivedT *>(this)->operator*();
}
ReferenceT operator[](DifferenceTypeT n) const {
static_assert(IsRandomAccess,
"Subscripting is only defined for random access iterators.");
return *static_cast<const DerivedT *>(this)->operator+(n);
}
};
/// \brief CRTP base class for adapting an iterator to a different type.
///
/// This class can be used through CRTP to adapt one iterator into another.
/// Typically this is done through providing in the derived class a custom \c
/// operator* implementation. Other methods can be overridden as well.
template <
typename DerivedT, typename WrappedIteratorT,
typename IteratorCategoryT =
typename std::iterator_traits<WrappedIteratorT>::iterator_category,
typename T = typename std::iterator_traits<WrappedIteratorT>::value_type,
typename DifferenceTypeT =
typename std::iterator_traits<WrappedIteratorT>::difference_type,
typename PointerT = T *, typename ReferenceT = T &,
// Don't provide these, they are mostly to act as aliases below.
typename WrappedTraitsT = std::iterator_traits<WrappedIteratorT>>
class iterator_adaptor_base
: public iterator_facade_base<DerivedT, IteratorCategoryT, T,
DifferenceTypeT, PointerT, ReferenceT> {
typedef typename iterator_adaptor_base::iterator_facade_base BaseT;
protected:
WrappedIteratorT I;
iterator_adaptor_base() {}
template <typename U>
explicit iterator_adaptor_base(
U &&u,
typename std::enable_if<
!std::is_base_of<typename std::remove_cv<
typename std::remove_reference<U>::type>::type,
DerivedT>::value,
int>::type = 0)
: I(std::forward<U &&>(u)) {}
public:
typedef DifferenceTypeT difference_type;
DerivedT &operator+=(difference_type n) {
static_assert(
BaseT::IsRandomAccess,
"The '+=' operator is only defined for random access iterators.");
I += n;
return *static_cast<DerivedT *>(this);
}
DerivedT &operator-=(difference_type n) {
static_assert(
BaseT::IsRandomAccess,
"The '-=' operator is only defined for random access iterators.");
I -= n;
return *static_cast<DerivedT *>(this);
}
using BaseT::operator-;
difference_type operator-(const DerivedT &RHS) const {
static_assert(
BaseT::IsRandomAccess,
"The '-' operator is only defined for random access iterators.");
return I - RHS.I;
}
// We have to explicitly provide ++ and -- rather than letting the facade
// forward to += because WrappedIteratorT might not support +=.
using BaseT::operator++;
DerivedT &operator++() {
++I;
return *static_cast<DerivedT *>(this);
}
using BaseT::operator--;
DerivedT &operator--() {
static_assert(
BaseT::IsBidirectional,
"The decrement operator is only defined for bidirectional iterators.");
--I;
return *static_cast<DerivedT *>(this);
}
bool operator==(const DerivedT &RHS) const { return I == RHS.I; }
bool operator<(const DerivedT &RHS) const {
static_assert(
BaseT::IsRandomAccess,
"Relational operators are only defined for random access iterators.");
return I < RHS.I;
}
ReferenceT operator*() const { return *I; }
};
/// \brief An iterator type that allows iterating over the pointees via some
/// other iterator.
///
/// The typical usage of this is to expose a type that iterates over Ts, but
/// which is implemented with some iterator over T*s:
///
/// \code
/// typedef pointee_iterator<SmallVectorImpl<T *>::iterator> iterator;
/// \endcode
template <typename WrappedIteratorT,
typename T = typename std::remove_reference<
decltype(**std::declval<WrappedIteratorT>())>::type>
struct pointee_iterator
: iterator_adaptor_base<
pointee_iterator<WrappedIteratorT>, WrappedIteratorT,
typename std::iterator_traits<WrappedIteratorT>::iterator_category,
T> {
pointee_iterator() {}
template <typename U>
pointee_iterator(U &&u)
: pointee_iterator::iterator_adaptor_base(std::forward<U &&>(u)) {}
T &operator*() const { return **this->I; }
};
}
#endif

View File

@ -0,0 +1,53 @@
//===- iterator_range.h - A range adaptor for iterators ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
/// This provides a very simple, boring adaptor for a begin and end iterator
/// into a range type. This should be used to build range views that work well
/// with range based for loops and range based constructors.
///
/// Note that code here follows more standards-based coding conventions as it
/// is mirroring proposed interfaces for standardization.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_ADT_ITERATOR_RANGE_H
#define LLVM_ADT_ITERATOR_RANGE_H
#include <utility>
namespace llvm {
/// \brief A range adaptor for a pair of iterators.
///
/// This just wraps two iterators into a range-compatible interface. Nothing
/// fancy at all.
template <typename IteratorT>
class iterator_range {
IteratorT begin_iterator, end_iterator;
public:
iterator_range() {}
iterator_range(IteratorT begin_iterator, IteratorT end_iterator)
: begin_iterator(std::move(begin_iterator)),
end_iterator(std::move(end_iterator)) {}
IteratorT begin() const { return begin_iterator; }
IteratorT end() const { return end_iterator; }
};
/// \brief Convenience function for iterating over sub-ranges.
///
/// This provides a bit of syntactic sugar to make using sub-ranges
/// in for loops a bit easier. Analogous to std::make_pair().
template <class T> iterator_range<T> make_range(T x, T y) {
return iterator_range<T>(std::move(x), std::move(y));
}
}
#endif

View File

@ -1,117 +0,0 @@
//===- llvm/ADT/polymorphic_ptr.h - Smart copyable owned ptr ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
/// This file provides a polymorphic_ptr class template. See the class comments
/// for details about this API, its intended use cases, etc.
///
/// The primary motivation here is to work around the necessity of copy
/// semantics in C++98. This is typically used where any actual copies are
/// incidental or unnecessary. As a consequence, it is expected to cease to be
/// useful and be removed when we can directly rely on move-only types.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_ADT_POLYMORPHIC_PTR_H
#define LLVM_ADT_POLYMORPHIC_PTR_H
#include "llvm/Support/Compiler.h"
namespace llvm {
/// \brief An owning, copyable polymorphic smart pointer.
///
/// This pointer exists to provide copyable owned smart pointer. Rather than
/// shared ownership semantics, it has unique ownership semantics and deep copy
/// semantics. It is copyable by requiring that the underlying type exposes
/// a method which can produce a (heap allocated) clone.
///
/// Note that in almost all scenarios use of this could be avoided if we could
/// build move-only containers of a std::unique_ptr, but until then this
/// provides an effective way to place polymorphic objects in a container.
template <typename T> class polymorphic_ptr {
T *ptr;
public:
polymorphic_ptr(T *ptr = 0) : ptr(ptr) {}
polymorphic_ptr(const polymorphic_ptr &arg) : ptr(arg ? arg->clone() : 0) {}
#if LLVM_HAS_RVALUE_REFERENCES
polymorphic_ptr(polymorphic_ptr &&arg) : ptr(arg.take()) {}
#endif
~polymorphic_ptr() { delete ptr; }
polymorphic_ptr &operator=(polymorphic_ptr arg) {
swap(arg);
return *this;
}
polymorphic_ptr &operator=(T *arg) {
if (arg != ptr) {
delete ptr;
ptr = arg;
}
return *this;
}
T &operator*() const { return *ptr; }
T *operator->() const { return ptr; }
LLVM_EXPLICIT operator bool() const { return ptr != 0; }
bool operator!() const { return ptr == 0; }
T *get() const { return ptr; }
T *take() {
T *tmp = ptr;
ptr = 0;
return tmp;
}
void swap(polymorphic_ptr &arg) {
T *tmp = ptr;
ptr = arg.ptr;
arg.ptr = tmp;
}
};
template <typename T>
void swap(polymorphic_ptr<T> &lhs, polymorphic_ptr<T> &rhs) {
lhs.swap(rhs);
}
template <typename T, typename U>
bool operator==(const polymorphic_ptr<T> &lhs, const polymorphic_ptr<U> &rhs) {
return lhs.get() == rhs.get();
}
template <typename T, typename U>
bool operator!=(const polymorphic_ptr<T> &lhs, const polymorphic_ptr<U> &rhs) {
return lhs.get() != rhs.get();
}
template <typename T, typename U>
bool operator==(const polymorphic_ptr<T> &lhs, U *rhs) {
return lhs.get() == rhs;
}
template <typename T, typename U>
bool operator!=(const polymorphic_ptr<T> &lhs, U *rhs) {
return lhs.get() != rhs;
}
template <typename T, typename U>
bool operator==(T *lhs, const polymorphic_ptr<U> &rhs) {
return lhs == rhs.get();
}
template <typename T, typename U>
bool operator!=(T *lhs, const polymorphic_ptr<U> &rhs) {
return lhs != rhs.get();
}
}
#endif

View File

@ -38,7 +38,7 @@
#define LLVM_ANALYSIS_ALIASANALYSIS_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/CallSite.h"
#include "llvm/IR/CallSite.h"
namespace llvm {
@ -55,7 +55,7 @@ class DominatorTree;
class AliasAnalysis {
protected:
const DataLayout *TD;
const DataLayout *DL;
const TargetLibraryInfo *TLI;
private:
@ -75,7 +75,7 @@ class AliasAnalysis {
public:
static char ID; // Class identification, replacement for typeinfo
AliasAnalysis() : TD(0), TLI(0), AA(0) {}
AliasAnalysis() : DL(nullptr), TLI(nullptr), AA(nullptr) {}
virtual ~AliasAnalysis(); // We want to be subclassed
/// UnknownSize - This is a special value which can be used with the
@ -86,7 +86,7 @@ class AliasAnalysis {
/// getDataLayout - Return a pointer to the current DataLayout object, or
/// null if no DataLayout object is available.
///
const DataLayout *getDataLayout() const { return TD; }
const DataLayout *getDataLayout() const { return DL; }
/// getTargetLibraryInfo - Return a pointer to the current TargetLibraryInfo
/// object, or null if no TargetLibraryInfo object is available.
@ -116,8 +116,8 @@ class AliasAnalysis {
/// 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)
explicit Location(const Value *P = nullptr, uint64_t S = UnknownSize,
const MDNode *N = nullptr)
: Ptr(P), Size(S), TBAATag(N) {}
Location getWithNewPtr(const Value *NewPtr) const {
@ -134,7 +134,7 @@ class AliasAnalysis {
Location getWithoutTBAATag() const {
Location Copy(*this);
Copy.TBAATag = 0;
Copy.TBAATag = nullptr;
return Copy;
}
};
@ -274,6 +274,14 @@ class AliasAnalysis {
UnknownModRefBehavior = Anywhere | ModRef
};
/// Get the location associated with a pointer argument of a callsite.
/// The mask bits are set to indicate the allowed aliasing ModRef kinds.
/// Note that these mask bits do not necessarily account for the overall
/// behavior of the function, but rather only provide additional
/// per-argument information.
virtual Location getArgLocation(ImmutableCallSite CS, unsigned ArgIdx,
ModRefResult &Mask);
/// getModRefBehavior - Return the behavior when calling the given call site.
virtual ModRefBehavior getModRefBehavior(ImmutableCallSite CS);
@ -560,12 +568,12 @@ struct DenseMapInfo<AliasAnalysis::Location> {
static inline AliasAnalysis::Location getEmptyKey() {
return
AliasAnalysis::Location(DenseMapInfo<const Value *>::getEmptyKey(),
0, 0);
0, nullptr);
}
static inline AliasAnalysis::Location getTombstoneKey() {
return
AliasAnalysis::Location(DenseMapInfo<const Value *>::getTombstoneKey(),
0, 0);
0, nullptr);
}
static unsigned getHashValue(const AliasAnalysis::Location &Val) {
return DenseMapInfo<const Value *>::getHashValue(Val.Ptr) ^
@ -597,6 +605,13 @@ bool isNoAliasArgument(const Value *V);
///
bool isIdentifiedObject(const Value *V);
/// isIdentifiedFunctionLocal - Return true if V is umabigously identified
/// at the function-level. Different IdentifiedFunctionLocals can't alias.
/// Further, an IdentifiedFunctionLocal can not alias with any function
/// arguments other than itself, which is not necessarily true for
/// IdentifiedObjects.
bool isIdentifiedFunctionLocal(const Value *V);
} // End llvm namespace
#endif

View File

@ -20,7 +20,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/ilist_node.h"
#include "llvm/Support/ValueHandle.h"
#include "llvm/IR/ValueHandle.h"
#include <vector>
namespace llvm {
@ -43,13 +43,13 @@ class AliasSet : public ilist_node<AliasSet> {
const MDNode *TBAAInfo;
public:
PointerRec(Value *V)
: Val(V), PrevInList(0), NextInList(0), AS(0), Size(0),
: Val(V), PrevInList(nullptr), NextInList(nullptr), AS(nullptr), Size(0),
TBAAInfo(DenseMapInfo<const MDNode *>::getEmptyKey()) {}
Value *getValue() const { return Val; }
PointerRec *getNext() const { return NextInList; }
bool hasAliasSet() const { return AS != 0; }
bool hasAliasSet() const { return AS != nullptr; }
PointerRec** setPrevInList(PointerRec **PIL) {
PrevInList = PIL;
@ -75,7 +75,7 @@ class AliasSet : public ilist_node<AliasSet> {
// If we have missing or conflicting TBAAInfo, return null.
if (TBAAInfo == DenseMapInfo<const MDNode *>::getEmptyKey() ||
TBAAInfo == DenseMapInfo<const MDNode *>::getTombstoneKey())
return 0;
return nullptr;
return TBAAInfo;
}
@ -91,7 +91,7 @@ class AliasSet : public ilist_node<AliasSet> {
}
void setAliasSet(AliasSet *as) {
assert(AS == 0 && "Already have an alias set!");
assert(!AS && "Already have an alias set!");
AS = as;
}
@ -100,7 +100,7 @@ class AliasSet : public ilist_node<AliasSet> {
*PrevInList = NextInList;
if (AS->PtrListEnd == &NextInList) {
AS->PtrListEnd = PrevInList;
assert(*AS->PtrListEnd == 0 && "List not terminated right!");
assert(*AS->PtrListEnd == nullptr && "List not terminated right!");
}
delete this;
}
@ -174,7 +174,7 @@ class AliasSet : public ilist_node<AliasSet> {
class iterator;
iterator begin() const { return iterator(PtrList); }
iterator end() const { return iterator(); }
bool empty() const { return PtrList == 0; }
bool empty() const { return PtrList == nullptr; }
void print(raw_ostream &OS) const;
void dump() const;
@ -184,7 +184,7 @@ class AliasSet : public ilist_node<AliasSet> {
PointerRec, ptrdiff_t> {
PointerRec *CurNode;
public:
explicit iterator(PointerRec *CN = 0) : CurNode(CN) {}
explicit iterator(PointerRec *CN = nullptr) : CurNode(CN) {}
bool operator==(const iterator& x) const {
return CurNode == x.CurNode;
@ -220,8 +220,9 @@ class AliasSet : public ilist_node<AliasSet> {
// Can only be created by AliasSetTracker. Also, ilist creates one
// to serve as a sentinel.
friend struct ilist_sentinel_traits<AliasSet>;
AliasSet() : PtrList(0), PtrListEnd(&PtrList), Forward(0), RefCount(0),
AccessTy(NoModRef), AliasTy(MustAlias), Volatile(false) {
AliasSet()
: PtrList(nullptr), PtrListEnd(&PtrList), Forward(nullptr), RefCount(0),
AccessTy(NoModRef), AliasTy(MustAlias), Volatile(false) {
}
AliasSet(const AliasSet &AS) LLVM_DELETED_FUNCTION;
@ -282,10 +283,10 @@ class AliasSetTracker {
/// notified whenever a Value is deleted.
class ASTCallbackVH : public CallbackVH {
AliasSetTracker *AST;
virtual void deleted();
virtual void allUsesReplacedWith(Value *);
void deleted() override;
void allUsesReplacedWith(Value *) override;
public:
ASTCallbackVH(Value *V, AliasSetTracker *AST = 0);
ASTCallbackVH(Value *V, AliasSetTracker *AST = nullptr);
ASTCallbackVH &operator=(Value *V);
};
/// ASTCallbackVHDenseMapInfo - Traits to tell DenseMap that tell us how to
@ -354,7 +355,7 @@ class AliasSetTracker {
/// pointer didn't alias anything).
AliasSet &getAliasSetForPointer(Value *P, uint64_t Size,
const MDNode *TBAAInfo,
bool *New = 0);
bool *New = nullptr);
/// getAliasSetForPointerIfExists - Return the alias set containing the
/// location specified if one exists, otherwise return null.
@ -408,7 +409,7 @@ class AliasSetTracker {
// entry for the pointer if it doesn't already exist.
AliasSet::PointerRec &getEntryFor(Value *V) {
AliasSet::PointerRec *&Entry = PointerMap[ASTCallbackVH(V, this)];
if (Entry == 0)
if (!Entry)
Entry = new AliasSet::PointerRec(V);
return *Entry;
}

View File

@ -1,347 +0,0 @@
//===-- BlockFrequencyImpl.h - Block Frequency Implementation --*- C++ -*--===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Shared implementation of BlockFrequency for IR and Machine Instructions.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_BLOCKFREQUENCYIMPL_H
#define LLVM_ANALYSIS_BLOCKFREQUENCYIMPL_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/Support/BlockFrequency.h"
#include "llvm/Support/BranchProbability.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include <string>
#include <vector>
namespace llvm {
class BlockFrequencyInfo;
class MachineBlockFrequencyInfo;
/// BlockFrequencyImpl implements block frequency algorithm for IR and
/// Machine Instructions. Algorithm starts with value ENTRY_FREQ
/// for the entry block and then propagates frequencies using branch weights
/// from (Machine)BranchProbabilityInfo. LoopInfo is not required because
/// algorithm can find "backedges" by itself.
template<class BlockT, class FunctionT, class BlockProbInfoT>
class BlockFrequencyImpl {
DenseMap<const BlockT *, BlockFrequency> Freqs;
BlockProbInfoT *BPI;
FunctionT *Fn;
typedef GraphTraits< Inverse<BlockT *> > GT;
const uint32_t EntryFreq;
std::string getBlockName(BasicBlock *BB) const {
return BB->getName().str();
}
std::string getBlockName(MachineBasicBlock *MBB) const {
std::string str;
raw_string_ostream ss(str);
ss << "BB#" << MBB->getNumber();
if (const BasicBlock *BB = MBB->getBasicBlock())
ss << " derived from LLVM BB " << BB->getName();
return ss.str();
}
void setBlockFreq(BlockT *BB, BlockFrequency Freq) {
Freqs[BB] = Freq;
DEBUG(dbgs() << "Frequency(" << getBlockName(BB) << ") = " << Freq << "\n");
}
/// getEdgeFreq - Return edge frequency based on SRC frequency and Src -> Dst
/// edge probability.
BlockFrequency getEdgeFreq(BlockT *Src, BlockT *Dst) const {
BranchProbability Prob = BPI->getEdgeProbability(Src, Dst);
return getBlockFreq(Src) * Prob;
}
/// incBlockFreq - Increase BB block frequency by FREQ.
///
void incBlockFreq(BlockT *BB, BlockFrequency Freq) {
Freqs[BB] += Freq;
DEBUG(dbgs() << "Frequency(" << getBlockName(BB) << ") += " << Freq
<< " --> " << Freqs[BB] << "\n");
}
// All blocks in postorder.
std::vector<BlockT *> POT;
// Map Block -> Position in reverse-postorder list.
DenseMap<BlockT *, unsigned> RPO;
// For each loop header, record the per-iteration probability of exiting the
// loop. This is the reciprocal of the expected number of loop iterations.
typedef DenseMap<BlockT*, BranchProbability> LoopExitProbMap;
LoopExitProbMap LoopExitProb;
// (reverse-)postorder traversal iterators.
typedef typename std::vector<BlockT *>::iterator pot_iterator;
typedef typename std::vector<BlockT *>::reverse_iterator rpot_iterator;
pot_iterator pot_begin() { return POT.begin(); }
pot_iterator pot_end() { return POT.end(); }
rpot_iterator rpot_begin() { return POT.rbegin(); }
rpot_iterator rpot_end() { return POT.rend(); }
rpot_iterator rpot_at(BlockT *BB) {
rpot_iterator I = rpot_begin();
unsigned idx = RPO.lookup(BB);
assert(idx);
std::advance(I, idx - 1);
assert(*I == BB);
return I;
}
/// isBackedge - Return if edge Src -> Dst is a reachable backedge.
///
bool isBackedge(BlockT *Src, BlockT *Dst) const {
unsigned a = RPO.lookup(Src);
if (!a)
return false;
unsigned b = RPO.lookup(Dst);
assert(b && "Destination block should be reachable");
return a >= b;
}
/// getSingleBlockPred - return single BB block predecessor or NULL if
/// BB has none or more predecessors.
BlockT *getSingleBlockPred(BlockT *BB) {
typename GT::ChildIteratorType
PI = GraphTraits< Inverse<BlockT *> >::child_begin(BB),
PE = GraphTraits< Inverse<BlockT *> >::child_end(BB);
if (PI == PE)
return 0;
BlockT *Pred = *PI;
++PI;
if (PI != PE)
return 0;
return Pred;
}
void doBlock(BlockT *BB, BlockT *LoopHead,
SmallPtrSet<BlockT *, 8> &BlocksInLoop) {
DEBUG(dbgs() << "doBlock(" << getBlockName(BB) << ")\n");
setBlockFreq(BB, 0);
if (BB == LoopHead) {
setBlockFreq(BB, EntryFreq);
return;
}
if(BlockT *Pred = getSingleBlockPred(BB)) {
if (BlocksInLoop.count(Pred))
setBlockFreq(BB, getEdgeFreq(Pred, BB));
// TODO: else? irreducible, ignore it for now.
return;
}
bool isInLoop = false;
bool isLoopHead = false;
for (typename GT::ChildIteratorType
PI = GraphTraits< Inverse<BlockT *> >::child_begin(BB),
PE = GraphTraits< Inverse<BlockT *> >::child_end(BB);
PI != PE; ++PI) {
BlockT *Pred = *PI;
if (isBackedge(Pred, BB)) {
isLoopHead = true;
} else if (BlocksInLoop.count(Pred)) {
incBlockFreq(BB, getEdgeFreq(Pred, BB));
isInLoop = true;
}
// TODO: else? irreducible.
}
if (!isInLoop)
return;
if (!isLoopHead)
return;
// This block is a loop header, so boost its frequency by the expected
// number of loop iterations. The loop blocks will be revisited so they all
// get this boost.
typename LoopExitProbMap::const_iterator I = LoopExitProb.find(BB);
assert(I != LoopExitProb.end() && "Loop header missing from table");
Freqs[BB] /= I->second;
DEBUG(dbgs() << "Loop header scaled to " << Freqs[BB] << ".\n");
}
/// doLoop - Propagate block frequency down through the loop.
void doLoop(BlockT *Head, BlockT *Tail) {
DEBUG(dbgs() << "doLoop(" << getBlockName(Head) << ", "
<< getBlockName(Tail) << ")\n");
SmallPtrSet<BlockT *, 8> BlocksInLoop;
for (rpot_iterator I = rpot_at(Head), E = rpot_at(Tail); ; ++I) {
BlockT *BB = *I;
doBlock(BB, Head, BlocksInLoop);
BlocksInLoop.insert(BB);
if (I == E)
break;
}
// Compute loop's cyclic probability using backedges probabilities.
BlockFrequency BackFreq;
for (typename GT::ChildIteratorType
PI = GraphTraits< Inverse<BlockT *> >::child_begin(Head),
PE = GraphTraits< Inverse<BlockT *> >::child_end(Head);
PI != PE; ++PI) {
BlockT *Pred = *PI;
assert(Pred);
if (isBackedge(Pred, Head))
BackFreq += getEdgeFreq(Pred, Head);
}
// The cyclic probability is freq(BackEdges) / freq(Head), where freq(Head)
// only counts edges entering the loop, not the loop backedges.
// The probability of leaving the loop on each iteration is:
//
// ExitProb = 1 - CyclicProb
//
// The Expected number of loop iterations is:
//
// Iterations = 1 / ExitProb
//
uint64_t D = std::max(getBlockFreq(Head).getFrequency(), UINT64_C(1));
uint64_t N = std::max(BackFreq.getFrequency(), UINT64_C(1));
if (N < D)
N = D - N;
else
// We'd expect N < D, but rounding and saturation means that can't be
// guaranteed.
N = 1;
// Now ExitProb = N / D, make sure it fits in an i32/i32 fraction.
assert(N <= D);
if (D > UINT32_MAX) {
unsigned Shift = 32 - countLeadingZeros(D);
D >>= Shift;
N >>= Shift;
if (N == 0)
N = 1;
}
BranchProbability LEP = BranchProbability(N, D);
LoopExitProb.insert(std::make_pair(Head, LEP));
DEBUG(dbgs() << "LoopExitProb[" << getBlockName(Head) << "] = " << LEP
<< " from 1 - " << BackFreq << " / " << getBlockFreq(Head)
<< ".\n");
}
friend class BlockFrequencyInfo;
friend class MachineBlockFrequencyInfo;
BlockFrequencyImpl() : EntryFreq(BlockFrequency::getEntryFrequency()) { }
void doFunction(FunctionT *fn, BlockProbInfoT *bpi) {
Fn = fn;
BPI = bpi;
// Clear everything.
RPO.clear();
POT.clear();
LoopExitProb.clear();
Freqs.clear();
BlockT *EntryBlock = fn->begin();
std::copy(po_begin(EntryBlock), po_end(EntryBlock), std::back_inserter(POT));
unsigned RPOidx = 0;
for (rpot_iterator I = rpot_begin(), E = rpot_end(); I != E; ++I) {
BlockT *BB = *I;
RPO[BB] = ++RPOidx;
DEBUG(dbgs() << "RPO[" << getBlockName(BB) << "] = " << RPO[BB] << "\n");
}
// Travel over all blocks in postorder.
for (pot_iterator I = pot_begin(), E = pot_end(); I != E; ++I) {
BlockT *BB = *I;
BlockT *LastTail = 0;
DEBUG(dbgs() << "POT: " << getBlockName(BB) << "\n");
for (typename GT::ChildIteratorType
PI = GraphTraits< Inverse<BlockT *> >::child_begin(BB),
PE = GraphTraits< Inverse<BlockT *> >::child_end(BB);
PI != PE; ++PI) {
BlockT *Pred = *PI;
if (isBackedge(Pred, BB) && (!LastTail || RPO[Pred] > RPO[LastTail]))
LastTail = Pred;
}
if (LastTail)
doLoop(BB, LastTail);
}
// At the end assume the whole function as a loop, and travel over it once
// again.
doLoop(*(rpot_begin()), *(pot_begin()));
}
public:
/// getBlockFreq - Return block frequency. Return 0 if we don't have it.
BlockFrequency getBlockFreq(const BlockT *BB) const {
typename DenseMap<const BlockT *, BlockFrequency>::const_iterator
I = Freqs.find(BB);
if (I != Freqs.end())
return I->second;
return 0;
}
void print(raw_ostream &OS) const {
OS << "\n\n---- Block Freqs ----\n";
for (typename FunctionT::iterator I = Fn->begin(), E = Fn->end(); I != E;) {
BlockT *BB = I++;
OS << " " << getBlockName(BB) << " = " << getBlockFreq(BB) << "\n";
for (typename GraphTraits<BlockT *>::ChildIteratorType
SI = GraphTraits<BlockT *>::child_begin(BB),
SE = GraphTraits<BlockT *>::child_end(BB); SI != SE; ++SI) {
BlockT *Succ = *SI;
OS << " " << getBlockName(BB) << " -> " << getBlockName(Succ)
<< " = " << getEdgeFreq(BB, Succ) << "\n";
}
}
}
void dump() const {
print(dbgs());
}
};
}
#endif

View File

@ -1,4 +1,4 @@
//===------- BlockFrequencyInfo.h - Block Frequency Analysis --*- C++ -*---===//
//===- BlockFrequencyInfo.h - Block Frequency Analysis ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -21,14 +21,13 @@
namespace llvm {
class BranchProbabilityInfo;
template<class BlockT, class FunctionT, class BranchProbInfoT>
class BlockFrequencyImpl;
template <class BlockT> class BlockFrequencyInfoImpl;
/// BlockFrequencyInfo pass uses BlockFrequencyImpl implementation to estimate
/// IR basic block frequencies.
/// BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to
/// estimate IR basic block frequencies.
class BlockFrequencyInfo : public FunctionPass {
BlockFrequencyImpl<BasicBlock, Function, BranchProbabilityInfo> *BFI;
typedef BlockFrequencyInfoImpl<BasicBlock> ImplType;
std::unique_ptr<ImplType> BFI;
public:
static char ID;
@ -37,10 +36,11 @@ class BlockFrequencyInfo : public FunctionPass {
~BlockFrequencyInfo();
void getAnalysisUsage(AnalysisUsage &AU) const;
void getAnalysisUsage(AnalysisUsage &AU) const override;
bool runOnFunction(Function &F);
void print(raw_ostream &O, const Module *M) const;
bool runOnFunction(Function &F) override;
void releaseMemory() override;
void print(raw_ostream &O, const Module *M) const override;
const Function *getFunction() const;
void view() const;
@ -50,6 +50,17 @@ class BlockFrequencyInfo : public FunctionPass {
/// comparison to the other block frequencies. We do this to avoid using of
/// floating points.
BlockFrequency getBlockFreq(const BasicBlock *BB) const;
// Print the block frequency Freq to OS using the current functions entry
// frequency to convert freq into a relative decimal form.
raw_ostream &printBlockFreq(raw_ostream &OS, const BlockFrequency Freq) const;
// Convenience method that attempts to look up the frequency associated with
// BB and print it to OS.
raw_ostream &printBlockFreq(raw_ostream &OS, const BasicBlock *BB) const;
uint64_t getEntryFreq() const;
};
}

File diff suppressed because it is too large Load Diff

View File

@ -16,6 +16,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/IR/CFG.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#include "llvm/Support/BranchProbability.h"
@ -44,9 +45,9 @@ class BranchProbabilityInfo : public FunctionPass {
initializeBranchProbabilityInfoPass(*PassRegistry::getPassRegistry());
}
void getAnalysisUsage(AnalysisUsage &AU) const;
bool runOnFunction(Function &F);
void print(raw_ostream &OS, const Module *M = 0) const;
void getAnalysisUsage(AnalysisUsage &AU) const override;
bool runOnFunction(Function &F) override;
void print(raw_ostream &OS, const Module *M = nullptr) const override;
/// \brief Get an edge's probability, relative to other out-edges of the Src.
///
@ -98,6 +99,9 @@ class BranchProbabilityInfo : public FunctionPass {
/// It is guaranteed to fall between 1 and UINT32_MAX.
uint32_t getEdgeWeight(const BasicBlock *Src, const BasicBlock *Dst) const;
uint32_t getEdgeWeight(const BasicBlock *Src,
succ_const_iterator Dst) const;
/// \brief Set the raw edge weight for a given edge.
///
/// This allows a pass to explicitly set the edge weight for an edge. It can

View File

@ -16,7 +16,7 @@
#define LLVM_ANALYSIS_CFG_H
#include "llvm/IR/BasicBlock.h"
#include "llvm/Support/CFG.h"
#include "llvm/IR/CFG.h"
namespace llvm {
@ -65,8 +65,8 @@ bool isCriticalEdge(const TerminatorInst *TI, unsigned SuccNum,
/// on branchy code but not loops, and LI is most useful on code with loops but
/// does not help on branchy code outside loops.
bool isPotentiallyReachable(const Instruction *From, const Instruction *To,
const DominatorTree *DT = 0,
const LoopInfo *LI = 0);
const DominatorTree *DT = nullptr,
const LoopInfo *LI = nullptr);
/// \brief Determine whether block 'To' is reachable from 'From', returning
/// true if uncertain.
@ -75,8 +75,8 @@ bool isPotentiallyReachable(const Instruction *From, const Instruction *To,
/// Returns false only if we can prove that once 'From' has been reached then
/// 'To' can not be executed. Conservatively returns true.
bool isPotentiallyReachable(const BasicBlock *From, const BasicBlock *To,
const DominatorTree *DT = 0,
const LoopInfo *LI = 0);
const DominatorTree *DT = nullptr,
const LoopInfo *LI = nullptr);
} // End llvm namespace

View File

@ -15,11 +15,10 @@
#ifndef LLVM_ANALYSIS_CFGPRINTER_H
#define LLVM_ANALYSIS_CFGPRINTER_H
#include "llvm/Assembly/Writer.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/GraphWriter.h"
namespace llvm {
@ -40,7 +39,7 @@ struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits {
std::string Str;
raw_string_ostream OS(Str);
WriteAsOperand(OS, Node, false);
Node->printAsOperand(OS, false);
return OS.str();
}
@ -51,7 +50,7 @@ struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits {
raw_string_ostream OS(Str);
if (Node->getName().empty()) {
WriteAsOperand(OS, Node, false);
Node->printAsOperand(OS, false);
OS << ":";
}

View File

@ -0,0 +1,591 @@
//===- CGSCCPassManager.h - Call graph pass management ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
///
/// This header provides classes for managing passes over SCCs of the call
/// graph. These passes form an important component of LLVM's interprocedural
/// optimizations. Because they operate on the SCCs of the call graph, and they
/// wtraverse the graph in post order, they can effectively do pair-wise
/// interprocedural optimizations for all call edges in the program. At each
/// call site edge, the callee has already been optimized as much as is
/// possible. This in turn allows very accurate analysis of it for IPO.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_CGSCC_PASS_MANAGER_H
#define LLVM_ANALYSIS_CGSCC_PASS_MANAGER_H
#include "llvm/IR/PassManager.h"
#include "llvm/Analysis/LazyCallGraph.h"
namespace llvm {
class CGSCCAnalysisManager;
class CGSCCPassManager {
public:
// We have to explicitly define all the special member functions because MSVC
// refuses to generate them.
CGSCCPassManager() {}
CGSCCPassManager(CGSCCPassManager &&Arg) : Passes(std::move(Arg.Passes)) {}
CGSCCPassManager &operator=(CGSCCPassManager &&RHS) {
Passes = std::move(RHS.Passes);
return *this;
}
/// \brief Run all of the CGSCC passes in this pass manager over a SCC.
PreservedAnalyses run(LazyCallGraph::SCC *C,
CGSCCAnalysisManager *AM = nullptr);
template <typename CGSCCPassT> void addPass(CGSCCPassT Pass) {
Passes.emplace_back(new CGSCCPassModel<CGSCCPassT>(std::move(Pass)));
}
static StringRef name() { return "CGSCCPassManager"; }
private:
// Pull in the concept type and model template specialized for SCCs.
typedef detail::PassConcept<LazyCallGraph::SCC *, CGSCCAnalysisManager>
CGSCCPassConcept;
template <typename PassT>
struct CGSCCPassModel
: detail::PassModel<LazyCallGraph::SCC *, CGSCCAnalysisManager, PassT> {
CGSCCPassModel(PassT Pass)
: detail::PassModel<LazyCallGraph::SCC *, CGSCCAnalysisManager, PassT>(
std::move(Pass)) {}
};
CGSCCPassManager(const CGSCCPassManager &) LLVM_DELETED_FUNCTION;
CGSCCPassManager &operator=(const CGSCCPassManager &) LLVM_DELETED_FUNCTION;
std::vector<std::unique_ptr<CGSCCPassConcept>> Passes;
};
/// \brief A function analysis manager to coordinate and cache analyses run over
/// a module.
class CGSCCAnalysisManager : public detail::AnalysisManagerBase<
CGSCCAnalysisManager, LazyCallGraph::SCC *> {
friend class detail::AnalysisManagerBase<CGSCCAnalysisManager,
LazyCallGraph::SCC *>;
typedef detail::AnalysisManagerBase<CGSCCAnalysisManager,
LazyCallGraph::SCC *> BaseT;
typedef BaseT::ResultConceptT ResultConceptT;
typedef BaseT::PassConceptT PassConceptT;
public:
// Most public APIs are inherited from the CRTP base class.
// We have to explicitly define all the special member functions because MSVC
// refuses to generate them.
CGSCCAnalysisManager() {}
CGSCCAnalysisManager(CGSCCAnalysisManager &&Arg)
: BaseT(std::move(static_cast<BaseT &>(Arg))),
CGSCCAnalysisResults(std::move(Arg.CGSCCAnalysisResults)) {}
CGSCCAnalysisManager &operator=(CGSCCAnalysisManager &&RHS) {
BaseT::operator=(std::move(static_cast<BaseT &>(RHS)));
CGSCCAnalysisResults = std::move(RHS.CGSCCAnalysisResults);
return *this;
}
/// \brief Returns true if the analysis manager has an empty results cache.
bool empty() const;
/// \brief Clear the function analysis result cache.
///
/// This routine allows cleaning up when the set of functions itself has
/// potentially changed, and thus we can't even look up a a result and
/// invalidate it directly. Notably, this does *not* call invalidate
/// functions as there is nothing to be done for them.
void clear();
private:
CGSCCAnalysisManager(const CGSCCAnalysisManager &) LLVM_DELETED_FUNCTION;
CGSCCAnalysisManager &
operator=(const CGSCCAnalysisManager &) LLVM_DELETED_FUNCTION;
/// \brief Get a function pass result, running the pass if necessary.
ResultConceptT &getResultImpl(void *PassID, LazyCallGraph::SCC *C);
/// \brief Get a cached function pass result or return null.
ResultConceptT *getCachedResultImpl(void *PassID,
LazyCallGraph::SCC *C) const;
/// \brief Invalidate a function pass result.
void invalidateImpl(void *PassID, LazyCallGraph::SCC *C);
/// \brief Invalidate the results for a function..
void invalidateImpl(LazyCallGraph::SCC *C, const PreservedAnalyses &PA);
/// \brief List of function analysis pass IDs and associated concept pointers.
///
/// Requires iterators to be valid across appending new entries and arbitrary
/// erases. Provides both the pass ID and concept pointer such that it is
/// half of a bijection and provides storage for the actual result concept.
typedef std::list<
std::pair<void *, std::unique_ptr<detail::AnalysisResultConcept<
LazyCallGraph::SCC *>>>> CGSCCAnalysisResultListT;
/// \brief Map type from function pointer to our custom list type.
typedef DenseMap<LazyCallGraph::SCC *, CGSCCAnalysisResultListT>
CGSCCAnalysisResultListMapT;
/// \brief Map from function to a list of function analysis results.
///
/// Provides linear time removal of all analysis results for a function and
/// the ultimate storage for a particular cached analysis result.
CGSCCAnalysisResultListMapT CGSCCAnalysisResultLists;
/// \brief Map type from a pair of analysis ID and function pointer to an
/// iterator into a particular result list.
typedef DenseMap<std::pair<void *, LazyCallGraph::SCC *>,
CGSCCAnalysisResultListT::iterator> CGSCCAnalysisResultMapT;
/// \brief Map from an analysis ID and function to a particular cached
/// analysis result.
CGSCCAnalysisResultMapT CGSCCAnalysisResults;
};
/// \brief A module analysis which acts as a proxy for a CGSCC analysis
/// manager.
///
/// This primarily proxies invalidation information from the module analysis
/// manager and module pass manager to a CGSCC analysis manager. You should
/// never use a CGSCC analysis manager from within (transitively) a module
/// pass manager unless your parent module pass has received a proxy result
/// object for it.
class CGSCCAnalysisManagerModuleProxy {
public:
class Result {
public:
explicit Result(CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {}
// We have to explicitly define all the special member functions because
// MSVC refuses to generate them.
Result(const Result &Arg) : CGAM(Arg.CGAM) {}
Result(Result &&Arg) : CGAM(std::move(Arg.CGAM)) {}
Result &operator=(Result RHS) {
std::swap(CGAM, RHS.CGAM);
return *this;
}
~Result();
/// \brief Accessor for the \c CGSCCAnalysisManager.
CGSCCAnalysisManager &getManager() { return *CGAM; }
/// \brief Handler for invalidation of the module.
///
/// If this analysis itself is preserved, then we assume that the call
/// graph of the module hasn't changed and thus we don't need to invalidate
/// *all* cached data associated with a \c SCC* in the \c
/// CGSCCAnalysisManager.
///
/// Regardless of whether this analysis is marked as preserved, all of the
/// analyses in the \c CGSCCAnalysisManager are potentially invalidated
/// based on the set of preserved analyses.
bool invalidate(Module *M, const PreservedAnalyses &PA);
private:
CGSCCAnalysisManager *CGAM;
};
static void *ID() { return (void *)&PassID; }
explicit CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManager &CGAM)
: CGAM(&CGAM) {}
// We have to explicitly define all the special member functions because MSVC
// refuses to generate them.
CGSCCAnalysisManagerModuleProxy(
const CGSCCAnalysisManagerModuleProxy &Arg)
: CGAM(Arg.CGAM) {}
CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManagerModuleProxy &&Arg)
: CGAM(std::move(Arg.CGAM)) {}
CGSCCAnalysisManagerModuleProxy &
operator=(CGSCCAnalysisManagerModuleProxy RHS) {
std::swap(CGAM, RHS.CGAM);
return *this;
}
/// \brief Run the analysis pass and create our proxy result object.
///
/// This doesn't do any interesting work, it is primarily used to insert our
/// proxy result object into the module analysis cache so that we can proxy
/// invalidation to the CGSCC analysis manager.
///
/// In debug builds, it will also assert that the analysis manager is empty
/// as no queries should arrive at the CGSCC analysis manager prior to
/// this analysis being requested.
Result run(Module *M);
private:
static char PassID;
CGSCCAnalysisManager *CGAM;
};
/// \brief A CGSCC analysis which acts as a proxy for a module analysis
/// manager.
///
/// This primarily provides an accessor to a parent module analysis manager to
/// CGSCC passes. Only the const interface of the module analysis manager is
/// provided to indicate that once inside of a CGSCC analysis pass you
/// cannot request a module analysis to actually run. Instead, the user must
/// rely on the \c getCachedResult API.
///
/// This proxy *doesn't* manage the invalidation in any way. That is handled by
/// the recursive return path of each layer of the pass manager and the
/// returned PreservedAnalysis set.
class ModuleAnalysisManagerCGSCCProxy {
public:
/// \brief Result proxy object for \c ModuleAnalysisManagerCGSCCProxy.
class Result {
public:
explicit Result(const ModuleAnalysisManager &MAM) : MAM(&MAM) {}
// We have to explicitly define all the special member functions because
// MSVC refuses to generate them.
Result(const Result &Arg) : MAM(Arg.MAM) {}
Result(Result &&Arg) : MAM(std::move(Arg.MAM)) {}
Result &operator=(Result RHS) {
std::swap(MAM, RHS.MAM);
return *this;
}
const ModuleAnalysisManager &getManager() const { return *MAM; }
/// \brief Handle invalidation by ignoring it, this pass is immutable.
bool invalidate(LazyCallGraph::SCC *) { return false; }
private:
const ModuleAnalysisManager *MAM;
};
static void *ID() { return (void *)&PassID; }
ModuleAnalysisManagerCGSCCProxy(const ModuleAnalysisManager &MAM)
: MAM(&MAM) {}
// We have to explicitly define all the special member functions because MSVC
// refuses to generate them.
ModuleAnalysisManagerCGSCCProxy(
const ModuleAnalysisManagerCGSCCProxy &Arg)
: MAM(Arg.MAM) {}
ModuleAnalysisManagerCGSCCProxy(ModuleAnalysisManagerCGSCCProxy &&Arg)
: MAM(std::move(Arg.MAM)) {}
ModuleAnalysisManagerCGSCCProxy &
operator=(ModuleAnalysisManagerCGSCCProxy RHS) {
std::swap(MAM, RHS.MAM);
return *this;
}
/// \brief Run the analysis pass and create our proxy result object.
/// Nothing to see here, it just forwards the \c MAM reference into the
/// result.
Result run(LazyCallGraph::SCC *) { return Result(*MAM); }
private:
static char PassID;
const ModuleAnalysisManager *MAM;
};
/// \brief The core module pass which does a post-order walk of the SCCs and
/// runs a CGSCC pass over each one.
///
/// Designed to allow composition of a CGSCCPass(Manager) and
/// a ModulePassManager. Note that this pass must be run with a module analysis
/// manager as it uses the LazyCallGraph analysis. It will also run the
/// \c CGSCCAnalysisManagerModuleProxy analysis prior to running the CGSCC
/// pass over the module to enable a \c FunctionAnalysisManager to be used
/// within this run safely.
template <typename CGSCCPassT> class ModuleToPostOrderCGSCCPassAdaptor {
public:
explicit ModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass)
: Pass(std::move(Pass)) {}
// We have to explicitly define all the special member functions because MSVC
// refuses to generate them.
ModuleToPostOrderCGSCCPassAdaptor(
const ModuleToPostOrderCGSCCPassAdaptor &Arg)
: Pass(Arg.Pass) {}
ModuleToPostOrderCGSCCPassAdaptor(ModuleToPostOrderCGSCCPassAdaptor &&Arg)
: Pass(std::move(Arg.Pass)) {}
friend void swap(ModuleToPostOrderCGSCCPassAdaptor &LHS,
ModuleToPostOrderCGSCCPassAdaptor &RHS) {
using std::swap;
swap(LHS.Pass, RHS.Pass);
}
ModuleToPostOrderCGSCCPassAdaptor &
operator=(ModuleToPostOrderCGSCCPassAdaptor RHS) {
swap(*this, RHS);
return *this;
}
/// \brief Runs the CGSCC pass across every SCC in the module.
PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM) {
assert(AM && "We need analyses to compute the call graph!");
// Setup the CGSCC analysis manager from its proxy.
CGSCCAnalysisManager &CGAM =
AM->getResult<CGSCCAnalysisManagerModuleProxy>(M).getManager();
// Get the call graph for this module.
LazyCallGraph &CG = AM->getResult<LazyCallGraphAnalysis>(M);
PreservedAnalyses PA = PreservedAnalyses::all();
for (LazyCallGraph::SCC &C : CG.postorder_sccs()) {
PreservedAnalyses PassPA = Pass.run(&C, &CGAM);
// We know that the CGSCC pass couldn't have invalidated any other
// SCC's analyses (that's the contract of a CGSCC pass), so
// directly handle the CGSCC analysis manager's invalidation here.
// FIXME: This isn't quite correct. We need to handle the case where the
// pass updated the CG, particularly some child of the current SCC, and
// invalidate its analyses.
CGAM.invalidate(&C, PassPA);
// Then intersect the preserved set so that invalidation of module
// analyses will eventually occur when the module pass completes.
PA.intersect(std::move(PassPA));
}
// By definition we preserve the proxy. This precludes *any* invalidation
// of CGSCC analyses by the proxy, but that's OK because we've taken
// care to invalidate analyses in the CGSCC analysis manager
// incrementally above.
PA.preserve<CGSCCAnalysisManagerModuleProxy>();
return PA;
}
static StringRef name() { return "ModuleToPostOrderCGSCCPassAdaptor"; }
private:
CGSCCPassT Pass;
};
/// \brief A function to deduce a function pass type and wrap it in the
/// templated adaptor.
template <typename CGSCCPassT>
ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>
createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass) {
return std::move(
ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>(std::move(Pass)));
}
/// \brief A CGSCC analysis which acts as a proxy for a function analysis
/// manager.
///
/// This primarily proxies invalidation information from the CGSCC analysis
/// manager and CGSCC pass manager to a function analysis manager. You should
/// never use a function analysis manager from within (transitively) a CGSCC
/// pass manager unless your parent CGSCC pass has received a proxy result
/// object for it.
class FunctionAnalysisManagerCGSCCProxy {
public:
class Result {
public:
explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {}
// We have to explicitly define all the special member functions because
// MSVC refuses to generate them.
Result(const Result &Arg) : FAM(Arg.FAM) {}
Result(Result &&Arg) : FAM(std::move(Arg.FAM)) {}
Result &operator=(Result RHS) {
std::swap(FAM, RHS.FAM);
return *this;
}
~Result();
/// \brief Accessor for the \c FunctionAnalysisManager.
FunctionAnalysisManager &getManager() { return *FAM; }
/// \brief Handler for invalidation of the SCC.
///
/// If this analysis itself is preserved, then we assume that the set of \c
/// Function objects in the \c SCC hasn't changed and thus we don't need
/// to invalidate *all* cached data associated with a \c Function* in the \c
/// FunctionAnalysisManager.
///
/// Regardless of whether this analysis is marked as preserved, all of the
/// analyses in the \c FunctionAnalysisManager are potentially invalidated
/// based on the set of preserved analyses.
bool invalidate(LazyCallGraph::SCC *C, const PreservedAnalyses &PA);
private:
FunctionAnalysisManager *FAM;
};
static void *ID() { return (void *)&PassID; }
explicit FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManager &FAM)
: FAM(&FAM) {}
// We have to explicitly define all the special member functions because MSVC
// refuses to generate them.
FunctionAnalysisManagerCGSCCProxy(
const FunctionAnalysisManagerCGSCCProxy &Arg)
: FAM(Arg.FAM) {}
FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManagerCGSCCProxy &&Arg)
: FAM(std::move(Arg.FAM)) {}
FunctionAnalysisManagerCGSCCProxy &
operator=(FunctionAnalysisManagerCGSCCProxy RHS) {
std::swap(FAM, RHS.FAM);
return *this;
}
/// \brief Run the analysis pass and create our proxy result object.
///
/// This doesn't do any interesting work, it is primarily used to insert our
/// proxy result object into the module analysis cache so that we can proxy
/// invalidation to the function analysis manager.
///
/// In debug builds, it will also assert that the analysis manager is empty
/// as no queries should arrive at the function analysis manager prior to
/// this analysis being requested.
Result run(LazyCallGraph::SCC *C);
private:
static char PassID;
FunctionAnalysisManager *FAM;
};
/// \brief A function analysis which acts as a proxy for a CGSCC analysis
/// manager.
///
/// This primarily provides an accessor to a parent CGSCC analysis manager to
/// function passes. Only the const interface of the CGSCC analysis manager is
/// provided to indicate that once inside of a function analysis pass you
/// cannot request a CGSCC analysis to actually run. Instead, the user must
/// rely on the \c getCachedResult API.
///
/// This proxy *doesn't* manage the invalidation in any way. That is handled by
/// the recursive return path of each layer of the pass manager and the
/// returned PreservedAnalysis set.
class CGSCCAnalysisManagerFunctionProxy {
public:
/// \brief Result proxy object for \c ModuleAnalysisManagerFunctionProxy.
class Result {
public:
explicit Result(const CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {}
// We have to explicitly define all the special member functions because
// MSVC refuses to generate them.
Result(const Result &Arg) : CGAM(Arg.CGAM) {}
Result(Result &&Arg) : CGAM(std::move(Arg.CGAM)) {}
Result &operator=(Result RHS) {
std::swap(CGAM, RHS.CGAM);
return *this;
}
const CGSCCAnalysisManager &getManager() const { return *CGAM; }
/// \brief Handle invalidation by ignoring it, this pass is immutable.
bool invalidate(Function *) { return false; }
private:
const CGSCCAnalysisManager *CGAM;
};
static void *ID() { return (void *)&PassID; }
CGSCCAnalysisManagerFunctionProxy(const CGSCCAnalysisManager &CGAM)
: CGAM(&CGAM) {}
// We have to explicitly define all the special member functions because MSVC
// refuses to generate them.
CGSCCAnalysisManagerFunctionProxy(
const CGSCCAnalysisManagerFunctionProxy &Arg)
: CGAM(Arg.CGAM) {}
CGSCCAnalysisManagerFunctionProxy(CGSCCAnalysisManagerFunctionProxy &&Arg)
: CGAM(std::move(Arg.CGAM)) {}
CGSCCAnalysisManagerFunctionProxy &
operator=(CGSCCAnalysisManagerFunctionProxy RHS) {
std::swap(CGAM, RHS.CGAM);
return *this;
}
/// \brief Run the analysis pass and create our proxy result object.
/// Nothing to see here, it just forwards the \c CGAM reference into the
/// result.
Result run(Function *) { return Result(*CGAM); }
private:
static char PassID;
const CGSCCAnalysisManager *CGAM;
};
/// \brief Adaptor that maps from a SCC to its functions.
///
/// Designed to allow composition of a FunctionPass(Manager) and
/// a CGSCCPassManager. Note that if this pass is constructed with a pointer
/// to a \c CGSCCAnalysisManager it will run the
/// \c FunctionAnalysisManagerCGSCCProxy analysis prior to running the function
/// pass over the SCC to enable a \c FunctionAnalysisManager to be used
/// within this run safely.
template <typename FunctionPassT> class CGSCCToFunctionPassAdaptor {
public:
explicit CGSCCToFunctionPassAdaptor(FunctionPassT Pass)
: Pass(std::move(Pass)) {}
// We have to explicitly define all the special member functions because MSVC
// refuses to generate them.
CGSCCToFunctionPassAdaptor(const CGSCCToFunctionPassAdaptor &Arg)
: Pass(Arg.Pass) {}
CGSCCToFunctionPassAdaptor(CGSCCToFunctionPassAdaptor &&Arg)
: Pass(std::move(Arg.Pass)) {}
friend void swap(CGSCCToFunctionPassAdaptor &LHS, CGSCCToFunctionPassAdaptor &RHS) {
using std::swap;
swap(LHS.Pass, RHS.Pass);
}
CGSCCToFunctionPassAdaptor &operator=(CGSCCToFunctionPassAdaptor RHS) {
swap(*this, RHS);
return *this;
}
/// \brief Runs the function pass across every function in the module.
PreservedAnalyses run(LazyCallGraph::SCC *C, CGSCCAnalysisManager *AM) {
FunctionAnalysisManager *FAM = nullptr;
if (AM)
// Setup the function analysis manager from its proxy.
FAM = &AM->getResult<FunctionAnalysisManagerCGSCCProxy>(C).getManager();
PreservedAnalyses PA = PreservedAnalyses::all();
for (LazyCallGraph::Node *N : *C) {
PreservedAnalyses PassPA = Pass.run(&N->getFunction(), FAM);
// We know that the function pass couldn't have invalidated any other
// function's analyses (that's the contract of a function pass), so
// directly handle the function analysis manager's invalidation here.
if (FAM)
FAM->invalidate(&N->getFunction(), PassPA);
// Then intersect the preserved set so that invalidation of module
// analyses will eventually occur when the module pass completes.
PA.intersect(std::move(PassPA));
}
// By definition we preserve the proxy. This precludes *any* invalidation
// of function analyses by the proxy, but that's OK because we've taken
// care to invalidate analyses in the function analysis manager
// incrementally above.
// FIXME: We need to update the call graph here to account for any deleted
// edges!
PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
return PA;
}
static StringRef name() { return "CGSCCToFunctionPassAdaptor"; }
private:
FunctionPassT Pass;
};
/// \brief A function to deduce a function pass type and wrap it in the
/// templated adaptor.
template <typename FunctionPassT>
CGSCCToFunctionPassAdaptor<FunctionPassT>
createCGSCCToFunctionPassAdaptor(FunctionPassT Pass) {
return std::move(CGSCCToFunctionPassAdaptor<FunctionPassT>(std::move(Pass)));
}
}
#endif

View File

@ -6,46 +6,47 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This interface is used to build and manipulate a call graph, which is a very
// useful tool for interprocedural optimization.
//
// Every function in a module is represented as a node in the call graph. The
// callgraph node keeps track of which functions the are called by the function
// corresponding to the node.
//
// A call graph may contain nodes where the function that they correspond to is
// null. These 'external' nodes are used to represent control flow that is not
// represented (or analyzable) in the module. In particular, this analysis
// builds one external node such that:
// 1. All functions in the module without internal linkage will have edges
// from this external node, indicating that they could be called by
// functions outside of the module.
// 2. All functions whose address is used for something more than a direct
// call, for example being stored into a memory location will also have an
// edge from this external node. Since they may be called by an unknown
// caller later, they must be tracked as such.
//
// There is a second external node added for calls that leave this module.
// Functions have a call edge to the external node iff:
// 1. The function is external, reflecting the fact that they could call
// anything without internal linkage or that has its address taken.
// 2. The function contains an indirect function call.
//
// As an extension in the future, there may be multiple nodes with a null
// function. These will be used when we can prove (through pointer analysis)
// that an indirect call site can call only a specific set of functions.
//
// Because of these properties, the CallGraph captures a conservative superset
// of all of the caller-callee relationships, which is useful for
// transformations.
//
// The CallGraph class also attempts to figure out what the root of the
// CallGraph is, which it currently does by looking for a function named 'main'.
// If no function named 'main' is found, the external node is used as the entry
// node, reflecting the fact that any function without internal linkage could
// be called into (which is common for libraries).
//
/// \file
///
/// This file provides interfaces used to build and manipulate a call graph,
/// which is a very useful tool for interprocedural optimization.
///
/// Every function in a module is represented as a node in the call graph. The
/// callgraph node keeps track of which functions are called by the function
/// corresponding to the node.
///
/// A call graph may contain nodes where the function that they correspond to
/// is null. These 'external' nodes are used to represent control flow that is
/// not represented (or analyzable) in the module. In particular, this
/// analysis builds one external node such that:
/// 1. All functions in the module without internal linkage will have edges
/// from this external node, indicating that they could be called by
/// functions outside of the module.
/// 2. All functions whose address is used for something more than a direct
/// call, for example being stored into a memory location will also have
/// an edge from this external node. Since they may be called by an
/// unknown caller later, they must be tracked as such.
///
/// There is a second external node added for calls that leave this module.
/// Functions have a call edge to the external node iff:
/// 1. The function is external, reflecting the fact that they could call
/// anything without internal linkage or that has its address taken.
/// 2. The function contains an indirect function call.
///
/// As an extension in the future, there may be multiple nodes with a null
/// function. These will be used when we can prove (through pointer analysis)
/// that an indirect call site can call only a specific set of functions.
///
/// Because of these properties, the CallGraph captures a conservative superset
/// of all of the caller-callee relationships, which is useful for
/// transformations.
///
/// The CallGraph class also attempts to figure out what the root of the
/// CallGraph is, which it currently does by looking for a function named
/// 'main'. If no function named 'main' is found, the external node is used as
/// the entry node, reflecting the fact that any function without internal
/// linkage could be called into (which is common for libraries).
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_CALLGRAPH_H
@ -53,11 +54,11 @@
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Pass.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Support/IncludeFile.h"
#include "llvm/Support/ValueHandle.h"
#include <map>
namespace llvm {
@ -66,171 +67,142 @@ class Function;
class Module;
class CallGraphNode;
//===----------------------------------------------------------------------===//
// CallGraph class definition
//
class CallGraph : public ModulePass {
Module *Mod; // The module this call graph represents
/// \brief The basic data container for the call graph of a \c Module of IR.
///
/// This class exposes both the interface to the call graph for a module of IR.
///
/// The core call graph itself can also be updated to reflect changes to the IR.
class CallGraph {
Module &M;
typedef std::map<const Function *, CallGraphNode *> FunctionMapTy;
FunctionMapTy FunctionMap; // Map from a function to its node
// Root is root of the call graph, or the external node if a 'main' function
// couldn't be found.
//
/// \brief A map from \c Function* to \c CallGraphNode*.
FunctionMapTy FunctionMap;
/// \brief Root is root of the call graph, or the external node if a 'main'
/// function couldn't be found.
CallGraphNode *Root;
// ExternalCallingNode - This node has edges to all external functions and
// those internal functions that have their address taken.
/// \brief This node has edges to all external functions and those internal
/// functions that have their address taken.
CallGraphNode *ExternalCallingNode;
// CallsExternalNode - This node has edges to it from all functions making
// indirect calls or calling an external function.
/// \brief This node has edges to it from all functions making indirect calls
/// or calling an external function.
CallGraphNode *CallsExternalNode;
/// Replace the function represented by this node by another.
/// \brief 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);
// Add a function to the call graph, and link the node to all of the functions
// that it calls.
/// \brief Add a function to the call graph, and link the node to all of the
/// functions that it calls.
void addToCallGraph(Function *F);
public:
static char ID; // Class identification, replacement for typeinfo
//===---------------------------------------------------------------------
// Accessors.
//
CallGraph(Module &M);
~CallGraph();
void print(raw_ostream &OS) const;
void dump() const;
typedef FunctionMapTy::iterator iterator;
typedef FunctionMapTy::const_iterator const_iterator;
/// getModule - Return the module the call graph corresponds to.
///
Module &getModule() const { return *Mod; }
/// \brief Returns the module the call graph corresponds to.
Module &getModule() const { return M; }
inline iterator begin() { return FunctionMap.begin(); }
inline iterator end() { return FunctionMap.end(); }
inline iterator begin() { return FunctionMap.begin(); }
inline iterator end() { return FunctionMap.end(); }
inline const_iterator begin() const { return FunctionMap.begin(); }
inline const_iterator end() const { return FunctionMap.end(); }
inline const_iterator end() const { return FunctionMap.end(); }
// Subscripting operators, return the call graph node for the provided
// function
/// \brief Returns the call graph node for the provided function.
inline const CallGraphNode *operator[](const Function *F) const {
const_iterator I = FunctionMap.find(F);
assert(I != FunctionMap.end() && "Function not in callgraph!");
return I->second;
}
/// \brief Returns the call graph node for the provided function.
inline CallGraphNode *operator[](const Function *F) {
const_iterator I = FunctionMap.find(F);
assert(I != FunctionMap.end() && "Function not in callgraph!");
return I->second;
}
/// Returns the CallGraphNode which is used to represent undetermined calls
/// into the callgraph.
/// \brief Returns the \c CallGraphNode which is used to represent
/// undetermined calls into the callgraph.
CallGraphNode *getExternalCallingNode() const { return ExternalCallingNode; }
CallGraphNode *getCallsExternalNode() const { return CallsExternalNode; }
/// Return the root/main method in the module, or some other root node, such
/// as the externalcallingnode.
CallGraphNode *getRoot() { return Root; }
const CallGraphNode *getRoot() const { return Root; }
CallGraphNode *getCallsExternalNode() const { return CallsExternalNode; }
//===---------------------------------------------------------------------
// Functions to keep a call graph up to date with a function that has been
// modified.
//
/// removeFunctionFromModule - Unlink the function from this module, returning
/// it. Because this removes the function from the module, the call graph
/// node is destroyed. This is only valid if the function does not call any
/// other functions (ie, there are no edges in it's CGN). The easiest way to
/// do this is to dropAllReferences before calling this.
/// \brief Unlink the function from this module, returning it.
///
/// Because this removes the function from the module, the call graph node is
/// destroyed. This is only valid if the function does not call any other
/// functions (ie, there are no edges in it's CGN). The easiest way to do
/// this is to dropAllReferences before calling this.
Function *removeFunctionFromModule(CallGraphNode *CGN);
/// getOrInsertFunction - This method is identical to calling operator[], but
/// it will insert a new CallGraphNode for the specified function if one does
/// not already exist.
/// \brief Similar to operator[], but this will insert a new CallGraphNode for
/// \c F if one does not already exist.
CallGraphNode *getOrInsertFunction(const Function *F);
CallGraph();
virtual ~CallGraph() { releaseMemory(); }
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
virtual bool runOnModule(Module &M);
virtual void releaseMemory();
void print(raw_ostream &o, const Module *) const;
void dump() const;
};
//===----------------------------------------------------------------------===//
// CallGraphNode class definition.
//
/// \brief A node in the call graph for a module.
///
/// Typically represents a function in the call graph. There are also special
/// "null" nodes used to represent theoretical entries in the call graph.
class CallGraphNode {
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:
typedef std::pair<WeakVH, CallGraphNode*> CallRecord;
private:
std::vector<CallRecord> CalledFunctions;
/// NumReferences - This is the number of times that this CallGraphNode occurs
/// in the CalledFunctions array of this or other CallGraphNodes.
unsigned NumReferences;
/// \brief A pair of the calling instruction (a call or invoke)
/// and the call graph node being called.
typedef std::pair<WeakVH, CallGraphNode *> CallRecord;
CallGraphNode(const CallGraphNode &) LLVM_DELETED_FUNCTION;
void operator=(const CallGraphNode &) LLVM_DELETED_FUNCTION;
void DropRef() { --NumReferences; }
void AddRef() { ++NumReferences; }
public:
typedef std::vector<CallRecord> CalledFunctionsVector;
// CallGraphNode ctor - Create a node for the specified function.
inline CallGraphNode(Function *f) : F(f), NumReferences(0) {}
/// \brief Creates a node for the specified function.
inline CallGraphNode(Function *F) : F(F), NumReferences(0) {}
~CallGraphNode() {
assert(NumReferences == 0 && "Node deleted while references remain");
}
//===---------------------------------------------------------------------
// Accessor methods.
//
typedef std::vector<CallRecord>::iterator iterator;
typedef std::vector<CallRecord>::const_iterator const_iterator;
// getFunction - Return the function that this call graph node represents.
/// \brief Returns the function that this call graph node represents.
Function *getFunction() const { return F; }
inline iterator begin() { return CalledFunctions.begin(); }
inline iterator end() { return CalledFunctions.end(); }
inline iterator end() { return CalledFunctions.end(); }
inline const_iterator begin() const { return CalledFunctions.begin(); }
inline const_iterator end() const { return CalledFunctions.end(); }
inline const_iterator end() const { return CalledFunctions.end(); }
inline bool empty() const { return CalledFunctions.empty(); }
inline unsigned size() const { return (unsigned)CalledFunctions.size(); }
/// getNumReferences - Return the number of other CallGraphNodes in this
/// CallGraph that reference this node in their callee list.
/// \brief Returns the number of other CallGraphNodes in this CallGraph that
/// reference this node in their callee list.
unsigned getNumReferences() const { return NumReferences; }
// Subscripting operator - Return the i'th called function.
//
/// \brief Returns the i'th called function.
CallGraphNode *operator[](unsigned i) const {
assert(i < CalledFunctions.size() && "Invalid index");
return CalledFunctions[i].second;
}
/// dump - Print out this call graph node.
///
/// \brief Print out this call graph node.
void dump() const;
void print(raw_ostream &OS) const;
@ -239,29 +211,25 @@ class CallGraphNode {
// modified
//
/// removeAllCalledFunctions - As the name implies, this removes all edges
/// from this CallGraphNode to any functions it calls.
/// \brief Removes all edges from this CallGraphNode to any functions it
/// calls.
void removeAllCalledFunctions() {
while (!CalledFunctions.empty()) {
CalledFunctions.back().second->DropRef();
CalledFunctions.pop_back();
}
}
/// stealCalledFunctionsFrom - Move all the callee information from N to this
/// node.
/// \brief Moves all the callee information from N to this node.
void stealCalledFunctionsFrom(CallGraphNode *N) {
assert(CalledFunctions.empty() &&
"Cannot steal callsite information if I already have some");
std::swap(CalledFunctions, N->CalledFunctions);
}
/// addCalledFunction - Add a function to the list of functions called by this
/// one.
/// \brief Adds a function to the list of functions called by this one.
void addCalledFunction(CallSite CS, CallGraphNode *M) {
assert(!CS.getInstruction() ||
!CS.getCalledFunction() ||
assert(!CS.getInstruction() || !CS.getCalledFunction() ||
!CS.getCalledFunction()->isIntrinsic());
CalledFunctions.push_back(std::make_pair(CS.getInstruction(), M));
M->AddRef();
@ -272,32 +240,152 @@ class CallGraphNode {
*I = CalledFunctions.back();
CalledFunctions.pop_back();
}
/// removeCallEdgeFor - This method removes the edge in the node for the
/// specified call site. Note that this method takes linear time, so it
/// should be used sparingly.
/// \brief Removes the edge in the node for the specified call site.
///
/// Note that this method takes linear time, so it should be used sparingly.
void removeCallEdgeFor(CallSite CS);
/// removeAnyCallEdgeTo - This method removes all call edges from this node
/// to the specified callee function. This takes more time to execute than
/// removeCallEdgeTo, so it should not be used unless necessary.
/// \brief Removes all call edges from this node to the specified callee
/// function.
///
/// This takes more time to execute than removeCallEdgeTo, so it should not
/// be used unless necessary.
void removeAnyCallEdgeTo(CallGraphNode *Callee);
/// removeOneAbstractEdgeTo - Remove one edge associated with a null callsite
/// from this node to the specified callee function.
/// \brief Removes one edge associated with a null callsite from this node to
/// the specified callee function.
void removeOneAbstractEdgeTo(CallGraphNode *Callee);
/// replaceCallEdge - This method replaces the edge in the node for the
/// specified call site with a new one. Note that this method takes linear
/// time, so it should be used sparingly.
/// \brief Replaces the edge in the node for the specified call site with a
/// new one.
///
/// Note that this method takes linear time, so it should be used sparingly.
void replaceCallEdge(CallSite CS, CallSite NewCS, CallGraphNode *NewNode);
/// allReferencesDropped - This is a special function that should only be
/// used by the CallGraph class.
void allReferencesDropped() {
NumReferences = 0;
private:
friend class CallGraph;
AssertingVH<Function> F;
std::vector<CallRecord> CalledFunctions;
/// \brief The number of times that this CallGraphNode occurs in the
/// CalledFunctions array of this or other CallGraphNodes.
unsigned NumReferences;
CallGraphNode(const CallGraphNode &) LLVM_DELETED_FUNCTION;
void operator=(const CallGraphNode &) LLVM_DELETED_FUNCTION;
void DropRef() { --NumReferences; }
void AddRef() { ++NumReferences; }
/// \brief A special function that should only be used by the CallGraph class.
void allReferencesDropped() { NumReferences = 0; }
};
/// \brief An analysis pass to compute the \c CallGraph for a \c Module.
///
/// This class implements the concept of an analysis pass used by the \c
/// ModuleAnalysisManager to run an analysis over a module and cache the
/// resulting data.
class CallGraphAnalysis {
public:
/// \brief A formulaic typedef to inform clients of the result type.
typedef CallGraph Result;
static void *ID() { return (void *)&PassID; }
/// \brief Compute the \c CallGraph for the module \c M.
///
/// The real work here is done in the \c CallGraph constructor.
CallGraph run(Module *M) { return CallGraph(*M); }
private:
static char PassID;
};
/// \brief The \c ModulePass which wraps up a \c CallGraph and the logic to
/// build it.
///
/// This class exposes both the interface to the call graph container and the
/// module pass which runs over a module of IR and produces the call graph. The
/// call graph interface is entirelly a wrapper around a \c CallGraph object
/// which is stored internally for each module.
class CallGraphWrapperPass : public ModulePass {
std::unique_ptr<CallGraph> G;
public:
static char ID; // Class identification, replacement for typeinfo
CallGraphWrapperPass();
virtual ~CallGraphWrapperPass();
/// \brief The internal \c CallGraph around which the rest of this interface
/// is wrapped.
const CallGraph &getCallGraph() const { return *G; }
CallGraph &getCallGraph() { return *G; }
typedef CallGraph::iterator iterator;
typedef CallGraph::const_iterator const_iterator;
/// \brief Returns the module the call graph corresponds to.
Module &getModule() const { return G->getModule(); }
inline iterator begin() { return G->begin(); }
inline iterator end() { return G->end(); }
inline const_iterator begin() const { return G->begin(); }
inline const_iterator end() const { return G->end(); }
/// \brief Returns the call graph node for the provided function.
inline const CallGraphNode *operator[](const Function *F) const {
return (*G)[F];
}
/// \brief Returns the call graph node for the provided function.
inline CallGraphNode *operator[](const Function *F) { return (*G)[F]; }
/// \brief Returns the \c CallGraphNode which is used to represent
/// undetermined calls into the callgraph.
CallGraphNode *getExternalCallingNode() const {
return G->getExternalCallingNode();
}
CallGraphNode *getCallsExternalNode() const {
return G->getCallsExternalNode();
}
//===---------------------------------------------------------------------
// Functions to keep a call graph up to date with a function that has been
// modified.
//
/// \brief Unlink the function from this module, returning it.
///
/// Because this removes the function from the module, the call graph node is
/// destroyed. This is only valid if the function does not call any other
/// functions (ie, there are no edges in it's CGN). The easiest way to do
/// this is to dropAllReferences before calling this.
Function *removeFunctionFromModule(CallGraphNode *CGN) {
return G->removeFunctionFromModule(CGN);
}
/// \brief Similar to operator[], but this will insert a new CallGraphNode for
/// \c F if one does not already exist.
CallGraphNode *getOrInsertFunction(const Function *F) {
return G->getOrInsertFunction(F);
}
//===---------------------------------------------------------------------
// Implementation of the ModulePass interface needed here.
//
void getAnalysisUsage(AnalysisUsage &AU) const override;
bool runOnModule(Module &M) override;
void releaseMemory() override;
void print(raw_ostream &o, const Module *) const override;
void dump() const;
};
//===----------------------------------------------------------------------===//
@ -307,11 +395,12 @@ class CallGraphNode {
// Provide graph traits for tranversing call graphs using standard graph
// traversals.
template <> struct GraphTraits<CallGraphNode*> {
template <> struct GraphTraits<CallGraphNode *> {
typedef CallGraphNode NodeType;
typedef CallGraphNode::CallRecord CGNPairTy;
typedef std::pointer_to_unary_function<CGNPairTy, CallGraphNode*> CGNDerefFun;
typedef std::pointer_to_unary_function<CGNPairTy, CallGraphNode *>
CGNDerefFun;
static NodeType *getEntryNode(CallGraphNode *CGN) { return CGN; }
@ -320,55 +409,54 @@ template <> struct GraphTraits<CallGraphNode*> {
static inline ChildIteratorType child_begin(NodeType *N) {
return map_iterator(N->begin(), CGNDerefFun(CGNDeref));
}
static inline ChildIteratorType child_end (NodeType *N) {
static inline ChildIteratorType child_end(NodeType *N) {
return map_iterator(N->end(), CGNDerefFun(CGNDeref));
}
static CallGraphNode *CGNDeref(CGNPairTy P) {
return P.second;
}
static CallGraphNode *CGNDeref(CGNPairTy P) { return P.second; }
};
template <> struct GraphTraits<const CallGraphNode*> {
template <> struct GraphTraits<const CallGraphNode *> {
typedef const CallGraphNode NodeType;
typedef NodeType::const_iterator ChildIteratorType;
static NodeType *getEntryNode(const CallGraphNode *CGN) { return CGN; }
static inline ChildIteratorType child_begin(NodeType *N) { return N->begin();}
static inline ChildIteratorType child_end (NodeType *N) { return N->end(); }
static inline ChildIteratorType child_begin(NodeType *N) {
return N->begin();
}
static inline ChildIteratorType child_end(NodeType *N) { return N->end(); }
};
template<> struct GraphTraits<CallGraph*> : public GraphTraits<CallGraphNode*> {
template <>
struct GraphTraits<CallGraph *> : public GraphTraits<CallGraphNode *> {
static NodeType *getEntryNode(CallGraph *CGN) {
return CGN->getExternalCallingNode(); // Start at the external node!
return CGN->getExternalCallingNode(); // Start at the external node!
}
typedef std::pair<const Function*, CallGraphNode*> PairTy;
typedef std::pointer_to_unary_function<PairTy, CallGraphNode&> DerefFun;
typedef std::pair<const Function *, CallGraphNode *> PairTy;
typedef std::pointer_to_unary_function<PairTy, CallGraphNode &> DerefFun;
// nodes_iterator/begin/end - Allow iteration over all nodes in the graph
typedef mapped_iterator<CallGraph::iterator, DerefFun> nodes_iterator;
static nodes_iterator nodes_begin(CallGraph *CG) {
return map_iterator(CG->begin(), DerefFun(CGdereference));
}
static nodes_iterator nodes_end (CallGraph *CG) {
static nodes_iterator nodes_end(CallGraph *CG) {
return map_iterator(CG->end(), DerefFun(CGdereference));
}
static CallGraphNode &CGdereference(PairTy P) {
return *P.second;
}
static CallGraphNode &CGdereference(PairTy P) { return *P.second; }
};
template<> struct GraphTraits<const CallGraph*> :
public GraphTraits<const CallGraphNode*> {
template <>
struct GraphTraits<const CallGraph *> : public GraphTraits<
const CallGraphNode *> {
static NodeType *getEntryNode(const CallGraph *CGN) {
return CGN->getExternalCallingNode();
}
// nodes_iterator/begin/end - Allow iteration over all nodes in the graph
typedef CallGraph::const_iterator nodes_iterator;
static nodes_iterator nodes_begin(const CallGraph *CG) { return CG->begin(); }
static nodes_iterator nodes_end (const CallGraph *CG) { return CG->end(); }
static nodes_iterator nodes_end(const CallGraph *CG) { return CG->end(); }
};
} // End llvm namespace

View File

@ -37,7 +37,8 @@ class CallGraphSCCPass : public Pass {
/// createPrinterPass - Get a pass that prints the Module
/// corresponding to a CallGraph.
Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const;
Pass *createPrinterPass(raw_ostream &O,
const std::string &Banner) const override;
using llvm::Pass::doInitialization;
using llvm::Pass::doFinalization;
@ -65,18 +66,17 @@ class CallGraphSCCPass : public Pass {
}
/// Assign pass manager to manager this pass
virtual void assignPassManager(PMStack &PMS,
PassManagerType PMT);
void assignPassManager(PMStack &PMS, PassManagerType PMT) override;
/// Return what kind of Pass Manager can manage this pass.
virtual PassManagerType getPotentialPassManagerType() const {
PassManagerType getPotentialPassManagerType() const override {
return PMT_CallGraphPassManager;
}
/// getAnalysisUsage - For this class, we declare that we require and preserve
/// the call graph. If the derived class implements this method, it should
/// always explicitly call the implementation here.
virtual void getAnalysisUsage(AnalysisUsage &Info) const;
void getAnalysisUsage(AnalysisUsage &Info) const override;
};
/// CallGraphSCC - This is a single SCC that a CallGraphSCCPass is run on.

View File

@ -18,6 +18,8 @@ namespace llvm {
class Value;
class Use;
class Instruction;
class DominatorTree;
/// PointerMayBeCaptured - Return true if this pointer value may be captured
/// by the enclosing function (which is required to exist). This routine can
@ -30,6 +32,20 @@ namespace llvm {
bool ReturnCaptures,
bool StoreCaptures);
/// PointerMayBeCapturedBefore - Return true if this pointer value may be
/// captured by the enclosing function (which is required to exist). If a
/// DominatorTree is provided, only captures which happen before the given
/// instruction are considered. This routine can be expensive, so consider
/// caching the results. The boolean ReturnCaptures specifies whether
/// returning the value (or part of it) from the function counts as capturing
/// it or not. The boolean StoreCaptures specified whether storing the value
/// (or part of it) into memory anywhere automatically counts as capturing it
/// or not. Captures by the provided instruction are considered if the
/// final parameter is true.
bool PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures,
bool StoreCaptures, const Instruction *I,
DominatorTree *DT, bool IncludeI = false);
/// This callback is used in conjunction with PointerMayBeCaptured. In
/// addition to the interface here, you'll need to provide your own getters
/// to see whether anything was captured.
@ -45,12 +61,12 @@ namespace llvm {
/// capture) return false. To search it, return true.
///
/// U->getUser() is always an Instruction.
virtual bool shouldExplore(Use *U);
virtual bool shouldExplore(const Use *U);
/// captured - Information about the pointer was captured by the user of
/// use U. Return true to stop the traversal or false to continue looking
/// for more capturing instructions.
virtual bool captured(Use *U) = 0;
virtual bool captured(const Use *U) = 0;
};
/// PointerMayBeCaptured - Visit the value and the values derived from it and

View File

@ -16,7 +16,7 @@
#define LLVM_ANALYSIS_CODEMETRICS_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/CallSite.h"
#include "llvm/IR/CallSite.h"
namespace llvm {
class BasicBlock;

View File

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

View File

@ -16,7 +16,7 @@
#ifndef LLVM_ANALYSIS_CONSTANTSSCANNER_H
#define LLVM_ANALYSIS_CONSTANTSSCANNER_H
#include "llvm/Support/InstIterator.h"
#include "llvm/IR/InstIterator.h"
namespace llvm {

View File

@ -16,53 +16,66 @@
#include "llvm/Analysis/CFGPrinter.h"
#include "llvm/Pass.h"
#include "llvm/Support/FileSystem.h"
namespace llvm {
template <class Analysis, bool Simple>
/// \brief Default traits class for extracting a graph from an analysis pass.
///
/// This assumes that 'GraphT' is 'AnalysisT *' and so just passes it through.
template <typename AnalysisT, typename GraphT = AnalysisT *>
struct DefaultAnalysisGraphTraits {
static GraphT getGraph(AnalysisT *A) { return A; }
};
template <
typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT> >
class DOTGraphTraitsViewer : public FunctionPass {
public:
DOTGraphTraitsViewer(StringRef GraphName, char &ID)
: FunctionPass(ID), Name(GraphName) {}
: FunctionPass(ID), Name(GraphName) {}
virtual bool runOnFunction(Function &F) {
Analysis *Graph = &getAnalysis<Analysis>();
std::string GraphName = DOTGraphTraits<Analysis*>::getGraphName(Graph);
bool runOnFunction(Function &F) override {
GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>());
std::string GraphName = DOTGraphTraits<GraphT>::getGraphName(Graph);
std::string Title = GraphName + " for '" + F.getName().str() + "' function";
ViewGraph(Graph, Name, Simple, Title);
ViewGraph(Graph, Name, IsSimple, Title);
return false;
}
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
AU.addRequired<Analysis>();
AU.addRequired<AnalysisT>();
}
private:
std::string Name;
};
template <class Analysis, bool Simple>
template <
typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT> >
class DOTGraphTraitsPrinter : public FunctionPass {
public:
DOTGraphTraitsPrinter(StringRef GraphName, char &ID)
: FunctionPass(ID), Name(GraphName) {}
: FunctionPass(ID), Name(GraphName) {}
virtual bool runOnFunction(Function &F) {
Analysis *Graph = &getAnalysis<Analysis>();
bool runOnFunction(Function &F) override {
GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>());
std::string Filename = Name + "." + F.getName().str() + ".dot";
std::string ErrorInfo;
errs() << "Writing '" << Filename << "'...";
raw_fd_ostream File(Filename.c_str(), ErrorInfo);
std::string GraphName = DOTGraphTraits<Analysis*>::getGraphName(Graph);
raw_fd_ostream File(Filename.c_str(), ErrorInfo, sys::fs::F_Text);
std::string GraphName = DOTGraphTraits<GraphT>::getGraphName(Graph);
std::string Title = GraphName + " for '" + F.getName().str() + "' function";
if (ErrorInfo.empty())
WriteGraph(File, Graph, Simple, Title);
WriteGraph(File, Graph, IsSimple, Title);
else
errs() << " error opening file for writing!";
errs() << "\n";
@ -70,57 +83,61 @@ class DOTGraphTraitsPrinter : public FunctionPass {
return false;
}
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
AU.addRequired<Analysis>();
AU.addRequired<AnalysisT>();
}
private:
std::string Name;
};
template <class Analysis, bool Simple>
template <
typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT> >
class DOTGraphTraitsModuleViewer : public ModulePass {
public:
DOTGraphTraitsModuleViewer(StringRef GraphName, char &ID)
: ModulePass(ID), Name(GraphName) {}
: ModulePass(ID), Name(GraphName) {}
virtual bool runOnModule(Module &M) {
Analysis *Graph = &getAnalysis<Analysis>();
std::string Title = DOTGraphTraits<Analysis*>::getGraphName(Graph);
bool runOnModule(Module &M) override {
GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>());
std::string Title = DOTGraphTraits<GraphT>::getGraphName(Graph);
ViewGraph(Graph, Name, Simple, Title);
ViewGraph(Graph, Name, IsSimple, Title);
return false;
}
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
AU.addRequired<Analysis>();
AU.addRequired<AnalysisT>();
}
private:
std::string Name;
};
template <class Analysis, bool Simple>
template <
typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT> >
class DOTGraphTraitsModulePrinter : public ModulePass {
public:
DOTGraphTraitsModulePrinter(StringRef GraphName, char &ID)
: ModulePass(ID), Name(GraphName) {}
: ModulePass(ID), Name(GraphName) {}
virtual bool runOnModule(Module &M) {
Analysis *Graph = &getAnalysis<Analysis>();
bool runOnModule(Module &M) override {
GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>());
std::string Filename = Name + ".dot";
std::string ErrorInfo;
errs() << "Writing '" << Filename << "'...";
raw_fd_ostream File(Filename.c_str(), ErrorInfo);
std::string Title = DOTGraphTraits<Analysis*>::getGraphName(Graph);
raw_fd_ostream File(Filename.c_str(), ErrorInfo, sys::fs::F_Text);
std::string Title = DOTGraphTraits<GraphT>::getGraphName(Graph);
if (ErrorInfo.empty())
WriteGraph(File, Graph, Simple, Title);
WriteGraph(File, Graph, IsSimple, Title);
else
errs() << " error opening file for writing!";
errs() << "\n";
@ -128,9 +145,9 @@ class DOTGraphTraitsModulePrinter : public ModulePass {
return false;
}
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
AU.addRequired<Analysis>();
AU.addRequired<AnalysisT>();
}
private:

View File

@ -73,8 +73,8 @@ namespace llvm {
Instruction *Destination) :
Src(Source),
Dst(Destination),
NextPredecessor(NULL),
NextSuccessor(NULL) {}
NextPredecessor(nullptr),
NextSuccessor(nullptr) {}
virtual ~Dependence() {}
/// Dependence::DVEntry - Each level in the distance/direction vector
@ -96,7 +96,7 @@ namespace llvm {
bool Splitable : 1; // Splitting the loop will break dependence.
const SCEV *Distance; // NULL implies no distance available.
DVEntry() : Direction(ALL), Scalar(true), PeelFirst(false),
PeelLast(false), Splitable(false), Distance(NULL) { }
PeelLast(false), Splitable(false), Distance(nullptr) { }
};
/// getSrc - Returns the source instruction for this dependence.
@ -154,7 +154,7 @@ namespace llvm {
/// getDistance - Returns the distance (or NULL) associated with a
/// particular level.
virtual const SCEV *getDistance(unsigned Level) const { return NULL; }
virtual const SCEV *getDistance(unsigned Level) const { return nullptr; }
/// isPeelFirst - Returns true if peeling the first iteration from
/// this loop will break this dependence.
@ -227,45 +227,45 @@ namespace llvm {
/// isLoopIndependent - Returns true if this is a loop-independent
/// dependence.
bool isLoopIndependent() const { return LoopIndependent; }
bool isLoopIndependent() const override { return LoopIndependent; }
/// isConfused - Returns true if this dependence is confused
/// (the compiler understands nothing and makes worst-case
/// assumptions).
bool isConfused() const { return false; }
bool isConfused() const override { return false; }
/// isConsistent - Returns true if this dependence is consistent
/// (occurs every time the source and destination are executed).
bool isConsistent() const { return Consistent; }
bool isConsistent() const override { return Consistent; }
/// getLevels - Returns the number of common loops surrounding the
/// source and destination of the dependence.
unsigned getLevels() const { return Levels; }
unsigned getLevels() const override { return Levels; }
/// getDirection - Returns the direction associated with a particular
/// level.
unsigned getDirection(unsigned Level) const;
unsigned getDirection(unsigned Level) const override;
/// getDistance - Returns the distance (or NULL) associated with a
/// particular level.
const SCEV *getDistance(unsigned Level) const;
const SCEV *getDistance(unsigned Level) const override;
/// isPeelFirst - Returns true if peeling the first iteration from
/// this loop will break this dependence.
bool isPeelFirst(unsigned Level) const;
bool isPeelFirst(unsigned Level) const override;
/// isPeelLast - Returns true if peeling the last iteration from
/// this loop will break this dependence.
bool isPeelLast(unsigned Level) const;
bool isPeelLast(unsigned Level) const override;
/// isSplitable - Returns true if splitting the loop will break
/// the dependence.
bool isSplitable(unsigned Level) const;
bool isSplitable(unsigned Level) const override;
/// isScalar - Returns true if a particular level is scalar; that is,
/// if no subscript in the source or destination mention the induction
/// variable associated with the loop at this level.
bool isScalar(unsigned Level) const;
bool isScalar(unsigned Level) const override;
private:
unsigned short Levels;
bool LoopIndependent;
@ -910,7 +910,8 @@ namespace llvm {
const Constraint &CurConstraint) const;
bool tryDelinearize(const SCEV *SrcSCEV, const SCEV *DstSCEV,
SmallVectorImpl<Subscript> &Pair) const;
SmallVectorImpl<Subscript> &Pair,
const SCEV *ElementSize) const;
public:
static char ID; // Class identification, replacement for typeinfo
@ -918,10 +919,10 @@ namespace llvm {
initializeDependenceAnalysisPass(*PassRegistry::getPassRegistry());
}
bool runOnFunction(Function &F);
void releaseMemory();
void getAnalysisUsage(AnalysisUsage &) const;
void print(raw_ostream &, const Module * = 0) const;
bool runOnFunction(Function &F) override;
void releaseMemory() override;
void getAnalysisUsage(AnalysisUsage &) const override;
void print(raw_ostream &, const Module * = nullptr) const override;
}; // class DependenceAnalysis
/// createDependenceAnalysisPass - This creates an instance of the

View File

@ -18,173 +18,191 @@
#ifndef LLVM_ANALYSIS_DOMINANCEFRONTIER_H
#define LLVM_ANALYSIS_DOMINANCEFRONTIER_H
#include "llvm/Analysis/Dominators.h"
#include "llvm/IR/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 {
template <class BlockT>
class DominanceFrontierBase {
public:
typedef std::set<BasicBlock*> DomSetType; // Dom set for a bb
typedef std::map<BasicBlock*, DomSetType> DomSetMapType; // Dom set map
typedef std::set<BlockT *> DomSetType; // Dom set for a bb
typedef std::map<BlockT *, DomSetType> DomSetMapType; // Dom set map
protected:
typedef GraphTraits<BlockT *> BlockTraits;
DomSetMapType Frontiers;
std::vector<BasicBlock*> Roots;
std::vector<BlockT *> Roots;
const bool IsPostDominators;
public:
DominanceFrontierBase(char &ID, bool isPostDom)
: FunctionPass(ID), IsPostDominators(isPostDom) {}
DominanceFrontierBase(bool isPostDom) : 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; }
inline const std::vector<BlockT *> &getRoots() const {
return Roots;
}
BlockT *getRoot() const {
assert(Roots.size() == 1 && "Should always have entry node!");
return Roots[0];
}
/// isPostDominator - Returns true if analysis based of postdoms
///
bool isPostDominator() const { return IsPostDominators; }
bool isPostDominator() const {
return IsPostDominators;
}
virtual void releaseMemory() { Frontiers.clear(); }
void releaseMemory() {
Frontiers.clear();
}
// Accessor interface:
typedef DomSetMapType::iterator iterator;
typedef DomSetMapType::const_iterator const_iterator;
iterator begin() { return Frontiers.begin(); }
typedef typename DomSetMapType::iterator iterator;
typedef typename 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 end() { return Frontiers.end(); }
const_iterator end() const { return Frontiers.end(); }
iterator find(BlockT *B) { return Frontiers.find(B); }
const_iterator find(BlockT *B) const { return Frontiers.find(B); }
iterator addBasicBlock(BasicBlock *BB, const DomSetType &frontier) {
iterator addBasicBlock(BlockT *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 removeBlock(BlockT *BB);
void addToFrontier(iterator I, BasicBlock *Node) {
assert(I != end() && "BB is not in DominanceFrontier!");
I->second.insert(Node);
}
void addToFrontier(iterator I, BlockT *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);
}
void removeFromFrontier(iterator I, BlockT *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;
}
bool compareDomSet(DomSetType &DS1, const DomSetType &DS2) const;
/// 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;
}
bool compare(DominanceFrontierBase<BlockT> &Other) const;
/// print - Convert to human readable form
///
virtual void print(raw_ostream &OS, const Module* = 0) const;
void print(raw_ostream &OS) 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 {
virtual void anchor();
template <class BlockT>
class ForwardDominanceFrontierBase : public DominanceFrontierBase<BlockT> {
private:
typedef GraphTraits<BlockT *> BlockTraits;
public:
static char ID; // Pass ID, replacement for typeid
DominanceFrontier() :
DominanceFrontierBase(ID, false) {
initializeDominanceFrontierPass(*PassRegistry::getPassRegistry());
}
typedef DominatorTreeBase<BlockT> DomTreeT;
typedef DomTreeNodeBase<BlockT> DomTreeNodeT;
typedef typename DominanceFrontierBase<BlockT>::DomSetType DomSetType;
BasicBlock *getRoot() const {
assert(Roots.size() == 1 && "Should always have entry node!");
return Roots[0];
ForwardDominanceFrontierBase() : DominanceFrontierBase<BlockT>(false) {}
void analyze(DomTreeT &DT) {
this->Roots = DT.getRoots();
assert(this->Roots.size() == 1 &&
"Only one entry block for forward domfronts!");
calculate(DT, DT[this->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);
const DomSetType &calculate(const DomTreeT &DT, const DomTreeNodeT *Node);
};
class DominanceFrontier : public FunctionPass {
ForwardDominanceFrontierBase<BasicBlock> Base;
public:
typedef DominatorTreeBase<BasicBlock> DomTreeT;
typedef DomTreeNodeBase<BasicBlock> DomTreeNodeT;
typedef DominanceFrontierBase<BasicBlock>::DomSetType DomSetType;
typedef DominanceFrontierBase<BasicBlock>::iterator iterator;
typedef DominanceFrontierBase<BasicBlock>::const_iterator const_iterator;
static char ID; // Pass ID, replacement for typeid
DominanceFrontier();
ForwardDominanceFrontierBase<BasicBlock> &getBase() { return Base; }
inline const std::vector<BasicBlock *> &getRoots() const {
return Base.getRoots();
}
BasicBlock *getRoot() const { return Base.getRoot(); }
bool isPostDominator() const { return Base.isPostDominator(); }
iterator begin() { return Base.begin(); }
const_iterator begin() const { return Base.begin(); }
iterator end() { return Base.end(); }
const_iterator end() const { return Base.end(); }
iterator find(BasicBlock *B) { return Base.find(B); }
const_iterator find(BasicBlock *B) const { return Base.find(B); }
iterator addBasicBlock(BasicBlock *BB, const DomSetType &frontier) {
return Base.addBasicBlock(BB, frontier);
}
void removeBlock(BasicBlock *BB) { return Base.removeBlock(BB); }
void addToFrontier(iterator I, BasicBlock *Node) {
return Base.addToFrontier(I, Node);
}
void removeFromFrontier(iterator I, BasicBlock *Node) {
return Base.removeFromFrontier(I, Node);
}
bool compareDomSet(DomSetType &DS1, const DomSetType &DS2) const {
return Base.compareDomSet(DS1, DS2);
}
bool compare(DominanceFrontierBase<BasicBlock> &Other) const {
return Base.compare(Other);
}
void releaseMemory() override;
bool runOnFunction(Function &) override;
void getAnalysisUsage(AnalysisUsage &AU) const override;
void print(raw_ostream &OS, const Module * = nullptr) const override;
void dump() const;
};
EXTERN_TEMPLATE_INSTANTIATION(class DominanceFrontierBase<BasicBlock>);
EXTERN_TEMPLATE_INSTANTIATION(class ForwardDominanceFrontierBase<BasicBlock>);
} // End llvm namespace
#endif

View File

@ -0,0 +1,228 @@
//===- 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 is the generic implementation of the DominanceFrontier class, which
// calculate and holds the dominance frontier for a function for.
//
// This should be considered deprecated, don't add any more uses of this data
// structure.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_DOMINANCEFRONTIER_IMPL_H
#define LLVM_ANALYSIS_DOMINANCEFRONTIER_IMPL_H
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/Debug.h"
namespace llvm {
namespace {
template <class BlockT>
class DFCalculateWorkObject {
public:
typedef DomTreeNodeBase<BlockT> DomTreeNodeT;
DFCalculateWorkObject(BlockT *B, BlockT *P, const DomTreeNodeT *N,
const DomTreeNodeT *PN)
: currentBB(B), parentBB(P), Node(N), parentNode(PN) {}
BlockT *currentBB;
BlockT *parentBB;
const DomTreeNodeT *Node;
const DomTreeNodeT *parentNode;
};
}
template <class BlockT>
void DominanceFrontierBase<BlockT>::removeBlock(BlockT *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);
}
template <class BlockT>
void DominanceFrontierBase<BlockT>::addToFrontier(iterator I,
BlockT *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);
}
template <class BlockT>
void DominanceFrontierBase<BlockT>::removeFromFrontier(iterator I,
BlockT *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);
}
template <class BlockT>
bool DominanceFrontierBase<BlockT>::compareDomSet(DomSetType &DS1,
const DomSetType &DS2) const {
std::set<BlockT *> tmpSet;
for (BlockT *BB : DS2)
tmpSet.insert(BB);
for (typename DomSetType::const_iterator I = DS1.begin(), E = DS1.end();
I != E;) {
BlockT *Node = *I++;
if (tmpSet.erase(Node) == 0)
// Node is in DS1 but tnot 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;
}
template <class BlockT>
bool DominanceFrontierBase<BlockT>::compare(
DominanceFrontierBase<BlockT> &Other) const {
DomSetMapType tmpFrontiers;
for (typename DomSetMapType::const_iterator I = Other.begin(),
E = Other.end();
I != E; ++I)
tmpFrontiers.insert(std::make_pair(I->first, I->second));
for (typename DomSetMapType::iterator I = tmpFrontiers.begin(),
E = tmpFrontiers.end();
I != E;) {
BlockT *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;
}
template <class BlockT>
void DominanceFrontierBase<BlockT>::print(raw_ostream &OS) const {
for (const_iterator I = begin(), E = end(); I != E; ++I) {
OS << " DomFrontier for BB ";
if (I->first)
I->first->printAsOperand(OS, false);
else
OS << " <<exit node>>";
OS << " is:\t";
const std::set<BlockT *> &BBs = I->second;
for (const BlockT *BB : BBs) {
OS << ' ';
if (BB)
BB->printAsOperand(OS, false);
else
OS << "<<exit node>>";
}
OS << '\n';
}
}
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
template <class BlockT>
void DominanceFrontierBase<BlockT>::dump() const {
print(dbgs());
}
#endif
template <class BlockT>
const typename ForwardDominanceFrontierBase<BlockT>::DomSetType &
ForwardDominanceFrontierBase<BlockT>::calculate(const DomTreeT &DT,
const DomTreeNodeT *Node) {
BlockT *BB = Node->getBlock();
DomSetType *Result = nullptr;
std::vector<DFCalculateWorkObject<BlockT>> workList;
SmallPtrSet<BlockT *, 32> visited;
workList.push_back(DFCalculateWorkObject<BlockT>(BB, nullptr, Node, nullptr));
do {
DFCalculateWorkObject<BlockT> *currentW = &workList.back();
assert(currentW && "Missing work object.");
BlockT *currentBB = currentW->currentBB;
BlockT *parentBB = currentW->parentBB;
const DomTreeNodeT *currentNode = currentW->Node;
const DomTreeNodeT *parentNode = currentW->parentNode;
assert(currentBB && "Invalid work object. Missing current Basic Block");
assert(currentNode && "Invalid work object. Missing current Node");
DomSetType &S = this->Frontiers[currentBB];
// Visit each block only once.
if (visited.count(currentBB) == 0) {
visited.insert(currentBB);
// Loop over CFG successors to calculate DFlocal[currentNode]
for (auto SI = BlockTraits::child_begin(currentBB),
SE = BlockTraits::child_end(currentBB);
SI != SE; ++SI) {
// Does Node immediately dominate this successor?
if (DT[*SI]->getIDom() != currentNode)
S.insert(*SI);
}
}
// At this point, S is DFlocal. Now we union in DFup's of our children...
// Loop through and visit the nodes that Node immediately dominates (Node's
// children in the IDomTree)
bool visitChild = false;
for (typename DomTreeNodeT::const_iterator NI = currentNode->begin(),
NE = currentNode->end();
NI != NE; ++NI) {
DomTreeNodeT *IDominee = *NI;
BlockT *childBB = IDominee->getBlock();
if (visited.count(childBB) == 0) {
workList.push_back(DFCalculateWorkObject<BlockT>(
childBB, currentBB, IDominee, currentNode));
visitChild = true;
}
}
// If all children are visited or there is any child then pop this block
// from the workList.
if (!visitChild) {
if (!parentBB) {
Result = &S;
break;
}
typename DomSetType::const_iterator CDFI = S.begin(), CDFE = S.end();
DomSetType &parentSet = this->Frontiers[parentBB];
for (; CDFI != CDFE; ++CDFI) {
if (!DT.properlyDominates(parentNode, DT[*CDFI]))
parentSet.insert(*CDFI);
}
workList.pop_back();
}
} while (!workList.empty());
return *Result;
}
} // End llvm namespace
#endif

View File

@ -39,7 +39,7 @@ class FindUsedTypes : public ModulePass {
/// passed in, then the types are printed symbolically if possible, using the
/// symbol table from the module.
///
void print(raw_ostream &o, const Module *M) const;
void print(raw_ostream &o, const Module *M) const override;
private:
/// IncorporateType - Incorporate one type and all of its subtypes into the
@ -53,10 +53,10 @@ class FindUsedTypes : public ModulePass {
public:
/// run - This incorporates all types used by the specified module
bool runOnModule(Module &M);
bool runOnModule(Module &M) override;
/// getAnalysisUsage - We do not modify anything.
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
}
};

View File

@ -17,7 +17,7 @@
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/ScalarEvolutionNormalization.h"
#include "llvm/Support/ValueHandle.h"
#include "llvm/IR/ValueHandle.h"
namespace llvm {
@ -86,7 +86,7 @@ class IVStrideUse : public CallbackVH, public ilist_node<IVStrideUse> {
/// Deleted - Implementation of CallbackVH virtual function to
/// receive notification when the User is deleted.
virtual void deleted();
void deleted() override;
};
template<> struct ilist_traits<IVStrideUse>
@ -122,18 +122,18 @@ class IVUsers : public LoopPass {
LoopInfo *LI;
DominatorTree *DT;
ScalarEvolution *SE;
DataLayout *TD;
const DataLayout *DL;
SmallPtrSet<Instruction*,16> Processed;
/// IVUses - A list of all tracked IV uses of induction variable expressions
/// we are interested in.
ilist<IVStrideUse> IVUses;
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
void getAnalysisUsage(AnalysisUsage &AU) const override;
virtual bool runOnLoop(Loop *L, LPPassManager &LPM);
bool runOnLoop(Loop *L, LPPassManager &LPM) override;
virtual void releaseMemory();
void releaseMemory() override;
public:
static char ID; // Pass ID, replacement for typeid
@ -169,7 +169,7 @@ class IVUsers : public LoopPass {
return Processed.count(Inst);
}
void print(raw_ostream &OS, const Module* = 0) const;
void print(raw_ostream &OS, const Module* = nullptr) const override;
/// dump - This method is used for debugging.
void dump() const;

View File

@ -99,7 +99,6 @@ class InlineCost {
/// \brief Cost analyzer used by inliner.
class InlineCostAnalysis : public CallGraphSCCPass {
const DataLayout *TD;
const TargetTransformInfo *TTI;
public:
@ -109,8 +108,8 @@ class InlineCostAnalysis : public CallGraphSCCPass {
~InlineCostAnalysis();
// Pass interface implementation.
void getAnalysisUsage(AnalysisUsage &AU) const;
bool runOnSCC(CallGraphSCC &SCC);
void getAnalysisUsage(AnalysisUsage &AU) const override;
bool runOnSCC(CallGraphSCC &SCC) override;
/// \brief Get an InlineCost object representing the cost of inlining this
/// callsite.

View File

@ -48,160 +48,166 @@ namespace llvm {
/// SimplifyAddInst - Given operands for an Add, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyAddInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW,
const DataLayout *TD = 0,
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr);
/// SimplifySubInst - Given operands for a Sub, see if we can
/// fold the result. If not, this returns null.
Value *SimplifySubInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW,
const DataLayout *TD = 0,
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr);
/// Given operands for an FAdd, see if we can fold the result. If not, this
/// returns null.
Value *SimplifyFAddInst(Value *LHS, Value *RHS, FastMathFlags FMF,
const DataLayout *TD = 0,
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr);
/// Given operands for an FSub, see if we can fold the result. If not, this
/// returns null.
Value *SimplifyFSubInst(Value *LHS, Value *RHS, FastMathFlags FMF,
const DataLayout *TD = 0,
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr);
/// Given operands for an FMul, see if we can fold the result. If not, this
/// returns null.
Value *SimplifyFMulInst(Value *LHS, Value *RHS,
FastMathFlags FMF,
const DataLayout *TD = 0,
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr);
/// SimplifyMulInst - Given operands for a Mul, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyMulInst(Value *LHS, Value *RHS, const DataLayout *TD = 0,
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
Value *SimplifyMulInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr);
/// SimplifySDivInst - Given operands for an SDiv, see if we can
/// fold the result. If not, this returns null.
Value *SimplifySDivInst(Value *LHS, Value *RHS, const DataLayout *TD = 0,
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
Value *SimplifySDivInst(Value *LHS, Value *RHS,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr);
/// SimplifyUDivInst - Given operands for a UDiv, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyUDivInst(Value *LHS, Value *RHS, const DataLayout *TD = 0,
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
Value *SimplifyUDivInst(Value *LHS, Value *RHS,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr);
/// SimplifyFDivInst - Given operands for an FDiv, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyFDivInst(Value *LHS, Value *RHS, const DataLayout *TD = 0,
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
Value *SimplifyFDivInst(Value *LHS, Value *RHS,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr);
/// SimplifySRemInst - Given operands for an SRem, see if we can
/// fold the result. If not, this returns null.
Value *SimplifySRemInst(Value *LHS, Value *RHS, const DataLayout *TD = 0,
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
Value *SimplifySRemInst(Value *LHS, Value *RHS,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr);
/// SimplifyURemInst - Given operands for a URem, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyURemInst(Value *LHS, Value *RHS, const DataLayout *TD = 0,
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
Value *SimplifyURemInst(Value *LHS, Value *RHS,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr);
/// SimplifyFRemInst - Given operands for an FRem, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyFRemInst(Value *LHS, Value *RHS, const DataLayout *TD = 0,
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
Value *SimplifyFRemInst(Value *LHS, Value *RHS,
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr);
/// SimplifyShlInst - Given operands for a Shl, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
const DataLayout *TD = 0,
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr);
/// SimplifyLShrInst - Given operands for a LShr, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact,
const DataLayout *TD = 0,
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr);
/// SimplifyAShrInst - Given operands for a AShr, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact,
const DataLayout *TD = 0,
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr);
/// SimplifyAndInst - Given operands for an And, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyAndInst(Value *LHS, Value *RHS, const DataLayout *TD = 0,
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
Value *SimplifyAndInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr);
/// SimplifyOrInst - Given operands for an Or, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyOrInst(Value *LHS, Value *RHS, const DataLayout *TD = 0,
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
Value *SimplifyOrInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr);
/// SimplifyXorInst - Given operands for a Xor, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyXorInst(Value *LHS, Value *RHS, const DataLayout *TD = 0,
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
Value *SimplifyXorInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr);
/// SimplifyICmpInst - Given operands for an ICmpInst, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
const DataLayout *TD = 0,
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr);
/// SimplifyFCmpInst - Given operands for an FCmpInst, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
const DataLayout *TD = 0,
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr);
/// SimplifySelectInst - Given operands for a SelectInst, see if we can fold
/// the result. If not, this returns null.
Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
const DataLayout *TD = 0,
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr);
/// SimplifyGEPInst - Given operands for an GetElementPtrInst, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyGEPInst(ArrayRef<Value *> Ops, const DataLayout *TD = 0,
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
Value *SimplifyGEPInst(ArrayRef<Value *> Ops, const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr);
/// SimplifyInsertValueInst - Given operands for an InsertValueInst, see if we
/// can fold the result. If not, this returns null.
Value *SimplifyInsertValueInst(Value *Agg, Value *Val,
ArrayRef<unsigned> Idxs,
const DataLayout *TD = 0,
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr);
/// SimplifyTruncInst - Given operands for an TruncInst, see if we can fold
/// the result. If not, this returns null.
Value *SimplifyTruncInst(Value *Op, Type *Ty, const DataLayout *TD = 0,
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
Value *SimplifyTruncInst(Value *Op, Type *Ty, const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr);
//=== Helper functions for higher up the class hierarchy.
@ -209,40 +215,40 @@ namespace llvm {
/// SimplifyCmpInst - Given operands for a CmpInst, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
const DataLayout *TD = 0,
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr);
/// SimplifyBinOp - Given operands for a BinaryOperator, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS,
const DataLayout *TD = 0,
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr);
/// \brief Given a function and iterators over arguments, see if we can fold
/// the result.
///
/// If this call could not be simplified returns null.
Value *SimplifyCall(Value *V, User::op_iterator ArgBegin,
User::op_iterator ArgEnd, const DataLayout *TD = 0,
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
User::op_iterator ArgEnd, const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr);
/// \brief Given a function and set of arguments, see if we can fold the
/// result.
///
/// If this call could not be simplified returns null.
Value *SimplifyCall(Value *V, ArrayRef<Value *> Args,
const DataLayout *TD = 0,
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr);
/// SimplifyInstruction - See if we can compute a simplified version of this
/// instruction. If not, this returns null.
Value *SimplifyInstruction(Instruction *I, const DataLayout *TD = 0,
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
Value *SimplifyInstruction(Instruction *I, const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr);
/// \brief Replace all uses of 'I' with 'SimpleV' and simplify the uses
@ -254,9 +260,9 @@ namespace llvm {
///
/// The function returns true if any simplifications were performed.
bool replaceAndRecursivelySimplify(Instruction *I, Value *SimpleV,
const DataLayout *TD = 0,
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr);
/// \brief Recursively attempt to simplify an instruction.
///
@ -265,9 +271,9 @@ namespace llvm {
/// of the users impacted. It returns true if any simplifications were
/// performed.
bool recursivelySimplifyInstruction(Instruction *I,
const DataLayout *TD = 0,
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
const DataLayout *TD = nullptr,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr);
} // end namespace llvm
#endif

View File

@ -48,9 +48,6 @@ class Interval {
Nodes.push_back(Header);
}
inline Interval(const Interval &I) // copy ctor
: HeaderNode(I.HeaderNode), Nodes(I.Nodes), Successors(I.Successors) {}
inline BasicBlock *getHeaderNode() const { return HeaderNode; }
/// Nodes - The basic blocks in this interval.

View File

@ -34,8 +34,8 @@
#define LLVM_ANALYSIS_INTERVALITERATOR_H
#include "llvm/Analysis/IntervalPartition.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/CFG.h"
#include <algorithm>
#include <set>
#include <vector>

View File

@ -34,7 +34,7 @@ namespace llvm {
// IntervalPartition - This class builds and holds an "interval partition" for
// a function. This partition divides the control flow graph into a set of
// maximal intervals, as defined with the properties above. Intuitively, an
// interval is a (possibly nonexistent) loop with a "tail" of non looping
// interval is a (possibly nonexistent) loop with a "tail" of non-looping
// nodes following it.
//
class IntervalPartition : public FunctionPass {
@ -48,12 +48,12 @@ class IntervalPartition : public FunctionPass {
public:
static char ID; // Pass identification, replacement for typeid
IntervalPartition() : FunctionPass(ID), RootInterval(0) {
IntervalPartition() : FunctionPass(ID), RootInterval(nullptr) {
initializeIntervalPartitionPass(*PassRegistry::getPassRegistry());
}
// run - Calculate the interval partition for this function
virtual bool runOnFunction(Function &F);
bool runOnFunction(Function &F) override;
// IntervalPartition ctor - Build a reduced interval partition from an
// existing interval graph. This takes an additional boolean parameter to
@ -62,7 +62,7 @@ class IntervalPartition : public FunctionPass {
IntervalPartition(IntervalPartition &I, bool);
// print - Show contents in human readable format...
virtual void print(raw_ostream &O, const Module* = 0) const;
void print(raw_ostream &O, const Module* = nullptr) const override;
// getRootInterval() - Return the root interval that contains the starting
// block of the function.
@ -77,11 +77,11 @@ class IntervalPartition : public FunctionPass {
// getBlockInterval - Return the interval that a basic block exists in.
inline Interval *getBlockInterval(BasicBlock *BB) {
IntervalMapTy::iterator I = IntervalMap.find(BB);
return I != IntervalMap.end() ? I->second : 0;
return I != IntervalMap.end() ? I->second : nullptr;
}
// getAnalysisUsage - Implement the Pass API
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
}
@ -89,7 +89,7 @@ class IntervalPartition : public FunctionPass {
const std::vector<Interval*> &getIntervals() const { return Intervals; }
// releaseMemory - Reset state back to before function was analyzed
void releaseMemory();
void releaseMemory() override;
private:
// addIntervalToPartition - Add an interval to the internal list of intervals,

View File

@ -0,0 +1,60 @@
//===-- JumpInstrTableInfo.h: Info for Jump-Instruction Tables --*- C++ -*-===//
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Information about jump-instruction tables that have been created by
/// JumpInstrTables pass.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_JUMPINSTRTABLEINFO_H
#define LLVM_ANALYSIS_JUMPINSTRTABLEINFO_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/Pass.h"
#include <vector>
namespace llvm {
class Function;
class FunctionType;
/// This class stores information about jump-instruction tables created by the
/// JumpInstrTables pass (in lib/CodeGen/JumpInstrTables.cpp). Each table is a
/// map from a function type to a vector of pairs. The first element of each
/// pair is the function that has the jumptable annotation. The second element
/// is a function that was declared by JumpInstrTables and used to replace all
/// address-taking sites for the original function.
///
/// The information in this pass is used in AsmPrinter
/// (lib/CodeGen/AsmPrinter/AsmPrinter.cpp) to generate the required assembly
/// for the jump-instruction tables.
class JumpInstrTableInfo : public ImmutablePass {
public:
static char ID;
JumpInstrTableInfo();
virtual ~JumpInstrTableInfo();
const char *getPassName() const override {
return "Jump-Instruction Table Info";
}
typedef std::pair<Function *, Function *> JumpPair;
typedef DenseMap<FunctionType *, std::vector<JumpPair> > JumpTables;
/// Inserts an entry in a table, adding the table if it doesn't exist.
void insertEntry(FunctionType *TableFunTy, Function *Target, Function *Jump);
/// Gets the tables.
const JumpTables &getTables() const { return Tables; }
private:
JumpTables Tables;
};
}
#endif /* LLVM_ANALYSIS_JUMPINSTRTABLEINFO_H */

View File

@ -0,0 +1,566 @@
//===- LazyCallGraph.h - Analysis of a Module's call graph ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
///
/// Implements a lazy call graph analysis and related passes for the new pass
/// manager.
///
/// NB: This is *not* a traditional call graph! It is a graph which models both
/// the current calls and potential calls. As a consequence there are many
/// edges in this call graph that do not correspond to a 'call' or 'invoke'
/// instruction.
///
/// The primary use cases of this graph analysis is to facilitate iterating
/// across the functions of a module in ways that ensure all callees are
/// visited prior to a caller (given any SCC constraints), or vice versa. As
/// such is it particularly well suited to organizing CGSCC optimizations such
/// as inlining, outlining, argument promotion, etc. That is its primary use
/// case and motivates the design. It may not be appropriate for other
/// purposes. The use graph of functions or some other conservative analysis of
/// call instructions may be interesting for optimizations and subsequent
/// analyses which don't work in the context of an overly specified
/// potential-call-edge graph.
///
/// To understand the specific rules and nature of this call graph analysis,
/// see the documentation of the \c LazyCallGraph below.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_LAZY_CALL_GRAPH
#define LLVM_ANALYSIS_LAZY_CALL_GRAPH
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/Allocator.h"
#include <iterator>
namespace llvm {
class ModuleAnalysisManager;
class PreservedAnalyses;
class raw_ostream;
/// \brief A lazily constructed view of the call graph of a module.
///
/// With the edges of this graph, the motivating constraint that we are
/// attempting to maintain is that function-local optimization, CGSCC-local
/// optimizations, and optimizations transforming a pair of functions connected
/// by an edge in the graph, do not invalidate a bottom-up traversal of the SCC
/// DAG. That is, no optimizations will delete, remove, or add an edge such
/// that functions already visited in a bottom-up order of the SCC DAG are no
/// longer valid to have visited, or such that functions not yet visited in
/// a bottom-up order of the SCC DAG are not required to have already been
/// visited.
///
/// Within this constraint, the desire is to minimize the merge points of the
/// SCC DAG. The greater the fanout of the SCC DAG and the fewer merge points
/// in the SCC DAG, the more independence there is in optimizing within it.
/// There is a strong desire to enable parallelization of optimizations over
/// the call graph, and both limited fanout and merge points will (artificially
/// in some cases) limit the scaling of such an effort.
///
/// To this end, graph represents both direct and any potential resolution to
/// an indirect call edge. Another way to think about it is that it represents
/// both the direct call edges and any direct call edges that might be formed
/// through static optimizations. Specifically, it considers taking the address
/// of a function to be an edge in the call graph because this might be
/// forwarded to become a direct call by some subsequent function-local
/// optimization. The result is that the graph closely follows the use-def
/// edges for functions. Walking "up" the graph can be done by looking at all
/// of the uses of a function.
///
/// The roots of the call graph are the external functions and functions
/// escaped into global variables. Those functions can be called from outside
/// of the module or via unknowable means in the IR -- we may not be able to
/// form even a potential call edge from a function body which may dynamically
/// load the function and call it.
///
/// This analysis still requires updates to remain valid after optimizations
/// which could potentially change the set of potential callees. The
/// constraints it operates under only make the traversal order remain valid.
///
/// The entire analysis must be re-computed if full interprocedural
/// optimizations run at any point. For example, globalopt completely
/// invalidates the information in this analysis.
///
/// FIXME: This class is named LazyCallGraph in a lame attempt to distinguish
/// it from the existing CallGraph. At some point, it is expected that this
/// will be the only call graph and it will be renamed accordingly.
class LazyCallGraph {
public:
class Node;
class SCC;
typedef SmallVector<PointerUnion<Function *, Node *>, 4> NodeVectorT;
typedef SmallVectorImpl<PointerUnion<Function *, Node *>> NodeVectorImplT;
/// \brief A lazy iterator used for both the entry nodes and child nodes.
///
/// When this iterator is dereferenced, if not yet available, a function will
/// be scanned for "calls" or uses of functions and its child information
/// will be constructed. All of these results are accumulated and cached in
/// the graph.
class iterator
: public iterator_adaptor_base<iterator, NodeVectorImplT::iterator,
std::forward_iterator_tag, Node> {
friend class LazyCallGraph;
friend class LazyCallGraph::Node;
LazyCallGraph *G;
NodeVectorImplT::iterator E;
// Build the iterator for a specific position in a node list.
iterator(LazyCallGraph &G, NodeVectorImplT::iterator NI,
NodeVectorImplT::iterator E)
: iterator_adaptor_base(NI), G(&G), E(E) {
while (I != E && I->isNull())
++I;
}
public:
iterator() {}
using iterator_adaptor_base::operator++;
iterator &operator++() {
do {
++I;
} while (I != E && I->isNull());
return *this;
}
reference operator*() const {
if (I->is<Node *>())
return *I->get<Node *>();
Function *F = I->get<Function *>();
Node &ChildN = G->get(*F);
*I = &ChildN;
return ChildN;
}
};
/// \brief A node in the call graph.
///
/// This represents a single node. It's primary roles are to cache the list of
/// callees, de-duplicate and provide fast testing of whether a function is
/// a callee, and facilitate iteration of child nodes in the graph.
class Node {
friend class LazyCallGraph;
friend class LazyCallGraph::SCC;
LazyCallGraph *G;
Function &F;
// We provide for the DFS numbering and Tarjan walk lowlink numbers to be
// stored directly within the node.
int DFSNumber;
int LowLink;
mutable NodeVectorT Callees;
DenseMap<Function *, size_t> CalleeIndexMap;
/// \brief Basic constructor implements the scanning of F into Callees and
/// CalleeIndexMap.
Node(LazyCallGraph &G, Function &F);
/// \brief Internal helper to insert a callee.
void insertEdgeInternal(Function &Callee);
/// \brief Internal helper to insert a callee.
void insertEdgeInternal(Node &CalleeN);
/// \brief Internal helper to remove a callee from this node.
void removeEdgeInternal(Function &Callee);
public:
typedef LazyCallGraph::iterator iterator;
Function &getFunction() const {
return F;
};
iterator begin() const {
return iterator(*G, Callees.begin(), Callees.end());
}
iterator end() const { return iterator(*G, Callees.end(), Callees.end()); }
/// Equality is defined as address equality.
bool operator==(const Node &N) const { return this == &N; }
bool operator!=(const Node &N) const { return !operator==(N); }
};
/// \brief An SCC of the call graph.
///
/// This represents a Strongly Connected Component of the call graph as
/// a collection of call graph nodes. While the order of nodes in the SCC is
/// stable, it is not any particular order.
class SCC {
friend class LazyCallGraph;
friend class LazyCallGraph::Node;
LazyCallGraph *G;
SmallPtrSet<SCC *, 1> ParentSCCs;
SmallVector<Node *, 1> Nodes;
SCC(LazyCallGraph &G) : G(&G) {}
void insert(Node &N);
void
internalDFS(SmallVectorImpl<std::pair<Node *, Node::iterator>> &DFSStack,
SmallVectorImpl<Node *> &PendingSCCStack, Node *N,
SmallVectorImpl<SCC *> &ResultSCCs);
public:
typedef SmallVectorImpl<Node *>::const_iterator iterator;
typedef pointee_iterator<SmallPtrSet<SCC *, 1>::const_iterator> parent_iterator;
iterator begin() const { return Nodes.begin(); }
iterator end() const { return Nodes.end(); }
parent_iterator parent_begin() const { return ParentSCCs.begin(); }
parent_iterator parent_end() const { return ParentSCCs.end(); }
iterator_range<parent_iterator> parents() const {
return iterator_range<parent_iterator>(parent_begin(), parent_end());
}
/// \brief Test if this SCC is a parent of \a C.
bool isParentOf(const SCC &C) const { return C.isChildOf(*this); }
/// \brief Test if this SCC is an ancestor of \a C.
bool isAncestorOf(const SCC &C) const { return C.isDescendantOf(*this); }
/// \brief Test if this SCC is a child of \a C.
bool isChildOf(const SCC &C) const {
return ParentSCCs.count(const_cast<SCC *>(&C));
}
/// \brief Test if this SCC is a descendant of \a C.
bool isDescendantOf(const SCC &C) const;
///@{
/// \name Mutation API
///
/// These methods provide the core API for updating the call graph in the
/// presence of a (potentially still in-flight) DFS-found SCCs.
///
/// Note that these methods sometimes have complex runtimes, so be careful
/// how you call them.
/// \brief Insert an edge from one node in this SCC to another in this SCC.
///
/// By the definition of an SCC, this does not change the nature or make-up
/// of any SCCs.
void insertIntraSCCEdge(Node &CallerN, Node &CalleeN);
/// \brief Insert an edge whose tail is in this SCC and head is in some
/// child SCC.
///
/// There must be an existing path from the caller to the callee. This
/// operation is inexpensive and does not change the set of SCCs in the
/// graph.
void insertOutgoingEdge(Node &CallerN, Node &CalleeN);
/// \brief Insert an edge whose tail is in a descendant SCC and head is in
/// this SCC.
///
/// There must be an existing path from the callee to the caller in this
/// case. NB! This is has the potential to be a very expensive function. It
/// inherently forms a cycle in the prior SCC DAG and we have to merge SCCs
/// to resolve that cycle. But finding all of the SCCs which participate in
/// the cycle can in the worst case require traversing every SCC in the
/// graph. Every attempt is made to avoid that, but passes must still
/// exercise caution calling this routine repeatedly.
///
/// FIXME: We could possibly optimize this quite a bit for cases where the
/// caller and callee are very nearby in the graph. See comments in the
/// implementation for details, but that use case might impact users.
SmallVector<SCC *, 1> insertIncomingEdge(Node &CallerN, Node &CalleeN);
/// \brief Remove an edge whose source is in this SCC and target is *not*.
///
/// This removes an inter-SCC edge. All inter-SCC edges originating from
/// this SCC have been fully explored by any in-flight DFS SCC formation,
/// so this is always safe to call once you have the source SCC.
///
/// This operation does not change the set of SCCs or the members of the
/// SCCs and so is very inexpensive. It may change the connectivity graph
/// of the SCCs though, so be careful calling this while iterating over
/// them.
void removeInterSCCEdge(Node &CallerN, Node &CalleeN);
/// \brief Remove an edge which is entirely within this SCC.
///
/// Both the \a Caller and the \a Callee must be within this SCC. Removing
/// such an edge make break cycles that form this SCC and thus this
/// operation may change the SCC graph significantly. In particular, this
/// operation will re-form new SCCs based on the remaining connectivity of
/// the graph. The following invariants are guaranteed to hold after
/// calling this method:
///
/// 1) This SCC is still an SCC in the graph.
/// 2) This SCC will be the parent of any new SCCs. Thus, this SCC is
/// preserved as the root of any new SCC directed graph formed.
/// 3) No SCC other than this SCC has its member set changed (this is
/// inherent in the definition of removing such an edge).
/// 4) All of the parent links of the SCC graph will be updated to reflect
/// the new SCC structure.
/// 5) All SCCs formed out of this SCC, excluding this SCC, will be
/// returned in a vector.
/// 6) The order of the SCCs in the vector will be a valid postorder
/// traversal of the new SCCs.
///
/// These invariants are very important to ensure that we can build
/// optimization pipeliens on top of the CGSCC pass manager which
/// intelligently update the SCC graph without invalidating other parts of
/// the SCC graph.
///
/// The runtime complexity of this method is, in the worst case, O(V+E)
/// where V is the number of nodes in this SCC and E is the number of edges
/// leaving the nodes in this SCC. Note that E includes both edges within
/// this SCC and edges from this SCC to child SCCs. Some effort has been
/// made to minimize the overhead of common cases such as self-edges and
/// edge removals which result in a spanning tree with no more cycles.
SmallVector<SCC *, 1> removeIntraSCCEdge(Node &CallerN, Node &CalleeN);
///@}
};
/// \brief A post-order depth-first SCC iterator over the call graph.
///
/// This iterator triggers the Tarjan DFS-based formation of the SCC DAG for
/// the call graph, walking it lazily in depth-first post-order. That is, it
/// always visits SCCs for a callee prior to visiting the SCC for a caller
/// (when they are in different SCCs).
class postorder_scc_iterator
: public iterator_facade_base<postorder_scc_iterator,
std::forward_iterator_tag, SCC> {
friend class LazyCallGraph;
friend class LazyCallGraph::Node;
/// \brief Nonce type to select the constructor for the end iterator.
struct IsAtEndT {};
LazyCallGraph *G;
SCC *C;
// Build the begin iterator for a node.
postorder_scc_iterator(LazyCallGraph &G) : G(&G) {
C = G.getNextSCCInPostOrder();
}
// Build the end iterator for a node. This is selected purely by overload.
postorder_scc_iterator(LazyCallGraph &G, IsAtEndT /*Nonce*/)
: G(&G), C(nullptr) {}
public:
bool operator==(const postorder_scc_iterator &Arg) const {
return G == Arg.G && C == Arg.C;
}
reference operator*() const { return *C; }
using iterator_facade_base::operator++;
postorder_scc_iterator &operator++() {
C = G->getNextSCCInPostOrder();
return *this;
}
};
/// \brief Construct a graph for the given module.
///
/// This sets up the graph and computes all of the entry points of the graph.
/// No function definitions are scanned until their nodes in the graph are
/// requested during traversal.
LazyCallGraph(Module &M);
LazyCallGraph(LazyCallGraph &&G);
LazyCallGraph &operator=(LazyCallGraph &&RHS);
iterator begin() {
return iterator(*this, EntryNodes.begin(), EntryNodes.end());
}
iterator end() { return iterator(*this, EntryNodes.end(), EntryNodes.end()); }
postorder_scc_iterator postorder_scc_begin() {
return postorder_scc_iterator(*this);
}
postorder_scc_iterator postorder_scc_end() {
return postorder_scc_iterator(*this, postorder_scc_iterator::IsAtEndT());
}
iterator_range<postorder_scc_iterator> postorder_sccs() {
return iterator_range<postorder_scc_iterator>(postorder_scc_begin(),
postorder_scc_end());
}
/// \brief Lookup a function in the graph which has already been scanned and
/// added.
Node *lookup(const Function &F) const { return NodeMap.lookup(&F); }
/// \brief Lookup a function's SCC in the graph.
///
/// \returns null if the function hasn't been assigned an SCC via the SCC
/// iterator walk.
SCC *lookupSCC(Node &N) const { return SCCMap.lookup(&N); }
/// \brief Get a graph node for a given function, scanning it to populate the
/// graph data as necessary.
Node &get(Function &F) {
Node *&N = NodeMap[&F];
if (N)
return *N;
return insertInto(F, N);
}
///@{
/// \name Pre-SCC Mutation API
///
/// These methods are only valid to call prior to forming any SCCs for this
/// call graph. They can be used to update the core node-graph during
/// a node-based inorder traversal that precedes any SCC-based traversal.
///
/// Once you begin manipulating a call graph's SCCs, you must perform all
/// mutation of the graph via the SCC methods.
/// \brief Update the call graph after inserting a new edge.
void insertEdge(Node &Caller, Function &Callee);
/// \brief Update the call graph after inserting a new edge.
void insertEdge(Function &Caller, Function &Callee) {
return insertEdge(get(Caller), Callee);
}
/// \brief Update the call graph after deleting an edge.
void removeEdge(Node &Caller, Function &Callee);
/// \brief Update the call graph after deleting an edge.
void removeEdge(Function &Caller, Function &Callee) {
return removeEdge(get(Caller), Callee);
}
///@}
private:
/// \brief Allocator that holds all the call graph nodes.
SpecificBumpPtrAllocator<Node> BPA;
/// \brief Maps function->node for fast lookup.
DenseMap<const Function *, Node *> NodeMap;
/// \brief The entry nodes to the graph.
///
/// These nodes are reachable through "external" means. Put another way, they
/// escape at the module scope.
NodeVectorT EntryNodes;
/// \brief Map of the entry nodes in the graph to their indices in
/// \c EntryNodes.
DenseMap<Function *, size_t> EntryIndexMap;
/// \brief Allocator that holds all the call graph SCCs.
SpecificBumpPtrAllocator<SCC> SCCBPA;
/// \brief Maps Function -> SCC for fast lookup.
DenseMap<Node *, SCC *> SCCMap;
/// \brief The leaf SCCs of the graph.
///
/// These are all of the SCCs which have no children.
SmallVector<SCC *, 4> LeafSCCs;
/// \brief Stack of nodes in the DFS walk.
SmallVector<std::pair<Node *, iterator>, 4> DFSStack;
/// \brief Set of entry nodes not-yet-processed into SCCs.
SmallVector<Function *, 4> SCCEntryNodes;
/// \brief Stack of nodes the DFS has walked but not yet put into a SCC.
SmallVector<Node *, 4> PendingSCCStack;
/// \brief Counter for the next DFS number to assign.
int NextDFSNumber;
/// \brief Helper to insert a new function, with an already looked-up entry in
/// the NodeMap.
Node &insertInto(Function &F, Node *&MappedN);
/// \brief Helper to update pointers back to the graph object during moves.
void updateGraphPtrs();
/// \brief Helper to form a new SCC out of the top of a DFSStack-like
/// structure.
SCC *formSCC(Node *RootN, SmallVectorImpl<Node *> &NodeStack);
/// \brief Retrieve the next node in the post-order SCC walk of the call graph.
SCC *getNextSCCInPostOrder();
};
// Provide GraphTraits specializations for call graphs.
template <> struct GraphTraits<LazyCallGraph::Node *> {
typedef LazyCallGraph::Node NodeType;
typedef LazyCallGraph::iterator ChildIteratorType;
static NodeType *getEntryNode(NodeType *N) { return N; }
static ChildIteratorType child_begin(NodeType *N) { return N->begin(); }
static ChildIteratorType child_end(NodeType *N) { return N->end(); }
};
template <> struct GraphTraits<LazyCallGraph *> {
typedef LazyCallGraph::Node NodeType;
typedef LazyCallGraph::iterator ChildIteratorType;
static NodeType *getEntryNode(NodeType *N) { return N; }
static ChildIteratorType child_begin(NodeType *N) { return N->begin(); }
static ChildIteratorType child_end(NodeType *N) { return N->end(); }
};
/// \brief An analysis pass which computes the call graph for a module.
class LazyCallGraphAnalysis {
public:
/// \brief Inform generic clients of the result type.
typedef LazyCallGraph Result;
static void *ID() { return (void *)&PassID; }
/// \brief Compute the \c LazyCallGraph for a the module \c M.
///
/// This just builds the set of entry points to the call graph. The rest is
/// built lazily as it is walked.
LazyCallGraph run(Module *M) { return LazyCallGraph(*M); }
private:
static char PassID;
};
/// \brief A pass which prints the call graph to a \c raw_ostream.
///
/// This is primarily useful for testing the analysis.
class LazyCallGraphPrinterPass {
raw_ostream &OS;
public:
explicit LazyCallGraphPrinterPass(raw_ostream &OS);
PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM);
static StringRef name() { return "LazyCallGraphPrinterPass"; }
};
}
#endif

View File

@ -26,17 +26,17 @@ namespace llvm {
/// LazyValueInfo - This pass computes, caches, and vends lazy value constraint
/// information.
class LazyValueInfo : public FunctionPass {
class DataLayout *TD;
const DataLayout *DL;
class TargetLibraryInfo *TLI;
void *PImpl;
LazyValueInfo(const LazyValueInfo&) LLVM_DELETED_FUNCTION;
void operator=(const LazyValueInfo&) LLVM_DELETED_FUNCTION;
public:
static char ID;
LazyValueInfo() : FunctionPass(ID), PImpl(0) {
LazyValueInfo() : FunctionPass(ID), PImpl(nullptr) {
initializeLazyValueInfoPass(*PassRegistry::getPassRegistry());
}
~LazyValueInfo() { assert(PImpl == 0 && "releaseMemory not called"); }
~LazyValueInfo() { assert(!PImpl && "releaseMemory not called"); }
/// Tristate - This is used to return true/false/dunno results.
enum Tristate {
@ -69,10 +69,10 @@ class LazyValueInfo : public FunctionPass {
void eraseBlock(BasicBlock *BB);
// Implementation boilerplate.
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
virtual void releaseMemory();
virtual bool runOnFunction(Function &F);
void getAnalysisUsage(AnalysisUsage &AU) const override;
void releaseMemory() override;
bool runOnFunction(Function &F) override;
};
} // end namespace llvm

View File

@ -27,7 +27,7 @@ namespace llvm {
LibCallInfo *LCI;
explicit LibCallAliasAnalysis(LibCallInfo *LC = 0)
explicit LibCallAliasAnalysis(LibCallInfo *LC = nullptr)
: FunctionPass(ID), LCI(LC) {
initializeLibCallAliasAnalysisPass(*PassRegistry::getPassRegistry());
}
@ -38,17 +38,17 @@ namespace llvm {
~LibCallAliasAnalysis();
ModRefResult getModRefInfo(ImmutableCallSite CS,
const Location &Loc);
const Location &Loc) override;
ModRefResult getModRefInfo(ImmutableCallSite CS1,
ImmutableCallSite CS2) {
ImmutableCallSite CS2) override {
// TODO: Could compare two direct calls against each other if we cared to.
return AliasAnalysis::getModRefInfo(CS1, CS2);
}
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
virtual bool runOnFunction(Function &F) {
void getAnalysisUsage(AnalysisUsage &AU) const override;
bool runOnFunction(Function &F) override {
InitializeAliasAnalysis(this); // set up super class
return false;
}
@ -57,7 +57,7 @@ namespace llvm {
/// an analysis interface through multiple inheritance. If needed, it
/// should override this to adjust the this pointer as needed for the
/// specified pass info.
virtual void *getAdjustedAnalysisPointer(const void *PI) {
void *getAdjustedAnalysisPointer(const void *PI) override {
if (PI == &AliasAnalysis::ID)
return (AliasAnalysis*)this;
return this;

View File

@ -27,7 +27,7 @@ namespace llvm {
/// standard libm functions. The location that they may be interested in is
/// an abstract location that represents errno for the current target. In
/// this case, a location for errno is anything such that the predicate
/// returns true. On Mac OS/X, this predicate would return true if the
/// returns true. On Mac OS X, this predicate would return true if the
/// pointer is the result of a call to "__error()".
///
/// Locations can also be defined in a constant-sensitive way. For example,
@ -130,7 +130,7 @@ namespace llvm {
mutable const LibCallLocationInfo *Locations;
mutable unsigned NumLocations;
public:
LibCallInfo() : Impl(0), Locations(0), NumLocations(0) {}
LibCallInfo() : Impl(nullptr), Locations(nullptr), NumLocations(0) {}
virtual ~LibCallInfo();
//===------------------------------------------------------------------===//

View File

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

View File

@ -33,8 +33,10 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/Instruction.h"
#include "llvm/Pass.h"
#include <algorithm>
@ -53,6 +55,7 @@ class Loop;
class MDNode;
class PHINode;
class raw_ostream;
template<class N> class DominatorTreeBase;
template<class N, class M> class LoopInfoBase;
template<class N, class M> class LoopBase;
@ -76,7 +79,7 @@ class LoopBase {
operator=(const LoopBase<BlockT, LoopT> &) LLVM_DELETED_FUNCTION;
public:
/// Loop ctor - This creates an empty loop.
LoopBase() : ParentLoop(0) {}
LoopBase() : ParentLoop(nullptr) {}
~LoopBase() {
for (size_t i = 0, e = SubLoops.size(); i != e; ++i)
delete SubLoops[i];
@ -103,7 +106,7 @@ class LoopBase {
///
bool contains(const LoopT *L) const {
if (L == this) return true;
if (L == 0) return false;
if (!L) return false;
return contains(L->getParentLoop());
}
@ -228,6 +231,18 @@ class LoopBase {
/// A latch block is a block that contains a branch back to the header.
BlockT *getLoopLatch() const;
/// getLoopLatches - Return all loop latch blocks of this loop. A latch block
/// is a block that contains a branch back to the header.
void getLoopLatches(SmallVectorImpl<BlockT *> &LoopLatches) const {
BlockT *H = getHeader();
typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits;
for (typename InvBlockTraits::ChildIteratorType I =
InvBlockTraits::child_begin(H),
E = InvBlockTraits::child_end(H); I != E; ++I)
if (contains(*I))
LoopLatches.push_back(*I);
}
//===--------------------------------------------------------------------===//
// APIs for updating loop information after changing the CFG
//
@ -250,7 +265,7 @@ class LoopBase {
/// updates the loop depth of the new child.
///
void addChildLoop(LoopT *NewChild) {
assert(NewChild->ParentLoop == 0 && "NewChild already has a parent!");
assert(!NewChild->ParentLoop && "NewChild already has a parent!");
NewChild->ParentLoop = static_cast<LoopT *>(this);
SubLoops.push_back(NewChild);
}
@ -263,7 +278,7 @@ class LoopBase {
LoopT *Child = *I;
assert(Child->ParentLoop == this && "Child is not a child of this loop!");
SubLoops.erase(SubLoops.begin()+(I-begin()));
Child->ParentLoop = 0;
Child->ParentLoop = nullptr;
return Child;
}
@ -318,7 +333,7 @@ class LoopBase {
protected:
friend class LoopInfoBase<BlockT, LoopT>;
explicit LoopBase(BlockT *BB) : ParentLoop(0) {
explicit LoopBase(BlockT *BB) : ParentLoop(nullptr) {
Blocks.push_back(BB);
DenseBlockSet.insert(BB);
}
@ -357,7 +372,7 @@ class Loop : public LoopBase<BasicBlock, Loop> {
/// If null, the terminator of the loop preheader is used.
///
bool makeLoopInvariant(Value *V, bool &Changed,
Instruction *InsertPt = 0) const;
Instruction *InsertPt = nullptr) const;
/// makeLoopInvariant - If the given instruction is inside of the
/// loop and it can be hoisted, do so to make it trivially loop-invariant.
@ -369,7 +384,7 @@ class Loop : public LoopBase<BasicBlock, Loop> {
/// If null, the terminator of the loop preheader is used.
///
bool makeLoopInvariant(Instruction *I, bool &Changed,
Instruction *InsertPt = 0) const;
Instruction *InsertPt = nullptr) const;
/// getCanonicalInductionVariable - Check to see if the loop has a canonical
/// induction variable: an integer recurrence that starts at 0 and increments
@ -438,6 +453,31 @@ class Loop : public LoopBase<BasicBlock, Loop> {
void dump() const;
/// \brief Return the debug location of the start of this loop.
/// This looks for a BB terminating instruction with a known debug
/// location by looking at the preheader and header blocks. If it
/// cannot find a terminating instruction with location information,
/// it returns an unknown location.
DebugLoc getStartLoc() const {
DebugLoc StartLoc;
BasicBlock *HeadBB;
// Try the pre-header first.
if ((HeadBB = getLoopPreheader()) != nullptr) {
StartLoc = HeadBB->getTerminator()->getDebugLoc();
if (!StartLoc.isUnknown())
return StartLoc;
}
// If we have no pre-header or there are no instructions with debug
// info in it, try the header.
HeadBB = getHeader();
if (HeadBB)
StartLoc = HeadBB->getTerminator()->getDebugLoc();
return StartLoc;
}
private:
friend class LoopInfoBase<BasicBlock, Loop>;
explicit Loop(BasicBlock *BB) : LoopBase<BasicBlock, Loop>(BB) {}
@ -516,7 +556,7 @@ class LoopInfoBase {
LoopT *removeLoop(iterator I) {
assert(I != end() && "Cannot remove end iterator!");
LoopT *L = *I;
assert(L->getParentLoop() == 0 && "Not a top-level loop!");
assert(!L->getParentLoop() && "Not a top-level loop!");
TopLevelLoops.erase(TopLevelLoops.begin() + (I-begin()));
return L;
}
@ -540,14 +580,14 @@ class LoopInfoBase {
std::find(TopLevelLoops.begin(), TopLevelLoops.end(), OldLoop);
assert(I != TopLevelLoops.end() && "Old loop not at top level!");
*I = NewLoop;
assert(NewLoop->ParentLoop == 0 && OldLoop->ParentLoop == 0 &&
assert(!NewLoop->ParentLoop && !OldLoop->ParentLoop &&
"Loops already embedded into a subloop!");
}
/// addTopLevelLoop - This adds the specified loop to the collection of
/// top-level loops.
void addTopLevelLoop(LoopT *New) {
assert(New->getParentLoop() == 0 && "Loop already in subloop!");
assert(!New->getParentLoop() && "Loop already in subloop!");
TopLevelLoops.push_back(New);
}
@ -568,7 +608,7 @@ class LoopInfoBase {
static bool isNotAlreadyContainedIn(const LoopT *SubLoop,
const LoopT *ParentLoop) {
if (SubLoop == 0) return true;
if (!SubLoop) return true;
if (SubLoop == ParentLoop) return false;
return isNotAlreadyContainedIn(SubLoop->getParentLoop(), ParentLoop);
}
@ -639,15 +679,15 @@ class LoopInfo : public FunctionPass {
/// runOnFunction - Calculate the natural loop information.
///
virtual bool runOnFunction(Function &F);
bool runOnFunction(Function &F) override;
virtual void verifyAnalysis() const;
void verifyAnalysis() const override;
virtual void releaseMemory() { LI.releaseMemory(); }
void releaseMemory() override { LI.releaseMemory(); }
virtual void print(raw_ostream &O, const Module* M = 0) const;
void print(raw_ostream &O, const Module* M = nullptr) const override;
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
void getAnalysisUsage(AnalysisUsage &AU) const override;
/// removeLoop - This removes the specified top-level loop from this loop info
/// object. The loop is not deleted, as it will presumably be inserted into

View File

@ -15,9 +15,11 @@
#ifndef LLVM_ANALYSIS_LOOPINFOIMPL_H
#define LLVM_ANALYSIS_LOOPINFOIMPL_H
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/IR/Dominators.h"
namespace llvm {
@ -51,7 +53,7 @@ BlockT *LoopBase<BlockT, LoopT>::getExitingBlock() const {
getExitingBlocks(ExitingBlocks);
if (ExitingBlocks.size() == 1)
return ExitingBlocks[0];
return 0;
return nullptr;
}
/// getExitBlocks - Return all of the successor blocks of this loop. These
@ -78,7 +80,7 @@ BlockT *LoopBase<BlockT, LoopT>::getExitBlock() const {
getExitBlocks(ExitBlocks);
if (ExitBlocks.size() == 1)
return ExitBlocks[0];
return 0;
return nullptr;
}
/// getExitEdges - Return all pairs of (_inside_block_,_outside_block_).
@ -106,14 +108,14 @@ template<class BlockT, class LoopT>
BlockT *LoopBase<BlockT, LoopT>::getLoopPreheader() const {
// Keep track of nodes outside the loop branching to the header...
BlockT *Out = getLoopPredecessor();
if (!Out) return 0;
if (!Out) return nullptr;
// Make sure there is only one exit out of the preheader.
typedef GraphTraits<BlockT*> BlockTraits;
typename BlockTraits::ChildIteratorType SI = BlockTraits::child_begin(Out);
++SI;
if (SI != BlockTraits::child_end(Out))
return 0; // Multiple exits from the block, must not be a preheader.
return nullptr; // Multiple exits from the block, must not be a preheader.
// The predecessor has exactly one successor, so it is a preheader.
return Out;
@ -127,7 +129,7 @@ BlockT *LoopBase<BlockT, LoopT>::getLoopPreheader() const {
template<class BlockT, class LoopT>
BlockT *LoopBase<BlockT, LoopT>::getLoopPredecessor() const {
// Keep track of nodes outside the loop branching to the header...
BlockT *Out = 0;
BlockT *Out = nullptr;
// Loop over the predecessors of the header node...
BlockT *Header = getHeader();
@ -138,7 +140,7 @@ BlockT *LoopBase<BlockT, LoopT>::getLoopPredecessor() const {
typename InvBlockTraits::NodeType *N = *PI;
if (!contains(N)) { // If the block is not in the loop...
if (Out && Out != N)
return 0; // Multiple predecessors outside the loop
return nullptr; // Multiple predecessors outside the loop
Out = N;
}
}
@ -158,11 +160,11 @@ BlockT *LoopBase<BlockT, LoopT>::getLoopLatch() const {
InvBlockTraits::child_begin(Header);
typename InvBlockTraits::ChildIteratorType PE =
InvBlockTraits::child_end(Header);
BlockT *Latch = 0;
BlockT *Latch = nullptr;
for (; PI != PE; ++PI) {
typename InvBlockTraits::NodeType *N = *PI;
if (contains(N)) {
if (Latch) return 0;
if (Latch) return nullptr;
Latch = N;
}
}
@ -186,7 +188,7 @@ addBasicBlockToLoop(BlockT *NewBB, LoopInfoBase<BlockT, LoopT> &LIB) {
assert((Blocks.empty() || LIB[getHeader()] == this) &&
"Incorrect LI specified for this loop!");
assert(NewBB && "Cannot add a null basic block to the loop!");
assert(LIB[NewBB] == 0 && "BasicBlock already in the loop!");
assert(!LIB[NewBB] && "BasicBlock already in the loop!");
LoopT *L = static_cast<LoopT *>(this);
@ -208,12 +210,12 @@ template<class BlockT, class LoopT>
void LoopBase<BlockT, LoopT>::
replaceChildLoopWith(LoopT *OldChild, LoopT *NewChild) {
assert(OldChild->ParentLoop == this && "This loop is already broken!");
assert(NewChild->ParentLoop == 0 && "NewChild already has a parent!");
assert(!NewChild->ParentLoop && "NewChild already has a parent!");
typename std::vector<LoopT *>::iterator I =
std::find(SubLoops.begin(), SubLoops.end(), OldChild);
assert(I != SubLoops.end() && "OldChild not in loop!");
*I = NewChild;
OldChild->ParentLoop = 0;
OldChild->ParentLoop = nullptr;
NewChild->ParentLoop = static_cast<LoopT *>(this);
}
@ -268,11 +270,10 @@ void LoopBase<BlockT, LoopT>::verifyLoop() const {
// though it is permitted if the predecessor is not itself actually
// reachable.
BlockT *EntryBB = BB->getParent()->begin();
for (df_iterator<BlockT *> NI = df_begin(EntryBB),
NE = df_end(EntryBB); NI != NE; ++NI)
for (unsigned i = 0, e = OutsideLoopPreds.size(); i != e; ++i)
assert(*NI != OutsideLoopPreds[i] &&
"Loop has multiple entry points!");
for (BlockT *CB : depth_first(EntryBB))
for (unsigned i = 0, e = OutsideLoopPreds.size(); i != e; ++i)
assert(CB != OutsideLoopPreds[i] &&
"Loop has multiple entry points!");
}
assert(HasInsideLoopPreds && "Loop block has no in-loop predecessors!");
assert(HasInsideLoopSuccs && "Loop block has no in-loop successors!");
@ -322,7 +323,7 @@ void LoopBase<BlockT, LoopT>::print(raw_ostream &OS, unsigned Depth) const {
for (unsigned i = 0; i < getBlocks().size(); ++i) {
if (i) OS << ",";
BlockT *BB = getBlocks()[i];
WriteAsOperand(OS, BB, false);
BB->printAsOperand(OS, false);
if (BB == getHeader()) OS << "<header>";
if (BB == getLoopLatch()) OS << "<latch>";
if (isLoopExiting(BB)) OS << "<exiting>";

View File

@ -32,7 +32,8 @@ class LoopPass : public Pass {
/// getPrinterPass - Get a pass to print the function corresponding
/// to a Loop.
Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const;
Pass *createPrinterPass(raw_ostream &O,
const std::string &Banner) const override;
// runOnLoop - This method should be implemented by the subclass to perform
// whatever action is necessary for the specified Loop.
@ -56,14 +57,13 @@ class LoopPass : public Pass {
// LPPassManager passes. In such case, pop LPPassManager from the
// stack. This will force assignPassManager() to create new
// LPPassManger as expected.
void preparePassManager(PMStack &PMS);
void preparePassManager(PMStack &PMS) override;
/// Assign pass manager to manage this pass
virtual void assignPassManager(PMStack &PMS,
PassManagerType PMT);
void assignPassManager(PMStack &PMS, PassManagerType PMT) override;
/// Return what kind of Pass Manager can manage this pass.
virtual PassManagerType getPotentialPassManagerType() const {
PassManagerType getPotentialPassManagerType() const override {
return PMT_LoopPassManager;
}
@ -81,6 +81,11 @@ class LoopPass : public Pass {
/// deleteAnalysisValue - Delete analysis info associated with value V.
virtual void deleteAnalysisValue(Value *V, Loop *L) {}
protected:
/// skipOptnoneFunction - Containing function has Attribute::OptimizeNone
/// and most transformation passes should skip it.
bool skipOptnoneFunction(const Loop *L) const;
};
class LPPassManager : public FunctionPass, public PMDataManager {
@ -90,21 +95,21 @@ class LPPassManager : public FunctionPass, public PMDataManager {
/// run - Execute all of the passes scheduled for execution. Keep track of
/// whether any of the passes modifies the module, and if so, return true.
bool runOnFunction(Function &F);
bool runOnFunction(Function &F) override;
/// Pass Manager itself does not invalidate any analysis info.
// LPPassManager needs LoopInfo.
void getAnalysisUsage(AnalysisUsage &Info) const;
void getAnalysisUsage(AnalysisUsage &Info) const override;
virtual const char *getPassName() const {
const char *getPassName() const override {
return "Loop Pass Manager";
}
virtual PMDataManager *getAsPMDataManager() { return this; }
virtual Pass *getAsPass() { return this; }
PMDataManager *getAsPMDataManager() override { return this; }
Pass *getAsPass() override { return this; }
/// Print passes managed by this manager
void dumpPassStructure(unsigned Offset);
void dumpPassStructure(unsigned Offset) override;
LoopPass *getContainedPass(unsigned N) {
assert(N < PassVector.size() && "Pass number out of range!");
@ -112,7 +117,7 @@ class LPPassManager : public FunctionPass, public PMDataManager {
return LP;
}
virtual PassManagerType getPassManagerType() const {
PassManagerType getPassManagerType() const override {
return PMT_LoopPassManager;
}

View File

@ -17,12 +17,12 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/TargetFolder.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstVisitor.h"
#include "llvm/IR/Operator.h"
#include "llvm/InstVisitor.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/TargetFolder.h"
#include "llvm/Support/ValueHandle.h"
namespace llvm {
class CallInst;
@ -190,6 +190,8 @@ class ObjectSizeOffsetVisitor
return knownSize(SizeOffset) && knownOffset(SizeOffset);
}
// These are "private", except they can't actually be made private. Only
// compute() should be used by external users.
SizeOffsetType visitAllocaInst(AllocaInst &I);
SizeOffsetType visitArgument(Argument &A);
SizeOffsetType visitCallSite(CallSite CS);
@ -231,7 +233,7 @@ class ObjectSizeOffsetEvaluator
bool RoundToAlign;
SizeOffsetEvalType unknown() {
return std::make_pair((Value*)0, (Value*)0);
return std::make_pair(nullptr, nullptr);
}
SizeOffsetEvalType compute_(Value *V);
@ -256,6 +258,7 @@ class ObjectSizeOffsetEvaluator
return knownSize(SizeOffset) && knownOffset(SizeOffset);
}
// The individual instruction visitors should be treated as private.
SizeOffsetEvalType visitAllocaInst(AllocaInst &I);
SizeOffsetEvalType visitCallSite(CallSite CS);
SizeOffsetEvalType visitExtractElementInst(ExtractElementInst &I);

View File

@ -15,13 +15,12 @@
#define LLVM_ANALYSIS_MEMORYDEPENDENCEANALYSIS_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Pass.h"
#include "llvm/Support/ValueHandle.h"
namespace llvm {
class Function;
@ -98,7 +97,7 @@ namespace llvm {
PairTy Value;
explicit MemDepResult(PairTy V) : Value(V) {}
public:
MemDepResult() : Value(0, Invalid) {}
MemDepResult() : Value(nullptr, Invalid) {}
/// get methods: These are static ctor methods for creating various
/// MemDepResult kinds.
@ -156,7 +155,7 @@ namespace llvm {
/// getInst() - If this is a normal dependency, return the instruction that
/// is depended on. Otherwise, return null.
Instruction *getInst() const {
if (Value.getInt() == Other) return NULL;
if (Value.getInt() == Other) return nullptr;
return Value.getPointer();
}
@ -286,7 +285,8 @@ namespace llvm {
/// pointer. May be null if there are no tags or conflicting tags.
const MDNode *TBAATag;
NonLocalPointerInfo() : Size(AliasAnalysis::UnknownSize), TBAATag(0) {}
NonLocalPointerInfo()
: Size(AliasAnalysis::UnknownSize), TBAATag(nullptr) {}
};
/// CachedNonLocalPointerInfo - This map stores the cached results of doing
@ -323,24 +323,25 @@ namespace llvm {
/// Current AA implementation, just a cache.
AliasAnalysis *AA;
DataLayout *TD;
const DataLayout *DL;
DominatorTree *DT;
OwningPtr<PredIteratorCache> PredCache;
std::unique_ptr<PredIteratorCache> PredCache;
public:
MemoryDependenceAnalysis();
~MemoryDependenceAnalysis();
static char ID;
/// Pass Implementation stuff. This doesn't do any analysis eagerly.
bool runOnFunction(Function &);
bool runOnFunction(Function &) override;
/// Clean up memory in between runs
void releaseMemory();
void releaseMemory() override;
/// getAnalysisUsage - Does not modify anything. It uses Value Numbering
/// and Alias Analysis.
///
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
void getAnalysisUsage(AnalysisUsage &AU) const override;
/// getDependency - Return the instruction on which a memory operation
/// depends. See the class comment for more details. It is illegal to call
@ -401,7 +402,7 @@ namespace llvm {
bool isLoad,
BasicBlock::iterator ScanIt,
BasicBlock *BB,
Instruction *QueryInst = 0);
Instruction *QueryInst = nullptr);
/// getLoadLoadClobberFullWidthSize - This is a little bit of analysis that
@ -415,7 +416,7 @@ namespace llvm {
int64_t MemLocOffs,
unsigned MemLocSize,
const LoadInst *LI,
const DataLayout &TD);
const DataLayout &DL);
private:
MemDepResult getCallSiteDependencyFrom(CallSite C, bool isReadOnlyCall,

View File

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

View File

@ -93,27 +93,6 @@ namespace llvm {
//
ImmutablePass *createObjCARCAliasAnalysisPass();
//===--------------------------------------------------------------------===//
//
// createDSAAPass - This pass implements simple context sensitive alias
// analysis.
//
ModulePass *createDSAAPass();
//===--------------------------------------------------------------------===//
//
// createDSOptPass - This pass uses DSA to do a series of simple
// optimizations.
//
ModulePass *createDSOptPass();
//===--------------------------------------------------------------------===//
//
// createSteensgaardPass - This pass uses the data structure graphs to do a
// simple context insensitive alias analysis.
//
ModulePass *createSteensgaardPass();
//===--------------------------------------------------------------------===//
//
/// createLazyValueInfoPass - This creates an instance of the LazyValueInfo
@ -163,6 +142,10 @@ namespace llvm {
// information and prints it with -analyze.
//
FunctionPass *createMemDepPrinter();
// createJumpInstrTableInfoPass - This creates a pass that stores information
// about the jump tables created by JumpInstrTables
ImmutablePass *createJumpInstrTableInfoPass();
}
#endif

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