Upgrade our copy of clang, llvm and lldb to 3.5.0 release.

Please note that this version now requires C++11 support to build; see
UPDATING for more information.

Release notes for llvm and clang can be found here:
<http://llvm.org/releases/3.5.0/docs/ReleaseNotes.html>
<http://llvm.org/releases/3.5.0/tools/clang/docs/ReleaseNotes.html>

Thanks to Ed Maste, Roman Divacky, Andrew Turner, Justin Hibbits and
Antoine Brodin for their invaluable help with this import.

Approved by:	portmgr (antoine)
MFC after:	1 month
This commit is contained in:
Dimitry Andric 2014-12-31 20:31:32 +00:00
commit 44b6c81fe4
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=276479
3960 changed files with 454898 additions and 232291 deletions

View File

@ -38,6 +38,42 @@
# xargs -n1 | sort | uniq -d;
# done
# 20141231: new clang import which bumps version from 3.4.1 to 3.5.0.
OLD_FILES+=usr/include/clang/3.4.1/__wmmintrin_aes.h
OLD_FILES+=usr/include/clang/3.4.1/__wmmintrin_pclmul.h
OLD_FILES+=usr/include/clang/3.4.1/altivec.h
OLD_FILES+=usr/include/clang/3.4.1/ammintrin.h
OLD_FILES+=usr/include/clang/3.4.1/arm_neon.h
OLD_FILES+=usr/include/clang/3.4.1/avx2intrin.h
OLD_FILES+=usr/include/clang/3.4.1/avxintrin.h
OLD_FILES+=usr/include/clang/3.4.1/bmi2intrin.h
OLD_FILES+=usr/include/clang/3.4.1/bmiintrin.h
OLD_FILES+=usr/include/clang/3.4.1/cpuid.h
OLD_FILES+=usr/include/clang/3.4.1/emmintrin.h
OLD_FILES+=usr/include/clang/3.4.1/f16cintrin.h
OLD_FILES+=usr/include/clang/3.4.1/fma4intrin.h
OLD_FILES+=usr/include/clang/3.4.1/fmaintrin.h
OLD_FILES+=usr/include/clang/3.4.1/immintrin.h
OLD_FILES+=usr/include/clang/3.4.1/lzcntintrin.h
OLD_FILES+=usr/include/clang/3.4.1/mm3dnow.h
OLD_FILES+=usr/include/clang/3.4.1/mm_malloc.h
OLD_FILES+=usr/include/clang/3.4.1/mmintrin.h
OLD_FILES+=usr/include/clang/3.4.1/module.map
OLD_FILES+=usr/include/clang/3.4.1/nmmintrin.h
OLD_FILES+=usr/include/clang/3.4.1/pmmintrin.h
OLD_FILES+=usr/include/clang/3.4.1/popcntintrin.h
OLD_FILES+=usr/include/clang/3.4.1/prfchwintrin.h
OLD_FILES+=usr/include/clang/3.4.1/rdseedintrin.h
OLD_FILES+=usr/include/clang/3.4.1/rtmintrin.h
OLD_FILES+=usr/include/clang/3.4.1/shaintrin.h
OLD_FILES+=usr/include/clang/3.4.1/smmintrin.h
OLD_FILES+=usr/include/clang/3.4.1/tbmintrin.h
OLD_FILES+=usr/include/clang/3.4.1/tmmintrin.h
OLD_FILES+=usr/include/clang/3.4.1/wmmintrin.h
OLD_FILES+=usr/include/clang/3.4.1/x86intrin.h
OLD_FILES+=usr/include/clang/3.4.1/xmmintrin.h
OLD_FILES+=usr/include/clang/3.4.1/xopintrin.h
OLD_DIRS+=usr/include/clang/3.4.1
# 20141226: Remove gpib/ieee488
OLD_FILES+=usr/include/dev/ieee488/ibfoo_int.h
OLD_FILES+=usr/include/dev/ieee488/tnt4882.h

View File

@ -31,6 +31,68 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 11.x IS SLOW:
disable the most expensive debugging functionality run
"ln -s 'abort:false,junk:false' /etc/malloc.conf".)
20141231:
Clang, llvm and lldb have been upgraded to 3.5.0 release.
As of this release, a prerequisite for building clang, llvm and lldb is
a C++11 capable compiler and C++11 standard library. This means that to
be able to successfully build the cross-tools stage of buildworld, with
clang as the bootstrap compiler, your system compiler or cross compiler
should either be clang 3.3 or later, or gcc 4.8 or later, and your
system C++ library should be libc++, or libdstdc++ from gcc 4.8 or
later.
On any standard FreeBSD 10.x or 11.x installation, where clang and
libc++ are on by default (that is, on x86 or arm), this should work out
of the box.
On 9.x installations where clang is enabled by default, e.g. on x86 and
powerpc, libc++ will not be enabled by default, so libc++ should be
built (with clang) and installed first. If both clang and libc++ are
missing, build clang first, then use it to build libc++.
On 8.x and earlier installations, upgrade to 9.x first, and then follow
the instructions for 9.x above.
Sparc64 and mips users are unaffected, as they still use gcc 4.2.1 by
default, and do not build clang.
Many embedded systems are resource constrained, and will not be able to
build clang in a reasonable time, or in some cases at all. In those
cases, cross building bootable systems on amd64 is a workaround.
This new version of clang introduces a number of new warnings, of which
the following are most likely to appear:
-Wabsolute-value
This warns in two cases, for both C and C++:
* When the code is trying to take the absolute value of an unsigned
quantity, which is effectively a no-op, and almost never what was
intended. The code should be fixed, if at all possible. If you are
sure that the unsigned quantity can be safely cast to signed, without
loss of information or undefined behavior, you can add an explicit
cast, or disable the warning.
* When the code is trying to take an absolute value, but the called
abs() variant is for the wrong type, which can lead to truncation.
If you want to disable the warning instead of fixing the code, please
make sure that truncation will not occur, or it might lead to unwanted
side-effects.
-Wtautological-undefined-compare and
-Wundefined-bool-conversion
These warn when C++ code is trying to compare 'this' against NULL, while
'this' should never be NULL in well-defined C++ code. However, there is
some legacy (pre C++11) code out there, which actively abuses this
feature, which was less strictly defined in previous C++ versions.
Squid and openjdk do this, for example. The warning can be turned off
for C++98 and earlier, but compiling the code in C++11 mode might result
in unexpected behavior; for example, the parts of the program that are
unreachable could be optimized away.
20141222:
The old NFS client and server (kernel options NFSCLIENT, NFSSERVER)
kernel sources have been removed. The .h files remain, since some

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,

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