Update llvm to release_39 branch r276489, and resolve conflicts.

This commit is contained in:
Dimitry Andric 2016-08-16 21:02:59 +00:00
commit 3ca95b0202
2545 changed files with 255938 additions and 120717 deletions

View File

@ -4,7 +4,7 @@ LLVM Release License
University of Illinois/NCSA
Open Source License
Copyright (c) 2003-2015 University of Illinois at Urbana-Champaign.
Copyright (c) 2003-2016 University of Illinois at Urbana-Champaign.
All rights reserved.
Developed by:

View File

@ -94,6 +94,8 @@ typedef enum {
LLVMJumpTableAttribute = 1ULL << 45,
LLVMConvergentAttribute = 1ULL << 46,
LLVMSafeStackAttribute = 1ULL << 47,
LLVMSwiftSelfAttribute = 1ULL << 48,
LLVMSwiftErrorAttribute = 1ULL << 49,
*/
} LLVMAttribute;
@ -245,6 +247,38 @@ typedef enum {
LLVMX86FastcallCallConv = 65
} LLVMCallConv;
typedef enum {
LLVMArgumentValueKind,
LLVMBasicBlockValueKind,
LLVMMemoryUseValueKind,
LLVMMemoryDefValueKind,
LLVMMemoryPhiValueKind,
LLVMFunctionValueKind,
LLVMGlobalAliasValueKind,
LLVMGlobalIFuncValueKind,
LLVMGlobalVariableValueKind,
LLVMBlockAddressValueKind,
LLVMConstantExprValueKind,
LLVMConstantArrayValueKind,
LLVMConstantStructValueKind,
LLVMConstantVectorValueKind,
LLVMUndefValueValueKind,
LLVMConstantAggregateZeroValueKind,
LLVMConstantDataArrayValueKind,
LLVMConstantDataVectorValueKind,
LLVMConstantIntValueKind,
LLVMConstantFPValueKind,
LLVMConstantPointerNullValueKind,
LLVMConstantTokenNoneValueKind,
LLVMMetadataAsValueValueKind,
LLVMInlineAsmValueKind,
LLVMInstructionValueKind,
} LLVMValueKind;
typedef enum {
LLVMIntEQ = 32, /**< equal */
LLVMIntNE, /**< not equal */
@ -346,6 +380,20 @@ typedef enum {
LLVMDSNote
} LLVMDiagnosticSeverity;
/**
* Attribute index are either LLVMAttributeReturnIndex,
* LLVMAttributeFunctionIndex or a parameter number from 1 to N.
*/
enum {
LLVMAttributeReturnIndex = 0U,
// ISO C restricts enumerator values to range of 'int'
// (4294967295 is too large)
// LLVMAttributeFunctionIndex = ~0U,
LLVMAttributeFunctionIndex = -1,
};
typedef unsigned LLVMAttributeIndex;
/**
* @}
*/
@ -397,6 +445,16 @@ void LLVMContextSetDiagnosticHandler(LLVMContextRef C,
LLVMDiagnosticHandler Handler,
void *DiagnosticContext);
/**
* Get the diagnostic handler of this context.
*/
LLVMDiagnosticHandler LLVMContextGetDiagnosticHandler(LLVMContextRef C);
/**
* Get the diagnostic context of this context.
*/
void *LLVMContextGetDiagnosticContext(LLVMContextRef C);
/**
* Set the yield callback function for this context.
*
@ -428,9 +486,63 @@ char *LLVMGetDiagInfoDescription(LLVMDiagnosticInfoRef DI);
*/
LLVMDiagnosticSeverity LLVMGetDiagInfoSeverity(LLVMDiagnosticInfoRef DI);
unsigned LLVMGetMDKindIDInContext(LLVMContextRef C, const char* Name,
unsigned LLVMGetMDKindIDInContext(LLVMContextRef C, const char *Name,
unsigned SLen);
unsigned LLVMGetMDKindID(const char* Name, unsigned SLen);
unsigned LLVMGetMDKindID(const char *Name, unsigned SLen);
/**
* Return an unique id given the name of a enum attribute,
* or 0 if no attribute by that name exists.
*
* See http://llvm.org/docs/LangRef.html#parameter-attributes
* and http://llvm.org/docs/LangRef.html#function-attributes
* for the list of available attributes.
*
* NB: Attribute names and/or id are subject to change without
* going through the C API deprecation cycle.
*/
unsigned LLVMGetEnumAttributeKindForName(const char *Name, size_t SLen);
unsigned LLVMGetLastEnumAttributeKind(void);
/**
* Create an enum attribute.
*/
LLVMAttributeRef LLVMCreateEnumAttribute(LLVMContextRef C, unsigned KindID,
uint64_t Val);
/**
* Get the unique id corresponding to the enum attribute
* passed as argument.
*/
unsigned LLVMGetEnumAttributeKind(LLVMAttributeRef A);
/**
* Get the enum attribute's value. 0 is returned if none exists.
*/
uint64_t LLVMGetEnumAttributeValue(LLVMAttributeRef A);
/**
* Create a string attribute.
*/
LLVMAttributeRef LLVMCreateStringAttribute(LLVMContextRef C,
const char *K, unsigned KLength,
const char *V, unsigned VLength);
/**
* Get the string attribute's kind.
*/
const char *LLVMGetStringAttributeKind(LLVMAttributeRef A, unsigned *Length);
/**
* Get the string attribute's value.
*/
const char *LLVMGetStringAttributeValue(LLVMAttributeRef A, unsigned *Length);
/**
* Check for the different types of attributes.
*/
LLVMBool LLVMIsEnumAttribute(LLVMAttributeRef A);
LLVMBool LLVMIsStringAttribute(LLVMAttributeRef A);
/**
* @}
@ -478,11 +590,36 @@ LLVMModuleRef LLVMCloneModule(LLVMModuleRef M);
*/
void LLVMDisposeModule(LLVMModuleRef M);
/**
* Obtain the identifier of a module.
*
* @param M Module to obtain identifier of
* @param Len Out parameter which holds the length of the returned string.
* @return The identifier of M.
* @see Module::getModuleIdentifier()
*/
const char *LLVMGetModuleIdentifier(LLVMModuleRef M, size_t *Len);
/**
* Set the identifier of a module to a string Ident with length Len.
*
* @param M The module to set identifier
* @param Ident The string to set M's identifier to
* @param Len Length of Ident
* @see Module::setModuleIdentifier()
*/
void LLVMSetModuleIdentifier(LLVMModuleRef M, const char *Ident, size_t Len);
/**
* Obtain the data layout for a module.
*
* @see Module::getDataLayout()
* @see Module::getDataLayoutStr()
*
* LLVMGetDataLayout is DEPRECATED, as the name is not only incorrect,
* but match the name of another method on the module. Prefer the use
* of LLVMGetDataLayoutStr, which is not ambiguous.
*/
const char *LLVMGetDataLayoutStr(LLVMModuleRef M);
const char *LLVMGetDataLayout(LLVMModuleRef M);
/**
@ -490,7 +627,7 @@ const char *LLVMGetDataLayout(LLVMModuleRef M);
*
* @see Module::setDataLayout()
*/
void LLVMSetDataLayout(LLVMModuleRef M, const char *Triple);
void LLVMSetDataLayout(LLVMModuleRef M, const char *DataLayoutStr);
/**
* Obtain the target triple for a module.
@ -554,7 +691,7 @@ LLVMTypeRef LLVMGetTypeByName(LLVMModuleRef M, const char *Name);
*
* @see llvm::Module::getNamedMetadata()
*/
unsigned LLVMGetNamedMetadataNumOperands(LLVMModuleRef M, const char* name);
unsigned LLVMGetNamedMetadataNumOperands(LLVMModuleRef M, const char *Name);
/**
* Obtain the named metadata operands for a module.
@ -567,7 +704,8 @@ unsigned LLVMGetNamedMetadataNumOperands(LLVMModuleRef M, const char* name);
* @see llvm::Module::getNamedMetadata()
* @see llvm::MDNode::getOperand()
*/
void LLVMGetNamedMetadataOperands(LLVMModuleRef M, const char* name, LLVMValueRef *Dest);
void LLVMGetNamedMetadataOperands(LLVMModuleRef M, const char *Name,
LLVMValueRef *Dest);
/**
* Add an operand to named metadata.
@ -575,7 +713,7 @@ void LLVMGetNamedMetadataOperands(LLVMModuleRef M, const char* name, LLVMValueRe
* @see llvm::Module::getNamedMetadata()
* @see llvm::MDNode::addOperand()
*/
void LLVMAddNamedMetadataOperand(LLVMModuleRef M, const char* name,
void LLVMAddNamedMetadataOperand(LLVMModuleRef M, const char *Name,
LLVMValueRef Val);
/**
@ -1163,6 +1301,13 @@ LLVMTypeRef LLVMX86MMXType(void);
*/
LLVMTypeRef LLVMTypeOf(LLVMValueRef Val);
/**
* Obtain the enumerated type of a Value instance.
*
* @see llvm::Value::getValueID()
*/
LLVMValueKind LLVMGetValueKind(LLVMValueRef Val);
/**
* Obtain the string name of a value.
*
@ -1200,7 +1345,7 @@ char *LLVMPrintValueToString(LLVMValueRef Val);
void LLVMReplaceAllUsesWith(LLVMValueRef OldVal, LLVMValueRef NewVal);
/**
* Determine whether the specified constant instance is constant.
* Determine whether the specified value instance is constant.
*/
LLVMBool LLVMIsConstant(LLVMValueRef Val);
@ -1520,7 +1665,7 @@ LLVMBool LLVMIsConstantString(LLVMValueRef c);
*
* @see ConstantDataSequential::getAsString()
*/
const char *LLVMGetAsString(LLVMValueRef c, size_t* out);
const char *LLVMGetAsString(LLVMValueRef c, size_t *Length);
/**
* Create an anonymous ConstantStruct with the specified values.
@ -1564,7 +1709,7 @@ LLVMValueRef LLVMConstNamedStruct(LLVMTypeRef StructTy,
*
* @see ConstantDataSequential::getElementAsConstant()
*/
LLVMValueRef LLVMGetElementAsConstant(LLVMValueRef c, unsigned idx);
LLVMValueRef LLVMGetElementAsConstant(LLVMValueRef C, unsigned idx);
/**
* Create a ConstantVector from values.
@ -1727,8 +1872,8 @@ unsigned LLVMGetAlignment(LLVMValueRef V);
void LLVMSetAlignment(LLVMValueRef V, unsigned Bytes);
/**
* @}
*/
* @}
*/
/**
* @defgroup LLVMCoreValueConstantGlobalVariable Global Variables
@ -1798,6 +1943,13 @@ LLVMValueRef LLVMAddAlias(LLVMModuleRef M, LLVMTypeRef Ty, LLVMValueRef Aliasee,
*/
void LLVMDeleteFunction(LLVMValueRef Fn);
/**
* Check whether the given function has a personality function.
*
* @see llvm::Function::hasPersonalityFn()
*/
LLVMBool LLVMHasPersonalityFn(LLVMValueRef Fn);
/**
* Obtain the personality function attached to the function.
*
@ -1860,6 +2012,19 @@ void LLVMSetGC(LLVMValueRef Fn, const char *Name);
*/
void LLVMAddFunctionAttr(LLVMValueRef Fn, LLVMAttribute PA);
void LLVMAddAttributeAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx,
LLVMAttributeRef A);
LLVMAttributeRef LLVMGetEnumAttributeAtIndex(LLVMValueRef F,
LLVMAttributeIndex Idx,
unsigned KindID);
LLVMAttributeRef LLVMGetStringAttributeAtIndex(LLVMValueRef F,
LLVMAttributeIndex Idx,
const char *K, unsigned KLen);
void LLVMRemoveEnumAttributeAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx,
unsigned KindID);
void LLVMRemoveStringAttributeAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx,
const char *K, unsigned KLen);
/**
* Add a target-dependent attribute to a function
* @see llvm::AttrBuilder::addAttribute()
@ -1985,7 +2150,7 @@ LLVMAttribute LLVMGetAttribute(LLVMValueRef Arg);
* @see llvm::Argument::addAttr()
* @see llvm::AttrBuilder::addAlignmentAttr()
*/
void LLVMSetParamAlignment(LLVMValueRef Arg, unsigned align);
void LLVMSetParamAlignment(LLVMValueRef Arg, unsigned Align);
/**
* @}
@ -2043,10 +2208,10 @@ LLVMValueRef LLVMMDNode(LLVMValueRef *Vals, unsigned Count);
* Obtain the underlying string from a MDString value.
*
* @param V Instance to obtain string from.
* @param Len Memory address which will hold length of returned string.
* @param Length Memory address which will hold length of returned string.
* @return String data in MDString.
*/
const char *LLVMGetMDString(LLVMValueRef V, unsigned* Len);
const char *LLVMGetMDString(LLVMValueRef V, unsigned *Length);
/**
* Obtain the number of operands from an MDNode value.
@ -2105,6 +2270,11 @@ LLVMBool LLVMValueIsBasicBlock(LLVMValueRef Val);
*/
LLVMBasicBlockRef LLVMValueAsBasicBlock(LLVMValueRef Val);
/**
* Obtain the string name of a basic block.
*/
const char *LLVMGetBasicBlockName(LLVMBasicBlockRef BB);
/**
* Obtain the function to which a basic block belongs.
*
@ -2323,6 +2493,16 @@ LLVMValueRef LLVMGetNextInstruction(LLVMValueRef Inst);
*/
LLVMValueRef LLVMGetPreviousInstruction(LLVMValueRef Inst);
/**
* Remove and delete an instruction.
*
* The instruction specified is removed from its containing building
* block but is kept alive.
*
* @see llvm::Instruction::removeFromParent()
*/
void LLVMInstructionRemoveFromParent(LLVMValueRef Inst);
/**
* Remove and delete an instruction.
*
@ -2380,6 +2560,17 @@ LLVMValueRef LLVMInstructionClone(LLVMValueRef Inst);
* @{
*/
/**
* Obtain the argument count for a call instruction.
*
* This expects an LLVMValueRef that corresponds to a llvm::CallInst or
* llvm::InvokeInst.
*
* @see llvm::CallInst::getNumArgOperands()
* @see llvm::InvokeInst::getNumArgOperands()
*/
unsigned LLVMGetNumArgOperands(LLVMValueRef Instr);
/**
* Set the calling convention for a call instruction.
*
@ -2401,12 +2592,35 @@ void LLVMSetInstructionCallConv(LLVMValueRef Instr, unsigned CC);
*/
unsigned LLVMGetInstructionCallConv(LLVMValueRef Instr);
void LLVMAddInstrAttribute(LLVMValueRef Instr, unsigned index, LLVMAttribute);
void LLVMRemoveInstrAttribute(LLVMValueRef Instr, unsigned index,
LLVMAttribute);
void LLVMSetInstrParamAlignment(LLVMValueRef Instr, unsigned index,
unsigned align);
unsigned Align);
void LLVMAddCallSiteAttribute(LLVMValueRef C, LLVMAttributeIndex Idx,
LLVMAttributeRef A);
LLVMAttributeRef LLVMGetCallSiteEnumAttribute(LLVMValueRef C,
LLVMAttributeIndex Idx,
unsigned KindID);
LLVMAttributeRef LLVMGetCallSiteStringAttribute(LLVMValueRef C,
LLVMAttributeIndex Idx,
const char *K, unsigned KLen);
void LLVMRemoveCallSiteEnumAttribute(LLVMValueRef C, LLVMAttributeIndex Idx,
unsigned KindID);
void LLVMRemoveCallSiteStringAttribute(LLVMValueRef C, LLVMAttributeIndex Idx,
const char *K, unsigned KLen);
/**
* Obtain the pointer to the function invoked by this instruction.
*
* This expects an LLVMValueRef that corresponds to a llvm::CallInst or
* llvm::InvokeInst.
*
* @see llvm::CallInst::getCalledValue()
* @see llvm::InvokeInst::getCalledValue()
*/
LLVMValueRef LLVMGetCalledValue(LLVMValueRef Instr);
/**
* Obtain whether a call instruction is a tail call.
@ -2426,6 +2640,42 @@ LLVMBool LLVMIsTailCall(LLVMValueRef CallInst);
*/
void LLVMSetTailCall(LLVMValueRef CallInst, LLVMBool IsTailCall);
/**
* Return the normal destination basic block.
*
* This only works on llvm::InvokeInst instructions.
*
* @see llvm::InvokeInst::getNormalDest()
*/
LLVMBasicBlockRef LLVMGetNormalDest(LLVMValueRef InvokeInst);
/**
* Return the unwind destination basic block.
*
* This only works on llvm::InvokeInst instructions.
*
* @see llvm::InvokeInst::getUnwindDest()
*/
LLVMBasicBlockRef LLVMGetUnwindDest(LLVMValueRef InvokeInst);
/**
* Set the normal destination basic block.
*
* This only works on llvm::InvokeInst instructions.
*
* @see llvm::InvokeInst::setNormalDest()
*/
void LLVMSetNormalDest(LLVMValueRef InvokeInst, LLVMBasicBlockRef B);
/**
* Set the unwind destination basic block.
*
* This only works on llvm::InvokeInst instructions.
*
* @see llvm::InvokeInst::setUnwindDest()
*/
void LLVMSetUnwindDest(LLVMValueRef InvokeInst, LLVMBasicBlockRef B);
/**
* @}
*/
@ -2496,6 +2746,47 @@ void LLVMSetCondition(LLVMValueRef Branch, LLVMValueRef Cond);
*/
LLVMBasicBlockRef LLVMGetSwitchDefaultDest(LLVMValueRef SwitchInstr);
/**
* @}
*/
/**
* @defgroup LLVMCCoreValueInstructionAlloca Allocas
*
* Functions in this group only apply to instructions that map to
* llvm::AllocaInst instances.
*
* @{
*/
/**
* Obtain the type that is being allocated by the alloca instruction.
*/
LLVMTypeRef LLVMGetAllocatedType(LLVMValueRef Alloca);
/**
* @}
*/
/**
* @defgroup LLVMCCoreValueInstructionGetElementPointer GEPs
*
* Functions in this group only apply to instructions that map to
* llvm::GetElementPtrInst instances.
*
* @{
*/
/**
* Check whether the given GEP instruction is inbounds.
*/
LLVMBool LLVMIsInBounds(LLVMValueRef GEP);
/**
* Set the given GEP instruction to be inbounds or not.
*/
void LLVMSetIsInBounds(LLVMValueRef GEP, LLVMBool InBounds);
/**
* @}
*/
@ -2530,6 +2821,31 @@ LLVMValueRef LLVMGetIncomingValue(LLVMValueRef PhiNode, unsigned Index);
*/
LLVMBasicBlockRef LLVMGetIncomingBlock(LLVMValueRef PhiNode, unsigned Index);
/**
* @}
*/
/**
* @defgroup LLVMCCoreValueInstructionExtractValue ExtractValue
* @defgroup LLVMCCoreValueInstructionInsertValue InsertValue
*
* Functions in this group only apply to instructions that map to
* llvm::ExtractValue and llvm::InsertValue instances.
*
* @{
*/
/**
* Obtain the number of indices.
* NB: This also works on GEP.
*/
unsigned LLVMGetNumIndices(LLVMValueRef Inst);
/**
* Obtain the indices as an array.
*/
const unsigned *LLVMGetIndices(LLVMValueRef Inst);
/**
* @}
*/
@ -2598,9 +2914,18 @@ void LLVMAddCase(LLVMValueRef Switch, LLVMValueRef OnVal,
/* Add a destination to the indirectbr instruction */
void LLVMAddDestination(LLVMValueRef IndirectBr, LLVMBasicBlockRef Dest);
/* Get the number of clauses on the landingpad instruction */
unsigned LLVMGetNumClauses(LLVMValueRef LandingPad);
/* Get the value of the clause at idnex Idx on the landingpad instruction */
LLVMValueRef LLVMGetClause(LLVMValueRef LandingPad, unsigned Idx);
/* Add a catch or filter clause to the landingpad instruction */
void LLVMAddClause(LLVMValueRef LandingPad, LLVMValueRef ClauseVal);
/* Get the 'cleanup' flag in the landingpad instruction */
LLVMBool LLVMIsCleanup(LLVMValueRef LandingPad);
/* Set the 'cleanup' flag in the landingpad instruction */
void LLVMSetCleanup(LLVMValueRef LandingPad, LLVMBool Val);
@ -2780,6 +3105,21 @@ LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B, LLVMAtomicRMWBinOp op,
LLVMValueRef PTR, LLVMValueRef Val,
LLVMAtomicOrdering ordering,
LLVMBool singleThread);
LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Ptr,
LLVMValueRef Cmp, LLVMValueRef New,
LLVMAtomicOrdering SuccessOrdering,
LLVMAtomicOrdering FailureOrdering,
LLVMBool SingleThread);
LLVMBool LLVMIsAtomicSingleThread(LLVMValueRef AtomicInst);
void LLVMSetAtomicSingleThread(LLVMValueRef AtomicInst, LLVMBool SingleThread);
LLVMAtomicOrdering LLVMGetCmpXchgSuccessOrdering(LLVMValueRef CmpXchgInst);
void LLVMSetCmpXchgSuccessOrdering(LLVMValueRef CmpXchgInst,
LLVMAtomicOrdering Ordering);
LLVMAtomicOrdering LLVMGetCmpXchgFailureOrdering(LLVMValueRef CmpXchgInst);
void LLVMSetCmpXchgFailureOrdering(LLVMValueRef CmpXchgInst,
LLVMAtomicOrdering Ordering);
/**
* @}

View File

@ -16,7 +16,11 @@
#define LLVM_C_DISASSEMBLER_H
#include "llvm/Support/DataTypes.h"
#ifdef __cplusplus
#include <cstddef>
#else
#include <stddef.h>
#endif
/**
* @defgroup LLVMCDisassembler Disassembler
@ -251,4 +255,4 @@ size_t LLVMDisasmInstruction(LLVMDisasmContextRef DC, uint8_t *Bytes,
}
#endif /* !defined(__cplusplus) */
#endif /* !defined(LLVM_C_DISASSEMBLER_H) */
#endif /* LLVM_C_DISASSEMBLER_H */

View File

@ -14,8 +14,6 @@
#ifndef LLVM_C_ERROR_HANDLING_H
#define LLVM_C_ERROR_HANDLING_H
#include "llvm-c/Types.h"
#ifdef __cplusplus
extern "C" {
#endif

View File

@ -27,20 +27,6 @@ typedef enum {
should not be used. */
} LLVMLinkerMode;
/* Links the source module into the destination module. The source module is
* damaged. The only thing that can be done is destroy it. Optionally returns a
* human-readable description of any errors that occurred in linking. OutMessage
* must be disposed with LLVMDisposeMessage. The return value is true if an
* error occurred, false otherwise.
*
* Note that the linker mode parameter \p Unused is no longer used, and has
* no effect.
*
* This function is deprecated. Use LLVMLinkModules2 instead.
*/
LLVMBool LLVMLinkModules(LLVMModuleRef Dest, LLVMModuleRef Src,
LLVMLinkerMode Unused, char **OutMessage);
/* Links the source module into the destination module. The source module is
* destroyed.
* The return value is true if an error occurred, false otherwise.

View File

@ -23,7 +23,6 @@
#define LLVM_C_ORCBINDINGS_H
#include "llvm-c/Object.h"
#include "llvm-c/Support.h"
#include "llvm-c/TargetMachine.h"
#ifdef __cplusplus
@ -33,11 +32,12 @@ extern "C" {
typedef struct LLVMOrcOpaqueJITStack *LLVMOrcJITStackRef;
typedef uint32_t LLVMOrcModuleHandle;
typedef uint64_t LLVMOrcTargetAddress;
typedef uint64_t (*LLVMOrcSymbolResolverFn)(const char *Name,
void *LookupCtx);
typedef uint64_t (*LLVMOrcSymbolResolverFn)(const char *Name, void *LookupCtx);
typedef uint64_t (*LLVMOrcLazyCompileCallbackFn)(LLVMOrcJITStackRef JITStack,
void *CallbackCtx);
typedef enum { LLVMOrcErrSuccess = 0, LLVMOrcErrGeneric } LLVMOrcErrorCode;
/**
* Create an ORC JIT stack.
*
@ -49,6 +49,14 @@ typedef uint64_t (*LLVMOrcLazyCompileCallbackFn)(LLVMOrcJITStackRef JITStack,
*/
LLVMOrcJITStackRef LLVMOrcCreateInstance(LLVMTargetMachineRef TM);
/**
* Get the error message for the most recent error (if any).
*
* This message is owned by the ORC JIT Stack and will be freed when the stack
* is disposed of by LLVMOrcDisposeInstance.
*/
const char *LLVMOrcGetErrorMsg(LLVMOrcJITStackRef JITStack);
/**
* Mangle the given symbol.
* Memory will be allocated for MangledSymbol to hold the result. The client
@ -59,7 +67,6 @@ void LLVMOrcGetMangledSymbol(LLVMOrcJITStackRef JITStack, char **MangledSymbol,
/**
* Dispose of a mangled symbol.
*/
void LLVMOrcDisposeMangledSymbol(char *MangledSymbol);
/**
@ -73,16 +80,16 @@ LLVMOrcCreateLazyCompileCallback(LLVMOrcJITStackRef JITStack,
/**
* Create a named indirect call stub.
*/
void LLVMOrcCreateIndirectStub(LLVMOrcJITStackRef JITStack,
const char *StubName,
LLVMOrcTargetAddress InitAddr);
LLVMOrcErrorCode LLVMOrcCreateIndirectStub(LLVMOrcJITStackRef JITStack,
const char *StubName,
LLVMOrcTargetAddress InitAddr);
/**
* Set the pointer for the given indirect stub.
*/
void LLVMOrcSetIndirectStubPointer(LLVMOrcJITStackRef JITStack,
const char *StubName,
LLVMOrcTargetAddress NewAddr);
LLVMOrcErrorCode LLVMOrcSetIndirectStubPointer(LLVMOrcJITStackRef JITStack,
const char *StubName,
LLVMOrcTargetAddress NewAddr);
/**
* Add module to be eagerly compiled.
@ -103,10 +110,10 @@ LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack, LLVMModuleRef Mod,
/**
* Add an object file.
*/
LLVMOrcModuleHandle
LLVMOrcAddObjectFile(LLVMOrcJITStackRef JITStack, LLVMObjectFileRef Obj,
LLVMOrcSymbolResolverFn SymbolResolver,
void *SymbolResolverCtx);
LLVMOrcModuleHandle LLVMOrcAddObjectFile(LLVMOrcJITStackRef JITStack,
LLVMObjectFileRef Obj,
LLVMOrcSymbolResolverFn SymbolResolver,
void *SymbolResolverCtx);
/**
* Remove a module set from the JIT.

View File

@ -183,14 +183,27 @@ static inline LLVMBool LLVMInitializeNativeDisassembler(void) {
/*===-- Target Data -------------------------------------------------------===*/
/**
* Obtain the data layout for a module.
*
* @see Module::getDataLayout()
*/
LLVMTargetDataRef LLVMGetModuleDataLayout(LLVMModuleRef M);
/**
* Set the data layout for a module.
*
* @see Module::setDataLayout()
*/
void LLVMSetModuleDataLayout(LLVMModuleRef M, LLVMTargetDataRef DL);
/** Creates target data from a target layout string.
See the constructor llvm::DataLayout::DataLayout. */
LLVMTargetDataRef LLVMCreateTargetData(const char *StringRep);
/** Adds target data information to a pass manager. This does not take ownership
of the target data.
See the method llvm::PassManagerBase::add. */
void LLVMAddTargetData(LLVMTargetDataRef TD, LLVMPassManagerRef PM);
/** Deallocates a TargetData.
See the destructor llvm::DataLayout::~DataLayout. */
void LLVMDisposeTargetData(LLVMTargetDataRef TD);
/** Adds target library information to a pass manager. This does not take
ownership of the target library info.
@ -275,10 +288,6 @@ unsigned LLVMElementAtOffset(LLVMTargetDataRef TD, LLVMTypeRef StructTy,
unsigned long long LLVMOffsetOfElement(LLVMTargetDataRef TD,
LLVMTypeRef StructTy, unsigned Element);
/** Deallocates a TargetData.
See the destructor llvm::DataLayout::~DataLayout. */
void LLVMDisposeTargetData(LLVMTargetDataRef TD);
/**
* @}
*/

View File

@ -115,8 +115,8 @@ char *LLVMGetTargetMachineCPU(LLVMTargetMachineRef T);
LLVMDisposeMessage. */
char *LLVMGetTargetMachineFeatureString(LLVMTargetMachineRef T);
/** Returns the llvm::DataLayout used for this llvm:TargetMachine. */
LLVMTargetDataRef LLVMGetTargetMachineData(LLVMTargetMachineRef T);
/** Create a DataLayout based on the targetMachine. */
LLVMTargetDataRef LLVMCreateTargetDataLayout(LLVMTargetMachineRef T);
/** Set the target machine's ASM verbosity. */
void LLVMSetTargetMachineAsmVerbosity(LLVMTargetMachineRef T,

View File

@ -104,13 +104,13 @@ void LLVMAddReassociatePass(LLVMPassManagerRef PM);
/** See llvm::createSCCPPass function. */
void LLVMAddSCCPPass(LLVMPassManagerRef PM);
/** See llvm::createScalarReplAggregatesPass function. */
/** See llvm::createSROAPass function. */
void LLVMAddScalarReplAggregatesPass(LLVMPassManagerRef PM);
/** See llvm::createScalarReplAggregatesPass function. */
/** See llvm::createSROAPass function. */
void LLVMAddScalarReplAggregatesPassSSA(LLVMPassManagerRef PM);
/** See llvm::createScalarReplAggregatesPass function. */
/** See llvm::createSROAPass function. */
void LLVMAddScalarReplAggregatesPassWithThreshold(LLVMPassManagerRef PM,
int Threshold);

View File

@ -108,6 +108,13 @@ typedef struct LLVMOpaquePassRegistry *LLVMPassRegistryRef;
* @see llvm::Use */
typedef struct LLVMOpaqueUse *LLVMUseRef;
/**
* Used to represent an attributes.
*
* @see llvm::Attribute
*/
typedef struct LLVMOpaqueAttributeRef *LLVMAttributeRef;
/**
* @see llvm::DiagnosticInfo
*/

View File

@ -16,7 +16,11 @@
#ifndef LLVM_C_LTO_H
#define LLVM_C_LTO_H
#ifdef __cplusplus
#include <cstddef>
#else
#include <stddef.h>
#endif
#include <sys/types.h>
#ifndef __cplusplus
@ -40,7 +44,7 @@ typedef bool lto_bool_t;
* @{
*/
#define LTO_API_VERSION 17
#define LTO_API_VERSION 20
/**
* \since prior to LTO_API_VERSION=3
@ -91,6 +95,9 @@ typedef struct LLVMOpaqueLTOModule *lto_module_t;
/** opaque reference to a code generator */
typedef struct LLVMOpaqueLTOCodeGenerator *lto_code_gen_t;
/** opaque reference to a thin code generator */
typedef struct LLVMOpaqueThinLTOCodeGenerator *thinlto_code_gen_t;
#ifdef __cplusplus
extern "C" {
#endif
@ -103,7 +110,6 @@ extern "C" {
extern const char*
lto_get_version(void);
/**
* Returns the last error string or NULL if last operation was successful.
*
@ -120,7 +126,6 @@ lto_get_error_message(void);
extern lto_bool_t
lto_module_is_object_file(const char* path);
/**
* Checks if a file is a loadable object compiled for requested target.
*
@ -130,15 +135,22 @@ extern lto_bool_t
lto_module_is_object_file_for_target(const char* path,
const char* target_triple_prefix);
/**
* Checks if a buffer is a loadable object file.
* Return true if \p Buffer contains a bitcode file with ObjC code (category
* or class) in it.
*
* \since prior to LTO_API_VERSION=3
* \since LTO_API_VERSION=20
*/
extern lto_bool_t
lto_module_is_object_file_in_memory(const void* mem, size_t length);
lto_module_has_objc_category(const void *mem, size_t length);
/**
* 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);
/**
* Checks if a buffer is a loadable object compiled for requested target.
@ -149,7 +161,6 @@ extern lto_bool_t
lto_module_is_object_file_in_memory_for_target(const void* mem, size_t length,
const char* target_triple_prefix);
/**
* Loads an object file from disk.
* Returns NULL on error (check lto_get_error_message() for details).
@ -159,7 +170,6 @@ lto_module_is_object_file_in_memory_for_target(const void* mem, size_t length,
extern lto_module_t
lto_module_create(const char* path);
/**
* Loads an object file from memory.
* Returns NULL on error (check lto_get_error_message() for details).
@ -252,7 +262,6 @@ lto_module_get_target_triple(lto_module_t mod);
extern void
lto_module_set_target_triple(lto_module_t mod, const char *triple);
/**
* Returns the number of symbols in the object module.
*
@ -261,7 +270,6 @@ lto_module_set_target_triple(lto_module_t mod, const char *triple);
extern unsigned int
lto_module_get_num_symbols(lto_module_t mod);
/**
* Returns the name of the ith symbol in the object module.
*
@ -270,7 +278,6 @@ lto_module_get_num_symbols(lto_module_t mod);
extern const char*
lto_module_get_symbol_name(lto_module_t mod, unsigned int index);
/**
* Returns the attributes of the ith symbol in the object module.
*
@ -279,7 +286,6 @@ lto_module_get_symbol_name(lto_module_t mod, unsigned int index);
extern lto_symbol_attributes
lto_module_get_symbol_attribute(lto_module_t mod, unsigned int index);
/**
* Returns the module's linker options.
*
@ -291,7 +297,6 @@ lto_module_get_symbol_attribute(lto_module_t mod, unsigned int index);
extern const char*
lto_module_get_linkeropts(lto_module_t mod);
/**
* Diagnostic severity.
*
@ -393,7 +398,6 @@ lto_codegen_set_module(lto_code_gen_t cg, lto_module_t mod);
extern lto_bool_t
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).
@ -403,7 +407,6 @@ lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model);
extern lto_bool_t
lto_codegen_set_pic_model(lto_code_gen_t cg, lto_codegen_model);
/**
* Sets the cpu to generate code for.
*
@ -412,7 +415,6 @@ lto_codegen_set_pic_model(lto_code_gen_t cg, lto_codegen_model);
extern void
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.
@ -548,6 +550,242 @@ extern void
lto_codegen_set_should_embed_uselists(lto_code_gen_t cg,
lto_bool_t ShouldEmbedUselists);
/**
* @}
* @defgroup LLVMCTLTO ThinLTO
* @ingroup LLVMC
*
* @{
*/
/**
* Type to wrap a single object returned by ThinLTO.
*
* \since LTO_API_VERSION=18
*/
typedef struct {
const char *Buffer;
size_t Size;
} LTOObjectBuffer;
/**
* Instantiates a ThinLTO code generator.
* Returns NULL on error (check lto_get_error_message() for details).
*
*
* The ThinLTOCodeGenerator is not intended to be reuse for multiple
* compilation: the model is that the client adds modules to the generator and
* ask to perform the ThinLTO optimizations / codegen, and finally destroys the
* codegenerator.
*
* \since LTO_API_VERSION=18
*/
extern thinlto_code_gen_t thinlto_create_codegen(void);
/**
* Frees the generator and all memory it internally allocated.
* Upon return the thinlto_code_gen_t is no longer valid.
*
* \since LTO_API_VERSION=18
*/
extern void thinlto_codegen_dispose(thinlto_code_gen_t cg);
/**
* Add a module to a ThinLTO code generator. Identifier has to be unique among
* all the modules in a code generator. The data buffer stays owned by the
* client, and is expected to be available for the entire lifetime of the
* thinlto_code_gen_t it is added to.
*
* On failure, returns NULL (check lto_get_error_message() for details).
*
*
* \since LTO_API_VERSION=18
*/
extern void thinlto_codegen_add_module(thinlto_code_gen_t cg,
const char *identifier, const char *data,
int length);
/**
* Optimize and codegen all the modules added to the codegenerator using
* ThinLTO. Resulting objects are accessible using thinlto_module_get_object().
*
* \since LTO_API_VERSION=18
*/
extern void thinlto_codegen_process(thinlto_code_gen_t cg);
/**
* Returns the number of object files produced by the ThinLTO CodeGenerator.
*
* It usually matches the number of input files, but this is not a guarantee of
* the API and may change in future implementation, so the client should not
* assume it.
*
* \since LTO_API_VERSION=18
*/
extern unsigned int thinlto_module_get_num_objects(thinlto_code_gen_t cg);
/**
* Returns a reference to the ith object file produced by the ThinLTO
* CodeGenerator.
*
* Client should use \p thinlto_module_get_num_objects() to get the number of
* available objects.
*
* \since LTO_API_VERSION=18
*/
extern LTOObjectBuffer thinlto_module_get_object(thinlto_code_gen_t cg,
unsigned int index);
/**
* Sets which PIC code model to generate.
* Returns true on error (check lto_get_error_message() for details).
*
* \since LTO_API_VERSION=18
*/
extern lto_bool_t thinlto_codegen_set_pic_model(thinlto_code_gen_t cg,
lto_codegen_model);
/**
* @}
* @defgroup LLVMCTLTO_CACHING ThinLTO Cache Control
* @ingroup LLVMCTLTO
*
* These entry points control the ThinLTO cache. The cache is intended to
* support incremental build, and thus needs to be persistent accross build.
* The client enabled the cache by supplying a path to an existing directory.
* The code generator will use this to store objects files that may be reused
* during a subsequent build.
* To avoid filling the disk space, a few knobs are provided:
* - The pruning interval limit the frequency at which the garbage collector
* will try to scan the cache directory to prune it from expired entries.
* Setting to -1 disable the pruning (default).
* - The pruning expiration time indicates to the garbage collector how old an
* entry needs to be to be removed.
* - Finally, the garbage collector can be instructed to prune the cache till
* the occupied space goes below a threshold.
* @{
*/
/**
* Sets the path to a directory to use as a cache storage for incremental build.
* Setting this activates caching.
*
* \since LTO_API_VERSION=18
*/
extern void thinlto_codegen_set_cache_dir(thinlto_code_gen_t cg,
const char *cache_dir);
/**
* Sets the cache pruning interval (in seconds). A negative value disable the
* pruning. An unspecified default value will be applied, and a value of 0 will
* be ignored.
*
* \since LTO_API_VERSION=18
*/
extern void thinlto_codegen_set_cache_pruning_interval(thinlto_code_gen_t cg,
int interval);
/**
* Sets the maximum cache size that can be persistent across build, in terms of
* percentage of the available space on the the disk. Set to 100 to indicate
* no limit, 50 to indicate that the cache size will not be left over half the
* available space. A value over 100 will be reduced to 100, a value of 0 will
* be ignored. An unspecified default value will be applied.
*
* The formula looks like:
* AvailableSpace = FreeSpace + ExistingCacheSize
* NewCacheSize = AvailableSpace * P/100
*
* \since LTO_API_VERSION=18
*/
extern void thinlto_codegen_set_final_cache_size_relative_to_available_space(
thinlto_code_gen_t cg, unsigned percentage);
/**
* Sets the expiration (in seconds) for an entry in the cache. An unspecified
* default value will be applied. A value of 0 will be ignored.
*
* \since LTO_API_VERSION=18
*/
extern void thinlto_codegen_set_cache_entry_expiration(thinlto_code_gen_t cg,
unsigned expiration);
/**
* @}
*/
/**
* Sets the path to a directory to use as a storage for temporary bitcode files.
* The intention is to make the bitcode files available for debugging at various
* stage of the pipeline.
*
* \since LTO_API_VERSION=18
*/
extern void thinlto_codegen_set_savetemps_dir(thinlto_code_gen_t cg,
const char *save_temps_dir);
/**
* Sets the cpu to generate code for.
*
* \since LTO_API_VERSION=18
*/
extern void thinlto_codegen_set_cpu(thinlto_code_gen_t cg, const char *cpu);
/**
* Disable CodeGen, only run the stages till codegen and stop. The output will
* be bitcode.
*
* \since LTO_API_VERSION=19
*/
extern void thinlto_codegen_disable_codegen(thinlto_code_gen_t cg,
lto_bool_t disable);
/**
* Perform CodeGen only: disable all other stages.
*
* \since LTO_API_VERSION=19
*/
extern void thinlto_codegen_set_codegen_only(thinlto_code_gen_t cg,
lto_bool_t codegen_only);
/**
* Parse -mllvm style debug options.
*
* \since LTO_API_VERSION=18
*/
extern void thinlto_debug_options(const char *const *options, int number);
/**
* Test if a module has support for ThinLTO linking.
*
* \since LTO_API_VERSION=18
*/
extern lto_bool_t lto_module_is_thinlto(lto_module_t mod);
/**
* Adds a symbol to the list of 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. For every single module, the functions
* referenced from code outside of the ThinLTO modules need to be added here.
*
* \since LTO_API_VERSION=18
*/
extern void thinlto_codegen_add_must_preserve_symbol(thinlto_code_gen_t cg,
const char *name,
int length);
/**
* Adds a symbol to the list of global symbols that are cross-referenced between
* ThinLTO files. If the ThinLTO CodeGenerator can ensure that every
* references from a ThinLTO module to this symbol is optimized away, then
* the symbol can be discarded.
*
* \since LTO_API_VERSION=18
*/
extern void thinlto_codegen_add_cross_referenced_symbol(thinlto_code_gen_t cg,
const char *name,
int length);
#ifdef __cplusplus
}
#endif
@ -556,4 +794,4 @@ lto_codegen_set_should_embed_uselists(lto_code_gen_t cg,
* @}
*/
#endif
#endif /* LLVM_C_LTO_H */

View File

@ -25,6 +25,8 @@ struct fltSemantics;
class APSInt;
class StringRef;
template <typename T> class SmallVectorImpl;
/// Enum that represents what fraction of the LSB truncated bits of an fp number
/// represent.
///
@ -511,19 +513,12 @@ public:
/// 0 -> \c IEK_Zero
/// Inf -> \c IEK_Inf
///
friend int ilogb(const APFloat &Arg) {
if (Arg.isNaN())
return IEK_NaN;
if (Arg.isZero())
return IEK_Zero;
if (Arg.isInfinity())
return IEK_Inf;
return Arg.exponent;
}
friend int ilogb(const APFloat &Arg);
/// \brief Returns: X * 2^Exp for integral exponents.
friend APFloat scalbn(APFloat X, int Exp);
friend APFloat scalbn(APFloat X, int Exp, roundingMode);
friend APFloat frexp(const APFloat &X, int &Exp, roundingMode);
private:
@ -579,6 +574,7 @@ private:
const APInt *fill);
void makeInf(bool Neg = false);
void makeZero(bool Neg = false);
void makeQuiet();
/// @}
@ -651,7 +647,14 @@ private:
/// These additional declarations are required in order to compile LLVM with IBM
/// xlC compiler.
hash_code hash_value(const APFloat &Arg);
APFloat scalbn(APFloat X, int Exp);
int ilogb(const APFloat &Arg);
APFloat scalbn(APFloat X, int Exp, APFloat::roundingMode);
/// \brief Equivalent of C standard library function.
///
/// While the C standard says Exp is an unspecified value for infinity and nan,
/// this returns INT_MAX for infinities, and INT_MIN for NaNs.
APFloat frexp(const APFloat &Val, int &Exp, APFloat::roundingMode RM);
/// \brief Returns the absolute value of the argument.
inline APFloat abs(APFloat X) {

View File

@ -16,7 +16,6 @@
#ifndef LLVM_ADT_APINT_H
#define LLVM_ADT_APINT_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MathExtras.h"
#include <cassert>
@ -31,6 +30,7 @@ class hash_code;
class raw_ostream;
template <typename T> class SmallVectorImpl;
template <typename T> class ArrayRef;
// An unsigned host type used as a single part of a multi-part
// bignum.
@ -177,11 +177,11 @@ class APInt {
/// provides a more convenient form of divide for internal use since KnuthDiv
/// has specific constraints on its inputs. If those constraints are not met
/// then it provides a simpler form of divide.
static void divide(const APInt LHS, unsigned lhsWords, const APInt &RHS,
static void divide(const APInt &LHS, unsigned lhsWords, const APInt &RHS,
unsigned rhsWords, APInt *Quotient, APInt *Remainder);
/// out-of-line slow case for inline constructor
void initSlowCase(unsigned numBits, uint64_t val, bool isSigned);
void initSlowCase(uint64_t val, bool isSigned);
/// shared code between two array constructors
void initFromArray(ArrayRef<uint64_t> array);
@ -239,7 +239,7 @@ public:
if (isSingleWord())
VAL = val;
else
initSlowCase(numBits, val, isSigned);
initSlowCase(val, isSigned);
clearUnusedBits();
}
@ -625,7 +625,12 @@ public:
/// Negates *this using two's complement logic.
///
/// \returns An APInt value representing the negation of *this.
APInt operator-() const { return APInt(BitWidth, 0) - (*this); }
APInt operator-() const {
APInt Result(*this);
Result.flipAllBits();
++Result;
return Result;
}
/// \brief Logical negation operator.
///
@ -835,13 +840,13 @@ public:
///
/// Adds RHS to this APInt and returns the result.
APInt operator+(const APInt &RHS) const;
APInt operator+(uint64_t RHS) const { return (*this) + APInt(BitWidth, RHS); }
APInt operator+(uint64_t RHS) const;
/// \brief Subtraction operator.
///
/// Subtracts RHS from this APInt and returns the result.
APInt operator-(const APInt &RHS) const;
APInt operator-(uint64_t RHS) const { return (*this) - APInt(BitWidth, RHS); }
APInt operator-(uint64_t RHS) const;
/// \brief Left logical shift operator.
///
@ -1451,6 +1456,10 @@ public:
/// \returns a byte-swapped representation of this APInt Value.
APInt LLVM_ATTRIBUTE_UNUSED_RESULT byteSwap() const;
/// \returns the value with the bit representation reversed of this APInt
/// Value.
APInt LLVM_ATTRIBUTE_UNUSED_RESULT reverseBits() const;
/// \brief Converts this APInt to a double value.
double roundToDouble(bool isSigned) const;
@ -1744,16 +1753,24 @@ inline raw_ostream &operator<<(raw_ostream &OS, const APInt &I) {
namespace APIntOps {
/// \brief Determine the smaller of two APInts considered to be signed.
inline APInt smin(const APInt &A, const APInt &B) { return A.slt(B) ? A : B; }
inline const APInt &smin(const APInt &A, const APInt &B) {
return A.slt(B) ? A : B;
}
/// \brief Determine the larger of two APInts considered to be signed.
inline APInt smax(const APInt &A, const APInt &B) { return A.sgt(B) ? A : B; }
inline const APInt &smax(const APInt &A, const APInt &B) {
return A.sgt(B) ? A : B;
}
/// \brief Determine the smaller of two APInts considered to be signed.
inline APInt umin(const APInt &A, const APInt &B) { return A.ult(B) ? A : B; }
inline const APInt &umin(const APInt &A, const APInt &B) {
return A.ult(B) ? A : B;
}
/// \brief Determine the larger of two APInts considered to be unsigned.
inline APInt umax(const APInt &A, const APInt &B) { return A.ugt(B) ? A : B; }
inline const APInt &umax(const APInt &A, const APInt &B) {
return A.ugt(B) ? A : B;
}
/// \brief Check if the specified APInt has a N-bits unsigned integer value.
inline bool isIntN(unsigned N, const APInt &APIVal) { return APIVal.isIntN(N); }
@ -1770,6 +1787,13 @@ inline bool isMask(unsigned numBits, const APInt &APIVal) {
APIVal == APInt::getLowBitsSet(APIVal.getBitWidth(), numBits);
}
/// \returns true if the argument is a non-empty sequence of ones starting at
/// the least significant bit with the remainder zero (32 bit version).
/// Ex. isMask(0x0000FFFFU) == true.
inline bool isMask(const APInt &Value) {
return (Value != 0) && ((Value + 1) & Value) == 0;
}
/// \brief Return true if the argument APInt value contains a sequence of ones
/// with the remainder zero.
inline bool isShiftedMask(unsigned numBits, const APInt &APIVal) {

View File

@ -16,7 +16,6 @@
#include <vector>
namespace llvm {
/// ArrayRef - Represent a constant reference to an array (0 or more elements
/// consecutively in memory), i.e. a start pointer and a length. It allows
/// various APIs to take consecutive elements easily and conveniently.
@ -92,19 +91,20 @@ namespace llvm {
/// Construct an ArrayRef<const T*> from ArrayRef<T*>. This uses SFINAE to
/// ensure that only ArrayRefs of pointers can be converted.
template <typename U>
ArrayRef(const ArrayRef<U *> &A,
typename std::enable_if<
std::is_convertible<U *const *, T const *>::value>::type* = 0)
ArrayRef(
const ArrayRef<U *> &A,
typename std::enable_if<
std::is_convertible<U *const *, T const *>::value>::type * = nullptr)
: Data(A.data()), Length(A.size()) {}
/// Construct an ArrayRef<const T*> from a SmallVector<T*>. This is
/// templated in order to avoid instantiating SmallVectorTemplateCommon<T>
/// whenever we copy-construct an ArrayRef.
template<typename U, typename DummyT>
/*implicit*/ ArrayRef(const SmallVectorTemplateCommon<U*, DummyT> &Vec,
typename std::enable_if<
std::is_convertible<U *const *,
T const *>::value>::type* = 0)
/*implicit*/ ArrayRef(
const SmallVectorTemplateCommon<U *, DummyT> &Vec,
typename std::enable_if<
std::is_convertible<U *const *, T const *>::value>::type * = nullptr)
: Data(Vec.data()), Length(Vec.size()) {
}
@ -161,20 +161,26 @@ namespace llvm {
}
/// slice(n) - Chop off the first N elements of the array.
ArrayRef<T> slice(unsigned N) const {
ArrayRef<T> slice(size_t N) const {
assert(N <= size() && "Invalid specifier");
return ArrayRef<T>(data()+N, size()-N);
}
/// slice(n, m) - Chop off the first N elements of the array, and keep M
/// elements in the array.
ArrayRef<T> slice(unsigned N, unsigned M) const {
ArrayRef<T> slice(size_t N, size_t M) const {
assert(N+M <= size() && "Invalid specifier");
return ArrayRef<T>(data()+N, M);
}
// \brief Drop the last \p N elements of the array.
ArrayRef<T> drop_back(unsigned N = 1) const {
/// \brief Drop the first \p N elements of the array.
ArrayRef<T> drop_front(size_t N = 1) const {
assert(size() >= N && "Dropping more elements than exist");
return slice(N, size() - N);
}
/// \brief Drop the last \p N elements of the array.
ArrayRef<T> drop_back(size_t N = 1) const {
assert(size() >= N && "Dropping more elements than exist");
return slice(0, size() - N);
}
@ -273,19 +279,25 @@ namespace llvm {
}
/// slice(n) - Chop off the first N elements of the array.
MutableArrayRef<T> slice(unsigned N) const {
MutableArrayRef<T> slice(size_t N) const {
assert(N <= this->size() && "Invalid specifier");
return MutableArrayRef<T>(data()+N, this->size()-N);
}
/// slice(n, m) - Chop off the first N elements of the array, and keep M
/// elements in the array.
MutableArrayRef<T> slice(unsigned N, unsigned M) const {
MutableArrayRef<T> slice(size_t N, size_t M) const {
assert(N+M <= this->size() && "Invalid specifier");
return MutableArrayRef<T>(data()+N, M);
}
MutableArrayRef<T> drop_back(unsigned N) const {
/// \brief Drop the first \p N elements of the array.
MutableArrayRef<T> drop_front(size_t N = 1) const {
assert(this->size() >= N && "Dropping more elements than exist");
return slice(N, this->size() - N);
}
MutableArrayRef<T> drop_back(size_t N = 1) const {
assert(this->size() >= N && "Dropping more elements than exist");
return slice(0, this->size() - N);
}
@ -379,6 +391,6 @@ namespace llvm {
template <typename T> hash_code hash_value(ArrayRef<T> S) {
return hash_combine_range(S.begin(), S.end());
}
}
} // end namespace llvm
#endif
#endif // LLVM_ADT_ARRAYREF_H

View File

@ -14,13 +14,13 @@
#ifndef LLVM_ADT_BITVECTOR_H
#define LLVM_ADT_BITVECTOR_H
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include <algorithm>
#include <cassert>
#include <climits>
#include <cstdint>
#include <cstdlib>
#include <cstring>
namespace llvm {
@ -69,7 +69,7 @@ public:
}
operator bool() const {
return ((*WordRef) & (BitWord(1) << BitPos)) ? true : false;
return ((*WordRef) & (BitWord(1) << BitPos)) != 0;
}
};
@ -105,6 +105,7 @@ public:
BitVector(BitVector &&RHS)
: Bits(RHS.Bits), Size(RHS.Size), Capacity(RHS.Capacity) {
RHS.Bits = nullptr;
RHS.Size = RHS.Capacity = 0;
}
~BitVector() {
@ -244,7 +245,7 @@ public:
BitWord PrefixMask = ~0UL << (I % BITWORD_SIZE);
Bits[I / BITWORD_SIZE] |= PrefixMask;
I = RoundUpToAlignment(I, BITWORD_SIZE);
I = alignTo(I, BITWORD_SIZE);
for (; I + BITWORD_SIZE <= E; I += BITWORD_SIZE)
Bits[I / BITWORD_SIZE] = ~0UL;
@ -283,7 +284,7 @@ public:
BitWord PrefixMask = ~0UL << (I % BITWORD_SIZE);
Bits[I / BITWORD_SIZE] &= ~PrefixMask;
I = RoundUpToAlignment(I, BITWORD_SIZE);
I = alignTo(I, BITWORD_SIZE);
for (; I + BITWORD_SIZE <= E; I += BITWORD_SIZE)
Bits[I / BITWORD_SIZE] = 0UL;
@ -454,6 +455,7 @@ public:
Capacity = RHS.Capacity;
RHS.Bits = nullptr;
RHS.Size = RHS.Capacity = 0;
return *this;
}
@ -576,7 +578,7 @@ static inline size_t capacity_in_bytes(const BitVector &X) {
return X.getMemorySize();
}
} // End llvm namespace
} // end namespace llvm
namespace std {
/// Implement std::swap in terms of BitVector swap.
@ -584,6 +586,6 @@ namespace std {
swap(llvm::BitVector &LHS, llvm::BitVector &RHS) {
LHS.swap(RHS);
}
}
} // end namespace std
#endif
#endif // LLVM_ADT_BITVECTOR_H

View File

@ -0,0 +1,153 @@
//===-- llvm/ADT/BitmaskEnum.h ----------------------------------*- 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_BITMASKENUM_H
#define LLVM_ADT_BITMASKENUM_H
#include <cassert>
#include <type_traits>
#include <utility>
#include "llvm/Support/MathExtras.h"
/// LLVM_MARK_AS_BITMASK_ENUM lets you opt in an individual enum type so you can
/// perform bitwise operations on it without putting static_cast everywhere.
///
/// \code
/// enum MyEnum {
/// E1 = 1, E2 = 2, E3 = 4, E4 = 8,
/// LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ E4)
/// };
///
/// void Foo() {
/// MyEnum A = (E1 | E2) & E3 ^ ~E4; // Look, ma: No static_cast!
/// }
/// \endcode
///
/// Normally when you do a bitwise operation on an enum value, you get back an
/// instance of the underlying type (e.g. int). But using this macro, bitwise
/// ops on your enum will return you back instances of the enum. This is
/// particularly useful for enums which represent a combination of flags.
///
/// The parameter to LLVM_MARK_AS_BITMASK_ENUM should be the largest individual
/// value in your enum.
///
/// All of the enum's values must be non-negative.
#define LLVM_MARK_AS_BITMASK_ENUM(LargestValue) \
LLVM_BITMASK_LARGEST_ENUMERATOR = LargestValue
/// LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE() pulls the operator overloads used
/// by LLVM_MARK_AS_BITMASK_ENUM into the current namespace.
///
/// Suppose you have an enum foo::bar::MyEnum. Before using
/// LLVM_MARK_AS_BITMASK_ENUM on MyEnum, you must put
/// LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE() somewhere inside namespace foo or
/// namespace foo::bar. This allows the relevant operator overloads to be found
/// by ADL.
///
/// You don't need to use this macro in namespace llvm; it's done at the bottom
/// of this file.
#define LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE() \
using ::llvm::BitmaskEnumDetail::operator~; \
using ::llvm::BitmaskEnumDetail::operator|; \
using ::llvm::BitmaskEnumDetail::operator&; \
using ::llvm::BitmaskEnumDetail::operator^; \
using ::llvm::BitmaskEnumDetail::operator|=; \
using ::llvm::BitmaskEnumDetail::operator&=; \
/* Force a semicolon at the end of this macro. */ \
using ::llvm::BitmaskEnumDetail::operator^=
namespace llvm {
/// Traits class to determine whether an enum has a
/// LLVM_BITMASK_LARGEST_ENUMERATOR enumerator.
template <typename E, typename Enable = void>
struct is_bitmask_enum : std::false_type {};
template <typename E>
struct is_bitmask_enum<
E, typename std::enable_if<sizeof(E::LLVM_BITMASK_LARGEST_ENUMERATOR) >=
0>::type> : std::true_type {};
namespace BitmaskEnumDetail {
/// Get a bitmask with 1s in all places up to the high-order bit of E's largest
/// value.
template <typename E> typename std::underlying_type<E>::type Mask() {
// On overflow, NextPowerOf2 returns zero with the type uint64_t, so
// subtracting 1 gives us the mask with all bits set, like we want.
return NextPowerOf2(static_cast<typename std::underlying_type<E>::type>(
E::LLVM_BITMASK_LARGEST_ENUMERATOR)) -
1;
}
/// Check that Val is in range for E, and return Val cast to E's underlying
/// type.
template <typename E> typename std::underlying_type<E>::type Underlying(E Val) {
auto U = static_cast<typename std::underlying_type<E>::type>(Val);
assert(U >= 0 && "Negative enum values are not allowed.");
assert(U <= Mask<E>() && "Enum value too large (or largest val too small?)");
return U;
}
template <typename E,
typename = typename std::enable_if<is_bitmask_enum<E>::value>::type>
E operator~(E Val) {
return static_cast<E>(~Underlying(Val) & Mask<E>());
}
template <typename E,
typename = typename std::enable_if<is_bitmask_enum<E>::value>::type>
E operator|(E LHS, E RHS) {
return static_cast<E>(Underlying(LHS) | Underlying(RHS));
}
template <typename E,
typename = typename std::enable_if<is_bitmask_enum<E>::value>::type>
E operator&(E LHS, E RHS) {
return static_cast<E>(Underlying(LHS) & Underlying(RHS));
}
template <typename E,
typename = typename std::enable_if<is_bitmask_enum<E>::value>::type>
E operator^(E LHS, E RHS) {
return static_cast<E>(Underlying(LHS) ^ Underlying(RHS));
}
// |=, &=, and ^= return a reference to LHS, to match the behavior of the
// operators on builtin types.
template <typename E,
typename = typename std::enable_if<is_bitmask_enum<E>::value>::type>
E &operator|=(E &LHS, E RHS) {
LHS = LHS | RHS;
return LHS;
}
template <typename E,
typename = typename std::enable_if<is_bitmask_enum<E>::value>::type>
E &operator&=(E &LHS, E RHS) {
LHS = LHS & RHS;
return LHS;
}
template <typename E,
typename = typename std::enable_if<is_bitmask_enum<E>::value>::type>
E &operator^=(E &LHS, E RHS) {
LHS = LHS ^ RHS;
return LHS;
}
} // namespace BitmaskEnumDetail
// Enable bitmask enums in namespace ::llvm and all nested namespaces.
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
} // namespace llvm
#endif

View File

@ -81,11 +81,13 @@ public:
}
unsigned size() const { return getNumEntries(); }
/// Grow the densemap so that it has at least Size buckets. Does not shrink
void resize(size_type Size) {
/// Grow the densemap so that it can contain at least \p NumEntries items
/// before resizing again.
void reserve(size_type NumEntries) {
auto NumBuckets = getMinBucketToReserveForEntries(NumEntries);
incrementEpoch();
if (Size > getNumBuckets())
grow(Size);
if (NumBuckets > getNumBuckets())
grow(NumBuckets);
}
void clear() {
@ -195,6 +197,26 @@ public:
true);
}
/// Alternate version of insert() which allows a different, and possibly
/// less expensive, key type.
/// The DenseMapInfo is responsible for supplying methods
/// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key
/// type used.
template <typename LookupKeyT>
std::pair<iterator, bool> insert_as(std::pair<KeyT, ValueT> &&KV,
const LookupKeyT &Val) {
BucketT *TheBucket;
if (LookupBucketFor(Val, TheBucket))
return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
false); // Already in map.
// Otherwise, insert the new element.
TheBucket = InsertIntoBucket(std::move(KV.first), std::move(KV.second), Val,
TheBucket);
return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
true);
}
/// insert - Range insertion of pairs.
template<typename InputIt>
void insert(InputIt I, InputIt E) {
@ -285,6 +307,17 @@ protected:
::new (&B->getFirst()) KeyT(EmptyKey);
}
/// Returns the number of buckets to allocate to ensure that the DenseMap can
/// accommodate \p NumEntries without need to grow().
unsigned getMinBucketToReserveForEntries(unsigned NumEntries) {
// Ensure that "NumEntries * 4 < NumBuckets * 3"
if (NumEntries == 0)
return 0;
// +1 is required because of the strict equality.
// For example if NumEntries is 48, we need to return 401.
return NextPowerOf2(NumEntries * 4 / 3 + 1);
}
void moveFromOldBuckets(BucketT *OldBucketsBegin, BucketT *OldBucketsEnd) {
initEmpty();
@ -399,7 +432,7 @@ private:
BucketT *InsertIntoBucket(const KeyT &Key, const ValueT &Value,
BucketT *TheBucket) {
TheBucket = InsertIntoBucketImpl(Key, TheBucket);
TheBucket = InsertIntoBucketImpl(Key, Key, TheBucket);
TheBucket->getFirst() = Key;
::new (&TheBucket->getSecond()) ValueT(Value);
@ -408,7 +441,7 @@ private:
BucketT *InsertIntoBucket(const KeyT &Key, ValueT &&Value,
BucketT *TheBucket) {
TheBucket = InsertIntoBucketImpl(Key, TheBucket);
TheBucket = InsertIntoBucketImpl(Key, Key, TheBucket);
TheBucket->getFirst() = Key;
::new (&TheBucket->getSecond()) ValueT(std::move(Value));
@ -416,14 +449,26 @@ private:
}
BucketT *InsertIntoBucket(KeyT &&Key, ValueT &&Value, BucketT *TheBucket) {
TheBucket = InsertIntoBucketImpl(Key, TheBucket);
TheBucket = InsertIntoBucketImpl(Key, Key, TheBucket);
TheBucket->getFirst() = std::move(Key);
::new (&TheBucket->getSecond()) ValueT(std::move(Value));
return TheBucket;
}
BucketT *InsertIntoBucketImpl(const KeyT &Key, BucketT *TheBucket) {
template <typename LookupKeyT>
BucketT *InsertIntoBucket(KeyT &&Key, ValueT &&Value, LookupKeyT &Lookup,
BucketT *TheBucket) {
TheBucket = InsertIntoBucketImpl(Key, Lookup, TheBucket);
TheBucket->getFirst() = std::move(Key);
::new (&TheBucket->getSecond()) ValueT(std::move(Value));
return TheBucket;
}
template <typename LookupKeyT>
BucketT *InsertIntoBucketImpl(const KeyT &Key, const LookupKeyT &Lookup,
BucketT *TheBucket) {
incrementEpoch();
// If the load of the hash table is more than 3/4, or if fewer than 1/8 of
@ -439,12 +484,12 @@ private:
unsigned NumBuckets = getNumBuckets();
if (LLVM_UNLIKELY(NewNumEntries * 4 >= NumBuckets * 3)) {
this->grow(NumBuckets * 2);
LookupBucketFor(Key, TheBucket);
LookupBucketFor(Lookup, TheBucket);
NumBuckets = getNumBuckets();
} else if (LLVM_UNLIKELY(NumBuckets-(NewNumEntries+getNumTombstones()) <=
NumBuckets/8)) {
this->grow(NumBuckets);
LookupBucketFor(Key, TheBucket);
LookupBucketFor(Lookup, TheBucket);
}
assert(TheBucket);
@ -550,9 +595,9 @@ class DenseMap : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>,
unsigned NumBuckets;
public:
explicit DenseMap(unsigned NumInitBuckets = 0) {
init(NumInitBuckets);
}
/// Create a DenseMap wth an optional \p InitialReserve that guarantee that
/// this number of elements can be inserted in the map without grow()
explicit DenseMap(unsigned InitialReserve = 0) { init(InitialReserve); }
DenseMap(const DenseMap &other) : BaseT() {
init(0);
@ -566,7 +611,7 @@ public:
template<typename InputIt>
DenseMap(const InputIt &I, const InputIt &E) {
init(NextPowerOf2(std::distance(I, E)));
init(std::distance(I, E));
this->insert(I, E);
}
@ -609,7 +654,8 @@ public:
}
}
void init(unsigned InitBuckets) {
void init(unsigned InitNumEntries) {
auto InitBuckets = BaseT::getMinBucketToReserveForEntries(InitNumEntries);
if (allocateBuckets(InitBuckets)) {
this->BaseT::initEmpty();
} else {

View File

@ -30,6 +30,36 @@ struct DenseMapInfo {
//static bool isEqual(const T &LHS, const T &RHS);
};
template <typename T> struct CachedHash {
CachedHash(T Val) : Val(std::move(Val)) {
Hash = DenseMapInfo<T>::getHashValue(Val);
}
CachedHash(T Val, unsigned Hash) : Val(std::move(Val)), Hash(Hash) {}
T Val;
unsigned Hash;
};
// Provide DenseMapInfo for all CachedHash<T>.
template <typename T> struct DenseMapInfo<CachedHash<T>> {
static CachedHash<T> getEmptyKey() {
T N = DenseMapInfo<T>::getEmptyKey();
return {N, 0};
}
static CachedHash<T> getTombstoneKey() {
T N = DenseMapInfo<T>::getTombstoneKey();
return {N, 0};
}
static unsigned getHashValue(CachedHash<T> Val) {
assert(!isEqual(Val, getEmptyKey()) && "Cannot hash the empty key!");
assert(!isEqual(Val, getTombstoneKey()) &&
"Cannot hash the tombstone key!");
return Val.Hash;
}
static bool isEqual(CachedHash<T> A, CachedHash<T> B) {
return DenseMapInfo<T>::isEqual(A.Val, B.Val);
}
};
// Provide DenseMapInfo for all pointers.
template<typename T>
struct DenseMapInfo<T*> {

View File

@ -94,6 +94,7 @@ public:
ValueT *operator->() { return &I->getFirst(); }
Iterator& operator++() { ++I; return *this; }
Iterator operator++(int) { auto T = *this; ++I; return T; }
bool operator==(const Iterator& X) const { return I == X.I; }
bool operator!=(const Iterator& X) const { return I != X.I; }
};
@ -115,6 +116,7 @@ public:
const ValueT *operator->() { return &I->getFirst(); }
ConstIterator& operator++() { ++I; return *this; }
ConstIterator operator++(int) { auto T = *this; ++I; return T; }
bool operator==(const ConstIterator& X) const { return I == X.I; }
bool operator!=(const ConstIterator& X) const { return I != X.I; }
};
@ -152,6 +154,19 @@ public:
return TheMap.insert(std::make_pair(V, Empty));
}
/// Alternative version of insert that uses a different (and possibly less
/// expensive) key type.
template <typename LookupKeyT>
std::pair<iterator, bool> insert_as(const ValueT &V,
const LookupKeyT &LookupKey) {
return insert_as(ValueT(V), LookupKey);
}
template <typename LookupKeyT>
std::pair<iterator, bool> insert_as(ValueT &&V, const LookupKeyT &LookupKey) {
detail::DenseSetEmpty Empty;
return TheMap.insert_as(std::make_pair(std::move(V), Empty), LookupKey);
}
// Range insertion of values.
template<typename InputIt>
void insert(InputIt I, InputIt E) {

View File

@ -17,10 +17,8 @@
#define LLVM_ADT_FOLDINGSET_H
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
/// This folding set used for two purposes:
@ -98,6 +96,7 @@ namespace llvm {
/// The result indicates whether the node existed in the folding set.
class FoldingSetNodeID;
class StringRef;
//===----------------------------------------------------------------------===//
/// FoldingSetImpl - Implements the folding set functionality. The main
@ -181,11 +180,26 @@ public:
/// empty - Returns true if there are no nodes in the folding set.
bool empty() const { return NumNodes == 0; }
/// reserve - Increase the number of buckets such that adding the
/// EltCount-th node won't cause a rebucket operation. reserve is permitted
/// to allocate more space than requested by EltCount.
void reserve(unsigned EltCount);
/// capacity - Returns the number of nodes permitted in the folding set
/// before a rebucket operation is performed.
unsigned capacity() {
// We allow a load factor of up to 2.0,
// so that means our capacity is NumBuckets * 2
return NumBuckets * 2;
}
private:
/// GrowHashTable - Double the size of the hash table and rehash everything.
///
void GrowHashTable();
/// GrowBucketCount - resize the hash table and rehash everything.
/// NewBucketCount must be a power of two, and must be greater than the old
/// bucket count.
void GrowBucketCount(unsigned NewBucketCount);
protected:
/// GetNodeProfile - Instantiations of the FoldingSet template implement
/// this function to gather data bits for the given node.

View File

@ -52,7 +52,6 @@
#include <algorithm>
#include <cassert>
#include <cstring>
#include <iterator>
#include <string>
#include <utility>
@ -632,7 +631,8 @@ inline hash_code hash_integer_value(uint64_t value) {
template <typename T>
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);
return ::llvm::hashing::detail::hash_integer_value(
static_cast<uint64_t>(value));
}
// Declared and documented above, but defined here so that any of the hashing

View File

@ -11,6 +11,7 @@
#define LLVM_ADT_POINTEREMBEDDEDINT_H
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
#include <climits>
@ -30,6 +31,8 @@ template <typename IntT, int Bits = sizeof(IntT) * CHAR_BIT>
class PointerEmbeddedInt {
uintptr_t Value;
// Note: This '<' is correct; using '<=' would result in some shifts
// overflowing their storage types.
static_assert(Bits < sizeof(uintptr_t) * CHAR_BIT,
"Cannot embed more bits than we have in a pointer!");
@ -42,25 +45,36 @@ class PointerEmbeddedInt {
Mask = static_cast<uintptr_t>(-1) << Bits
};
struct RawValueTag {
explicit RawValueTag() = default;
};
friend class PointerLikeTypeTraits<PointerEmbeddedInt>;
explicit PointerEmbeddedInt(uintptr_t Value) : Value(Value) {}
explicit PointerEmbeddedInt(uintptr_t Value, RawValueTag) : Value(Value) {}
public:
PointerEmbeddedInt() : Value(0) {}
PointerEmbeddedInt(IntT I) : Value(static_cast<uintptr_t>(I) << Shift) {
assert((I & Mask) == 0 && "Integer has bits outside those preserved!");
PointerEmbeddedInt(IntT I) {
*this = I;
}
PointerEmbeddedInt &operator=(IntT I) {
assert((I & Mask) == 0 && "Integer has bits outside those preserved!");
assert((std::is_signed<IntT>::value ? llvm::isInt<Bits>(I)
: llvm::isUInt<Bits>(I)) &&
"Integer has bits outside those preserved!");
Value = static_cast<uintptr_t>(I) << Shift;
return *this;
}
// Note that this imilict conversion additionally allows all of the basic
// Note that this implicit conversion additionally allows all of the basic
// comparison operators to work transparently, etc.
operator IntT() const { return static_cast<IntT>(Value >> Shift); }
operator IntT() const {
if (std::is_signed<IntT>::value)
return static_cast<IntT>(static_cast<intptr_t>(Value) >> Shift);
return static_cast<IntT>(Value >> Shift);
}
};
// Provide pointer like traits to support use with pointer unions and sum
@ -74,10 +88,10 @@ public:
return reinterpret_cast<void *>(P.Value);
}
static inline T getFromVoidPointer(void *P) {
return T(reinterpret_cast<uintptr_t>(P));
return T(reinterpret_cast<uintptr_t>(P), typename T::RawValueTag());
}
static inline T getFromVoidPointer(const void *P) {
return T(reinterpret_cast<uintptr_t>(P));
return T(reinterpret_cast<uintptr_t>(P), typename T::RawValueTag());
}
enum { NumLowBitsAvailable = T::Shift };

View File

@ -28,7 +28,7 @@ namespace llvm {
// visited nodes during the po_iterator's depth-first traversal.
//
// The default implementation simply contains a set of visited nodes, while
// the Extended=true version uses a reference to an external set.
// the External=true version uses a reference to an external set.
//
// It is possible to prune the depth-first traversal in several ways:
//

View File

@ -0,0 +1,224 @@
//===- PriorityWorklist.h - Worklist with insertion priority ----*- 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 priority worklist. See the class comments for details.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_ADT_PRIORITYWORKLIST_H
#define LLVM_ADT_PRIORITYWORKLIST_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include <algorithm>
#include <cassert>
#include <utility>
#include <vector>
namespace llvm {
/// A FILO worklist that prioritizes on re-insertion without duplication.
///
/// This is very similar to a \c SetVector with the primary difference that
/// while re-insertion does not create a duplicate, it does adjust the
/// visitation order to respect the last insertion point. This can be useful
/// when the visit order needs to be prioritized based on insertion point
/// without actually having duplicate visits.
///
/// Note that this doesn't prevent re-insertion of elements which have been
/// visited -- if you need to break cycles, a set will still be necessary.
///
/// The type \c T must be default constructable to a null value that will be
/// ignored. It is an error to insert such a value, and popping elements will
/// never produce such a value. It is expected to be used with common nullable
/// types like pointers or optionals.
///
/// Internally this uses a vector to store the worklist and a map to identify
/// existing elements in the worklist. Both of these may be customized, but the
/// map must support the basic DenseMap API for mapping from a T to an integer
/// index into the vector.
///
/// A partial specialization is provided to automatically select a SmallVector
/// and a SmallDenseMap if custom data structures are not provided.
template <typename T, typename VectorT = std::vector<T>,
typename MapT = DenseMap<T, ptrdiff_t>>
class PriorityWorklist {
public:
typedef T value_type;
typedef T key_type;
typedef T& reference;
typedef const T& const_reference;
typedef typename MapT::size_type size_type;
/// Construct an empty PriorityWorklist
PriorityWorklist() {}
/// Determine if the PriorityWorklist is empty or not.
bool empty() const {
return V.empty();
}
/// Returns the number of elements in the worklist.
size_type size() const {
return M.size();
}
/// Count the number of elements of a given key in the PriorityWorklist.
/// \returns 0 if the element is not in the PriorityWorklist, 1 if it is.
size_type count(const key_type &key) const {
return M.count(key);
}
/// Return the last element of the PriorityWorklist.
const T &back() const {
assert(!empty() && "Cannot call back() on empty PriorityWorklist!");
return V.back();
}
/// Insert a new element into the PriorityWorklist.
/// \returns true if the element was inserted into the PriorityWorklist.
bool insert(const T &X) {
assert(X != T() && "Cannot insert a null (default constructed) value!");
auto InsertResult = M.insert({X, V.size()});
if (InsertResult.second) {
// Fresh value, just append it to the vector.
V.push_back(X);
return true;
}
auto &Index = InsertResult.first->second;
assert(V[Index] == X && "Value not actually at index in map!");
if (Index != (ptrdiff_t)(V.size() - 1)) {
// If the element isn't at the back, null it out and append a fresh one.
V[Index] = T();
Index = (ptrdiff_t)V.size();
V.push_back(X);
}
return false;
}
/// Remove the last element of the PriorityWorklist.
void pop_back() {
assert(!empty() && "Cannot remove an element when empty!");
assert(back() != T() && "Cannot have a null element at the back!");
M.erase(back());
do {
V.pop_back();
} while (!V.empty() && V.back() == T());
}
T LLVM_ATTRIBUTE_UNUSED_RESULT pop_back_val() {
T Ret = back();
pop_back();
return Ret;
}
/// Erase an item from the worklist.
///
/// Note that this is constant time due to the nature of the worklist implementation.
bool erase(const T& X) {
auto I = M.find(X);
if (I == M.end())
return false;
assert(V[I->second] == X && "Value not actually at index in map!");
if (I->second == (ptrdiff_t)(V.size() - 1)) {
do {
V.pop_back();
} while (!V.empty() && V.back() == T());
} else {
V[I->second] = T();
}
M.erase(I);
return true;
}
/// Erase items from the set vector based on a predicate function.
///
/// This is intended to be equivalent to the following code, if we could
/// write it:
///
/// \code
/// V.erase(std::remove_if(V.begin(), V.end(), P), V.end());
/// \endcode
///
/// However, PriorityWorklist doesn't expose non-const iterators, making any
/// algorithm like remove_if impossible to use.
///
/// \returns true if any element is removed.
template <typename UnaryPredicate>
bool erase_if(UnaryPredicate P) {
typename VectorT::iterator E = std::remove_if(
V.begin(), V.end(), TestAndEraseFromMap<UnaryPredicate>(P, M));
if (E == V.end())
return false;
for (auto I = V.begin(); I != E; ++I)
if (*I != T())
M[*I] = I - V.begin();
V.erase(E, V.end());
return true;
}
/// Completely clear the PriorityWorklist
void clear() {
M.clear();
V.clear();
}
private:
/// A wrapper predicate designed for use with std::remove_if.
///
/// This predicate wraps a predicate suitable for use with std::remove_if to
/// call M.erase(x) on each element which is slated for removal. This just
/// allows the predicate to be move only which we can't do with lambdas
/// today.
template <typename UnaryPredicateT>
class TestAndEraseFromMap {
UnaryPredicateT P;
MapT &M;
public:
TestAndEraseFromMap(UnaryPredicateT P, MapT &M)
: P(std::move(P)), M(M) {}
bool operator()(const T &Arg) {
if (Arg == T())
// Skip null values in the PriorityWorklist.
return false;
if (P(Arg)) {
M.erase(Arg);
return true;
}
return false;
}
};
/// The map from value to index in the vector.
MapT M;
/// The vector of elements in insertion order.
VectorT V;
};
/// A version of \c PriorityWorklist that selects small size optimized data
/// structures for the vector and map.
template <typename T, unsigned N>
class SmallPriorityWorklist
: public PriorityWorklist<T, SmallVector<T, N>,
SmallDenseMap<T, ptrdiff_t>> {
public:
SmallPriorityWorklist() {}
};
}
#endif

View File

@ -17,7 +17,6 @@
#ifndef LLVM_ADT_STLEXTRAS_H
#define LLVM_ADT_STLEXTRAS_H
#include "llvm/Support/Compiler.h"
#include <algorithm> // for std::all_of
#include <cassert>
#include <cstddef> // for std::size_t
@ -27,6 +26,9 @@
#include <memory>
#include <utility> // for std::pair
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Compiler.h"
namespace llvm {
//===----------------------------------------------------------------------===//
@ -117,7 +119,9 @@ public:
iterator_category;
typedef typename std::iterator_traits<RootIt>::difference_type
difference_type;
typedef typename UnaryFunc::result_type value_type;
typedef typename std::result_of<
UnaryFunc(decltype(*std::declval<RootIt>()))>
::type value_type;
typedef void pointer;
//typedef typename UnaryFunc::result_type *pointer;
@ -379,6 +383,14 @@ bool any_of(R &&Range, UnaryPredicate &&P) {
std::forward<UnaryPredicate>(P));
}
/// Provide wrappers to std::none_of which take ranges instead of having to pass
/// begin/end explicitly.
template <typename R, class UnaryPredicate>
bool none_of(R &&Range, UnaryPredicate &&P) {
return std::none_of(Range.begin(), Range.end(),
std::forward<UnaryPredicate>(P));
}
/// Provide wrappers to std::find which take ranges instead of having to pass
/// begin/end explicitly.
template<typename R, class T>
@ -386,6 +398,43 @@ auto find(R &&Range, const T &val) -> decltype(Range.begin()) {
return std::find(Range.begin(), Range.end(), val);
}
/// Provide wrappers to std::find_if which take ranges instead of having to pass
/// begin/end explicitly.
template <typename R, class T>
auto find_if(R &&Range, const T &Pred) -> decltype(Range.begin()) {
return std::find_if(Range.begin(), Range.end(), Pred);
}
/// Provide wrappers to std::remove_if which take ranges instead of having to
/// pass begin/end explicitly.
template<typename R, class UnaryPredicate>
auto remove_if(R &&Range, UnaryPredicate &&P) -> decltype(Range.begin()) {
return std::remove_if(Range.begin(), Range.end(), P);
}
/// Wrapper function around std::find to detect if an element exists
/// in a container.
template <typename R, typename E>
bool is_contained(R &&Range, const E &Element) {
return std::find(Range.begin(), Range.end(), Element) != Range.end();
}
/// Wrapper function around std::count_if to count the number of times an
/// element satisfying a given predicate occurs in a range.
template <typename R, typename UnaryPredicate>
auto count_if(R &&Range, UnaryPredicate &&P)
-> typename std::iterator_traits<decltype(Range.begin())>::difference_type {
return std::count_if(Range.begin(), Range.end(), P);
}
/// Wrapper function around std::transform to apply a function to a range and
/// store the result elsewhere.
template <typename R, class OutputIt, typename UnaryPredicate>
OutputIt transform(R &&Range, OutputIt d_first, UnaryPredicate &&P) {
return std::transform(Range.begin(), Range.end(), d_first,
std::forward<UnaryPredicate>(P));
}
//===----------------------------------------------------------------------===//
// Extra additions to <memory>
//===----------------------------------------------------------------------===//

View File

@ -0,0 +1,79 @@
//===- Sequence.h - Utility for producing sequences of values ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
/// This routine provides some synthesis utilities to produce sequences of
/// values. The names are intentionally kept very short as they tend to occur
/// in common and widely used contexts.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_ADT_SEQ_H
#define LLVM_ADT_SEQ_H
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
namespace llvm {
namespace detail {
template <typename ValueT>
class value_sequence_iterator
: public iterator_facade_base<value_sequence_iterator<ValueT>,
std::random_access_iterator_tag,
const ValueT> {
typedef typename value_sequence_iterator::iterator_facade_base BaseT;
ValueT Value;
public:
typedef typename BaseT::difference_type difference_type;
typedef typename BaseT::reference reference;
value_sequence_iterator() = default;
value_sequence_iterator(const value_sequence_iterator &) = default;
value_sequence_iterator(value_sequence_iterator &&Arg)
: Value(std::move(Arg.Value)) {}
template <typename U, typename Enabler = decltype(ValueT(std::declval<U>()))>
value_sequence_iterator(U &&Value) : Value(std::forward<U>(Value)) {}
value_sequence_iterator &operator+=(difference_type N) {
Value += N;
return *this;
}
value_sequence_iterator &operator-=(difference_type N) {
Value -= N;
return *this;
}
using BaseT::operator-;
difference_type operator-(const value_sequence_iterator &RHS) const {
return Value - RHS.Value;
}
bool operator==(const value_sequence_iterator &RHS) const {
return Value == RHS.Value;
}
bool operator<(const value_sequence_iterator &RHS) const {
return Value < RHS.Value;
}
reference operator*() const { return Value; }
};
} // End detail namespace.
template <typename ValueT>
iterator_range<detail::value_sequence_iterator<ValueT>> seq(ValueT Begin,
ValueT End) {
return make_range(detail::value_sequence_iterator<ValueT>(Begin),
detail::value_sequence_iterator<ValueT>(End));
}
}
#endif

View File

@ -24,6 +24,7 @@
#include "llvm/ADT/SmallSet.h"
#include <algorithm>
#include <cassert>
#include <utility>
#include <vector>
namespace llvm {
@ -123,7 +124,7 @@ public:
}
/// \brief Insert a new element into the SetVector.
/// \returns true iff the element was inserted into the SetVector.
/// \returns true if the element was inserted into the SetVector.
bool insert(const value_type &X) {
bool result = set_.insert(X).second;
if (result)
@ -151,6 +152,24 @@ public:
return false;
}
/// Erase a single element from the set vector.
/// \returns an iterator pointing to the next element that followed the
/// element erased. This is the end of the SetVector if the last element is
/// erased.
iterator erase(iterator I) {
const key_type &V = *I;
assert(set_.count(V) && "Corrupted SetVector instances!");
set_.erase(V);
// FIXME: No need to use the non-const iterator when built with
// std:vector.erase(const_iterator) as defined in C++11. This is for
// compatibility with non-standard libstdc++ up to 4.8 (fixed in 4.9).
auto NI = vector_.begin();
std::advance(NI, std::distance<iterator>(NI, I));
return vector_.erase(NI);
}
/// \brief Remove items from the set vector based on a predicate function.
///
/// This is intended to be equivalent to the following code, if we could
@ -207,6 +226,31 @@ public:
bool operator!=(const SetVector &that) const {
return vector_ != that.vector_;
}
/// \brief Compute This := This u S, return whether 'This' changed.
/// TODO: We should be able to use set_union from SetOperations.h, but
/// SetVector interface is inconsistent with DenseSet.
template <class STy>
bool set_union(const STy &S) {
bool Changed = false;
for (typename STy::const_iterator SI = S.begin(), SE = S.end(); SI != SE;
++SI)
if (insert(*SI))
Changed = true;
return Changed;
}
/// \brief Compute This := This - B
/// TODO: We should be able to use set_subtract from SetOperations.h, but
/// SetVector interface is inconsistent with DenseSet.
template <class STy>
void set_subtract(const STy &S) {
for (typename STy::const_iterator SI = S.begin(), SE = S.end(); SI != SE;
++SI)
remove(*SI);
}
private:
/// \brief A wrapper predicate designed for use with std::remove_if.
@ -219,7 +263,8 @@ private:
set_type &set_;
public:
TestAndEraseFromSet(UnaryPredicate P, set_type &set_) : P(P), set_(set_) {}
TestAndEraseFromSet(UnaryPredicate P, set_type &set_)
: P(std::move(P)), set_(set_) {}
template <typename ArgumentT>
bool operator()(const ArgumentT &Arg) {

View File

@ -15,19 +15,16 @@
#define LLVM_ADT_SMALLBITVECTOR_H
#include "llvm/ADT/BitVector.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MathExtras.h"
#include <cassert>
namespace llvm {
/// SmallBitVector - This is a 'bitvector' (really, a variable-sized bit array),
/// optimized for the case when the array is small. It contains one
/// pointer-sized field, which is directly used as a plain collection of bits
/// when possible, or as a pointer to a larger heap-allocated array when
/// necessary. This allows normal "small" cases to be fast without losing
/// generality for large inputs.
///
/// This is a 'bitvector' (really, a variable-sized bit array), optimized for
/// the case when the array is small. It contains one pointer-sized field, which
/// is directly used as a plain collection of bits when possible, or as a
/// pointer to a larger heap-allocated array when necessary. This allows normal
/// "small" cases to be fast without losing generality for large inputs.
class SmallBitVector {
// TODO: In "large" mode, a pointer to a BitVector is used, leading to an
// unnecessary level of indirection. It would be more efficient to use a
@ -139,11 +136,11 @@ private:
}
public:
/// SmallBitVector default ctor - Creates an empty bitvector.
/// Creates an empty bitvector.
SmallBitVector() : X(1) {}
/// SmallBitVector ctor - Creates a bitvector of specified number of bits. All
/// bits are initialized to the specified value.
/// Creates a bitvector of specified number of bits. All bits are initialized
/// to the specified value.
explicit SmallBitVector(unsigned s, bool t = false) {
if (s <= SmallNumDataBits)
switchToSmall(t ? ~uintptr_t(0) : 0, s);
@ -168,17 +165,17 @@ public:
delete getPointer();
}
/// empty - Tests whether there are no bits in this bitvector.
/// Tests whether there are no bits in this bitvector.
bool empty() const {
return isSmall() ? getSmallSize() == 0 : getPointer()->empty();
}
/// size - Returns the number of bits in this bitvector.
/// Returns the number of bits in this bitvector.
size_t size() const {
return isSmall() ? getSmallSize() : getPointer()->size();
}
/// count - Returns the number of bits which are set.
/// Returns the number of bits which are set.
size_type count() const {
if (isSmall()) {
uintptr_t Bits = getSmallBits();
@ -187,29 +184,28 @@ public:
return getPointer()->count();
}
/// any - Returns true if any bit is set.
/// Returns true if any bit is set.
bool any() const {
if (isSmall())
return getSmallBits() != 0;
return getPointer()->any();
}
/// all - Returns true if all bits are set.
/// Returns true if all bits are set.
bool all() const {
if (isSmall())
return getSmallBits() == (uintptr_t(1) << getSmallSize()) - 1;
return getPointer()->all();
}
/// none - Returns true if none of the bits are set.
/// Returns true if none of the bits are set.
bool none() const {
if (isSmall())
return getSmallBits() == 0;
return getPointer()->none();
}
/// find_first - Returns the index of the first set bit, -1 if none
/// of the bits are set.
/// Returns the index of the first set bit, -1 if none of the bits are set.
int find_first() const {
if (isSmall()) {
uintptr_t Bits = getSmallBits();
@ -220,8 +216,8 @@ public:
return getPointer()->find_first();
}
/// find_next - Returns the index of the next set bit following the
/// "Prev" bit. Returns -1 if the next set bit is not found.
/// Returns the index of the next set bit following the "Prev" bit.
/// Returns -1 if the next set bit is not found.
int find_next(unsigned Prev) const {
if (isSmall()) {
uintptr_t Bits = getSmallBits();
@ -234,14 +230,14 @@ public:
return getPointer()->find_next(Prev);
}
/// clear - Clear all bits.
/// Clear all bits.
void clear() {
if (!isSmall())
delete getPointer();
switchToSmall(0, 0);
}
/// resize - Grow or shrink the bitvector.
/// Grow or shrink the bitvector.
void resize(unsigned N, bool t = false) {
if (!isSmall()) {
getPointer()->resize(N, t);
@ -296,7 +292,7 @@ public:
return *this;
}
/// set - Efficiently set a range of bits in [I, E)
/// Efficiently set a range of bits in [I, E)
SmallBitVector &set(unsigned I, unsigned E) {
assert(I <= E && "Attempted to set backwards range!");
assert(E <= size() && "Attempted to set out-of-bounds range!");
@ -327,7 +323,7 @@ public:
return *this;
}
/// reset - Efficiently reset a range of bits in [I, E)
/// Efficiently reset a range of bits in [I, E)
SmallBitVector &reset(unsigned I, unsigned E) {
assert(I <= E && "Attempted to reset backwards range!");
assert(E <= size() && "Attempted to reset out-of-bounds range!");
@ -422,7 +418,7 @@ public:
return *this;
}
/// reset - Reset bits that are set in RHS. Same as *this &= ~RHS.
/// Reset bits that are set in RHS. Same as *this &= ~RHS.
SmallBitVector &reset(const SmallBitVector &RHS) {
if (isSmall() && RHS.isSmall())
setSmallBits(getSmallBits() & ~RHS.getSmallBits());
@ -436,8 +432,7 @@ public:
return *this;
}
/// test - Check if (This - RHS) is zero.
/// This is the same as reset(RHS) and any().
/// Check if (This - RHS) is zero. This is the same as reset(RHS) and any().
bool test(const SmallBitVector &RHS) const {
if (isSmall() && RHS.isSmall())
return (getSmallBits() & ~RHS.getSmallBits()) != 0;
@ -514,7 +509,7 @@ public:
std::swap(X, RHS.X);
}
/// setBitsInMask - Add '1' bits from Mask to this vector. Don't resize.
/// Add '1' bits from Mask to this vector. Don't resize.
/// This computes "*this |= Mask".
void setBitsInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
if (isSmall())
@ -523,8 +518,8 @@ public:
getPointer()->setBitsInMask(Mask, MaskWords);
}
/// clearBitsInMask - Clear any bits in this vector that are set in Mask.
/// Don't resize. This computes "*this &= ~Mask".
/// Clear any bits in this vector that are set in Mask. Don't resize.
/// This computes "*this &= ~Mask".
void clearBitsInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
if (isSmall())
applyMask<false, false>(Mask, MaskWords);
@ -532,8 +527,8 @@ public:
getPointer()->clearBitsInMask(Mask, MaskWords);
}
/// setBitsNotInMask - Add a bit to this vector for every '0' bit in Mask.
/// Don't resize. This computes "*this |= ~Mask".
/// Add a bit to this vector for every '0' bit in Mask. Don't resize.
/// This computes "*this |= ~Mask".
void setBitsNotInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
if (isSmall())
applyMask<true, true>(Mask, MaskWords);
@ -541,8 +536,8 @@ public:
getPointer()->setBitsNotInMask(Mask, MaskWords);
}
/// clearBitsNotInMask - Clear a bit in this vector for every '0' bit in Mask.
/// Don't resize. This computes "*this &= Mask".
/// Clear a bit in this vector for every '0' bit in Mask. Don't resize.
/// This computes "*this &= Mask".
void clearBitsNotInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
if (isSmall())
applyMask<false, true>(Mask, MaskWords);

View File

@ -21,6 +21,7 @@
#include <cassert>
#include <cstddef>
#include <cstring>
#include <cstdlib>
#include <iterator>
#include <utility>
@ -58,36 +59,45 @@ protected:
/// CurArraySize - The allocated size of CurArray, always a power of two.
unsigned CurArraySize;
// If small, this is # elts allocated consecutively
unsigned NumElements;
/// Number of elements in CurArray that contain a value or are a tombstone.
/// If small, all these elements are at the beginning of CurArray and the rest
/// is uninitialized.
unsigned NumNonEmpty;
/// Number of tombstones in CurArray.
unsigned NumTombstones;
// Helpers to copy and move construct a SmallPtrSet.
SmallPtrSetImplBase(const void **SmallStorage, const SmallPtrSetImplBase &that);
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) {
SmallPtrSetImplBase &&that);
explicit SmallPtrSetImplBase(const void **SmallStorage, unsigned SmallSize)
: SmallArray(SmallStorage), CurArray(SmallStorage),
CurArraySize(SmallSize), NumNonEmpty(0), NumTombstones(0) {
assert(SmallSize && (SmallSize & (SmallSize-1)) == 0 &&
"Initial size must be a power of two!");
clear();
}
~SmallPtrSetImplBase();
~SmallPtrSetImplBase() {
if (!isSmall())
free(CurArray);
}
public:
typedef unsigned size_type;
bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { return size() == 0; }
size_type size() const { return NumElements; }
size_type size() const { return NumNonEmpty - NumTombstones; }
void clear() {
// If the capacity of the array is huge, and the # elements used is small,
// shrink the array.
if (!isSmall() && NumElements*4 < CurArraySize && CurArraySize > 32)
return shrink_and_clear();
if (!isSmall()) {
if (size() * 4 < CurArraySize && CurArraySize > 32)
return shrink_and_clear();
// Fill the array with empty markers.
memset(CurArray, -1, CurArraySize * sizeof(void *));
}
// Fill the array with empty markers.
memset(CurArray, -1, CurArraySize*sizeof(void*));
NumElements = 0;
NumNonEmpty = 0;
NumTombstones = 0;
}
@ -99,10 +109,42 @@ protected:
return reinterpret_cast<void*>(-1);
}
const void **EndPointer() const {
return isSmall() ? CurArray + NumNonEmpty : CurArray + CurArraySize;
}
/// insert_imp - This returns true if the pointer was new to the set, false if
/// it was already in the set. This is hidden from the client so that the
/// derived class can check that the right type of pointer is passed in.
std::pair<const void *const *, bool> insert_imp(const void *Ptr);
std::pair<const void *const *, bool> insert_imp(const void *Ptr) {
if (isSmall()) {
// Check to see if it is already in the set.
const void **LastTombstone = nullptr;
for (const void **APtr = SmallArray, **E = SmallArray + NumNonEmpty;
APtr != E; ++APtr) {
const void *Value = *APtr;
if (Value == Ptr)
return std::make_pair(APtr, false);
if (Value == getTombstoneMarker())
LastTombstone = APtr;
}
// Did we find any tombstone marker?
if (LastTombstone != nullptr) {
*LastTombstone = Ptr;
--NumTombstones;
return std::make_pair(LastTombstone, true);
}
// Nope, there isn't. If we stay small, just 'pushback' now.
if (NumNonEmpty < CurArraySize) {
SmallArray[NumNonEmpty++] = Ptr;
return std::make_pair(SmallArray + (NumNonEmpty - 1), true);
}
// Otherwise, hit the big set case, which will call grow.
}
return insert_imp_big(Ptr);
}
/// erase_imp - If the set contains the specified pointer, remove it and
/// return true, otherwise return false. This is hidden from the client so
@ -114,7 +156,7 @@ protected:
if (isSmall()) {
// Linear search for the item.
for (const void *const *APtr = SmallArray,
*const *E = SmallArray+NumElements; APtr != E; ++APtr)
*const *E = SmallArray + NumNonEmpty; APtr != E; ++APtr)
if (*APtr == Ptr)
return true;
return false;
@ -127,6 +169,8 @@ protected:
private:
bool isSmall() const { return CurArray == SmallArray; }
std::pair<const void *const *, bool> insert_imp_big(const void *Ptr);
const void * const *FindBucketFor(const void *Ptr) const;
void shrink_and_clear();
@ -142,6 +186,12 @@ protected:
void CopyFrom(const SmallPtrSetImplBase &RHS);
void MoveFrom(unsigned SmallSize, SmallPtrSetImplBase &&RHS);
private:
/// Code shared by MoveFrom() and move constructor.
void MoveHelper(unsigned SmallSize, SmallPtrSetImplBase &&RHS);
/// Code shared by CopyFrom() and copy constructor.
void CopyHelper(const SmallPtrSetImplBase &RHS);
};
/// SmallPtrSetIteratorImpl - This is the common base class shared between all
@ -154,7 +204,7 @@ protected:
public:
explicit SmallPtrSetIteratorImpl(const void *const *BP, const void*const *E)
: Bucket(BP), End(E) {
AdvanceIfNotValid();
AdvanceIfNotValid();
}
bool operator==(const SmallPtrSetIteratorImpl &RHS) const {
@ -266,7 +316,7 @@ public:
/// the element equal to Ptr.
std::pair<iterator, bool> insert(PtrType Ptr) {
auto p = insert_imp(PtrTraits::getAsVoidPointer(Ptr));
return std::make_pair(iterator(p.first, CurArray + CurArraySize), p.second);
return std::make_pair(iterator(p.first, EndPointer()), p.second);
}
/// erase - If the set contains the specified pointer, remove it and return
@ -287,10 +337,11 @@ public:
}
inline iterator begin() const {
return iterator(CurArray, CurArray+CurArraySize);
return iterator(CurArray, EndPointer());
}
inline iterator end() const {
return iterator(CurArray+CurArraySize, CurArray+CurArraySize);
const void *const *End = EndPointer();
return iterator(End, End);
}
};
@ -300,6 +351,11 @@ public:
/// SmallPtrSetImplBase for details of the algorithm.
template<class PtrType, unsigned SmallSize>
class SmallPtrSet : public SmallPtrSetImpl<PtrType> {
// In small mode SmallPtrSet uses linear search for the elements, so it is
// not a good idea to choose this value too high. You may consider using a
// DenseSet<> instead if you expect many elements in the set.
static_assert(SmallSize <= 32, "SmallSize should be small");
typedef SmallPtrSetImpl<PtrType> BaseT;
// Make sure that SmallSize is a power of two, round up if not.

View File

@ -38,6 +38,11 @@ class SmallSet {
typedef typename SmallVector<T, N>::const_iterator VIterator;
typedef typename SmallVector<T, N>::iterator mutable_iterator;
// In small mode SmallPtrSet uses linear search for the elements, so it is
// not a good idea to choose this value too high. You may consider using a
// DenseSet<> instead if you expect many elements in the set.
static_assert(N <= 32, "N should be small");
public:
typedef size_t size_type;
SmallSet() {}

View File

@ -184,33 +184,12 @@ protected:
}
}
/// Use move-assignment to move the range [I, E) onto the
/// objects starting with "Dest". This is just <memory>'s
/// std::move, but not all stdlibs actually provide that.
template<typename It1, typename It2>
static It2 move(It1 I, It1 E, It2 Dest) {
for (; I != E; ++I, ++Dest)
*Dest = ::std::move(*I);
return Dest;
}
/// Use move-assignment to move the range
/// [I, E) onto the objects ending at "Dest", moving objects
/// in reverse order. This is just <algorithm>'s
/// 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) {
while (I != E)
*--Dest = ::std::move(*--E);
return Dest;
}
/// 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) {
for (; I != E; ++I, ++Dest)
::new ((void*) &*Dest) T(::std::move(*I));
std::uninitialized_copy(std::make_move_iterator(I),
std::make_move_iterator(E), Dest);
}
/// Copy the range [I, E) onto the uninitialized memory starting with "Dest",
@ -283,20 +262,6 @@ protected:
// No need to do a destroy loop for POD's.
static void destroy_range(T *, T *) {}
/// Use move-assignment to move the range [I, E) onto the
/// objects starting with "Dest". For PODs, this is just memcpy.
template<typename It1, typename It2>
static It2 move(It1 I, It1 E, It2 Dest) {
return ::std::copy(I, E, Dest);
}
/// Use move-assignment to move the range [I, E) onto the objects ending at
/// "Dest", moving objects in reverse order.
template<typename It1, typename It2>
static It2 move_backward(It1 I, It1 E, It2 Dest) {
return ::std::copy_backward(I, E, Dest);
}
/// Move the range [I, E) onto the uninitialized memory
/// starting with "Dest", constructing elements into it as needed.
template<typename It1, typename It2>
@ -356,6 +321,7 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
SmallVectorImpl(const SmallVectorImpl&) = delete;
public:
typedef typename SuperClass::iterator iterator;
typedef typename SuperClass::const_iterator const_iterator;
typedef typename SuperClass::size_type size_type;
protected:
@ -459,26 +425,33 @@ public:
append(IL);
}
iterator erase(iterator I) {
iterator erase(const_iterator CI) {
// Just cast away constness because this is a non-const member function.
iterator I = const_cast<iterator>(CI);
assert(I >= this->begin() && "Iterator to erase is out of bounds.");
assert(I < this->end() && "Erasing at past-the-end iterator.");
iterator N = I;
// Shift all elts down one.
this->move(I+1, this->end(), I);
std::move(I+1, this->end(), I);
// Drop the last elt.
this->pop_back();
return(N);
}
iterator erase(iterator S, iterator E) {
iterator erase(const_iterator CS, const_iterator CE) {
// Just cast away constness because this is a non-const member function.
iterator S = const_cast<iterator>(CS);
iterator E = const_cast<iterator>(CE);
assert(S >= this->begin() && "Range to erase is out of bounds.");
assert(S <= E && "Trying to erase invalid range.");
assert(E <= this->end() && "Trying to erase past the end.");
iterator N = S;
// Shift all elts down.
iterator I = this->move(E, this->end(), S);
iterator I = std::move(E, this->end(), S);
// Drop the last elts.
this->destroy_range(I, this->end());
this->setEnd(I);
@ -502,7 +475,7 @@ public:
::new ((void*) this->end()) T(::std::move(this->back()));
// Push everything else over.
this->move_backward(I, this->end()-1, this->end());
std::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
@ -531,7 +504,7 @@ public:
}
::new ((void*) this->end()) T(std::move(this->back()));
// Push everything else over.
this->move_backward(I, this->end()-1, this->end());
std::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
@ -572,7 +545,7 @@ public:
std::move_iterator<iterator>(this->end()));
// Copy the existing elements that get replaced.
this->move_backward(I, OldEnd-NumToInsert, OldEnd);
std::move_backward(I, OldEnd-NumToInsert, OldEnd);
std::fill_n(I, NumToInsert, Elt);
return I;
@ -626,7 +599,7 @@ public:
std::move_iterator<iterator>(this->end()));
// Copy the existing elements that get replaced.
this->move_backward(I, OldEnd-NumToInsert, OldEnd);
std::move_backward(I, OldEnd-NumToInsert, OldEnd);
std::copy(From, To, I);
return I;
@ -807,7 +780,7 @@ SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) {
// Assign common elements.
iterator NewEnd = this->begin();
if (RHSSize)
NewEnd = this->move(RHS.begin(), RHS.end(), NewEnd);
NewEnd = std::move(RHS.begin(), RHS.end(), NewEnd);
// Destroy excess elements and trim the bounds.
this->destroy_range(NewEnd, this->end());
@ -831,7 +804,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.begin()+CurSize, this->begin());
std::move(RHS.begin(), RHS.begin()+CurSize, this->begin());
}
// Move-construct the new elements in place.

View File

@ -263,6 +263,11 @@ public:
return *insert(ValueT(Key)).first;
}
ValueT pop_back_val() {
// Sparse does not need to be cleared, see find().
return Dense.pop_back_val();
}
/// erase - Erases an existing element identified by a valid iterator.
///
/// This invalidates all iterators, but erase() returns an iterator pointing

View File

@ -27,7 +27,8 @@
#define LLVM_ADT_STATISTIC_H
#include "llvm/Support/Atomic.h"
#include "llvm/Support/Valgrind.h"
#include "llvm/Support/Compiler.h"
#include <atomic>
#include <memory>
namespace llvm {
@ -36,77 +37,66 @@ class raw_fd_ostream;
class Statistic {
public:
const char *DebugType;
const char *Name;
const char *Desc;
volatile llvm::sys::cas_flag Value;
std::atomic<unsigned> Value;
bool Initialized;
llvm::sys::cas_flag getValue() const { return Value; }
unsigned getValue() const { return Value.load(std::memory_order_relaxed); }
const char *getDebugType() const { return DebugType; }
const char *getName() const { return Name; }
const char *getDesc() const { return Desc; }
/// 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 = false;
void construct(const char *debugtype, const char *name, const char *desc) {
DebugType = debugtype;
Name = name;
Desc = desc;
Value = 0;
Initialized = false;
}
// Allow use of this class as the value itself.
operator unsigned() const { return Value; }
operator unsigned() const { return getValue(); }
#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
const Statistic &operator=(unsigned Val) {
Value = Val;
Value.store(Val, std::memory_order_relaxed);
return init();
}
const Statistic &operator++() {
// FIXME: This function and all those that follow carefully use an
// atomic operation to update the value safely in the presence of
// concurrent accesses, but not to read the return value, so the
// return value is not thread safe.
sys::AtomicIncrement(&Value);
Value.fetch_add(1, std::memory_order_relaxed);
return init();
}
unsigned operator++(int) {
init();
unsigned OldValue = Value;
sys::AtomicIncrement(&Value);
return OldValue;
return Value.fetch_add(1, std::memory_order_relaxed);
}
const Statistic &operator--() {
sys::AtomicDecrement(&Value);
Value.fetch_sub(1, std::memory_order_relaxed);
return init();
}
unsigned operator--(int) {
init();
unsigned OldValue = Value;
sys::AtomicDecrement(&Value);
return OldValue;
return Value.fetch_sub(1, std::memory_order_relaxed);
}
const Statistic &operator+=(const unsigned &V) {
if (!V) return *this;
sys::AtomicAdd(&Value, V);
const Statistic &operator+=(unsigned V) {
if (V == 0)
return *this;
Value.fetch_add(V, std::memory_order_relaxed);
return init();
}
const Statistic &operator-=(const unsigned &V) {
if (!V) return *this;
sys::AtomicAdd(&Value, -V);
return init();
}
const Statistic &operator*=(const unsigned &V) {
sys::AtomicMul(&Value, V);
return init();
}
const Statistic &operator/=(const unsigned &V) {
sys::AtomicDiv(&Value, V);
const Statistic &operator-=(unsigned V) {
if (V == 0)
return *this;
Value.fetch_sub(V, std::memory_order_relaxed);
return init();
}
@ -140,14 +130,6 @@ public:
return *this;
}
const Statistic &operator*=(const unsigned &V) {
return *this;
}
const Statistic &operator/=(const unsigned &V) {
return *this;
}
#endif // !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
protected:
@ -163,8 +145,8 @@ protected:
// STATISTIC - A macro to make definition of statistics really simple. This
// automatically passes the DEBUG_TYPE of the file into the statistic.
#define STATISTIC(VARNAME, DESC) \
static llvm::Statistic VARNAME = { DEBUG_TYPE, DESC, 0, 0 }
#define STATISTIC(VARNAME, DESC) \
static llvm::Statistic VARNAME = {DEBUG_TYPE, #VARNAME, DESC, {0}, 0}
/// \brief Enable the collection and printing of statistics.
void EnableStatistics();
@ -181,6 +163,9 @@ void PrintStatistics();
/// \brief Print statistics to the given output stream.
void PrintStatistics(raw_ostream &OS);
} // End llvm namespace
/// Print statistics in JSON format.
void PrintStatisticsJSON(raw_ostream &OS);
#endif
} // end llvm namespace
#endif // LLVM_ADT_STATISTIC_H

View File

@ -44,55 +44,40 @@ static inline unsigned hexDigitValue(char C) {
return -1U;
}
/// utohex_buffer - Emit the specified number into the buffer specified by
/// BufferEnd, returning a pointer to the start of the string. This can be used
/// like this: (note that the buffer must be large enough to handle any number):
/// char Buffer[40];
/// printf("0x%s", utohex_buffer(X, Buffer+40));
///
/// This should only be used with unsigned types.
///
template<typename IntTy>
static inline char *utohex_buffer(IntTy X, char *BufferEnd, bool LowerCase = false) {
char *BufPtr = BufferEnd;
*--BufPtr = 0; // Null terminate buffer.
if (X == 0) {
*--BufPtr = '0'; // Handle special case.
return BufPtr;
}
static inline std::string utohexstr(uint64_t X, bool LowerCase = false) {
char Buffer[17];
char *BufPtr = std::end(Buffer);
if (X == 0) *--BufPtr = '0';
while (X) {
unsigned char Mod = static_cast<unsigned char>(X) & 15;
*--BufPtr = hexdigit(Mod, LowerCase);
X >>= 4;
}
return BufPtr;
return std::string(BufPtr, std::end(Buffer));
}
static inline std::string utohexstr(uint64_t X, bool LowerCase = false) {
char Buffer[17];
return utohex_buffer(X, Buffer+17, LowerCase);
}
/// Convert buffer \p Input to its hexadecimal representation.
/// The returned string is double the size of \p Input.
static inline std::string toHex(StringRef Input) {
static const char *const LUT = "0123456789ABCDEF";
size_t Length = Input.size();
static inline std::string utostr_32(uint32_t X, bool isNeg = false) {
char Buffer[11];
char *BufPtr = Buffer+11;
if (X == 0) *--BufPtr = '0'; // Handle special case...
while (X) {
*--BufPtr = '0' + char(X % 10);
X /= 10;
std::string Output;
Output.reserve(2 * Length);
for (size_t i = 0; i < Length; ++i) {
const unsigned char c = Input[i];
Output.push_back(LUT[c >> 4]);
Output.push_back(LUT[c & 15]);
}
if (isNeg) *--BufPtr = '-'; // Add negative sign...
return std::string(BufPtr, Buffer+11);
return Output;
}
static inline std::string utostr(uint64_t X, bool isNeg = false) {
char Buffer[21];
char *BufPtr = Buffer+21;
char *BufPtr = std::end(Buffer);
if (X == 0) *--BufPtr = '0'; // Handle special case...
@ -102,7 +87,7 @@ static inline std::string utostr(uint64_t X, bool isNeg = false) {
}
if (isNeg) *--BufPtr = '-'; // Add negative sign...
return std::string(BufPtr, Buffer+21);
return std::string(BufPtr, std::end(Buffer));
}

View File

@ -16,6 +16,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
#include <cstring>
#include <utility>
@ -88,12 +89,15 @@ protected:
/// table, returning it. If the key is not in the table, this returns null.
StringMapEntryBase *RemoveKey(StringRef Key);
private:
/// Allocate the table with the specified number of buckets and otherwise
/// setup the map as empty.
void init(unsigned Size);
public:
static StringMapEntryBase *getTombstoneVal() {
return (StringMapEntryBase*)-1;
uintptr_t Val = static_cast<uintptr_t>(-1);
Val <<= PointerLikeTypeTraits<StringMapEntryBase *>::NumLowBitsAvailable;
return reinterpret_cast<StringMapEntryBase *>(Val);
}
unsigned getNumBuckets() const { return NumBuckets; }
@ -122,9 +126,9 @@ public:
explicit StringMapEntry(unsigned strLen)
: StringMapEntryBase(strLen), second() {}
template <class InitTy>
StringMapEntry(unsigned strLen, InitTy &&V)
: StringMapEntryBase(strLen), second(std::forward<InitTy>(V)) {}
template <typename... InitTy>
StringMapEntry(unsigned strLen, InitTy &&... InitVals)
: StringMapEntryBase(strLen), second(std::forward<InitTy>(InitVals)...) {}
StringRef getKey() const {
return StringRef(getKeyData(), getKeyLength());
@ -142,11 +146,11 @@ public:
StringRef first() const { return StringRef(getKeyData(), getKeyLength()); }
/// Create - Create a StringMapEntry for the specified key and default
/// construct the value.
template <typename AllocatorTy, typename InitType>
/// Create a StringMapEntry for the specified key construct the value using
/// \p InitiVals.
template <typename AllocatorTy, typename... InitTy>
static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator,
InitType &&InitVal) {
InitTy &&... InitVals) {
unsigned KeyLength = Key.size();
// Allocate a new item with space for the string at the end and a null
@ -158,8 +162,8 @@ public:
StringMapEntry *NewItem =
static_cast<StringMapEntry*>(Allocator.Allocate(AllocSize,Alignment));
// Default construct the value.
new (NewItem) StringMapEntry(KeyLength, std::forward<InitType>(InitVal));
// Construct the value.
new (NewItem) StringMapEntry(KeyLength, std::forward<InitTy>(InitVals)...);
// Copy the string information.
char *StrBuffer = const_cast<char*>(NewItem->getKeyData());
@ -169,16 +173,11 @@ public:
return NewItem;
}
template<typename AllocatorTy>
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(StringRef Key, InitType &&InitVal) {
template <typename... InitType>
static StringMapEntry *Create(StringRef Key, InitType &&... InitVal) {
MallocAllocator A;
return Create(Key, A, std::forward<InitType>(InitVal));
return Create(Key, A, std::forward<InitType>(InitVal)...);
}
static StringMapEntry *Create(StringRef Key) {
@ -233,7 +232,7 @@ public:
Allocator(A) {}
StringMap(std::initializer_list<std::pair<StringRef, ValueTy>> List)
: StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) {
: StringMapImpl(List.size(), static_cast<unsigned>(sizeof(MapEntryTy))) {
for (const auto &P : List) {
insert(P);
}
@ -248,7 +247,40 @@ public:
return *this;
}
// FIXME: Implement copy operations if/when they're needed.
StringMap(const StringMap &RHS) :
StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))),
Allocator(RHS.Allocator) {
if (RHS.empty())
return;
// Allocate TheTable of the same size as RHS's TheTable, and set the
// sentinel appropriately (and NumBuckets).
init(RHS.NumBuckets);
unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1),
*RHSHashTable = (unsigned *)(RHS.TheTable + NumBuckets + 1);
NumItems = RHS.NumItems;
NumTombstones = RHS.NumTombstones;
for (unsigned I = 0, E = NumBuckets; I != E; ++I) {
StringMapEntryBase *Bucket = RHS.TheTable[I];
if (!Bucket || Bucket == getTombstoneVal()) {
TheTable[I] = Bucket;
continue;
}
TheTable[I] = MapEntryTy::Create(
static_cast<MapEntryTy *>(Bucket)->getKey(), Allocator,
static_cast<MapEntryTy *>(Bucket)->getValue());
HashTable[I] = RHSHashTable[I];
}
// Note that here we've copied everything from the RHS into this object,
// tombstones included. We could, instead, have re-probed for each key to
// instantiate this new object without any tombstone buckets. The
// assumption here is that items are rarely deleted from most StringMaps,
// and so tombstones are rare, so the cost of re-probing for all inputs is
// not worthwhile.
}
AllocatorTy &getAllocator() { return Allocator; }
const AllocatorTy &getAllocator() const { return Allocator; }
@ -295,8 +327,10 @@ public:
return ValueTy();
}
/// Lookup the ValueTy for the \p Key, or create a default constructed value
/// if the key is not in the map.
ValueTy &operator[](StringRef Key) {
return insert(std::make_pair(Key, ValueTy())).first->second;
return emplace_second(Key).first->second;
}
/// count - Return 1 if the element is in the map, 0 otherwise.
@ -328,7 +362,16 @@ public:
/// 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);
return emplace_second(KV.first, std::move(KV.second));
}
/// Emplace a new element for the specified key 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.
template <typename... ArgsTy>
std::pair<iterator, bool> emplace_second(StringRef Key, ArgsTy &&... Args) {
unsigned BucketNo = LookupBucketFor(Key);
StringMapEntryBase *&Bucket = TheTable[BucketNo];
if (Bucket && Bucket != getTombstoneVal())
return std::make_pair(iterator(TheTable + BucketNo, false),
@ -336,8 +379,7 @@ public:
if (Bucket == getTombstoneVal())
--NumTombstones;
Bucket =
MapEntryTy::Create(KV.first, Allocator, std::move(KV.second));
Bucket = MapEntryTy::Create(Key, Allocator, std::forward<ArgsTy>(Args)...);
++NumItems;
assert(NumItems + NumTombstones <= NumBuckets);

View File

@ -10,6 +10,7 @@
#ifndef LLVM_ADT_STRINGREF_H
#define LLVM_ADT_STRINGREF_H
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Compiler.h"
#include <algorithm>
#include <cassert>
@ -101,6 +102,9 @@ namespace llvm {
const unsigned char *bytes_end() const {
return reinterpret_cast<const unsigned char *>(end());
}
iterator_range<const unsigned char *> bytes() const {
return make_range(bytes_begin(), bytes_end());
}
/// @}
/// @name String Operations
@ -133,6 +137,9 @@ namespace llvm {
// copy - Allocate copy in Allocator and return StringRef to it.
template <typename Allocator> StringRef copy(Allocator &A) const {
// Don't request a length 0 copy from the allocator.
if (empty())
return StringRef();
char *S = A.template Allocate<char>(Length);
std::copy(begin(), end(), S);
return StringRef(S, Length);
@ -443,9 +450,10 @@ namespace llvm {
/// empty substring will be returned.
///
/// \param End The index following the last character to include in the
/// substring. If this is npos, or less than \p Start, or exceeds the
/// number of characters remaining in the string, the string suffix
/// (starting with \p Start) will be returned.
/// substring. If this is npos or exceeds the number of characters
/// remaining in the string, the string suffix (starting with \p Start)
/// will be returned. If this is less than \p Start, an empty string will
/// be returned.
LLVM_ATTRIBUTE_ALWAYS_INLINE
StringRef slice(size_t Start, size_t End) const {
Start = std::min(Start, Length);
@ -539,18 +547,36 @@ namespace llvm {
return std::make_pair(slice(0, Idx), slice(Idx+1, npos));
}
/// Return string with consecutive \p Char characters starting from the
/// the left removed.
StringRef ltrim(char Char) const {
return drop_front(std::min(Length, find_first_not_of(Char)));
}
/// Return string with consecutive characters in \p Chars starting from
/// the left removed.
StringRef ltrim(StringRef Chars = " \t\n\v\f\r") const {
return drop_front(std::min(Length, find_first_not_of(Chars)));
}
/// Return string with consecutive \p Char characters starting from the
/// right removed.
StringRef rtrim(char Char) const {
return drop_back(Length - std::min(Length, find_last_not_of(Char) + 1));
}
/// Return string with consecutive characters in \p Chars starting from
/// the right removed.
StringRef rtrim(StringRef Chars = " \t\n\v\f\r") const {
return drop_back(Length - std::min(Length, find_last_not_of(Chars) + 1));
}
/// Return string with consecutive \p Char characters starting from the
/// left and right removed.
StringRef trim(char Char) const {
return ltrim(Char).rtrim(Char);
}
/// Return string with consecutive characters in \p Chars starting from
/// the left and right removed.
StringRef trim(StringRef Chars = " \t\n\v\f\r") const {

View File

@ -33,6 +33,12 @@ namespace llvm {
assert(!Key.empty());
return base::insert(std::make_pair(Key, '\0'));
}
template <typename InputIt>
void insert(const InputIt &Begin, const InputIt &End) {
for (auto It = Begin; It != End; ++It)
base::insert(std::make_pair(*It, '\0'));
}
};
}

View File

@ -104,8 +104,16 @@ public:
/// This also is a constructor for individual array elements due to the single
/// element constructor for ArrayRef.
explicit TinyPtrVector(ArrayRef<EltTy> Elts)
: Val(Elts.size() == 1 ? PtrUnion(Elts[0])
: PtrUnion(new VecTy(Elts.begin(), Elts.end()))) {}
: Val(Elts.empty()
? PtrUnion()
: Elts.size() == 1
? PtrUnion(Elts[0])
: PtrUnion(new VecTy(Elts.begin(), Elts.end()))) {}
TinyPtrVector(size_t Count, EltTy Value)
: Val(Count == 0 ? PtrUnion()
: Count == 1 ? PtrUnion(Value)
: PtrUnion(new VecTy(Count, Value))) {}
// implicit conversion operator to ArrayRef.
operator ArrayRef<EltTy>() const {
@ -125,6 +133,15 @@ public:
return *Val.template get<VecTy*>();
}
// Implicit conversion to ArrayRef<U> if EltTy* implicitly converts to U*.
template<typename U,
typename std::enable_if<
std::is_convertible<ArrayRef<EltTy>, ArrayRef<U>>::value,
bool>::type = false>
operator ArrayRef<U>() const {
return operator ArrayRef<EltTy>();
}
bool empty() const {
// This vector can be empty if it contains no element, or if it
// contains a pointer to an empty vector.
@ -142,8 +159,10 @@ public:
return Val.template get<VecTy*>()->size();
}
typedef const EltTy *const_iterator;
typedef EltTy *iterator;
typedef const EltTy *const_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
iterator begin() {
if (Val.template is<EltTy>())
@ -166,6 +185,15 @@ public:
return (const_iterator)const_cast<TinyPtrVector*>(this)->end();
}
reverse_iterator rbegin() { return reverse_iterator(end()); }
reverse_iterator rend() { return reverse_iterator(begin()); }
const_reverse_iterator rbegin() const {
return const_reverse_iterator(end());
}
const_reverse_iterator rend() const {
return const_reverse_iterator(begin());
}
EltTy operator[](unsigned i) const {
assert(!Val.isNull() && "can't index into an empty vector");
if (EltTy V = Val.template dyn_cast<EltTy>()) {

View File

@ -46,49 +46,52 @@ public:
enum ArchType {
UnknownArch,
arm, // ARM (little endian): arm, armv.*, xscale
armeb, // ARM (big endian): armeb
aarch64, // AArch64 (little endian): aarch64
aarch64_be, // AArch64 (big endian): aarch64_be
avr, // AVR: Atmel AVR microcontroller
bpfel, // eBPF or extended BPF or 64-bit BPF (little endian)
bpfeb, // eBPF or extended BPF or 64-bit BPF (big endian)
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
amdgcn, // AMDGCN: AMD GCN GPUs
sparc, // Sparc: sparc
sparcv9, // Sparcv9: Sparcv9
sparcel, // Sparc: (endianness = little). NB: 'Sparcle' is a CPU variant
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)
le64, // le64: generic little-endian 64-bit CPU (PNaCl)
amdil, // AMDIL
amdil64, // AMDIL with 64-bit pointers
hsail, // AMD HSAIL
hsail64, // AMD HSAIL with 64-bit pointers
spir, // SPIR: standard portable IR for OpenCL 32-bit version
spir64, // SPIR: standard portable IR for OpenCL 64-bit version
kalimba, // Kalimba: generic kalimba
shave, // SHAVE: Movidius vector VLIW processors
wasm32, // WebAssembly with 32-bit pointers
wasm64, // WebAssembly with 64-bit pointers
LastArchType = wasm64
arm, // ARM (little endian): arm, armv.*, xscale
armeb, // ARM (big endian): armeb
aarch64, // AArch64 (little endian): aarch64
aarch64_be, // AArch64 (big endian): aarch64_be
avr, // AVR: Atmel AVR microcontroller
bpfel, // eBPF or extended BPF or 64-bit BPF (little endian)
bpfeb, // eBPF or extended BPF or 64-bit BPF (big endian)
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
amdgcn, // AMDGCN: AMD GCN GPUs
sparc, // Sparc: sparc
sparcv9, // Sparcv9: Sparcv9
sparcel, // Sparc: (endianness = little). NB: 'Sparcle' is a CPU variant
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)
le64, // le64: generic little-endian 64-bit CPU (PNaCl)
amdil, // AMDIL
amdil64, // AMDIL with 64-bit pointers
hsail, // AMD HSAIL
hsail64, // AMD HSAIL with 64-bit pointers
spir, // SPIR: standard portable IR for OpenCL 32-bit version
spir64, // SPIR: standard portable IR for OpenCL 64-bit version
kalimba, // Kalimba: generic kalimba
shave, // SHAVE: Movidius vector VLIW processors
lanai, // Lanai: Lanai 32-bit
wasm32, // WebAssembly with 32-bit pointers
wasm64, // WebAssembly with 64-bit pointers
renderscript32, // 32-bit RenderScript
renderscript64, // 64-bit RenderScript
LastArchType = renderscript64
};
enum SubArchType {
NoSubArch,
@ -96,6 +99,8 @@ public:
ARMSubArch_v8_2a,
ARMSubArch_v8_1a,
ARMSubArch_v8,
ARMSubArch_v8m_baseline,
ARMSubArch_v8m_mainline,
ARMSubArch_v7,
ARMSubArch_v7em,
ARMSubArch_v7m,
@ -128,7 +133,9 @@ public:
NVIDIA,
CSR,
Myriad,
LastVendorType = Myriad
AMD,
Mesa,
LastVendorType = Mesa
};
enum OSType {
UnknownOS,
@ -160,7 +167,8 @@ public:
ELFIAMCU,
TvOS, // Apple tvOS
WatchOS, // Apple watchOS
LastOSType = WatchOS
Mesa3D,
LastOSType = Mesa3D
};
enum EnvironmentType {
UnknownEnvironment,
@ -173,6 +181,9 @@ public:
EABI,
EABIHF,
Android,
Musl,
MuslEABI,
MuslEABIHF,
MSVC,
Itanium,
@ -390,8 +401,8 @@ public:
/// isMacOSXVersionLT - Comparison function for checking OS X version
/// compatibility, which handles supporting skewed version numbering schemes
/// used by the "darwin" triples.
unsigned isMacOSXVersionLT(unsigned Major, unsigned Minor = 0,
unsigned Micro = 0) const {
bool isMacOSXVersionLT(unsigned Major, unsigned Minor = 0,
unsigned Micro = 0) const {
assert(isMacOSX() && "Not an OS X triple!");
// If this is OS X, expect a sane version number.
@ -428,6 +439,10 @@ public:
return getOS() == Triple::WatchOS;
}
bool isWatchABI() const {
return getSubArch() == Triple::ARMSubArch_v7k;
}
/// isOSDarwin - Is this a "Darwin" OS (OS X, iOS, or watchOS).
bool isOSDarwin() const {
return isMacOSX() || isiOS() || isWatchOS();
@ -459,6 +474,12 @@ public:
return getOS() == Triple::ELFIAMCU;
}
bool isGNUEnvironment() const {
EnvironmentType Env = getEnvironment();
return Env == Triple::GNU || Env == Triple::GNUEABI ||
Env == Triple::GNUEABIHF || Env == Triple::GNUX32;
}
/// Checks if the environment could be MSVC.
bool isWindowsMSVCEnvironment() const {
return getOS() == Triple::Win32 &&
@ -513,6 +534,16 @@ public:
return getOS() == Triple::Linux;
}
/// Tests whether the OS is kFreeBSD.
bool isOSKFreeBSD() const {
return getOS() == Triple::KFreeBSD;
}
/// Tests whether the OS uses glibc.
bool isOSGlibc() const {
return getOS() == Triple::Linux || getOS() == Triple::KFreeBSD;
}
/// Tests whether the OS uses the ELF binary format.
bool isOSBinFormatELF() const {
return getObjectFormat() == Triple::ELF;
@ -544,6 +575,21 @@ public:
/// Tests whether the target is Android
bool isAndroid() const { return getEnvironment() == Triple::Android; }
/// Tests whether the environment is musl-libc
bool isMusl() const {
return getEnvironment() == Triple::Musl ||
getEnvironment() == Triple::MuslEABI ||
getEnvironment() == Triple::MuslEABIHF;
}
/// Tests whether the target is NVPTX (32- or 64-bit).
bool isNVPTX() const {
return getArch() == Triple::nvptx || getArch() == Triple::nvptx64;
}
/// Tests wether the target supports comdat
bool supportsCOMDAT() const { return !isOSBinFormatMachO(); }
/// @}
/// @name Mutators
/// @{
@ -632,6 +678,11 @@ public:
/// string then the triple's arch name is used.
StringRef getARMCPUForArch(StringRef Arch = StringRef()) const;
/// Tests whether the target triple is little endian.
///
/// \returns true if the triple is little endian, false otherwise.
bool isLittleEndian() const;
/// @}
/// @name Static helpers for IDs.
/// @{

View File

@ -186,53 +186,38 @@ template<typename Ty>
struct ilist_traits<const Ty> : public ilist_traits<Ty> {};
//===----------------------------------------------------------------------===//
// ilist_iterator<Node> - Iterator for intrusive list.
// Iterator for intrusive list.
//
template<typename NodeTy>
template <typename NodeTy>
class ilist_iterator
: public std::iterator<std::bidirectional_iterator_tag, NodeTy, ptrdiff_t> {
: public std::iterator<std::bidirectional_iterator_tag, NodeTy, ptrdiff_t> {
public:
typedef ilist_traits<NodeTy> Traits;
typedef std::iterator<std::bidirectional_iterator_tag,
NodeTy, ptrdiff_t> super;
typedef std::iterator<std::bidirectional_iterator_tag, NodeTy, ptrdiff_t>
super;
typedef typename super::value_type value_type;
typedef typename super::difference_type difference_type;
typedef typename super::pointer pointer;
typedef typename super::reference reference;
private:
pointer NodePtr;
// ilist_iterator is not a random-access iterator, but it has an
// implicit conversion to pointer-type, which is. Declare (but
// don't define) these functions as private to help catch
// accidental misuse.
void operator[](difference_type) const;
void operator+(difference_type) const;
void operator-(difference_type) const;
void operator+=(difference_type) const;
void operator-=(difference_type) const;
template<class T> void operator<(T) const;
template<class T> void operator<=(T) const;
template<class T> void operator>(T) const;
template<class T> void operator>=(T) const;
template<class T> void operator-(T) const;
public:
explicit ilist_iterator(pointer NP) : NodePtr(NP) {}
explicit ilist_iterator(reference NR) : NodePtr(&NR) {}
ilist_iterator() : NodePtr(nullptr) {}
// This is templated so that we can allow constructing a const iterator from
// a nonconst iterator...
template<class node_ty>
template <class node_ty>
ilist_iterator(const ilist_iterator<node_ty> &RHS)
: NodePtr(RHS.getNodePtrUnchecked()) {}
: NodePtr(RHS.getNodePtrUnchecked()) {}
// This is templated so that we can allow assigning to a const iterator from
// a nonconst iterator...
template<class node_ty>
template <class node_ty>
const ilist_iterator &operator=(const ilist_iterator<node_ty> &RHS) {
NodePtr = RHS.getNodePtrUnchecked();
return *this;
@ -241,13 +226,8 @@ public:
void reset(pointer NP) { NodePtr = NP; }
// Accessors...
explicit operator pointer() const {
return NodePtr;
}
reference operator*() const {
return *NodePtr;
}
explicit operator pointer() const { return NodePtr; }
reference operator*() const { return *NodePtr; }
pointer operator->() const { return &operator*(); }
// Comparison operators
@ -259,21 +239,21 @@ public:
}
// Increment and decrement operators...
ilist_iterator &operator--() { // predecrement - Back up
ilist_iterator &operator--() {
NodePtr = Traits::getPrev(NodePtr);
assert(NodePtr && "--'d off the beginning of an ilist!");
return *this;
}
ilist_iterator &operator++() { // preincrement - Advance
ilist_iterator &operator++() {
NodePtr = Traits::getNext(NodePtr);
return *this;
}
ilist_iterator operator--(int) { // postdecrement operators...
ilist_iterator operator--(int) {
ilist_iterator tmp = *this;
--*this;
return tmp;
}
ilist_iterator operator++(int) { // postincrement operators...
ilist_iterator operator++(int) {
ilist_iterator tmp = *this;
++*this;
return tmp;
@ -283,38 +263,6 @@ public:
pointer getNodePtrUnchecked() const { return NodePtr; }
};
// These are to catch errors when people try to use them as random access
// iterators.
template<typename T>
void operator-(int, ilist_iterator<T>) = delete;
template<typename T>
void operator-(ilist_iterator<T>,int) = delete;
template<typename T>
void operator+(int, ilist_iterator<T>) = delete;
template<typename T>
void operator+(ilist_iterator<T>,int) = delete;
// operator!=/operator== - Allow mixed comparisons without dereferencing
// the iterator, which could very likely be pointing to end().
template<typename T>
bool operator!=(const T* LHS, const ilist_iterator<const T> &RHS) {
return LHS != RHS.getNodePtrUnchecked();
}
template<typename T>
bool operator==(const T* LHS, const ilist_iterator<const T> &RHS) {
return LHS == RHS.getNodePtrUnchecked();
}
template<typename T>
bool operator!=(T* LHS, const ilist_iterator<T> &RHS) {
return LHS != RHS.getNodePtrUnchecked();
}
template<typename T>
bool operator==(T* LHS, const ilist_iterator<T> &RHS) {
return LHS == RHS.getNodePtrUnchecked();
}
// Allow ilist_iterators to convert into pointers to a node automatically when
// used by the dyn_cast, cast, isa mechanisms...
@ -474,6 +422,10 @@ public:
return iterator(New);
}
iterator insert(iterator where, const NodeTy &New) {
return this->insert(where, new NodeTy(New));
}
iterator insertAfter(iterator where, NodeTy *New) {
if (empty())
return insert(begin(), New);
@ -720,7 +672,7 @@ struct ilist : public iplist<NodeTy> {
typedef typename iplist<NodeTy>::iterator iterator;
ilist() {}
ilist(const ilist &right) {
ilist(const ilist &right) : iplist<NodeTy>() {
insert(this->begin(), right.begin(), right.end());
}
explicit ilist(size_type count) {

View File

@ -46,6 +46,22 @@ protected:
std::is_base_of<std::bidirectional_iterator_tag, IteratorCategoryT>::value,
};
/// A proxy object for computing a reference via indirecting a copy of an
/// iterator. This is used in APIs which need to produce a reference via
/// indirection but for which the iterator object might be a temporary. The
/// proxy preserves the iterator internally and exposes the indirected
/// reference via a conversion operator.
class ReferenceProxy {
friend iterator_facade_base;
DerivedT I;
ReferenceProxy(DerivedT I) : I(std::move(I)) {}
public:
operator ReferenceT() const { return *I; }
};
public:
DerivedT operator+(DifferenceTypeT n) const {
static_assert(
@ -120,10 +136,10 @@ public:
PointerT operator->() const {
return &static_cast<const DerivedT *>(this)->operator*();
}
ReferenceT operator[](DifferenceTypeT n) const {
ReferenceProxy operator[](DifferenceTypeT n) const {
static_assert(IsRandomAccess,
"Subscripting is only defined for random access iterators.");
return *static_cast<const DerivedT *>(this)->operator+(n);
return ReferenceProxy(static_cast<const DerivedT *>(this)->operator+(n));
}
};

View File

@ -38,11 +38,11 @@
#ifndef LLVM_ANALYSIS_ALIASANALYSIS_H
#define LLVM_ANALYSIS_ALIASANALYSIS_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Analysis/MemoryLocation.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
namespace llvm {
class BasicAAResult;
@ -50,7 +50,6 @@ class LoadInst;
class StoreInst;
class VAArgInst;
class DataLayout;
class TargetLibraryInfo;
class Pass;
class AnalysisUsage;
class MemTransferInst;
@ -141,7 +140,7 @@ enum FunctionModRefBehavior {
/// non-volatile loads and stores from objects pointed to by its
/// pointer-typed arguments, with arbitrary offsets.
///
/// This property corresponds to the IntrReadWriteArgMem LLVM intrinsic flag.
/// This property corresponds to the IntrArgMemOnly LLVM intrinsic flag.
FMRB_OnlyAccessesArgumentPointees = FMRL_ArgumentPointees | MRI_ModRef,
/// This function does not perform any non-local stores or volatile loads,
@ -152,6 +151,13 @@ enum FunctionModRefBehavior {
/// This property corresponds to the IntrReadMem LLVM intrinsic flag.
FMRB_OnlyReadsMemory = FMRL_Anywhere | MRI_Ref,
// This function does not read from memory anywhere, but may write to any
// memory location.
//
// This property corresponds to the LLVM IR 'writeonly' attribute.
// This property corresponds to the IntrWriteMem LLVM intrinsic flag.
FMRB_DoesNotReadMemory = FMRL_Anywhere | MRI_Mod,
/// This indicates that the function could not be classified into one of the
/// behaviors above.
FMRB_UnknownModRefBehavior = FMRL_Anywhere | MRI_ModRef
@ -161,9 +167,8 @@ class AAResults {
public:
// Make these results default constructable and movable. We have to spell
// these out because MSVC won't synthesize them.
AAResults() {}
AAResults(const TargetLibraryInfo &TLI) : TLI(TLI) {}
AAResults(AAResults &&Arg);
AAResults &operator=(AAResults &&Arg);
~AAResults();
/// Register a specific AA result.
@ -314,6 +319,12 @@ public:
return !(MRB & MRI_Mod);
}
/// Checks if functions with the specified behavior are known to only write
/// memory (or not access memory at all).
static bool doesNotReadMemory(FunctionModRefBehavior MRB) {
return !(MRB & MRI_Ref);
}
/// Checks if functions with the specified behavior are known to read and
/// write at most from objects pointed to by their pointer-typed arguments
/// (with arbitrary offsets).
@ -450,11 +461,11 @@ public:
ModRefInfo getModRefInfo(const Instruction *I) {
if (auto CS = ImmutableCallSite(I)) {
auto MRB = getModRefBehavior(CS);
if (MRB & MRI_ModRef)
if ((MRB & MRI_ModRef) == MRI_ModRef)
return MRI_ModRef;
else if (MRB & MRI_Ref)
if (MRB & MRI_Ref)
return MRI_Ref;
else if (MRB & MRI_Mod)
if (MRB & MRI_Mod)
return MRI_Mod;
return MRI_NoModRef;
}
@ -557,6 +568,8 @@ private:
template <typename T> friend class AAResultBase;
const TargetLibraryInfo &TLI;
std::vector<std::unique_ptr<Concept>> AAs;
};
@ -753,20 +766,23 @@ protected:
}
};
const TargetLibraryInfo &TLI;
explicit AAResultBase(const TargetLibraryInfo &TLI) : TLI(TLI) {}
explicit AAResultBase() {}
// Provide all the copy and move constructors so that derived types aren't
// constrained.
AAResultBase(const AAResultBase &Arg) : TLI(Arg.TLI) {}
AAResultBase(AAResultBase &&Arg) : TLI(Arg.TLI) {}
AAResultBase(const AAResultBase &Arg) {}
AAResultBase(AAResultBase &&Arg) {}
/// Get a proxy for the best AA result set to query at this time.
///
/// When this result is part of a larger aggregation, this will proxy to that
/// aggregation. When this result is used in isolation, it will just delegate
/// back to the derived class's implementation.
///
/// Note that callers of this need to take considerable care to not cause
/// performance problems when they use this routine, in the case of a large
/// number of alias analyses being aggregated, it can be expensive to walk
/// back across the chain.
AAResultsProxy getBestAAResults() { return AAResultsProxy(AAR, derived()); }
public:
@ -783,13 +799,6 @@ public:
}
FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS) {
if (!CS.hasOperandBundles())
// If CS has operand bundles then aliasing attributes from the function it
// calls do not directly apply to the CallSite. This can be made more
// precise in the future.
if (const Function *F = CS.getCalledFunction())
return getBestAAResults().getModRefBehavior(F);
return FMRB_UnknownModRefBehavior;
}
@ -797,170 +806,24 @@ public:
return FMRB_UnknownModRefBehavior;
}
ModRefInfo getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc);
ModRefInfo getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc) {
return MRI_ModRef;
}
ModRefInfo getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2);
ModRefInfo getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2) {
return MRI_ModRef;
}
};
/// Synthesize \c ModRefInfo for a call site and memory location by examining
/// the general behavior of the call site and any specific information for its
/// arguments.
///
/// This essentially, delegates across the alias analysis interface to collect
/// information which may be enough to (conservatively) fulfill the query.
template <typename DerivedT>
ModRefInfo AAResultBase<DerivedT>::getModRefInfo(ImmutableCallSite CS,
const MemoryLocation &Loc) {
auto MRB = getBestAAResults().getModRefBehavior(CS);
if (MRB == FMRB_DoesNotAccessMemory)
return MRI_NoModRef;
ModRefInfo Mask = MRI_ModRef;
if (AAResults::onlyReadsMemory(MRB))
Mask = MRI_Ref;
if (AAResults::onlyAccessesArgPointees(MRB)) {
bool DoesAlias = false;
ModRefInfo AllArgsMask = MRI_NoModRef;
if (AAResults::doesAccessArgPointees(MRB)) {
for (ImmutableCallSite::arg_iterator AI = CS.arg_begin(),
AE = CS.arg_end();
AI != AE; ++AI) {
const Value *Arg = *AI;
if (!Arg->getType()->isPointerTy())
continue;
unsigned ArgIdx = std::distance(CS.arg_begin(), AI);
MemoryLocation ArgLoc = MemoryLocation::getForArgument(CS, ArgIdx, TLI);
AliasResult ArgAlias = getBestAAResults().alias(ArgLoc, Loc);
if (ArgAlias != NoAlias) {
ModRefInfo ArgMask = getBestAAResults().getArgModRefInfo(CS, ArgIdx);
DoesAlias = true;
AllArgsMask = ModRefInfo(AllArgsMask | ArgMask);
}
}
}
if (!DoesAlias)
return MRI_NoModRef;
Mask = ModRefInfo(Mask & AllArgsMask);
}
// If Loc is a constant memory location, the call definitely could not
// modify the memory location.
if ((Mask & MRI_Mod) &&
getBestAAResults().pointsToConstantMemory(Loc, /*OrLocal*/ false))
Mask = ModRefInfo(Mask & ~MRI_Mod);
return Mask;
}
/// Synthesize \c ModRefInfo for two call sites by examining the general
/// behavior of the call site and any specific information for its arguments.
///
/// This essentially, delegates across the alias analysis interface to collect
/// information which may be enough to (conservatively) fulfill the query.
template <typename DerivedT>
ModRefInfo AAResultBase<DerivedT>::getModRefInfo(ImmutableCallSite CS1,
ImmutableCallSite CS2) {
// If CS1 or CS2 are readnone, they don't interact.
auto CS1B = getBestAAResults().getModRefBehavior(CS1);
if (CS1B == FMRB_DoesNotAccessMemory)
return MRI_NoModRef;
auto CS2B = getBestAAResults().getModRefBehavior(CS2);
if (CS2B == FMRB_DoesNotAccessMemory)
return MRI_NoModRef;
// If they both only read from memory, there is no dependence.
if (AAResults::onlyReadsMemory(CS1B) && AAResults::onlyReadsMemory(CS2B))
return MRI_NoModRef;
ModRefInfo Mask = MRI_ModRef;
// If CS1 only reads memory, the only dependence on CS2 can be
// from CS1 reading memory written by CS2.
if (AAResults::onlyReadsMemory(CS1B))
Mask = ModRefInfo(Mask & MRI_Ref);
// If CS2 only access memory through arguments, accumulate the mod/ref
// information from CS1's references to the memory referenced by
// CS2's arguments.
if (AAResults::onlyAccessesArgPointees(CS2B)) {
ModRefInfo R = MRI_NoModRef;
if (AAResults::doesAccessArgPointees(CS2B)) {
for (ImmutableCallSite::arg_iterator I = CS2.arg_begin(),
E = CS2.arg_end();
I != E; ++I) {
const Value *Arg = *I;
if (!Arg->getType()->isPointerTy())
continue;
unsigned CS2ArgIdx = std::distance(CS2.arg_begin(), I);
auto CS2ArgLoc = MemoryLocation::getForArgument(CS2, CS2ArgIdx, TLI);
// ArgMask indicates what CS2 might do to CS2ArgLoc, and the dependence
// of CS1 on that location is the inverse.
ModRefInfo ArgMask =
getBestAAResults().getArgModRefInfo(CS2, CS2ArgIdx);
if (ArgMask == MRI_Mod)
ArgMask = MRI_ModRef;
else if (ArgMask == MRI_Ref)
ArgMask = MRI_Mod;
ArgMask = ModRefInfo(ArgMask &
getBestAAResults().getModRefInfo(CS1, CS2ArgLoc));
R = ModRefInfo((R | ArgMask) & Mask);
if (R == Mask)
break;
}
}
return R;
}
// If CS1 only accesses memory through arguments, check if CS2 references
// any of the memory referenced by CS1's arguments. If not, return NoModRef.
if (AAResults::onlyAccessesArgPointees(CS1B)) {
ModRefInfo R = MRI_NoModRef;
if (AAResults::doesAccessArgPointees(CS1B)) {
for (ImmutableCallSite::arg_iterator I = CS1.arg_begin(),
E = CS1.arg_end();
I != E; ++I) {
const Value *Arg = *I;
if (!Arg->getType()->isPointerTy())
continue;
unsigned CS1ArgIdx = std::distance(CS1.arg_begin(), I);
auto CS1ArgLoc = MemoryLocation::getForArgument(CS1, CS1ArgIdx, TLI);
// ArgMask indicates what CS1 might do to CS1ArgLoc; if CS1 might Mod
// CS1ArgLoc, then we care about either a Mod or a Ref by CS2. If CS1
// might Ref, then we care only about a Mod by CS2.
ModRefInfo ArgMask = getBestAAResults().getArgModRefInfo(CS1, CS1ArgIdx);
ModRefInfo ArgR = getBestAAResults().getModRefInfo(CS2, CS1ArgLoc);
if (((ArgMask & MRI_Mod) != MRI_NoModRef &&
(ArgR & MRI_ModRef) != MRI_NoModRef) ||
((ArgMask & MRI_Ref) != MRI_NoModRef &&
(ArgR & MRI_Mod) != MRI_NoModRef))
R = ModRefInfo((R | ArgMask) & Mask);
if (R == Mask)
break;
}
}
return R;
}
return Mask;
}
/// isNoAliasCall - Return true if this pointer is returned by a noalias
/// function.
/// Return true if this pointer is returned by a noalias function.
bool isNoAliasCall(const Value *V);
/// isNoAliasArgument - Return true if this is an argument with the noalias
/// attribute.
/// Return true if this is an argument with the noalias attribute.
bool isNoAliasArgument(const Value *V);
/// isIdentifiedObject - Return true if this pointer refers to a distinct and
/// identifiable object. This returns true for:
/// Return true if this pointer refers to a distinct and identifiable object.
/// This returns true for:
/// Global Variables and Functions (but not Global Aliases)
/// Allocas
/// ByVal and NoAlias Arguments
@ -968,8 +831,8 @@ 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.
/// 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.
@ -987,42 +850,48 @@ bool isIdentifiedFunctionLocal(const Value *V);
/// This manager effectively wraps the AnalysisManager for registering alias
/// analyses. When you register your alias analysis with this manager, it will
/// ensure the analysis itself is registered with its AnalysisManager.
class AAManager {
class AAManager : public AnalysisInfoMixin<AAManager> {
public:
typedef AAResults Result;
// This type hase value semantics. We have to spell these out because MSVC
// won't synthesize them.
AAManager() {}
AAManager(AAManager &&Arg)
: FunctionResultGetters(std::move(Arg.FunctionResultGetters)) {}
AAManager(const AAManager &Arg)
: FunctionResultGetters(Arg.FunctionResultGetters) {}
AAManager(AAManager &&Arg) : ResultGetters(std::move(Arg.ResultGetters)) {}
AAManager(const AAManager &Arg) : ResultGetters(Arg.ResultGetters) {}
AAManager &operator=(AAManager &&RHS) {
FunctionResultGetters = std::move(RHS.FunctionResultGetters);
ResultGetters = std::move(RHS.ResultGetters);
return *this;
}
AAManager &operator=(const AAManager &RHS) {
FunctionResultGetters = RHS.FunctionResultGetters;
ResultGetters = RHS.ResultGetters;
return *this;
}
/// Register a specific AA result.
template <typename AnalysisT> void registerFunctionAnalysis() {
FunctionResultGetters.push_back(&getFunctionAAResultImpl<AnalysisT>);
ResultGetters.push_back(&getFunctionAAResultImpl<AnalysisT>);
}
/// Register a specific AA result.
template <typename AnalysisT> void registerModuleAnalysis() {
ResultGetters.push_back(&getModuleAAResultImpl<AnalysisT>);
}
Result run(Function &F, AnalysisManager<Function> &AM) {
Result R;
for (auto &Getter : FunctionResultGetters)
Result R(AM.getResult<TargetLibraryAnalysis>(F));
for (auto &Getter : ResultGetters)
(*Getter)(F, AM, R);
return R;
}
private:
friend AnalysisInfoMixin<AAManager>;
static char PassID;
SmallVector<void (*)(Function &F, AnalysisManager<Function> &AM,
AAResults &AAResults),
4> FunctionResultGetters;
4> ResultGetters;
template <typename AnalysisT>
static void getFunctionAAResultImpl(Function &F,
@ -1030,6 +899,15 @@ private:
AAResults &AAResults) {
AAResults.addAAResult(AM.template getResult<AnalysisT>(F));
}
template <typename AnalysisT>
static void getModuleAAResultImpl(Function &F, AnalysisManager<Function> &AM,
AAResults &AAResults) {
auto &MAM =
AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
if (auto *R = MAM.template getCachedResult<AnalysisT>(*F.getParent()))
AAResults.addAAResult(*R);
}
};
/// A wrapper pass to provide the legacy pass manager access to a suitably
@ -1065,8 +943,16 @@ ImmutablePass *createExternalAAWrapperPass(
/// A helper for the legacy pass manager to create a \c AAResults
/// object populated to the best of our ability for a particular function when
/// inside of a \c ModulePass or a \c CallGraphSCCPass.
///
/// If a \c ModulePass or a \c CallGraphSCCPass calls \p
/// createLegacyPMAAResults, it also needs to call \p addUsedAAAnalyses in \p
/// getAnalysisUsage.
AAResults createLegacyPMAAResults(Pass &P, Function &F, BasicAAResult &BAR);
/// A helper for the legacy pass manager to populate \p AU to add uses to make
/// sure the analyses required by \p createLegacyPMAAResults are available.
void getAAResultsAnalysisUsage(AnalysisUsage &AU);
} // End llvm namespace
#endif

View File

@ -0,0 +1,70 @@
//===- AliasAnalysisEvaluator.h - Alias Analysis Accuracy Evaluator -------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
///
/// This file implements a simple N^2 alias analysis accuracy evaluator. The
/// analysis result is a set of statistics of how many times the AA
/// infrastructure provides each kind of alias result and mod/ref result when
/// queried with all pairs of pointers in the function.
///
/// It can be used to evaluate a change in an alias analysis implementation,
/// algorithm, or the AA pipeline infrastructure itself. It acts like a stable
/// and easily tested consumer of all AA information exposed.
///
/// This is inspired and adapted from code by: Naveen Neelakantam, Francesco
/// Spadini, and Wojciech Stryjewski.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_ALIASANALYSISEVALUATOR_H
#define LLVM_ANALYSIS_ALIASANALYSISEVALUATOR_H
#include "llvm/IR/Function.h"
#include "llvm/IR/PassManager.h"
namespace llvm {
class AAResults;
class AAEvaluator : public PassInfoMixin<AAEvaluator> {
int64_t FunctionCount;
int64_t NoAliasCount, MayAliasCount, PartialAliasCount, MustAliasCount;
int64_t NoModRefCount, ModCount, RefCount, ModRefCount;
public:
AAEvaluator()
: FunctionCount(), NoAliasCount(), MayAliasCount(), PartialAliasCount(),
MustAliasCount(), NoModRefCount(), ModCount(), RefCount(),
ModRefCount() {}
AAEvaluator(AAEvaluator &&Arg)
: FunctionCount(Arg.FunctionCount), NoAliasCount(Arg.NoAliasCount),
MayAliasCount(Arg.MayAliasCount),
PartialAliasCount(Arg.PartialAliasCount),
MustAliasCount(Arg.MustAliasCount), NoModRefCount(Arg.NoModRefCount),
ModCount(Arg.ModCount), RefCount(Arg.RefCount),
ModRefCount(Arg.ModRefCount) {
Arg.FunctionCount = 0;
}
~AAEvaluator();
/// \brief Run the pass over the function.
PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
private:
// Allow the legacy pass to run this using an internal API.
friend class AAEvalLegacyPass;
void runInternal(Function &F, AAResults &AA);
};
/// Create a wrapper of the above for the legacy pass manager.
FunctionPass *createAAEvalPass();
}
#endif

View File

@ -7,9 +7,9 @@
//
//===----------------------------------------------------------------------===//
//
// This file defines two classes: AliasSetTracker and AliasSet. These interface
// This file defines two classes: AliasSetTracker and AliasSet. These interfaces
// are used to classify a collection of pointer references into a maximal number
// of disjoint sets. Each AliasSet object constructed by the AliasSetTracker
// of disjoint sets. Each AliasSet object constructed by the AliasSetTracker
// object refers to memory disjoint from the other sets.
//
//===----------------------------------------------------------------------===//
@ -30,6 +30,7 @@ namespace llvm {
class LoadInst;
class StoreInst;
class VAArgInst;
class MemSetInst;
class AliasSetTracker;
class AliasSet;
@ -58,8 +59,12 @@ class AliasSet : public ilist_node<AliasSet> {
return &NextInList;
}
void updateSizeAndAAInfo(uint64_t NewSize, const AAMDNodes &NewAAInfo) {
if (NewSize > Size) Size = NewSize;
bool updateSizeAndAAInfo(uint64_t NewSize, const AAMDNodes &NewAAInfo) {
bool SizeChanged = false;
if (NewSize > Size) {
Size = NewSize;
SizeChanged = true;
}
if (AAInfo == DenseMapInfo<AAMDNodes>::getEmptyKey())
// We don't have a AAInfo yet. Set it to NewAAInfo.
@ -67,12 +72,14 @@ class AliasSet : public ilist_node<AliasSet> {
else if (AAInfo != NewAAInfo)
// NewAAInfo conflicts with AAInfo.
AAInfo = DenseMapInfo<AAMDNodes>::getTombstoneKey();
return SizeChanged;
}
uint64_t getSize() const { return Size; }
/// getAAInfo - Return the AAInfo, or null if there is no
/// information or conflicting information.
/// Return the AAInfo, or null if there is no information or conflicting
/// information.
AAMDNodes getAAInfo() const {
// If we have missing or conflicting AAInfo, return null.
if (AAInfo == DenseMapInfo<AAMDNodes>::getEmptyKey() ||
@ -111,11 +118,11 @@ class AliasSet : public ilist_node<AliasSet> {
PointerRec *PtrList, **PtrListEnd; // Doubly linked list of nodes.
AliasSet *Forward; // Forwarding pointer.
// All instructions without a specific address in this alias set.
/// All instructions without a specific address in this alias set.
std::vector<AssertingVH<Instruction> > UnknownInsts;
// RefCount - Number of nodes pointing to this AliasSet plus the number of
// AliasSets forwarding to it.
/// Number of nodes pointing to this AliasSet plus the number of AliasSets
/// forwarding to it.
unsigned RefCount : 28;
/// The kinds of access this alias set models.
@ -143,8 +150,8 @@ class AliasSet : public ilist_node<AliasSet> {
};
unsigned Alias : 1;
// Volatile - True if this alias set contains volatile loads or stores.
bool Volatile : 1;
/// True if this alias set contains volatile loads or stores.
unsigned Volatile : 1;
void addRef() { ++RefCount; }
void dropRef(AliasSetTracker &AST) {
@ -165,20 +172,18 @@ public:
bool isMustAlias() const { return Alias == SetMustAlias; }
bool isMayAlias() const { return Alias == SetMayAlias; }
// isVolatile - Return true if this alias set contains volatile loads or
// stores.
/// Return true if this alias set contains volatile loads or stores.
bool isVolatile() const { return Volatile; }
/// isForwardingAliasSet - Return true if this alias set should be ignored as
/// part of the AliasSetTracker object.
/// Return true if this alias set should be ignored as part of the
/// AliasSetTracker object.
bool isForwardingAliasSet() const { return Forward; }
/// mergeSetIn - Merge the specified alias set into this alias set...
///
/// Merge the specified alias set into this alias set.
void mergeSetIn(AliasSet &AS, AliasSetTracker &AST);
// Alias Set iteration - Allow access to all of the pointer which are part of
// this alias set...
// Alias Set iteration - Allow access to all of the pointers which are part of
// this alias set.
class iterator;
iterator begin() const { return iterator(PtrList); }
iterator end() const { return iterator(); }
@ -236,9 +241,9 @@ private:
return PtrList;
}
/// getForwardedTarget - Return the real alias set this represents. If this
/// has been merged with another set and is forwarding, return the ultimate
/// destination set. This also implements the union-find collapsing as well.
/// Return the real alias set this represents. If this has been merged with
/// another set and is forwarding, return the ultimate destination set. This
/// also implements the union-find collapsing as well.
AliasSet *getForwardedTarget(AliasSetTracker &AST) {
if (!Forward) return this;
@ -271,9 +276,8 @@ private:
void setVolatile() { Volatile = true; }
public:
/// aliasesPointer - Return true if the specified pointer "may" (or must)
/// alias one of the members in the set.
///
/// Return true if the specified pointer "may" (or must) alias one of the
/// members in the set.
bool aliasesPointer(const Value *Ptr, uint64_t Size, const AAMDNodes &AAInfo,
AliasAnalysis &AA) const;
bool aliasesUnknownInst(const Instruction *Inst, AliasAnalysis &AA) const;
@ -285,8 +289,8 @@ inline raw_ostream& operator<<(raw_ostream &OS, const AliasSet &AS) {
}
class AliasSetTracker {
/// CallbackVH - A CallbackVH to arrange for AliasSetTracker to be
/// notified whenever a Value is deleted.
/// A CallbackVH to arrange for AliasSetTracker to be notified whenever a
/// Value is deleted.
class ASTCallbackVH final : public CallbackVH {
AliasSetTracker *AST;
void deleted() override;
@ -296,8 +300,8 @@ class AliasSetTracker {
ASTCallbackVH(Value *V, AliasSetTracker *AST = nullptr);
ASTCallbackVH &operator=(Value *V);
};
/// ASTCallbackVHDenseMapInfo - Traits to tell DenseMap that tell us how to
/// compare and hash the value handle.
/// Traits to tell DenseMap that tell us how to compare and hash the value
/// handle.
struct ASTCallbackVHDenseMapInfo : public DenseMapInfo<Value *> {};
AliasAnalysis &AA;
@ -311,15 +315,14 @@ class AliasSetTracker {
PointerMapType PointerMap;
public:
/// AliasSetTracker ctor - Create an empty collection of AliasSets, and use
/// the specified alias analysis object to disambiguate load and store
/// addresses.
/// Create an empty collection of AliasSets, and use the specified alias
/// analysis object to disambiguate load and store addresses.
explicit AliasSetTracker(AliasAnalysis &aa) : AA(aa) {}
~AliasSetTracker() { clear(); }
/// add methods - These methods are used to add different types of
/// instructions to the alias sets. Adding a new instruction can result in
/// one of three actions happening:
/// These methods are used to add different types of instructions to the alias
/// sets. Adding a new instruction can result in one of three actions
/// happening:
///
/// 1. If the instruction doesn't alias any other sets, create a new set.
/// 2. If the instruction aliases exactly one set, add it to the set
@ -333,47 +336,46 @@ public:
bool add(LoadInst *LI);
bool add(StoreInst *SI);
bool add(VAArgInst *VAAI);
bool add(MemSetInst *MSI);
bool add(Instruction *I); // Dispatch to one of the other add methods...
void add(BasicBlock &BB); // Add all instructions in basic block
void add(const AliasSetTracker &AST); // Add alias relations from another AST
bool addUnknown(Instruction *I);
/// remove methods - These methods are used to remove all entries that might
/// be aliased by the specified instruction. These methods return true if any
/// alias sets were eliminated.
// Remove a location
/// These methods are used to remove all entries that might be aliased by the
/// specified instruction. These methods return true if any alias sets were
/// eliminated.
bool remove(Value *Ptr, uint64_t Size, const AAMDNodes &AAInfo);
bool remove(LoadInst *LI);
bool remove(StoreInst *SI);
bool remove(VAArgInst *VAAI);
bool remove(MemSetInst *MSI);
bool remove(Instruction *I);
void remove(AliasSet &AS);
bool removeUnknown(Instruction *I);
void clear();
/// getAliasSets - Return the alias sets that are active.
///
/// Return the alias sets that are active.
const ilist<AliasSet> &getAliasSets() const { return AliasSets; }
/// getAliasSetForPointer - Return the alias set that the specified pointer
/// lives in. If the New argument is non-null, this method sets the value to
/// true if a new alias set is created to contain the pointer (because the
/// pointer didn't alias anything).
/// Return the alias set that the specified pointer lives in. If the New
/// argument is non-null, this method sets the value to true if a new alias
/// set is created to contain the pointer (because the pointer didn't alias
/// anything).
AliasSet &getAliasSetForPointer(Value *P, uint64_t Size,
const AAMDNodes &AAInfo,
bool *New = nullptr);
/// getAliasSetForPointerIfExists - Return the alias set containing the
/// location specified if one exists, otherwise return null.
/// Return the alias set containing the location specified if one exists,
/// otherwise return null.
AliasSet *getAliasSetForPointerIfExists(const Value *P, uint64_t Size,
const AAMDNodes &AAInfo) {
return findAliasSetForPointer(P, Size, AAInfo);
return mergeAliasSetsForPointer(P, Size, AAInfo);
}
/// containsPointer - Return true if the specified location is represented by
/// this alias set, false otherwise. This does not modify the AST object or
/// alias sets.
/// Return true if the specified location is represented by this alias set,
/// false otherwise. This does not modify the AST object or alias sets.
bool containsPointer(const Value *P, uint64_t Size,
const AAMDNodes &AAInfo) const;
@ -381,23 +383,19 @@ public:
/// members in any of the sets.
bool containsUnknown(const Instruction *I) const;
/// getAliasAnalysis - Return the underlying alias analysis object used by
/// this tracker.
/// Return the underlying alias analysis object used by this tracker.
AliasAnalysis &getAliasAnalysis() const { return AA; }
/// deleteValue method - This method is used to remove a pointer value from
/// the AliasSetTracker entirely. It should be used when an instruction is
/// deleted from the program to update the AST. If you don't use this, you
/// would have dangling pointers to deleted instructions.
///
/// This method is used to remove a pointer value from the AliasSetTracker
/// entirely. It should be used when an instruction is deleted from the
/// program to update the AST. If you don't use this, you would have dangling
/// pointers to deleted instructions.
void deleteValue(Value *PtrVal);
/// copyValue - This method should be used whenever a preexisting value in the
/// program is copied or cloned, introducing a new value. Note that it is ok
/// for clients that use this method to introduce the same value multiple
/// times: if the tracker already knows about a value, it will ignore the
/// request.
///
/// This method should be used whenever a preexisting value in the program is
/// copied or cloned, introducing a new value. Note that it is ok for clients
/// that use this method to introduce the same value multiple times: if the
/// tracker already knows about a value, it will ignore the request.
void copyValue(Value *From, Value *To);
typedef ilist<AliasSet>::iterator iterator;
@ -416,8 +414,8 @@ private:
friend class AliasSet;
void removeAliasSet(AliasSet *AS);
// getEntryFor - Just like operator[] on the map, except that it creates an
// entry for the pointer if it doesn't already exist.
/// Just like operator[] on the map, except that it creates an entry for the
/// pointer if it doesn't already exist.
AliasSet::PointerRec &getEntryFor(Value *V) {
AliasSet::PointerRec *&Entry = PointerMap[ASTCallbackVH(V, this)];
if (!Entry)
@ -433,8 +431,8 @@ private:
AS.Access |= E;
return AS;
}
AliasSet *findAliasSetForPointer(const Value *Ptr, uint64_t Size,
const AAMDNodes &AAInfo);
AliasSet *mergeAliasSetsForPointer(const Value *Ptr, uint64_t Size,
const AAMDNodes &AAInfo);
AliasSet *findAliasSetForUnknownInst(Instruction *Inst);
};

View File

@ -22,16 +22,12 @@
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Pass.h"
#include <memory>
namespace llvm {
// FIXME: Replace this brittle forward declaration with the include of the new
// PassManager.h when doing so doesn't break the PassManagerBuilder.
template <typename IRUnitT> class AnalysisManager;
class PreservedAnalyses;
/// \brief A cache of @llvm.assume calls within a function.
///
/// This cache provides fast lookup of assumptions within a function by caching
@ -97,36 +93,31 @@ public:
///
/// This analysis is intended for use with the new pass manager and will vend
/// assumption caches for a given function.
class AssumptionAnalysis {
class AssumptionAnalysis : public AnalysisInfoMixin<AssumptionAnalysis> {
friend AnalysisInfoMixin<AssumptionAnalysis>;
static char PassID;
public:
typedef AssumptionCache Result;
/// \brief Opaque, unique identifier for this analysis pass.
static void *ID() { return (void *)&PassID; }
/// \brief Provide a name for the analysis for debugging and logging.
static StringRef name() { return "AssumptionAnalysis"; }
AssumptionAnalysis() {}
AssumptionAnalysis(const AssumptionAnalysis &Arg) {}
AssumptionAnalysis(AssumptionAnalysis &&Arg) {}
AssumptionAnalysis &operator=(const AssumptionAnalysis &RHS) { return *this; }
AssumptionAnalysis &operator=(AssumptionAnalysis &&RHS) { return *this; }
AssumptionCache run(Function &F) { return AssumptionCache(F); }
AssumptionCache run(Function &F, FunctionAnalysisManager &) {
return AssumptionCache(F);
}
};
/// \brief Printer pass for the \c AssumptionAnalysis results.
class AssumptionPrinterPass {
class AssumptionPrinterPass : public PassInfoMixin<AssumptionPrinterPass> {
raw_ostream &OS;
public:
explicit AssumptionPrinterPass(raw_ostream &OS) : OS(OS) {}
PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM);
static StringRef name() { return "AssumptionPrinterPass"; }
PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
};
/// \brief An immutable pass that tracks lazily created \c AssumptionCache

View File

@ -40,6 +40,7 @@ class BasicAAResult : public AAResultBase<BasicAAResult> {
friend AAResultBase<BasicAAResult>;
const DataLayout &DL;
const TargetLibraryInfo &TLI;
AssumptionCache &AC;
DominatorTree *DT;
LoopInfo *LI;
@ -48,13 +49,14 @@ public:
BasicAAResult(const DataLayout &DL, const TargetLibraryInfo &TLI,
AssumptionCache &AC, DominatorTree *DT = nullptr,
LoopInfo *LI = nullptr)
: AAResultBase(TLI), DL(DL), AC(AC), DT(DT), LI(LI) {}
: AAResultBase(), DL(DL), TLI(TLI), AC(AC), DT(DT), LI(LI) {}
BasicAAResult(const BasicAAResult &Arg)
: AAResultBase(Arg), DL(Arg.DL), AC(Arg.AC), DT(Arg.DT), LI(Arg.LI) {}
BasicAAResult(BasicAAResult &&Arg)
: AAResultBase(std::move(Arg)), DL(Arg.DL), AC(Arg.AC), DT(Arg.DT),
: AAResultBase(Arg), DL(Arg.DL), TLI(Arg.TLI), AC(Arg.AC), DT(Arg.DT),
LI(Arg.LI) {}
BasicAAResult(BasicAAResult &&Arg)
: AAResultBase(std::move(Arg)), DL(Arg.DL), TLI(Arg.TLI), AC(Arg.AC),
DT(Arg.DT), LI(Arg.LI) {}
/// Handle invalidation events from the new pass manager.
///
@ -107,6 +109,20 @@ private:
}
};
// Represents the internal structure of a GEP, decomposed into a base pointer,
// constant offsets, and variable scaled indices.
struct DecomposedGEP {
// Base pointer of the GEP
const Value *Base;
// Total constant offset w.r.t the base from indexing into structs
int64_t StructOffset;
// Total constant offset w.r.t the base from indexing through
// pointers/arrays/vectors
int64_t OtherOffset;
// Scaled variable (non-constant) indices.
SmallVector<VariableGEPIndex, 4> VarIndices;
};
/// Track alias queries to guard against recursion.
typedef std::pair<MemoryLocation, MemoryLocation> LocPair;
typedef SmallDenseMap<LocPair, AliasResult, 8> AliasCacheTy;
@ -137,11 +153,13 @@ private:
const DataLayout &DL, unsigned Depth, AssumptionCache *AC,
DominatorTree *DT, bool &NSW, bool &NUW);
static const Value *
DecomposeGEPExpression(const Value *V, int64_t &BaseOffs,
SmallVectorImpl<VariableGEPIndex> &VarIndices,
bool &MaxLookupReached, const DataLayout &DL,
AssumptionCache *AC, DominatorTree *DT);
static bool DecomposeGEPExpression(const Value *V, DecomposedGEP &Decomposed,
const DataLayout &DL, AssumptionCache *AC, DominatorTree *DT);
static bool isGEPBaseAtNegativeOffset(const GEPOperator *GEPOp,
const DecomposedGEP &DecompGEP, const DecomposedGEP &DecompObject,
uint64_t ObjectAccessSize);
/// \brief A Heuristic for aliasGEP that searches for a constant offset
/// between the variables.
///
@ -178,20 +196,14 @@ private:
};
/// Analysis pass providing a never-invalidated alias analysis result.
class BasicAA {
class BasicAA : public AnalysisInfoMixin<BasicAA> {
friend AnalysisInfoMixin<BasicAA>;
static char PassID;
public:
typedef BasicAAResult Result;
/// \brief Opaque, unique identifier for this analysis pass.
static void *ID() { return (void *)&PassID; }
BasicAAResult run(Function &F, AnalysisManager<Function> *AM);
/// \brief Provide access to a name for this pass for debugging purposes.
static StringRef name() { return "BasicAliasAnalysis"; }
private:
static char PassID;
BasicAAResult run(Function &F, AnalysisManager<Function> &AM);
};
/// Legacy wrapper pass to provide the BasicAAResult object.

View File

@ -14,6 +14,8 @@
#ifndef LLVM_ANALYSIS_BLOCKFREQUENCYINFO_H
#define LLVM_ANALYSIS_BLOCKFREQUENCYINFO_H
#include "llvm/ADT/Optional.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Pass.h"
#include "llvm/Support/BlockFrequency.h"
#include <climits>
@ -30,12 +32,21 @@ class BlockFrequencyInfo {
typedef BlockFrequencyInfoImpl<BasicBlock> ImplType;
std::unique_ptr<ImplType> BFI;
void operator=(const BlockFrequencyInfo &) = delete;
BlockFrequencyInfo(const BlockFrequencyInfo &) = delete;
public:
BlockFrequencyInfo();
BlockFrequencyInfo(const Function &F, const BranchProbabilityInfo &BPI,
const LoopInfo &LI);
BlockFrequencyInfo(BlockFrequencyInfo &&Arg);
BlockFrequencyInfo &operator=(BlockFrequencyInfo &&RHS);
~BlockFrequencyInfo();
const Function *getFunction() const;
const BranchProbabilityInfo *getBPI() const;
void view() const;
/// getblockFreq - Return block frequency. Return 0 if we don't have the
@ -45,6 +56,11 @@ public:
/// floating points.
BlockFrequency getBlockFreq(const BasicBlock *BB) const;
/// \brief Returns the estimated profile count of \p BB.
/// This computes the relative block frequency of \p BB and multiplies it by
/// the enclosing function's count (if available) and returns the value.
Optional<uint64_t> getBlockProfileCount(const BasicBlock *BB) const;
// Set the frequency of the given basic block.
void setBlockFreq(const BasicBlock *BB, uint64_t Freq);
@ -65,6 +81,30 @@ public:
void print(raw_ostream &OS) const;
};
/// \brief Analysis pass which computes \c BlockFrequencyInfo.
class BlockFrequencyAnalysis
: public AnalysisInfoMixin<BlockFrequencyAnalysis> {
friend AnalysisInfoMixin<BlockFrequencyAnalysis>;
static char PassID;
public:
/// \brief Provide the result typedef for this analysis pass.
typedef BlockFrequencyInfo Result;
/// \brief Run the analysis pass over a function and produce BFI.
Result run(Function &F, AnalysisManager<Function> &AM);
};
/// \brief Printer pass for the \c BlockFrequencyInfo results.
class BlockFrequencyPrinterPass
: public PassInfoMixin<BlockFrequencyPrinterPass> {
raw_ostream &OS;
public:
explicit BlockFrequencyPrinterPass(raw_ostream &OS) : OS(OS) {}
PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
};
/// \brief Legacy analysis pass which computes \c BlockFrequencyInfo.
class BlockFrequencyInfoWrapperPass : public FunctionPass {
BlockFrequencyInfo BFI;

View File

@ -16,12 +16,16 @@
#define LLVM_ANALYSIS_BLOCKFREQUENCYINFOIMPL_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/Support/BlockFrequency.h"
#include "llvm/Support/BranchProbability.h"
#include "llvm/Support/DOTGraphTraits.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/ScaledNumber.h"
#include "llvm/Support/raw_ostream.h"
#include <deque>
@ -476,6 +480,8 @@ public:
Scaled64 getFloatingBlockFreq(const BlockNode &Node) const;
BlockFrequency getBlockFreq(const BlockNode &Node) const;
Optional<uint64_t> getBlockProfileCount(const Function &F,
const BlockNode &Node) const;
void setBlockFreq(const BlockNode &Node, uint64_t Freq);
@ -915,11 +921,17 @@ public:
BlockFrequency getBlockFreq(const BlockT *BB) const {
return BlockFrequencyInfoImplBase::getBlockFreq(getNode(BB));
}
Optional<uint64_t> getBlockProfileCount(const Function &F,
const BlockT *BB) const {
return BlockFrequencyInfoImplBase::getBlockProfileCount(F, getNode(BB));
}
void setBlockFreq(const BlockT *BB, uint64_t Freq);
Scaled64 getFloatingBlockFreq(const BlockT *BB) const {
return BlockFrequencyInfoImplBase::getFloatingBlockFreq(getNode(BB));
}
const BranchProbabilityInfoT &getBPI() const { return *BPI; }
/// \brief Print the frequencies for the current function.
///
/// Prints the frequencies for the blocks in the current function.
@ -1173,12 +1185,10 @@ void BlockFrequencyInfoImpl<BT>::computeIrreducibleMass(
updateLoopWithIrreducible(*OuterLoop);
}
namespace {
// A helper function that converts a branch probability into weight.
inline uint32_t getWeightFromBranchProb(const BranchProbability Prob) {
return Prob.getNumerator();
}
} // namespace
template <class BT>
bool
@ -1224,6 +1234,115 @@ raw_ostream &BlockFrequencyInfoImpl<BT>::print(raw_ostream &OS) const {
return OS;
}
// Graph trait base class for block frequency information graph
// viewer.
enum GVDAGType { GVDT_None, GVDT_Fraction, GVDT_Integer, GVDT_Count };
template <class BlockFrequencyInfoT, class BranchProbabilityInfoT>
struct BFIDOTGraphTraitsBase : public DefaultDOTGraphTraits {
explicit BFIDOTGraphTraitsBase(bool isSimple = false)
: DefaultDOTGraphTraits(isSimple) {}
typedef GraphTraits<BlockFrequencyInfoT *> GTraits;
typedef typename GTraits::NodeType NodeType;
typedef typename GTraits::ChildIteratorType EdgeIter;
typedef typename GTraits::nodes_iterator NodeIter;
uint64_t MaxFrequency = 0;
static std::string getGraphName(const BlockFrequencyInfoT *G) {
return G->getFunction()->getName();
}
std::string getNodeAttributes(const NodeType *Node,
const BlockFrequencyInfoT *Graph,
unsigned HotPercentThreshold = 0) {
std::string Result;
if (!HotPercentThreshold)
return Result;
// Compute MaxFrequency on the fly:
if (!MaxFrequency) {
for (NodeIter I = GTraits::nodes_begin(Graph),
E = GTraits::nodes_end(Graph);
I != E; ++I) {
NodeType &N = *I;
MaxFrequency =
std::max(MaxFrequency, Graph->getBlockFreq(&N).getFrequency());
}
}
BlockFrequency Freq = Graph->getBlockFreq(Node);
BlockFrequency HotFreq =
(BlockFrequency(MaxFrequency) *
BranchProbability::getBranchProbability(HotPercentThreshold, 100));
if (Freq < HotFreq)
return Result;
raw_string_ostream OS(Result);
OS << "color=\"red\"";
OS.flush();
return Result;
}
std::string getNodeLabel(const NodeType *Node,
const BlockFrequencyInfoT *Graph, GVDAGType GType) {
std::string Result;
raw_string_ostream OS(Result);
OS << Node->getName().str() << " : ";
switch (GType) {
case GVDT_Fraction:
Graph->printBlockFreq(OS, Node);
break;
case GVDT_Integer:
OS << Graph->getBlockFreq(Node).getFrequency();
break;
case GVDT_Count: {
auto Count = Graph->getBlockProfileCount(Node);
if (Count)
OS << Count.getValue();
else
OS << "Unknown";
break;
}
case GVDT_None:
llvm_unreachable("If we are not supposed to render a graph we should "
"never reach this point.");
}
return Result;
}
std::string getEdgeAttributes(const NodeType *Node, EdgeIter EI,
const BlockFrequencyInfoT *BFI,
const BranchProbabilityInfoT *BPI,
unsigned HotPercentThreshold = 0) {
std::string Str;
if (!BPI)
return Str;
BranchProbability BP = BPI->getEdgeProbability(Node, EI);
uint32_t N = BP.getNumerator();
uint32_t D = BP.getDenominator();
double Percent = 100.0 * N / D;
raw_string_ostream OS(Str);
OS << format("label=\"%.1f%%\"", Percent);
if (HotPercentThreshold) {
BlockFrequency EFreq = BFI->getBlockFreq(Node) * BP;
BlockFrequency HotFreq = BlockFrequency(MaxFrequency) *
BranchProbability(HotPercentThreshold, 100);
if (EFreq >= HotFreq) {
OS << ",color=\"red\"";
}
}
OS.flush();
return Str;
}
};
} // end namespace llvm
#undef DEBUG_TYPE

View File

@ -15,8 +15,11 @@
#define LLVM_ANALYSIS_BRANCHPROBABILITYINFO_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#include "llvm/Support/BranchProbability.h"
@ -40,7 +43,22 @@ class raw_ostream;
class BranchProbabilityInfo {
public:
BranchProbabilityInfo() {}
BranchProbabilityInfo(Function &F, const LoopInfo &LI) { calculate(F, LI); }
BranchProbabilityInfo(const Function &F, const LoopInfo &LI) {
calculate(F, LI);
}
BranchProbabilityInfo(BranchProbabilityInfo &&Arg)
: Probs(std::move(Arg.Probs)), LastF(Arg.LastF),
PostDominatedByUnreachable(std::move(Arg.PostDominatedByUnreachable)),
PostDominatedByColdCall(std::move(Arg.PostDominatedByColdCall)) {}
BranchProbabilityInfo &operator=(BranchProbabilityInfo &&RHS) {
releaseMemory();
Probs = std::move(RHS.Probs);
PostDominatedByColdCall = std::move(RHS.PostDominatedByColdCall);
PostDominatedByUnreachable = std::move(RHS.PostDominatedByUnreachable);
return *this;
}
void releaseMemory();
@ -74,7 +92,7 @@ public:
///
/// Given a basic block, look through its successors and if one exists for
/// which \see isEdgeHot would return true, return that successor block.
BasicBlock *getHotSucc(BasicBlock *BB) const;
const BasicBlock *getHotSucc(const BasicBlock *BB) const;
/// \brief Print an edge's probability.
///
@ -98,9 +116,31 @@ public:
return IsLikely ? LikelyProb : LikelyProb.getCompl();
}
void calculate(Function &F, const LoopInfo& LI);
void calculate(const Function &F, const LoopInfo &LI);
/// Forget analysis results for the given basic block.
void eraseBlock(const BasicBlock *BB);
private:
void operator=(const BranchProbabilityInfo &) = delete;
BranchProbabilityInfo(const BranchProbabilityInfo &) = delete;
// We need to store CallbackVH's in order to correctly handle basic block
// removal.
class BasicBlockCallbackVH final : public CallbackVH {
BranchProbabilityInfo *BPI;
void deleted() override {
assert(BPI != nullptr);
BPI->eraseBlock(cast<BasicBlock>(getValPtr()));
BPI->Handles.erase(*this);
}
public:
BasicBlockCallbackVH(const Value *V, BranchProbabilityInfo *BPI=nullptr)
: CallbackVH(const_cast<Value *>(V)), BPI(BPI) {}
};
DenseSet<BasicBlockCallbackVH, DenseMapInfo<Value*>> Handles;
// Since we allow duplicate edges from one basic block to another, we use
// a pair (PredBlock and an index in the successors) to specify an edge.
typedef std::pair<const BasicBlock *, unsigned> Edge;
@ -116,22 +156,46 @@ private:
DenseMap<Edge, BranchProbability> Probs;
/// \brief Track the last function we run over for printing.
Function *LastF;
const Function *LastF;
/// \brief Track the set of blocks directly succeeded by a returning block.
SmallPtrSet<BasicBlock *, 16> PostDominatedByUnreachable;
SmallPtrSet<const BasicBlock *, 16> PostDominatedByUnreachable;
/// \brief Track the set of blocks that always lead to a cold call.
SmallPtrSet<BasicBlock *, 16> PostDominatedByColdCall;
SmallPtrSet<const BasicBlock *, 16> PostDominatedByColdCall;
bool calcUnreachableHeuristics(BasicBlock *BB);
bool calcMetadataWeights(BasicBlock *BB);
bool calcColdCallHeuristics(BasicBlock *BB);
bool calcPointerHeuristics(BasicBlock *BB);
bool calcLoopBranchHeuristics(BasicBlock *BB, const LoopInfo &LI);
bool calcZeroHeuristics(BasicBlock *BB);
bool calcFloatingPointHeuristics(BasicBlock *BB);
bool calcInvokeHeuristics(BasicBlock *BB);
bool calcUnreachableHeuristics(const BasicBlock *BB);
bool calcMetadataWeights(const BasicBlock *BB);
bool calcColdCallHeuristics(const BasicBlock *BB);
bool calcPointerHeuristics(const BasicBlock *BB);
bool calcLoopBranchHeuristics(const BasicBlock *BB, const LoopInfo &LI);
bool calcZeroHeuristics(const BasicBlock *BB);
bool calcFloatingPointHeuristics(const BasicBlock *BB);
bool calcInvokeHeuristics(const BasicBlock *BB);
};
/// \brief Analysis pass which computes \c BranchProbabilityInfo.
class BranchProbabilityAnalysis
: public AnalysisInfoMixin<BranchProbabilityAnalysis> {
friend AnalysisInfoMixin<BranchProbabilityAnalysis>;
static char PassID;
public:
/// \brief Provide the result typedef for this analysis pass.
typedef BranchProbabilityInfo Result;
/// \brief Run the analysis pass over a function and produce BPI.
BranchProbabilityInfo run(Function &F, AnalysisManager<Function> &AM);
};
/// \brief Printer pass for the \c BranchProbabilityAnalysis results.
class BranchProbabilityPrinterPass
: public PassInfoMixin<BranchProbabilityPrinterPass> {
raw_ostream &OS;
public:
explicit BranchProbabilityPrinterPass(raw_ostream &OS) : OS(OS) {}
PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
};
/// \brief Legacy analysis pass which computes \c BranchProbabilityInfo.

View File

@ -0,0 +1,138 @@
//=- CFLAndersAliasAnalysis.h - Unification-based Alias Analysis ---*- C++-*-=//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
/// This is the interface for LLVM's inclusion-based alias analysis
/// implemented with CFL graph reachability.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_CFLANDERSALIASANALYSIS_H
#define LLVM_ANALYSIS_CFLANDERSALIASANALYSIS_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Pass.h"
#include <forward_list>
namespace llvm {
class TargetLibraryInfo;
namespace cflaa {
struct AliasSummary;
}
class CFLAndersAAResult : public AAResultBase<CFLAndersAAResult> {
friend AAResultBase<CFLAndersAAResult>;
class FunctionInfo;
public:
explicit CFLAndersAAResult(const TargetLibraryInfo &);
CFLAndersAAResult(CFLAndersAAResult &&);
~CFLAndersAAResult();
/// Handle invalidation events from the new pass manager.
/// By definition, this result is stateless and so remains valid.
bool invalidate(Function &, const PreservedAnalyses &) { return false; }
/// Evict the given function from cache
void evict(const Function &Fn);
/// \brief Get the alias summary for the given function
/// Return nullptr if the summary is not found or not available
const cflaa::AliasSummary *getAliasSummary(const Function &);
AliasResult query(const MemoryLocation &, const MemoryLocation &);
AliasResult alias(const MemoryLocation &, const MemoryLocation &);
private:
struct FunctionHandle final : public CallbackVH {
FunctionHandle(Function *Fn, CFLAndersAAResult *Result)
: CallbackVH(Fn), Result(Result) {
assert(Fn != nullptr);
assert(Result != nullptr);
}
void deleted() override { removeSelfFromCache(); }
void allUsesReplacedWith(Value *) override { removeSelfFromCache(); }
private:
CFLAndersAAResult *Result;
void removeSelfFromCache() {
assert(Result != nullptr);
auto *Val = getValPtr();
Result->evict(*cast<Function>(Val));
setValPtr(nullptr);
}
};
/// \brief Ensures that the given function is available in the cache.
/// Returns the appropriate entry from the cache.
const Optional<FunctionInfo> &ensureCached(const Function &);
/// \brief Inserts the given Function into the cache.
void scan(const Function &);
/// \brief Build summary for a given function
FunctionInfo buildInfoFrom(const Function &);
const TargetLibraryInfo &TLI;
/// \brief Cached mapping of Functions to their StratifiedSets.
/// If a function's sets are currently being built, it is marked
/// in the cache as an Optional without a value. This way, if we
/// have any kind of recursion, it is discernable from a function
/// that simply has empty sets.
DenseMap<const Function *, Optional<FunctionInfo>> Cache;
std::forward_list<FunctionHandle> Handles;
};
/// Analysis pass providing a never-invalidated alias analysis result.
///
/// FIXME: We really should refactor CFL to use the analysis more heavily, and
/// in particular to leverage invalidation to trigger re-computation.
class CFLAndersAA : public AnalysisInfoMixin<CFLAndersAA> {
friend AnalysisInfoMixin<CFLAndersAA>;
static char PassID;
public:
typedef CFLAndersAAResult Result;
CFLAndersAAResult run(Function &F, AnalysisManager<Function> &AM);
};
/// Legacy wrapper pass to provide the CFLAndersAAResult object.
class CFLAndersAAWrapperPass : public ImmutablePass {
std::unique_ptr<CFLAndersAAResult> Result;
public:
static char ID;
CFLAndersAAWrapperPass();
CFLAndersAAResult &getResult() { return *Result; }
const CFLAndersAAResult &getResult() const { return *Result; }
void initializePass() override;
void getAnalysisUsage(AnalysisUsage &AU) const override;
};
//===--------------------------------------------------------------------===//
//
// createCFLAndersAAWrapperPass - This pass implements a set-based approach to
// alias analysis.
//
ImmutablePass *createCFLAndersAAWrapperPass();
}
#endif

View File

@ -1,4 +1,4 @@
//===- CFLAliasAnalysis.h - CFL-Based Alias Analysis Interface ---*- C++ -*-==//
//=- CFLSteensAliasAnalysis.h - Unification-based Alias Analysis ---*- C++-*-=//
//
// The LLVM Compiler Infrastructure
//
@ -7,17 +7,18 @@
//
//===----------------------------------------------------------------------===//
/// \file
/// This is the interface for LLVM's primary stateless and local alias analysis.
/// This is the interface for LLVM's unification-based alias analysis
/// implemented with CFL graph reachability.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_CFLALIASANALYSIS_H
#define LLVM_ANALYSIS_CFLALIASANALYSIS_H
#ifndef LLVM_ANALYSIS_CFLSTEENSALIASANALYSIS_H
#define LLVM_ANALYSIS_CFLSTEENSALIASANALYSIS_H
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ValueHandle.h"
@ -26,14 +27,20 @@
namespace llvm {
class CFLAAResult : public AAResultBase<CFLAAResult> {
friend AAResultBase<CFLAAResult>;
class TargetLibraryInfo;
struct FunctionInfo;
namespace cflaa {
struct AliasSummary;
}
class CFLSteensAAResult : public AAResultBase<CFLSteensAAResult> {
friend AAResultBase<CFLSteensAAResult>;
class FunctionInfo;
public:
explicit CFLAAResult(const TargetLibraryInfo &TLI);
CFLAAResult(CFLAAResult &&Arg);
explicit CFLSteensAAResult(const TargetLibraryInfo &);
CFLSteensAAResult(CFLSteensAAResult &&Arg);
~CFLSteensAAResult();
/// Handle invalidation events from the new pass manager.
///
@ -49,26 +56,23 @@ public:
/// Returns the appropriate entry from the cache.
const Optional<FunctionInfo> &ensureCached(Function *Fn);
/// \brief Get the alias summary for the given function
/// Return nullptr if the summary is not found or not available
const cflaa::AliasSummary *getAliasSummary(Function &Fn);
AliasResult query(const MemoryLocation &LocA, const MemoryLocation &LocB);
AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB) {
if (LocA.Ptr == LocB.Ptr) {
if (LocA.Size == LocB.Size) {
return MustAlias;
} else {
return PartialAlias;
}
}
if (LocA.Ptr == LocB.Ptr)
return LocA.Size == LocB.Size ? MustAlias : PartialAlias;
// Comparisons between global variables and other constants should be
// handled by BasicAA.
// TODO: ConstantExpr handling -- CFLAA may report NoAlias when comparing
// a GlobalValue and ConstantExpr, but every query needs to have at least
// one Value tied to a Function, and neither GlobalValues nor ConstantExprs
// are.
if (isa<Constant>(LocA.Ptr) && isa<Constant>(LocB.Ptr)) {
// CFLSteensAA may report NoAlias when comparing a GlobalValue and
// ConstantExpr, but every query needs to have at least one Value tied to a
// Function, and neither GlobalValues nor ConstantExprs are.
if (isa<Constant>(LocA.Ptr) && isa<Constant>(LocB.Ptr))
return AAResultBase::alias(LocA, LocB);
}
AliasResult QueryResult = query(LocA, LocB);
if (QueryResult == MayAlias)
@ -77,9 +81,19 @@ public:
return QueryResult;
}
/// Get the location associated with a pointer argument of a callsite.
ModRefInfo getArgModRefInfo(ImmutableCallSite CS, unsigned ArgIdx);
/// Returns the behavior when calling the given call site.
FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS);
/// Returns the behavior when calling the given function. For use when the
/// call site is not known.
FunctionModRefBehavior getModRefBehavior(const Function *F);
private:
struct FunctionHandle final : public CallbackVH {
FunctionHandle(Function *Fn, CFLAAResult *Result)
FunctionHandle(Function *Fn, CFLSteensAAResult *Result)
: CallbackVH(Fn), Result(Result) {
assert(Fn != nullptr);
assert(Result != nullptr);
@ -89,7 +103,7 @@ private:
void allUsesReplacedWith(Value *) override { removeSelfFromCache(); }
private:
CFLAAResult *Result;
CFLSteensAAResult *Result;
void removeSelfFromCache() {
assert(Result != nullptr);
@ -99,6 +113,8 @@ private:
}
};
const TargetLibraryInfo &TLI;
/// \brief Cached mapping of Functions to their StratifiedSets.
/// If a function's sets are currently being built, it is marked
/// in the cache as an Optional without a value. This way, if we
@ -114,45 +130,38 @@ private:
///
/// FIXME: We really should refactor CFL to use the analysis more heavily, and
/// in particular to leverage invalidation to trigger re-computation of sets.
class CFLAA {
public:
typedef CFLAAResult Result;
/// \brief Opaque, unique identifier for this analysis pass.
static void *ID() { return (void *)&PassID; }
CFLAAResult run(Function &F, AnalysisManager<Function> *AM);
/// \brief Provide access to a name for this pass for debugging purposes.
static StringRef name() { return "CFLAA"; }
private:
class CFLSteensAA : public AnalysisInfoMixin<CFLSteensAA> {
friend AnalysisInfoMixin<CFLSteensAA>;
static char PassID;
public:
typedef CFLSteensAAResult Result;
CFLSteensAAResult run(Function &F, AnalysisManager<Function> &AM);
};
/// Legacy wrapper pass to provide the CFLAAResult object.
class CFLAAWrapperPass : public ImmutablePass {
std::unique_ptr<CFLAAResult> Result;
/// Legacy wrapper pass to provide the CFLSteensAAResult object.
class CFLSteensAAWrapperPass : public ImmutablePass {
std::unique_ptr<CFLSteensAAResult> Result;
public:
static char ID;
CFLAAWrapperPass();
CFLSteensAAWrapperPass();
CFLAAResult &getResult() { return *Result; }
const CFLAAResult &getResult() const { return *Result; }
CFLSteensAAResult &getResult() { return *Result; }
const CFLSteensAAResult &getResult() const { return *Result; }
bool doInitialization(Module &M) override;
bool doFinalization(Module &M) override;
void initializePass() override;
void getAnalysisUsage(AnalysisUsage &AU) const override;
};
//===--------------------------------------------------------------------===//
//
// createCFLAAWrapperPass - This pass implements a set-based approach to
// createCFLSteensAAWrapperPass - This pass implements a set-based approach to
// alias analysis.
//
ImmutablePass *createCFLAAWrapperPass();
ImmutablePass *createCFLSteensAAWrapperPass();
}
#endif

View File

@ -11,7 +11,7 @@
/// 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
/// traverse 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.
@ -26,6 +26,7 @@
namespace llvm {
extern template class PassManager<LazyCallGraph::SCC>;
/// \brief The CGSCC pass manager.
///
/// See the documentation for the PassManager template for details. It runs
@ -33,6 +34,7 @@ namespace llvm {
/// typedef serves as a convenient way to refer to this construct.
typedef PassManager<LazyCallGraph::SCC> CGSCCPassManager;
extern template class AnalysisManager<LazyCallGraph::SCC>;
/// \brief The CGSCC analysis manager.
///
/// See the documentation for the AnalysisManager template for detail
@ -41,147 +43,16 @@ typedef PassManager<LazyCallGraph::SCC> CGSCCPassManager;
/// pass manager infrastructure.
typedef AnalysisManager<LazyCallGraph::SCC> CGSCCAnalysisManager;
/// \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();
extern template class InnerAnalysisManagerProxy<CGSCCAnalysisManager, Module>;
/// A proxy from a \c CGSCCAnalysisManager to a \c Module.
typedef InnerAnalysisManagerProxy<CGSCCAnalysisManager, Module>
CGSCCAnalysisManagerModuleProxy;
/// \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; }
static StringRef name() { return "CGSCCAnalysisManagerModuleProxy"; }
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; }
static StringRef name() { return "ModuleAnalysisManagerCGSCCProxy"; }
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;
};
extern template class OuterAnalysisManagerProxy<ModuleAnalysisManager,
LazyCallGraph::SCC>;
/// A proxy from a \c ModuleAnalysisManager to an \c SCC.
typedef OuterAnalysisManagerProxy<ModuleAnalysisManager, LazyCallGraph::SCC>
ModuleAnalysisManagerCGSCCProxy;
/// \brief The core module pass which does a post-order walk of the SCCs and
/// runs a CGSCC pass over each one.
@ -192,21 +63,24 @@ private:
/// \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 {
template <typename CGSCCPassT>
class ModuleToPostOrderCGSCCPassAdaptor
: public PassInfoMixin<ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>> {
public:
explicit ModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass)
: Pass(std::move(Pass)) {}
explicit ModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass, bool DebugLogging = false)
: Pass(std::move(Pass)), DebugLogging(DebugLogging) {}
// We have to explicitly define all the special member functions because MSVC
// refuses to generate them.
ModuleToPostOrderCGSCCPassAdaptor(
const ModuleToPostOrderCGSCCPassAdaptor &Arg)
: Pass(Arg.Pass) {}
: Pass(Arg.Pass), DebugLogging(Arg.DebugLogging) {}
ModuleToPostOrderCGSCCPassAdaptor(ModuleToPostOrderCGSCCPassAdaptor &&Arg)
: Pass(std::move(Arg.Pass)) {}
: Pass(std::move(Arg.Pass)), DebugLogging(Arg.DebugLogging) {}
friend void swap(ModuleToPostOrderCGSCCPassAdaptor &LHS,
ModuleToPostOrderCGSCCPassAdaptor &RHS) {
using std::swap;
swap(LHS.Pass, RHS.Pass);
swap(LHS.DebugLogging, RHS.DebugLogging);
}
ModuleToPostOrderCGSCCPassAdaptor &
operator=(ModuleToPostOrderCGSCCPassAdaptor RHS) {
@ -215,33 +89,36 @@ public:
}
/// \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!");
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) {
// Setup the CGSCC analysis manager from its proxy.
CGSCCAnalysisManager &CGAM =
AM->getResult<CGSCCAnalysisManagerModuleProxy>(M).getManager();
AM.getResult<CGSCCAnalysisManagerModuleProxy>(M).getManager();
// Get the call graph for this module.
LazyCallGraph &CG = AM->getResult<LazyCallGraphAnalysis>(M);
LazyCallGraph &CG = AM.getResult<LazyCallGraphAnalysis>(M);
PreservedAnalyses PA = PreservedAnalyses::all();
for (LazyCallGraph::SCC &C : CG.postorder_sccs()) {
PreservedAnalyses PassPA = Pass.run(C, &CGAM);
for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs()) {
if (DebugLogging)
dbgs() << "Running an SCC pass across the RefSCC: " << RC << "\n";
// 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. We
// also update the preserved set of analyses to reflect that invalidated
// analyses are now safe to preserve.
// 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.
PassPA = CGAM.invalidate(C, std::move(PassPA));
for (LazyCallGraph::SCC &C : RC) {
PreservedAnalyses PassPA = Pass.run(C, CGAM);
// Then intersect the preserved set so that invalidation of module
// analyses will eventually occur when the module pass completes.
PA.intersect(std::move(PassPA));
// 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. We
// also update the preserved set of analyses to reflect that invalidated
// analyses are now safe to preserve.
// 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.
PassPA = CGAM.invalidate(C, std::move(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
@ -252,163 +129,29 @@ public:
return PA;
}
static StringRef name() { return "ModuleToPostOrderCGSCCPassAdaptor"; }
private:
CGSCCPassT Pass;
bool DebugLogging;
};
/// \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 ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>(std::move(Pass));
createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass, bool DebugLogging = false) {
return ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>(std::move(Pass), DebugLogging);
}
/// \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();
extern template class InnerAnalysisManagerProxy<FunctionAnalysisManager,
LazyCallGraph::SCC>;
/// A proxy from a \c FunctionAnalysisManager to an \c SCC.
typedef InnerAnalysisManagerProxy<FunctionAnalysisManager, LazyCallGraph::SCC>
FunctionAnalysisManagerCGSCCProxy;
/// \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; }
static StringRef name() { return "FunctionAnalysisManagerCGSCCProxy"; }
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 CGSCCAnalysisManagerFunctionProxy.
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; }
static StringRef name() { return "CGSCCAnalysisManagerFunctionProxy"; }
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;
};
extern template class OuterAnalysisManagerProxy<CGSCCAnalysisManager, Function>;
/// A proxy from a \c CGSCCAnalysisManager to a \c Function.
typedef OuterAnalysisManagerProxy<CGSCCAnalysisManager, Function>
CGSCCAnalysisManagerFunctionProxy;
/// \brief Adaptor that maps from a SCC to its functions.
///
@ -418,20 +161,23 @@ private:
/// \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 {
template <typename FunctionPassT>
class CGSCCToFunctionPassAdaptor
: public PassInfoMixin<CGSCCToFunctionPassAdaptor<FunctionPassT>> {
public:
explicit CGSCCToFunctionPassAdaptor(FunctionPassT Pass)
: Pass(std::move(Pass)) {}
explicit CGSCCToFunctionPassAdaptor(FunctionPassT Pass, bool DebugLogging = false)
: Pass(std::move(Pass)), DebugLogging(DebugLogging) {}
// We have to explicitly define all the special member functions because MSVC
// refuses to generate them.
CGSCCToFunctionPassAdaptor(const CGSCCToFunctionPassAdaptor &Arg)
: Pass(Arg.Pass) {}
: Pass(Arg.Pass), DebugLogging(Arg.DebugLogging) {}
CGSCCToFunctionPassAdaptor(CGSCCToFunctionPassAdaptor &&Arg)
: Pass(std::move(Arg.Pass)) {}
: Pass(std::move(Arg.Pass)), DebugLogging(Arg.DebugLogging) {}
friend void swap(CGSCCToFunctionPassAdaptor &LHS,
CGSCCToFunctionPassAdaptor &RHS) {
using std::swap;
swap(LHS.Pass, RHS.Pass);
swap(LHS.DebugLogging, RHS.DebugLogging);
}
CGSCCToFunctionPassAdaptor &operator=(CGSCCToFunctionPassAdaptor RHS) {
swap(*this, RHS);
@ -439,23 +185,24 @@ public:
}
/// \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 run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM) {
// Setup the function analysis manager from its proxy.
FunctionAnalysisManager &FAM =
AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C).getManager();
if (DebugLogging)
dbgs() << "Running function passes across an SCC: " << C << "\n";
PreservedAnalyses PA = PreservedAnalyses::all();
for (LazyCallGraph::Node *N : C) {
PreservedAnalyses PassPA = Pass.run(N->getFunction(), FAM);
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.
// Also, update the preserved analyses to reflect that once invalidated
// these can again be preserved.
if (FAM)
PassPA = FAM->invalidate(N->getFunction(), std::move(PassPA));
PassPA = FAM.invalidate(N.getFunction(), std::move(PassPA));
// Then intersect the preserved set so that invalidation of module
// analyses will eventually occur when the module pass completes.
@ -472,18 +219,18 @@ public:
return PA;
}
static StringRef name() { return "CGSCCToFunctionPassAdaptor"; }
private:
FunctionPassT Pass;
bool DebugLogging;
};
/// \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 CGSCCToFunctionPassAdaptor<FunctionPassT>(std::move(Pass));
createCGSCCToFunctionPassAdaptor(FunctionPassT Pass, bool DebugLogging = false) {
return CGSCCToFunctionPassAdaptor<FunctionPassT>(std::move(Pass),
DebugLogging);
}
}

View File

@ -57,6 +57,7 @@
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Pass.h"
#include <map>
@ -294,20 +295,27 @@ private:
/// 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 {
class CallGraphAnalysis : public AnalysisInfoMixin<CallGraphAnalysis> {
friend AnalysisInfoMixin<CallGraphAnalysis>;
static char PassID;
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); }
CallGraph run(Module &M, ModuleAnalysisManager &) { return CallGraph(M); }
};
private:
static char PassID;
/// \brief Printer pass for the \c CallGraphAnalysis results.
class CallGraphPrinterPass : public PassInfoMixin<CallGraphPrinterPass> {
raw_ostream &OS;
public:
explicit CallGraphPrinterPass(raw_ostream &OS) : OS(OS) {}
PreservedAnalyses run(Module &M, AnalysisManager<Module> &AM);
};
/// \brief The \c ModulePass which wraps up a \c CallGraph and the logic to

View File

@ -23,6 +23,7 @@
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Pass.h"
#include "llvm/PassSupport.h"
namespace llvm {
@ -77,15 +78,21 @@ public:
/// the call graph. If the derived class implements this method, it should
/// always explicitly call the implementation here.
void getAnalysisUsage(AnalysisUsage &Info) const override;
protected:
/// Optional passes call this function to check whether the pass should be
/// skipped. This is the case when optimization bisect is over the limit.
bool skipSCC(CallGraphSCC &SCC) const;
};
/// CallGraphSCC - This is a single SCC that a CallGraphSCCPass is run on.
class CallGraphSCC {
const CallGraph &CG; // The call graph for this SCC.
void *Context; // The CGPassManager object that is vending this.
std::vector<CallGraphNode*> Nodes;
public:
CallGraphSCC(void *context) : Context(context) {}
CallGraphSCC(CallGraph &cg, void *context) : CG(cg), Context(context) {}
void initialize(CallGraphNode *const *I, CallGraphNode *const *E) {
Nodes.assign(I, E);
@ -101,6 +108,25 @@ public:
typedef std::vector<CallGraphNode *>::const_iterator iterator;
iterator begin() const { return Nodes.begin(); }
iterator end() const { return Nodes.end(); }
const CallGraph &getCallGraph() { return CG; }
};
void initializeDummyCGSCCPassPass(PassRegistry &);
/// This pass is required by interprocedural register allocation. It forces
/// codegen to follow bottom up order on call graph.
class DummyCGSCCPass : public CallGraphSCCPass {
public:
static char ID;
DummyCGSCCPass() : CallGraphSCCPass(ID) {
PassRegistry &Registry = *PassRegistry::getPassRegistry();
initializeDummyCGSCCPassPass(Registry);
};
bool runOnSCC(CallGraphSCC &SCC) override { return false; }
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
}
};
} // End llvm namespace

View File

@ -17,10 +17,10 @@
namespace llvm {
class ModulePass;
class ModulePass;
ModulePass *createCallGraphViewerPass();
ModulePass *createCallGraphPrinterPass();
ModulePass *createCallGraphViewerPass();
ModulePass *createCallGraphDOTPrinterPass();
} // end namespace llvm

View File

@ -42,50 +42,48 @@ bool callIsSmall(ImmutableCallSite CS);
struct CodeMetrics {
/// \brief True if this function contains a call to setjmp or other functions
/// with attribute "returns twice" without having the attribute itself.
bool exposesReturnsTwice;
bool exposesReturnsTwice = false;
/// \brief True if this function calls itself.
bool isRecursive;
bool isRecursive = false;
/// \brief True if this function cannot be duplicated.
///
/// True if this function contains one or more indirect branches, or it contains
/// one or more 'noduplicate' instructions.
bool notDuplicatable;
bool notDuplicatable = false;
/// \brief True if this function contains a call to a convergent function.
bool convergent = false;
/// \brief True if this function calls alloca (in the C sense).
bool usesDynamicAlloca;
bool usesDynamicAlloca = false;
/// \brief Number of instructions in the analyzed blocks.
unsigned NumInsts;
unsigned NumInsts = false;
/// \brief Number of analyzed blocks.
unsigned NumBlocks;
unsigned NumBlocks = false;
/// \brief Keeps track of basic block code size estimates.
DenseMap<const BasicBlock *, unsigned> NumBBInsts;
/// \brief Keep track of the number of calls to 'big' functions.
unsigned NumCalls;
unsigned NumCalls = false;
/// \brief The number of calls to internal functions with a single caller.
///
/// These are likely targets for future inlining, likely exposed by
/// interleaved devirtualization.
unsigned NumInlineCandidates;
unsigned NumInlineCandidates = 0;
/// \brief How many instructions produce vector values.
///
/// The inliner is more aggressive with inlining vector kernels.
unsigned NumVectorInsts;
unsigned NumVectorInsts = 0;
/// \brief How many 'ret' instructions the blocks contain.
unsigned NumRets;
CodeMetrics()
: exposesReturnsTwice(false), isRecursive(false), notDuplicatable(false),
usesDynamicAlloca(false), NumInsts(0), NumBlocks(0), NumCalls(0),
NumInlineCandidates(0), NumVectorInsts(0), NumRets(0) {}
unsigned NumRets = 0;
/// \brief Add information about a block to the current state.
void analyzeBasicBlock(const BasicBlock *BB, const TargetTransformInfo &TTI,

View File

@ -21,30 +21,36 @@
#define LLVM_ANALYSIS_CONSTANTFOLDING_H
namespace llvm {
class Constant;
class ConstantExpr;
class Instruction;
class DataLayout;
class TargetLibraryInfo;
class Function;
class Type;
template<typename T>
class ArrayRef;
class APInt;
template <typename T> class ArrayRef;
class Constant;
class ConstantExpr;
class DataLayout;
class Function;
class GlobalValue;
class Instruction;
class TargetLibraryInfo;
class Type;
/// If this constant is a constant offset from a global, return the global and
/// the constant. Because of constantexprs, this function is recursive.
bool IsConstantOffsetFromGlobal(Constant *C, GlobalValue *&GV, APInt &Offset,
const DataLayout &DL);
/// ConstantFoldInstruction - Try to constant fold the specified instruction.
/// If successful, the constant result is returned, if not, null is returned.
/// Note that this fails if not all of the operands are constant. Otherwise,
/// this function can only fail when attempting to fold instructions like loads
/// and stores, which have no constant expression form.
Constant *ConstantFoldInstruction(Instruction *I, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr);
Constant *ConstantFoldInstruction(Instruction *I, const DataLayout &DL,
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 &DL,
const TargetLibraryInfo *TLI = nullptr);
Constant *
ConstantFoldConstantExpression(const ConstantExpr *CE, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr);
/// ConstantFoldInstOperands - Attempt to constant fold an instruction with the
/// specified operands. If successful, the constant result is returned, if not,
@ -52,19 +58,42 @@ namespace llvm {
/// fold instructions like loads and stores, which have no constant expression
/// form.
///
Constant *ConstantFoldInstOperands(unsigned Opcode, Type *DestTy,
ArrayRef<Constant *> Ops,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr);
Constant *ConstantFoldInstOperands(Instruction *I, ArrayRef<Constant *> Ops,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr);
/// ConstantFoldInstOperands - Attempt to constant fold an instruction with the
/// specified operands. If successful, the constant result is returned, if not,
/// null is returned. Note that this function can fail when attempting to
/// fold instructions like loads and stores, which have no constant expression
/// form.
///
/// This function doesn't work for compares (use ConstantFoldCompareInstOperands
/// for this) and GEPs.
Constant *ConstantFoldInstOperands(unsigned Opcode, Type *DestTy,
ArrayRef<Constant *> Ops,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr);
/// ConstantFoldCompareInstOperands - Attempt to constant fold a compare
/// instruction (icmp/fcmp) with the specified operands. If it fails, it
/// returns a constant expression of the specified operands.
///
Constant *
ConstantFoldCompareInstOperands(unsigned Predicate, Constant *LHS,
Constant *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr);
Constant *
ConstantFoldCompareInstOperands(unsigned Predicate, Constant *LHS,
Constant *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr);
/// \brief Attempt to constant fold a binary operation with the specified
/// operands. If it fails, it returns a constant expression of the specified
/// operands.
Constant *ConstantFoldBinaryOpOperands(unsigned Opcode, Constant *LHS,
Constant *RHS, const DataLayout &DL);
/// \brief Attempt to constant fold a cast with the specified operand. If it
/// fails, it returns a constant expression of the specified operand.
Constant *ConstantFoldCastOperand(unsigned Opcode, Constant *C, Type *DestTy,
const DataLayout &DL);
/// ConstantFoldInsertValueInstruction - Attempt to constant fold an insertvalue
/// instruction with the specified operands and indices. The constant result is
@ -86,7 +115,7 @@ Constant *ConstantFoldExtractElementInstruction(Constant *Val, Constant *Idx);
/// 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 &DL);
Constant *ConstantFoldLoadFromConstPtr(Constant *C, Type *Ty, const DataLayout &DL);
/// ConstantFoldLoadThroughGEPConstantExpr - Given a constant and a
/// getelementptr constantexpr, return the constant value being addressed by the
@ -98,7 +127,7 @@ Constant *ConstantFoldLoadThroughGEPConstantExpr(Constant *C, ConstantExpr *CE);
/// return the constant value being addressed by a virtual load, or null if
/// something is funny and we can't decide.
Constant *ConstantFoldLoadThroughGEPIndices(Constant *C,
ArrayRef<Constant*> Indices);
ArrayRef<Constant *> Indices);
/// canConstantFoldCallTo - Return true if its even possible to fold a call to
/// the specified function.

View File

@ -26,6 +26,7 @@
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/IR/PassManager.h"
namespace llvm {
@ -35,40 +36,81 @@ class Instruction;
class DominatorTree;
class AssumptionCache;
struct DemandedBits : public FunctionPass {
static char ID; // Pass identification, replacement for typeid
DemandedBits();
class DemandedBits {
public:
DemandedBits(Function &F, AssumptionCache &AC, DominatorTree &DT) :
F(F), AC(AC), DT(DT), Analyzed(false) {}
bool runOnFunction(Function& F) override;
void getAnalysisUsage(AnalysisUsage& AU) const override;
void print(raw_ostream &OS, const Module *M) const override;
/// Return the bits demanded from instruction I.
APInt getDemandedBits(Instruction *I);
/// Return true if, during analysis, I could not be reached.
bool isInstructionDead(Instruction *I);
void print(raw_ostream &OS);
private:
Function &F;
AssumptionCache &AC;
DominatorTree &DT;
void performAnalysis();
void determineLiveOperandBits(const Instruction *UserI,
const Instruction *I, unsigned OperandNo,
const APInt &AOut, APInt &AB,
APInt &KnownZero, APInt &KnownOne,
APInt &KnownZero2, APInt &KnownOne2);
const Instruction *I, unsigned OperandNo,
const APInt &AOut, APInt &AB,
APInt &KnownZero, APInt &KnownOne,
APInt &KnownZero2, APInt &KnownOne2);
AssumptionCache *AC;
DominatorTree *DT;
Function *F;
bool Analyzed;
// The set of visited instructions (non-integer-typed only).
SmallPtrSet<Instruction*, 128> Visited;
SmallPtrSet<Instruction*, 32> Visited;
DenseMap<Instruction *, APInt> AliveBits;
};
class DemandedBitsWrapperPass : public FunctionPass {
private:
mutable Optional<DemandedBits> DB;
public:
static char ID; // Pass identification, replacement for typeid
DemandedBitsWrapperPass();
bool runOnFunction(Function &F) override;
void getAnalysisUsage(AnalysisUsage &AU) const override;
/// Clean up memory in between runs
void releaseMemory() override;
DemandedBits &getDemandedBits() { return *DB; }
void print(raw_ostream &OS, const Module *M) const override;
};
/// An analysis that produces \c DemandedBits for a function.
class DemandedBitsAnalysis : public AnalysisInfoMixin<DemandedBitsAnalysis> {
friend AnalysisInfoMixin<DemandedBitsAnalysis>;
static char PassID;
public:
/// \brief Provide the result typedef for this analysis pass.
typedef DemandedBits Result;
/// \brief Run the analysis pass over a function and produce demanded bits
/// information.
DemandedBits run(Function &F, AnalysisManager<Function> &AM);
};
/// \brief Printer pass for DemandedBits
class DemandedBitsPrinterPass : public PassInfoMixin<DemandedBitsPrinterPass> {
raw_ostream &OS;
public:
explicit DemandedBitsPrinterPass(raw_ostream &OS) : OS(OS) {}
PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
};
/// Create a demanded bits analysis pass.
FunctionPass *createDemandedBitsPass();
FunctionPass *createDemandedBitsWrapperPass();
} // End llvm namespace

View File

@ -41,12 +41,12 @@
#define LLVM_ANALYSIS_DEPENDENCEANALYSIS_H
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Pass.h"
namespace llvm {
template <typename T> class ArrayRef;
class Loop;
class LoopInfo;
class ScalarEvolution;
@ -206,7 +206,7 @@ namespace llvm {
private:
Instruction *Src, *Dst;
const Dependence *NextPredecessor, *NextSuccessor;
friend class DependenceAnalysis;
friend class DependenceInfo;
};
/// FullDependence - This class represents a dependence between two memory
@ -274,16 +274,17 @@ namespace llvm {
bool LoopIndependent;
bool Consistent; // Init to true, then refine.
std::unique_ptr<DVEntry[]> DV;
friend class DependenceAnalysis;
friend class DependenceInfo;
};
/// DependenceAnalysis - This class is the main dependence-analysis driver.
/// DependenceInfo - This class is the main dependence-analysis driver.
///
class DependenceAnalysis : public FunctionPass {
void operator=(const DependenceAnalysis &) = delete;
DependenceAnalysis(const DependenceAnalysis &) = delete;
class DependenceInfo {
public:
DependenceInfo(Function *F, AliasAnalysis *AA, ScalarEvolution *SE,
LoopInfo *LI)
: AA(AA), SE(SE), LI(LI), F(F) {}
/// depends - Tests for a dependence between the Src and Dst instructions.
/// Returns NULL if no dependence; otherwise, returns a Dependence (or a
/// FullDependence) with as much information as can be gleaned.
@ -336,6 +337,8 @@ namespace llvm {
/// both loops.
const SCEV *getSplitIteration(const Dependence &Dep, unsigned Level);
Function *getFunction() const { return F; }
private:
AliasAnalysis *AA;
ScalarEvolution *SE;
@ -919,22 +922,41 @@ namespace llvm {
bool tryDelinearize(Instruction *Src, Instruction *Dst,
SmallVectorImpl<Subscript> &Pair);
}; // class DependenceInfo
/// \brief AnalysisPass to compute dependence information in a function
class DependenceAnalysis : public AnalysisInfoMixin<DependenceAnalysis> {
public:
typedef DependenceInfo Result;
Result run(Function &F, FunctionAnalysisManager &FAM);
private:
static char PassID;
friend struct AnalysisInfoMixin<DependenceAnalysis>;
}; // class DependenceAnalysis
/// \brief Legacy pass manager pass to access dependence information
class DependenceAnalysisWrapperPass : public FunctionPass {
public:
static char ID; // Class identification, replacement for typeinfo
DependenceAnalysis() : FunctionPass(ID) {
initializeDependenceAnalysisPass(*PassRegistry::getPassRegistry());
DependenceAnalysisWrapperPass() : FunctionPass(ID) {
initializeDependenceAnalysisWrapperPassPass(
*PassRegistry::getPassRegistry());
}
bool runOnFunction(Function &F) override;
void releaseMemory() override;
void getAnalysisUsage(AnalysisUsage &) const override;
void print(raw_ostream &, const Module * = nullptr) const override;
}; // class DependenceAnalysis
DependenceInfo &getDI() const;
private:
std::unique_ptr<DependenceInfo> info;
}; // class DependenceAnalysisWrapperPass
/// createDependenceAnalysisPass - This creates an instance of the
/// DependenceAnalysis pass.
FunctionPass *createDependenceAnalysisPass();
/// DependenceAnalysis wrapper pass.
FunctionPass *createDependenceAnalysisWrapperPass();
} // namespace llvm

View File

@ -19,6 +19,7 @@
#define LLVM_ANALYSIS_DOMINANCEFRONTIER_H
#include "llvm/IR/Dominators.h"
#include "llvm/IR/PassManager.h"
#include <map>
#include <set>
@ -133,63 +134,24 @@ public:
const DomSetType &calculate(const DomTreeT &DT, const DomTreeNodeT *Node);
};
class DominanceFrontier : public FunctionPass {
ForwardDominanceFrontierBase<BasicBlock> Base;
class DominanceFrontier : public ForwardDominanceFrontierBase<BasicBlock> {
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;
};
class DominanceFrontierWrapperPass : public FunctionPass {
DominanceFrontier DF;
public:
static char ID; // Pass ID, replacement for typeid
DominanceFrontier();
DominanceFrontierWrapperPass();
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);
}
DominanceFrontier &getDominanceFrontier() { return DF; }
const DominanceFrontier &getDominanceFrontier() const { return DF; }
void releaseMemory() override;
@ -205,6 +167,30 @@ public:
extern template class DominanceFrontierBase<BasicBlock>;
extern template class ForwardDominanceFrontierBase<BasicBlock>;
/// \brief Analysis pass which computes a \c DominanceFrontier.
class DominanceFrontierAnalysis
: public AnalysisInfoMixin<DominanceFrontierAnalysis> {
friend AnalysisInfoMixin<DominanceFrontierAnalysis>;
static char PassID;
public:
/// \brief Provide the result typedef for this analysis pass.
typedef DominanceFrontier Result;
/// \brief Run the analysis pass over a function and produce a dominator tree.
DominanceFrontier run(Function &F, AnalysisManager<Function> &AM);
};
/// \brief Printer pass for the \c DominanceFrontier.
class DominanceFrontierPrinterPass
: public PassInfoMixin<DominanceFrontierPrinterPass> {
raw_ostream &OS;
public:
explicit DominanceFrontierPrinterPass(raw_ostream &OS);
PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
};
} // End llvm namespace
#endif

View File

@ -23,12 +23,15 @@ enum class EHPersonality {
Unknown,
GNU_Ada,
GNU_C,
GNU_C_SjLj,
GNU_CXX,
GNU_CXX_SjLj,
GNU_ObjC,
MSVC_X86SEH,
MSVC_Win64SEH,
MSVC_CXX,
CoreCLR
CoreCLR,
Rust
};
/// \brief See if the given exception handling personality function is one

View File

@ -35,6 +35,7 @@ class GlobalsAAResult : public AAResultBase<GlobalsAAResult> {
class FunctionInfo;
const DataLayout &DL;
const TargetLibraryInfo &TLI;
/// The globals that do not have their addresses taken.
SmallPtrSet<const GlobalValue *, 8> NonAddressTakenGlobals;
@ -76,6 +77,7 @@ class GlobalsAAResult : public AAResultBase<GlobalsAAResult> {
public:
GlobalsAAResult(GlobalsAAResult &&Arg);
~GlobalsAAResult();
static GlobalsAAResult analyzeModule(Module &M, const TargetLibraryInfo &TLI,
CallGraph &CG);
@ -116,20 +118,14 @@ private:
};
/// Analysis pass providing a never-invalidated alias analysis result.
class GlobalsAA {
class GlobalsAA : public AnalysisInfoMixin<GlobalsAA> {
friend AnalysisInfoMixin<GlobalsAA>;
static char PassID;
public:
typedef GlobalsAAResult Result;
/// \brief Opaque, unique identifier for this analysis pass.
static void *ID() { return (void *)&PassID; }
GlobalsAAResult run(Module &M, AnalysisManager<Module> *AM);
/// \brief Provide access to a name for this pass for debugging purposes.
static StringRef name() { return "GlobalsAA"; }
private:
static char PassID;
GlobalsAAResult run(Module &M, AnalysisManager<Module> &AM);
};
/// Legacy wrapper pass to provide the GlobalsAAResult object.

View File

@ -117,7 +117,7 @@ private:
mutable ilist_node<IVStrideUse> Sentinel;
};
class IVUsers : public LoopPass {
class IVUsers {
friend class IVStrideUse;
Loop *L;
AssumptionCache *AC;
@ -133,15 +133,9 @@ class IVUsers : public LoopPass {
// Ephemeral values used by @llvm.assume in this function.
SmallPtrSet<const Value *, 32> EphValues;
void getAnalysisUsage(AnalysisUsage &AU) const override;
bool runOnLoop(Loop *L, LPPassManager &LPM) override;
void releaseMemory() override;
public:
static char ID; // Pass ID, replacement for typeid
IVUsers();
IVUsers(Loop *L, AssumptionCache *AC, LoopInfo *LI, DominatorTree *DT,
ScalarEvolution *SE);
Loop *getLoop() const { return L; }
@ -173,16 +167,58 @@ public:
return Processed.count(Inst);
}
void print(raw_ostream &OS, const Module* = nullptr) const override;
void releaseMemory();
void print(raw_ostream &OS, const Module * = nullptr) const;
/// dump - This method is used for debugging.
void dump() const;
protected:
bool AddUsersImpl(Instruction *I, SmallPtrSetImpl<Loop*> &SimpleLoopNests);
};
Pass *createIVUsersPass();
class IVUsersWrapperPass : public LoopPass {
std::unique_ptr<IVUsers> IU;
public:
static char ID;
IVUsersWrapperPass();
IVUsers &getIU() { return *IU; }
const IVUsers &getIU() const { return *IU; }
void getAnalysisUsage(AnalysisUsage &AU) const override;
bool runOnLoop(Loop *L, LPPassManager &LPM) override;
void releaseMemory() override;
void print(raw_ostream &OS, const Module * = nullptr) const override;
};
/// Analysis pass that exposes the \c IVUsers for a loop.
class IVUsersAnalysis : public AnalysisInfoMixin<IVUsersAnalysis> {
friend AnalysisInfoMixin<IVUsersAnalysis>;
static char PassID;
public:
typedef IVUsers Result;
IVUsers run(Loop &L, AnalysisManager<Loop> &AM);
};
/// Printer pass for the \c IVUsers for a loop.
class IVUsersPrinterPass : public PassInfoMixin<IVUsersPrinterPass> {
raw_ostream &OS;
public:
explicit IVUsersPrinterPass(raw_ostream &OS) : OS(OS) {}
PreservedAnalyses run(Loop &L, AnalysisManager<Loop> &AM);
};
}
#endif

View File

@ -0,0 +1,67 @@
//===- IndirectCallPromotionAnalysis.h - Indirect call analysis -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
/// Interface to identify indirect call promotion candidates.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_INDIRECTCALLPROMOTIONANALYSIS_H
#define LLVM_ANALYSIS_INDIRECTCALLPROMOTIONANALYSIS_H
#include "llvm/ProfileData/InstrProf.h"
namespace llvm {
class Instruction;
// Class for identifying profitable indirect call promotion candidates when
// the indirect-call value profile metadata is available.
class ICallPromotionAnalysis {
private:
// Allocate space to read the profile annotation.
std::unique_ptr<InstrProfValueData[]> ValueDataArray;
// Count is the call count for the direct-call target and
// TotalCount is the call count for the indirect-call callsite.
// Return true we should promote this indirect-call target.
bool isPromotionProfitable(uint64_t Count, uint64_t TotalCount);
// Returns the number of profitable candidates to promote for the
// current ValueDataArray and the given \p Inst.
uint32_t getProfitablePromotionCandidates(const Instruction *Inst,
uint32_t NumVals,
uint64_t TotalCount);
// Noncopyable
ICallPromotionAnalysis(const ICallPromotionAnalysis &other) = delete;
ICallPromotionAnalysis &
operator=(const ICallPromotionAnalysis &other) = delete;
public:
ICallPromotionAnalysis();
/// \brief Returns reference to array of InstrProfValueData for the given
/// instruction \p I.
///
/// The \p NumVals, \p TotalCount and \p NumCandidates
/// are set to the number of values in the array, the total profile count
/// of the indirect call \p I, and the number of profitable candidates
/// in the given array (which is sorted in reverse order of profitability).
///
/// The returned array space is owned by this class, and overwritten on
/// subsequent calls.
ArrayRef<InstrProfValueData>
getPromotionCandidatesForInstruction(const Instruction *I, uint32_t &NumVals,
uint64_t &TotalCount,
uint32_t &NumCandidates);
};
} // end namespace llvm
#endif

View File

@ -0,0 +1,43 @@
//===-- IndirectCallSiteVisitor.h - indirect call-sites visitor -----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements defines a visitor class and a helper function that find
// all indirect call-sites in a function.
#include "llvm/IR/InstVisitor.h"
#include <vector>
namespace llvm {
// Visitor class that finds all indirect call sites.
struct PGOIndirectCallSiteVisitor
: public InstVisitor<PGOIndirectCallSiteVisitor> {
std::vector<Instruction *> IndirectCallInsts;
PGOIndirectCallSiteVisitor() {}
void visitCallSite(CallSite CS) {
if (CS.getCalledFunction() || !CS.getCalledValue())
return;
Instruction *I = CS.getInstruction();
if (CallInst *CI = dyn_cast<CallInst>(I)) {
if (CI->isInlineAsm())
return;
}
if (isa<Constant>(CS.getCalledValue()))
return;
IndirectCallInsts.push_back(I);
}
};
// Helper function that finds all indirect call sites.
static inline std::vector<Instruction *> findIndirectCallSites(Function &F) {
PGOIndirectCallSiteVisitor ICV;
ICV.visit(F);
return ICV.IndirectCallInsts;
}
}

View File

@ -23,6 +23,7 @@ class AssumptionCacheTracker;
class CallSite;
class DataLayout;
class Function;
class ProfileSummaryInfo;
class TargetTransformInfo;
namespace InlineConstants {
@ -101,25 +102,31 @@ public:
/// \brief Get an InlineCost object representing the cost of inlining this
/// callsite.
///
/// Note that threshold is passed into this function. Only costs below the
/// threshold are computed with any accuracy. The threshold can be used to
/// bound the computation necessary to determine whether the cost is
/// Note that a default threshold is passed into this function. This threshold
/// could be modified based on callsite's properties and only costs below this
/// new threshold are computed with any accuracy. The new threshold can be
/// used to bound the computation necessary to determine whether the cost is
/// sufficiently low to warrant inlining.
///
/// Also note that calling this function *dynamically* computes the cost of
/// inlining the callsite. It is an expensive, heavyweight call.
InlineCost getInlineCost(CallSite CS, int Threshold,
InlineCost getInlineCost(CallSite CS, int DefaultThreshold,
TargetTransformInfo &CalleeTTI,
AssumptionCacheTracker *ACT);
AssumptionCacheTracker *ACT, ProfileSummaryInfo *PSI);
/// \brief Get an InlineCost with the callee explicitly specified.
/// This allows you to calculate the cost of inlining a function via a
/// pointer. This behaves exactly as the version with no explicit callee
/// parameter in all other respects.
//
InlineCost getInlineCost(CallSite CS, Function *Callee, int Threshold,
InlineCost getInlineCost(CallSite CS, Function *Callee, int DefaultThreshold,
TargetTransformInfo &CalleeTTI,
AssumptionCacheTracker *ACT);
AssumptionCacheTracker *ACT, ProfileSummaryInfo *PSI);
int computeThresholdFromOptLevels(unsigned OptLevel, unsigned SizeOptLevel);
/// \brief Return the default value of -inline-threshold.
int getDefaultInlineThreshold();
/// \brief Minimal filter to detect invalid constructs for inlining.
bool isInlineViable(Function &Callee);

View File

@ -46,8 +46,7 @@ namespace llvm {
class Type;
class Value;
/// SimplifyAddInst - Given operands for an Add, see if we can
/// fold the result. If not, this returns null.
/// Given operands for an Add, fold the result or return null.
Value *SimplifyAddInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@ -55,8 +54,7 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// SimplifySubInst - Given operands for a Sub, see if we can
/// fold the result. If not, this returns null.
/// Given operands for a Sub, fold the result or return null.
Value *SimplifySubInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@ -64,8 +62,7 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// Given operands for an FAdd, see if we can fold the result. If not, this
/// returns null.
/// Given operands for an FAdd, fold the result or return null.
Value *SimplifyFAddInst(Value *LHS, Value *RHS, FastMathFlags FMF,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@ -73,8 +70,7 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// Given operands for an FSub, see if we can fold the result. If not, this
/// returns null.
/// Given operands for an FSub, fold the result or return null.
Value *SimplifyFSubInst(Value *LHS, Value *RHS, FastMathFlags FMF,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@ -82,8 +78,7 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// Given operands for an FMul, see if we can fold the result. If not, this
/// returns null.
/// Given operands for an FMul, fold the result or return null.
Value *SimplifyFMulInst(Value *LHS, Value *RHS, FastMathFlags FMF,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@ -91,32 +86,28 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// SimplifyMulInst - Given operands for a Mul, see if we can
/// fold the result. If not, this returns null.
/// Given operands for a Mul, fold the result or return null.
Value *SimplifyMulInst(Value *LHS, Value *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// SimplifySDivInst - Given operands for an SDiv, see if we can
/// fold the result. If not, this returns null.
/// Given operands for an SDiv, fold the result or return null.
Value *SimplifySDivInst(Value *LHS, Value *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// SimplifyUDivInst - Given operands for a UDiv, see if we can
/// fold the result. If not, this returns null.
/// Given operands for a UDiv, fold the result or return null.
Value *SimplifyUDivInst(Value *LHS, Value *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// SimplifyFDivInst - Given operands for an FDiv, see if we can
/// fold the result. If not, this returns null.
/// Given operands for an FDiv, fold the result or return null.
Value *SimplifyFDivInst(Value *LHS, Value *RHS, FastMathFlags FMF,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@ -124,24 +115,21 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// SimplifySRemInst - Given operands for an SRem, see if we can
/// fold the result. If not, this returns null.
/// Given operands for an SRem, fold the result or return null.
Value *SimplifySRemInst(Value *LHS, Value *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// SimplifyURemInst - Given operands for a URem, see if we can
/// fold the result. If not, this returns null.
/// Given operands for a URem, fold the result or return null.
Value *SimplifyURemInst(Value *LHS, Value *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// SimplifyFRemInst - Given operands for an FRem, see if we can
/// fold the result. If not, this returns null.
/// Given operands for an FRem, fold the result or return null.
Value *SimplifyFRemInst(Value *LHS, Value *RHS, FastMathFlags FMF,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@ -149,8 +137,7 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// SimplifyShlInst - Given operands for a Shl, see if we can
/// fold the result. If not, this returns null.
/// Given operands for a Shl, fold the result or return null.
Value *SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@ -158,8 +145,7 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// SimplifyLShrInst - Given operands for a LShr, see if we can
/// fold the result. If not, this returns null.
/// Given operands for a LShr, fold the result or return null.
Value *SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@ -167,8 +153,7 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// SimplifyAShrInst - Given operands for a AShr, see if we can
/// fold the result. If not, this returns null.
/// Given operands for a AShr, fold the result or return nulll.
Value *SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@ -176,32 +161,28 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// SimplifyAndInst - Given operands for an And, see if we can
/// fold the result. If not, this returns null.
/// Given operands for an And, fold the result or return null.
Value *SimplifyAndInst(Value *LHS, Value *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// SimplifyOrInst - Given operands for an Or, see if we can
/// fold the result. If not, this returns null.
/// Given operands for an Or, fold the result or return null.
Value *SimplifyOrInst(Value *LHS, Value *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// SimplifyXorInst - Given operands for a Xor, see if we can
/// fold the result. If not, this returns null.
/// Given operands for an Xor, fold the result or return null.
Value *SimplifyXorInst(Value *LHS, Value *RHS, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// SimplifyICmpInst - Given operands for an ICmpInst, see if we can
/// fold the result. If not, this returns null.
/// Given operands for an ICmpInst, fold the result or return null.
Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@ -209,8 +190,7 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// SimplifyFCmpInst - Given operands for an FCmpInst, see if we can
/// fold the result. If not, this returns null.
/// Given operands for an FCmpInst, fold the result or return null.
Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
FastMathFlags FMF, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@ -218,8 +198,7 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// SimplifySelectInst - Given operands for a SelectInst, see if we can fold
/// the result. If not, this returns null.
/// Given operands for a SelectInst, fold the result or return null.
Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@ -227,16 +206,15 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = 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 &DL,
/// Given operands for a GetElementPtrInst, fold the result or return null.
Value *SimplifyGEPInst(Type *SrcTy, ArrayRef<Value *> Ops,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// SimplifyInsertValueInst - Given operands for an InsertValueInst, see if we
/// can fold the result. If not, this returns null.
/// Given operands for an InsertValueInst, fold the result or return null.
Value *SimplifyInsertValueInst(Value *Agg, Value *Val,
ArrayRef<unsigned> Idxs, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@ -244,8 +222,7 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// \brief Given operands for an ExtractValueInst, see if we can fold the
/// result. If not, this returns null.
/// Given operands for an ExtractValueInst, fold the result or return null.
Value *SimplifyExtractValueInst(Value *Agg, ArrayRef<unsigned> Idxs,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@ -253,8 +230,7 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// \brief Given operands for an ExtractElementInst, see if we can fold the
/// result. If not, this returns null.
/// Given operands for an ExtractElementInst, fold the result or return null.
Value *SimplifyExtractElementInst(Value *Vec, Value *Idx,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@ -262,8 +238,7 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// SimplifyTruncInst - Given operands for an TruncInst, see if we can fold
/// the result. If not, this returns null.
/// Given operands for an TruncInst, fold the result or return null.
Value *SimplifyTruncInst(Value *Op, Type *Ty, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
@ -273,8 +248,7 @@ namespace llvm {
//=== Helper functions for higher up the class hierarchy.
/// SimplifyCmpInst - Given operands for a CmpInst, see if we can
/// fold the result. If not, this returns null.
/// Given operands for a CmpInst, fold the result or return null.
Value *SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@ -282,16 +256,15 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// SimplifyBinOp - Given operands for a BinaryOperator, see if we can
/// fold the result. If not, this returns null.
/// Given operands for a BinaryOperator, fold the result or return null.
Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// SimplifyFPBinOp - Given operands for a BinaryOperator, see if we can
/// fold the result. If not, this returns null.
/// Given operands for an FP BinaryOperator, fold the result or return null.
/// In contrast to SimplifyBinOp, try to use FastMathFlag when folding the
/// result. In case we don't need FastMathFlags, simply fall to SimplifyBinOp.
Value *SimplifyFPBinOp(unsigned Opcode, Value *LHS, Value *RHS,
@ -301,10 +274,8 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = 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.
/// Given a function and iterators over arguments, fold the result or return
/// null.
Value *SimplifyCall(Value *V, User::op_iterator ArgBegin,
User::op_iterator ArgEnd, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
@ -312,25 +283,21 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = 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.
/// Given a function and set of arguments, fold the result or return null.
Value *SimplifyCall(Value *V, ArrayRef<Value *> Args, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// SimplifyInstruction - See if we can compute a simplified version of this
/// instruction. If not, this returns null.
/// See if we can compute a simplified version of this instruction. If not,
/// return null.
Value *SimplifyInstruction(Instruction *I, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr);
/// \brief Replace all uses of 'I' with 'SimpleV' and simplify the uses
/// recursively.
/// Replace all uses of 'I' with 'SimpleV' and simplify the uses recursively.
///
/// This first performs a normal RAUW of I with SimpleV. It then recursively
/// attempts to simplify those users updated by the operation. The 'I'
@ -342,7 +309,7 @@ namespace llvm {
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr);
/// \brief Recursively attempt to simplify an instruction.
/// Recursively attempt to simplify an instruction.
///
/// This routine uses SimplifyInstruction to simplify 'I', and if successful
/// replaces uses of 'I' with the simplified value. It then recurses on each

View File

@ -67,8 +67,9 @@ public:
/// contains - Find out if a basic block is in this interval
inline bool contains(BasicBlock *BB) const {
for (unsigned i = 0; i < Nodes.size(); ++i)
if (Nodes[i] == BB) return true;
for (BasicBlock *Node : Nodes)
if (Node == BB)
return true;
return false;
// I don't want the dependency on <algorithm>
//return find(Nodes.begin(), Nodes.end(), BB) != Nodes.end();
@ -76,8 +77,9 @@ public:
/// isSuccessor - find out if a basic block is a successor of this Interval
inline bool isSuccessor(BasicBlock *BB) const {
for (unsigned i = 0; i < Successors.size(); ++i)
if (Successors[i] == BB) return true;
for (BasicBlock *Successor : Successors)
if (Successor == BB)
return true;
return false;
// I don't want the dependency on <algorithm>
//return find(Successors.begin(), Successors.end(), BB) != Successors.end();

View File

@ -24,18 +24,14 @@
#ifndef LLVM_ANALYSIS_IDF_H
#define LLVM_ANALYSIS_IDF_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Dominators.h"
namespace llvm {
class BasicBlock;
template <class T> class DomTreeNodeBase;
typedef DomTreeNodeBase<BasicBlock> DomTreeNode;
template <class T> class DominatorTreeBase;
/// \brief Determine the iterated dominance frontier, given a set of defining
/// blocks, and optionally, a set of live-in blocks.
///
@ -44,6 +40,9 @@ template <class T> class DominatorTreeBase;
/// This algorithm is a linear time computation of Iterated Dominance Frontiers,
/// pruned using the live-in set.
/// By default, liveness is not used to prune the IDF computation.
/// The template parameters should be either BasicBlock* or Inverse<BasicBlock
/// *>, depending on if you want the forward or reverse IDF.
template <class NodeTy>
class IDFCalculator {
public:
@ -92,5 +91,7 @@ private:
const SmallPtrSetImpl<BasicBlock *> *DefBlocks;
SmallVector<BasicBlock *, 32> PHIBlocks;
};
typedef IDFCalculator<BasicBlock *> ForwardIDFCalculator;
typedef IDFCalculator<Inverse<BasicBlock *>> ReverseIDFCalculator;
}
#endif

View File

@ -0,0 +1,125 @@
//===- LazyBlockFrequencyInfo.h - Lazy Block Frequency Analysis -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is an alternative analysis pass to BlockFrequencyInfoWrapperPass. The
// difference is that with this pass the block frequencies are not computed when
// the analysis pass is executed but rather when the BFI results is explicitly
// requested by the analysis client.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_LAZYBLOCKFREQUENCYINFO_H
#define LLVM_ANALYSIS_LAZYBLOCKFREQUENCYINFO_H
#include "llvm/Analysis/BlockFrequencyInfo.h"
#include "llvm/Pass.h"
namespace llvm {
class AnalysisUsage;
class BranchProbabilityInfo;
class Function;
class LoopInfo;
/// \brief This is an alternative analysis pass to
/// BlockFrequencyInfoWrapperPass. The difference is that with this pass the
/// block frequencies are not computed when the analysis pass is executed but
/// rather when the BFI results is explicitly requested by the analysis client.
///
/// There are some additional requirements for any client pass that wants to use
/// the analysis:
///
/// 1. The pass needs to initialize dependent passes with:
///
/// INITIALIZE_PASS_DEPENDENCY(LazyBFIPass)
///
/// 2. Similarly, getAnalysisUsage should call:
///
/// LazyBlockFrequencyInfoPass::getLazyBFIAnalysisUsage(AU)
///
/// 3. The computed BFI should be requested with
/// getAnalysis<LazyBlockFrequencyInfoPass>().getBFI() before either LoopInfo
/// or BPI could be invalidated for example by changing the CFG.
///
/// Note that it is expected that we wouldn't need this functionality for the
/// new PM since with the new PM, analyses are executed on demand.
class LazyBlockFrequencyInfoPass : public FunctionPass {
/// Wraps a BFI to allow lazy computation of the block frequencies.
///
/// A pass that only conditionally uses BFI can uncondtionally require the
/// analysis without paying for the overhead if BFI doesn't end up being used.
class LazyBlockFrequencyInfo {
public:
LazyBlockFrequencyInfo()
: Calculated(false), F(nullptr), BPI(nullptr), LI(nullptr) {}
/// Set up the per-function input.
void setAnalysis(const Function *F, const BranchProbabilityInfo *BPI,
const LoopInfo *LI) {
this->F = F;
this->BPI = BPI;
this->LI = LI;
}
/// Retrieve the BFI with the block frequencies computed.
BlockFrequencyInfo &getCalculated() {
if (!Calculated) {
assert(F && BPI && LI && "call setAnalysis");
BFI.calculate(*F, *BPI, *LI);
Calculated = true;
}
return BFI;
}
const BlockFrequencyInfo &getCalculated() const {
return const_cast<LazyBlockFrequencyInfo *>(this)->getCalculated();
}
void releaseMemory() {
BFI.releaseMemory();
Calculated = false;
setAnalysis(nullptr, nullptr, nullptr);
}
private:
BlockFrequencyInfo BFI;
bool Calculated;
const Function *F;
const BranchProbabilityInfo *BPI;
const LoopInfo *LI;
};
LazyBlockFrequencyInfo LBFI;
public:
static char ID;
LazyBlockFrequencyInfoPass();
/// \brief Compute and return the block frequencies.
BlockFrequencyInfo &getBFI() { return LBFI.getCalculated(); }
/// \brief Compute and return the block frequencies.
const BlockFrequencyInfo &getBFI() const { return LBFI.getCalculated(); }
void getAnalysisUsage(AnalysisUsage &AU) const override;
/// Helper for client passes to set up the analysis usage on behalf of this
/// pass.
static void getLazyBFIAnalysisUsage(AnalysisUsage &AU);
bool runOnFunction(Function &F) override;
void releaseMemory() override;
void print(raw_ostream &OS, const Module *M) const override;
};
/// \brief Helper for client passes to initialize dependent passes for LBFI.
void initializeLazyBFIPassPass(PassRegistry &Registry);
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -15,11 +15,13 @@
#ifndef LLVM_ANALYSIS_LAZYVALUEINFO_H
#define LLVM_ANALYSIS_LAZYVALUEINFO_H
#include "llvm/IR/PassManager.h"
#include "llvm/Pass.h"
namespace llvm {
class AssumptionCache;
class Constant;
class ConstantRange;
class DataLayout;
class DominatorTree;
class Instruction;
@ -27,19 +29,33 @@ namespace llvm {
class Value;
/// This pass computes, caches, and vends lazy value constraint information.
class LazyValueInfo : public FunctionPass {
AssumptionCache *AC;
class TargetLibraryInfo *TLI;
DominatorTree *DT;
void *PImpl;
class LazyValueInfo {
friend class LazyValueInfoWrapperPass;
AssumptionCache *AC = nullptr;
class TargetLibraryInfo *TLI = nullptr;
DominatorTree *DT = nullptr;
void *PImpl = nullptr;
LazyValueInfo(const LazyValueInfo&) = delete;
void operator=(const LazyValueInfo&) = delete;
public:
static char ID;
LazyValueInfo() : FunctionPass(ID), PImpl(nullptr) {
initializeLazyValueInfoPass(*PassRegistry::getPassRegistry());
~LazyValueInfo();
LazyValueInfo() {}
LazyValueInfo(AssumptionCache *AC_, TargetLibraryInfo *TLI_,
DominatorTree *DT_)
: AC(AC_), TLI(TLI_), DT(DT_) {}
LazyValueInfo(LazyValueInfo &&Arg)
: AC(Arg.AC), TLI(Arg.TLI), DT(Arg.DT), PImpl(Arg.PImpl) {
Arg.PImpl = nullptr;
}
LazyValueInfo &operator=(LazyValueInfo &&Arg) {
releaseMemory();
AC = Arg.AC;
TLI = Arg.TLI;
DT = Arg.DT;
PImpl = Arg.PImpl;
Arg.PImpl = nullptr;
return *this;
}
~LazyValueInfo() override { assert(!PImpl && "releaseMemory not called"); }
/// This is used to return true/false/dunno results.
enum Tristate {
@ -65,6 +81,11 @@ public:
/// constant at the end of the specified block. Return null if not.
Constant *getConstant(Value *V, BasicBlock *BB, Instruction *CxtI = nullptr);
/// Return the ConstantRange constraint that is known to hold for the
/// specified value at the end of the specified block. This may only be called
/// on integer-typed Values.
ConstantRange getConstantRange(Value *V, BasicBlock *BB, Instruction *CxtI = nullptr);
/// Determine whether the specified value is known to be a
/// constant on the specified edge. Return null if not.
Constant *getConstantOnEdge(Value *V, BasicBlock *FromBB, BasicBlock *ToBB,
@ -77,11 +98,41 @@ public:
/// Inform the analysis cache that we have erased a block.
void eraseBlock(BasicBlock *BB);
// Implementation boilerplate.
// For old PM pass. Delete once LazyValueInfoWrapperPass is gone.
void releaseMemory();
};
/// \brief Analysis to compute lazy value information.
class LazyValueAnalysis : public AnalysisInfoMixin<LazyValueAnalysis> {
public:
typedef LazyValueInfo Result;
Result run(Function &F, FunctionAnalysisManager &FAM);
private:
static char PassID;
friend struct AnalysisInfoMixin<LazyValueAnalysis>;
};
/// Wrapper around LazyValueInfo.
class LazyValueInfoWrapperPass : public FunctionPass {
LazyValueInfoWrapperPass(const LazyValueInfoWrapperPass&) = delete;
void operator=(const LazyValueInfoWrapperPass&) = delete;
public:
static char ID;
LazyValueInfoWrapperPass() : FunctionPass(ID) {
initializeLazyValueInfoWrapperPassPass(*PassRegistry::getPassRegistry());
}
~LazyValueInfoWrapperPass() override {
assert(!Info.PImpl && "releaseMemory not called");
}
LazyValueInfo &getLVI();
void getAnalysisUsage(AnalysisUsage &AU) const override;
void releaseMemory() override;
bool runOnFunction(Function &F) override;
private:
LazyValueInfo Info;
};
} // end namespace llvm

View File

@ -23,39 +23,74 @@ namespace llvm {
class DataLayout;
class MDNode;
/// isDereferenceablePointer - Return true if this is always a dereferenceable
/// pointer. If the context instruction is specified perform context-sensitive
/// analysis and return true if the pointer is dereferenceable at the
/// specified instruction.
bool isDereferenceablePointer(const Value *V, const DataLayout &DL,
const Instruction *CtxI = nullptr,
const DominatorTree *DT = nullptr);
/// Returns true if V is always a dereferenceable pointer with alignment
/// greater or equal than requested. If the context instruction is specified
/// performs context-sensitive analysis and returns true if the pointer is
/// dereferenceable at the specified instruction.
bool isDereferenceableAndAlignedPointer(const Value *V, unsigned Align,
const DataLayout &DL,
const Instruction *CtxI = nullptr,
const DominatorTree *DT = nullptr);
/// isSafeToLoadUnconditionally - Return true if we know that executing a load
/// from this value cannot trap. If it is not obviously safe to load from the
/// 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);
/// from this value cannot trap.
///
/// If DT and ScanFrom are specified this method performs context-sensitive
/// analysis and returns true if it is safe to load immediately before ScanFrom.
///
/// If it is not obviously safe to load from the 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, unsigned Align,
const DataLayout &DL,
Instruction *ScanFrom = nullptr,
const DominatorTree *DT = nullptr);
/// DefMaxInstsToScan - the default number of maximum instructions
/// to scan in the block, used by FindAvailableLoadedValue().
extern cl::opt<unsigned> DefMaxInstsToScan;
/// FindAvailableLoadedValue - Scan the ScanBB block backwards (starting at
/// the instruction before ScanFrom) checking to see if we have the value at
/// the memory address *Ptr locally available within a small number of
/// instructions. If the value is available, return it.
/// \brief Scan backwards to see if we have the value of the given load
/// available locally within a small number of instructions.
///
/// If not, return the iterator for the last validated instruction that the
/// value would be live through. If we scanned the entire block and didn't
/// find something that invalidates *Ptr or provides it, ScanFrom would be
/// left at begin() and this returns null. ScanFrom could also be left
/// You can use this function to scan across multiple blocks: after you call
/// this function, if ScanFrom points at the beginning of the block, it's safe
/// to continue scanning the predecessors.
///
/// MaxInstsToScan specifies the maximum instructions to scan in the block.
/// If it is set to 0, it will scan the whole block. You can also optionally
/// specify an alias analysis implementation, which makes this more precise.
/// Note that performing load CSE requires special care to make sure the
/// metadata is set appropriately. In particular, aliasing metadata needs
/// to be merged. (This doesn't matter for store-to-load forwarding because
/// the only relevant load gets deleted.)
///
/// If AATags is non-null and a load or store is found, the AA tags from the
/// load or store are recorded there. If there are no AA tags or if no access
/// is found, it is left unmodified.
Value *FindAvailableLoadedValue(Value *Ptr, BasicBlock *ScanBB,
/// \param Load The load we want to replace.
/// \param ScanBB The basic block to scan. FIXME: This is redundant.
/// \param [in,out] ScanFrom The location to start scanning from. When this
/// function returns, it points at the last instruction scanned.
/// \param MaxInstsToScan The maximum number of instructions to scan. If this
/// is zero, the whole block will be scanned.
/// \param AA Optional pointer to alias analysis, to make the scan more
/// precise.
/// \param [out] AATags The aliasing metadata for the operation which produced
/// the value. FIXME: This is basically useless.
/// \param [out] IsLoadCSE Whether the returned value is a load from the same
/// location in memory, as opposed to the value operand of a store.
///
/// \returns The found value, or nullptr if no value is found.
Value *FindAvailableLoadedValue(LoadInst *Load,
BasicBlock *ScanBB,
BasicBlock::iterator &ScanFrom,
unsigned MaxInstsToScan = DefMaxInstsToScan,
AliasAnalysis *AA = nullptr,
AAMDNodes *AATags = nullptr);
AAMDNodes *AATags = nullptr,
bool *IsLoadCSE = nullptr);
}

View File

@ -228,7 +228,7 @@ public:
/// \brief The maximum number of bytes of a vector register we can vectorize
/// the accesses safely with.
unsigned getMaxSafeDepDistBytes() { return MaxSafeDepDistBytes; }
uint64_t getMaxSafeDepDistBytes() { return MaxSafeDepDistBytes; }
/// \brief In same cases when the dependency check fails we can still
/// vectorize the loop with a dynamic array access check.
@ -284,7 +284,7 @@ private:
unsigned AccessIdx;
// We can access this many bytes in parallel safely.
unsigned MaxSafeDepDistBytes;
uint64_t MaxSafeDepDistBytes;
/// \brief If we see a non-constant dependence distance we can still try to
/// vectorize this loop with runtime checks.
@ -321,7 +321,10 @@ private:
/// \brief Check whether the data dependence could prevent store-load
/// forwarding.
bool couldPreventStoreLoadForward(unsigned Distance, unsigned TypeByteSize);
///
/// \return false if we shouldn't vectorize at all or avoid larger
/// vectorization factors by limiting MaxSafeDepDistBytes.
bool couldPreventStoreLoadForward(uint64_t Distance, uint64_t TypeByteSize);
};
/// \brief Holds information about the memory runtime legality checks to verify
@ -363,10 +366,10 @@ public:
}
/// Insert a pointer and calculate the start and end SCEVs.
/// \p We need Preds in order to compute the SCEV expression of the pointer
/// We need \p PSE in order to compute the SCEV expression of the pointer
/// according to the assumptions that we've made during the analysis.
/// The method might also version the pointer stride according to \p Strides,
/// and change \p Preds.
/// and add new predicates to \p PSE.
void insert(Loop *Lp, Value *Ptr, bool WritePtr, unsigned DepSetId,
unsigned ASId, const ValueToValueMap &Strides,
PredicatedScalarEvolution &PSE);
@ -508,23 +511,53 @@ private:
/// PSE must be emitted in order for the results of this analysis to be valid.
class LoopAccessInfo {
public:
LoopAccessInfo(Loop *L, ScalarEvolution *SE, const DataLayout &DL,
const TargetLibraryInfo *TLI, AliasAnalysis *AA,
DominatorTree *DT, LoopInfo *LI,
const ValueToValueMap &Strides);
LoopAccessInfo(Loop *L, ScalarEvolution *SE, const TargetLibraryInfo *TLI,
AliasAnalysis *AA, DominatorTree *DT, LoopInfo *LI);
// FIXME:
// Hack for MSVC 2013 which sems like it can't synthesize this even
// with default keyword:
// LoopAccessInfo(LoopAccessInfo &&LAI) = default;
LoopAccessInfo(LoopAccessInfo &&LAI)
: PSE(std::move(LAI.PSE)), PtrRtChecking(std::move(LAI.PtrRtChecking)),
DepChecker(std::move(LAI.DepChecker)), TheLoop(LAI.TheLoop),
NumLoads(LAI.NumLoads), NumStores(LAI.NumStores),
MaxSafeDepDistBytes(LAI.MaxSafeDepDistBytes), CanVecMem(LAI.CanVecMem),
StoreToLoopInvariantAddress(LAI.StoreToLoopInvariantAddress),
Report(std::move(LAI.Report)),
SymbolicStrides(std::move(LAI.SymbolicStrides)),
StrideSet(std::move(LAI.StrideSet)) {}
// LoopAccessInfo &operator=(LoopAccessInfo &&LAI) = default;
LoopAccessInfo &operator=(LoopAccessInfo &&LAI) {
assert(this != &LAI);
PSE = std::move(LAI.PSE);
PtrRtChecking = std::move(LAI.PtrRtChecking);
DepChecker = std::move(LAI.DepChecker);
TheLoop = LAI.TheLoop;
NumLoads = LAI.NumLoads;
NumStores = LAI.NumStores;
MaxSafeDepDistBytes = LAI.MaxSafeDepDistBytes;
CanVecMem = LAI.CanVecMem;
StoreToLoopInvariantAddress = LAI.StoreToLoopInvariantAddress;
Report = std::move(LAI.Report);
SymbolicStrides = std::move(LAI.SymbolicStrides);
StrideSet = std::move(LAI.StrideSet);
return *this;
}
/// Return true we can analyze the memory accesses in the loop and there are
/// no memory dependence cycles.
bool canVectorizeMemory() const { return CanVecMem; }
const RuntimePointerChecking *getRuntimePointerChecking() const {
return &PtrRtChecking;
return PtrRtChecking.get();
}
/// \brief Number of memchecks required to prove independence of otherwise
/// may-alias pointers.
unsigned getNumRuntimePointerChecks() const {
return PtrRtChecking.getNumberOfChecks();
return PtrRtChecking->getNumberOfChecks();
}
/// Return true if the block BB needs to be predicated in order for the loop
@ -535,7 +568,7 @@ public:
/// Returns true if the value V is uniform within the loop.
bool isUniform(Value *V) const;
unsigned getMaxSafeDepDistBytes() const { return MaxSafeDepDistBytes; }
uint64_t getMaxSafeDepDistBytes() const { return MaxSafeDepDistBytes; }
unsigned getNumStores() const { return NumStores; }
unsigned getNumLoads() const { return NumLoads;}
@ -563,23 +596,25 @@ public:
/// \brief the Memory Dependence Checker which can determine the
/// loop-independent and loop-carried dependences between memory accesses.
const MemoryDepChecker &getDepChecker() const { return DepChecker; }
const MemoryDepChecker &getDepChecker() const { return *DepChecker; }
/// \brief Return the list of instructions that use \p Ptr to read or write
/// memory.
SmallVector<Instruction *, 4> getInstructionsForAccess(Value *Ptr,
bool isWrite) const {
return DepChecker.getInstructionsForAccess(Ptr, isWrite);
return DepChecker->getInstructionsForAccess(Ptr, isWrite);
}
/// \brief If an access has a symbolic strides, this maps the pointer value to
/// the stride symbol.
const ValueToValueMap &getSymbolicStrides() const { return SymbolicStrides; }
/// \brief Pointer has a symbolic stride.
bool hasStride(Value *V) const { return StrideSet.count(V); }
/// \brief Print the information about the memory accesses in the loop.
void print(raw_ostream &OS, unsigned Depth = 0) const;
/// \brief Used to ensure that if the analysis was run with speculating the
/// value of symbolic strides, the client queries it with the same assumption.
/// Only used in DEBUG build but we don't want NDEBUG-dependent ABI.
unsigned NumSymbolicStrides;
/// \brief Checks existence of store to invariant address inside loop.
/// If the loop has any store to invariant address, then it returns true,
/// else returns false.
@ -592,11 +627,12 @@ public:
/// should be re-written (and therefore simplified) according to PSE.
/// A user of LoopAccessAnalysis will need to emit the runtime checks
/// associated with this predicate.
PredicatedScalarEvolution PSE;
const PredicatedScalarEvolution &getPSE() const { return *PSE; }
private:
/// \brief Analyze the loop. Substitute symbolic strides using Strides.
void analyzeLoop(const ValueToValueMap &Strides);
/// \brief Analyze the loop.
void analyzeLoop(AliasAnalysis *AA, LoopInfo *LI,
const TargetLibraryInfo *TLI, DominatorTree *DT);
/// \brief Check if the structure of the loop allows it to be analyzed by this
/// pass.
@ -604,25 +640,28 @@ private:
void emitAnalysis(LoopAccessReport &Message);
/// \brief Collect memory access with loop invariant strides.
///
/// Looks for accesses like "a[i * StrideA]" where "StrideA" is loop
/// invariant.
void collectStridedAccess(Value *LoadOrStoreInst);
std::unique_ptr<PredicatedScalarEvolution> PSE;
/// We need to check that all of the pointers in this list are disjoint
/// at runtime.
RuntimePointerChecking PtrRtChecking;
/// at runtime. Using std::unique_ptr to make using move ctor simpler.
std::unique_ptr<RuntimePointerChecking> PtrRtChecking;
/// \brief the Memory Dependence Checker which can determine the
/// loop-independent and loop-carried dependences between memory accesses.
MemoryDepChecker DepChecker;
std::unique_ptr<MemoryDepChecker> DepChecker;
Loop *TheLoop;
const DataLayout &DL;
const TargetLibraryInfo *TLI;
AliasAnalysis *AA;
DominatorTree *DT;
LoopInfo *LI;
unsigned NumLoads;
unsigned NumStores;
unsigned MaxSafeDepDistBytes;
uint64_t MaxSafeDepDistBytes;
/// \brief Cache the result of analyzeLoop.
bool CanVecMem;
@ -634,15 +673,23 @@ private:
/// \brief The diagnostics report generated for the analysis. E.g. why we
/// couldn't analyze the loop.
Optional<LoopAccessReport> Report;
/// \brief If an access has a symbolic strides, this maps the pointer value to
/// the stride symbol.
ValueToValueMap SymbolicStrides;
/// \brief Set of symbolic strides values.
SmallPtrSet<Value *, 8> StrideSet;
};
Value *stripIntegerCast(Value *V);
///\brief Return the SCEV corresponding to a pointer with the symbolic stride
/// replaced with constant one, assuming \p Preds is true.
/// \brief Return the SCEV corresponding to a pointer with the symbolic stride
/// replaced with constant one, assuming the SCEV predicate associated with
/// \p PSE is true.
///
/// If necessary this method will version the stride of the pointer according
/// to \p PtrToStride and therefore add a new predicate to \p Preds.
/// to \p PtrToStride and therefore add further predicates to \p PSE.
///
/// If \p OrigPtr is not null, use it to look up the stride value instead of \p
/// Ptr. \p PtrToStride provides the mapping between the pointer value and its
@ -651,13 +698,24 @@ const SCEV *replaceSymbolicStrideSCEV(PredicatedScalarEvolution &PSE,
const ValueToValueMap &PtrToStride,
Value *Ptr, Value *OrigPtr = nullptr);
/// \brief Check the stride of the pointer and ensure that it does not wrap in
/// the address space, assuming \p Preds is true.
/// \brief If the pointer has a constant stride return it in units of its
/// element size. Otherwise return zero.
///
/// Ensure that it does not wrap in the address space, assuming the predicate
/// associated with \p PSE is true.
///
/// If necessary this method will version the stride of the pointer according
/// to \p PtrToStride and therefore add a new predicate to \p Preds.
int isStridedPtr(PredicatedScalarEvolution &PSE, Value *Ptr, const Loop *Lp,
const ValueToValueMap &StridesMap);
/// to \p PtrToStride and therefore add further predicates to \p PSE.
/// The \p Assume parameter indicates if we are allowed to make additional
/// run-time assumptions.
int64_t getPtrStride(PredicatedScalarEvolution &PSE, Value *Ptr, const Loop *Lp,
const ValueToValueMap &StridesMap = ValueToValueMap(),
bool Assume = false);
/// \brief Returns true if the memory operations \p A and \p B are consecutive.
/// This is a simple API that does not depend on the analysis pass.
bool isConsecutiveAccess(Value *A, Value *B, const DataLayout &DL,
ScalarEvolution &SE, bool CheckType = true);
/// \brief This analysis provides dependence information for the memory accesses
/// of a loop.
@ -666,12 +724,12 @@ int isStridedPtr(PredicatedScalarEvolution &PSE, Value *Ptr, const Loop *Lp,
/// querying the loop access info via LAA::getInfo. getInfo return a
/// LoopAccessInfo object. See this class for the specifics of what information
/// is provided.
class LoopAccessAnalysis : public FunctionPass {
class LoopAccessLegacyAnalysis : public FunctionPass {
public:
static char ID;
LoopAccessAnalysis() : FunctionPass(ID) {
initializeLoopAccessAnalysisPass(*PassRegistry::getPassRegistry());
LoopAccessLegacyAnalysis() : FunctionPass(ID) {
initializeLoopAccessLegacyAnalysisPass(*PassRegistry::getPassRegistry());
}
bool runOnFunction(Function &F) override;
@ -680,11 +738,8 @@ public:
/// \brief Query the result of the loop access information for the loop \p L.
///
/// If the client speculates (and then issues run-time checks) for the values
/// of symbolic strides, \p Strides provides the mapping (see
/// replaceSymbolicStrideSCEV). If there is no cached result available run
/// the analysis.
const LoopAccessInfo &getInfo(Loop *L, const ValueToValueMap &Strides);
/// If there is no cached result available run the analysis.
const LoopAccessInfo &getInfo(Loop *L);
void releaseMemory() override {
// Invalidate the cache when the pass is freed.
@ -706,6 +761,34 @@ private:
LoopInfo *LI;
};
/// \brief This analysis provides dependence information for the memory
/// accesses of a loop.
///
/// It runs the analysis for a loop on demand. This can be initiated by
/// querying the loop access info via AM.getResult<LoopAccessAnalysis>.
/// getResult return a LoopAccessInfo object. See this class for the
/// specifics of what information is provided.
class LoopAccessAnalysis
: public AnalysisInfoMixin<LoopAccessAnalysis> {
friend AnalysisInfoMixin<LoopAccessAnalysis>;
static char PassID;
public:
typedef LoopAccessInfo Result;
Result run(Loop &, AnalysisManager<Loop> &);
static StringRef name() { return "LoopAccessAnalysis"; }
};
/// \brief Printer pass for the \c LoopAccessInfo results.
class LoopAccessInfoPrinterPass
: public PassInfoMixin<LoopAccessInfoPrinterPass> {
raw_ostream &OS;
public:
explicit LoopAccessInfoPrinterPass(raw_ostream &OS) : OS(OS) {}
PreservedAnalyses run(Loop &L, AnalysisManager<Loop> &AM);
};
inline Instruction *MemoryDepChecker::Dependence::getSource(
const LoopAccessInfo &LAI) const {
return LAI.getDepChecker().getMemoryInstructions()[Source];

View File

@ -25,6 +25,12 @@
// * the loop depth
// * etc...
//
// Note that this analysis specifically identifies *Loops* not cycles or SCCs
// in the CFG. There can be strongly connected compontents in the CFG which
// this analysis will not recognize and that will not be represented by a Loop
// instance. In particular, a Loop might be inside such a non-loop SCC, or a
// non-loop SCC might contain a sub-SCC which is a Loop.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_LOOPINFO_H
@ -38,16 +44,12 @@
#include "llvm/IR/CFG.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Pass.h"
#include <algorithm>
namespace llvm {
// FIXME: Replace this brittle forward declaration with the include of the new
// PassManager.h when doing so doesn't break the PassManagerBuilder.
template <typename IRUnitT> class AnalysisManager;
class PreservedAnalyses;
class DominatorTree;
class LoopInfo;
class Loop;
@ -346,6 +348,9 @@ raw_ostream& operator<<(raw_ostream &OS, const LoopBase<BlockT, LoopT> &Loop) {
// Implementation in LoopInfoImpl.h
extern template class LoopBase<BasicBlock, Loop>;
/// Represents a single loop in the control flow graph. Note that not all SCCs
/// in the CFG are neccessarily loops.
class Loop : public LoopBase<BasicBlock, Loop> {
public:
Loop() {}
@ -452,21 +457,13 @@ public:
/// 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 {
BasicBlock *HeadBB;
DebugLoc getStartLoc() const;
// Try the pre-header first.
if ((HeadBB = getLoopPreheader()) != nullptr)
if (DebugLoc DL = HeadBB->getTerminator()->getDebugLoc())
return DL;
// If we have no pre-header or there are no instructions with debug
// info in it, try the header.
HeadBB = getHeader();
if (HeadBB)
return HeadBB->getTerminator()->getDebugLoc();
return DebugLoc();
StringRef getName() const {
if (BasicBlock *Header = getHeader())
if (Header->hasName())
return Header->getName();
return "<unnamed loop>";
}
private:
@ -775,30 +772,23 @@ template <> struct GraphTraits<Loop*> {
};
/// \brief Analysis pass that exposes the \c LoopInfo for a function.
class LoopAnalysis {
class LoopAnalysis : public AnalysisInfoMixin<LoopAnalysis> {
friend AnalysisInfoMixin<LoopAnalysis>;
static char PassID;
public:
typedef LoopInfo Result;
/// \brief Opaque, unique identifier for this analysis pass.
static void *ID() { return (void *)&PassID; }
/// \brief Provide a name for the analysis for debugging and logging.
static StringRef name() { return "LoopAnalysis"; }
LoopInfo run(Function &F, AnalysisManager<Function> *AM);
LoopInfo run(Function &F, AnalysisManager<Function> &AM);
};
/// \brief Printer pass for the \c LoopAnalysis results.
class LoopPrinterPass {
class LoopPrinterPass : public PassInfoMixin<LoopPrinterPass> {
raw_ostream &OS;
public:
explicit LoopPrinterPass(raw_ostream &OS) : OS(OS) {}
PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM);
static StringRef name() { return "LoopPrinterPass"; }
PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
};
/// \brief The legacy pass manager's analysis pass to compute loop information.
@ -828,7 +818,7 @@ public:
};
/// \brief Pass for printing a loop's contents as LLVM's text IR assembly.
class PrintLoopPass {
class PrintLoopPass : public PassInfoMixin<PrintLoopPass> {
raw_ostream &OS;
std::string Banner;
@ -836,8 +826,7 @@ public:
PrintLoopPass();
PrintLoopPass(raw_ostream &OS, const std::string &Banner = "");
PreservedAnalyses run(Loop &L);
static StringRef name() { return "PrintLoopPass"; }
PreservedAnalyses run(Loop &L, AnalysisManager<Loop> &);
};
} // End llvm namespace

View File

@ -277,7 +277,7 @@ void LoopBase<BlockT, LoopT>::verifyLoop() const {
}
assert(HasInsideLoopPreds && "Loop block has no in-loop predecessors!");
assert(HasInsideLoopSuccs && "Loop block has no in-loop successors!");
assert(BB != getHeader()->getParent()->begin() &&
assert(BB != &getHeader()->getParent()->front() &&
"Loop contains function entry block!");
NumVisited++;

View File

@ -88,9 +88,10 @@ public:
virtual void deleteAnalysisLoop(Loop *L) {}
protected:
/// skipOptnoneFunction - Containing function has Attribute::OptimizeNone
/// and most transformation passes should skip it.
bool skipOptnoneFunction(const Loop *L) const;
/// Optional passes call this function to check whether the pass should be
/// skipped. This is the case when Attribute::OptimizeNone is set or when
/// optimization bisect is over the limit.
bool skipLoop(const Loop *L) const;
};
class LPPassManager : public FunctionPass, public PMDataManager {

View File

@ -0,0 +1,142 @@
//===- LoopPassManager.h - Loop 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 loops in LLVM IR.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_LOOPPASSMANAGER_H
#define LLVM_ANALYSIS_LOOPPASSMANAGER_H
#include "llvm/ADT/STLExtras.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/IR/PassManager.h"
namespace llvm {
extern template class PassManager<Loop>;
/// \brief The loop pass manager.
///
/// See the documentation for the PassManager template for details. It runs a
/// sequency of loop passes over each loop that the manager is run over. This
/// typedef serves as a convenient way to refer to this construct.
typedef PassManager<Loop> LoopPassManager;
extern template class AnalysisManager<Loop>;
/// \brief The loop analysis manager.
///
/// See the documentation for the AnalysisManager template for detail
/// documentation. This typedef serves as a convenient way to refer to this
/// construct in the adaptors and proxies used to integrate this into the larger
/// pass manager infrastructure.
typedef AnalysisManager<Loop> LoopAnalysisManager;
extern template class InnerAnalysisManagerProxy<LoopAnalysisManager, Function>;
/// A proxy from a \c LoopAnalysisManager to a \c Function.
typedef InnerAnalysisManagerProxy<LoopAnalysisManager, Function>
LoopAnalysisManagerFunctionProxy;
extern template class OuterAnalysisManagerProxy<FunctionAnalysisManager, Loop>;
/// A proxy from a \c FunctionAnalysisManager to a \c Loop.
typedef OuterAnalysisManagerProxy<FunctionAnalysisManager, Loop>
FunctionAnalysisManagerLoopProxy;
/// Returns the minimum set of Analyses that all loop passes must preserve.
PreservedAnalyses getLoopPassPreservedAnalyses();
/// \brief Adaptor that maps from a function to its loops.
///
/// Designed to allow composition of a LoopPass(Manager) and a
/// FunctionPassManager. Note that if this pass is constructed with a \c
/// FunctionAnalysisManager it will run the \c LoopAnalysisManagerFunctionProxy
/// analysis prior to running the loop passes over the function to enable a \c
/// LoopAnalysisManager to be used within this run safely.
template <typename LoopPassT>
class FunctionToLoopPassAdaptor
: public PassInfoMixin<FunctionToLoopPassAdaptor<LoopPassT>> {
public:
explicit FunctionToLoopPassAdaptor(LoopPassT Pass)
: Pass(std::move(Pass)) {}
// We have to explicitly define all the special member functions because MSVC
// refuses to generate them.
FunctionToLoopPassAdaptor(const FunctionToLoopPassAdaptor &Arg)
: Pass(Arg.Pass) {}
FunctionToLoopPassAdaptor(FunctionToLoopPassAdaptor &&Arg)
: Pass(std::move(Arg.Pass)) {}
friend void swap(FunctionToLoopPassAdaptor &LHS,
FunctionToLoopPassAdaptor &RHS) {
using std::swap;
swap(LHS.Pass, RHS.Pass);
}
FunctionToLoopPassAdaptor &operator=(FunctionToLoopPassAdaptor RHS) {
swap(*this, RHS);
return *this;
}
/// \brief Runs the loop passes across every loop in the function.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
// Setup the loop analysis manager from its proxy.
LoopAnalysisManager &LAM =
AM.getResult<LoopAnalysisManagerFunctionProxy>(F).getManager();
// Get the loop structure for this function
LoopInfo &LI = AM.getResult<LoopAnalysis>(F);
PreservedAnalyses PA = PreservedAnalyses::all();
// We want to visit the loops in reverse post-order. We'll build the stack
// of loops to visit in Loops by first walking the loops in pre-order.
SmallVector<Loop *, 2> Loops;
SmallVector<Loop *, 2> WorkList(LI.begin(), LI.end());
while (!WorkList.empty()) {
Loop *L = WorkList.pop_back_val();
WorkList.insert(WorkList.end(), L->begin(), L->end());
Loops.push_back(L);
}
// Now pop each element off of the stack to visit the loops in reverse
// post-order.
for (auto *L : reverse(Loops)) {
PreservedAnalyses PassPA = Pass.run(*L, LAM);
assert(PassPA.preserved(getLoopPassPreservedAnalyses()) &&
"Loop passes must preserve all relevant analyses");
// We know that the loop pass couldn't have invalidated any other loop's
// analyses (that's the contract of a loop pass), so directly handle the
// loop analysis manager's invalidation here. Also, update the
// preserved analyses to reflect that once invalidated these can again
// be preserved.
PassPA = LAM.invalidate(*L, std::move(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
// loop analyses by the proxy, but that's OK because we've taken care to
// invalidate analyses in the loop analysis manager incrementally above.
PA.preserve<LoopAnalysisManagerFunctionProxy>();
return PA;
}
private:
LoopPassT Pass;
};
/// \brief A function to deduce a loop pass type and wrap it in the templated
/// adaptor.
template <typename LoopPassT>
FunctionToLoopPassAdaptor<LoopPassT>
createFunctionToLoopPassAdaptor(LoopPassT Pass) {
return FunctionToLoopPassAdaptor<LoopPassT>(std::move(Pass));
}
}
#endif // LLVM_ANALYSIS_LOOPPASSMANAGER_H

View File

@ -0,0 +1,95 @@
//===- llvm/Analysis/LoopUnrollAnalyzer.h - Loop Unroll Analyzer-*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements UnrolledInstAnalyzer class. It's used for predicting
// potential effects that loop unrolling might have, such as enabling constant
// propagation and other optimizations.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_LOOPUNROLLANALYZER_H
#define LLVM_ANALYSIS_LOOPUNROLLANALYZER_H
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
#include "llvm/IR/InstVisitor.h"
// This class is used to get an estimate of the optimization effects that we
// could get from complete loop unrolling. It comes from the fact that some
// loads might be replaced with concrete constant values and that could trigger
// a chain of instruction simplifications.
//
// E.g. we might have:
// int a[] = {0, 1, 0};
// v = 0;
// for (i = 0; i < 3; i ++)
// v += b[i]*a[i];
// If we completely unroll the loop, we would get:
// v = b[0]*a[0] + b[1]*a[1] + b[2]*a[2]
// Which then will be simplified to:
// v = b[0]* 0 + b[1]* 1 + b[2]* 0
// And finally:
// v = b[1]
namespace llvm {
class UnrolledInstAnalyzer : private InstVisitor<UnrolledInstAnalyzer, bool> {
typedef InstVisitor<UnrolledInstAnalyzer, bool> Base;
friend class InstVisitor<UnrolledInstAnalyzer, bool>;
struct SimplifiedAddress {
Value *Base = nullptr;
ConstantInt *Offset = nullptr;
};
public:
UnrolledInstAnalyzer(unsigned Iteration,
DenseMap<Value *, Constant *> &SimplifiedValues,
ScalarEvolution &SE, const Loop *L)
: SimplifiedValues(SimplifiedValues), SE(SE), L(L) {
IterationNumber = SE.getConstant(APInt(64, Iteration));
}
// Allow access to the initial visit method.
using Base::visit;
private:
/// \brief A cache of pointer bases and constant-folded offsets corresponding
/// to GEP (or derived from GEP) instructions.
///
/// In order to find the base pointer one needs to perform non-trivial
/// traversal of the corresponding SCEV expression, so it's good to have the
/// results saved.
DenseMap<Value *, SimplifiedAddress> SimplifiedAddresses;
/// \brief SCEV expression corresponding to number of currently simulated
/// iteration.
const SCEV *IterationNumber;
/// \brief A Value->Constant map for keeping values that we managed to
/// constant-fold on the given iteration.
///
/// While we walk the loop instructions, we build up and maintain a mapping
/// of simplified values specific to this iteration. The idea is to propagate
/// any special information we have about loads that can be replaced with
/// constants after complete unrolling, and account for likely simplifications
/// post-unrolling.
DenseMap<Value *, Constant *> &SimplifiedValues;
ScalarEvolution &SE;
const Loop *L;
bool simplifyInstWithSCEV(Instruction *I);
bool visitInstruction(Instruction &I) { return simplifyInstWithSCEV(&I); }
bool visitBinaryOperator(BinaryOperator &I);
bool visitLoad(LoadInst &I);
bool visitCastInst(CastInst &I);
bool visitCmpInst(CmpInst &I);
bool visitPHINode(PHINode &PN);
};
}
#endif

View File

@ -32,6 +32,11 @@ class TargetLibraryInfo;
class Type;
class Value;
enum class ObjSizeMode {
Exact = 0,
Min = 1,
Max = 2
};
/// \brief Tests if a value is a call or invoke to a library function that
/// allocates or reallocates memory (either malloc, calloc, realloc, or strdup
@ -130,8 +135,11 @@ static inline CallInst *isFreeCall(Value *I, const TargetLibraryInfo *TLI) {
/// underlying object pointed to by Ptr.
/// If RoundToAlign is true, then Size is rounded up to the aligment of allocas,
/// byval arguments, and global variables.
/// If Mode is Min or Max the size will be evaluated even if it depends on
/// a condition and corresponding value will be returned (min or max).
bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL,
const TargetLibraryInfo *TLI, bool RoundToAlign = false);
const TargetLibraryInfo *TLI, bool RoundToAlign = false,
ObjSizeMode Mode = ObjSizeMode::Exact);
typedef std::pair<APInt, APInt> SizeOffsetType;
@ -143,6 +151,7 @@ class ObjectSizeOffsetVisitor
const DataLayout &DL;
const TargetLibraryInfo *TLI;
bool RoundToAlign;
ObjSizeMode Mode;
unsigned IntTyBits;
APInt Zero;
SmallPtrSet<Instruction *, 8> SeenInsts;
@ -155,19 +164,20 @@ class ObjectSizeOffsetVisitor
public:
ObjectSizeOffsetVisitor(const DataLayout &DL, const TargetLibraryInfo *TLI,
LLVMContext &Context, bool RoundToAlign = false);
LLVMContext &Context, bool RoundToAlign = false,
ObjSizeMode Mode = ObjSizeMode::Exact);
SizeOffsetType compute(Value *V);
bool knownSize(SizeOffsetType &SizeOffset) {
static bool knownSize(const SizeOffsetType &SizeOffset) {
return SizeOffset.first.getBitWidth() > 1;
}
bool knownOffset(SizeOffsetType &SizeOffset) {
static bool knownOffset(const SizeOffsetType &SizeOffset) {
return SizeOffset.second.getBitWidth() > 1;
}
bool bothKnown(SizeOffsetType &SizeOffset) {
static bool bothKnown(const SizeOffsetType &SizeOffset) {
return knownSize(SizeOffset) && knownOffset(SizeOffset);
}
@ -198,7 +208,7 @@ typedef std::pair<Value*, Value*> SizeOffsetEvalType;
class ObjectSizeOffsetEvaluator
: public InstVisitor<ObjectSizeOffsetEvaluator, SizeOffsetEvalType> {
typedef IRBuilder<true, TargetFolder> BuilderTy;
typedef IRBuilder<TargetFolder> BuilderTy;
typedef std::pair<WeakVH, WeakVH> WeakEvalType;
typedef DenseMap<const Value*, WeakEvalType> CacheMapTy;
typedef SmallPtrSet<const Value*, 8> PtrSetTy;

View File

@ -15,452 +15,493 @@
#define LLVM_ANALYSIS_MEMORYDEPENDENCEANALYSIS_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerSumType.h"
#include "llvm/ADT/PointerEmbeddedInt.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/PredIteratorCache.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Pass.h"
namespace llvm {
class Function;
class FunctionPass;
class Instruction;
class CallSite;
class AssumptionCache;
class MemoryDependenceAnalysis;
class PredIteratorCache;
class DominatorTree;
class PHITransAddr;
class Function;
class FunctionPass;
class Instruction;
class CallSite;
class AssumptionCache;
class MemoryDependenceResults;
class PredIteratorCache;
class DominatorTree;
class PHITransAddr;
/// MemDepResult - A memory dependence query can return one of three different
/// answers, described below.
class MemDepResult {
enum DepType {
/// Invalid - Clients of MemDep never see this.
Invalid = 0,
/// Clobber - This is a dependence on the specified instruction which
/// clobbers the desired value. The pointer member of the MemDepResult
/// pair holds the instruction that clobbers the memory. For example,
/// this occurs when we see a may-aliased store to the memory location we
/// care about.
///
/// There are several cases that may be interesting here:
/// 1. Loads are clobbered by may-alias stores.
/// 2. Loads are considered clobbered by partially-aliased loads. The
/// client may choose to analyze deeper into these cases.
Clobber,
/// Def - This is a dependence on the specified instruction which
/// defines/produces the desired memory location. The pointer member of
/// the MemDepResult pair holds the instruction that defines the memory.
/// Cases of interest:
/// 1. This could be a load or store for dependence queries on
/// load/store. The value loaded or stored is the produced value.
/// Note that the pointer operand may be different than that of the
/// queried pointer due to must aliases and phi translation. Note
/// that the def may not be the same type as the query, the pointers
/// may just be must aliases.
/// 2. For loads and stores, this could be an allocation instruction. In
/// this case, the load is loading an undef value or a store is the
/// first store to (that part of) the allocation.
/// 3. Dependence queries on calls return Def only when they are
/// readonly calls or memory use intrinsics with identical callees
/// and no intervening clobbers. No validation is done that the
/// operands to the calls are the same.
Def,
/// Other - This marker indicates that the query has no known dependency
/// in the specified block. More detailed state info is encoded in the
/// upper part of the pair (i.e. the Instruction*)
Other
};
/// If DepType is "Other", the upper part of the pair
/// (i.e. the Instruction* part) is instead used to encode more detailed
/// type information as follows
enum OtherType {
/// NonLocal - This marker indicates that the query has no dependency in
/// the specified block. To find out more, the client should query other
/// predecessor blocks.
NonLocal = 0x4,
/// NonFuncLocal - This marker indicates that the query has no
/// dependency in the specified function.
NonFuncLocal = 0x8,
/// Unknown - This marker indicates that the query dependency
/// is unknown.
Unknown = 0xc
};
typedef PointerIntPair<Instruction*, 2, DepType> PairTy;
PairTy Value;
explicit MemDepResult(PairTy V) : Value(V) {}
public:
MemDepResult() : Value(nullptr, Invalid) {}
/// get methods: These are static ctor methods for creating various
/// MemDepResult kinds.
static MemDepResult getDef(Instruction *Inst) {
assert(Inst && "Def requires inst");
return MemDepResult(PairTy(Inst, Def));
}
static MemDepResult getClobber(Instruction *Inst) {
assert(Inst && "Clobber requires inst");
return MemDepResult(PairTy(Inst, Clobber));
}
static MemDepResult getNonLocal() {
return MemDepResult(
PairTy(reinterpret_cast<Instruction*>(NonLocal), Other));
}
static MemDepResult getNonFuncLocal() {
return MemDepResult(
PairTy(reinterpret_cast<Instruction*>(NonFuncLocal), Other));
}
static MemDepResult getUnknown() {
return MemDepResult(
PairTy(reinterpret_cast<Instruction*>(Unknown), Other));
}
/// isClobber - Return true if this MemDepResult represents a query that is
/// an instruction clobber dependency.
bool isClobber() const { return Value.getInt() == Clobber; }
/// isDef - Return true if this MemDepResult represents a query that is
/// an instruction definition dependency.
bool isDef() const { return Value.getInt() == Def; }
/// isNonLocal - Return true if this MemDepResult represents a query that
/// is transparent to the start of the block, but where a non-local hasn't
/// been done.
bool isNonLocal() const {
return Value.getInt() == Other
&& Value.getPointer() == reinterpret_cast<Instruction*>(NonLocal);
}
/// isNonFuncLocal - Return true if this MemDepResult represents a query
/// that is transparent to the start of the function.
bool isNonFuncLocal() const {
return Value.getInt() == Other
&& Value.getPointer() == reinterpret_cast<Instruction*>(NonFuncLocal);
}
/// isUnknown - Return true if this MemDepResult represents a query which
/// cannot and/or will not be computed.
bool isUnknown() const {
return Value.getInt() == Other
&& Value.getPointer() == reinterpret_cast<Instruction*>(Unknown);
}
/// 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 nullptr;
return Value.getPointer();
}
bool operator==(const MemDepResult &M) const { return Value == M.Value; }
bool operator!=(const MemDepResult &M) const { return Value != M.Value; }
bool operator<(const MemDepResult &M) const { return Value < M.Value; }
bool operator>(const MemDepResult &M) const { return Value > M.Value; }
private:
friend class MemoryDependenceAnalysis;
/// Dirty - Entries with this marker occur in a LocalDeps map or
/// NonLocalDeps map when the instruction they previously referenced was
/// removed from MemDep. In either case, the entry may include an
/// instruction pointer. If so, the pointer is an instruction in the
/// block where scanning can start from, saving some work.
/// A memory dependence query can return one of three different answers.
class MemDepResult {
enum DepType {
/// Clients of MemDep never see this.
///
/// In a default-constructed MemDepResult object, the type will be Dirty
/// Entries with this marker occur in a LocalDeps map or NonLocalDeps map
/// when the instruction they previously referenced was removed from
/// MemDep. In either case, the entry may include an instruction pointer.
/// If so, the pointer is an instruction in the block where scanning can
/// start from, saving some work.
///
/// In a default-constructed MemDepResult object, the type will be Invalid
/// and the instruction pointer will be null.
Invalid = 0,
/// This is a dependence on the specified instruction which clobbers the
/// desired value. The pointer member of the MemDepResult pair holds the
/// instruction that clobbers the memory. For example, this occurs when we
/// see a may-aliased store to the memory location we care about.
///
/// There are several cases that may be interesting here:
/// 1. Loads are clobbered by may-alias stores.
/// 2. Loads are considered clobbered by partially-aliased loads. The
/// client may choose to analyze deeper into these cases.
Clobber,
/// isDirty - Return true if this is a MemDepResult in its dirty/invalid.
/// state.
bool isDirty() const { return Value.getInt() == Invalid; }
/// This is a dependence on the specified instruction which defines or
/// produces the desired memory location. The pointer member of the
/// MemDepResult pair holds the instruction that defines the memory.
///
/// Cases of interest:
/// 1. This could be a load or store for dependence queries on
/// load/store. The value loaded or stored is the produced value.
/// Note that the pointer operand may be different than that of the
/// queried pointer due to must aliases and phi translation. Note
/// that the def may not be the same type as the query, the pointers
/// may just be must aliases.
/// 2. For loads and stores, this could be an allocation instruction. In
/// this case, the load is loading an undef value or a store is the
/// first store to (that part of) the allocation.
/// 3. Dependence queries on calls return Def only when they are readonly
/// calls or memory use intrinsics with identical callees and no
/// intervening clobbers. No validation is done that the operands to
/// the calls are the same.
Def,
static MemDepResult getDirty(Instruction *Inst) {
return MemDepResult(PairTy(Inst, Invalid));
}
/// This marker indicates that the query has no known dependency in the
/// specified block.
///
/// More detailed state info is encoded in the upper part of the pair (i.e.
/// the Instruction*)
Other
};
/// NonLocalDepEntry - This is an entry in the NonLocalDepInfo cache. For
/// each BasicBlock (the BB entry) it keeps a MemDepResult.
class NonLocalDepEntry {
BasicBlock *BB;
MemDepResult Result;
/// If DepType is "Other", the upper part of the sum type is an encoding of
/// the following more detailed type information.
enum OtherType {
/// This marker indicates that the query has no dependency in the specified
/// block.
///
/// To find out more, the client should query other predecessor blocks.
NonLocal = 1,
/// This marker indicates that the query has no dependency in the specified
/// function.
NonFuncLocal,
/// This marker indicates that the query dependency is unknown.
Unknown
};
public:
NonLocalDepEntry(BasicBlock *bb, MemDepResult result)
typedef PointerSumType<
DepType, PointerSumTypeMember<Invalid, Instruction *>,
PointerSumTypeMember<Clobber, Instruction *>,
PointerSumTypeMember<Def, Instruction *>,
PointerSumTypeMember<Other, PointerEmbeddedInt<OtherType, 3>>>
ValueTy;
ValueTy Value;
explicit MemDepResult(ValueTy V) : Value(V) {}
public:
MemDepResult() : Value() {}
/// get methods: These are static ctor methods for creating various
/// MemDepResult kinds.
static MemDepResult getDef(Instruction *Inst) {
assert(Inst && "Def requires inst");
return MemDepResult(ValueTy::create<Def>(Inst));
}
static MemDepResult getClobber(Instruction *Inst) {
assert(Inst && "Clobber requires inst");
return MemDepResult(ValueTy::create<Clobber>(Inst));
}
static MemDepResult getNonLocal() {
return MemDepResult(ValueTy::create<Other>(NonLocal));
}
static MemDepResult getNonFuncLocal() {
return MemDepResult(ValueTy::create<Other>(NonFuncLocal));
}
static MemDepResult getUnknown() {
return MemDepResult(ValueTy::create<Other>(Unknown));
}
/// Tests if this MemDepResult represents a query that is an instruction
/// clobber dependency.
bool isClobber() const { return Value.is<Clobber>(); }
/// Tests if this MemDepResult represents a query that is an instruction
/// definition dependency.
bool isDef() const { return Value.is<Def>(); }
/// Tests if this MemDepResult represents a query that is transparent to the
/// start of the block, but where a non-local hasn't been done.
bool isNonLocal() const {
return Value.is<Other>() && Value.cast<Other>() == NonLocal;
}
/// Tests if this MemDepResult represents a query that is transparent to the
/// start of the function.
bool isNonFuncLocal() const {
return Value.is<Other>() && Value.cast<Other>() == NonFuncLocal;
}
/// Tests if this MemDepResult represents a query which cannot and/or will
/// not be computed.
bool isUnknown() const {
return Value.is<Other>() && Value.cast<Other>() == Unknown;
}
/// If this is a normal dependency, returns the instruction that is depended
/// on. Otherwise, returns null.
Instruction *getInst() const {
switch (Value.getTag()) {
case Invalid:
return Value.cast<Invalid>();
case Clobber:
return Value.cast<Clobber>();
case Def:
return Value.cast<Def>();
case Other:
return nullptr;
}
llvm_unreachable("Unknown discriminant!");
}
bool operator==(const MemDepResult &M) const { return Value == M.Value; }
bool operator!=(const MemDepResult &M) const { return Value != M.Value; }
bool operator<(const MemDepResult &M) const { return Value < M.Value; }
bool operator>(const MemDepResult &M) const { return Value > M.Value; }
private:
friend class MemoryDependenceResults;
/// Tests if this is a MemDepResult in its dirty/invalid. state.
bool isDirty() const { return Value.is<Invalid>(); }
static MemDepResult getDirty(Instruction *Inst) {
return MemDepResult(ValueTy::create<Invalid>(Inst));
}
};
/// This is an entry in the NonLocalDepInfo cache.
///
/// For each BasicBlock (the BB entry) it keeps a MemDepResult.
class NonLocalDepEntry {
BasicBlock *BB;
MemDepResult Result;
public:
NonLocalDepEntry(BasicBlock *bb, MemDepResult result)
: BB(bb), Result(result) {}
// This is used for searches.
NonLocalDepEntry(BasicBlock *bb) : BB(bb) {}
// This is used for searches.
NonLocalDepEntry(BasicBlock *bb) : BB(bb) {}
// BB is the sort key, it can't be changed.
BasicBlock *getBB() const { return BB; }
// BB is the sort key, it can't be changed.
BasicBlock *getBB() const { return BB; }
void setResult(const MemDepResult &R) { Result = R; }
void setResult(const MemDepResult &R) { Result = R; }
const MemDepResult &getResult() const { return Result; }
const MemDepResult &getResult() const { return Result; }
bool operator<(const NonLocalDepEntry &RHS) const {
return BB < RHS.BB;
}
};
bool operator<(const NonLocalDepEntry &RHS) const { return BB < RHS.BB; }
};
/// NonLocalDepResult - This is a result from a NonLocal dependence query.
/// For each BasicBlock (the BB entry) it keeps a MemDepResult and the
/// (potentially phi translated) address that was live in the block.
class NonLocalDepResult {
NonLocalDepEntry Entry;
Value *Address;
/// This is a result from a NonLocal dependence query.
///
/// For each BasicBlock (the BB entry) it keeps a MemDepResult and the
/// (potentially phi translated) address that was live in the block.
class NonLocalDepResult {
NonLocalDepEntry Entry;
Value *Address;
public:
NonLocalDepResult(BasicBlock *bb, MemDepResult result, Value *address)
public:
NonLocalDepResult(BasicBlock *bb, MemDepResult result, Value *address)
: Entry(bb, result), Address(address) {}
// BB is the sort key, it can't be changed.
BasicBlock *getBB() const { return Entry.getBB(); }
// BB is the sort key, it can't be changed.
BasicBlock *getBB() const { return Entry.getBB(); }
void setResult(const MemDepResult &R, Value *Addr) {
Entry.setResult(R);
Address = Addr;
}
void setResult(const MemDepResult &R, Value *Addr) {
Entry.setResult(R);
Address = Addr;
}
const MemDepResult &getResult() const { return Entry.getResult(); }
const MemDepResult &getResult() const { return Entry.getResult(); }
/// getAddress - Return the address of this pointer in this block. This can
/// be different than the address queried for the non-local result because
/// of phi translation. This returns null if the address was not available
/// in a block (i.e. because phi translation failed) or if this is a cached
/// result and that address was deleted.
/// Returns the address of this pointer in this block.
///
/// This can be different than the address queried for the non-local result
/// because of phi translation. This returns null if the address was not
/// available in a block (i.e. because phi translation failed) or if this is
/// a cached result and that address was deleted.
///
/// The address is always null for a non-local 'call' dependence.
Value *getAddress() const { return Address; }
};
/// Provides a lazy, caching interface for making common memory aliasing
/// information queries, backed by LLVM's alias analysis passes.
///
/// The dependency information returned is somewhat unusual, but is pragmatic.
/// If queried about a store or call that might modify memory, the analysis
/// will return the instruction[s] that may either load from that memory or
/// store to it. If queried with a load or call that can never modify memory,
/// the analysis will return calls and stores that might modify the pointer,
/// but generally does not return loads unless a) they are volatile, or
/// b) they load from *must-aliased* pointers. Returning a dependence on
/// must-alias'd pointers instead of all pointers interacts well with the
/// internal caching mechanism.
class MemoryDependenceResults {
// A map from instructions to their dependency.
typedef DenseMap<Instruction *, MemDepResult> LocalDepMapType;
LocalDepMapType LocalDeps;
public:
typedef std::vector<NonLocalDepEntry> NonLocalDepInfo;
private:
/// A pair<Value*, bool> where the bool is true if the dependence is a read
/// only dependence, false if read/write.
typedef PointerIntPair<const Value *, 1, bool> ValueIsLoadPair;
/// This pair is used when caching information for a block.
///
/// If the pointer is null, the cache value is not a full query that starts
/// at the specified block. If non-null, the bool indicates whether or not
/// the contents of the block was skipped.
typedef PointerIntPair<BasicBlock *, 1, bool> BBSkipFirstBlockPair;
/// This record is the information kept for each (value, is load) pair.
struct NonLocalPointerInfo {
/// The pair of the block and the skip-first-block flag.
BBSkipFirstBlockPair Pair;
/// The results of the query for each relevant block.
NonLocalDepInfo NonLocalDeps;
/// The maximum size of the dereferences of the pointer.
///
/// The address is always null for a non-local 'call' dependence.
Value *getAddress() const { return Address; }
/// May be UnknownSize if the sizes are unknown.
uint64_t Size;
/// The AA tags associated with dereferences of the pointer.
///
/// The members may be null if there are no tags or conflicting tags.
AAMDNodes AATags;
NonLocalPointerInfo() : Size(MemoryLocation::UnknownSize) {}
};
/// MemoryDependenceAnalysis - This is an analysis that determines, for a
/// given memory operation, what preceding memory operations it depends on.
/// It builds on alias analysis information, and tries to provide a lazy,
/// caching interface to a common kind of alias information query.
/// This map stores the cached results of doing a pointer lookup at the
/// bottom of a block.
///
/// The dependency information returned is somewhat unusual, but is pragmatic.
/// If queried about a store or call that might modify memory, the analysis
/// will return the instruction[s] that may either load from that memory or
/// store to it. If queried with a load or call that can never modify memory,
/// the analysis will return calls and stores that might modify the pointer,
/// but generally does not return loads unless a) they are volatile, or
/// b) they load from *must-aliased* pointers. Returning a dependence on
/// must-alias'd pointers instead of all pointers interacts well with the
/// internal caching mechanism.
/// The key of this map is the pointer+isload bit, the value is a list of
/// <bb->result> mappings.
typedef DenseMap<ValueIsLoadPair, NonLocalPointerInfo>
CachedNonLocalPointerInfo;
CachedNonLocalPointerInfo NonLocalPointerDeps;
// A map from instructions to their non-local pointer dependencies.
typedef DenseMap<Instruction *, SmallPtrSet<ValueIsLoadPair, 4>>
ReverseNonLocalPtrDepTy;
ReverseNonLocalPtrDepTy ReverseNonLocalPtrDeps;
/// This is the instruction we keep for each cached access that we have for
/// an instruction.
///
class MemoryDependenceAnalysis : public FunctionPass {
// A map from instructions to their dependency.
typedef DenseMap<Instruction*, MemDepResult> LocalDepMapType;
LocalDepMapType LocalDeps;
/// The pointer is an owning pointer and the bool indicates whether we have
/// any dirty bits in the set.
typedef std::pair<NonLocalDepInfo, bool> PerInstNLInfo;
public:
typedef std::vector<NonLocalDepEntry> NonLocalDepInfo;
// A map from instructions to their non-local dependencies.
typedef DenseMap<Instruction *, PerInstNLInfo> NonLocalDepMapType;
private:
/// ValueIsLoadPair - This is a pair<Value*, bool> where the bool is true if
/// the dependence is a read only dependence, false if read/write.
typedef PointerIntPair<const Value*, 1, bool> ValueIsLoadPair;
NonLocalDepMapType NonLocalDeps;
/// BBSkipFirstBlockPair - This pair is used when caching information for a
/// block. If the pointer is null, the cache value is not a full query that
/// starts at the specified block. If non-null, the bool indicates whether
/// or not the contents of the block was skipped.
typedef PointerIntPair<BasicBlock*, 1, bool> BBSkipFirstBlockPair;
// A reverse mapping from dependencies to the dependees. This is
// used when removing instructions to keep the cache coherent.
typedef DenseMap<Instruction *, SmallPtrSet<Instruction *, 4>>
ReverseDepMapType;
ReverseDepMapType ReverseLocalDeps;
/// NonLocalPointerInfo - This record is the information kept for each
/// (value, is load) pair.
struct NonLocalPointerInfo {
/// Pair - The pair of the block and the skip-first-block flag.
BBSkipFirstBlockPair Pair;
/// NonLocalDeps - The results of the query for each relevant block.
NonLocalDepInfo NonLocalDeps;
/// Size - The maximum size of the dereferences of the
/// pointer. May be UnknownSize if the sizes are unknown.
uint64_t Size;
/// AATags - The AA tags associated with dereferences of the
/// pointer. The members may be null if there are no tags or
/// conflicting tags.
AAMDNodes AATags;
// A reverse mapping from dependencies to the non-local dependees.
ReverseDepMapType ReverseNonLocalDeps;
NonLocalPointerInfo() : Size(MemoryLocation::UnknownSize) {}
};
/// Current AA implementation, just a cache.
AliasAnalysis &AA;
AssumptionCache &AC;
const TargetLibraryInfo &TLI;
DominatorTree &DT;
PredIteratorCache PredCache;
/// CachedNonLocalPointerInfo - This map stores the cached results of doing
/// a pointer lookup at the bottom of a block. The key of this map is the
/// pointer+isload bit, the value is a list of <bb->result> mappings.
typedef DenseMap<ValueIsLoadPair,
NonLocalPointerInfo> CachedNonLocalPointerInfo;
CachedNonLocalPointerInfo NonLocalPointerDeps;
public:
MemoryDependenceResults(AliasAnalysis &AA, AssumptionCache &AC,
const TargetLibraryInfo &TLI,
DominatorTree &DT)
: AA(AA), AC(AC), TLI(TLI), DT(DT) {}
// A map from instructions to their non-local pointer dependencies.
typedef DenseMap<Instruction*,
SmallPtrSet<ValueIsLoadPair, 4> > ReverseNonLocalPtrDepTy;
ReverseNonLocalPtrDepTy ReverseNonLocalPtrDeps;
/// Returns the instruction on which a memory operation depends.
///
/// See the class comment for more details. It is illegal to call this on
/// non-memory instructions.
MemDepResult getDependency(Instruction *QueryInst);
/// PerInstNLInfo - This is the instruction we keep for each cached access
/// that we have for an instruction. The pointer is an owning pointer and
/// the bool indicates whether we have any dirty bits in the set.
typedef std::pair<NonLocalDepInfo, bool> PerInstNLInfo;
/// Perform a full dependency query for the specified call, returning the set
/// of blocks that the value is potentially live across.
///
/// The returned set of results will include a "NonLocal" result for all
/// blocks where the value is live across.
///
/// This method assumes the instruction returns a "NonLocal" dependency
/// within its own block.
///
/// This returns a reference to an internal data structure that may be
/// invalidated on the next non-local query or when an instruction is
/// removed. Clients must copy this data if they want it around longer than
/// that.
const NonLocalDepInfo &getNonLocalCallDependency(CallSite QueryCS);
// A map from instructions to their non-local dependencies.
typedef DenseMap<Instruction*, PerInstNLInfo> NonLocalDepMapType;
NonLocalDepMapType NonLocalDeps;
// A reverse mapping from dependencies to the dependees. This is
// used when removing instructions to keep the cache coherent.
typedef DenseMap<Instruction*,
SmallPtrSet<Instruction*, 4> > ReverseDepMapType;
ReverseDepMapType ReverseLocalDeps;
// A reverse mapping from dependencies to the non-local dependees.
ReverseDepMapType ReverseNonLocalDeps;
/// Current AA implementation, just a cache.
AliasAnalysis *AA;
DominatorTree *DT;
AssumptionCache *AC;
const TargetLibraryInfo *TLI;
PredIteratorCache PredCache;
public:
MemoryDependenceAnalysis();
~MemoryDependenceAnalysis() override;
static char ID;
/// Pass Implementation stuff. This doesn't do any analysis eagerly.
bool runOnFunction(Function &) override;
/// Clean up memory in between runs
void releaseMemory() override;
/// getAnalysisUsage - Does not modify anything. It uses Value Numbering
/// and Alias Analysis.
///
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
/// this on non-memory instructions.
MemDepResult getDependency(Instruction *QueryInst);
/// getNonLocalCallDependency - Perform a full dependency query for the
/// specified call, returning the set of blocks that the value is
/// potentially live across. The returned set of results will include a
/// "NonLocal" result for all blocks where the value is live across.
///
/// This method assumes the instruction returns a "NonLocal" dependency
/// within its own block.
///
/// This returns a reference to an internal data structure that may be
/// invalidated on the next non-local query or when an instruction is
/// removed. Clients must copy this data if they want it around longer than
/// that.
const NonLocalDepInfo &getNonLocalCallDependency(CallSite QueryCS);
/// getNonLocalPointerDependency - Perform a full dependency query for an
/// access to the QueryInst's specified memory location, returning the set
/// of instructions that either define or clobber the value.
///
/// Warning: For a volatile query instruction, the dependencies will be
/// accurate, and thus usable for reordering, but it is never legal to
/// remove the query instruction.
///
/// This method assumes the pointer has a "NonLocal" dependency within
/// QueryInst's parent basic block.
void getNonLocalPointerDependency(Instruction *QueryInst,
/// Perform a full dependency query for an access to the QueryInst's
/// specified memory location, returning the set of instructions that either
/// define or clobber the value.
///
/// Warning: For a volatile query instruction, the dependencies will be
/// accurate, and thus usable for reordering, but it is never legal to
/// remove the query instruction.
///
/// This method assumes the pointer has a "NonLocal" dependency within
/// QueryInst's parent basic block.
void getNonLocalPointerDependency(Instruction *QueryInst,
SmallVectorImpl<NonLocalDepResult> &Result);
/// removeInstruction - Remove an instruction from the dependence analysis,
/// updating the dependence of instructions that previously depended on it.
void removeInstruction(Instruction *InstToRemove);
/// Removes an instruction from the dependence analysis, updating the
/// dependence of instructions that previously depended on it.
void removeInstruction(Instruction *InstToRemove);
/// invalidateCachedPointerInfo - This method is used to invalidate cached
/// information about the specified pointer, because it may be too
/// conservative in memdep. This is an optional call that can be used when
/// the client detects an equivalence between the pointer and some other
/// value and replaces the other value with ptr. This can make Ptr available
/// in more places that cached info does not necessarily keep.
void invalidateCachedPointerInfo(Value *Ptr);
/// Invalidates cached information about the specified pointer, because it
/// may be too conservative in memdep.
///
/// This is an optional call that can be used when the client detects an
/// equivalence between the pointer and some other value and replaces the
/// other value with ptr. This can make Ptr available in more places that
/// cached info does not necessarily keep.
void invalidateCachedPointerInfo(Value *Ptr);
/// invalidateCachedPredecessors - Clear the PredIteratorCache info.
/// This needs to be done when the CFG changes, e.g., due to splitting
/// critical edges.
void invalidateCachedPredecessors();
/// Clears the PredIteratorCache info.
///
/// This needs to be done when the CFG changes, e.g., due to splitting
/// critical edges.
void invalidateCachedPredecessors();
/// \brief Return the instruction on which a memory location depends.
/// If isLoad is true, this routine ignores may-aliases with read-only
/// operations. If isLoad is false, this routine ignores may-aliases
/// with reads from read-only locations. If possible, pass the query
/// instruction as well; this function may take advantage of the metadata
/// annotated to the query instruction to refine the result.
///
/// Note that this is an uncached query, and thus may be inefficient.
///
MemDepResult getPointerDependencyFrom(const MemoryLocation &Loc,
bool isLoad,
BasicBlock::iterator ScanIt,
BasicBlock *BB,
Instruction *QueryInst = nullptr);
/// Returns the instruction on which a memory location depends.
///
/// If isLoad is true, this routine ignores may-aliases with read-only
/// operations. If isLoad is false, this routine ignores may-aliases
/// with reads from read-only locations. If possible, pass the query
/// instruction as well; this function may take advantage of the metadata
/// annotated to the query instruction to refine the result.
///
/// Note that this is an uncached query, and thus may be inefficient.
MemDepResult getPointerDependencyFrom(const MemoryLocation &Loc, bool isLoad,
BasicBlock::iterator ScanIt,
BasicBlock *BB,
Instruction *QueryInst = nullptr);
MemDepResult getSimplePointerDependencyFrom(const MemoryLocation &MemLoc,
bool isLoad,
BasicBlock::iterator ScanIt,
BasicBlock *BB,
Instruction *QueryInst);
MemDepResult getSimplePointerDependencyFrom(const MemoryLocation &MemLoc,
bool isLoad,
BasicBlock::iterator ScanIt,
BasicBlock *BB,
Instruction *QueryInst);
/// This analysis looks for other loads and stores with invariant.group
/// metadata and the same pointer operand. Returns Unknown if it does not
/// find anything, and Def if it can be assumed that 2 instructions load or
/// store the same value.
/// FIXME: This analysis works only on single block because of restrictions
/// at the call site.
MemDepResult getInvariantGroupPointerDependency(LoadInst *LI,
BasicBlock *BB);
/// This analysis looks for other loads and stores with invariant.group
/// metadata and the same pointer operand. Returns Unknown if it does not
/// find anything, and Def if it can be assumed that 2 instructions load or
/// store the same value.
/// FIXME: This analysis works only on single block because of restrictions
/// at the call site.
MemDepResult getInvariantGroupPointerDependency(LoadInst *LI, BasicBlock *BB);
/// getLoadLoadClobberFullWidthSize - This is a little bit of analysis that
/// looks at a memory location for a load (specified by MemLocBase, Offs,
/// and Size) and compares it against a load. If the specified load could
/// be safely widened to a larger integer load that is 1) still efficient,
/// 2) safe for the target, and 3) would provide the specified memory
/// location value, then this function returns the size in bytes of the
/// load width to use. If not, this returns zero.
static unsigned getLoadLoadClobberFullWidthSize(const Value *MemLocBase,
int64_t MemLocOffs,
unsigned MemLocSize,
const LoadInst *LI);
/// Looks at a memory location for a load (specified by MemLocBase, Offs, and
/// Size) and compares it against a load.
///
/// If the specified load could be safely widened to a larger integer load
/// that is 1) still efficient, 2) safe for the target, and 3) would provide
/// the specified memory location value, then this function returns the size
/// in bytes of the load width to use. If not, this returns zero.
static unsigned getLoadLoadClobberFullWidthSize(const Value *MemLocBase,
int64_t MemLocOffs,
unsigned MemLocSize,
const LoadInst *LI);
private:
MemDepResult getCallSiteDependencyFrom(CallSite C, bool isReadOnlyCall,
BasicBlock::iterator ScanIt,
BasicBlock *BB);
bool getNonLocalPointerDepFromBB(Instruction *QueryInst,
const PHITransAddr &Pointer,
const MemoryLocation &Loc, bool isLoad,
BasicBlock *BB,
SmallVectorImpl<NonLocalDepResult> &Result,
DenseMap<BasicBlock *, Value *> &Visited,
bool SkipFirstBlock = false);
MemDepResult GetNonLocalInfoForBlock(Instruction *QueryInst,
const MemoryLocation &Loc, bool isLoad,
BasicBlock *BB, NonLocalDepInfo *Cache,
unsigned NumSortedEntries);
/// Release memory in caches.
void releaseMemory();
void RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair P);
private:
MemDepResult getCallSiteDependencyFrom(CallSite C, bool isReadOnlyCall,
BasicBlock::iterator ScanIt,
BasicBlock *BB);
bool getNonLocalPointerDepFromBB(Instruction *QueryInst,
const PHITransAddr &Pointer,
const MemoryLocation &Loc, bool isLoad,
BasicBlock *BB,
SmallVectorImpl<NonLocalDepResult> &Result,
DenseMap<BasicBlock *, Value *> &Visited,
bool SkipFirstBlock = false);
MemDepResult GetNonLocalInfoForBlock(Instruction *QueryInst,
const MemoryLocation &Loc, bool isLoad,
BasicBlock *BB, NonLocalDepInfo *Cache,
unsigned NumSortedEntries);
/// verifyRemoved - Verify that the specified instruction does not occur
/// in our internal data structures.
void verifyRemoved(Instruction *Inst) const;
};
void RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair P);
void verifyRemoved(Instruction *Inst) const;
};
/// An analysis that produces \c MemoryDependenceResults for a function.
///
/// This is essentially a no-op because the results are computed entirely
/// lazily.
class MemoryDependenceAnalysis
: public AnalysisInfoMixin<MemoryDependenceAnalysis> {
friend AnalysisInfoMixin<MemoryDependenceAnalysis>;
static char PassID;
public:
typedef MemoryDependenceResults Result;
MemoryDependenceResults run(Function &F, AnalysisManager<Function> &AM);
};
/// A wrapper analysis pass for the legacy pass manager that exposes a \c
/// MemoryDepnedenceResults instance.
class MemoryDependenceWrapperPass : public FunctionPass {
Optional<MemoryDependenceResults> MemDep;
public:
MemoryDependenceWrapperPass();
~MemoryDependenceWrapperPass() override;
static char ID;
/// Pass Implementation stuff. This doesn't do any analysis eagerly.
bool runOnFunction(Function &) override;
/// Clean up memory in between runs
void releaseMemory() override;
/// Does not modify anything. It uses Value Numbering and Alias Analysis.
void getAnalysisUsage(AnalysisUsage &AU) const override;
MemoryDependenceResults &getMemDep() { return *MemDep; }
};
} // End llvm namespace

View File

@ -16,7 +16,7 @@
#ifndef LLVM_ANALYSIS_MEMORYLOCATION_H
#define LLVM_ANALYSIS_MEMORYLOCATION_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Metadata.h"

View File

@ -0,0 +1,91 @@
//===- ModuleSummaryAnalysis.h - Module summary index builder ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
/// This is the interface to build a ModuleSummaryIndex for a module.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_MODULESUMMARYANALYSIS_H
#define LLVM_ANALYSIS_MODULESUMMARYANALYSIS_H
#include "llvm/ADT/STLExtras.h"
#include "llvm/IR/ModuleSummaryIndex.h"
#include "llvm/Pass.h"
namespace llvm {
class BlockFrequencyInfo;
/// Class to build a module summary index for the given Module, possibly from
/// a Pass.
class ModuleSummaryIndexBuilder {
/// The index being built
std::unique_ptr<ModuleSummaryIndex> Index;
/// The module for which we are building an index
const Module *M;
public:
/// Default constructor
ModuleSummaryIndexBuilder() = default;
/// Constructor that builds an index for the given Module. An optional
/// callback can be supplied to obtain the frequency info for a function.
ModuleSummaryIndexBuilder(
const Module *M,
std::function<BlockFrequencyInfo *(const Function &F)> Ftor = nullptr);
/// Get a reference to the index owned by builder
ModuleSummaryIndex &getIndex() const { return *Index; }
/// Take ownership of the built index
std::unique_ptr<ModuleSummaryIndex> takeIndex() { return std::move(Index); }
private:
/// Compute summary for given function with optional frequency information
void computeFunctionSummary(const Function &F,
BlockFrequencyInfo *BFI = nullptr);
/// Compute summary for given variable with optional frequency information
void computeVariableSummary(const GlobalVariable &V);
};
/// Legacy wrapper pass to provide the ModuleSummaryIndex object.
class ModuleSummaryIndexWrapperPass : public ModulePass {
std::unique_ptr<ModuleSummaryIndexBuilder> IndexBuilder;
public:
static char ID;
ModuleSummaryIndexWrapperPass();
/// Get the index built by pass
ModuleSummaryIndex &getIndex() { return IndexBuilder->getIndex(); }
const ModuleSummaryIndex &getIndex() const {
return IndexBuilder->getIndex();
}
bool runOnModule(Module &M) override;
bool doFinalization(Module &M) override;
void getAnalysisUsage(AnalysisUsage &AU) const override;
};
//===--------------------------------------------------------------------===//
//
// createModuleSummaryIndexWrapperPass - This pass builds a ModuleSummaryIndex
// object for the module, to be written to bitcode or LLVM assembly.
//
ModulePass *createModuleSummaryIndexWrapperPass();
/// Returns true if \p M is eligible for ThinLTO promotion.
///
/// Currently we check if it has any any InlineASM that uses an internal symbol.
bool moduleCanBeRenamedForThinLTO(const Module &M);
}
#endif

View File

@ -24,7 +24,6 @@
#define LLVM_ANALYSIS_OBJCARCALIASANALYSIS_H
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Pass.h"
namespace llvm {
@ -42,8 +41,7 @@ class ObjCARCAAResult : public AAResultBase<ObjCARCAAResult> {
const DataLayout &DL;
public:
explicit ObjCARCAAResult(const DataLayout &DL, const TargetLibraryInfo &TLI)
: AAResultBase(TLI), DL(DL) {}
explicit ObjCARCAAResult(const DataLayout &DL) : AAResultBase(), DL(DL) {}
ObjCARCAAResult(ObjCARCAAResult &&Arg)
: AAResultBase(std::move(Arg)), DL(Arg.DL) {}
@ -63,20 +61,14 @@ public:
};
/// Analysis pass providing a never-invalidated alias analysis result.
class ObjCARCAA {
class ObjCARCAA : public AnalysisInfoMixin<ObjCARCAA> {
friend AnalysisInfoMixin<ObjCARCAA>;
static char PassID;
public:
typedef ObjCARCAAResult Result;
/// \brief Opaque, unique identifier for this analysis pass.
static void *ID() { return (void *)&PassID; }
ObjCARCAAResult run(Function &F, AnalysisManager<Function> *AM);
/// \brief Provide access to a name for this pass for debugging purposes.
static StringRef name() { return "ObjCARCAA"; }
private:
static char PassID;
ObjCARCAAResult run(Function &F, AnalysisManager<Function> &AM);
};
/// Legacy wrapper pass to provide the ObjCARCAAResult object.

View File

@ -54,6 +54,7 @@ inline bool ModuleHasARC(const Module &M) {
M.getNamedValue("objc_release") ||
M.getNamedValue("objc_autorelease") ||
M.getNamedValue("objc_retainAutoreleasedReturnValue") ||
M.getNamedValue("objc_unsafeClaimAutoreleasedReturnValue") ||
M.getNamedValue("objc_retainBlock") ||
M.getNamedValue("objc_autoreleaseReturnValue") ||
M.getNamedValue("objc_autoreleasePoolPush") ||

View File

@ -30,6 +30,7 @@ namespace objcarc {
enum class ARCInstKind {
Retain, ///< objc_retain
RetainRV, ///< objc_retainAutoreleasedReturnValue
ClaimRV, ///< objc_unsafeClaimAutoreleasedReturnValue
RetainBlock, ///< objc_retainBlock
Release, ///< objc_release
Autorelease, ///< objc_autorelease

View File

@ -0,0 +1,104 @@
//===- OptimizationDiagnosticInfo.h - Optimization Diagnostic ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Optimization diagnostic interfaces. It's packaged as an analysis pass so
// that by using this service passes become dependent on BFI as well. BFI is
// used to compute the "hotness" of the diagnostic message.
//===----------------------------------------------------------------------===//
#ifndef LLVM_IR_OPTIMIZATIONDIAGNOSTICINFO_H
#define LLVM_IR_OPTIMIZATIONDIAGNOSTICINFO_H
#include "llvm/ADT/Optional.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Pass.h"
namespace llvm {
class BlockFrequencyInfo;
class DebugLoc;
class Function;
class LLVMContext;
class Loop;
class Pass;
class Twine;
class Value;
class OptimizationRemarkEmitter {
public:
OptimizationRemarkEmitter(Function *F, BlockFrequencyInfo *BFI)
: F(F), BFI(BFI) {}
OptimizationRemarkEmitter(OptimizationRemarkEmitter &&Arg)
: F(Arg.F), BFI(Arg.BFI) {}
OptimizationRemarkEmitter &operator=(OptimizationRemarkEmitter &&RHS) {
F = RHS.F;
BFI = RHS.BFI;
return *this;
}
/// Emit an optimization-missed message.
///
/// \p PassName is the name of the pass emitting the message. If
/// -Rpass-missed= is given and the name matches the regular expression in
/// -Rpass, then the remark will be emitted. \p Fn is the function triggering
/// the remark, \p DLoc is the debug location where the diagnostic is
/// generated. \p V is the IR Value that identifies the code region. \p Msg is
/// the message string to use.
void emitOptimizationRemarkMissed(const char *PassName, const DebugLoc &DLoc,
Value *V, const Twine &Msg);
/// \brief Same as above but derives the IR Value for the code region and the
/// debug location from the Loop parameter \p L.
void emitOptimizationRemarkMissed(const char *PassName, Loop *L,
const Twine &Msg);
private:
Function *F;
BlockFrequencyInfo *BFI;
Optional<uint64_t> computeHotness(Value *V);
OptimizationRemarkEmitter(const OptimizationRemarkEmitter &) = delete;
void operator=(const OptimizationRemarkEmitter &) = delete;
};
class OptimizationRemarkEmitterWrapperPass : public FunctionPass {
std::unique_ptr<OptimizationRemarkEmitter> ORE;
public:
OptimizationRemarkEmitterWrapperPass();
bool runOnFunction(Function &F) override;
void getAnalysisUsage(AnalysisUsage &AU) const override;
OptimizationRemarkEmitter &getORE() {
assert(ORE && "pass not run yet");
return *ORE;
}
static char ID;
};
class OptimizationRemarkEmitterAnalysis
: public AnalysisInfoMixin<OptimizationRemarkEmitterAnalysis> {
friend AnalysisInfoMixin<OptimizationRemarkEmitterAnalysis>;
static char PassID;
public:
/// \brief Provide the result typedef for this analysis pass.
typedef OptimizationRemarkEmitter Result;
/// \brief Run the analysis pass over a function and produce BFI.
Result run(Function &F, AnalysisManager<Function> &AM);
};
}
#endif // LLVM_IR_OPTIMIZATIONDIAGNOSTICINFO_H

View File

@ -23,13 +23,6 @@ namespace llvm {
class Pass;
class PassInfo;
//===--------------------------------------------------------------------===//
//
// createAAEvalPass - This pass implements a simple N^2 alias analysis
// accuracy evaluator.
//
FunctionPass *createAAEvalPass();
//===--------------------------------------------------------------------===//
//
// createObjCARCAAWrapperPass - This pass implements ObjC-ARC-based
@ -47,10 +40,10 @@ namespace llvm {
//===--------------------------------------------------------------------===//
//
// createDependenceAnalysisPass - This creates an instance of the
// DependenceAnalysis pass.
// createDependenceAnalysisWrapperPass - This creates an instance of the
// DependenceAnalysisWrapper pass.
//
FunctionPass *createDependenceAnalysisPass();
FunctionPass *createDependenceAnalysisWrapperPass();
//===--------------------------------------------------------------------===//
//

View File

@ -15,22 +15,62 @@
#define LLVM_ANALYSIS_POSTDOMINATORS_H
#include "llvm/IR/Dominators.h"
#include "llvm/IR/PassManager.h"
namespace llvm {
/// PostDominatorTree Class - Concrete subclass of DominatorTree that is used to
/// compute the post-dominator tree.
///
struct PostDominatorTree : public FunctionPass {
static char ID; // Pass identification, replacement for typeid
DominatorTreeBase<BasicBlock>* DT;
struct PostDominatorTree : public DominatorTreeBase<BasicBlock> {
typedef DominatorTreeBase<BasicBlock> Base;
PostDominatorTree() : FunctionPass(ID) {
initializePostDominatorTreePass(*PassRegistry::getPassRegistry());
DT = new DominatorTreeBase<BasicBlock>(true);
PostDominatorTree() : DominatorTreeBase<BasicBlock>(true) {}
PostDominatorTree(PostDominatorTree &&Arg)
: Base(std::move(static_cast<Base &>(Arg))) {}
PostDominatorTree &operator=(PostDominatorTree &&RHS) {
Base::operator=(std::move(static_cast<Base &>(RHS)));
return *this;
}
};
/// \brief Analysis pass which computes a \c PostDominatorTree.
class PostDominatorTreeAnalysis
: public AnalysisInfoMixin<PostDominatorTreeAnalysis> {
friend AnalysisInfoMixin<PostDominatorTreeAnalysis>;
static char PassID;
public:
/// \brief Provide the result typedef for this analysis pass.
typedef PostDominatorTree Result;
/// \brief Run the analysis pass over a function and produce a post dominator
/// tree.
PostDominatorTree run(Function &F, FunctionAnalysisManager &);
};
/// \brief Printer pass for the \c PostDominatorTree.
class PostDominatorTreePrinterPass
: public PassInfoMixin<PostDominatorTreePrinterPass> {
raw_ostream &OS;
public:
explicit PostDominatorTreePrinterPass(raw_ostream &OS);
PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
};
struct PostDominatorTreeWrapperPass : public FunctionPass {
static char ID; // Pass identification, replacement for typeid
PostDominatorTree DT;
PostDominatorTreeWrapperPass() : FunctionPass(ID) {
initializePostDominatorTreeWrapperPassPass(*PassRegistry::getPassRegistry());
}
~PostDominatorTree() override;
PostDominatorTree &getPostDomTree() { return DT; }
const PostDominatorTree &getPostDomTree() const { return DT; }
bool runOnFunction(Function &F) override;
@ -38,55 +78,8 @@ struct PostDominatorTree : public FunctionPass {
AU.setPreservesAll();
}
inline const std::vector<BasicBlock*> &getRoots() const {
return DT->getRoots();
}
inline DomTreeNode *getRootNode() const {
return DT->getRootNode();
}
inline DomTreeNode *operator[](BasicBlock *BB) const {
return DT->getNode(BB);
}
inline DomTreeNode *getNode(BasicBlock *BB) const {
return DT->getNode(BB);
}
inline bool dominates(DomTreeNode* A, DomTreeNode* B) const {
return DT->dominates(A, B);
}
inline bool dominates(const BasicBlock* A, const BasicBlock* B) const {
return DT->dominates(A, B);
}
inline bool properlyDominates(const DomTreeNode* A, DomTreeNode* B) const {
return DT->properlyDominates(A, B);
}
inline bool properlyDominates(BasicBlock* A, BasicBlock* B) const {
return DT->properlyDominates(A, B);
}
inline BasicBlock *findNearestCommonDominator(BasicBlock *A, BasicBlock *B) {
return DT->findNearestCommonDominator(A, B);
}
inline const BasicBlock *findNearestCommonDominator(const BasicBlock *A,
const BasicBlock *B) {
return DT->findNearestCommonDominator(A, B);
}
/// Get all nodes post-dominated by R, including R itself.
void getDescendants(BasicBlock *R,
SmallVectorImpl<BasicBlock *> &Result) const {
DT->getDescendants(R, Result);
}
void releaseMemory() override {
DT->releaseMemory();
DT.releaseMemory();
}
void print(raw_ostream &OS, const Module*) const override;

View File

@ -0,0 +1,113 @@
//===- llvm/Analysis/ProfileSummaryInfo.h - profile summary ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a pass that provides access to profile summary
// information.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_PROFILE_SUMMARY_INFO_H
#define LLVM_ANALYSIS_PROFILE_SUMMARY_INFO_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/ProfileSummary.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Pass.h"
#include <memory>
namespace llvm {
class ProfileSummary;
/// \brief Analysis providing profile information.
///
/// This is an immutable analysis pass that provides ability to query global
/// (program-level) profile information. The main APIs are isHotCount and
/// isColdCount that tells whether a given profile count is considered hot/cold
/// based on the profile summary. This also provides convenience methods to
/// check whether a function is hot or cold.
// FIXME: Provide convenience methods to determine hotness/coldness of other IR
// units. This would require making this depend on BFI.
class ProfileSummaryInfo {
private:
Module &M;
std::unique_ptr<ProfileSummary> Summary;
void computeSummary();
void computeThresholds();
// Count thresholds to answer isHotCount and isColdCount queries.
Optional<uint64_t> HotCountThreshold, ColdCountThreshold;
public:
ProfileSummaryInfo(Module &M) : M(M) {}
ProfileSummaryInfo(ProfileSummaryInfo &&Arg)
: M(Arg.M), Summary(std::move(Arg.Summary)) {}
/// \brief Returns true if \p F is a hot function.
bool isHotFunction(const Function *F);
/// \brief Returns true if \p F is a cold function.
bool isColdFunction(const Function *F);
/// \brief Returns true if count \p C is considered hot.
bool isHotCount(uint64_t C);
/// \brief Returns true if count \p C is considered cold.
bool isColdCount(uint64_t C);
};
/// An analysis pass based on legacy pass manager to deliver ProfileSummaryInfo.
class ProfileSummaryInfoWrapperPass : public ImmutablePass {
std::unique_ptr<ProfileSummaryInfo> PSI;
public:
static char ID;
ProfileSummaryInfoWrapperPass();
ProfileSummaryInfo *getPSI(Module &M);
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
}
};
/// An analysis pass based on the new PM to deliver ProfileSummaryInfo.
class ProfileSummaryAnalysis
: public AnalysisInfoMixin<ProfileSummaryAnalysis> {
public:
typedef ProfileSummaryInfo Result;
ProfileSummaryAnalysis() {}
ProfileSummaryAnalysis(const ProfileSummaryAnalysis &Arg) {}
ProfileSummaryAnalysis(ProfileSummaryAnalysis &&Arg) {}
ProfileSummaryAnalysis &operator=(const ProfileSummaryAnalysis &RHS) {
return *this;
}
ProfileSummaryAnalysis &operator=(ProfileSummaryAnalysis &&RHS) {
return *this;
}
Result run(Module &M, ModuleAnalysisManager &);
private:
friend AnalysisInfoMixin<ProfileSummaryAnalysis>;
static char PassID;
};
/// \brief Printer pass that uses \c ProfileSummaryAnalysis.
class ProfileSummaryPrinterPass
: public PassInfoMixin<ProfileSummaryPrinterPass> {
raw_ostream &OS;
public:
explicit ProfileSummaryPrinterPass(raw_ostream &OS) : OS(OS) {}
PreservedAnalyses run(Module &M, AnalysisManager<Module> &AM);
};
} // end namespace llvm
#endif

View File

@ -41,6 +41,7 @@
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/PassManager.h"
#include <map>
#include <memory>
#include <set>
@ -676,6 +677,22 @@ class RegionInfoBase {
RegionInfoBase(const RegionInfoBase &) = delete;
const RegionInfoBase &operator=(const RegionInfoBase &) = delete;
RegionInfoBase(RegionInfoBase &&Arg)
: DT(std::move(Arg.DT)), PDT(std::move(Arg.PDT)), DF(std::move(Arg.DF)),
TopLevelRegion(std::move(Arg.TopLevelRegion)),
BBtoRegion(std::move(Arg.BBtoRegion)) {
Arg.wipe();
}
RegionInfoBase &operator=(RegionInfoBase &&RHS) {
DT = std::move(RHS.DT);
PDT = std::move(RHS.PDT);
DF = std::move(RHS.DF);
TopLevelRegion = std::move(RHS.TopLevelRegion);
BBtoRegion = std::move(RHS.BBtoRegion);
RHS.wipe();
return *this;
}
DomTreeT *DT;
PostDomTreeT *PDT;
DomFrontierT *DF;
@ -687,6 +704,18 @@ private:
/// Map every BB to the smallest region, that contains BB.
BBtoRegionMap BBtoRegion;
/// \brief Wipe this region tree's state without releasing any resources.
///
/// This is essentially a post-move helper only. It leaves the object in an
/// assignable and destroyable state, but otherwise invalid.
void wipe() {
DT = nullptr;
PDT = nullptr;
DF = nullptr;
TopLevelRegion = nullptr;
BBtoRegion.clear();
}
// Check whether the entries of BBtoRegion for the BBs of region
// SR are correct. Triggers an assertion if not. Calls itself recursively for
// subregions.
@ -836,10 +865,19 @@ public:
class RegionInfo : public RegionInfoBase<RegionTraits<Function>> {
public:
typedef RegionInfoBase<RegionTraits<Function>> Base;
explicit RegionInfo();
~RegionInfo() override;
RegionInfo(RegionInfo &&Arg)
: Base(std::move(static_cast<Base &>(Arg))) {}
RegionInfo &operator=(RegionInfo &&RHS) {
Base::operator=(std::move(static_cast<Base &>(RHS)));
return *this;
}
// updateStatistics - Update statistic about created regions.
void updateStatistics(Region *R) final;
@ -884,6 +922,31 @@ public:
//@}
};
/// \brief Analysis pass that exposes the \c RegionInfo for a function.
class RegionInfoAnalysis : public AnalysisInfoMixin<RegionInfoAnalysis> {
friend AnalysisInfoMixin<RegionInfoAnalysis>;
static char PassID;
public:
typedef RegionInfo Result;
RegionInfo run(Function &F, AnalysisManager<Function> &AM);
};
/// \brief Printer pass for the \c RegionInfo.
class RegionInfoPrinterPass : public PassInfoMixin<RegionInfoPrinterPass> {
raw_ostream &OS;
public:
explicit RegionInfoPrinterPass(raw_ostream &OS);
PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
};
/// \brief Verifier pass for the \c RegionInfo.
struct RegionInfoVerifierPass : PassInfoMixin<RegionInfoVerifierPass> {
PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
};
template <>
template <>
inline BasicBlock *

View File

@ -18,7 +18,6 @@
#include "llvm/Analysis/PostDominators.h"
#include "llvm/Analysis/RegionInfo.h"
#include "llvm/Analysis/RegionIterator.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
@ -666,7 +665,7 @@ typename Tr::RegionT *RegionInfoBase<Tr>::createRegion(BlockT *entry,
new RegionT(entry, exit, static_cast<RegionInfoT *>(this), DT);
BBtoRegion.insert(std::make_pair(entry, region));
#ifdef XDEBUG
#ifdef EXPENSIVE_CHECKS
region->verifyRegion();
#else
DEBUG(region->verifyRegion());
@ -765,7 +764,7 @@ void RegionInfoBase<Tr>::buildRegionsTree(DomTreeNodeT *N, RegionT *region) {
}
}
#ifdef XDEBUG
#ifdef EXPENSIVE_CHECKS
template <class Tr>
bool RegionInfoBase<Tr>::VerifyRegionInfo = true;
#else
@ -799,7 +798,7 @@ void RegionInfoBase<Tr>::releaseMemory() {
template <class Tr>
void RegionInfoBase<Tr>::verifyAnalysis() const {
// Do only verify regions if explicitely activated using XDEBUG or
// Do only verify regions if explicitely activated using EXPENSIVE_CHECKS or
// -verify-region-info
if (!RegionInfoBase<Tr>::VerifyRegionInfo)
return;

View File

@ -23,17 +23,17 @@
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/IR/ValueMap.h"
#include "llvm/Pass.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/DataTypes.h"
#include <map>
namespace llvm {
class APInt;
@ -53,6 +53,7 @@ namespace llvm {
class SCEVExpander;
class SCEVPredicate;
class SCEVUnknown;
class Function;
template <> struct FoldingSetTrait<SCEV>;
template <> struct FoldingSetTrait<SCEVPredicate>;
@ -168,8 +169,8 @@ namespace llvm {
static bool classof(const SCEV *S);
};
/// SCEVPredicate - This class represents an assumption made using SCEV
/// expressions which can be checked at run-time.
/// This class represents an assumption made using SCEV expressions which can
/// be checked at run-time.
class SCEVPredicate : public FoldingSetNode {
friend struct FoldingSetTrait<SCEVPredicate>;
@ -178,7 +179,7 @@ namespace llvm {
FoldingSetNodeIDRef FastID;
public:
enum SCEVPredicateKind { P_Union, P_Equal };
enum SCEVPredicateKind { P_Union, P_Equal, P_Wrap };
protected:
SCEVPredicateKind Kind;
@ -191,23 +192,23 @@ namespace llvm {
SCEVPredicateKind getKind() const { return Kind; }
/// \brief Returns the estimated complexity of this predicate.
/// This is roughly measured in the number of run-time checks required.
/// Returns the estimated complexity of this predicate. This is roughly
/// measured in the number of run-time checks required.
virtual unsigned getComplexity() const { return 1; }
/// \brief Returns true if the predicate is always true. This means that no
/// Returns true if the predicate is always true. This means that no
/// assumptions were made and nothing needs to be checked at run-time.
virtual bool isAlwaysTrue() const = 0;
/// \brief Returns true if this predicate implies \p N.
/// Returns true if this predicate implies \p N.
virtual bool implies(const SCEVPredicate *N) const = 0;
/// \brief Prints a textual representation of this predicate with an
/// indentation of \p Depth.
/// Prints a textual representation of this predicate with an indentation of
/// \p Depth.
virtual void print(raw_ostream &OS, unsigned Depth = 0) const = 0;
/// \brief Returns the SCEV to which this predicate applies, or nullptr
/// if this is a SCEVUnionPredicate.
/// Returns the SCEV to which this predicate applies, or nullptr if this is
/// a SCEVUnionPredicate.
virtual const SCEV *getExpr() const = 0;
};
@ -236,10 +237,9 @@ namespace llvm {
}
};
/// SCEVEqualPredicate - This class represents an assumption that two SCEV
/// expressions are equal, and this can be checked at run-time. We assume
/// that the left hand side is a SCEVUnknown and the right hand side a
/// constant.
/// This class represents an assumption that two SCEV expressions are equal,
/// and this can be checked at run-time. We assume that the left hand side is
/// a SCEVUnknown and the right hand side a constant.
class SCEVEqualPredicate final : public SCEVPredicate {
/// We assume that LHS == RHS, where LHS is a SCEVUnknown and RHS a
/// constant.
@ -256,10 +256,10 @@ namespace llvm {
bool isAlwaysTrue() const override;
const SCEV *getExpr() const override;
/// \brief Returns the left hand side of the equality.
/// Returns the left hand side of the equality.
const SCEVUnknown *getLHS() const { return LHS; }
/// \brief Returns the right hand side of the equality.
/// Returns the right hand side of the equality.
const SCEVConstant *getRHS() const { return RHS; }
/// Methods for support type inquiry through isa, cast, and dyn_cast:
@ -268,9 +268,107 @@ namespace llvm {
}
};
/// SCEVUnionPredicate - This class represents a composition of other
/// SCEV predicates, and is the class that most clients will interact with.
/// This is equivalent to a logical "AND" of all the predicates in the union.
/// This class represents an assumption made on an AddRec expression. Given an
/// affine AddRec expression {a,+,b}, we assume that it has the nssw or nusw
/// flags (defined below) in the first X iterations of the loop, where X is a
/// SCEV expression returned by getPredicatedBackedgeTakenCount).
///
/// Note that this does not imply that X is equal to the backedge taken
/// count. This means that if we have a nusw predicate for i32 {0,+,1} with a
/// predicated backedge taken count of X, we only guarantee that {0,+,1} has
/// nusw in the first X iterations. {0,+,1} may still wrap in the loop if we
/// have more than X iterations.
class SCEVWrapPredicate final : public SCEVPredicate {
public:
/// Similar to SCEV::NoWrapFlags, but with slightly different semantics
/// for FlagNUSW. The increment is considered to be signed, and a + b
/// (where b is the increment) is considered to wrap if:
/// zext(a + b) != zext(a) + sext(b)
///
/// If Signed is a function that takes an n-bit tuple and maps to the
/// integer domain as the tuples value interpreted as twos complement,
/// and Unsigned a function that takes an n-bit tuple and maps to the
/// integer domain as as the base two value of input tuple, then a + b
/// has IncrementNUSW iff:
///
/// 0 <= Unsigned(a) + Signed(b) < 2^n
///
/// The IncrementNSSW flag has identical semantics with SCEV::FlagNSW.
///
/// Note that the IncrementNUSW flag is not commutative: if base + inc
/// has IncrementNUSW, then inc + base doesn't neccessarily have this
/// property. The reason for this is that this is used for sign/zero
/// extending affine AddRec SCEV expressions when a SCEVWrapPredicate is
/// assumed. A {base,+,inc} expression is already non-commutative with
/// regards to base and inc, since it is interpreted as:
/// (((base + inc) + inc) + inc) ...
enum IncrementWrapFlags {
IncrementAnyWrap = 0, // No guarantee.
IncrementNUSW = (1 << 0), // No unsigned with signed increment wrap.
IncrementNSSW = (1 << 1), // No signed with signed increment wrap
// (equivalent with SCEV::NSW)
IncrementNoWrapMask = (1 << 2) - 1
};
/// Convenient IncrementWrapFlags manipulation methods.
static SCEVWrapPredicate::IncrementWrapFlags LLVM_ATTRIBUTE_UNUSED_RESULT
clearFlags(SCEVWrapPredicate::IncrementWrapFlags Flags,
SCEVWrapPredicate::IncrementWrapFlags OffFlags) {
assert((Flags & IncrementNoWrapMask) == Flags && "Invalid flags value!");
assert((OffFlags & IncrementNoWrapMask) == OffFlags &&
"Invalid flags value!");
return (SCEVWrapPredicate::IncrementWrapFlags)(Flags & ~OffFlags);
}
static SCEVWrapPredicate::IncrementWrapFlags LLVM_ATTRIBUTE_UNUSED_RESULT
maskFlags(SCEVWrapPredicate::IncrementWrapFlags Flags, int Mask) {
assert((Flags & IncrementNoWrapMask) == Flags && "Invalid flags value!");
assert((Mask & IncrementNoWrapMask) == Mask && "Invalid mask value!");
return (SCEVWrapPredicate::IncrementWrapFlags)(Flags & Mask);
}
static SCEVWrapPredicate::IncrementWrapFlags LLVM_ATTRIBUTE_UNUSED_RESULT
setFlags(SCEVWrapPredicate::IncrementWrapFlags Flags,
SCEVWrapPredicate::IncrementWrapFlags OnFlags) {
assert((Flags & IncrementNoWrapMask) == Flags && "Invalid flags value!");
assert((OnFlags & IncrementNoWrapMask) == OnFlags &&
"Invalid flags value!");
return (SCEVWrapPredicate::IncrementWrapFlags)(Flags | OnFlags);
}
/// Returns the set of SCEVWrapPredicate no wrap flags implied by a
/// SCEVAddRecExpr.
static SCEVWrapPredicate::IncrementWrapFlags
getImpliedFlags(const SCEVAddRecExpr *AR, ScalarEvolution &SE);
private:
const SCEVAddRecExpr *AR;
IncrementWrapFlags Flags;
public:
explicit SCEVWrapPredicate(const FoldingSetNodeIDRef ID,
const SCEVAddRecExpr *AR,
IncrementWrapFlags Flags);
/// Returns the set assumed no overflow flags.
IncrementWrapFlags getFlags() const { return Flags; }
/// Implementation of the SCEVPredicate interface
const SCEV *getExpr() const override;
bool implies(const SCEVPredicate *N) const override;
void print(raw_ostream &OS, unsigned Depth = 0) const override;
bool isAlwaysTrue() const override;
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVPredicate *P) {
return P->getKind() == P_Wrap;
}
};
/// This class represents a composition of other SCEV predicates, and is the
/// class that most clients will interact with. This is equivalent to a
/// logical "AND" of all the predicates in the union.
class SCEVUnionPredicate final : public SCEVPredicate {
private:
typedef DenseMap<const SCEV *, SmallVector<const SCEVPredicate *, 4>>
@ -288,11 +386,11 @@ namespace llvm {
return Preds;
}
/// \brief Adds a predicate to this union.
/// Adds a predicate to this union.
void add(const SCEVPredicate *N);
/// \brief Returns a reference to a vector containing all predicates
/// which apply to \p Expr.
/// Returns a reference to a vector containing all predicates which apply to
/// \p Expr.
ArrayRef<const SCEVPredicate *> getPredicatesForExpr(const SCEV *Expr);
/// Implementation of the SCEVPredicate interface
@ -301,8 +399,8 @@ namespace llvm {
void print(raw_ostream &OS, unsigned Depth) const override;
const SCEV *getExpr() const override;
/// \brief We estimate the complexity of a union predicate as the size
/// number of predicates in the union.
/// We estimate the complexity of a union predicate as the size number of
/// predicates in the union.
unsigned getComplexity() const override { return Preds.size(); }
/// Methods for support type inquiry through isa, cast, and dyn_cast:
@ -364,6 +462,12 @@ namespace llvm {
///
Function &F;
/// Does the module have any calls to the llvm.experimental.guard intrinsic
/// at all? If this is false, we avoid doing work that will only help if
/// thare are guards present in the IR.
///
bool HasGuards;
/// The target library information for the target we are targeting.
///
TargetLibraryInfo &TLI;
@ -382,6 +486,21 @@ namespace llvm {
/// This SCEV is used to represent unknown trip counts and things.
std::unique_ptr<SCEVCouldNotCompute> CouldNotCompute;
/// The typedef for HasRecMap.
///
typedef DenseMap<const SCEV *, bool> HasRecMapType;
/// This is a cache to record whether a SCEV contains any scAddRecExpr.
HasRecMapType HasRecMap;
/// The typedef for ExprValueMap.
///
typedef DenseMap<const SCEV *, SetVector<Value *>> ExprValueMapType;
/// ExprValueMap -- This map records the original values from which
/// the SCEV expr is generated from.
ExprValueMapType ExprValueMap;
/// The typedef for ValueExprMap.
///
typedef DenseMap<SCEVCallbackVH, const SCEV *, DenseMapInfo<Value *> >
@ -410,9 +529,14 @@ namespace llvm {
const SCEV *Exact;
const SCEV *Max;
/// A predicate union guard for this ExitLimit. The result is only
/// valid if this predicate evaluates to 'true' at run-time.
SCEVUnionPredicate Pred;
/*implicit*/ ExitLimit(const SCEV *E) : Exact(E), Max(E) {}
ExitLimit(const SCEV *E, const SCEV *M) : Exact(E), Max(M) {
ExitLimit(const SCEV *E, const SCEV *M, SCEVUnionPredicate &P)
: Exact(E), Max(M), Pred(P) {
assert((isa<SCEVCouldNotCompute>(Exact) ||
!isa<SCEVCouldNotCompute>(Max)) &&
"Exact is not allowed to be less precise than Max");
@ -424,30 +548,147 @@ namespace llvm {
return !isa<SCEVCouldNotCompute>(Exact) ||
!isa<SCEVCouldNotCompute>(Max);
}
/// Test whether this ExitLimit contains all information.
bool hasFullInfo() const { return !isa<SCEVCouldNotCompute>(Exact); }
};
/// Forward declaration of ExitNotTakenExtras
struct ExitNotTakenExtras;
/// Information about the number of times a particular loop exit may be
/// reached before exiting the loop.
struct ExitNotTakenInfo {
AssertingVH<BasicBlock> ExitingBlock;
const SCEV *ExactNotTaken;
PointerIntPair<ExitNotTakenInfo*, 1> NextExit;
ExitNotTakenInfo() : ExitingBlock(nullptr), ExactNotTaken(nullptr) {}
ExitNotTakenExtras *ExtraInfo;
bool Complete;
ExitNotTakenInfo()
: ExitingBlock(nullptr), ExactNotTaken(nullptr), ExtraInfo(nullptr),
Complete(true) {}
ExitNotTakenInfo(BasicBlock *ExitBlock, const SCEV *Expr,
ExitNotTakenExtras *Ptr)
: ExitingBlock(ExitBlock), ExactNotTaken(Expr), ExtraInfo(Ptr),
Complete(true) {}
/// Return true if all loop exits are computable.
bool isCompleteList() const {
return NextExit.getInt() == 0;
bool isCompleteList() const { return Complete; }
/// Sets the incomplete property, indicating that one of the loop exits
/// doesn't have a corresponding ExitNotTakenInfo entry.
void setIncomplete() { Complete = false; }
/// Returns a pointer to the predicate associated with this information,
/// or nullptr if this doesn't exist (meaning always true).
SCEVUnionPredicate *getPred() const {
if (ExtraInfo)
return &ExtraInfo->Pred;
return nullptr;
}
void setIncomplete() { NextExit.setInt(1); }
/// Return a pointer to the next exit's not-taken info.
ExitNotTakenInfo *getNextExit() const {
return NextExit.getPointer();
/// Return true if the SCEV predicate associated with this information
/// is always true.
bool hasAlwaysTruePred() const {
return !getPred() || getPred()->isAlwaysTrue();
}
void setNextExit(ExitNotTakenInfo *ENT) { NextExit.setPointer(ENT); }
/// Defines a simple forward iterator for ExitNotTakenInfo.
class ExitNotTakenInfoIterator
: public std::iterator<std::forward_iterator_tag, ExitNotTakenInfo> {
const ExitNotTakenInfo *Start;
unsigned Position;
public:
ExitNotTakenInfoIterator(const ExitNotTakenInfo *Start,
unsigned Position)
: Start(Start), Position(Position) {}
const ExitNotTakenInfo &operator*() const {
if (Position == 0)
return *Start;
return Start->ExtraInfo->Exits[Position - 1];
}
const ExitNotTakenInfo *operator->() const {
if (Position == 0)
return Start;
return &Start->ExtraInfo->Exits[Position - 1];
}
bool operator==(const ExitNotTakenInfoIterator &RHS) const {
return Start == RHS.Start && Position == RHS.Position;
}
bool operator!=(const ExitNotTakenInfoIterator &RHS) const {
return Start != RHS.Start || Position != RHS.Position;
}
ExitNotTakenInfoIterator &operator++() { // Preincrement
if (!Start)
return *this;
unsigned Elements =
Start->ExtraInfo ? Start->ExtraInfo->Exits.size() + 1 : 1;
++Position;
// We've run out of elements.
if (Position == Elements) {
Start = nullptr;
Position = 0;
}
return *this;
}
ExitNotTakenInfoIterator operator++(int) { // Postincrement
ExitNotTakenInfoIterator Tmp = *this;
++*this;
return Tmp;
}
};
/// Iterators
ExitNotTakenInfoIterator begin() const {
return ExitNotTakenInfoIterator(this, 0);
}
ExitNotTakenInfoIterator end() const {
return ExitNotTakenInfoIterator(nullptr, 0);
}
};
/// Describes the extra information that a ExitNotTakenInfo can have.
struct ExitNotTakenExtras {
/// The predicate associated with the ExitNotTakenInfo struct.
SCEVUnionPredicate Pred;
/// The extra exits in the loop. Only the ExitNotTakenExtras structure
/// pointed to by the first ExitNotTakenInfo struct (associated with the
/// first loop exit) will populate this vector to prevent having
/// redundant information.
SmallVector<ExitNotTakenInfo, 4> Exits;
};
/// A struct containing the information attached to a backedge.
struct EdgeInfo {
EdgeInfo(BasicBlock *Block, const SCEV *Taken, SCEVUnionPredicate &P) :
ExitBlock(Block), Taken(Taken), Pred(std::move(P)) {}
/// The exit basic block.
BasicBlock *ExitBlock;
/// The (exact) number of time we take the edge back.
const SCEV *Taken;
/// The SCEV predicated associated with Taken. If Pred doesn't evaluate
/// to true, the information in Taken is not valid (or equivalent with
/// a CouldNotCompute.
SCEVUnionPredicate Pred;
};
/// Information about the backedge-taken count of a loop. This currently
@ -459,16 +700,16 @@ namespace llvm {
ExitNotTakenInfo ExitNotTaken;
/// An expression indicating the least maximum backedge-taken count of the
/// loop that is known, or a SCEVCouldNotCompute.
/// loop that is known, or a SCEVCouldNotCompute. This expression is only
/// valid if the predicates associated with all loop exits are true.
const SCEV *Max;
public:
BackedgeTakenInfo() : Max(nullptr) {}
/// Initialize BackedgeTakenInfo from a list of exact exit counts.
BackedgeTakenInfo(
SmallVectorImpl< std::pair<BasicBlock *, const SCEV *> > &ExitCounts,
bool Complete, const SCEV *MaxCount);
BackedgeTakenInfo(SmallVectorImpl<EdgeInfo> &ExitCounts, bool Complete,
const SCEV *MaxCount);
/// Test whether this BackedgeTakenInfo contains any computed information,
/// or whether it's all SCEVCouldNotCompute values.
@ -476,11 +717,27 @@ namespace llvm {
return ExitNotTaken.ExitingBlock || !isa<SCEVCouldNotCompute>(Max);
}
/// Test whether this BackedgeTakenInfo contains complete information.
bool hasFullInfo() const { return ExitNotTaken.isCompleteList(); }
/// Return an expression indicating the exact backedge-taken count of the
/// loop if it is known, or SCEVCouldNotCompute otherwise. This is the
/// loop if it is known or SCEVCouldNotCompute otherwise. This is the
/// number of times the loop header can be guaranteed to execute, minus
/// one.
const SCEV *getExact(ScalarEvolution *SE) const;
///
/// If the SCEV predicate associated with the answer can be different
/// from AlwaysTrue, we must add a (non null) Predicates argument.
/// The SCEV predicate associated with the answer will be added to
/// Predicates. A run-time check needs to be emitted for the SCEV
/// predicate in order for the answer to be valid.
///
/// Note that we should always know if we need to pass a predicate
/// argument or not from the way the ExitCounts vector was computed.
/// If we allowed SCEV predicates to be generated when populating this
/// vector, this information can contain them and therefore a
/// SCEVPredicate argument should be added to getExact.
const SCEV *getExact(ScalarEvolution *SE,
SCEVUnionPredicate *Predicates = nullptr) const;
/// Return the number of times this loop exit may fall through to the back
/// edge, or SCEVCouldNotCompute. The loop is guaranteed not to exit via
@ -501,7 +758,11 @@ namespace llvm {
/// Cache the backedge-taken count of the loops for this function as they
/// are computed.
DenseMap<const Loop*, BackedgeTakenInfo> BackedgeTakenCounts;
DenseMap<const Loop *, BackedgeTakenInfo> BackedgeTakenCounts;
/// Cache the predicated backedge-taken count of the loops for this
/// function as they are computed.
DenseMap<const Loop *, BackedgeTakenInfo> PredicatedBackedgeTakenCounts;
/// This map contains entries for all of the PHI instructions that we
/// attempt to compute constant evolutions for. This allows us to avoid
@ -520,6 +781,16 @@ namespace llvm {
SmallVector<PointerIntPair<const Loop *, 2, LoopDisposition>, 2>>
LoopDispositions;
/// Cache for \c loopHasNoAbnormalExits.
DenseMap<const Loop *, bool> LoopHasNoAbnormalExits;
/// Returns true if \p L contains no instruction that can abnormally exit
/// the loop (i.e. via throwing an exception, by terminating the thread
/// cleanly or by infinite looping in a called function). Strictly
/// speaking, the last one is not leaving the loop, but is identical to
/// leaving the loop for reasoning about undefined behavior.
bool loopHasNoAbnormalExits(const Loop *L);
/// Compute a LoopDisposition value.
LoopDisposition computeLoopDisposition(const SCEV *S, const Loop *L);
@ -547,8 +818,7 @@ namespace llvm {
DenseMap<const SCEV *, ConstantRange> &Cache =
Hint == HINT_RANGE_UNSIGNED ? UnsignedRanges : SignedRanges;
std::pair<DenseMap<const SCEV *, ConstantRange>::iterator, bool> Pair =
Cache.insert(std::make_pair(S, CR));
auto Pair = Cache.insert({S, CR});
if (!Pair.second)
Pair.first->second = CR;
return Pair.first->second;
@ -557,6 +827,19 @@ namespace llvm {
/// Determine the range for a particular SCEV.
ConstantRange getRange(const SCEV *S, RangeSignHint Hint);
/// Determines the range for the affine SCEVAddRecExpr {\p Start,+,\p Stop}.
/// Helper for \c getRange.
ConstantRange getRangeForAffineAR(const SCEV *Start, const SCEV *Stop,
const SCEV *MaxBECount,
unsigned BitWidth);
/// Try to compute a range for the affine SCEVAddRecExpr {\p Start,+,\p
/// Stop} by "factoring out" a ternary expression from the add recurrence.
/// Helper called by \c getRange.
ConstantRange getRangeViaFactoring(const SCEV *Start, const SCEV *Stop,
const SCEV *MaxBECount,
unsigned BitWidth);
/// We know that there is no SCEV for the specified value. Analyze the
/// expression.
const SCEV *createSCEV(Value *V);
@ -588,36 +871,59 @@ namespace llvm {
/// This looks up computed SCEV values for all instructions that depend on
/// the given instruction and removes them from the ValueExprMap map if they
/// reference SymName. This is used during PHI resolution.
void ForgetSymbolicName(Instruction *I, const SCEV *SymName);
void forgetSymbolicName(Instruction *I, const SCEV *SymName);
/// Return the BackedgeTakenInfo for the given loop, lazily computing new
/// values if the loop hasn't been analyzed yet.
/// values if the loop hasn't been analyzed yet. The returned result is
/// guaranteed not to be predicated.
const BackedgeTakenInfo &getBackedgeTakenInfo(const Loop *L);
/// Similar to getBackedgeTakenInfo, but will add predicates as required
/// with the purpose of returning complete information.
const BackedgeTakenInfo &getPredicatedBackedgeTakenInfo(const Loop *L);
/// Compute the number of times the specified loop will iterate.
BackedgeTakenInfo computeBackedgeTakenCount(const Loop *L);
/// If AllowPredicates is set, we will create new SCEV predicates as
/// necessary in order to return an exact answer.
BackedgeTakenInfo computeBackedgeTakenCount(const Loop *L,
bool AllowPredicates = false);
/// Compute the number of times the backedge of the specified loop will
/// execute if it exits via the specified block.
ExitLimit computeExitLimit(const Loop *L, BasicBlock *ExitingBlock);
/// execute if it exits via the specified block. If AllowPredicates is set,
/// this call will try to use a minimal set of SCEV predicates in order to
/// return an exact answer.
ExitLimit computeExitLimit(const Loop *L, BasicBlock *ExitingBlock,
bool AllowPredicates = false);
/// Compute the number of times the backedge of the specified loop will
/// execute if its exit condition were a conditional branch of ExitCond,
/// TBB, and FBB.
///
/// \p ControlsExit is true if ExitCond directly controls the exit
/// branch. In this case, we can assume that the loop exits only if the
/// condition is true and can infer that failing to meet the condition prior
/// to integer wraparound results in undefined behavior.
///
/// If \p AllowPredicates is set, this call will try to use a minimal set of
/// SCEV predicates in order to return an exact answer.
ExitLimit computeExitLimitFromCond(const Loop *L,
Value *ExitCond,
BasicBlock *TBB,
BasicBlock *FBB,
bool IsSubExpr);
bool ControlsExit,
bool AllowPredicates = false);
/// Compute the number of times the backedge of the specified loop will
/// execute if its exit condition were a conditional branch of the ICmpInst
/// ExitCond, TBB, and FBB.
/// ExitCond, TBB, and FBB. If AllowPredicates is set, this call will try
/// to use a minimal set of SCEV predicates in order to return an exact
/// answer.
ExitLimit computeExitLimitFromICmp(const Loop *L,
ICmpInst *ExitCond,
BasicBlock *TBB,
BasicBlock *FBB,
bool IsSubExpr);
bool IsSubExpr,
bool AllowPredicates = false);
/// Compute the number of times the backedge of the specified loop will
/// execute if its exit condition were a switch with a single exiting case
@ -655,20 +961,35 @@ namespace llvm {
/// Return the number of times an exit condition comparing the specified
/// value to zero will execute. If not computable, return CouldNotCompute.
ExitLimit HowFarToZero(const SCEV *V, const Loop *L, bool IsSubExpr);
/// If AllowPredicates is set, this call will try to use a minimal set of
/// SCEV predicates in order to return an exact answer.
ExitLimit howFarToZero(const SCEV *V, const Loop *L, bool IsSubExpr,
bool AllowPredicates = false);
/// Return the number of times an exit condition checking the specified
/// value for nonzero will execute. If not computable, return
/// CouldNotCompute.
ExitLimit HowFarToNonZero(const SCEV *V, const Loop *L);
ExitLimit howFarToNonZero(const SCEV *V, const Loop *L);
/// Return the number of times an exit condition containing the specified
/// less-than comparison will execute. If not computable, return
/// CouldNotCompute. isSigned specifies whether the less-than is signed.
ExitLimit HowManyLessThans(const SCEV *LHS, const SCEV *RHS,
const Loop *L, bool isSigned, bool IsSubExpr);
ExitLimit HowManyGreaterThans(const SCEV *LHS, const SCEV *RHS,
const Loop *L, bool isSigned, bool IsSubExpr);
/// CouldNotCompute.
///
/// \p isSigned specifies whether the less-than is signed.
///
/// \p ControlsExit is true when the LHS < RHS condition directly controls
/// the branch (loops exits only if condition is true). In this case, we can
/// use NoWrapFlags to skip overflow checks.
///
/// If \p AllowPredicates is set, this call will try to use a minimal set of
/// SCEV predicates in order to return an exact answer.
ExitLimit howManyLessThans(const SCEV *LHS, const SCEV *RHS, const Loop *L,
bool isSigned, bool ControlsExit,
bool AllowPredicates = false);
ExitLimit howManyGreaterThans(const SCEV *LHS, const SCEV *RHS,
const Loop *L, bool isSigned, bool IsSubExpr,
bool AllowPredicates = false);
/// Return a predecessor of BB (which may not be an immediate predecessor)
/// which has exactly one successor from which BB is reachable, or null if
@ -707,12 +1028,18 @@ namespace llvm {
/// Test whether the condition described by Pred, LHS, and RHS is true
/// whenever the condition described by Pred, FoundLHS, and FoundRHS is
/// true. Utility function used by isImpliedCondOperands.
/// true. Utility function used by isImpliedCondOperands. Tries to get
/// cases like "X `sgt` 0 => X - 1 `sgt` -1".
bool isImpliedCondOperandsViaRanges(ICmpInst::Predicate Pred,
const SCEV *LHS, const SCEV *RHS,
const SCEV *FoundLHS,
const SCEV *FoundRHS);
/// Return true if the condition denoted by \p LHS \p Pred \p RHS is implied
/// by a call to \c @llvm.experimental.guard in \p BB.
bool isImpliedViaGuard(BasicBlock *BB, ICmpInst::Predicate Pred,
const SCEV *LHS, const SCEV *RHS);
/// Test whether the condition described by Pred, LHS, and RHS is true
/// whenever the condition described by Pred, FoundLHS, and FoundRHS is
/// true.
@ -733,8 +1060,8 @@ namespace llvm {
/// Test if the given expression is known to satisfy the condition described
/// by Pred and the known constant ranges of LHS and RHS.
///
bool isKnownPredicateWithRanges(ICmpInst::Predicate Pred,
const SCEV *LHS, const SCEV *RHS);
bool isKnownPredicateViaConstantRanges(ICmpInst::Predicate Pred,
const SCEV *LHS, const SCEV *RHS);
/// Try to prove the condition described by "LHS Pred RHS" by ruling out
/// integer overflow.
@ -778,6 +1105,9 @@ namespace llvm {
bool proveNoWrapByVaryingStart(const SCEV *Start, const SCEV *Step,
const Loop *L);
/// Try to prove NSW or NUW on \p AR relying on ConstantRange manipulation.
SCEV::NoWrapFlags proveNoWrapViaConstantRanges(const SCEVAddRecExpr *AR);
bool isMonotonicPredicateImpl(const SCEVAddRecExpr *LHS,
ICmpInst::Predicate Pred, bool &Increasing);
@ -793,11 +1123,35 @@ namespace llvm {
bool isMonotonicPredicate(const SCEVAddRecExpr *LHS,
ICmpInst::Predicate Pred, bool &Increasing);
// Return SCEV no-wrap flags that can be proven based on reasoning
// about how poison produced from no-wrap flags on this value
// (e.g. a nuw add) would trigger undefined behavior on overflow.
/// Return SCEV no-wrap flags that can be proven based on reasoning about
/// how poison produced from no-wrap flags on this value (e.g. a nuw add)
/// would trigger undefined behavior on overflow.
SCEV::NoWrapFlags getNoWrapFlagsFromUB(const Value *V);
/// Return true if the SCEV corresponding to \p I is never poison. Proving
/// this is more complex than proving that just \p I is never poison, since
/// SCEV commons expressions across control flow, and you can have cases
/// like:
///
/// idx0 = a + b;
/// ptr[idx0] = 100;
/// if (<condition>) {
/// idx1 = a +nsw b;
/// ptr[idx1] = 200;
/// }
///
/// where the SCEV expression (+ a b) is guaranteed to not be poison (and
/// hence not sign-overflow) only if "<condition>" is true. Since both
/// `idx0` and `idx1` will be mapped to the same SCEV expression, (+ a b),
/// it is not okay to annotate (+ a b) with <nsw> in the above example.
bool isSCEVExprNeverPoison(const Instruction *I);
/// This is like \c isSCEVExprNeverPoison but it specifically works for
/// instructions that will get mapped to SCEV add recurrences. Return true
/// if \p I will never generate poison under the assumption that \p I is an
/// add recurrence on the loop \p L.
bool isAddRecNeverPoison(const Instruction *I, const Loop *L);
public:
ScalarEvolution(Function &F, TargetLibraryInfo &TLI, AssumptionCache &AC,
DominatorTree &DT, LoopInfo &LI);
@ -821,6 +1175,17 @@ namespace llvm {
/// return true. For pointer types, this is the pointer-sized integer type.
Type *getEffectiveSCEVType(Type *Ty) const;
/// Return true if the SCEV is a scAddRecExpr or it contains
/// scAddRecExpr. The result will be cached in HasRecMap.
///
bool containsAddRecurrence(const SCEV *S);
/// Return the Value set from which the SCEV expr is generated.
SetVector<Value *> *getSCEVValues(const SCEV *S);
/// Erase Value from ValueExprMap and ExprValueMap.
void eraseValueFromMap(Value *V);
/// Return a SCEV expression for the full generality of the specified
/// expression.
const SCEV *getSCEV(Value *V);
@ -867,7 +1232,7 @@ namespace llvm {
SmallVector<const SCEV *, 4> NewOp(Operands.begin(), Operands.end());
return getAddRecExpr(NewOp, L, Flags);
}
/// \brief Returns an expression for a GEP
/// Returns an expression for a GEP
///
/// \p PointeeType The type used as the basis for the pointer arithmetics
/// \p BaseExpr The expression for the pointer operand.
@ -885,10 +1250,10 @@ namespace llvm {
const SCEV *getUnknown(Value *V);
const SCEV *getCouldNotCompute();
/// \brief Return a SCEV for the constant 0 of a specific type.
/// Return a SCEV for the constant 0 of a specific type.
const SCEV *getZero(Type *Ty) { return getConstant(Ty, 0); }
/// \brief Return a SCEV for the constant 1 of a specific type.
/// Return a SCEV for the constant 1 of a specific type.
const SCEV *getOne(Type *Ty) { return getConstant(Ty, 1); }
/// Return an expression for sizeof AllocTy that is type IntTy
@ -981,7 +1346,7 @@ namespace llvm {
bool isLoopBackedgeGuardedByCond(const Loop *L, ICmpInst::Predicate Pred,
const SCEV *LHS, const SCEV *RHS);
/// \brief Returns the maximum trip count of the loop if it is a single-exit
/// Returns the maximum trip count of the loop if it is a single-exit
/// loop and we can compute a small maximum for that loop.
///
/// Implemented in terms of the \c getSmallConstantTripCount overload with
@ -997,7 +1362,7 @@ namespace llvm {
/// prematurely via another branch.
unsigned getSmallConstantTripCount(Loop *L, BasicBlock *ExitingBlock);
/// \brief Returns the largest constant divisor of the trip count of the
/// Returns the largest constant divisor of the trip count of the
/// loop if it is a single-exit loop and we can compute a small maximum for
/// that loop.
///
@ -1031,6 +1396,13 @@ namespace llvm {
///
const SCEV *getBackedgeTakenCount(const Loop *L);
/// Similar to getBackedgeTakenCount, except it will add a set of
/// SCEV predicates to Predicates that are required to be true in order for
/// the answer to be correct. Predicates can be checked with run-time
/// checks and can be used to perform loop versioning.
const SCEV *getPredicatedBackedgeTakenCount(const Loop *L,
SCEVUnionPredicate &Predicates);
/// Similar to getBackedgeTakenCount, except return the least SCEV value
/// that is known never to be less than the actual backedge taken count.
const SCEV *getMaxBackedgeTakenCount(const Loop *L);
@ -1050,7 +1422,7 @@ namespace llvm {
/// def-use chain linking it to a loop.
void forgetValue(Value *V);
/// \brief Called when the client has changed the disposition of values in
/// Called when the client has changed the disposition of values in
/// this loop.
///
/// We don't have a way to invalidate per-loop dispositions. Clear and
@ -1154,7 +1526,8 @@ namespace llvm {
const SCEV *getElementSize(Instruction *Inst);
/// Compute the array dimensions Sizes from the set of Terms extracted from
/// the memory access function of this SCEVAddRecExpr.
/// the memory access function of this SCEVAddRecExpr (second step of
/// delinearization).
void findArrayDimensions(SmallVectorImpl<const SCEV *> &Terms,
SmallVectorImpl<const SCEV *> &Sizes,
const SCEV *ElementSize) const;
@ -1162,13 +1535,15 @@ namespace llvm {
void print(raw_ostream &OS) const;
void verify() const;
/// Collect parametric terms occurring in step expressions.
/// Collect parametric terms occurring in step expressions (first step of
/// delinearization).
void collectParametricTerms(const SCEV *Expr,
SmallVectorImpl<const SCEV *> &Terms);
/// Return in Subscripts the access functions for each dimension in Sizes.
/// Return in Subscripts the access functions for each dimension in Sizes
/// (third step of delinearization).
void computeAccessFunctions(const SCEV *Expr,
SmallVectorImpl<const SCEV *> &Subscripts,
SmallVectorImpl<const SCEV *> &Sizes);
@ -1251,8 +1626,18 @@ namespace llvm {
const SCEVPredicate *getEqualPredicate(const SCEVUnknown *LHS,
const SCEVConstant *RHS);
/// Re-writes the SCEV according to the Predicates in \p Preds.
const SCEV *rewriteUsingPredicate(const SCEV *Scev, SCEVUnionPredicate &A);
const SCEVPredicate *
getWrapPredicate(const SCEVAddRecExpr *AR,
SCEVWrapPredicate::IncrementWrapFlags AddedFlags);
/// Re-writes the SCEV according to the Predicates in \p A.
const SCEV *rewriteUsingPredicate(const SCEV *S, const Loop *L,
SCEVUnionPredicate &A);
/// Tries to convert the \p S expression to an AddRec expression,
/// adding additional predicates to \p Preds as required.
const SCEVAddRecExpr *
convertSCEVToAddRecWithPredicates(const SCEV *S, const Loop *L,
SCEVUnionPredicate &Preds);
private:
/// Compute the backedge taken count knowing the interval difference, the
@ -1283,31 +1668,26 @@ namespace llvm {
SCEVUnknown *FirstUnknown;
};
/// \brief Analysis pass that exposes the \c ScalarEvolution for a function.
class ScalarEvolutionAnalysis {
/// Analysis pass that exposes the \c ScalarEvolution for a function.
class ScalarEvolutionAnalysis
: public AnalysisInfoMixin<ScalarEvolutionAnalysis> {
friend AnalysisInfoMixin<ScalarEvolutionAnalysis>;
static char PassID;
public:
typedef ScalarEvolution Result;
/// \brief Opaque, unique identifier for this analysis pass.
static void *ID() { return (void *)&PassID; }
/// \brief Provide a name for the analysis for debugging and logging.
static StringRef name() { return "ScalarEvolutionAnalysis"; }
ScalarEvolution run(Function &F, AnalysisManager<Function> *AM);
ScalarEvolution run(Function &F, AnalysisManager<Function> &AM);
};
/// \brief Printer pass for the \c ScalarEvolutionAnalysis results.
class ScalarEvolutionPrinterPass {
/// Printer pass for the \c ScalarEvolutionAnalysis results.
class ScalarEvolutionPrinterPass
: public PassInfoMixin<ScalarEvolutionPrinterPass> {
raw_ostream &OS;
public:
explicit ScalarEvolutionPrinterPass(raw_ostream &OS) : OS(OS) {}
PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM);
static StringRef name() { return "ScalarEvolutionPrinterPass"; }
PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
};
class ScalarEvolutionWrapperPass : public FunctionPass {
@ -1343,42 +1723,81 @@ namespace llvm {
/// - lowers the number of expression rewrites.
class PredicatedScalarEvolution {
public:
PredicatedScalarEvolution(ScalarEvolution &SE);
PredicatedScalarEvolution(ScalarEvolution &SE, Loop &L);
const SCEVUnionPredicate &getUnionPredicate() const;
/// \brief Returns the SCEV expression of V, in the context of the current
/// SCEV predicate.
/// The order of transformations applied on the expression of V returned
/// by ScalarEvolution is guaranteed to be preserved, even when adding new
/// predicates.
/// Returns the SCEV expression of V, in the context of the current SCEV
/// predicate. The order of transformations applied on the expression of V
/// returned by ScalarEvolution is guaranteed to be preserved, even when
/// adding new predicates.
const SCEV *getSCEV(Value *V);
/// \brief Adds a new predicate.
/// Get the (predicated) backedge count for the analyzed loop.
const SCEV *getBackedgeTakenCount();
/// Adds a new predicate.
void addPredicate(const SCEVPredicate &Pred);
/// \brief Returns the ScalarEvolution analysis used.
/// Attempts to produce an AddRecExpr for V by adding additional SCEV
/// predicates. If we can't transform the expression into an AddRecExpr we
/// return nullptr and not add additional SCEV predicates to the current
/// context.
const SCEVAddRecExpr *getAsAddRec(Value *V);
/// Proves that V doesn't overflow by adding SCEV predicate.
void setNoOverflow(Value *V, SCEVWrapPredicate::IncrementWrapFlags Flags);
/// Returns true if we've proved that V doesn't wrap by means of a SCEV
/// predicate.
bool hasNoOverflow(Value *V, SCEVWrapPredicate::IncrementWrapFlags Flags);
/// Returns the ScalarEvolution analysis used.
ScalarEvolution *getSE() const { return &SE; }
/// We need to explicitly define the copy constructor because of FlagsMap.
PredicatedScalarEvolution(const PredicatedScalarEvolution&);
/// Print the SCEV mappings done by the Predicated Scalar Evolution.
/// The printed text is indented by \p Depth.
void print(raw_ostream &OS, unsigned Depth) const;
private:
/// \brief Increments the version number of the predicate.
/// This needs to be called every time the SCEV predicate changes.
/// Increments the version number of the predicate. This needs to be called
/// every time the SCEV predicate changes.
void updateGeneration();
/// Holds a SCEV and the version number of the SCEV predicate used to
/// perform the rewrite of the expression.
typedef std::pair<unsigned, const SCEV *> RewriteEntry;
/// Maps a SCEV to the rewrite result of that SCEV at a certain version
/// number. If this number doesn't match the current Generation, we will
/// need to do a rewrite. To preserve the transformation order of previous
/// rewrites, we will rewrite the previous result instead of the original
/// SCEV.
DenseMap<const SCEV *, RewriteEntry> RewriteMap;
/// Records what NoWrap flags we've added to a Value *.
ValueMap<Value *, SCEVWrapPredicate::IncrementWrapFlags> FlagsMap;
/// The ScalarEvolution analysis.
ScalarEvolution &SE;
/// The analyzed Loop.
const Loop &L;
/// The SCEVPredicate that forms our context. We will rewrite all
/// expressions assuming that this predicate true.
SCEVUnionPredicate Preds;
/// Marks the version of the SCEV predicate used. When rewriting a SCEV
/// expression we mark it with the version of the predicate. We use this to
/// figure out if the predicate has changed from the last rewrite of the
/// SCEV. If so, we need to perform a new rewrite.
unsigned Generation;
/// The backedge taken count.
const SCEV *BackedgeCount;
};
}

View File

@ -28,8 +28,7 @@ class SCEVAAResult : public AAResultBase<SCEVAAResult> {
ScalarEvolution &SE;
public:
explicit SCEVAAResult(const TargetLibraryInfo &TLI, ScalarEvolution &SE)
: AAResultBase(TLI), SE(SE) {}
explicit SCEVAAResult(ScalarEvolution &SE) : AAResultBase(), SE(SE) {}
SCEVAAResult(SCEVAAResult &&Arg) : AAResultBase(std::move(Arg)), SE(Arg.SE) {}
AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB);
@ -39,20 +38,14 @@ private:
};
/// Analysis pass providing a never-invalidated alias analysis result.
class SCEVAA {
class SCEVAA : public AnalysisInfoMixin<SCEVAA> {
friend AnalysisInfoMixin<SCEVAA>;
static char PassID;
public:
typedef SCEVAAResult Result;
/// \brief Opaque, unique identifier for this analysis pass.
static void *ID() { return (void *)&PassID; }
SCEVAAResult run(Function &F, AnalysisManager<Function> *AM);
/// \brief Provide access to a name for this pass for debugging purposes.
static StringRef name() { return "SCEVAA"; }
private:
static char PassID;
SCEVAAResult run(Function &F, AnalysisManager<Function> &AM);
};
/// Legacy wrapper pass to provide the SCEVAAResult object.

View File

@ -80,9 +80,49 @@ namespace llvm {
/// already in "expanded" form.
bool LSRMode;
typedef IRBuilder<true, TargetFolder> BuilderType;
typedef IRBuilder<TargetFolder> BuilderType;
BuilderType Builder;
// RAII object that stores the current insertion point and restores it when
// the object is destroyed. This includes the debug location. Duplicated
// from InsertPointGuard to add SetInsertPoint() which is used to updated
// InsertPointGuards stack when insert points are moved during SCEV
// expansion.
class SCEVInsertPointGuard {
IRBuilderBase &Builder;
AssertingVH<BasicBlock> Block;
BasicBlock::iterator Point;
DebugLoc DbgLoc;
SCEVExpander *SE;
SCEVInsertPointGuard(const SCEVInsertPointGuard &) = delete;
SCEVInsertPointGuard &operator=(const SCEVInsertPointGuard &) = delete;
public:
SCEVInsertPointGuard(IRBuilderBase &B, SCEVExpander *SE)
: Builder(B), Block(B.GetInsertBlock()), Point(B.GetInsertPoint()),
DbgLoc(B.getCurrentDebugLocation()), SE(SE) {
SE->InsertPointGuards.push_back(this);
}
~SCEVInsertPointGuard() {
// These guards should always created/destroyed in FIFO order since they
// are used to guard lexically scoped blocks of code in
// ScalarEvolutionExpander.
assert(SE->InsertPointGuards.back() == this);
SE->InsertPointGuards.pop_back();
Builder.restoreIP(IRBuilderBase::InsertPoint(Block, Point));
Builder.SetCurrentDebugLocation(DbgLoc);
}
BasicBlock::iterator GetInsertPoint() const { return Point; }
void SetInsertPoint(BasicBlock::iterator I) { Point = I; }
};
/// Stack of pointers to saved insert points, used to keep insert points
/// consistent when instructions are moved.
SmallVector<SCEVInsertPointGuard *, 8> InsertPointGuards;
#ifndef NDEBUG
const char *DebugType;
#endif
@ -101,6 +141,11 @@ namespace llvm {
#endif
}
~SCEVExpander() {
// Make sure the insert point guard stack is consistent.
assert(InsertPointGuards.empty());
}
#ifndef NDEBUG
void setDebugType(const char* s) { DebugType = s; }
#endif
@ -162,6 +207,15 @@ namespace llvm {
Value *expandEqualPredicate(const SCEVEqualPredicate *Pred,
Instruction *Loc);
/// \brief Generates code that evaluates if the \p AR expression will
/// overflow.
Value *generateOverflowCheck(const SCEVAddRecExpr *AR, Instruction *Loc,
bool Signed);
/// \brief A specialized variant of expandCodeForPredicate, handling the
/// case when we are expanding code for a SCEVWrapPredicate.
Value *expandWrapPredicate(const SCEVWrapPredicate *P, Instruction *Loc);
/// \brief A specialized variant of expandCodeForPredicate, handling the
/// case when we are expanding code for a SCEVUnionPredicate.
Value *expandUnionPredicate(const SCEVUnionPredicate *Pred,
@ -254,6 +308,9 @@ namespace llvm {
const SCEV *const *op_end,
PointerType *PTy, Type *Ty, Value *V);
/// \brief Find a previous Value in ExprValueMap for expand.
Value *FindValueInExprValueMap(const SCEV *S, const Instruction *InsertPt);
Value *expand(const SCEV *S);
/// \brief Insert code to directly compute the specified SCEV expression
@ -306,6 +363,11 @@ namespace llvm {
bool &InvertStep);
Value *expandIVInc(PHINode *PN, Value *StepV, const Loop *L,
Type *ExpandTy, Type *IntTy, bool useSubtract);
void hoistBeforePos(DominatorTree *DT, Instruction *InstToHoist,
Instruction *Pos, PHINode *LoopPhi);
void fixupInsertPoints(Instruction *I);
};
}

View File

@ -32,9 +32,7 @@ namespace llvm {
scUnknown, scCouldNotCompute
};
//===--------------------------------------------------------------------===//
/// SCEVConstant - This class represents a constant integer value.
///
/// This class represents a constant integer value.
class SCEVConstant : public SCEV {
friend class ScalarEvolution;
@ -53,9 +51,7 @@ namespace llvm {
}
};
//===--------------------------------------------------------------------===//
/// SCEVCastExpr - This is the base class for unary cast operator classes.
///
/// This is the base class for unary cast operator classes.
class SCEVCastExpr : public SCEV {
protected:
const SCEV *Op;
@ -76,10 +72,8 @@ namespace llvm {
}
};
//===--------------------------------------------------------------------===//
/// SCEVTruncateExpr - This class represents a truncation of an integer value
/// to a smaller integer value.
///
/// This class represents a truncation of an integer value to a
/// smaller integer value.
class SCEVTruncateExpr : public SCEVCastExpr {
friend class ScalarEvolution;
@ -93,10 +87,8 @@ namespace llvm {
}
};
//===--------------------------------------------------------------------===//
/// SCEVZeroExtendExpr - This class represents a zero extension of a small
/// integer value to a larger integer value.
///
/// This class represents a zero extension of a small integer value
/// to a larger integer value.
class SCEVZeroExtendExpr : public SCEVCastExpr {
friend class ScalarEvolution;
@ -110,10 +102,8 @@ namespace llvm {
}
};
//===--------------------------------------------------------------------===//
/// SCEVSignExtendExpr - This class represents a sign extension of a small
/// integer value to a larger integer value.
///
/// This class represents a sign extension of a small integer value
/// to a larger integer value.
class SCEVSignExtendExpr : public SCEVCastExpr {
friend class ScalarEvolution;
@ -128,10 +118,8 @@ namespace llvm {
};
//===--------------------------------------------------------------------===//
/// SCEVNAryExpr - This node is a base class providing common
/// functionality for n'ary operators.
///
/// This node is a base class providing common functionality for
/// n'ary operators.
class SCEVNAryExpr : public SCEV {
protected:
// Since SCEVs are immutable, ScalarEvolution allocates operand
@ -166,6 +154,18 @@ namespace llvm {
return (NoWrapFlags)(SubclassData & Mask);
}
bool hasNoUnsignedWrap() const {
return getNoWrapFlags(FlagNUW) != FlagAnyWrap;
}
bool hasNoSignedWrap() const {
return getNoWrapFlags(FlagNSW) != FlagAnyWrap;
}
bool hasNoSelfWrap() const {
return getNoWrapFlags(FlagNW) != FlagAnyWrap;
}
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEV *S) {
return S->getSCEVType() == scAddExpr ||
@ -176,10 +176,7 @@ namespace llvm {
}
};
//===--------------------------------------------------------------------===//
/// SCEVCommutativeExpr - This node is the base class for n'ary commutative
/// operators.
///
/// This node is the base class for n'ary commutative operators.
class SCEVCommutativeExpr : public SCEVNAryExpr {
protected:
SCEVCommutativeExpr(const FoldingSetNodeIDRef ID,
@ -202,9 +199,7 @@ namespace llvm {
};
//===--------------------------------------------------------------------===//
/// SCEVAddExpr - This node represents an addition of some number of SCEVs.
///
/// This node represents an addition of some number of SCEVs.
class SCEVAddExpr : public SCEVCommutativeExpr {
friend class ScalarEvolution;
@ -227,9 +222,8 @@ namespace llvm {
}
};
//===--------------------------------------------------------------------===//
/// SCEVMulExpr - This node represents multiplication of some number of SCEVs.
///
/// This node represents multiplication of some number of SCEVs.
class SCEVMulExpr : public SCEVCommutativeExpr {
friend class ScalarEvolution;
@ -246,9 +240,7 @@ namespace llvm {
};
//===--------------------------------------------------------------------===//
/// SCEVUDivExpr - This class represents a binary unsigned division operation.
///
/// This class represents a binary unsigned division operation.
class SCEVUDivExpr : public SCEV {
friend class ScalarEvolution;
@ -277,12 +269,11 @@ namespace llvm {
};
//===--------------------------------------------------------------------===//
/// SCEVAddRecExpr - This node represents a polynomial recurrence on the trip
/// count of the specified loop. This is the primary focus of the
/// ScalarEvolution framework; all the other SCEV subclasses are mostly just
/// supporting infrastructure to allow SCEVAddRecExpr expressions to be
/// created and analyzed.
/// This node represents a polynomial recurrence on the trip count
/// of the specified loop. This is the primary focus of the
/// ScalarEvolution framework; all the other SCEV subclasses are
/// mostly just supporting infrastructure to allow SCEVAddRecExpr
/// expressions to be created and analyzed.
///
/// All operands of an AddRec are required to be loop invariant.
///
@ -299,10 +290,10 @@ namespace llvm {
const SCEV *getStart() const { return Operands[0]; }
const Loop *getLoop() const { return L; }
/// getStepRecurrence - This method constructs and returns the recurrence
/// indicating how much this expression steps by. If this is a polynomial
/// of degree N, it returns a chrec of degree N-1.
/// We cannot determine whether the step recurrence has self-wraparound.
/// Constructs and returns the recurrence indicating how much this
/// expression steps by. If this is a polynomial of degree N, it
/// returns a chrec of degree N-1. We cannot determine whether
/// the step recurrence has self-wraparound.
const SCEV *getStepRecurrence(ScalarEvolution &SE) const {
if (isAffine()) return getOperand(1);
return SE.getAddRecExpr(SmallVector<const SCEV *, 3>(op_begin()+1,
@ -310,17 +301,17 @@ namespace llvm {
getLoop(), FlagAnyWrap);
}
/// isAffine - Return true if this represents an expression
/// A + B*x where A and B are loop invariant values.
/// Return true if this represents an expression A + B*x where A
/// and B are loop invariant values.
bool isAffine() const {
// We know that the start value is invariant. This expression is thus
// affine iff the step is also invariant.
return getNumOperands() == 2;
}
/// isQuadratic - Return true if this represents an expression
/// A + B*x + C*x^2 where A, B and C are loop invariant values.
/// This corresponds to an addrec of the form {L,+,M,+,N}
/// Return true if this represents an expression A + B*x + C*x^2
/// where A, B and C are loop invariant values. This corresponds
/// to an addrec of the form {L,+,M,+,N}
bool isQuadratic() const {
return getNumOperands() == 3;
}
@ -334,21 +325,21 @@ namespace llvm {
SubclassData |= Flags;
}
/// evaluateAtIteration - Return the value of this chain of recurrences at
/// the specified iteration number.
/// Return the value of this chain of recurrences at the specified
/// iteration number.
const SCEV *evaluateAtIteration(const SCEV *It, ScalarEvolution &SE) const;
/// getNumIterationsInRange - Return the number of iterations of this loop
/// that produce values in the specified constant range. Another way of
/// looking at this is that it returns the first iteration number where the
/// value is not in the condition, thus computing the exit count. If the
/// iteration count can't be computed, an instance of SCEVCouldNotCompute is
/// returned.
const SCEV *getNumIterationsInRange(ConstantRange Range,
ScalarEvolution &SE) const;
/// Return the number of iterations of this loop that produce
/// values in the specified constant range. Another way of
/// looking at this is that it returns the first iteration number
/// where the value is not in the condition, thus computing the
/// exit count. If the iteration count can't be computed, an
/// instance of SCEVCouldNotCompute is returned.
const SCEV *getNumIterationsInRange(const ConstantRange &Range,
ScalarEvolution &SE) const;
/// getPostIncExpr - Return an expression representing the value of
/// this expression one iteration of the loop ahead.
/// Return an expression representing the value of this expression
/// one iteration of the loop ahead.
const SCEVAddRecExpr *getPostIncExpr(ScalarEvolution &SE) const {
return cast<SCEVAddRecExpr>(SE.getAddExpr(this, getStepRecurrence(SE)));
}
@ -359,9 +350,7 @@ namespace llvm {
}
};
//===--------------------------------------------------------------------===//
/// SCEVSMaxExpr - This class represents a signed maximum selection.
///
/// This class represents a signed maximum selection.
class SCEVSMaxExpr : public SCEVCommutativeExpr {
friend class ScalarEvolution;
@ -380,9 +369,7 @@ namespace llvm {
};
//===--------------------------------------------------------------------===//
/// SCEVUMaxExpr - This class represents an unsigned maximum selection.
///
/// This class represents an unsigned maximum selection.
class SCEVUMaxExpr : public SCEVCommutativeExpr {
friend class ScalarEvolution;
@ -400,11 +387,9 @@ namespace llvm {
}
};
//===--------------------------------------------------------------------===//
/// SCEVUnknown - This means that we are dealing with an entirely unknown SCEV
/// value, and only represent it as its LLVM Value. This is the "bottom"
/// value for the analysis.
///
/// This means that we are dealing with an entirely unknown SCEV
/// value, and only represent it as its LLVM Value. This is the
/// "bottom" value for the analysis.
class SCEVUnknown final : public SCEV, private CallbackVH {
friend class ScalarEvolution;
@ -412,13 +397,13 @@ namespace llvm {
void deleted() override;
void allUsesReplacedWith(Value *New) override;
/// SE - The parent ScalarEvolution value. This is used to update
/// the parent's maps when the value associated with a SCEVUnknown
/// is deleted or RAUW'd.
/// The parent ScalarEvolution value. This is used to update the
/// parent's maps when the value associated with a SCEVUnknown is
/// deleted or RAUW'd.
ScalarEvolution *SE;
/// Next - The next pointer in the linked list of all
/// SCEVUnknown instances owned by a ScalarEvolution.
/// The next pointer in the linked list of all SCEVUnknown
/// instances owned by a ScalarEvolution.
SCEVUnknown *Next;
SCEVUnknown(const FoldingSetNodeIDRef ID, Value *V,
@ -428,15 +413,17 @@ namespace llvm {
public:
Value *getValue() const { return getValPtr(); }
/// isSizeOf, isAlignOf, isOffsetOf - Test whether this is a special
/// constant representing a type size, alignment, or field offset in
/// a target-independent manner, and hasn't happened to have been
/// folded with other operations into something unrecognizable. This
/// is mainly only useful for pretty-printing and other situations
/// where it isn't absolutely required for these to succeed.
/// @{
/// Test whether this is a special constant representing a type
/// size, alignment, or field offset in a target-independent
/// manner, and hasn't happened to have been folded with other
/// operations into something unrecognizable. This is mainly only
/// useful for pretty-printing and other situations where it isn't
/// absolutely required for these to succeed.
bool isSizeOf(Type *&AllocTy) const;
bool isAlignOf(Type *&AllocTy) const;
bool isOffsetOf(Type *&STy, Constant *&FieldNo) const;
/// @}
Type *getType() const { return getValPtr()->getType(); }
@ -446,8 +433,8 @@ namespace llvm {
}
};
/// SCEVVisitor - This class defines a simple visitor class that may be used
/// for various SCEV analysis purposes.
/// This class defines a simple visitor class that may be used for
/// various SCEV analysis purposes.
template<typename SC, typename RetVal=void>
struct SCEVVisitor {
RetVal visit(const SCEV *S) {
@ -524,14 +511,10 @@ namespace llvm {
case scMulExpr:
case scSMaxExpr:
case scUMaxExpr:
case scAddRecExpr: {
const SCEVNAryExpr *NAry = cast<SCEVNAryExpr>(S);
for (SCEVNAryExpr::op_iterator I = NAry->op_begin(),
E = NAry->op_end(); I != E; ++I) {
push(*I);
}
case scAddRecExpr:
for (const auto *Op : cast<SCEVNAryExpr>(S)->operands())
push(Op);
break;
}
case scUDivExpr: {
const SCEVUDivExpr *UDiv = cast<SCEVUDivExpr>(S);
push(UDiv->getLHS());
@ -697,13 +680,6 @@ namespace llvm {
private:
LoopToScevMapT &Map;
};
/// Applies the Map (Loop -> SCEV) to the given Scev.
static inline const SCEV *apply(const SCEV *Scev, LoopToScevMapT &Map,
ScalarEvolution &SE) {
return SCEVLoopAddRecRewriter::rewrite(Scev, Map, SE);
}
}
#endif

View File

@ -27,8 +27,7 @@ class ScopedNoAliasAAResult : public AAResultBase<ScopedNoAliasAAResult> {
friend AAResultBase<ScopedNoAliasAAResult>;
public:
explicit ScopedNoAliasAAResult(const TargetLibraryInfo &TLI)
: AAResultBase(TLI) {}
explicit ScopedNoAliasAAResult() : AAResultBase() {}
ScopedNoAliasAAResult(ScopedNoAliasAAResult &&Arg)
: AAResultBase(std::move(Arg)) {}
@ -48,20 +47,14 @@ private:
};
/// Analysis pass providing a never-invalidated alias analysis result.
class ScopedNoAliasAA {
class ScopedNoAliasAA : public AnalysisInfoMixin<ScopedNoAliasAA> {
friend AnalysisInfoMixin<ScopedNoAliasAA>;
static char PassID;
public:
typedef ScopedNoAliasAAResult Result;
/// \brief Opaque, unique identifier for this analysis pass.
static void *ID() { return (void *)&PassID; }
ScopedNoAliasAAResult run(Function &F, AnalysisManager<Function> *AM);
/// \brief Provide access to a name for this pass for debugging purposes.
static StringRef name() { return "ScopedNoAliasAA"; }
private:
static char PassID;
ScopedNoAliasAAResult run(Function &F, AnalysisManager<Function> &AM);
};
/// Legacy wrapper pass to provide the ScopedNoAliasAAResult object.

View File

@ -17,6 +17,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/IR/BasicBlock.h"
#include <set>
#include <vector>

View File

@ -195,6 +195,11 @@ TLI_DEFINE_STRING_INTERNAL("__memmove_chk")
/// void *__memset_chk(void *s, char v, size_t n, size_t s1size);
TLI_DEFINE_ENUM_INTERNAL(memset_chk)
TLI_DEFINE_STRING_INTERNAL("__memset_chk")
// int __nvvm_reflect(const char *)
TLI_DEFINE_ENUM_INTERNAL(nvvm_reflect)
TLI_DEFINE_STRING_INTERNAL("__nvvm_reflect")
/// double __sincospi_stret(double x);
TLI_DEFINE_ENUM_INTERNAL(sincospi_stret)
TLI_DEFINE_STRING_INTERNAL("__sincospi_stret")

View File

@ -11,15 +11,17 @@
#define LLVM_ANALYSIS_TARGETLIBRARYINFO_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/Triple.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Pass.h"
namespace llvm {
/// VecDesc - Describes a possible vectorization of a function.
template <typename T> class ArrayRef;
/// Describes a possible vectorization of a function.
/// Function 'VectorFnName' is equivalent to 'ScalarFnName' vectorized
/// by a factor 'VectorizationFactor'.
struct VecDesc {
@ -27,7 +29,6 @@ struct VecDesc {
const char *VectorFnName;
unsigned VectorizationFactor;
};
class PreservedAnalyses;
namespace LibFunc {
enum Func {
@ -38,7 +39,7 @@ class PreservedAnalyses;
};
}
/// \brief Implementation of the target library information.
/// Implementation of the target library information.
///
/// This class constructs tables that hold the target library information and
/// make it available. However, it is somewhat expensive to compute and only
@ -70,8 +71,13 @@ class TargetLibraryInfoImpl {
/// on VectorFnName rather than ScalarFnName.
std::vector<VecDesc> ScalarDescs;
/// Return true if the function type FTy is valid for the library function
/// F, regardless of whether the function is available.
bool isValidProtoForLibFunc(const FunctionType &FTy, LibFunc::Func F,
const DataLayout *DL) const;
public:
/// \brief List of known vector-functions libraries.
/// List of known vector-functions libraries.
///
/// The vector-functions library defines, which functions are vectorizable
/// and with which factor. The library can be specified by either frontend,
@ -92,24 +98,31 @@ public:
TargetLibraryInfoImpl &operator=(const TargetLibraryInfoImpl &TLI);
TargetLibraryInfoImpl &operator=(TargetLibraryInfoImpl &&TLI);
/// \brief Searches for a particular function name.
/// Searches for a particular function name.
///
/// If it is one of the known library functions, return true and set F to the
/// corresponding value.
bool getLibFunc(StringRef funcName, LibFunc::Func &F) const;
/// \brief Forces a function to be marked as unavailable.
/// Searches for a particular function name, also checking that its type is
/// valid for the library function matching that name.
///
/// If it is one of the known library functions, return true and set F to the
/// corresponding value.
bool getLibFunc(const Function &FDecl, LibFunc::Func &F) const;
/// Forces a function to be marked as unavailable.
void setUnavailable(LibFunc::Func F) {
setState(F, Unavailable);
}
/// \brief Forces a function to be marked as available.
/// Forces a function to be marked as available.
void setAvailable(LibFunc::Func F) {
setState(F, StandardName);
}
/// \brief Forces a function to be marked as available and provide an
/// alternate name that must be used.
/// Forces a function to be marked as available and provide an alternate name
/// that must be used.
void setAvailableWithName(LibFunc::Func F, StringRef Name) {
if (StandardNames[F] != Name) {
setState(F, CustomName);
@ -120,48 +133,47 @@ public:
}
}
/// \brief Disables all builtins.
/// Disables all builtins.
///
/// This can be used for options like -fno-builtin.
void disableAllFunctions();
/// addVectorizableFunctions - Add a set of scalar -> vector mappings,
/// queryable via getVectorizedFunction and getScalarizedFunction.
/// Add a set of scalar -> vector mappings, queryable via
/// getVectorizedFunction and getScalarizedFunction.
void addVectorizableFunctions(ArrayRef<VecDesc> Fns);
/// Calls addVectorizableFunctions with a known preset of functions for the
/// given vector library.
void addVectorizableFunctionsFromVecLib(enum VectorLibrary VecLib);
/// isFunctionVectorizable - Return true if the function F has a
/// vector equivalent with vectorization factor VF.
/// Return true if the function F has a vector equivalent with vectorization
/// factor VF.
bool isFunctionVectorizable(StringRef F, unsigned VF) const {
return !getVectorizedFunction(F, VF).empty();
}
/// isFunctionVectorizable - Return true if the function F has a
/// vector equivalent with any vectorization factor.
/// Return true if the function F has a vector equivalent with any
/// vectorization factor.
bool isFunctionVectorizable(StringRef F) const;
/// getVectorizedFunction - Return the name of the equivalent of
/// F, vectorized with factor VF. If no such mapping exists,
/// return the empty string.
/// Return the name of the equivalent of F, vectorized with factor VF. If no
/// such mapping exists, return the empty string.
StringRef getVectorizedFunction(StringRef F, unsigned VF) const;
/// isFunctionScalarizable - Return true if the function F has a
/// scalar equivalent, and set VF to be the vectorization factor.
/// Return true if the function F has a scalar equivalent, and set VF to be
/// the vectorization factor.
bool isFunctionScalarizable(StringRef F, unsigned &VF) const {
return !getScalarizedFunction(F, VF).empty();
}
/// getScalarizedFunction - Return the name of the equivalent of
/// F, scalarized. If no such mapping exists, return the empty string.
/// Return the name of the equivalent of F, scalarized. If no such mapping
/// exists, return the empty string.
///
/// Set VF to the vectorization factor.
StringRef getScalarizedFunction(StringRef F, unsigned &VF) const;
};
/// \brief Provides information about what library functions are available for
/// Provides information about what library functions are available for
/// the current target.
///
/// This both allows optimizations to handle them specially and frontends to
@ -187,7 +199,7 @@ public:
return *this;
}
/// \brief Searches for a particular function name.
/// Searches for a particular function name.
///
/// If it is one of the known library functions, return true and set F to the
/// corresponding value.
@ -195,7 +207,11 @@ public:
return Impl->getLibFunc(funcName, F);
}
/// \brief Tests whether a library function is available.
bool getLibFunc(const Function &FDecl, LibFunc::Func &F) const {
return Impl->getLibFunc(FDecl, F);
}
/// Tests whether a library function is available.
bool has(LibFunc::Func F) const {
return Impl->getState(F) != TargetLibraryInfoImpl::Unavailable;
}
@ -209,8 +225,8 @@ public:
return Impl->getVectorizedFunction(F, VF);
}
/// \brief Tests if the function is both available and a candidate for
/// optimized code generation.
/// Tests if the function is both available and a candidate for optimized code
/// generation.
bool hasOptimizedCodeGen(LibFunc::Func F) const {
if (Impl->getState(F) == TargetLibraryInfoImpl::Unavailable)
return false;
@ -251,31 +267,28 @@ public:
return Impl->CustomNames.find(F)->second;
}
/// \brief Handle invalidation from the pass manager.
/// Handle invalidation from the pass manager.
///
/// If we try to invalidate this info, just return false. It cannot become
/// invalid even if the module changes.
bool invalidate(Module &, const PreservedAnalyses &) { return false; }
};
/// \brief Analysis pass providing the \c TargetLibraryInfo.
/// Analysis pass providing the \c TargetLibraryInfo.
///
/// Note that this pass's result cannot be invalidated, it is immutable for the
/// life of the module.
class TargetLibraryAnalysis {
class TargetLibraryAnalysis : public AnalysisInfoMixin<TargetLibraryAnalysis> {
public:
typedef TargetLibraryInfo Result;
/// \brief Opaque, unique identifier for this analysis pass.
static void *ID() { return (void *)&PassID; }
/// \brief Default construct the library analysis.
/// Default construct the library analysis.
///
/// This will use the module's triple to construct the library info for that
/// module.
TargetLibraryAnalysis() {}
/// \brief Construct a library analysis with preset info.
/// Construct a library analysis with preset info.
///
/// This will directly copy the preset info into the result without
/// consulting the module's triple.
@ -291,20 +304,18 @@ public:
return *this;
}
TargetLibraryInfo run(Module &M);
TargetLibraryInfo run(Function &F);
/// \brief Provide access to a name for this pass for debugging purposes.
static StringRef name() { return "TargetLibraryAnalysis"; }
TargetLibraryInfo run(Module &M, ModuleAnalysisManager &);
TargetLibraryInfo run(Function &F, FunctionAnalysisManager &);
private:
friend AnalysisInfoMixin<TargetLibraryAnalysis>;
static char PassID;
Optional<TargetLibraryInfoImpl> PresetInfoImpl;
StringMap<std::unique_ptr<TargetLibraryInfoImpl>> Impls;
TargetLibraryInfoImpl &lookupInfoImpl(Triple T);
TargetLibraryInfoImpl &lookupInfoImpl(const Triple &T);
};
class TargetLibraryInfoWrapperPass : public ImmutablePass {

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