Initial drop of LLVM 10 to third_party/llvm-10.0 llvm-10-update: d32170dbd Change-Id: I654944085579e1e7a738ae8611bbaea27ccf0ccc
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/Analysis.h b/third_party/llvm-10.0/llvm/include/llvm-c/Analysis.h new file mode 100644 index 0000000..270b145 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/Analysis.h
@@ -0,0 +1,62 @@ +/*===-- llvm-c/Analysis.h - Analysis Library C Interface --------*- C++ -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to libLLVMAnalysis.a, which *| +|* implements various analyses of the LLVM IR. *| +|* *| +|* Many exotic languages can interoperate with C code but have a harder time *| +|* with C++ due to name mangling. So in addition to C, this interface enables *| +|* tools written in such languages. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_ANALYSIS_H +#define LLVM_C_ANALYSIS_H + +#include "llvm-c/ExternC.h" +#include "llvm-c/Types.h" + +LLVM_C_EXTERN_C_BEGIN + +/** + * @defgroup LLVMCAnalysis Analysis + * @ingroup LLVMC + * + * @{ + */ + +typedef enum { + LLVMAbortProcessAction, /* verifier will print to stderr and abort() */ + LLVMPrintMessageAction, /* verifier will print to stderr and return 1 */ + LLVMReturnStatusAction /* verifier will just return 1 */ +} LLVMVerifierFailureAction; + + +/* Verifies that a module is valid, taking the specified action if not. + Optionally returns a human-readable description of any invalid constructs. + OutMessage must be disposed with LLVMDisposeMessage. */ +LLVMBool LLVMVerifyModule(LLVMModuleRef M, LLVMVerifierFailureAction Action, + char **OutMessage); + +/* Verifies that a single function is valid, taking the specified action. Useful + for debugging. */ +LLVMBool LLVMVerifyFunction(LLVMValueRef Fn, LLVMVerifierFailureAction Action); + +/* Open up a ghostview window that displays the CFG of the current function. + Useful for debugging. */ +void LLVMViewFunctionCFG(LLVMValueRef Fn); +void LLVMViewFunctionCFGOnly(LLVMValueRef Fn); + +/** + * @} + */ + +LLVM_C_EXTERN_C_END + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/BitReader.h b/third_party/llvm-10.0/llvm/include/llvm-c/BitReader.h new file mode 100644 index 0000000..012c0e6 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/BitReader.h
@@ -0,0 +1,82 @@ +/*===-- llvm-c/BitReader.h - BitReader Library C Interface ------*- C++ -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to libLLVMBitReader.a, which *| +|* implements input of the LLVM bitcode format. *| +|* *| +|* Many exotic languages can interoperate with C code but have a harder time *| +|* with C++ due to name mangling. So in addition to C, this interface enables *| +|* tools written in such languages. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_BITREADER_H +#define LLVM_C_BITREADER_H + +#include "llvm-c/ExternC.h" +#include "llvm-c/Types.h" + +LLVM_C_EXTERN_C_BEGIN + +/** + * @defgroup LLVMCBitReader Bit Reader + * @ingroup LLVMC + * + * @{ + */ + +/* Builds a module from the bitcode in the specified memory buffer, returning a + reference to the module via the OutModule parameter. Returns 0 on success. + Optionally returns a human-readable error message via OutMessage. + + This is deprecated. Use LLVMParseBitcode2. */ +LLVMBool LLVMParseBitcode(LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutModule, + char **OutMessage); + +/* Builds a module from the bitcode in the specified memory buffer, returning a + reference to the module via the OutModule parameter. Returns 0 on success. */ +LLVMBool LLVMParseBitcode2(LLVMMemoryBufferRef MemBuf, + LLVMModuleRef *OutModule); + +/* This is deprecated. Use LLVMParseBitcodeInContext2. */ +LLVMBool LLVMParseBitcodeInContext(LLVMContextRef ContextRef, + LLVMMemoryBufferRef MemBuf, + LLVMModuleRef *OutModule, char **OutMessage); + +LLVMBool LLVMParseBitcodeInContext2(LLVMContextRef ContextRef, + LLVMMemoryBufferRef MemBuf, + LLVMModuleRef *OutModule); + +/** Reads a module from the specified path, returning via the OutMP parameter + a module provider which performs lazy deserialization. Returns 0 on success. + Optionally returns a human-readable error message via OutMessage. + This is deprecated. Use LLVMGetBitcodeModuleInContext2. */ +LLVMBool LLVMGetBitcodeModuleInContext(LLVMContextRef ContextRef, + LLVMMemoryBufferRef MemBuf, + LLVMModuleRef *OutM, char **OutMessage); + +/** Reads a module from the specified path, returning via the OutMP parameter a + * module provider which performs lazy deserialization. Returns 0 on success. */ +LLVMBool LLVMGetBitcodeModuleInContext2(LLVMContextRef ContextRef, + LLVMMemoryBufferRef MemBuf, + LLVMModuleRef *OutM); + +/* This is deprecated. Use LLVMGetBitcodeModule2. */ +LLVMBool LLVMGetBitcodeModule(LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutM, + char **OutMessage); + +LLVMBool LLVMGetBitcodeModule2(LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutM); + +/** + * @} + */ + +LLVM_C_EXTERN_C_END + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/BitWriter.h b/third_party/llvm-10.0/llvm/include/llvm-c/BitWriter.h new file mode 100644 index 0000000..ea84b65 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/BitWriter.h
@@ -0,0 +1,56 @@ +/*===-- llvm-c/BitWriter.h - BitWriter Library C Interface ------*- C++ -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to libLLVMBitWriter.a, which *| +|* implements output of the LLVM bitcode format. *| +|* *| +|* Many exotic languages can interoperate with C code but have a harder time *| +|* with C++ due to name mangling. So in addition to C, this interface enables *| +|* tools written in such languages. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_BITWRITER_H +#define LLVM_C_BITWRITER_H + +#include "llvm-c/ExternC.h" +#include "llvm-c/Types.h" + +LLVM_C_EXTERN_C_BEGIN + +/** + * @defgroup LLVMCBitWriter Bit Writer + * @ingroup LLVMC + * + * @{ + */ + +/*===-- Operations on modules ---------------------------------------------===*/ + +/** Writes a module to the specified path. Returns 0 on success. */ +int LLVMWriteBitcodeToFile(LLVMModuleRef M, const char *Path); + +/** Writes a module to an open file descriptor. Returns 0 on success. */ +int LLVMWriteBitcodeToFD(LLVMModuleRef M, int FD, int ShouldClose, + int Unbuffered); + +/** Deprecated for LLVMWriteBitcodeToFD. Writes a module to an open file + descriptor. Returns 0 on success. Closes the Handle. */ +int LLVMWriteBitcodeToFileHandle(LLVMModuleRef M, int Handle); + +/** Writes a module to a new memory buffer and returns it. */ +LLVMMemoryBufferRef LLVMWriteBitcodeToMemoryBuffer(LLVMModuleRef M); + +/** + * @} + */ + +LLVM_C_EXTERN_C_END + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/Comdat.h b/third_party/llvm-10.0/llvm/include/llvm-c/Comdat.h new file mode 100644 index 0000000..45b4007 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/Comdat.h
@@ -0,0 +1,72 @@ +/*===-- llvm-c/Comdat.h - Module Comdat C Interface -------------*- C++ -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file defines the C interface to COMDAT. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_COMDAT_H +#define LLVM_C_COMDAT_H + +#include "llvm-c/ExternC.h" +#include "llvm-c/Types.h" + +LLVM_C_EXTERN_C_BEGIN + +typedef enum { + LLVMAnyComdatSelectionKind, ///< The linker may choose any COMDAT. + LLVMExactMatchComdatSelectionKind, ///< The data referenced by the COMDAT must + ///< be the same. + LLVMLargestComdatSelectionKind, ///< The linker will choose the largest + ///< COMDAT. + LLVMNoDuplicatesComdatSelectionKind, ///< No other Module may specify this + ///< COMDAT. + LLVMSameSizeComdatSelectionKind ///< The data referenced by the COMDAT must be + ///< the same size. +} LLVMComdatSelectionKind; + +/** + * Return the Comdat in the module with the specified name. It is created + * if it didn't already exist. + * + * @see llvm::Module::getOrInsertComdat() + */ +LLVMComdatRef LLVMGetOrInsertComdat(LLVMModuleRef M, const char *Name); + +/** + * Get the Comdat assigned to the given global object. + * + * @see llvm::GlobalObject::getComdat() + */ +LLVMComdatRef LLVMGetComdat(LLVMValueRef V); + +/** + * Assign the Comdat to the given global object. + * + * @see llvm::GlobalObject::setComdat() + */ +void LLVMSetComdat(LLVMValueRef V, LLVMComdatRef C); + +/* + * Get the conflict resolution selection kind for the Comdat. + * + * @see llvm::Comdat::getSelectionKind() + */ +LLVMComdatSelectionKind LLVMGetComdatSelectionKind(LLVMComdatRef C); + +/* + * Set the conflict resolution selection kind for the Comdat. + * + * @see llvm::Comdat::setSelectionKind() + */ +void LLVMSetComdatSelectionKind(LLVMComdatRef C, LLVMComdatSelectionKind Kind); + +LLVM_C_EXTERN_C_END + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/Core.h b/third_party/llvm-10.0/llvm/include/llvm-c/Core.h new file mode 100644 index 0000000..7a39731 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/Core.h
@@ -0,0 +1,4094 @@ +/*===-- llvm-c/Core.h - Core Library C Interface ------------------*- C -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to libLLVMCore.a, which implements *| +|* the LLVM intermediate representation. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_CORE_H +#define LLVM_C_CORE_H + +#include "llvm-c/ErrorHandling.h" +#include "llvm-c/ExternC.h" +#include "llvm-c/Types.h" + +LLVM_C_EXTERN_C_BEGIN + +/** + * @defgroup LLVMC LLVM-C: C interface to LLVM + * + * This module exposes parts of the LLVM library as a C API. + * + * @{ + */ + +/** + * @defgroup LLVMCTransforms Transforms + */ + +/** + * @defgroup LLVMCCore Core + * + * This modules provide an interface to libLLVMCore, which implements + * the LLVM intermediate representation as well as other related types + * and utilities. + * + * Many exotic languages can interoperate with C code but have a harder time + * with C++ due to name mangling. So in addition to C, this interface enables + * tools written in such languages. + * + * @{ + */ + +/** + * @defgroup LLVMCCoreTypes Types and Enumerations + * + * @{ + */ + +/// External users depend on the following values being stable. It is not safe +/// to reorder them. +typedef enum { + /* Terminator Instructions */ + LLVMRet = 1, + LLVMBr = 2, + LLVMSwitch = 3, + LLVMIndirectBr = 4, + LLVMInvoke = 5, + /* removed 6 due to API changes */ + LLVMUnreachable = 7, + LLVMCallBr = 67, + + /* Standard Unary Operators */ + LLVMFNeg = 66, + + /* Standard Binary Operators */ + LLVMAdd = 8, + LLVMFAdd = 9, + LLVMSub = 10, + LLVMFSub = 11, + LLVMMul = 12, + LLVMFMul = 13, + LLVMUDiv = 14, + LLVMSDiv = 15, + LLVMFDiv = 16, + LLVMURem = 17, + LLVMSRem = 18, + LLVMFRem = 19, + + /* Logical Operators */ + LLVMShl = 20, + LLVMLShr = 21, + LLVMAShr = 22, + LLVMAnd = 23, + LLVMOr = 24, + LLVMXor = 25, + + /* Memory Operators */ + LLVMAlloca = 26, + LLVMLoad = 27, + LLVMStore = 28, + LLVMGetElementPtr = 29, + + /* Cast Operators */ + LLVMTrunc = 30, + LLVMZExt = 31, + LLVMSExt = 32, + LLVMFPToUI = 33, + LLVMFPToSI = 34, + LLVMUIToFP = 35, + LLVMSIToFP = 36, + LLVMFPTrunc = 37, + LLVMFPExt = 38, + LLVMPtrToInt = 39, + LLVMIntToPtr = 40, + LLVMBitCast = 41, + LLVMAddrSpaceCast = 60, + + /* Other Operators */ + LLVMICmp = 42, + LLVMFCmp = 43, + LLVMPHI = 44, + LLVMCall = 45, + LLVMSelect = 46, + LLVMUserOp1 = 47, + LLVMUserOp2 = 48, + LLVMVAArg = 49, + LLVMExtractElement = 50, + LLVMInsertElement = 51, + LLVMShuffleVector = 52, + LLVMExtractValue = 53, + LLVMInsertValue = 54, + LLVMFreeze = 68, + + /* Atomic operators */ + LLVMFence = 55, + LLVMAtomicCmpXchg = 56, + LLVMAtomicRMW = 57, + + /* Exception Handling Operators */ + LLVMResume = 58, + LLVMLandingPad = 59, + LLVMCleanupRet = 61, + LLVMCatchRet = 62, + LLVMCatchPad = 63, + LLVMCleanupPad = 64, + LLVMCatchSwitch = 65 +} LLVMOpcode; + +typedef enum { + LLVMVoidTypeKind, /**< type with no size */ + LLVMHalfTypeKind, /**< 16 bit floating point type */ + LLVMFloatTypeKind, /**< 32 bit floating point type */ + LLVMDoubleTypeKind, /**< 64 bit floating point type */ + LLVMX86_FP80TypeKind, /**< 80 bit floating point type (X87) */ + LLVMFP128TypeKind, /**< 128 bit floating point type (112-bit mantissa)*/ + LLVMPPC_FP128TypeKind, /**< 128 bit floating point type (two 64-bits) */ + LLVMLabelTypeKind, /**< Labels */ + LLVMIntegerTypeKind, /**< Arbitrary bit width integers */ + LLVMFunctionTypeKind, /**< Functions */ + LLVMStructTypeKind, /**< Structures */ + LLVMArrayTypeKind, /**< Arrays */ + LLVMPointerTypeKind, /**< Pointers */ + LLVMVectorTypeKind, /**< SIMD 'packed' format, or other vector type */ + LLVMMetadataTypeKind, /**< Metadata */ + LLVMX86_MMXTypeKind, /**< X86 MMX */ + LLVMTokenTypeKind /**< Tokens */ +} LLVMTypeKind; + +typedef enum { + LLVMExternalLinkage, /**< Externally visible function */ + LLVMAvailableExternallyLinkage, + LLVMLinkOnceAnyLinkage, /**< Keep one copy of function when linking (inline)*/ + LLVMLinkOnceODRLinkage, /**< Same, but only replaced by something + equivalent. */ + LLVMLinkOnceODRAutoHideLinkage, /**< Obsolete */ + LLVMWeakAnyLinkage, /**< Keep one copy of function when linking (weak) */ + LLVMWeakODRLinkage, /**< Same, but only replaced by something + equivalent. */ + LLVMAppendingLinkage, /**< Special purpose, only applies to global arrays */ + LLVMInternalLinkage, /**< Rename collisions when linking (static + functions) */ + LLVMPrivateLinkage, /**< Like Internal, but omit from symbol table */ + LLVMDLLImportLinkage, /**< Obsolete */ + LLVMDLLExportLinkage, /**< Obsolete */ + LLVMExternalWeakLinkage,/**< ExternalWeak linkage description */ + LLVMGhostLinkage, /**< Obsolete */ + LLVMCommonLinkage, /**< Tentative definitions */ + LLVMLinkerPrivateLinkage, /**< Like Private, but linker removes. */ + LLVMLinkerPrivateWeakLinkage /**< Like LinkerPrivate, but is weak. */ +} LLVMLinkage; + +typedef enum { + LLVMDefaultVisibility, /**< The GV is visible */ + LLVMHiddenVisibility, /**< The GV is hidden */ + LLVMProtectedVisibility /**< The GV is protected */ +} LLVMVisibility; + +typedef enum { + LLVMNoUnnamedAddr, /**< Address of the GV is significant. */ + LLVMLocalUnnamedAddr, /**< Address of the GV is locally insignificant. */ + LLVMGlobalUnnamedAddr /**< Address of the GV is globally insignificant. */ +} LLVMUnnamedAddr; + +typedef enum { + LLVMDefaultStorageClass = 0, + LLVMDLLImportStorageClass = 1, /**< Function to be imported from DLL. */ + LLVMDLLExportStorageClass = 2 /**< Function to be accessible from DLL. */ +} LLVMDLLStorageClass; + +typedef enum { + LLVMCCallConv = 0, + LLVMFastCallConv = 8, + LLVMColdCallConv = 9, + LLVMGHCCallConv = 10, + LLVMHiPECallConv = 11, + LLVMWebKitJSCallConv = 12, + LLVMAnyRegCallConv = 13, + LLVMPreserveMostCallConv = 14, + LLVMPreserveAllCallConv = 15, + LLVMSwiftCallConv = 16, + LLVMCXXFASTTLSCallConv = 17, + LLVMX86StdcallCallConv = 64, + LLVMX86FastcallCallConv = 65, + LLVMARMAPCSCallConv = 66, + LLVMARMAAPCSCallConv = 67, + LLVMARMAAPCSVFPCallConv = 68, + LLVMMSP430INTRCallConv = 69, + LLVMX86ThisCallCallConv = 70, + LLVMPTXKernelCallConv = 71, + LLVMPTXDeviceCallConv = 72, + LLVMSPIRFUNCCallConv = 75, + LLVMSPIRKERNELCallConv = 76, + LLVMIntelOCLBICallConv = 77, + LLVMX8664SysVCallConv = 78, + LLVMWin64CallConv = 79, + LLVMX86VectorCallCallConv = 80, + LLVMHHVMCallConv = 81, + LLVMHHVMCCallConv = 82, + LLVMX86INTRCallConv = 83, + LLVMAVRINTRCallConv = 84, + LLVMAVRSIGNALCallConv = 85, + LLVMAVRBUILTINCallConv = 86, + LLVMAMDGPUVSCallConv = 87, + LLVMAMDGPUGSCallConv = 88, + LLVMAMDGPUPSCallConv = 89, + LLVMAMDGPUCSCallConv = 90, + LLVMAMDGPUKERNELCallConv = 91, + LLVMX86RegCallCallConv = 92, + LLVMAMDGPUHSCallConv = 93, + LLVMMSP430BUILTINCallConv = 94, + LLVMAMDGPULSCallConv = 95, + LLVMAMDGPUESCallConv = 96 +} 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 */ + LLVMIntUGT, /**< unsigned greater than */ + LLVMIntUGE, /**< unsigned greater or equal */ + LLVMIntULT, /**< unsigned less than */ + LLVMIntULE, /**< unsigned less or equal */ + LLVMIntSGT, /**< signed greater than */ + LLVMIntSGE, /**< signed greater or equal */ + LLVMIntSLT, /**< signed less than */ + LLVMIntSLE /**< signed less or equal */ +} LLVMIntPredicate; + +typedef enum { + LLVMRealPredicateFalse, /**< Always false (always folded) */ + LLVMRealOEQ, /**< True if ordered and equal */ + LLVMRealOGT, /**< True if ordered and greater than */ + LLVMRealOGE, /**< True if ordered and greater than or equal */ + LLVMRealOLT, /**< True if ordered and less than */ + LLVMRealOLE, /**< True if ordered and less than or equal */ + LLVMRealONE, /**< True if ordered and operands are unequal */ + LLVMRealORD, /**< True if ordered (no nans) */ + LLVMRealUNO, /**< True if unordered: isnan(X) | isnan(Y) */ + LLVMRealUEQ, /**< True if unordered or equal */ + LLVMRealUGT, /**< True if unordered or greater than */ + LLVMRealUGE, /**< True if unordered, greater than, or equal */ + LLVMRealULT, /**< True if unordered or less than */ + LLVMRealULE, /**< True if unordered, less than, or equal */ + LLVMRealUNE, /**< True if unordered or not equal */ + LLVMRealPredicateTrue /**< Always true (always folded) */ +} LLVMRealPredicate; + +typedef enum { + LLVMLandingPadCatch, /**< A catch clause */ + LLVMLandingPadFilter /**< A filter clause */ +} LLVMLandingPadClauseTy; + +typedef enum { + LLVMNotThreadLocal = 0, + LLVMGeneralDynamicTLSModel, + LLVMLocalDynamicTLSModel, + LLVMInitialExecTLSModel, + LLVMLocalExecTLSModel +} LLVMThreadLocalMode; + +typedef enum { + LLVMAtomicOrderingNotAtomic = 0, /**< A load or store which is not atomic */ + LLVMAtomicOrderingUnordered = 1, /**< Lowest level of atomicity, guarantees + somewhat sane results, lock free. */ + LLVMAtomicOrderingMonotonic = 2, /**< guarantees that if you take all the + operations affecting a specific address, + a consistent ordering exists */ + LLVMAtomicOrderingAcquire = 4, /**< Acquire provides a barrier of the sort + necessary to acquire a lock to access other + memory with normal loads and stores. */ + LLVMAtomicOrderingRelease = 5, /**< Release is similar to Acquire, but with + a barrier of the sort necessary to release + a lock. */ + LLVMAtomicOrderingAcquireRelease = 6, /**< provides both an Acquire and a + Release barrier (for fences and + operations which both read and write + memory). */ + LLVMAtomicOrderingSequentiallyConsistent = 7 /**< provides Acquire semantics + for loads and Release + semantics for stores. + Additionally, it guarantees + that a total ordering exists + between all + SequentiallyConsistent + operations. */ +} LLVMAtomicOrdering; + +typedef enum { + LLVMAtomicRMWBinOpXchg, /**< Set the new value and return the one old */ + LLVMAtomicRMWBinOpAdd, /**< Add a value and return the old one */ + LLVMAtomicRMWBinOpSub, /**< Subtract a value and return the old one */ + LLVMAtomicRMWBinOpAnd, /**< And a value and return the old one */ + LLVMAtomicRMWBinOpNand, /**< Not-And a value and return the old one */ + LLVMAtomicRMWBinOpOr, /**< OR a value and return the old one */ + LLVMAtomicRMWBinOpXor, /**< Xor a value and return the old one */ + LLVMAtomicRMWBinOpMax, /**< Sets the value if it's greater than the + original using a signed comparison and return + the old one */ + LLVMAtomicRMWBinOpMin, /**< Sets the value if it's Smaller than the + original using a signed comparison and return + the old one */ + LLVMAtomicRMWBinOpUMax, /**< Sets the value if it's greater than the + original using an unsigned comparison and return + the old one */ + LLVMAtomicRMWBinOpUMin, /**< Sets the value if it's greater than the + original using an unsigned comparison and return + the old one */ + LLVMAtomicRMWBinOpFAdd, /**< Add a floating point value and return the + old one */ + LLVMAtomicRMWBinOpFSub /**< Subtract a floating point value and return the + old one */ +} LLVMAtomicRMWBinOp; + +typedef enum { + LLVMDSError, + LLVMDSWarning, + LLVMDSRemark, + LLVMDSNote +} LLVMDiagnosticSeverity; + +typedef enum { + LLVMInlineAsmDialectATT, + LLVMInlineAsmDialectIntel +} LLVMInlineAsmDialect; + +typedef enum { + /** + * Emits an error if two values disagree, otherwise the resulting value is + * that of the operands. + * + * @see Module::ModFlagBehavior::Error + */ + LLVMModuleFlagBehaviorError, + /** + * Emits a warning if two values disagree. The result value will be the + * operand for the flag from the first module being linked. + * + * @see Module::ModFlagBehavior::Warning + */ + LLVMModuleFlagBehaviorWarning, + /** + * Adds a requirement that another module flag be present and have a + * specified value after linking is performed. The value must be a metadata + * pair, where the first element of the pair is the ID of the module flag + * to be restricted, and the second element of the pair is the value the + * module flag should be restricted to. This behavior can be used to + * restrict the allowable results (via triggering of an error) of linking + * IDs with the **Override** behavior. + * + * @see Module::ModFlagBehavior::Require + */ + LLVMModuleFlagBehaviorRequire, + /** + * Uses the specified value, regardless of the behavior or value of the + * other module. If both modules specify **Override**, but the values + * differ, an error will be emitted. + * + * @see Module::ModFlagBehavior::Override + */ + LLVMModuleFlagBehaviorOverride, + /** + * Appends the two values, which are required to be metadata nodes. + * + * @see Module::ModFlagBehavior::Append + */ + LLVMModuleFlagBehaviorAppend, + /** + * Appends the two values, which are required to be metadata + * nodes. However, duplicate entries in the second list are dropped + * during the append operation. + * + * @see Module::ModFlagBehavior::AppendUnique + */ + LLVMModuleFlagBehaviorAppendUnique, +} LLVMModuleFlagBehavior; + +/** + * 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; + +/** + * @} + */ + +void LLVMInitializeCore(LLVMPassRegistryRef R); + +/** Deallocate and destroy all ManagedStatic variables. + @see llvm::llvm_shutdown + @see ManagedStatic */ +void LLVMShutdown(void); + +/*===-- Error handling ----------------------------------------------------===*/ + +char *LLVMCreateMessage(const char *Message); +void LLVMDisposeMessage(char *Message); + +/** + * @defgroup LLVMCCoreContext Contexts + * + * Contexts are execution states for the core LLVM IR system. + * + * Most types are tied to a context instance. Multiple contexts can + * exist simultaneously. A single context is not thread safe. However, + * different contexts can execute on different threads simultaneously. + * + * @{ + */ + +typedef void (*LLVMDiagnosticHandler)(LLVMDiagnosticInfoRef, void *); +typedef void (*LLVMYieldCallback)(LLVMContextRef, void *); + +/** + * Create a new context. + * + * Every call to this function should be paired with a call to + * LLVMContextDispose() or the context will leak memory. + */ +LLVMContextRef LLVMContextCreate(void); + +/** + * Obtain the global context instance. + */ +LLVMContextRef LLVMGetGlobalContext(void); + +/** + * Set the diagnostic handler for this context. + */ +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. + * + * @see LLVMContext::setYieldCallback() + */ +void LLVMContextSetYieldCallback(LLVMContextRef C, LLVMYieldCallback Callback, + void *OpaqueHandle); + +/** + * Retrieve whether the given context is set to discard all value names. + * + * @see LLVMContext::shouldDiscardValueNames() + */ +LLVMBool LLVMContextShouldDiscardValueNames(LLVMContextRef C); + +/** + * Set whether the given context discards all value names. + * + * If true, only the names of GlobalValue objects will be available in the IR. + * This can be used to save memory and runtime, especially in release mode. + * + * @see LLVMContext::setDiscardValueNames() + */ +void LLVMContextSetDiscardValueNames(LLVMContextRef C, LLVMBool Discard); + +/** + * Destroy a context instance. + * + * This should be called for every call to LLVMContextCreate() or memory + * will be leaked. + */ +void LLVMContextDispose(LLVMContextRef C); + +/** + * Return a string representation of the DiagnosticInfo. Use + * LLVMDisposeMessage to free the string. + * + * @see DiagnosticInfo::print() + */ +char *LLVMGetDiagInfoDescription(LLVMDiagnosticInfoRef DI); + +/** + * Return an enum LLVMDiagnosticSeverity. + * + * @see DiagnosticInfo::getSeverity() + */ +LLVMDiagnosticSeverity LLVMGetDiagInfoSeverity(LLVMDiagnosticInfoRef DI); + +unsigned LLVMGetMDKindIDInContext(LLVMContextRef C, const char *Name, + unsigned SLen); +unsigned LLVMGetMDKindID(const char *Name, unsigned SLen); + +/** + * 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); + +/** + * @} + */ + +/** + * @defgroup LLVMCCoreModule Modules + * + * Modules represent the top-level structure in an LLVM program. An LLVM + * module is effectively a translation unit or a collection of + * translation units merged together. + * + * @{ + */ + +/** + * Create a new, empty module in the global context. + * + * This is equivalent to calling LLVMModuleCreateWithNameInContext with + * LLVMGetGlobalContext() as the context parameter. + * + * Every invocation should be paired with LLVMDisposeModule() or memory + * will be leaked. + */ +LLVMModuleRef LLVMModuleCreateWithName(const char *ModuleID); + +/** + * Create a new, empty module in a specific context. + * + * Every invocation should be paired with LLVMDisposeModule() or memory + * will be leaked. + */ +LLVMModuleRef LLVMModuleCreateWithNameInContext(const char *ModuleID, + LLVMContextRef C); +/** + * Return an exact copy of the specified module. + */ +LLVMModuleRef LLVMCloneModule(LLVMModuleRef M); + +/** + * Destroy a module instance. + * + * This must be called for every created module or memory will be + * leaked. + */ +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 module's original source file name. + * + * @param M Module to obtain the name of + * @param Len Out parameter which holds the length of the returned string + * @return The original source file name of M + * @see Module::getSourceFileName() + */ +const char *LLVMGetSourceFileName(LLVMModuleRef M, size_t *Len); + +/** + * Set the original source file name of a module to a string Name with length + * Len. + * + * @param M The module to set the source file name of + * @param Name The string to set M's source file name to + * @param Len Length of Name + * @see Module::setSourceFileName() + */ +void LLVMSetSourceFileName(LLVMModuleRef M, const char *Name, size_t Len); + +/** + * Obtain the data layout for a module. + * + * @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); + +/** + * Set the data layout for a module. + * + * @see Module::setDataLayout() + */ +void LLVMSetDataLayout(LLVMModuleRef M, const char *DataLayoutStr); + +/** + * Obtain the target triple for a module. + * + * @see Module::getTargetTriple() + */ +const char *LLVMGetTarget(LLVMModuleRef M); + +/** + * Set the target triple for a module. + * + * @see Module::setTargetTriple() + */ +void LLVMSetTarget(LLVMModuleRef M, const char *Triple); + +/** + * Returns the module flags as an array of flag-key-value triples. The caller + * is responsible for freeing this array by calling + * \c LLVMDisposeModuleFlagsMetadata. + * + * @see Module::getModuleFlagsMetadata() + */ +LLVMModuleFlagEntry *LLVMCopyModuleFlagsMetadata(LLVMModuleRef M, size_t *Len); + +/** + * Destroys module flags metadata entries. + */ +void LLVMDisposeModuleFlagsMetadata(LLVMModuleFlagEntry *Entries); + +/** + * Returns the flag behavior for a module flag entry at a specific index. + * + * @see Module::ModuleFlagEntry::Behavior + */ +LLVMModuleFlagBehavior +LLVMModuleFlagEntriesGetFlagBehavior(LLVMModuleFlagEntry *Entries, + unsigned Index); + +/** + * Returns the key for a module flag entry at a specific index. + * + * @see Module::ModuleFlagEntry::Key + */ +const char *LLVMModuleFlagEntriesGetKey(LLVMModuleFlagEntry *Entries, + unsigned Index, size_t *Len); + +/** + * Returns the metadata for a module flag entry at a specific index. + * + * @see Module::ModuleFlagEntry::Val + */ +LLVMMetadataRef LLVMModuleFlagEntriesGetMetadata(LLVMModuleFlagEntry *Entries, + unsigned Index); + +/** + * Add a module-level flag to the module-level flags metadata if it doesn't + * already exist. + * + * @see Module::getModuleFlag() + */ +LLVMMetadataRef LLVMGetModuleFlag(LLVMModuleRef M, + const char *Key, size_t KeyLen); + +/** + * Add a module-level flag to the module-level flags metadata if it doesn't + * already exist. + * + * @see Module::addModuleFlag() + */ +void LLVMAddModuleFlag(LLVMModuleRef M, LLVMModuleFlagBehavior Behavior, + const char *Key, size_t KeyLen, + LLVMMetadataRef Val); + +/** + * Dump a representation of a module to stderr. + * + * @see Module::dump() + */ +void LLVMDumpModule(LLVMModuleRef M); + +/** + * Print a representation of a module to a file. The ErrorMessage needs to be + * disposed with LLVMDisposeMessage. Returns 0 on success, 1 otherwise. + * + * @see Module::print() + */ +LLVMBool LLVMPrintModuleToFile(LLVMModuleRef M, const char *Filename, + char **ErrorMessage); + +/** + * Return a string representation of the module. Use + * LLVMDisposeMessage to free the string. + * + * @see Module::print() + */ +char *LLVMPrintModuleToString(LLVMModuleRef M); + +/** + * Get inline assembly for a module. + * + * @see Module::getModuleInlineAsm() + */ +const char *LLVMGetModuleInlineAsm(LLVMModuleRef M, size_t *Len); + +/** + * Set inline assembly for a module. + * + * @see Module::setModuleInlineAsm() + */ +void LLVMSetModuleInlineAsm2(LLVMModuleRef M, const char *Asm, size_t Len); + +/** + * Append inline assembly to a module. + * + * @see Module::appendModuleInlineAsm() + */ +void LLVMAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm, size_t Len); + +/** + * Create the specified uniqued inline asm string. + * + * @see InlineAsm::get() + */ +LLVMValueRef LLVMGetInlineAsm(LLVMTypeRef Ty, + char *AsmString, size_t AsmStringSize, + char *Constraints, size_t ConstraintsSize, + LLVMBool HasSideEffects, LLVMBool IsAlignStack, + LLVMInlineAsmDialect Dialect); + +/** + * Obtain the context to which this module is associated. + * + * @see Module::getContext() + */ +LLVMContextRef LLVMGetModuleContext(LLVMModuleRef M); + +/** + * Obtain a Type from a module by its registered name. + */ +LLVMTypeRef LLVMGetTypeByName(LLVMModuleRef M, const char *Name); + +/** + * Obtain an iterator to the first NamedMDNode in a Module. + * + * @see llvm::Module::named_metadata_begin() + */ +LLVMNamedMDNodeRef LLVMGetFirstNamedMetadata(LLVMModuleRef M); + +/** + * Obtain an iterator to the last NamedMDNode in a Module. + * + * @see llvm::Module::named_metadata_end() + */ +LLVMNamedMDNodeRef LLVMGetLastNamedMetadata(LLVMModuleRef M); + +/** + * Advance a NamedMDNode iterator to the next NamedMDNode. + * + * Returns NULL if the iterator was already at the end and there are no more + * named metadata nodes. + */ +LLVMNamedMDNodeRef LLVMGetNextNamedMetadata(LLVMNamedMDNodeRef NamedMDNode); + +/** + * Decrement a NamedMDNode iterator to the previous NamedMDNode. + * + * Returns NULL if the iterator was already at the beginning and there are + * no previous named metadata nodes. + */ +LLVMNamedMDNodeRef LLVMGetPreviousNamedMetadata(LLVMNamedMDNodeRef NamedMDNode); + +/** + * Retrieve a NamedMDNode with the given name, returning NULL if no such + * node exists. + * + * @see llvm::Module::getNamedMetadata() + */ +LLVMNamedMDNodeRef LLVMGetNamedMetadata(LLVMModuleRef M, + const char *Name, size_t NameLen); + +/** + * Retrieve a NamedMDNode with the given name, creating a new node if no such + * node exists. + * + * @see llvm::Module::getOrInsertNamedMetadata() + */ +LLVMNamedMDNodeRef LLVMGetOrInsertNamedMetadata(LLVMModuleRef M, + const char *Name, + size_t NameLen); + +/** + * Retrieve the name of a NamedMDNode. + * + * @see llvm::NamedMDNode::getName() + */ +const char *LLVMGetNamedMetadataName(LLVMNamedMDNodeRef NamedMD, + size_t *NameLen); + +/** + * Obtain the number of operands for named metadata in a module. + * + * @see llvm::Module::getNamedMetadata() + */ +unsigned LLVMGetNamedMetadataNumOperands(LLVMModuleRef M, const char *Name); + +/** + * Obtain the named metadata operands for a module. + * + * The passed LLVMValueRef pointer should refer to an array of + * LLVMValueRef at least LLVMGetNamedMetadataNumOperands long. This + * array will be populated with the LLVMValueRef instances. Each + * instance corresponds to a llvm::MDNode. + * + * @see llvm::Module::getNamedMetadata() + * @see llvm::MDNode::getOperand() + */ +void LLVMGetNamedMetadataOperands(LLVMModuleRef M, const char *Name, + LLVMValueRef *Dest); + +/** + * Add an operand to named metadata. + * + * @see llvm::Module::getNamedMetadata() + * @see llvm::MDNode::addOperand() + */ +void LLVMAddNamedMetadataOperand(LLVMModuleRef M, const char *Name, + LLVMValueRef Val); + +/** + * Return the directory of the debug location for this value, which must be + * an llvm::Instruction, llvm::GlobalVariable, or llvm::Function. + * + * @see llvm::Instruction::getDebugLoc() + * @see llvm::GlobalVariable::getDebugInfo() + * @see llvm::Function::getSubprogram() + */ +const char *LLVMGetDebugLocDirectory(LLVMValueRef Val, unsigned *Length); + +/** + * Return the filename of the debug location for this value, which must be + * an llvm::Instruction, llvm::GlobalVariable, or llvm::Function. + * + * @see llvm::Instruction::getDebugLoc() + * @see llvm::GlobalVariable::getDebugInfo() + * @see llvm::Function::getSubprogram() + */ +const char *LLVMGetDebugLocFilename(LLVMValueRef Val, unsigned *Length); + +/** + * Return the line number of the debug location for this value, which must be + * an llvm::Instruction, llvm::GlobalVariable, or llvm::Function. + * + * @see llvm::Instruction::getDebugLoc() + * @see llvm::GlobalVariable::getDebugInfo() + * @see llvm::Function::getSubprogram() + */ +unsigned LLVMGetDebugLocLine(LLVMValueRef Val); + +/** + * Return the column number of the debug location for this value, which must be + * an llvm::Instruction. + * + * @see llvm::Instruction::getDebugLoc() + */ +unsigned LLVMGetDebugLocColumn(LLVMValueRef Val); + +/** + * Add a function to a module under a specified name. + * + * @see llvm::Function::Create() + */ +LLVMValueRef LLVMAddFunction(LLVMModuleRef M, const char *Name, + LLVMTypeRef FunctionTy); + +/** + * Obtain a Function value from a Module by its name. + * + * The returned value corresponds to a llvm::Function value. + * + * @see llvm::Module::getFunction() + */ +LLVMValueRef LLVMGetNamedFunction(LLVMModuleRef M, const char *Name); + +/** + * Obtain an iterator to the first Function in a Module. + * + * @see llvm::Module::begin() + */ +LLVMValueRef LLVMGetFirstFunction(LLVMModuleRef M); + +/** + * Obtain an iterator to the last Function in a Module. + * + * @see llvm::Module::end() + */ +LLVMValueRef LLVMGetLastFunction(LLVMModuleRef M); + +/** + * Advance a Function iterator to the next Function. + * + * Returns NULL if the iterator was already at the end and there are no more + * functions. + */ +LLVMValueRef LLVMGetNextFunction(LLVMValueRef Fn); + +/** + * Decrement a Function iterator to the previous Function. + * + * Returns NULL if the iterator was already at the beginning and there are + * no previous functions. + */ +LLVMValueRef LLVMGetPreviousFunction(LLVMValueRef Fn); + +/** Deprecated: Use LLVMSetModuleInlineAsm2 instead. */ +void LLVMSetModuleInlineAsm(LLVMModuleRef M, const char *Asm); + +/** + * @} + */ + +/** + * @defgroup LLVMCCoreType Types + * + * Types represent the type of a value. + * + * Types are associated with a context instance. The context internally + * deduplicates types so there is only 1 instance of a specific type + * alive at a time. In other words, a unique type is shared among all + * consumers within a context. + * + * A Type in the C API corresponds to llvm::Type. + * + * Types have the following hierarchy: + * + * types: + * integer type + * real type + * function type + * sequence types: + * array type + * pointer type + * vector type + * void type + * label type + * opaque type + * + * @{ + */ + +/** + * Obtain the enumerated type of a Type instance. + * + * @see llvm::Type:getTypeID() + */ +LLVMTypeKind LLVMGetTypeKind(LLVMTypeRef Ty); + +/** + * Whether the type has a known size. + * + * Things that don't have a size are abstract types, labels, and void.a + * + * @see llvm::Type::isSized() + */ +LLVMBool LLVMTypeIsSized(LLVMTypeRef Ty); + +/** + * Obtain the context to which this type instance is associated. + * + * @see llvm::Type::getContext() + */ +LLVMContextRef LLVMGetTypeContext(LLVMTypeRef Ty); + +/** + * Dump a representation of a type to stderr. + * + * @see llvm::Type::dump() + */ +void LLVMDumpType(LLVMTypeRef Val); + +/** + * Return a string representation of the type. Use + * LLVMDisposeMessage to free the string. + * + * @see llvm::Type::print() + */ +char *LLVMPrintTypeToString(LLVMTypeRef Val); + +/** + * @defgroup LLVMCCoreTypeInt Integer Types + * + * Functions in this section operate on integer types. + * + * @{ + */ + +/** + * Obtain an integer type from a context with specified bit width. + */ +LLVMTypeRef LLVMInt1TypeInContext(LLVMContextRef C); +LLVMTypeRef LLVMInt8TypeInContext(LLVMContextRef C); +LLVMTypeRef LLVMInt16TypeInContext(LLVMContextRef C); +LLVMTypeRef LLVMInt32TypeInContext(LLVMContextRef C); +LLVMTypeRef LLVMInt64TypeInContext(LLVMContextRef C); +LLVMTypeRef LLVMInt128TypeInContext(LLVMContextRef C); +LLVMTypeRef LLVMIntTypeInContext(LLVMContextRef C, unsigned NumBits); + +/** + * Obtain an integer type from the global context with a specified bit + * width. + */ +LLVMTypeRef LLVMInt1Type(void); +LLVMTypeRef LLVMInt8Type(void); +LLVMTypeRef LLVMInt16Type(void); +LLVMTypeRef LLVMInt32Type(void); +LLVMTypeRef LLVMInt64Type(void); +LLVMTypeRef LLVMInt128Type(void); +LLVMTypeRef LLVMIntType(unsigned NumBits); +unsigned LLVMGetIntTypeWidth(LLVMTypeRef IntegerTy); + +/** + * @} + */ + +/** + * @defgroup LLVMCCoreTypeFloat Floating Point Types + * + * @{ + */ + +/** + * Obtain a 16-bit floating point type from a context. + */ +LLVMTypeRef LLVMHalfTypeInContext(LLVMContextRef C); + +/** + * Obtain a 32-bit floating point type from a context. + */ +LLVMTypeRef LLVMFloatTypeInContext(LLVMContextRef C); + +/** + * Obtain a 64-bit floating point type from a context. + */ +LLVMTypeRef LLVMDoubleTypeInContext(LLVMContextRef C); + +/** + * Obtain a 80-bit floating point type (X87) from a context. + */ +LLVMTypeRef LLVMX86FP80TypeInContext(LLVMContextRef C); + +/** + * Obtain a 128-bit floating point type (112-bit mantissa) from a + * context. + */ +LLVMTypeRef LLVMFP128TypeInContext(LLVMContextRef C); + +/** + * Obtain a 128-bit floating point type (two 64-bits) from a context. + */ +LLVMTypeRef LLVMPPCFP128TypeInContext(LLVMContextRef C); + +/** + * Obtain a floating point type from the global context. + * + * These map to the functions in this group of the same name. + */ +LLVMTypeRef LLVMHalfType(void); +LLVMTypeRef LLVMFloatType(void); +LLVMTypeRef LLVMDoubleType(void); +LLVMTypeRef LLVMX86FP80Type(void); +LLVMTypeRef LLVMFP128Type(void); +LLVMTypeRef LLVMPPCFP128Type(void); + +/** + * @} + */ + +/** + * @defgroup LLVMCCoreTypeFunction Function Types + * + * @{ + */ + +/** + * Obtain a function type consisting of a specified signature. + * + * The function is defined as a tuple of a return Type, a list of + * parameter types, and whether the function is variadic. + */ +LLVMTypeRef LLVMFunctionType(LLVMTypeRef ReturnType, + LLVMTypeRef *ParamTypes, unsigned ParamCount, + LLVMBool IsVarArg); + +/** + * Returns whether a function type is variadic. + */ +LLVMBool LLVMIsFunctionVarArg(LLVMTypeRef FunctionTy); + +/** + * Obtain the Type this function Type returns. + */ +LLVMTypeRef LLVMGetReturnType(LLVMTypeRef FunctionTy); + +/** + * Obtain the number of parameters this function accepts. + */ +unsigned LLVMCountParamTypes(LLVMTypeRef FunctionTy); + +/** + * Obtain the types of a function's parameters. + * + * The Dest parameter should point to a pre-allocated array of + * LLVMTypeRef at least LLVMCountParamTypes() large. On return, the + * first LLVMCountParamTypes() entries in the array will be populated + * with LLVMTypeRef instances. + * + * @param FunctionTy The function type to operate on. + * @param Dest Memory address of an array to be filled with result. + */ +void LLVMGetParamTypes(LLVMTypeRef FunctionTy, LLVMTypeRef *Dest); + +/** + * @} + */ + +/** + * @defgroup LLVMCCoreTypeStruct Structure Types + * + * These functions relate to LLVMTypeRef instances. + * + * @see llvm::StructType + * + * @{ + */ + +/** + * Create a new structure type in a context. + * + * A structure is specified by a list of inner elements/types and + * whether these can be packed together. + * + * @see llvm::StructType::create() + */ +LLVMTypeRef LLVMStructTypeInContext(LLVMContextRef C, LLVMTypeRef *ElementTypes, + unsigned ElementCount, LLVMBool Packed); + +/** + * Create a new structure type in the global context. + * + * @see llvm::StructType::create() + */ +LLVMTypeRef LLVMStructType(LLVMTypeRef *ElementTypes, unsigned ElementCount, + LLVMBool Packed); + +/** + * Create an empty structure in a context having a specified name. + * + * @see llvm::StructType::create() + */ +LLVMTypeRef LLVMStructCreateNamed(LLVMContextRef C, const char *Name); + +/** + * Obtain the name of a structure. + * + * @see llvm::StructType::getName() + */ +const char *LLVMGetStructName(LLVMTypeRef Ty); + +/** + * Set the contents of a structure type. + * + * @see llvm::StructType::setBody() + */ +void LLVMStructSetBody(LLVMTypeRef StructTy, LLVMTypeRef *ElementTypes, + unsigned ElementCount, LLVMBool Packed); + +/** + * Get the number of elements defined inside the structure. + * + * @see llvm::StructType::getNumElements() + */ +unsigned LLVMCountStructElementTypes(LLVMTypeRef StructTy); + +/** + * Get the elements within a structure. + * + * The function is passed the address of a pre-allocated array of + * LLVMTypeRef at least LLVMCountStructElementTypes() long. After + * invocation, this array will be populated with the structure's + * elements. The objects in the destination array will have a lifetime + * of the structure type itself, which is the lifetime of the context it + * is contained in. + */ +void LLVMGetStructElementTypes(LLVMTypeRef StructTy, LLVMTypeRef *Dest); + +/** + * Get the type of the element at a given index in the structure. + * + * @see llvm::StructType::getTypeAtIndex() + */ +LLVMTypeRef LLVMStructGetTypeAtIndex(LLVMTypeRef StructTy, unsigned i); + +/** + * Determine whether a structure is packed. + * + * @see llvm::StructType::isPacked() + */ +LLVMBool LLVMIsPackedStruct(LLVMTypeRef StructTy); + +/** + * Determine whether a structure is opaque. + * + * @see llvm::StructType::isOpaque() + */ +LLVMBool LLVMIsOpaqueStruct(LLVMTypeRef StructTy); + +/** + * Determine whether a structure is literal. + * + * @see llvm::StructType::isLiteral() + */ +LLVMBool LLVMIsLiteralStruct(LLVMTypeRef StructTy); + +/** + * @} + */ + +/** + * @defgroup LLVMCCoreTypeSequential Sequential Types + * + * Sequential types represents "arrays" of types. This is a super class + * for array, vector, and pointer types. + * + * @{ + */ + +/** + * Obtain the type of elements within a sequential type. + * + * This works on array, vector, and pointer types. + * + * @see llvm::SequentialType::getElementType() + */ +LLVMTypeRef LLVMGetElementType(LLVMTypeRef Ty); + +/** + * Returns type's subtypes + * + * @see llvm::Type::subtypes() + */ +void LLVMGetSubtypes(LLVMTypeRef Tp, LLVMTypeRef *Arr); + +/** + * Return the number of types in the derived type. + * + * @see llvm::Type::getNumContainedTypes() + */ +unsigned LLVMGetNumContainedTypes(LLVMTypeRef Tp); + +/** + * Create a fixed size array type that refers to a specific type. + * + * The created type will exist in the context that its element type + * exists in. + * + * @see llvm::ArrayType::get() + */ +LLVMTypeRef LLVMArrayType(LLVMTypeRef ElementType, unsigned ElementCount); + +/** + * Obtain the length of an array type. + * + * This only works on types that represent arrays. + * + * @see llvm::ArrayType::getNumElements() + */ +unsigned LLVMGetArrayLength(LLVMTypeRef ArrayTy); + +/** + * Create a pointer type that points to a defined type. + * + * The created type will exist in the context that its pointee type + * exists in. + * + * @see llvm::PointerType::get() + */ +LLVMTypeRef LLVMPointerType(LLVMTypeRef ElementType, unsigned AddressSpace); + +/** + * Obtain the address space of a pointer type. + * + * This only works on types that represent pointers. + * + * @see llvm::PointerType::getAddressSpace() + */ +unsigned LLVMGetPointerAddressSpace(LLVMTypeRef PointerTy); + +/** + * Create a vector type that contains a defined type and has a specific + * number of elements. + * + * The created type will exist in the context thats its element type + * exists in. + * + * @see llvm::VectorType::get() + */ +LLVMTypeRef LLVMVectorType(LLVMTypeRef ElementType, unsigned ElementCount); + +/** + * Obtain the number of elements in a vector type. + * + * This only works on types that represent vectors. + * + * @see llvm::VectorType::getNumElements() + */ +unsigned LLVMGetVectorSize(LLVMTypeRef VectorTy); + +/** + * @} + */ + +/** + * @defgroup LLVMCCoreTypeOther Other Types + * + * @{ + */ + +/** + * Create a void type in a context. + */ +LLVMTypeRef LLVMVoidTypeInContext(LLVMContextRef C); + +/** + * Create a label type in a context. + */ +LLVMTypeRef LLVMLabelTypeInContext(LLVMContextRef C); + +/** + * Create a X86 MMX type in a context. + */ +LLVMTypeRef LLVMX86MMXTypeInContext(LLVMContextRef C); + +/** + * Create a token type in a context. + */ +LLVMTypeRef LLVMTokenTypeInContext(LLVMContextRef C); + +/** + * Create a metadata type in a context. + */ +LLVMTypeRef LLVMMetadataTypeInContext(LLVMContextRef C); + +/** + * These are similar to the above functions except they operate on the + * global context. + */ +LLVMTypeRef LLVMVoidType(void); +LLVMTypeRef LLVMLabelType(void); +LLVMTypeRef LLVMX86MMXType(void); + +/** + * @} + */ + +/** + * @} + */ + +/** + * @defgroup LLVMCCoreValues Values + * + * The bulk of LLVM's object model consists of values, which comprise a very + * rich type hierarchy. + * + * LLVMValueRef essentially represents llvm::Value. There is a rich + * hierarchy of classes within this type. Depending on the instance + * obtained, not all APIs are available. + * + * Callers can determine the type of an LLVMValueRef by calling the + * LLVMIsA* family of functions (e.g. LLVMIsAArgument()). These + * functions are defined by a macro, so it isn't obvious which are + * available by looking at the Doxygen source code. Instead, look at the + * source definition of LLVM_FOR_EACH_VALUE_SUBCLASS and note the list + * of value names given. These value names also correspond to classes in + * the llvm::Value hierarchy. + * + * @{ + */ + +#define LLVM_FOR_EACH_VALUE_SUBCLASS(macro) \ + macro(Argument) \ + macro(BasicBlock) \ + macro(InlineAsm) \ + macro(User) \ + macro(Constant) \ + macro(BlockAddress) \ + macro(ConstantAggregateZero) \ + macro(ConstantArray) \ + macro(ConstantDataSequential) \ + macro(ConstantDataArray) \ + macro(ConstantDataVector) \ + macro(ConstantExpr) \ + macro(ConstantFP) \ + macro(ConstantInt) \ + macro(ConstantPointerNull) \ + macro(ConstantStruct) \ + macro(ConstantTokenNone) \ + macro(ConstantVector) \ + macro(GlobalValue) \ + macro(GlobalAlias) \ + macro(GlobalIFunc) \ + macro(GlobalObject) \ + macro(Function) \ + macro(GlobalVariable) \ + macro(UndefValue) \ + macro(Instruction) \ + macro(UnaryOperator) \ + macro(BinaryOperator) \ + macro(CallInst) \ + macro(IntrinsicInst) \ + macro(DbgInfoIntrinsic) \ + macro(DbgVariableIntrinsic) \ + macro(DbgDeclareInst) \ + macro(DbgLabelInst) \ + macro(MemIntrinsic) \ + macro(MemCpyInst) \ + macro(MemMoveInst) \ + macro(MemSetInst) \ + macro(CmpInst) \ + macro(FCmpInst) \ + macro(ICmpInst) \ + macro(ExtractElementInst) \ + macro(GetElementPtrInst) \ + macro(InsertElementInst) \ + macro(InsertValueInst) \ + macro(LandingPadInst) \ + macro(PHINode) \ + macro(SelectInst) \ + macro(ShuffleVectorInst) \ + macro(StoreInst) \ + macro(BranchInst) \ + macro(IndirectBrInst) \ + macro(InvokeInst) \ + macro(ReturnInst) \ + macro(SwitchInst) \ + macro(UnreachableInst) \ + macro(ResumeInst) \ + macro(CleanupReturnInst) \ + macro(CatchReturnInst) \ + macro(CatchSwitchInst) \ + macro(CallBrInst) \ + macro(FuncletPadInst) \ + macro(CatchPadInst) \ + macro(CleanupPadInst) \ + macro(UnaryInstruction) \ + macro(AllocaInst) \ + macro(CastInst) \ + macro(AddrSpaceCastInst) \ + macro(BitCastInst) \ + macro(FPExtInst) \ + macro(FPToSIInst) \ + macro(FPToUIInst) \ + macro(FPTruncInst) \ + macro(IntToPtrInst) \ + macro(PtrToIntInst) \ + macro(SExtInst) \ + macro(SIToFPInst) \ + macro(TruncInst) \ + macro(UIToFPInst) \ + macro(ZExtInst) \ + macro(ExtractValueInst) \ + macro(LoadInst) \ + macro(VAArgInst) \ + macro(FreezeInst) \ + macro(AtomicCmpXchgInst) \ + macro(AtomicRMWInst) \ + macro(FenceInst) + +/** + * @defgroup LLVMCCoreValueGeneral General APIs + * + * Functions in this section work on all LLVMValueRef instances, + * regardless of their sub-type. They correspond to functions available + * on llvm::Value. + * + * @{ + */ + +/** + * Obtain the type of a value. + * + * @see llvm::Value::getType() + */ +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. + * + * @see llvm::Value::getName() + */ +const char *LLVMGetValueName2(LLVMValueRef Val, size_t *Length); + +/** + * Set the string name of a value. + * + * @see llvm::Value::setName() + */ +void LLVMSetValueName2(LLVMValueRef Val, const char *Name, size_t NameLen); + +/** + * Dump a representation of a value to stderr. + * + * @see llvm::Value::dump() + */ +void LLVMDumpValue(LLVMValueRef Val); + +/** + * Return a string representation of the value. Use + * LLVMDisposeMessage to free the string. + * + * @see llvm::Value::print() + */ +char *LLVMPrintValueToString(LLVMValueRef Val); + +/** + * Replace all uses of a value with another one. + * + * @see llvm::Value::replaceAllUsesWith() + */ +void LLVMReplaceAllUsesWith(LLVMValueRef OldVal, LLVMValueRef NewVal); + +/** + * Determine whether the specified value instance is constant. + */ +LLVMBool LLVMIsConstant(LLVMValueRef Val); + +/** + * Determine whether a value instance is undefined. + */ +LLVMBool LLVMIsUndef(LLVMValueRef Val); + +/** + * Convert value instances between types. + * + * Internally, an LLVMValueRef is "pinned" to a specific type. This + * series of functions allows you to cast an instance to a specific + * type. + * + * If the cast is not valid for the specified type, NULL is returned. + * + * @see llvm::dyn_cast_or_null<> + */ +#define LLVM_DECLARE_VALUE_CAST(name) \ + LLVMValueRef LLVMIsA##name(LLVMValueRef Val); +LLVM_FOR_EACH_VALUE_SUBCLASS(LLVM_DECLARE_VALUE_CAST) + +LLVMValueRef LLVMIsAMDNode(LLVMValueRef Val); +LLVMValueRef LLVMIsAMDString(LLVMValueRef Val); + +/** Deprecated: Use LLVMGetValueName2 instead. */ +const char *LLVMGetValueName(LLVMValueRef Val); +/** Deprecated: Use LLVMSetValueName2 instead. */ +void LLVMSetValueName(LLVMValueRef Val, const char *Name); + +/** + * @} + */ + +/** + * @defgroup LLVMCCoreValueUses Usage + * + * This module defines functions that allow you to inspect the uses of a + * LLVMValueRef. + * + * It is possible to obtain an LLVMUseRef for any LLVMValueRef instance. + * Each LLVMUseRef (which corresponds to a llvm::Use instance) holds a + * llvm::User and llvm::Value. + * + * @{ + */ + +/** + * Obtain the first use of a value. + * + * Uses are obtained in an iterator fashion. First, call this function + * to obtain a reference to the first use. Then, call LLVMGetNextUse() + * on that instance and all subsequently obtained instances until + * LLVMGetNextUse() returns NULL. + * + * @see llvm::Value::use_begin() + */ +LLVMUseRef LLVMGetFirstUse(LLVMValueRef Val); + +/** + * Obtain the next use of a value. + * + * This effectively advances the iterator. It returns NULL if you are on + * the final use and no more are available. + */ +LLVMUseRef LLVMGetNextUse(LLVMUseRef U); + +/** + * Obtain the user value for a user. + * + * The returned value corresponds to a llvm::User type. + * + * @see llvm::Use::getUser() + */ +LLVMValueRef LLVMGetUser(LLVMUseRef U); + +/** + * Obtain the value this use corresponds to. + * + * @see llvm::Use::get(). + */ +LLVMValueRef LLVMGetUsedValue(LLVMUseRef U); + +/** + * @} + */ + +/** + * @defgroup LLVMCCoreValueUser User value + * + * Function in this group pertain to LLVMValueRef instances that descent + * from llvm::User. This includes constants, instructions, and + * operators. + * + * @{ + */ + +/** + * Obtain an operand at a specific index in a llvm::User value. + * + * @see llvm::User::getOperand() + */ +LLVMValueRef LLVMGetOperand(LLVMValueRef Val, unsigned Index); + +/** + * Obtain the use of an operand at a specific index in a llvm::User value. + * + * @see llvm::User::getOperandUse() + */ +LLVMUseRef LLVMGetOperandUse(LLVMValueRef Val, unsigned Index); + +/** + * Set an operand at a specific index in a llvm::User value. + * + * @see llvm::User::setOperand() + */ +void LLVMSetOperand(LLVMValueRef User, unsigned Index, LLVMValueRef Val); + +/** + * Obtain the number of operands in a llvm::User value. + * + * @see llvm::User::getNumOperands() + */ +int LLVMGetNumOperands(LLVMValueRef Val); + +/** + * @} + */ + +/** + * @defgroup LLVMCCoreValueConstant Constants + * + * This section contains APIs for interacting with LLVMValueRef that + * correspond to llvm::Constant instances. + * + * These functions will work for any LLVMValueRef in the llvm::Constant + * class hierarchy. + * + * @{ + */ + +/** + * Obtain a constant value referring to the null instance of a type. + * + * @see llvm::Constant::getNullValue() + */ +LLVMValueRef LLVMConstNull(LLVMTypeRef Ty); /* all zeroes */ + +/** + * Obtain a constant value referring to the instance of a type + * consisting of all ones. + * + * This is only valid for integer types. + * + * @see llvm::Constant::getAllOnesValue() + */ +LLVMValueRef LLVMConstAllOnes(LLVMTypeRef Ty); + +/** + * Obtain a constant value referring to an undefined value of a type. + * + * @see llvm::UndefValue::get() + */ +LLVMValueRef LLVMGetUndef(LLVMTypeRef Ty); + +/** + * Determine whether a value instance is null. + * + * @see llvm::Constant::isNullValue() + */ +LLVMBool LLVMIsNull(LLVMValueRef Val); + +/** + * Obtain a constant that is a constant pointer pointing to NULL for a + * specified type. + */ +LLVMValueRef LLVMConstPointerNull(LLVMTypeRef Ty); + +/** + * @defgroup LLVMCCoreValueConstantScalar Scalar constants + * + * Functions in this group model LLVMValueRef instances that correspond + * to constants referring to scalar types. + * + * For integer types, the LLVMTypeRef parameter should correspond to a + * llvm::IntegerType instance and the returned LLVMValueRef will + * correspond to a llvm::ConstantInt. + * + * For floating point types, the LLVMTypeRef returned corresponds to a + * llvm::ConstantFP. + * + * @{ + */ + +/** + * Obtain a constant value for an integer type. + * + * The returned value corresponds to a llvm::ConstantInt. + * + * @see llvm::ConstantInt::get() + * + * @param IntTy Integer type to obtain value of. + * @param N The value the returned instance should refer to. + * @param SignExtend Whether to sign extend the produced value. + */ +LLVMValueRef LLVMConstInt(LLVMTypeRef IntTy, unsigned long long N, + LLVMBool SignExtend); + +/** + * Obtain a constant value for an integer of arbitrary precision. + * + * @see llvm::ConstantInt::get() + */ +LLVMValueRef LLVMConstIntOfArbitraryPrecision(LLVMTypeRef IntTy, + unsigned NumWords, + const uint64_t Words[]); + +/** + * Obtain a constant value for an integer parsed from a string. + * + * A similar API, LLVMConstIntOfStringAndSize is also available. If the + * string's length is available, it is preferred to call that function + * instead. + * + * @see llvm::ConstantInt::get() + */ +LLVMValueRef LLVMConstIntOfString(LLVMTypeRef IntTy, const char *Text, + uint8_t Radix); + +/** + * Obtain a constant value for an integer parsed from a string with + * specified length. + * + * @see llvm::ConstantInt::get() + */ +LLVMValueRef LLVMConstIntOfStringAndSize(LLVMTypeRef IntTy, const char *Text, + unsigned SLen, uint8_t Radix); + +/** + * Obtain a constant value referring to a double floating point value. + */ +LLVMValueRef LLVMConstReal(LLVMTypeRef RealTy, double N); + +/** + * Obtain a constant for a floating point value parsed from a string. + * + * A similar API, LLVMConstRealOfStringAndSize is also available. It + * should be used if the input string's length is known. + */ +LLVMValueRef LLVMConstRealOfString(LLVMTypeRef RealTy, const char *Text); + +/** + * Obtain a constant for a floating point value parsed from a string. + */ +LLVMValueRef LLVMConstRealOfStringAndSize(LLVMTypeRef RealTy, const char *Text, + unsigned SLen); + +/** + * Obtain the zero extended value for an integer constant value. + * + * @see llvm::ConstantInt::getZExtValue() + */ +unsigned long long LLVMConstIntGetZExtValue(LLVMValueRef ConstantVal); + +/** + * Obtain the sign extended value for an integer constant value. + * + * @see llvm::ConstantInt::getSExtValue() + */ +long long LLVMConstIntGetSExtValue(LLVMValueRef ConstantVal); + +/** + * Obtain the double value for an floating point constant value. + * losesInfo indicates if some precision was lost in the conversion. + * + * @see llvm::ConstantFP::getDoubleValue + */ +double LLVMConstRealGetDouble(LLVMValueRef ConstantVal, LLVMBool *losesInfo); + +/** + * @} + */ + +/** + * @defgroup LLVMCCoreValueConstantComposite Composite Constants + * + * Functions in this group operate on composite constants. + * + * @{ + */ + +/** + * Create a ConstantDataSequential and initialize it with a string. + * + * @see llvm::ConstantDataArray::getString() + */ +LLVMValueRef LLVMConstStringInContext(LLVMContextRef C, const char *Str, + unsigned Length, LLVMBool DontNullTerminate); + +/** + * Create a ConstantDataSequential with string content in the global context. + * + * This is the same as LLVMConstStringInContext except it operates on the + * global context. + * + * @see LLVMConstStringInContext() + * @see llvm::ConstantDataArray::getString() + */ +LLVMValueRef LLVMConstString(const char *Str, unsigned Length, + LLVMBool DontNullTerminate); + +/** + * Returns true if the specified constant is an array of i8. + * + * @see ConstantDataSequential::getAsString() + */ +LLVMBool LLVMIsConstantString(LLVMValueRef c); + +/** + * Get the given constant data sequential as a string. + * + * @see ConstantDataSequential::getAsString() + */ +const char *LLVMGetAsString(LLVMValueRef c, size_t *Length); + +/** + * Create an anonymous ConstantStruct with the specified values. + * + * @see llvm::ConstantStruct::getAnon() + */ +LLVMValueRef LLVMConstStructInContext(LLVMContextRef C, + LLVMValueRef *ConstantVals, + unsigned Count, LLVMBool Packed); + +/** + * Create a ConstantStruct in the global Context. + * + * This is the same as LLVMConstStructInContext except it operates on the + * global Context. + * + * @see LLVMConstStructInContext() + */ +LLVMValueRef LLVMConstStruct(LLVMValueRef *ConstantVals, unsigned Count, + LLVMBool Packed); + +/** + * Create a ConstantArray from values. + * + * @see llvm::ConstantArray::get() + */ +LLVMValueRef LLVMConstArray(LLVMTypeRef ElementTy, + LLVMValueRef *ConstantVals, unsigned Length); + +/** + * Create a non-anonymous ConstantStruct from values. + * + * @see llvm::ConstantStruct::get() + */ +LLVMValueRef LLVMConstNamedStruct(LLVMTypeRef StructTy, + LLVMValueRef *ConstantVals, + unsigned Count); + +/** + * Get an element at specified index as a constant. + * + * @see ConstantDataSequential::getElementAsConstant() + */ +LLVMValueRef LLVMGetElementAsConstant(LLVMValueRef C, unsigned idx); + +/** + * Create a ConstantVector from values. + * + * @see llvm::ConstantVector::get() + */ +LLVMValueRef LLVMConstVector(LLVMValueRef *ScalarConstantVals, unsigned Size); + +/** + * @} + */ + +/** + * @defgroup LLVMCCoreValueConstantExpressions Constant Expressions + * + * Functions in this group correspond to APIs on llvm::ConstantExpr. + * + * @see llvm::ConstantExpr. + * + * @{ + */ +LLVMOpcode LLVMGetConstOpcode(LLVMValueRef ConstantVal); +LLVMValueRef LLVMAlignOf(LLVMTypeRef Ty); +LLVMValueRef LLVMSizeOf(LLVMTypeRef Ty); +LLVMValueRef LLVMConstNeg(LLVMValueRef ConstantVal); +LLVMValueRef LLVMConstNSWNeg(LLVMValueRef ConstantVal); +LLVMValueRef LLVMConstNUWNeg(LLVMValueRef ConstantVal); +LLVMValueRef LLVMConstFNeg(LLVMValueRef ConstantVal); +LLVMValueRef LLVMConstNot(LLVMValueRef ConstantVal); +LLVMValueRef LLVMConstAdd(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstNSWAdd(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstNUWAdd(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstFAdd(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstSub(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstNSWSub(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstNUWSub(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstFSub(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstMul(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstNSWMul(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstNUWMul(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstFMul(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstUDiv(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstExactUDiv(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstSDiv(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstExactSDiv(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstFDiv(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstURem(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstSRem(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstFRem(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstAnd(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstOr(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstXor(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstICmp(LLVMIntPredicate Predicate, + LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstFCmp(LLVMRealPredicate Predicate, + LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstShl(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstLShr(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstAShr(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstGEP(LLVMValueRef ConstantVal, + LLVMValueRef *ConstantIndices, unsigned NumIndices); +LLVMValueRef LLVMConstGEP2(LLVMTypeRef Ty, LLVMValueRef ConstantVal, + LLVMValueRef *ConstantIndices, unsigned NumIndices); +LLVMValueRef LLVMConstInBoundsGEP(LLVMValueRef ConstantVal, + LLVMValueRef *ConstantIndices, + unsigned NumIndices); +LLVMValueRef LLVMConstInBoundsGEP2(LLVMTypeRef Ty, LLVMValueRef ConstantVal, + LLVMValueRef *ConstantIndices, + unsigned NumIndices); +LLVMValueRef LLVMConstTrunc(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstSExt(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstZExt(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstFPTrunc(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstFPExt(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstUIToFP(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstSIToFP(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstFPToUI(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstFPToSI(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstPtrToInt(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstIntToPtr(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstBitCast(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstAddrSpaceCast(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstZExtOrBitCast(LLVMValueRef ConstantVal, + LLVMTypeRef ToType); +LLVMValueRef LLVMConstSExtOrBitCast(LLVMValueRef ConstantVal, + LLVMTypeRef ToType); +LLVMValueRef LLVMConstTruncOrBitCast(LLVMValueRef ConstantVal, + LLVMTypeRef ToType); +LLVMValueRef LLVMConstPointerCast(LLVMValueRef ConstantVal, + LLVMTypeRef ToType); +LLVMValueRef LLVMConstIntCast(LLVMValueRef ConstantVal, LLVMTypeRef ToType, + LLVMBool isSigned); +LLVMValueRef LLVMConstFPCast(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstSelect(LLVMValueRef ConstantCondition, + LLVMValueRef ConstantIfTrue, + LLVMValueRef ConstantIfFalse); +LLVMValueRef LLVMConstExtractElement(LLVMValueRef VectorConstant, + LLVMValueRef IndexConstant); +LLVMValueRef LLVMConstInsertElement(LLVMValueRef VectorConstant, + LLVMValueRef ElementValueConstant, + LLVMValueRef IndexConstant); +LLVMValueRef LLVMConstShuffleVector(LLVMValueRef VectorAConstant, + LLVMValueRef VectorBConstant, + LLVMValueRef MaskConstant); +LLVMValueRef LLVMConstExtractValue(LLVMValueRef AggConstant, unsigned *IdxList, + unsigned NumIdx); +LLVMValueRef LLVMConstInsertValue(LLVMValueRef AggConstant, + LLVMValueRef ElementValueConstant, + unsigned *IdxList, unsigned NumIdx); +LLVMValueRef LLVMBlockAddress(LLVMValueRef F, LLVMBasicBlockRef BB); + +/** Deprecated: Use LLVMGetInlineAsm instead. */ +LLVMValueRef LLVMConstInlineAsm(LLVMTypeRef Ty, + const char *AsmString, const char *Constraints, + LLVMBool HasSideEffects, LLVMBool IsAlignStack); + +/** + * @} + */ + +/** + * @defgroup LLVMCCoreValueConstantGlobals Global Values + * + * This group contains functions that operate on global values. Functions in + * this group relate to functions in the llvm::GlobalValue class tree. + * + * @see llvm::GlobalValue + * + * @{ + */ + +LLVMModuleRef LLVMGetGlobalParent(LLVMValueRef Global); +LLVMBool LLVMIsDeclaration(LLVMValueRef Global); +LLVMLinkage LLVMGetLinkage(LLVMValueRef Global); +void LLVMSetLinkage(LLVMValueRef Global, LLVMLinkage Linkage); +const char *LLVMGetSection(LLVMValueRef Global); +void LLVMSetSection(LLVMValueRef Global, const char *Section); +LLVMVisibility LLVMGetVisibility(LLVMValueRef Global); +void LLVMSetVisibility(LLVMValueRef Global, LLVMVisibility Viz); +LLVMDLLStorageClass LLVMGetDLLStorageClass(LLVMValueRef Global); +void LLVMSetDLLStorageClass(LLVMValueRef Global, LLVMDLLStorageClass Class); +LLVMUnnamedAddr LLVMGetUnnamedAddress(LLVMValueRef Global); +void LLVMSetUnnamedAddress(LLVMValueRef Global, LLVMUnnamedAddr UnnamedAddr); + +/** + * Returns the "value type" of a global value. This differs from the formal + * type of a global value which is always a pointer type. + * + * @see llvm::GlobalValue::getValueType() + */ +LLVMTypeRef LLVMGlobalGetValueType(LLVMValueRef Global); + +/** Deprecated: Use LLVMGetUnnamedAddress instead. */ +LLVMBool LLVMHasUnnamedAddr(LLVMValueRef Global); +/** Deprecated: Use LLVMSetUnnamedAddress instead. */ +void LLVMSetUnnamedAddr(LLVMValueRef Global, LLVMBool HasUnnamedAddr); + +/** + * @defgroup LLVMCCoreValueWithAlignment Values with alignment + * + * Functions in this group only apply to values with alignment, i.e. + * global variables, load and store instructions. + */ + +/** + * Obtain the preferred alignment of the value. + * @see llvm::AllocaInst::getAlignment() + * @see llvm::LoadInst::getAlignment() + * @see llvm::StoreInst::getAlignment() + * @see llvm::GlobalValue::getAlignment() + */ +unsigned LLVMGetAlignment(LLVMValueRef V); + +/** + * Set the preferred alignment of the value. + * @see llvm::AllocaInst::setAlignment() + * @see llvm::LoadInst::setAlignment() + * @see llvm::StoreInst::setAlignment() + * @see llvm::GlobalValue::setAlignment() + */ +void LLVMSetAlignment(LLVMValueRef V, unsigned Bytes); + +/** + * Sets a metadata attachment, erasing the existing metadata attachment if + * it already exists for the given kind. + * + * @see llvm::GlobalObject::setMetadata() + */ +void LLVMGlobalSetMetadata(LLVMValueRef Global, unsigned Kind, + LLVMMetadataRef MD); + +/** + * Erases a metadata attachment of the given kind if it exists. + * + * @see llvm::GlobalObject::eraseMetadata() + */ +void LLVMGlobalEraseMetadata(LLVMValueRef Global, unsigned Kind); + +/** + * Removes all metadata attachments from this value. + * + * @see llvm::GlobalObject::clearMetadata() + */ +void LLVMGlobalClearMetadata(LLVMValueRef Global); + +/** + * Retrieves an array of metadata entries representing the metadata attached to + * this value. The caller is responsible for freeing this array by calling + * \c LLVMDisposeValueMetadataEntries. + * + * @see llvm::GlobalObject::getAllMetadata() + */ +LLVMValueMetadataEntry *LLVMGlobalCopyAllMetadata(LLVMValueRef Value, + size_t *NumEntries); + +/** + * Destroys value metadata entries. + */ +void LLVMDisposeValueMetadataEntries(LLVMValueMetadataEntry *Entries); + +/** + * Returns the kind of a value metadata entry at a specific index. + */ +unsigned LLVMValueMetadataEntriesGetKind(LLVMValueMetadataEntry *Entries, + unsigned Index); + +/** + * Returns the underlying metadata node of a value metadata entry at a + * specific index. + */ +LLVMMetadataRef +LLVMValueMetadataEntriesGetMetadata(LLVMValueMetadataEntry *Entries, + unsigned Index); + +/** + * @} + */ + +/** + * @defgroup LLVMCoreValueConstantGlobalVariable Global Variables + * + * This group contains functions that operate on global variable values. + * + * @see llvm::GlobalVariable + * + * @{ + */ +LLVMValueRef LLVMAddGlobal(LLVMModuleRef M, LLVMTypeRef Ty, const char *Name); +LLVMValueRef LLVMAddGlobalInAddressSpace(LLVMModuleRef M, LLVMTypeRef Ty, + const char *Name, + unsigned AddressSpace); +LLVMValueRef LLVMGetNamedGlobal(LLVMModuleRef M, const char *Name); +LLVMValueRef LLVMGetFirstGlobal(LLVMModuleRef M); +LLVMValueRef LLVMGetLastGlobal(LLVMModuleRef M); +LLVMValueRef LLVMGetNextGlobal(LLVMValueRef GlobalVar); +LLVMValueRef LLVMGetPreviousGlobal(LLVMValueRef GlobalVar); +void LLVMDeleteGlobal(LLVMValueRef GlobalVar); +LLVMValueRef LLVMGetInitializer(LLVMValueRef GlobalVar); +void LLVMSetInitializer(LLVMValueRef GlobalVar, LLVMValueRef ConstantVal); +LLVMBool LLVMIsThreadLocal(LLVMValueRef GlobalVar); +void LLVMSetThreadLocal(LLVMValueRef GlobalVar, LLVMBool IsThreadLocal); +LLVMBool LLVMIsGlobalConstant(LLVMValueRef GlobalVar); +void LLVMSetGlobalConstant(LLVMValueRef GlobalVar, LLVMBool IsConstant); +LLVMThreadLocalMode LLVMGetThreadLocalMode(LLVMValueRef GlobalVar); +void LLVMSetThreadLocalMode(LLVMValueRef GlobalVar, LLVMThreadLocalMode Mode); +LLVMBool LLVMIsExternallyInitialized(LLVMValueRef GlobalVar); +void LLVMSetExternallyInitialized(LLVMValueRef GlobalVar, LLVMBool IsExtInit); + +/** + * @} + */ + +/** + * @defgroup LLVMCoreValueConstantGlobalAlias Global Aliases + * + * This group contains function that operate on global alias values. + * + * @see llvm::GlobalAlias + * + * @{ + */ +LLVMValueRef LLVMAddAlias(LLVMModuleRef M, LLVMTypeRef Ty, LLVMValueRef Aliasee, + const char *Name); + +/** + * Obtain a GlobalAlias value from a Module by its name. + * + * The returned value corresponds to a llvm::GlobalAlias value. + * + * @see llvm::Module::getNamedAlias() + */ +LLVMValueRef LLVMGetNamedGlobalAlias(LLVMModuleRef M, + const char *Name, size_t NameLen); + +/** + * Obtain an iterator to the first GlobalAlias in a Module. + * + * @see llvm::Module::alias_begin() + */ +LLVMValueRef LLVMGetFirstGlobalAlias(LLVMModuleRef M); + +/** + * Obtain an iterator to the last GlobalAlias in a Module. + * + * @see llvm::Module::alias_end() + */ +LLVMValueRef LLVMGetLastGlobalAlias(LLVMModuleRef M); + +/** + * Advance a GlobalAlias iterator to the next GlobalAlias. + * + * Returns NULL if the iterator was already at the end and there are no more + * global aliases. + */ +LLVMValueRef LLVMGetNextGlobalAlias(LLVMValueRef GA); + +/** + * Decrement a GlobalAlias iterator to the previous GlobalAlias. + * + * Returns NULL if the iterator was already at the beginning and there are + * no previous global aliases. + */ +LLVMValueRef LLVMGetPreviousGlobalAlias(LLVMValueRef GA); + +/** + * Retrieve the target value of an alias. + */ +LLVMValueRef LLVMAliasGetAliasee(LLVMValueRef Alias); + +/** + * Set the target value of an alias. + */ +void LLVMAliasSetAliasee(LLVMValueRef Alias, LLVMValueRef Aliasee); + +/** + * @} + */ + +/** + * @defgroup LLVMCCoreValueFunction Function values + * + * Functions in this group operate on LLVMValueRef instances that + * correspond to llvm::Function instances. + * + * @see llvm::Function + * + * @{ + */ + +/** + * Remove a function from its containing module and deletes it. + * + * @see llvm::Function::eraseFromParent() + */ +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. + * + * @see llvm::Function::getPersonalityFn() + */ +LLVMValueRef LLVMGetPersonalityFn(LLVMValueRef Fn); + +/** + * Set the personality function attached to the function. + * + * @see llvm::Function::setPersonalityFn() + */ +void LLVMSetPersonalityFn(LLVMValueRef Fn, LLVMValueRef PersonalityFn); + +/** + * Obtain the intrinsic ID number which matches the given function name. + * + * @see llvm::Function::lookupIntrinsicID() + */ +unsigned LLVMLookupIntrinsicID(const char *Name, size_t NameLen); + +/** + * Obtain the ID number from a function instance. + * + * @see llvm::Function::getIntrinsicID() + */ +unsigned LLVMGetIntrinsicID(LLVMValueRef Fn); + +/** + * Create or insert the declaration of an intrinsic. For overloaded intrinsics, + * parameter types must be provided to uniquely identify an overload. + * + * @see llvm::Intrinsic::getDeclaration() + */ +LLVMValueRef LLVMGetIntrinsicDeclaration(LLVMModuleRef Mod, + unsigned ID, + LLVMTypeRef *ParamTypes, + size_t ParamCount); + +/** + * Retrieves the type of an intrinsic. For overloaded intrinsics, parameter + * types must be provided to uniquely identify an overload. + * + * @see llvm::Intrinsic::getType() + */ +LLVMTypeRef LLVMIntrinsicGetType(LLVMContextRef Ctx, unsigned ID, + LLVMTypeRef *ParamTypes, size_t ParamCount); + +/** + * Retrieves the name of an intrinsic. + * + * @see llvm::Intrinsic::getName() + */ +const char *LLVMIntrinsicGetName(unsigned ID, size_t *NameLength); + +/** + * Copies the name of an overloaded intrinsic identified by a given list of + * parameter types. + * + * Unlike LLVMIntrinsicGetName, the caller is responsible for freeing the + * returned string. + * + * @see llvm::Intrinsic::getName() + */ +const char *LLVMIntrinsicCopyOverloadedName(unsigned ID, + LLVMTypeRef *ParamTypes, + size_t ParamCount, + size_t *NameLength); + +/** + * Obtain if the intrinsic identified by the given ID is overloaded. + * + * @see llvm::Intrinsic::isOverloaded() + */ +LLVMBool LLVMIntrinsicIsOverloaded(unsigned ID); + +/** + * Obtain the calling function of a function. + * + * The returned value corresponds to the LLVMCallConv enumeration. + * + * @see llvm::Function::getCallingConv() + */ +unsigned LLVMGetFunctionCallConv(LLVMValueRef Fn); + +/** + * Set the calling convention of a function. + * + * @see llvm::Function::setCallingConv() + * + * @param Fn Function to operate on + * @param CC LLVMCallConv to set calling convention to + */ +void LLVMSetFunctionCallConv(LLVMValueRef Fn, unsigned CC); + +/** + * Obtain the name of the garbage collector to use during code + * generation. + * + * @see llvm::Function::getGC() + */ +const char *LLVMGetGC(LLVMValueRef Fn); + +/** + * Define the garbage collector to use during code generation. + * + * @see llvm::Function::setGC() + */ +void LLVMSetGC(LLVMValueRef Fn, const char *Name); + +/** + * Add an attribute to a function. + * + * @see llvm::Function::addAttribute() + */ +void LLVMAddAttributeAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx, + LLVMAttributeRef A); +unsigned LLVMGetAttributeCountAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx); +void LLVMGetAttributesAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx, + LLVMAttributeRef *Attrs); +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() + */ +void LLVMAddTargetDependentFunctionAttr(LLVMValueRef Fn, const char *A, + const char *V); + +/** + * @defgroup LLVMCCoreValueFunctionParameters Function Parameters + * + * Functions in this group relate to arguments/parameters on functions. + * + * Functions in this group expect LLVMValueRef instances that correspond + * to llvm::Function instances. + * + * @{ + */ + +/** + * Obtain the number of parameters in a function. + * + * @see llvm::Function::arg_size() + */ +unsigned LLVMCountParams(LLVMValueRef Fn); + +/** + * Obtain the parameters in a function. + * + * The takes a pointer to a pre-allocated array of LLVMValueRef that is + * at least LLVMCountParams() long. This array will be filled with + * LLVMValueRef instances which correspond to the parameters the + * function receives. Each LLVMValueRef corresponds to a llvm::Argument + * instance. + * + * @see llvm::Function::arg_begin() + */ +void LLVMGetParams(LLVMValueRef Fn, LLVMValueRef *Params); + +/** + * Obtain the parameter at the specified index. + * + * Parameters are indexed from 0. + * + * @see llvm::Function::arg_begin() + */ +LLVMValueRef LLVMGetParam(LLVMValueRef Fn, unsigned Index); + +/** + * Obtain the function to which this argument belongs. + * + * Unlike other functions in this group, this one takes an LLVMValueRef + * that corresponds to a llvm::Attribute. + * + * The returned LLVMValueRef is the llvm::Function to which this + * argument belongs. + */ +LLVMValueRef LLVMGetParamParent(LLVMValueRef Inst); + +/** + * Obtain the first parameter to a function. + * + * @see llvm::Function::arg_begin() + */ +LLVMValueRef LLVMGetFirstParam(LLVMValueRef Fn); + +/** + * Obtain the last parameter to a function. + * + * @see llvm::Function::arg_end() + */ +LLVMValueRef LLVMGetLastParam(LLVMValueRef Fn); + +/** + * Obtain the next parameter to a function. + * + * This takes an LLVMValueRef obtained from LLVMGetFirstParam() (which is + * actually a wrapped iterator) and obtains the next parameter from the + * underlying iterator. + */ +LLVMValueRef LLVMGetNextParam(LLVMValueRef Arg); + +/** + * Obtain the previous parameter to a function. + * + * This is the opposite of LLVMGetNextParam(). + */ +LLVMValueRef LLVMGetPreviousParam(LLVMValueRef Arg); + +/** + * Set the alignment for a function parameter. + * + * @see llvm::Argument::addAttr() + * @see llvm::AttrBuilder::addAlignmentAttr() + */ +void LLVMSetParamAlignment(LLVMValueRef Arg, unsigned Align); + +/** + * @} + */ + +/** + * @defgroup LLVMCCoreValueGlobalIFunc IFuncs + * + * Functions in this group relate to indirect functions. + * + * Functions in this group expect LLVMValueRef instances that correspond + * to llvm::GlobalIFunc instances. + * + * @{ + */ + +/** + * Add a global indirect function to a module under a specified name. + * + * @see llvm::GlobalIFunc::create() + */ +LLVMValueRef LLVMAddGlobalIFunc(LLVMModuleRef M, + const char *Name, size_t NameLen, + LLVMTypeRef Ty, unsigned AddrSpace, + LLVMValueRef Resolver); + +/** + * Obtain a GlobalIFunc value from a Module by its name. + * + * The returned value corresponds to a llvm::GlobalIFunc value. + * + * @see llvm::Module::getNamedIFunc() + */ +LLVMValueRef LLVMGetNamedGlobalIFunc(LLVMModuleRef M, + const char *Name, size_t NameLen); + +/** + * Obtain an iterator to the first GlobalIFunc in a Module. + * + * @see llvm::Module::ifunc_begin() + */ +LLVMValueRef LLVMGetFirstGlobalIFunc(LLVMModuleRef M); + +/** + * Obtain an iterator to the last GlobalIFunc in a Module. + * + * @see llvm::Module::ifunc_end() + */ +LLVMValueRef LLVMGetLastGlobalIFunc(LLVMModuleRef M); + +/** + * Advance a GlobalIFunc iterator to the next GlobalIFunc. + * + * Returns NULL if the iterator was already at the end and there are no more + * global aliases. + */ +LLVMValueRef LLVMGetNextGlobalIFunc(LLVMValueRef IFunc); + +/** + * Decrement a GlobalIFunc iterator to the previous GlobalIFunc. + * + * Returns NULL if the iterator was already at the beginning and there are + * no previous global aliases. + */ +LLVMValueRef LLVMGetPreviousGlobalIFunc(LLVMValueRef IFunc); + +/** + * Retrieves the resolver function associated with this indirect function, or + * NULL if it doesn't not exist. + * + * @see llvm::GlobalIFunc::getResolver() + */ +LLVMValueRef LLVMGetGlobalIFuncResolver(LLVMValueRef IFunc); + +/** + * Sets the resolver function associated with this indirect function. + * + * @see llvm::GlobalIFunc::setResolver() + */ +void LLVMSetGlobalIFuncResolver(LLVMValueRef IFunc, LLVMValueRef Resolver); + +/** + * Remove a global indirect function from its parent module and delete it. + * + * @see llvm::GlobalIFunc::eraseFromParent() + */ +void LLVMEraseGlobalIFunc(LLVMValueRef IFunc); + +/** + * Remove a global indirect function from its parent module. + * + * This unlinks the global indirect function from its containing module but + * keeps it alive. + * + * @see llvm::GlobalIFunc::removeFromParent() + */ +void LLVMRemoveGlobalIFunc(LLVMValueRef IFunc); + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @defgroup LLVMCCoreValueMetadata Metadata + * + * @{ + */ + +/** + * Create an MDString value from a given string value. + * + * The MDString value does not take ownership of the given string, it remains + * the responsibility of the caller to free it. + * + * @see llvm::MDString::get() + */ +LLVMMetadataRef LLVMMDStringInContext2(LLVMContextRef C, const char *Str, + size_t SLen); + +/** + * Create an MDNode value with the given array of operands. + * + * @see llvm::MDNode::get() + */ +LLVMMetadataRef LLVMMDNodeInContext2(LLVMContextRef C, LLVMMetadataRef *MDs, + size_t Count); + +/** + * Obtain a Metadata as a Value. + */ +LLVMValueRef LLVMMetadataAsValue(LLVMContextRef C, LLVMMetadataRef MD); + +/** + * Obtain a Value as a Metadata. + */ +LLVMMetadataRef LLVMValueAsMetadata(LLVMValueRef Val); + +/** + * Obtain the underlying string from a MDString value. + * + * @param V Instance to obtain string from. + * @param Length Memory address which will hold length of returned string. + * @return String data in MDString. + */ +const char *LLVMGetMDString(LLVMValueRef V, unsigned *Length); + +/** + * Obtain the number of operands from an MDNode value. + * + * @param V MDNode to get number of operands from. + * @return Number of operands of the MDNode. + */ +unsigned LLVMGetMDNodeNumOperands(LLVMValueRef V); + +/** + * Obtain the given MDNode's operands. + * + * The passed LLVMValueRef pointer should point to enough memory to hold all of + * the operands of the given MDNode (see LLVMGetMDNodeNumOperands) as + * LLVMValueRefs. This memory will be populated with the LLVMValueRefs of the + * MDNode's operands. + * + * @param V MDNode to get the operands from. + * @param Dest Destination array for operands. + */ +void LLVMGetMDNodeOperands(LLVMValueRef V, LLVMValueRef *Dest); + +/** Deprecated: Use LLVMMDStringInContext2 instead. */ +LLVMValueRef LLVMMDStringInContext(LLVMContextRef C, const char *Str, + unsigned SLen); +/** Deprecated: Use LLVMMDStringInContext2 instead. */ +LLVMValueRef LLVMMDString(const char *Str, unsigned SLen); +/** Deprecated: Use LLVMMDNodeInContext2 instead. */ +LLVMValueRef LLVMMDNodeInContext(LLVMContextRef C, LLVMValueRef *Vals, + unsigned Count); +/** Deprecated: Use LLVMMDNodeInContext2 instead. */ +LLVMValueRef LLVMMDNode(LLVMValueRef *Vals, unsigned Count); + +/** + * @} + */ + +/** + * @defgroup LLVMCCoreValueBasicBlock Basic Block + * + * A basic block represents a single entry single exit section of code. + * Basic blocks contain a list of instructions which form the body of + * the block. + * + * Basic blocks belong to functions. They have the type of label. + * + * Basic blocks are themselves values. However, the C API models them as + * LLVMBasicBlockRef. + * + * @see llvm::BasicBlock + * + * @{ + */ + +/** + * Convert a basic block instance to a value type. + */ +LLVMValueRef LLVMBasicBlockAsValue(LLVMBasicBlockRef BB); + +/** + * Determine whether an LLVMValueRef is itself a basic block. + */ +LLVMBool LLVMValueIsBasicBlock(LLVMValueRef Val); + +/** + * Convert an LLVMValueRef to an LLVMBasicBlockRef instance. + */ +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. + * + * @see llvm::BasicBlock::getParent() + */ +LLVMValueRef LLVMGetBasicBlockParent(LLVMBasicBlockRef BB); + +/** + * Obtain the terminator instruction for a basic block. + * + * If the basic block does not have a terminator (it is not well-formed + * if it doesn't), then NULL is returned. + * + * The returned LLVMValueRef corresponds to an llvm::Instruction. + * + * @see llvm::BasicBlock::getTerminator() + */ +LLVMValueRef LLVMGetBasicBlockTerminator(LLVMBasicBlockRef BB); + +/** + * Obtain the number of basic blocks in a function. + * + * @param Fn Function value to operate on. + */ +unsigned LLVMCountBasicBlocks(LLVMValueRef Fn); + +/** + * Obtain all of the basic blocks in a function. + * + * This operates on a function value. The BasicBlocks parameter is a + * pointer to a pre-allocated array of LLVMBasicBlockRef of at least + * LLVMCountBasicBlocks() in length. This array is populated with + * LLVMBasicBlockRef instances. + */ +void LLVMGetBasicBlocks(LLVMValueRef Fn, LLVMBasicBlockRef *BasicBlocks); + +/** + * Obtain the first basic block in a function. + * + * The returned basic block can be used as an iterator. You will likely + * eventually call into LLVMGetNextBasicBlock() with it. + * + * @see llvm::Function::begin() + */ +LLVMBasicBlockRef LLVMGetFirstBasicBlock(LLVMValueRef Fn); + +/** + * Obtain the last basic block in a function. + * + * @see llvm::Function::end() + */ +LLVMBasicBlockRef LLVMGetLastBasicBlock(LLVMValueRef Fn); + +/** + * Advance a basic block iterator. + */ +LLVMBasicBlockRef LLVMGetNextBasicBlock(LLVMBasicBlockRef BB); + +/** + * Go backwards in a basic block iterator. + */ +LLVMBasicBlockRef LLVMGetPreviousBasicBlock(LLVMBasicBlockRef BB); + +/** + * Obtain the basic block that corresponds to the entry point of a + * function. + * + * @see llvm::Function::getEntryBlock() + */ +LLVMBasicBlockRef LLVMGetEntryBasicBlock(LLVMValueRef Fn); + +/** + * Insert the given basic block after the insertion point of the given builder. + * + * The insertion point must be valid. + * + * @see llvm::Function::BasicBlockListType::insertAfter() + */ +void LLVMInsertExistingBasicBlockAfterInsertBlock(LLVMBuilderRef Builder, + LLVMBasicBlockRef BB); + +/** + * Append the given basic block to the basic block list of the given function. + * + * @see llvm::Function::BasicBlockListType::push_back() + */ +void LLVMAppendExistingBasicBlock(LLVMValueRef Fn, + LLVMBasicBlockRef BB); + +/** + * Create a new basic block without inserting it into a function. + * + * @see llvm::BasicBlock::Create() + */ +LLVMBasicBlockRef LLVMCreateBasicBlockInContext(LLVMContextRef C, + const char *Name); + +/** + * Append a basic block to the end of a function. + * + * @see llvm::BasicBlock::Create() + */ +LLVMBasicBlockRef LLVMAppendBasicBlockInContext(LLVMContextRef C, + LLVMValueRef Fn, + const char *Name); + +/** + * Append a basic block to the end of a function using the global + * context. + * + * @see llvm::BasicBlock::Create() + */ +LLVMBasicBlockRef LLVMAppendBasicBlock(LLVMValueRef Fn, const char *Name); + +/** + * Insert a basic block in a function before another basic block. + * + * The function to add to is determined by the function of the + * passed basic block. + * + * @see llvm::BasicBlock::Create() + */ +LLVMBasicBlockRef LLVMInsertBasicBlockInContext(LLVMContextRef C, + LLVMBasicBlockRef BB, + const char *Name); + +/** + * Insert a basic block in a function using the global context. + * + * @see llvm::BasicBlock::Create() + */ +LLVMBasicBlockRef LLVMInsertBasicBlock(LLVMBasicBlockRef InsertBeforeBB, + const char *Name); + +/** + * Remove a basic block from a function and delete it. + * + * This deletes the basic block from its containing function and deletes + * the basic block itself. + * + * @see llvm::BasicBlock::eraseFromParent() + */ +void LLVMDeleteBasicBlock(LLVMBasicBlockRef BB); + +/** + * Remove a basic block from a function. + * + * This deletes the basic block from its containing function but keep + * the basic block alive. + * + * @see llvm::BasicBlock::removeFromParent() + */ +void LLVMRemoveBasicBlockFromParent(LLVMBasicBlockRef BB); + +/** + * Move a basic block to before another one. + * + * @see llvm::BasicBlock::moveBefore() + */ +void LLVMMoveBasicBlockBefore(LLVMBasicBlockRef BB, LLVMBasicBlockRef MovePos); + +/** + * Move a basic block to after another one. + * + * @see llvm::BasicBlock::moveAfter() + */ +void LLVMMoveBasicBlockAfter(LLVMBasicBlockRef BB, LLVMBasicBlockRef MovePos); + +/** + * Obtain the first instruction in a basic block. + * + * The returned LLVMValueRef corresponds to a llvm::Instruction + * instance. + */ +LLVMValueRef LLVMGetFirstInstruction(LLVMBasicBlockRef BB); + +/** + * Obtain the last instruction in a basic block. + * + * The returned LLVMValueRef corresponds to an LLVM:Instruction. + */ +LLVMValueRef LLVMGetLastInstruction(LLVMBasicBlockRef BB); + +/** + * @} + */ + +/** + * @defgroup LLVMCCoreValueInstruction Instructions + * + * Functions in this group relate to the inspection and manipulation of + * individual instructions. + * + * In the C++ API, an instruction is modeled by llvm::Instruction. This + * class has a large number of descendents. llvm::Instruction is a + * llvm::Value and in the C API, instructions are modeled by + * LLVMValueRef. + * + * This group also contains sub-groups which operate on specific + * llvm::Instruction types, e.g. llvm::CallInst. + * + * @{ + */ + +/** + * Determine whether an instruction has any metadata attached. + */ +int LLVMHasMetadata(LLVMValueRef Val); + +/** + * Return metadata associated with an instruction value. + */ +LLVMValueRef LLVMGetMetadata(LLVMValueRef Val, unsigned KindID); + +/** + * Set metadata associated with an instruction value. + */ +void LLVMSetMetadata(LLVMValueRef Val, unsigned KindID, LLVMValueRef Node); + +/** + * Returns the metadata associated with an instruction value, but filters out + * all the debug locations. + * + * @see llvm::Instruction::getAllMetadataOtherThanDebugLoc() + */ +LLVMValueMetadataEntry * +LLVMInstructionGetAllMetadataOtherThanDebugLoc(LLVMValueRef Instr, + size_t *NumEntries); + +/** + * Obtain the basic block to which an instruction belongs. + * + * @see llvm::Instruction::getParent() + */ +LLVMBasicBlockRef LLVMGetInstructionParent(LLVMValueRef Inst); + +/** + * Obtain the instruction that occurs after the one specified. + * + * The next instruction will be from the same basic block. + * + * If this is the last instruction in a basic block, NULL will be + * returned. + */ +LLVMValueRef LLVMGetNextInstruction(LLVMValueRef Inst); + +/** + * Obtain the instruction that occurred before this one. + * + * If the instruction is the first instruction in a basic block, NULL + * will be returned. + */ +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. + * + * The instruction specified is removed from its containing building + * block and then deleted. + * + * @see llvm::Instruction::eraseFromParent() + */ +void LLVMInstructionEraseFromParent(LLVMValueRef Inst); + +/** + * Obtain the code opcode for an individual instruction. + * + * @see llvm::Instruction::getOpCode() + */ +LLVMOpcode LLVMGetInstructionOpcode(LLVMValueRef Inst); + +/** + * Obtain the predicate of an instruction. + * + * This is only valid for instructions that correspond to llvm::ICmpInst + * or llvm::ConstantExpr whose opcode is llvm::Instruction::ICmp. + * + * @see llvm::ICmpInst::getPredicate() + */ +LLVMIntPredicate LLVMGetICmpPredicate(LLVMValueRef Inst); + +/** + * Obtain the float predicate of an instruction. + * + * This is only valid for instructions that correspond to llvm::FCmpInst + * or llvm::ConstantExpr whose opcode is llvm::Instruction::FCmp. + * + * @see llvm::FCmpInst::getPredicate() + */ +LLVMRealPredicate LLVMGetFCmpPredicate(LLVMValueRef Inst); + +/** + * Create a copy of 'this' instruction that is identical in all ways + * except the following: + * * The instruction has no parent + * * The instruction has no name + * + * @see llvm::Instruction::clone() + */ +LLVMValueRef LLVMInstructionClone(LLVMValueRef Inst); + +/** + * Determine whether an instruction is a terminator. This routine is named to + * be compatible with historical functions that did this by querying the + * underlying C++ type. + * + * @see llvm::Instruction::isTerminator() + */ +LLVMValueRef LLVMIsATerminatorInst(LLVMValueRef Inst); + +/** + * @defgroup LLVMCCoreValueInstructionCall Call Sites and Invocations + * + * Functions in this group apply to instructions that refer to call + * sites and invocations. These correspond to C++ types in the + * llvm::CallInst class tree. + * + * @{ + */ + +/** + * Obtain the argument count for a call instruction. + * + * This expects an LLVMValueRef that corresponds to a llvm::CallInst, + * llvm::InvokeInst, or llvm:FuncletPadInst. + * + * @see llvm::CallInst::getNumArgOperands() + * @see llvm::InvokeInst::getNumArgOperands() + * @see llvm::FuncletPadInst::getNumArgOperands() + */ +unsigned LLVMGetNumArgOperands(LLVMValueRef Instr); + +/** + * Set the calling convention for a call instruction. + * + * This expects an LLVMValueRef that corresponds to a llvm::CallInst or + * llvm::InvokeInst. + * + * @see llvm::CallInst::setCallingConv() + * @see llvm::InvokeInst::setCallingConv() + */ +void LLVMSetInstructionCallConv(LLVMValueRef Instr, unsigned CC); + +/** + * Obtain the calling convention for a call instruction. + * + * This is the opposite of LLVMSetInstructionCallConv(). Reads its + * usage. + * + * @see LLVMSetInstructionCallConv() + */ +unsigned LLVMGetInstructionCallConv(LLVMValueRef Instr); + +void LLVMSetInstrParamAlignment(LLVMValueRef Instr, unsigned index, + unsigned Align); + +void LLVMAddCallSiteAttribute(LLVMValueRef C, LLVMAttributeIndex Idx, + LLVMAttributeRef A); +unsigned LLVMGetCallSiteAttributeCount(LLVMValueRef C, LLVMAttributeIndex Idx); +void LLVMGetCallSiteAttributes(LLVMValueRef C, LLVMAttributeIndex Idx, + LLVMAttributeRef *Attrs); +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 function type called by this instruction. + * + * @see llvm::CallBase::getFunctionType() + */ +LLVMTypeRef LLVMGetCalledFunctionType(LLVMValueRef C); + +/** + * 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. + * + * This only works on llvm::CallInst instructions. + * + * @see llvm::CallInst::isTailCall() + */ +LLVMBool LLVMIsTailCall(LLVMValueRef CallInst); + +/** + * Set whether a call instruction is a tail call. + * + * This only works on llvm::CallInst instructions. + * + * @see llvm::CallInst::setTailCall() + */ +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. + * + * Works on llvm::InvokeInst, llvm::CleanupReturnInst, and + * llvm::CatchSwitchInst instructions. + * + * @see llvm::InvokeInst::getUnwindDest() + * @see llvm::CleanupReturnInst::getUnwindDest() + * @see llvm::CatchSwitchInst::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. + * + * Works on llvm::InvokeInst, llvm::CleanupReturnInst, and + * llvm::CatchSwitchInst instructions. + * + * @see llvm::InvokeInst::setUnwindDest() + * @see llvm::CleanupReturnInst::setUnwindDest() + * @see llvm::CatchSwitchInst::setUnwindDest() + */ +void LLVMSetUnwindDest(LLVMValueRef InvokeInst, LLVMBasicBlockRef B); + +/** + * @} + */ + +/** + * @defgroup LLVMCCoreValueInstructionTerminator Terminators + * + * Functions in this group only apply to instructions for which + * LLVMIsATerminatorInst returns true. + * + * @{ + */ + +/** + * Return the number of successors that this terminator has. + * + * @see llvm::Instruction::getNumSuccessors + */ +unsigned LLVMGetNumSuccessors(LLVMValueRef Term); + +/** + * Return the specified successor. + * + * @see llvm::Instruction::getSuccessor + */ +LLVMBasicBlockRef LLVMGetSuccessor(LLVMValueRef Term, unsigned i); + +/** + * Update the specified successor to point at the provided block. + * + * @see llvm::Instruction::setSuccessor + */ +void LLVMSetSuccessor(LLVMValueRef Term, unsigned i, LLVMBasicBlockRef block); + +/** + * Return if a branch is conditional. + * + * This only works on llvm::BranchInst instructions. + * + * @see llvm::BranchInst::isConditional + */ +LLVMBool LLVMIsConditional(LLVMValueRef Branch); + +/** + * Return the condition of a branch instruction. + * + * This only works on llvm::BranchInst instructions. + * + * @see llvm::BranchInst::getCondition + */ +LLVMValueRef LLVMGetCondition(LLVMValueRef Branch); + +/** + * Set the condition of a branch instruction. + * + * This only works on llvm::BranchInst instructions. + * + * @see llvm::BranchInst::setCondition + */ +void LLVMSetCondition(LLVMValueRef Branch, LLVMValueRef Cond); + +/** + * Obtain the default destination basic block of a switch instruction. + * + * This only works on llvm::SwitchInst instructions. + * + * @see llvm::SwitchInst::getDefaultDest() + */ +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); + +/** + * @} + */ + +/** + * @defgroup LLVMCCoreValueInstructionPHINode PHI Nodes + * + * Functions in this group only apply to instructions that map to + * llvm::PHINode instances. + * + * @{ + */ + +/** + * Add an incoming value to the end of a PHI list. + */ +void LLVMAddIncoming(LLVMValueRef PhiNode, LLVMValueRef *IncomingValues, + LLVMBasicBlockRef *IncomingBlocks, unsigned Count); + +/** + * Obtain the number of incoming basic blocks to a PHI node. + */ +unsigned LLVMCountIncoming(LLVMValueRef PhiNode); + +/** + * Obtain an incoming value to a PHI node as an LLVMValueRef. + */ +LLVMValueRef LLVMGetIncomingValue(LLVMValueRef PhiNode, unsigned Index); + +/** + * Obtain an incoming value to a PHI node as an LLVMBasicBlockRef. + */ +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); + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @defgroup LLVMCCoreInstructionBuilder Instruction Builders + * + * An instruction builder represents a point within a basic block and is + * the exclusive means of building instructions using the C interface. + * + * @{ + */ + +LLVMBuilderRef LLVMCreateBuilderInContext(LLVMContextRef C); +LLVMBuilderRef LLVMCreateBuilder(void); +void LLVMPositionBuilder(LLVMBuilderRef Builder, LLVMBasicBlockRef Block, + LLVMValueRef Instr); +void LLVMPositionBuilderBefore(LLVMBuilderRef Builder, LLVMValueRef Instr); +void LLVMPositionBuilderAtEnd(LLVMBuilderRef Builder, LLVMBasicBlockRef Block); +LLVMBasicBlockRef LLVMGetInsertBlock(LLVMBuilderRef Builder); +void LLVMClearInsertionPosition(LLVMBuilderRef Builder); +void LLVMInsertIntoBuilder(LLVMBuilderRef Builder, LLVMValueRef Instr); +void LLVMInsertIntoBuilderWithName(LLVMBuilderRef Builder, LLVMValueRef Instr, + const char *Name); +void LLVMDisposeBuilder(LLVMBuilderRef Builder); + +/* Metadata */ + +/** + * Get location information used by debugging information. + * + * @see llvm::IRBuilder::getCurrentDebugLocation() + */ +LLVMMetadataRef LLVMGetCurrentDebugLocation2(LLVMBuilderRef Builder); + +/** + * Set location information used by debugging information. + * + * To clear the location metadata of the given instruction, pass NULL to \p Loc. + * + * @see llvm::IRBuilder::SetCurrentDebugLocation() + */ +void LLVMSetCurrentDebugLocation2(LLVMBuilderRef Builder, LLVMMetadataRef Loc); + +/** + * Attempts to set the debug location for the given instruction using the + * current debug location for the given builder. If the builder has no current + * debug location, this function is a no-op. + * + * @see llvm::IRBuilder::SetInstDebugLocation() + */ +void LLVMSetInstDebugLocation(LLVMBuilderRef Builder, LLVMValueRef Inst); + +/** + * Get the dafult floating-point math metadata for a given builder. + * + * @see llvm::IRBuilder::getDefaultFPMathTag() + */ +LLVMMetadataRef LLVMBuilderGetDefaultFPMathTag(LLVMBuilderRef Builder); + +/** + * Set the default floating-point math metadata for the given builder. + * + * To clear the metadata, pass NULL to \p FPMathTag. + * + * @see llvm::IRBuilder::setDefaultFPMathTag() + */ +void LLVMBuilderSetDefaultFPMathTag(LLVMBuilderRef Builder, + LLVMMetadataRef FPMathTag); + +/** + * Deprecated: Passing the NULL location will crash. + * Use LLVMGetCurrentDebugLocation2 instead. + */ +void LLVMSetCurrentDebugLocation(LLVMBuilderRef Builder, LLVMValueRef L); +/** + * Deprecated: Returning the NULL location will crash. + * Use LLVMGetCurrentDebugLocation2 instead. + */ +LLVMValueRef LLVMGetCurrentDebugLocation(LLVMBuilderRef Builder); + +/* Terminators */ +LLVMValueRef LLVMBuildRetVoid(LLVMBuilderRef); +LLVMValueRef LLVMBuildRet(LLVMBuilderRef, LLVMValueRef V); +LLVMValueRef LLVMBuildAggregateRet(LLVMBuilderRef, LLVMValueRef *RetVals, + unsigned N); +LLVMValueRef LLVMBuildBr(LLVMBuilderRef, LLVMBasicBlockRef Dest); +LLVMValueRef LLVMBuildCondBr(LLVMBuilderRef, LLVMValueRef If, + LLVMBasicBlockRef Then, LLVMBasicBlockRef Else); +LLVMValueRef LLVMBuildSwitch(LLVMBuilderRef, LLVMValueRef V, + LLVMBasicBlockRef Else, unsigned NumCases); +LLVMValueRef LLVMBuildIndirectBr(LLVMBuilderRef B, LLVMValueRef Addr, + unsigned NumDests); +// LLVMBuildInvoke is deprecated in favor of LLVMBuildInvoke2, in preparation +// for opaque pointer types. +LLVMValueRef LLVMBuildInvoke(LLVMBuilderRef, LLVMValueRef Fn, + LLVMValueRef *Args, unsigned NumArgs, + LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch, + const char *Name); +LLVMValueRef LLVMBuildInvoke2(LLVMBuilderRef, LLVMTypeRef Ty, LLVMValueRef Fn, + LLVMValueRef *Args, unsigned NumArgs, + LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch, + const char *Name); +LLVMValueRef LLVMBuildUnreachable(LLVMBuilderRef); + +/* Exception Handling */ +LLVMValueRef LLVMBuildResume(LLVMBuilderRef B, LLVMValueRef Exn); +LLVMValueRef LLVMBuildLandingPad(LLVMBuilderRef B, LLVMTypeRef Ty, + LLVMValueRef PersFn, unsigned NumClauses, + const char *Name); +LLVMValueRef LLVMBuildCleanupRet(LLVMBuilderRef B, LLVMValueRef CatchPad, + LLVMBasicBlockRef BB); +LLVMValueRef LLVMBuildCatchRet(LLVMBuilderRef B, LLVMValueRef CatchPad, + LLVMBasicBlockRef BB); +LLVMValueRef LLVMBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad, + LLVMValueRef *Args, unsigned NumArgs, + const char *Name); +LLVMValueRef LLVMBuildCleanupPad(LLVMBuilderRef B, LLVMValueRef ParentPad, + LLVMValueRef *Args, unsigned NumArgs, + const char *Name); +LLVMValueRef LLVMBuildCatchSwitch(LLVMBuilderRef B, LLVMValueRef ParentPad, + LLVMBasicBlockRef UnwindBB, + unsigned NumHandlers, const char *Name); + +/* Add a case to the switch instruction */ +void LLVMAddCase(LLVMValueRef Switch, LLVMValueRef OnVal, + LLVMBasicBlockRef Dest); + +/* 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); + +/* Add a destination to the catchswitch instruction */ +void LLVMAddHandler(LLVMValueRef CatchSwitch, LLVMBasicBlockRef Dest); + +/* Get the number of handlers on the catchswitch instruction */ +unsigned LLVMGetNumHandlers(LLVMValueRef CatchSwitch); + +/** + * Obtain the basic blocks acting as handlers for a catchswitch instruction. + * + * The Handlers parameter should point to a pre-allocated array of + * LLVMBasicBlockRefs at least LLVMGetNumHandlers() large. On return, the + * first LLVMGetNumHandlers() entries in the array will be populated + * with LLVMBasicBlockRef instances. + * + * @param CatchSwitch The catchswitch instruction to operate on. + * @param Handlers Memory address of an array to be filled with basic blocks. + */ +void LLVMGetHandlers(LLVMValueRef CatchSwitch, LLVMBasicBlockRef *Handlers); + +/* Funclets */ + +/* Get the number of funcletpad arguments. */ +LLVMValueRef LLVMGetArgOperand(LLVMValueRef Funclet, unsigned i); + +/* Set a funcletpad argument at the given index. */ +void LLVMSetArgOperand(LLVMValueRef Funclet, unsigned i, LLVMValueRef value); + +/** + * Get the parent catchswitch instruction of a catchpad instruction. + * + * This only works on llvm::CatchPadInst instructions. + * + * @see llvm::CatchPadInst::getCatchSwitch() + */ +LLVMValueRef LLVMGetParentCatchSwitch(LLVMValueRef CatchPad); + +/** + * Set the parent catchswitch instruction of a catchpad instruction. + * + * This only works on llvm::CatchPadInst instructions. + * + * @see llvm::CatchPadInst::setCatchSwitch() + */ +void LLVMSetParentCatchSwitch(LLVMValueRef CatchPad, LLVMValueRef CatchSwitch); + +/* Arithmetic */ +LLVMValueRef LLVMBuildAdd(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildNSWAdd(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildNUWAdd(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildFAdd(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildSub(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildNSWSub(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildNUWSub(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildFSub(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildMul(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildNSWMul(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildNUWMul(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildFMul(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildUDiv(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildExactUDiv(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildSDiv(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildExactSDiv(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildFDiv(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildURem(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildSRem(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildFRem(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildShl(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildLShr(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildAShr(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildAnd(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildOr(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildXor(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildBinOp(LLVMBuilderRef B, LLVMOpcode Op, + LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildNeg(LLVMBuilderRef, LLVMValueRef V, const char *Name); +LLVMValueRef LLVMBuildNSWNeg(LLVMBuilderRef B, LLVMValueRef V, + const char *Name); +LLVMValueRef LLVMBuildNUWNeg(LLVMBuilderRef B, LLVMValueRef V, + const char *Name); +LLVMValueRef LLVMBuildFNeg(LLVMBuilderRef, LLVMValueRef V, const char *Name); +LLVMValueRef LLVMBuildNot(LLVMBuilderRef, LLVMValueRef V, const char *Name); + +/* Memory */ +LLVMValueRef LLVMBuildMalloc(LLVMBuilderRef, LLVMTypeRef Ty, const char *Name); +LLVMValueRef LLVMBuildArrayMalloc(LLVMBuilderRef, LLVMTypeRef Ty, + LLVMValueRef Val, const char *Name); + +/** + * Creates and inserts a memset to the specified pointer and the + * specified value. + * + * @see llvm::IRRBuilder::CreateMemSet() + */ +LLVMValueRef LLVMBuildMemSet(LLVMBuilderRef B, LLVMValueRef Ptr, + LLVMValueRef Val, LLVMValueRef Len, + unsigned Align); +/** + * Creates and inserts a memcpy between the specified pointers. + * + * @see llvm::IRRBuilder::CreateMemCpy() + */ +LLVMValueRef LLVMBuildMemCpy(LLVMBuilderRef B, + LLVMValueRef Dst, unsigned DstAlign, + LLVMValueRef Src, unsigned SrcAlign, + LLVMValueRef Size); +/** + * Creates and inserts a memmove between the specified pointers. + * + * @see llvm::IRRBuilder::CreateMemMove() + */ +LLVMValueRef LLVMBuildMemMove(LLVMBuilderRef B, + LLVMValueRef Dst, unsigned DstAlign, + LLVMValueRef Src, unsigned SrcAlign, + LLVMValueRef Size); + +LLVMValueRef LLVMBuildAlloca(LLVMBuilderRef, LLVMTypeRef Ty, const char *Name); +LLVMValueRef LLVMBuildArrayAlloca(LLVMBuilderRef, LLVMTypeRef Ty, + LLVMValueRef Val, const char *Name); +LLVMValueRef LLVMBuildFree(LLVMBuilderRef, LLVMValueRef PointerVal); +// LLVMBuildLoad is deprecated in favor of LLVMBuildLoad2, in preparation for +// opaque pointer types. +LLVMValueRef LLVMBuildLoad(LLVMBuilderRef, LLVMValueRef PointerVal, + const char *Name); +LLVMValueRef LLVMBuildLoad2(LLVMBuilderRef, LLVMTypeRef Ty, + LLVMValueRef PointerVal, const char *Name); +LLVMValueRef LLVMBuildStore(LLVMBuilderRef, LLVMValueRef Val, LLVMValueRef Ptr); +// LLVMBuildGEP, LLVMBuildInBoundsGEP, and LLVMBuildStructGEP are deprecated in +// favor of LLVMBuild*GEP2, in preparation for opaque pointer types. +LLVMValueRef LLVMBuildGEP(LLVMBuilderRef B, LLVMValueRef Pointer, + LLVMValueRef *Indices, unsigned NumIndices, + const char *Name); +LLVMValueRef LLVMBuildInBoundsGEP(LLVMBuilderRef B, LLVMValueRef Pointer, + LLVMValueRef *Indices, unsigned NumIndices, + const char *Name); +LLVMValueRef LLVMBuildStructGEP(LLVMBuilderRef B, LLVMValueRef Pointer, + unsigned Idx, const char *Name); +LLVMValueRef LLVMBuildGEP2(LLVMBuilderRef B, LLVMTypeRef Ty, + LLVMValueRef Pointer, LLVMValueRef *Indices, + unsigned NumIndices, const char *Name); +LLVMValueRef LLVMBuildInBoundsGEP2(LLVMBuilderRef B, LLVMTypeRef Ty, + LLVMValueRef Pointer, LLVMValueRef *Indices, + unsigned NumIndices, const char *Name); +LLVMValueRef LLVMBuildStructGEP2(LLVMBuilderRef B, LLVMTypeRef Ty, + LLVMValueRef Pointer, unsigned Idx, + const char *Name); +LLVMValueRef LLVMBuildGlobalString(LLVMBuilderRef B, const char *Str, + const char *Name); +LLVMValueRef LLVMBuildGlobalStringPtr(LLVMBuilderRef B, const char *Str, + const char *Name); +LLVMBool LLVMGetVolatile(LLVMValueRef MemoryAccessInst); +void LLVMSetVolatile(LLVMValueRef MemoryAccessInst, LLVMBool IsVolatile); +LLVMBool LLVMGetWeak(LLVMValueRef CmpXchgInst); +void LLVMSetWeak(LLVMValueRef CmpXchgInst, LLVMBool IsWeak); +LLVMAtomicOrdering LLVMGetOrdering(LLVMValueRef MemoryAccessInst); +void LLVMSetOrdering(LLVMValueRef MemoryAccessInst, LLVMAtomicOrdering Ordering); +LLVMAtomicRMWBinOp LLVMGetAtomicRMWBinOp(LLVMValueRef AtomicRMWInst); +void LLVMSetAtomicRMWBinOp(LLVMValueRef AtomicRMWInst, LLVMAtomicRMWBinOp BinOp); + +/* Casts */ +LLVMValueRef LLVMBuildTrunc(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildZExt(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildSExt(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildFPToUI(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildFPToSI(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildUIToFP(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildSIToFP(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildFPTrunc(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildFPExt(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildPtrToInt(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildIntToPtr(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildBitCast(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildAddrSpaceCast(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildZExtOrBitCast(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildSExtOrBitCast(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildTruncOrBitCast(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildCast(LLVMBuilderRef B, LLVMOpcode Op, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildPointerCast(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildIntCast2(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, LLVMBool IsSigned, + const char *Name); +LLVMValueRef LLVMBuildFPCast(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); + +/** Deprecated: This cast is always signed. Use LLVMBuildIntCast2 instead. */ +LLVMValueRef LLVMBuildIntCast(LLVMBuilderRef, LLVMValueRef Val, /*Signed cast!*/ + LLVMTypeRef DestTy, const char *Name); + +/* Comparisons */ +LLVMValueRef LLVMBuildICmp(LLVMBuilderRef, LLVMIntPredicate Op, + LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildFCmp(LLVMBuilderRef, LLVMRealPredicate Op, + LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); + +/* Miscellaneous instructions */ +LLVMValueRef LLVMBuildPhi(LLVMBuilderRef, LLVMTypeRef Ty, const char *Name); +// LLVMBuildCall is deprecated in favor of LLVMBuildCall2, in preparation for +// opaque pointer types. +LLVMValueRef LLVMBuildCall(LLVMBuilderRef, LLVMValueRef Fn, + LLVMValueRef *Args, unsigned NumArgs, + const char *Name); +LLVMValueRef LLVMBuildCall2(LLVMBuilderRef, LLVMTypeRef, LLVMValueRef Fn, + LLVMValueRef *Args, unsigned NumArgs, + const char *Name); +LLVMValueRef LLVMBuildSelect(LLVMBuilderRef, LLVMValueRef If, + LLVMValueRef Then, LLVMValueRef Else, + const char *Name); +LLVMValueRef LLVMBuildVAArg(LLVMBuilderRef, LLVMValueRef List, LLVMTypeRef Ty, + const char *Name); +LLVMValueRef LLVMBuildExtractElement(LLVMBuilderRef, LLVMValueRef VecVal, + LLVMValueRef Index, const char *Name); +LLVMValueRef LLVMBuildInsertElement(LLVMBuilderRef, LLVMValueRef VecVal, + LLVMValueRef EltVal, LLVMValueRef Index, + const char *Name); +LLVMValueRef LLVMBuildShuffleVector(LLVMBuilderRef, LLVMValueRef V1, + LLVMValueRef V2, LLVMValueRef Mask, + const char *Name); +LLVMValueRef LLVMBuildExtractValue(LLVMBuilderRef, LLVMValueRef AggVal, + unsigned Index, const char *Name); +LLVMValueRef LLVMBuildInsertValue(LLVMBuilderRef, LLVMValueRef AggVal, + LLVMValueRef EltVal, unsigned Index, + const char *Name); +LLVMValueRef LLVMBuildFreeze(LLVMBuilderRef, LLVMValueRef Val, + const char *Name); + +LLVMValueRef LLVMBuildIsNull(LLVMBuilderRef, LLVMValueRef Val, + const char *Name); +LLVMValueRef LLVMBuildIsNotNull(LLVMBuilderRef, LLVMValueRef Val, + const char *Name); +LLVMValueRef LLVMBuildPtrDiff(LLVMBuilderRef, LLVMValueRef LHS, + LLVMValueRef RHS, const char *Name); +LLVMValueRef LLVMBuildFence(LLVMBuilderRef B, LLVMAtomicOrdering ordering, + LLVMBool singleThread, const char *Name); +LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B, LLVMAtomicRMWBinOp op, + LLVMValueRef PTR, LLVMValueRef Val, + LLVMAtomicOrdering ordering, + LLVMBool singleThread); +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); + +/** + * @} + */ + +/** + * @defgroup LLVMCCoreModuleProvider Module Providers + * + * @{ + */ + +/** + * Changes the type of M so it can be passed to FunctionPassManagers and the + * JIT. They take ModuleProviders for historical reasons. + */ +LLVMModuleProviderRef +LLVMCreateModuleProviderForExistingModule(LLVMModuleRef M); + +/** + * Destroys the module M. + */ +void LLVMDisposeModuleProvider(LLVMModuleProviderRef M); + +/** + * @} + */ + +/** + * @defgroup LLVMCCoreMemoryBuffers Memory Buffers + * + * @{ + */ + +LLVMBool LLVMCreateMemoryBufferWithContentsOfFile(const char *Path, + LLVMMemoryBufferRef *OutMemBuf, + char **OutMessage); +LLVMBool LLVMCreateMemoryBufferWithSTDIN(LLVMMemoryBufferRef *OutMemBuf, + char **OutMessage); +LLVMMemoryBufferRef LLVMCreateMemoryBufferWithMemoryRange(const char *InputData, + size_t InputDataLength, + const char *BufferName, + LLVMBool RequiresNullTerminator); +LLVMMemoryBufferRef LLVMCreateMemoryBufferWithMemoryRangeCopy(const char *InputData, + size_t InputDataLength, + const char *BufferName); +const char *LLVMGetBufferStart(LLVMMemoryBufferRef MemBuf); +size_t LLVMGetBufferSize(LLVMMemoryBufferRef MemBuf); +void LLVMDisposeMemoryBuffer(LLVMMemoryBufferRef MemBuf); + +/** + * @} + */ + +/** + * @defgroup LLVMCCorePassRegistry Pass Registry + * + * @{ + */ + +/** Return the global pass registry, for use with initialization functions. + @see llvm::PassRegistry::getPassRegistry */ +LLVMPassRegistryRef LLVMGetGlobalPassRegistry(void); + +/** + * @} + */ + +/** + * @defgroup LLVMCCorePassManagers Pass Managers + * + * @{ + */ + +/** Constructs a new whole-module pass pipeline. This type of pipeline is + suitable for link-time optimization and whole-module transformations. + @see llvm::PassManager::PassManager */ +LLVMPassManagerRef LLVMCreatePassManager(void); + +/** Constructs a new function-by-function pass pipeline over the module + provider. It does not take ownership of the module provider. This type of + pipeline is suitable for code generation and JIT compilation tasks. + @see llvm::FunctionPassManager::FunctionPassManager */ +LLVMPassManagerRef LLVMCreateFunctionPassManagerForModule(LLVMModuleRef M); + +/** Deprecated: Use LLVMCreateFunctionPassManagerForModule instead. */ +LLVMPassManagerRef LLVMCreateFunctionPassManager(LLVMModuleProviderRef MP); + +/** Initializes, executes on the provided module, and finalizes all of the + passes scheduled in the pass manager. Returns 1 if any of the passes + modified the module, 0 otherwise. + @see llvm::PassManager::run(Module&) */ +LLVMBool LLVMRunPassManager(LLVMPassManagerRef PM, LLVMModuleRef M); + +/** Initializes all of the function passes scheduled in the function pass + manager. Returns 1 if any of the passes modified the module, 0 otherwise. + @see llvm::FunctionPassManager::doInitialization */ +LLVMBool LLVMInitializeFunctionPassManager(LLVMPassManagerRef FPM); + +/** Executes all of the function passes scheduled in the function pass manager + on the provided function. Returns 1 if any of the passes modified the + function, false otherwise. + @see llvm::FunctionPassManager::run(Function&) */ +LLVMBool LLVMRunFunctionPassManager(LLVMPassManagerRef FPM, LLVMValueRef F); + +/** Finalizes all of the function passes scheduled in the function pass + manager. Returns 1 if any of the passes modified the module, 0 otherwise. + @see llvm::FunctionPassManager::doFinalization */ +LLVMBool LLVMFinalizeFunctionPassManager(LLVMPassManagerRef FPM); + +/** Frees the memory of a pass pipeline. For function pipelines, does not free + the module provider. + @see llvm::PassManagerBase::~PassManagerBase. */ +void LLVMDisposePassManager(LLVMPassManagerRef PM); + +/** + * @} + */ + +/** + * @defgroup LLVMCCoreThreading Threading + * + * Handle the structures needed to make LLVM safe for multithreading. + * + * @{ + */ + +/** Deprecated: Multi-threading can only be enabled/disabled with the compile + time define LLVM_ENABLE_THREADS. This function always returns + LLVMIsMultithreaded(). */ +LLVMBool LLVMStartMultithreaded(void); + +/** Deprecated: Multi-threading can only be enabled/disabled with the compile + time define LLVM_ENABLE_THREADS. */ +void LLVMStopMultithreaded(void); + +/** Check whether LLVM is executing in thread-safe mode or not. + @see llvm::llvm_is_multithreaded */ +LLVMBool LLVMIsMultithreaded(void); + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +LLVM_C_EXTERN_C_END + +#endif /* LLVM_C_CORE_H */
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/DataTypes.h b/third_party/llvm-10.0/llvm/include/llvm-c/DataTypes.h new file mode 100644 index 0000000..893b22b --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/DataTypes.h
@@ -0,0 +1,90 @@ +/*===-- include/llvm-c/DataTypes.h - Define fixed size types ------*- C -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file contains definitions to figure out the size of _HOST_ data types.*| +|* This file is important because different host OS's define different macros,*| +|* which makes portability tough. This file exports the following *| +|* definitions: *| +|* *| +|* [u]int(32|64)_t : typedefs for signed and unsigned 32/64 bit system types*| +|* [U]INT(8|16|32|64)_(MIN|MAX) : Constants for the min and max values. *| +|* *| +|* No library is required when using these functions. *| +|* *| +|*===----------------------------------------------------------------------===*/ + +/* Please leave this file C-compatible. */ + +#ifndef LLVM_C_DATATYPES_H +#define LLVM_C_DATATYPES_H + +#ifdef __cplusplus +#include <cmath> +#else +#include <math.h> +#endif + +#include <inttypes.h> +#include <stdint.h> + +#ifndef _MSC_VER + +#if !defined(UINT32_MAX) +# error "The standard header <cstdint> is not C++11 compliant. Must #define "\ + "__STDC_LIMIT_MACROS before #including llvm-c/DataTypes.h" +#endif + +#if !defined(UINT32_C) +# error "The standard header <cstdint> is not C++11 compliant. Must #define "\ + "__STDC_CONSTANT_MACROS before #including llvm-c/DataTypes.h" +#endif + +/* Note that <inttypes.h> includes <stdint.h>, if this is a C99 system. */ +#include <sys/types.h> + +#ifdef _AIX +// GCC is strict about defining large constants: they must have LL modifier. +#undef INT64_MAX +#undef INT64_MIN +#endif + +#else /* _MSC_VER */ +#ifdef __cplusplus +#include <cstddef> +#include <cstdlib> +#else +#include <stddef.h> +#include <stdlib.h> +#endif +#include <sys/types.h> + +#if defined(_WIN64) +typedef signed __int64 ssize_t; +#else +typedef signed int ssize_t; +#endif /* _WIN64 */ + +#endif /* _MSC_VER */ + +/* Set defaults for constants which we cannot find. */ +#if !defined(INT64_MAX) +# define INT64_MAX 9223372036854775807LL +#endif +#if !defined(INT64_MIN) +# define INT64_MIN ((-INT64_MAX)-1) +#endif +#if !defined(UINT64_MAX) +# define UINT64_MAX 0xffffffffffffffffULL +#endif + +#ifndef HUGE_VALF +#define HUGE_VALF (float)HUGE_VAL +#endif + +#endif /* LLVM_C_DATATYPES_H */
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/DebugInfo.h b/third_party/llvm-10.0/llvm/include/llvm-c/DebugInfo.h new file mode 100644 index 0000000..e933fe4 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/DebugInfo.h
@@ -0,0 +1,1357 @@ +//===------------ DebugInfo.h - LLVM C API Debug Info API -----------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// This file declares the C API endpoints for generating DWARF Debug Info +/// +/// Note: This interface is experimental. It is *NOT* stable, and may be +/// changed without warning. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_C_DEBUGINFO_H +#define LLVM_C_DEBUGINFO_H + +#include "llvm-c/Core.h" +#include "llvm-c/ExternC.h" + +LLVM_C_EXTERN_C_BEGIN + +/** + * Debug info flags. + */ +typedef enum { + LLVMDIFlagZero = 0, + LLVMDIFlagPrivate = 1, + LLVMDIFlagProtected = 2, + LLVMDIFlagPublic = 3, + LLVMDIFlagFwdDecl = 1 << 2, + LLVMDIFlagAppleBlock = 1 << 3, + LLVMDIFlagReservedBit4 = 1 << 4, + LLVMDIFlagVirtual = 1 << 5, + LLVMDIFlagArtificial = 1 << 6, + LLVMDIFlagExplicit = 1 << 7, + LLVMDIFlagPrototyped = 1 << 8, + LLVMDIFlagObjcClassComplete = 1 << 9, + LLVMDIFlagObjectPointer = 1 << 10, + LLVMDIFlagVector = 1 << 11, + LLVMDIFlagStaticMember = 1 << 12, + LLVMDIFlagLValueReference = 1 << 13, + LLVMDIFlagRValueReference = 1 << 14, + LLVMDIFlagReserved = 1 << 15, + LLVMDIFlagSingleInheritance = 1 << 16, + LLVMDIFlagMultipleInheritance = 2 << 16, + LLVMDIFlagVirtualInheritance = 3 << 16, + LLVMDIFlagIntroducedVirtual = 1 << 18, + LLVMDIFlagBitField = 1 << 19, + LLVMDIFlagNoReturn = 1 << 20, + LLVMDIFlagTypePassByValue = 1 << 22, + LLVMDIFlagTypePassByReference = 1 << 23, + LLVMDIFlagEnumClass = 1 << 24, + LLVMDIFlagFixedEnum = LLVMDIFlagEnumClass, // Deprecated. + LLVMDIFlagThunk = 1 << 25, + LLVMDIFlagNonTrivial = 1 << 26, + LLVMDIFlagBigEndian = 1 << 27, + LLVMDIFlagLittleEndian = 1 << 28, + LLVMDIFlagIndirectVirtualBase = (1 << 2) | (1 << 5), + LLVMDIFlagAccessibility = LLVMDIFlagPrivate | LLVMDIFlagProtected | + LLVMDIFlagPublic, + LLVMDIFlagPtrToMemberRep = LLVMDIFlagSingleInheritance | + LLVMDIFlagMultipleInheritance | + LLVMDIFlagVirtualInheritance +} LLVMDIFlags; + +/** + * Source languages known by DWARF. + */ +typedef enum { + LLVMDWARFSourceLanguageC89, + LLVMDWARFSourceLanguageC, + LLVMDWARFSourceLanguageAda83, + LLVMDWARFSourceLanguageC_plus_plus, + LLVMDWARFSourceLanguageCobol74, + LLVMDWARFSourceLanguageCobol85, + LLVMDWARFSourceLanguageFortran77, + LLVMDWARFSourceLanguageFortran90, + LLVMDWARFSourceLanguagePascal83, + LLVMDWARFSourceLanguageModula2, + // New in DWARF v3: + LLVMDWARFSourceLanguageJava, + LLVMDWARFSourceLanguageC99, + LLVMDWARFSourceLanguageAda95, + LLVMDWARFSourceLanguageFortran95, + LLVMDWARFSourceLanguagePLI, + LLVMDWARFSourceLanguageObjC, + LLVMDWARFSourceLanguageObjC_plus_plus, + LLVMDWARFSourceLanguageUPC, + LLVMDWARFSourceLanguageD, + // New in DWARF v4: + LLVMDWARFSourceLanguagePython, + // New in DWARF v5: + LLVMDWARFSourceLanguageOpenCL, + LLVMDWARFSourceLanguageGo, + LLVMDWARFSourceLanguageModula3, + LLVMDWARFSourceLanguageHaskell, + LLVMDWARFSourceLanguageC_plus_plus_03, + LLVMDWARFSourceLanguageC_plus_plus_11, + LLVMDWARFSourceLanguageOCaml, + LLVMDWARFSourceLanguageRust, + LLVMDWARFSourceLanguageC11, + LLVMDWARFSourceLanguageSwift, + LLVMDWARFSourceLanguageJulia, + LLVMDWARFSourceLanguageDylan, + LLVMDWARFSourceLanguageC_plus_plus_14, + LLVMDWARFSourceLanguageFortran03, + LLVMDWARFSourceLanguageFortran08, + LLVMDWARFSourceLanguageRenderScript, + LLVMDWARFSourceLanguageBLISS, + // Vendor extensions: + LLVMDWARFSourceLanguageMips_Assembler, + LLVMDWARFSourceLanguageGOOGLE_RenderScript, + LLVMDWARFSourceLanguageBORLAND_Delphi +} LLVMDWARFSourceLanguage; + +/** + * The amount of debug information to emit. + */ +typedef enum { + LLVMDWARFEmissionNone = 0, + LLVMDWARFEmissionFull, + LLVMDWARFEmissionLineTablesOnly +} LLVMDWARFEmissionKind; + +/** + * The kind of metadata nodes. + */ +enum { + LLVMMDStringMetadataKind, + LLVMConstantAsMetadataMetadataKind, + LLVMLocalAsMetadataMetadataKind, + LLVMDistinctMDOperandPlaceholderMetadataKind, + LLVMMDTupleMetadataKind, + LLVMDILocationMetadataKind, + LLVMDIExpressionMetadataKind, + LLVMDIGlobalVariableExpressionMetadataKind, + LLVMGenericDINodeMetadataKind, + LLVMDISubrangeMetadataKind, + LLVMDIEnumeratorMetadataKind, + LLVMDIBasicTypeMetadataKind, + LLVMDIDerivedTypeMetadataKind, + LLVMDICompositeTypeMetadataKind, + LLVMDISubroutineTypeMetadataKind, + LLVMDIFileMetadataKind, + LLVMDICompileUnitMetadataKind, + LLVMDISubprogramMetadataKind, + LLVMDILexicalBlockMetadataKind, + LLVMDILexicalBlockFileMetadataKind, + LLVMDINamespaceMetadataKind, + LLVMDIModuleMetadataKind, + LLVMDITemplateTypeParameterMetadataKind, + LLVMDITemplateValueParameterMetadataKind, + LLVMDIGlobalVariableMetadataKind, + LLVMDILocalVariableMetadataKind, + LLVMDILabelMetadataKind, + LLVMDIObjCPropertyMetadataKind, + LLVMDIImportedEntityMetadataKind, + LLVMDIMacroMetadataKind, + LLVMDIMacroFileMetadataKind, + LLVMDICommonBlockMetadataKind +}; +typedef unsigned LLVMMetadataKind; + +/** + * An LLVM DWARF type encoding. + */ +typedef unsigned LLVMDWARFTypeEncoding; + +/** + * Describes the kind of macro declaration used for LLVMDIBuilderCreateMacro. + * @see llvm::dwarf::MacinfoRecordType + * @note Values are from DW_MACINFO_* constants in the DWARF specification. + */ +typedef enum { + LLVMDWARFMacinfoRecordTypeDefine = 0x01, + LLVMDWARFMacinfoRecordTypeMacro = 0x02, + LLVMDWARFMacinfoRecordTypeStartFile = 0x03, + LLVMDWARFMacinfoRecordTypeEndFile = 0x04, + LLVMDWARFMacinfoRecordTypeVendorExt = 0xff +} LLVMDWARFMacinfoRecordType; + +/** + * The current debug metadata version number. + */ +unsigned LLVMDebugMetadataVersion(void); + +/** + * The version of debug metadata that's present in the provided \c Module. + */ +unsigned LLVMGetModuleDebugMetadataVersion(LLVMModuleRef Module); + +/** + * Strip debug info in the module if it exists. + * To do this, we remove all calls to the debugger intrinsics and any named + * metadata for debugging. We also remove debug locations for instructions. + * Return true if module is modified. + */ +LLVMBool LLVMStripModuleDebugInfo(LLVMModuleRef Module); + +/** + * Construct a builder for a module, and do not allow for unresolved nodes + * attached to the module. + */ +LLVMDIBuilderRef LLVMCreateDIBuilderDisallowUnresolved(LLVMModuleRef M); + +/** + * Construct a builder for a module and collect unresolved nodes attached + * to the module in order to resolve cycles during a call to + * \c LLVMDIBuilderFinalize. + */ +LLVMDIBuilderRef LLVMCreateDIBuilder(LLVMModuleRef M); + +/** + * Deallocates the \c DIBuilder and everything it owns. + * @note You must call \c LLVMDIBuilderFinalize before this + */ +void LLVMDisposeDIBuilder(LLVMDIBuilderRef Builder); + +/** + * Construct any deferred debug info descriptors. + */ +void LLVMDIBuilderFinalize(LLVMDIBuilderRef Builder); + +/** + * A CompileUnit provides an anchor for all debugging + * information generated during this instance of compilation. + * \param Lang Source programming language, eg. + * \c LLVMDWARFSourceLanguageC99 + * \param FileRef File info. + * \param Producer Identify the producer of debugging information + * and code. Usually this is a compiler + * version string. + * \param ProducerLen The length of the C string passed to \c Producer. + * \param isOptimized A boolean flag which indicates whether optimization + * is enabled or not. + * \param Flags This string lists command line options. This + * string is directly embedded in debug info + * output which may be used by a tool + * analyzing generated debugging information. + * \param FlagsLen The length of the C string passed to \c Flags. + * \param RuntimeVer This indicates runtime version for languages like + * Objective-C. + * \param SplitName The name of the file that we'll split debug info + * out into. + * \param SplitNameLen The length of the C string passed to \c SplitName. + * \param Kind The kind of debug information to generate. + * \param DWOId The DWOId if this is a split skeleton compile unit. + * \param SplitDebugInlining Whether to emit inline debug info. + * \param DebugInfoForProfiling Whether to emit extra debug info for + * profile collection. + */ +LLVMMetadataRef LLVMDIBuilderCreateCompileUnit( + LLVMDIBuilderRef Builder, LLVMDWARFSourceLanguage Lang, + LLVMMetadataRef FileRef, const char *Producer, size_t ProducerLen, + LLVMBool isOptimized, const char *Flags, size_t FlagsLen, + unsigned RuntimeVer, const char *SplitName, size_t SplitNameLen, + LLVMDWARFEmissionKind Kind, unsigned DWOId, LLVMBool SplitDebugInlining, + LLVMBool DebugInfoForProfiling); + +/** + * Create a file descriptor to hold debugging information for a file. + * \param Builder The \c DIBuilder. + * \param Filename File name. + * \param FilenameLen The length of the C string passed to \c Filename. + * \param Directory Directory. + * \param DirectoryLen The length of the C string passed to \c Directory. + */ +LLVMMetadataRef +LLVMDIBuilderCreateFile(LLVMDIBuilderRef Builder, const char *Filename, + size_t FilenameLen, const char *Directory, + size_t DirectoryLen); + +/** + * Creates a new descriptor for a module with the specified parent scope. + * \param Builder The \c DIBuilder. + * \param ParentScope The parent scope containing this module declaration. + * \param Name Module name. + * \param NameLen The length of the C string passed to \c Name. + * \param ConfigMacros A space-separated shell-quoted list of -D macro + definitions as they would appear on a command line. + * \param ConfigMacrosLen The length of the C string passed to \c ConfigMacros. + * \param IncludePath The path to the module map file. + * \param IncludePathLen The length of the C string passed to \c IncludePath. + * \param SysRoot The Clang system root (value of -isysroot). + * \param SysRootLen The length of the C string passed to \c SysRoot. + */ +LLVMMetadataRef +LLVMDIBuilderCreateModule(LLVMDIBuilderRef Builder, LLVMMetadataRef ParentScope, + const char *Name, size_t NameLen, + const char *ConfigMacros, size_t ConfigMacrosLen, + const char *IncludePath, size_t IncludePathLen, + const char *SysRoot, size_t SysRootLen); + +/** + * Creates a new descriptor for a namespace with the specified parent scope. + * \param Builder The \c DIBuilder. + * \param ParentScope The parent scope containing this module declaration. + * \param Name NameSpace name. + * \param NameLen The length of the C string passed to \c Name. + * \param ExportSymbols Whether or not the namespace exports symbols, e.g. + * this is true of C++ inline namespaces. + */ +LLVMMetadataRef +LLVMDIBuilderCreateNameSpace(LLVMDIBuilderRef Builder, + LLVMMetadataRef ParentScope, + const char *Name, size_t NameLen, + LLVMBool ExportSymbols); + +/** + * Create a new descriptor for the specified subprogram. + * \param Builder The \c DIBuilder. + * \param Scope Function scope. + * \param Name Function name. + * \param NameLen Length of enumeration name. + * \param LinkageName Mangled function name. + * \param LinkageNameLen Length of linkage name. + * \param File File where this variable is defined. + * \param LineNo Line number. + * \param Ty Function type. + * \param IsLocalToUnit True if this function is not externally visible. + * \param IsDefinition True if this is a function definition. + * \param ScopeLine Set to the beginning of the scope this starts + * \param Flags E.g.: \c LLVMDIFlagLValueReference. These flags are + * used to emit dwarf attributes. + * \param IsOptimized True if optimization is ON. + */ +LLVMMetadataRef LLVMDIBuilderCreateFunction( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, const char *LinkageName, size_t LinkageNameLen, + LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty, + LLVMBool IsLocalToUnit, LLVMBool IsDefinition, + unsigned ScopeLine, LLVMDIFlags Flags, LLVMBool IsOptimized); + +/** + * Create a descriptor for a lexical block with the specified parent context. + * \param Builder The \c DIBuilder. + * \param Scope Parent lexical block. + * \param File Source file. + * \param Line The line in the source file. + * \param Column The column in the source file. + */ +LLVMMetadataRef LLVMDIBuilderCreateLexicalBlock( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, + LLVMMetadataRef File, unsigned Line, unsigned Column); + +/** + * Create a descriptor for a lexical block with a new file attached. + * \param Builder The \c DIBuilder. + * \param Scope Lexical block. + * \param File Source file. + * \param Discriminator DWARF path discriminator value. + */ +LLVMMetadataRef +LLVMDIBuilderCreateLexicalBlockFile(LLVMDIBuilderRef Builder, + LLVMMetadataRef Scope, + LLVMMetadataRef File, + unsigned Discriminator); + +/** + * Create a descriptor for an imported namespace. Suitable for e.g. C++ + * using declarations. + * \param Builder The \c DIBuilder. + * \param Scope The scope this module is imported into + * \param File File where the declaration is located. + * \param Line Line number of the declaration. + */ +LLVMMetadataRef +LLVMDIBuilderCreateImportedModuleFromNamespace(LLVMDIBuilderRef Builder, + LLVMMetadataRef Scope, + LLVMMetadataRef NS, + LLVMMetadataRef File, + unsigned Line); + +/** + * Create a descriptor for an imported module that aliases another + * imported entity descriptor. + * \param Builder The \c DIBuilder. + * \param Scope The scope this module is imported into + * \param ImportedEntity Previous imported entity to alias. + * \param File File where the declaration is located. + * \param Line Line number of the declaration. + */ +LLVMMetadataRef +LLVMDIBuilderCreateImportedModuleFromAlias(LLVMDIBuilderRef Builder, + LLVMMetadataRef Scope, + LLVMMetadataRef ImportedEntity, + LLVMMetadataRef File, + unsigned Line); + +/** + * Create a descriptor for an imported module. + * \param Builder The \c DIBuilder. + * \param Scope The scope this module is imported into + * \param M The module being imported here + * \param File File where the declaration is located. + * \param Line Line number of the declaration. + */ +LLVMMetadataRef +LLVMDIBuilderCreateImportedModuleFromModule(LLVMDIBuilderRef Builder, + LLVMMetadataRef Scope, + LLVMMetadataRef M, + LLVMMetadataRef File, + unsigned Line); + +/** + * Create a descriptor for an imported function, type, or variable. Suitable + * for e.g. FORTRAN-style USE declarations. + * \param Builder The DIBuilder. + * \param Scope The scope this module is imported into. + * \param Decl The declaration (or definition) of a function, type, + or variable. + * \param File File where the declaration is located. + * \param Line Line number of the declaration. + * \param Name A name that uniquely identifies this imported declaration. + * \param NameLen The length of the C string passed to \c Name. + */ +LLVMMetadataRef +LLVMDIBuilderCreateImportedDeclaration(LLVMDIBuilderRef Builder, + LLVMMetadataRef Scope, + LLVMMetadataRef Decl, + LLVMMetadataRef File, + unsigned Line, + const char *Name, size_t NameLen); + +/** + * Creates a new DebugLocation that describes a source location. + * \param Line The line in the source file. + * \param Column The column in the source file. + * \param Scope The scope in which the location resides. + * \param InlinedAt The scope where this location was inlined, if at all. + * (optional). + * \note If the item to which this location is attached cannot be + * attributed to a source line, pass 0 for the line and column. + */ +LLVMMetadataRef +LLVMDIBuilderCreateDebugLocation(LLVMContextRef Ctx, unsigned Line, + unsigned Column, LLVMMetadataRef Scope, + LLVMMetadataRef InlinedAt); + +/** + * Get the line number of this debug location. + * \param Location The debug location. + * + * @see DILocation::getLine() + */ +unsigned LLVMDILocationGetLine(LLVMMetadataRef Location); + +/** + * Get the column number of this debug location. + * \param Location The debug location. + * + * @see DILocation::getColumn() + */ +unsigned LLVMDILocationGetColumn(LLVMMetadataRef Location); + +/** + * Get the local scope associated with this debug location. + * \param Location The debug location. + * + * @see DILocation::getScope() + */ +LLVMMetadataRef LLVMDILocationGetScope(LLVMMetadataRef Location); + +/** + * Get the "inline at" location associated with this debug location. + * \param Location The debug location. + * + * @see DILocation::getInlinedAt() + */ +LLVMMetadataRef LLVMDILocationGetInlinedAt(LLVMMetadataRef Location); + +/** + * Get the metadata of the file associated with a given scope. + * \param Scope The scope object. + * + * @see DIScope::getFile() + */ +LLVMMetadataRef LLVMDIScopeGetFile(LLVMMetadataRef Scope); + +/** + * Get the directory of a given file. + * \param File The file object. + * \param Len The length of the returned string. + * + * @see DIFile::getDirectory() + */ +const char *LLVMDIFileGetDirectory(LLVMMetadataRef File, unsigned *Len); + +/** + * Get the name of a given file. + * \param File The file object. + * \param Len The length of the returned string. + * + * @see DIFile::getFilename() + */ +const char *LLVMDIFileGetFilename(LLVMMetadataRef File, unsigned *Len); + +/** + * Get the source of a given file. + * \param File The file object. + * \param Len The length of the returned string. + * + * @see DIFile::getSource() + */ +const char *LLVMDIFileGetSource(LLVMMetadataRef File, unsigned *Len); + +/** + * Create a type array. + * \param Builder The DIBuilder. + * \param Data The type elements. + * \param NumElements Number of type elements. + */ +LLVMMetadataRef LLVMDIBuilderGetOrCreateTypeArray(LLVMDIBuilderRef Builder, + LLVMMetadataRef *Data, + size_t NumElements); + +/** + * Create subroutine type. + * \param Builder The DIBuilder. + * \param File The file in which the subroutine resides. + * \param ParameterTypes An array of subroutine parameter types. This + * includes return type at 0th index. + * \param NumParameterTypes The number of parameter types in \c ParameterTypes + * \param Flags E.g.: \c LLVMDIFlagLValueReference. + * These flags are used to emit dwarf attributes. + */ +LLVMMetadataRef +LLVMDIBuilderCreateSubroutineType(LLVMDIBuilderRef Builder, + LLVMMetadataRef File, + LLVMMetadataRef *ParameterTypes, + unsigned NumParameterTypes, + LLVMDIFlags Flags); + +/** + * Create debugging information entry for a macro. + * @param Builder The DIBuilder. + * @param ParentMacroFile Macro parent (could be NULL). + * @param Line Source line number where the macro is defined. + * @param RecordType DW_MACINFO_define or DW_MACINFO_undef. + * @param Name Macro name. + * @param NameLen Macro name length. + * @param Value Macro value. + * @param ValueLen Macro value length. + */ +LLVMMetadataRef LLVMDIBuilderCreateMacro(LLVMDIBuilderRef Builder, + LLVMMetadataRef ParentMacroFile, + unsigned Line, + LLVMDWARFMacinfoRecordType RecordType, + const char *Name, size_t NameLen, + const char *Value, size_t ValueLen); + +/** + * Create debugging information temporary entry for a macro file. + * List of macro node direct children will be calculated by DIBuilder, + * using the \p ParentMacroFile relationship. + * @param Builder The DIBuilder. + * @param ParentMacroFile Macro parent (could be NULL). + * @param Line Source line number where the macro file is included. + * @param File File descriptor containing the name of the macro file. + */ +LLVMMetadataRef +LLVMDIBuilderCreateTempMacroFile(LLVMDIBuilderRef Builder, + LLVMMetadataRef ParentMacroFile, unsigned Line, + LLVMMetadataRef File); + +/** + * Create debugging information entry for an enumerator. + * @param Builder The DIBuilder. + * @param Name Enumerator name. + * @param NameLen Length of enumerator name. + * @param Value Enumerator value. + * @param IsUnsigned True if the value is unsigned. + */ +LLVMMetadataRef LLVMDIBuilderCreateEnumerator(LLVMDIBuilderRef Builder, + const char *Name, size_t NameLen, + int64_t Value, + LLVMBool IsUnsigned); + +/** + * Create debugging information entry for an enumeration. + * \param Builder The DIBuilder. + * \param Scope Scope in which this enumeration is defined. + * \param Name Enumeration name. + * \param NameLen Length of enumeration name. + * \param File File where this member is defined. + * \param LineNumber Line number. + * \param SizeInBits Member size. + * \param AlignInBits Member alignment. + * \param Elements Enumeration elements. + * \param NumElements Number of enumeration elements. + * \param ClassTy Underlying type of a C++11/ObjC fixed enum. + */ +LLVMMetadataRef LLVMDIBuilderCreateEnumerationType( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, LLVMMetadataRef File, unsigned LineNumber, + uint64_t SizeInBits, uint32_t AlignInBits, LLVMMetadataRef *Elements, + unsigned NumElements, LLVMMetadataRef ClassTy); + +/** + * Create debugging information entry for a union. + * \param Builder The DIBuilder. + * \param Scope Scope in which this union is defined. + * \param Name Union name. + * \param NameLen Length of union name. + * \param File File where this member is defined. + * \param LineNumber Line number. + * \param SizeInBits Member size. + * \param AlignInBits Member alignment. + * \param Flags Flags to encode member attribute, e.g. private + * \param Elements Union elements. + * \param NumElements Number of union elements. + * \param RunTimeLang Optional parameter, Objective-C runtime version. + * \param UniqueId A unique identifier for the union. + * \param UniqueIdLen Length of unique identifier. + */ +LLVMMetadataRef LLVMDIBuilderCreateUnionType( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, LLVMMetadataRef File, unsigned LineNumber, + uint64_t SizeInBits, uint32_t AlignInBits, LLVMDIFlags Flags, + LLVMMetadataRef *Elements, unsigned NumElements, unsigned RunTimeLang, + const char *UniqueId, size_t UniqueIdLen); + + +/** + * Create debugging information entry for an array. + * \param Builder The DIBuilder. + * \param Size Array size. + * \param AlignInBits Alignment. + * \param Ty Element type. + * \param Subscripts Subscripts. + * \param NumSubscripts Number of subscripts. + */ +LLVMMetadataRef +LLVMDIBuilderCreateArrayType(LLVMDIBuilderRef Builder, uint64_t Size, + uint32_t AlignInBits, LLVMMetadataRef Ty, + LLVMMetadataRef *Subscripts, + unsigned NumSubscripts); + +/** + * Create debugging information entry for a vector type. + * \param Builder The DIBuilder. + * \param Size Vector size. + * \param AlignInBits Alignment. + * \param Ty Element type. + * \param Subscripts Subscripts. + * \param NumSubscripts Number of subscripts. + */ +LLVMMetadataRef +LLVMDIBuilderCreateVectorType(LLVMDIBuilderRef Builder, uint64_t Size, + uint32_t AlignInBits, LLVMMetadataRef Ty, + LLVMMetadataRef *Subscripts, + unsigned NumSubscripts); + +/** + * Create a DWARF unspecified type. + * \param Builder The DIBuilder. + * \param Name The unspecified type's name. + * \param NameLen Length of type name. + */ +LLVMMetadataRef +LLVMDIBuilderCreateUnspecifiedType(LLVMDIBuilderRef Builder, const char *Name, + size_t NameLen); + +/** + * Create debugging information entry for a basic + * type. + * \param Builder The DIBuilder. + * \param Name Type name. + * \param NameLen Length of type name. + * \param SizeInBits Size of the type. + * \param Encoding DWARF encoding code, e.g. \c LLVMDWARFTypeEncoding_float. + * \param Flags Flags to encode optional attribute like endianity + */ +LLVMMetadataRef +LLVMDIBuilderCreateBasicType(LLVMDIBuilderRef Builder, const char *Name, + size_t NameLen, uint64_t SizeInBits, + LLVMDWARFTypeEncoding Encoding, + LLVMDIFlags Flags); + +/** + * Create debugging information entry for a pointer. + * \param Builder The DIBuilder. + * \param PointeeTy Type pointed by this pointer. + * \param SizeInBits Size. + * \param AlignInBits Alignment. (optional, pass 0 to ignore) + * \param AddressSpace DWARF address space. (optional, pass 0 to ignore) + * \param Name Pointer type name. (optional) + * \param NameLen Length of pointer type name. (optional) + */ +LLVMMetadataRef LLVMDIBuilderCreatePointerType( + LLVMDIBuilderRef Builder, LLVMMetadataRef PointeeTy, + uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace, + const char *Name, size_t NameLen); + +/** + * Create debugging information entry for a struct. + * \param Builder The DIBuilder. + * \param Scope Scope in which this struct is defined. + * \param Name Struct name. + * \param NameLen Struct name length. + * \param File File where this member is defined. + * \param LineNumber Line number. + * \param SizeInBits Member size. + * \param AlignInBits Member alignment. + * \param Flags Flags to encode member attribute, e.g. private + * \param Elements Struct elements. + * \param NumElements Number of struct elements. + * \param RunTimeLang Optional parameter, Objective-C runtime version. + * \param VTableHolder The object containing the vtable for the struct. + * \param UniqueId A unique identifier for the struct. + * \param UniqueIdLen Length of the unique identifier for the struct. + */ +LLVMMetadataRef LLVMDIBuilderCreateStructType( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, LLVMMetadataRef File, unsigned LineNumber, + uint64_t SizeInBits, uint32_t AlignInBits, LLVMDIFlags Flags, + LLVMMetadataRef DerivedFrom, LLVMMetadataRef *Elements, + unsigned NumElements, unsigned RunTimeLang, LLVMMetadataRef VTableHolder, + const char *UniqueId, size_t UniqueIdLen); + +/** + * Create debugging information entry for a member. + * \param Builder The DIBuilder. + * \param Scope Member scope. + * \param Name Member name. + * \param NameLen Length of member name. + * \param File File where this member is defined. + * \param LineNo Line number. + * \param SizeInBits Member size. + * \param AlignInBits Member alignment. + * \param OffsetInBits Member offset. + * \param Flags Flags to encode member attribute, e.g. private + * \param Ty Parent type. + */ +LLVMMetadataRef LLVMDIBuilderCreateMemberType( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, LLVMMetadataRef File, unsigned LineNo, + uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, + LLVMDIFlags Flags, LLVMMetadataRef Ty); + +/** + * Create debugging information entry for a + * C++ static data member. + * \param Builder The DIBuilder. + * \param Scope Member scope. + * \param Name Member name. + * \param NameLen Length of member name. + * \param File File where this member is declared. + * \param LineNumber Line number. + * \param Type Type of the static member. + * \param Flags Flags to encode member attribute, e.g. private. + * \param ConstantVal Const initializer of the member. + * \param AlignInBits Member alignment. + */ +LLVMMetadataRef +LLVMDIBuilderCreateStaticMemberType( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, LLVMMetadataRef File, unsigned LineNumber, + LLVMMetadataRef Type, LLVMDIFlags Flags, LLVMValueRef ConstantVal, + uint32_t AlignInBits); + +/** + * Create debugging information entry for a pointer to member. + * \param Builder The DIBuilder. + * \param PointeeType Type pointed to by this pointer. + * \param ClassType Type for which this pointer points to members of. + * \param SizeInBits Size. + * \param AlignInBits Alignment. + * \param Flags Flags. + */ +LLVMMetadataRef +LLVMDIBuilderCreateMemberPointerType(LLVMDIBuilderRef Builder, + LLVMMetadataRef PointeeType, + LLVMMetadataRef ClassType, + uint64_t SizeInBits, + uint32_t AlignInBits, + LLVMDIFlags Flags); +/** + * Create debugging information entry for Objective-C instance variable. + * \param Builder The DIBuilder. + * \param Name Member name. + * \param NameLen The length of the C string passed to \c Name. + * \param File File where this member is defined. + * \param LineNo Line number. + * \param SizeInBits Member size. + * \param AlignInBits Member alignment. + * \param OffsetInBits Member offset. + * \param Flags Flags to encode member attribute, e.g. private + * \param Ty Parent type. + * \param PropertyNode Property associated with this ivar. + */ +LLVMMetadataRef +LLVMDIBuilderCreateObjCIVar(LLVMDIBuilderRef Builder, + const char *Name, size_t NameLen, + LLVMMetadataRef File, unsigned LineNo, + uint64_t SizeInBits, uint32_t AlignInBits, + uint64_t OffsetInBits, LLVMDIFlags Flags, + LLVMMetadataRef Ty, LLVMMetadataRef PropertyNode); + +/** + * Create debugging information entry for Objective-C property. + * \param Builder The DIBuilder. + * \param Name Property name. + * \param NameLen The length of the C string passed to \c Name. + * \param File File where this property is defined. + * \param LineNo Line number. + * \param GetterName Name of the Objective C property getter selector. + * \param GetterNameLen The length of the C string passed to \c GetterName. + * \param SetterName Name of the Objective C property setter selector. + * \param SetterNameLen The length of the C string passed to \c SetterName. + * \param PropertyAttributes Objective C property attributes. + * \param Ty Type. + */ +LLVMMetadataRef +LLVMDIBuilderCreateObjCProperty(LLVMDIBuilderRef Builder, + const char *Name, size_t NameLen, + LLVMMetadataRef File, unsigned LineNo, + const char *GetterName, size_t GetterNameLen, + const char *SetterName, size_t SetterNameLen, + unsigned PropertyAttributes, + LLVMMetadataRef Ty); + +/** + * Create a uniqued DIType* clone with FlagObjectPointer and FlagArtificial set. + * \param Builder The DIBuilder. + * \param Type The underlying type to which this pointer points. + */ +LLVMMetadataRef +LLVMDIBuilderCreateObjectPointerType(LLVMDIBuilderRef Builder, + LLVMMetadataRef Type); + +/** + * Create debugging information entry for a qualified + * type, e.g. 'const int'. + * \param Builder The DIBuilder. + * \param Tag Tag identifying type, + * e.g. LLVMDWARFTypeQualifier_volatile_type + * \param Type Base Type. + */ +LLVMMetadataRef +LLVMDIBuilderCreateQualifiedType(LLVMDIBuilderRef Builder, unsigned Tag, + LLVMMetadataRef Type); + +/** + * Create debugging information entry for a c++ + * style reference or rvalue reference type. + * \param Builder The DIBuilder. + * \param Tag Tag identifying type, + * \param Type Base Type. + */ +LLVMMetadataRef +LLVMDIBuilderCreateReferenceType(LLVMDIBuilderRef Builder, unsigned Tag, + LLVMMetadataRef Type); + +/** + * Create C++11 nullptr type. + * \param Builder The DIBuilder. + */ +LLVMMetadataRef +LLVMDIBuilderCreateNullPtrType(LLVMDIBuilderRef Builder); + +/** + * Create debugging information entry for a typedef. + * \param Builder The DIBuilder. + * \param Type Original type. + * \param Name Typedef name. + * \param File File where this type is defined. + * \param LineNo Line number. + * \param Scope The surrounding context for the typedef. + */ +LLVMMetadataRef +LLVMDIBuilderCreateTypedef(LLVMDIBuilderRef Builder, LLVMMetadataRef Type, + const char *Name, size_t NameLen, + LLVMMetadataRef File, unsigned LineNo, + LLVMMetadataRef Scope, uint32_t AlignInBits); + +/** + * Create debugging information entry to establish inheritance relationship + * between two types. + * \param Builder The DIBuilder. + * \param Ty Original type. + * \param BaseTy Base type. Ty is inherits from base. + * \param BaseOffset Base offset. + * \param VBPtrOffset Virtual base pointer offset. + * \param Flags Flags to describe inheritance attribute, e.g. private + */ +LLVMMetadataRef +LLVMDIBuilderCreateInheritance(LLVMDIBuilderRef Builder, + LLVMMetadataRef Ty, LLVMMetadataRef BaseTy, + uint64_t BaseOffset, uint32_t VBPtrOffset, + LLVMDIFlags Flags); + +/** + * Create a permanent forward-declared type. + * \param Builder The DIBuilder. + * \param Tag A unique tag for this type. + * \param Name Type name. + * \param NameLen Length of type name. + * \param Scope Type scope. + * \param File File where this type is defined. + * \param Line Line number where this type is defined. + * \param RuntimeLang Indicates runtime version for languages like + * Objective-C. + * \param SizeInBits Member size. + * \param AlignInBits Member alignment. + * \param UniqueIdentifier A unique identifier for the type. + * \param UniqueIdentifierLen Length of the unique identifier. + */ +LLVMMetadataRef LLVMDIBuilderCreateForwardDecl( + LLVMDIBuilderRef Builder, unsigned Tag, const char *Name, + size_t NameLen, LLVMMetadataRef Scope, LLVMMetadataRef File, unsigned Line, + unsigned RuntimeLang, uint64_t SizeInBits, uint32_t AlignInBits, + const char *UniqueIdentifier, size_t UniqueIdentifierLen); + +/** + * Create a temporary forward-declared type. + * \param Builder The DIBuilder. + * \param Tag A unique tag for this type. + * \param Name Type name. + * \param NameLen Length of type name. + * \param Scope Type scope. + * \param File File where this type is defined. + * \param Line Line number where this type is defined. + * \param RuntimeLang Indicates runtime version for languages like + * Objective-C. + * \param SizeInBits Member size. + * \param AlignInBits Member alignment. + * \param Flags Flags. + * \param UniqueIdentifier A unique identifier for the type. + * \param UniqueIdentifierLen Length of the unique identifier. + */ +LLVMMetadataRef +LLVMDIBuilderCreateReplaceableCompositeType( + LLVMDIBuilderRef Builder, unsigned Tag, const char *Name, + size_t NameLen, LLVMMetadataRef Scope, LLVMMetadataRef File, unsigned Line, + unsigned RuntimeLang, uint64_t SizeInBits, uint32_t AlignInBits, + LLVMDIFlags Flags, const char *UniqueIdentifier, + size_t UniqueIdentifierLen); + +/** + * Create debugging information entry for a bit field member. + * \param Builder The DIBuilder. + * \param Scope Member scope. + * \param Name Member name. + * \param NameLen Length of member name. + * \param File File where this member is defined. + * \param LineNumber Line number. + * \param SizeInBits Member size. + * \param OffsetInBits Member offset. + * \param StorageOffsetInBits Member storage offset. + * \param Flags Flags to encode member attribute. + * \param Type Parent type. + */ +LLVMMetadataRef +LLVMDIBuilderCreateBitFieldMemberType(LLVMDIBuilderRef Builder, + LLVMMetadataRef Scope, + const char *Name, size_t NameLen, + LLVMMetadataRef File, unsigned LineNumber, + uint64_t SizeInBits, + uint64_t OffsetInBits, + uint64_t StorageOffsetInBits, + LLVMDIFlags Flags, LLVMMetadataRef Type); + +/** + * Create debugging information entry for a class. + * \param Scope Scope in which this class is defined. + * \param Name Class name. + * \param NameLen The length of the C string passed to \c Name. + * \param File File where this member is defined. + * \param LineNumber Line number. + * \param SizeInBits Member size. + * \param AlignInBits Member alignment. + * \param OffsetInBits Member offset. + * \param Flags Flags to encode member attribute, e.g. private. + * \param DerivedFrom Debug info of the base class of this type. + * \param Elements Class members. + * \param NumElements Number of class elements. + * \param VTableHolder Debug info of the base class that contains vtable + * for this type. This is used in + * DW_AT_containing_type. See DWARF documentation + * for more info. + * \param TemplateParamsNode Template type parameters. + * \param UniqueIdentifier A unique identifier for the type. + * \param UniqueIdentifierLen Length of the unique identifier. + */ +LLVMMetadataRef LLVMDIBuilderCreateClassType(LLVMDIBuilderRef Builder, + LLVMMetadataRef Scope, const char *Name, size_t NameLen, + LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits, + uint32_t AlignInBits, uint64_t OffsetInBits, LLVMDIFlags Flags, + LLVMMetadataRef DerivedFrom, + LLVMMetadataRef *Elements, unsigned NumElements, + LLVMMetadataRef VTableHolder, LLVMMetadataRef TemplateParamsNode, + const char *UniqueIdentifier, size_t UniqueIdentifierLen); + +/** + * Create a uniqued DIType* clone with FlagArtificial set. + * \param Builder The DIBuilder. + * \param Type The underlying type. + */ +LLVMMetadataRef +LLVMDIBuilderCreateArtificialType(LLVMDIBuilderRef Builder, + LLVMMetadataRef Type); + +/** + * Get the name of this DIType. + * \param DType The DIType. + * \param Length The length of the returned string. + * + * @see DIType::getName() + */ +const char *LLVMDITypeGetName(LLVMMetadataRef DType, size_t *Length); + +/** + * Get the size of this DIType in bits. + * \param DType The DIType. + * + * @see DIType::getSizeInBits() + */ +uint64_t LLVMDITypeGetSizeInBits(LLVMMetadataRef DType); + +/** + * Get the offset of this DIType in bits. + * \param DType The DIType. + * + * @see DIType::getOffsetInBits() + */ +uint64_t LLVMDITypeGetOffsetInBits(LLVMMetadataRef DType); + +/** + * Get the alignment of this DIType in bits. + * \param DType The DIType. + * + * @see DIType::getAlignInBits() + */ +uint32_t LLVMDITypeGetAlignInBits(LLVMMetadataRef DType); + +/** + * Get the source line where this DIType is declared. + * \param DType The DIType. + * + * @see DIType::getLine() + */ +unsigned LLVMDITypeGetLine(LLVMMetadataRef DType); + +/** + * Get the flags associated with this DIType. + * \param DType The DIType. + * + * @see DIType::getFlags() + */ +LLVMDIFlags LLVMDITypeGetFlags(LLVMMetadataRef DType); + +/** + * Create a descriptor for a value range. + * \param Builder The DIBuilder. + * \param LowerBound Lower bound of the subrange, e.g. 0 for C, 1 for Fortran. + * \param Count Count of elements in the subrange. + */ +LLVMMetadataRef LLVMDIBuilderGetOrCreateSubrange(LLVMDIBuilderRef Builder, + int64_t LowerBound, + int64_t Count); + +/** + * Create an array of DI Nodes. + * \param Builder The DIBuilder. + * \param Data The DI Node elements. + * \param NumElements Number of DI Node elements. + */ +LLVMMetadataRef LLVMDIBuilderGetOrCreateArray(LLVMDIBuilderRef Builder, + LLVMMetadataRef *Data, + size_t NumElements); + +/** + * Create a new descriptor for the specified variable which has a complex + * address expression for its address. + * \param Builder The DIBuilder. + * \param Addr An array of complex address operations. + * \param Length Length of the address operation array. + */ +LLVMMetadataRef LLVMDIBuilderCreateExpression(LLVMDIBuilderRef Builder, + int64_t *Addr, size_t Length); + +/** + * Create a new descriptor for the specified variable that does not have an + * address, but does have a constant value. + * \param Builder The DIBuilder. + * \param Value The constant value. + */ +LLVMMetadataRef +LLVMDIBuilderCreateConstantValueExpression(LLVMDIBuilderRef Builder, + int64_t Value); + +/** + * Create a new descriptor for the specified variable. + * \param Scope Variable scope. + * \param Name Name of the variable. + * \param NameLen The length of the C string passed to \c Name. + * \param Linkage Mangled name of the variable. + * \param LinkLen The length of the C string passed to \c Linkage. + * \param File File where this variable is defined. + * \param LineNo Line number. + * \param Ty Variable Type. + * \param LocalToUnit Boolean flag indicate whether this variable is + * externally visible or not. + * \param Expr The location of the global relative to the attached + * GlobalVariable. + * \param Decl Reference to the corresponding declaration. + * variables. + * \param AlignInBits Variable alignment(or 0 if no alignment attr was + * specified) + */ +LLVMMetadataRef LLVMDIBuilderCreateGlobalVariableExpression( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, const char *Linkage, size_t LinkLen, LLVMMetadataRef File, + unsigned LineNo, LLVMMetadataRef Ty, LLVMBool LocalToUnit, + LLVMMetadataRef Expr, LLVMMetadataRef Decl, uint32_t AlignInBits); + +/** + * Retrieves the \c DIVariable associated with this global variable expression. + * \param GVE The global variable expression. + * + * @see llvm::DIGlobalVariableExpression::getVariable() + */ +LLVMMetadataRef LLVMDIGlobalVariableExpressionGetVariable(LLVMMetadataRef GVE); + +/** + * Retrieves the \c DIExpression associated with this global variable expression. + * \param GVE The global variable expression. + * + * @see llvm::DIGlobalVariableExpression::getExpression() + */ +LLVMMetadataRef LLVMDIGlobalVariableExpressionGetExpression( + LLVMMetadataRef GVE); + +/** + * Get the metadata of the file associated with a given variable. + * \param Var The variable object. + * + * @see DIVariable::getFile() + */ +LLVMMetadataRef LLVMDIVariableGetFile(LLVMMetadataRef Var); + +/** + * Get the metadata of the scope associated with a given variable. + * \param Var The variable object. + * + * @see DIVariable::getScope() + */ +LLVMMetadataRef LLVMDIVariableGetScope(LLVMMetadataRef Var); + +/** + * Get the source line where this \c DIVariable is declared. + * \param Var The DIVariable. + * + * @see DIVariable::getLine() + */ +unsigned LLVMDIVariableGetLine(LLVMMetadataRef Var); + +/** + * Create a new temporary \c MDNode. Suitable for use in constructing cyclic + * \c MDNode structures. A temporary \c MDNode is not uniqued, may be RAUW'd, + * and must be manually deleted with \c LLVMDisposeTemporaryMDNode. + * \param Ctx The context in which to construct the temporary node. + * \param Data The metadata elements. + * \param NumElements Number of metadata elements. + */ +LLVMMetadataRef LLVMTemporaryMDNode(LLVMContextRef Ctx, LLVMMetadataRef *Data, + size_t NumElements); + +/** + * Deallocate a temporary node. + * + * Calls \c replaceAllUsesWith(nullptr) before deleting, so any remaining + * references will be reset. + * \param TempNode The temporary metadata node. + */ +void LLVMDisposeTemporaryMDNode(LLVMMetadataRef TempNode); + +/** + * Replace all uses of temporary metadata. + * \param TempTargetMetadata The temporary metadata node. + * \param Replacement The replacement metadata node. + */ +void LLVMMetadataReplaceAllUsesWith(LLVMMetadataRef TempTargetMetadata, + LLVMMetadataRef Replacement); + +/** + * Create a new descriptor for the specified global variable that is temporary + * and meant to be RAUWed. + * \param Scope Variable scope. + * \param Name Name of the variable. + * \param NameLen The length of the C string passed to \c Name. + * \param Linkage Mangled name of the variable. + * \param LnkLen The length of the C string passed to \c Linkage. + * \param File File where this variable is defined. + * \param LineNo Line number. + * \param Ty Variable Type. + * \param LocalToUnit Boolean flag indicate whether this variable is + * externally visible or not. + * \param Decl Reference to the corresponding declaration. + * \param AlignInBits Variable alignment(or 0 if no alignment attr was + * specified) + */ +LLVMMetadataRef LLVMDIBuilderCreateTempGlobalVariableFwdDecl( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, const char *Linkage, size_t LnkLen, LLVMMetadataRef File, + unsigned LineNo, LLVMMetadataRef Ty, LLVMBool LocalToUnit, + LLVMMetadataRef Decl, uint32_t AlignInBits); + +/** + * Insert a new llvm.dbg.declare intrinsic call before the given instruction. + * \param Builder The DIBuilder. + * \param Storage The storage of the variable to declare. + * \param VarInfo The variable's debug info descriptor. + * \param Expr A complex location expression for the variable. + * \param DebugLoc Debug info location. + * \param Instr Instruction acting as a location for the new intrinsic. + */ +LLVMValueRef LLVMDIBuilderInsertDeclareBefore( + LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMValueRef Instr); + +/** + * Insert a new llvm.dbg.declare intrinsic call at the end of the given basic + * block. If the basic block has a terminator instruction, the intrinsic is + * inserted before that terminator instruction. + * \param Builder The DIBuilder. + * \param Storage The storage of the variable to declare. + * \param VarInfo The variable's debug info descriptor. + * \param Expr A complex location expression for the variable. + * \param DebugLoc Debug info location. + * \param Block Basic block acting as a location for the new intrinsic. + */ +LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd( + LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMBasicBlockRef Block); + +/** + * Insert a new llvm.dbg.value intrinsic call before the given instruction. + * \param Builder The DIBuilder. + * \param Val The value of the variable. + * \param VarInfo The variable's debug info descriptor. + * \param Expr A complex location expression for the variable. + * \param DebugLoc Debug info location. + * \param Instr Instruction acting as a location for the new intrinsic. + */ +LLVMValueRef LLVMDIBuilderInsertDbgValueBefore(LLVMDIBuilderRef Builder, + LLVMValueRef Val, + LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, + LLVMMetadataRef DebugLoc, + LLVMValueRef Instr); + +/** + * Insert a new llvm.dbg.value intrinsic call at the end of the given basic + * block. If the basic block has a terminator instruction, the intrinsic is + * inserted before that terminator instruction. + * \param Builder The DIBuilder. + * \param Val The value of the variable. + * \param VarInfo The variable's debug info descriptor. + * \param Expr A complex location expression for the variable. + * \param DebugLoc Debug info location. + * \param Block Basic block acting as a location for the new intrinsic. + */ +LLVMValueRef LLVMDIBuilderInsertDbgValueAtEnd(LLVMDIBuilderRef Builder, + LLVMValueRef Val, + LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, + LLVMMetadataRef DebugLoc, + LLVMBasicBlockRef Block); + +/** + * Create a new descriptor for a local auto variable. + * \param Builder The DIBuilder. + * \param Scope The local scope the variable is declared in. + * \param Name Variable name. + * \param NameLen Length of variable name. + * \param File File where this variable is defined. + * \param LineNo Line number. + * \param Ty Metadata describing the type of the variable. + * \param AlwaysPreserve If true, this descriptor will survive optimizations. + * \param Flags Flags. + * \param AlignInBits Variable alignment. + */ +LLVMMetadataRef LLVMDIBuilderCreateAutoVariable( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty, + LLVMBool AlwaysPreserve, LLVMDIFlags Flags, uint32_t AlignInBits); + +/** + * Create a new descriptor for a function parameter variable. + * \param Builder The DIBuilder. + * \param Scope The local scope the variable is declared in. + * \param Name Variable name. + * \param NameLen Length of variable name. + * \param ArgNo Unique argument number for this variable; starts at 1. + * \param File File where this variable is defined. + * \param LineNo Line number. + * \param Ty Metadata describing the type of the variable. + * \param AlwaysPreserve If true, this descriptor will survive optimizations. + * \param Flags Flags. + */ +LLVMMetadataRef LLVMDIBuilderCreateParameterVariable( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, unsigned ArgNo, LLVMMetadataRef File, unsigned LineNo, + LLVMMetadataRef Ty, LLVMBool AlwaysPreserve, LLVMDIFlags Flags); + +/** + * Get the metadata of the subprogram attached to a function. + * + * @see llvm::Function::getSubprogram() + */ +LLVMMetadataRef LLVMGetSubprogram(LLVMValueRef Func); + +/** + * Set the subprogram attached to a function. + * + * @see llvm::Function::setSubprogram() + */ +void LLVMSetSubprogram(LLVMValueRef Func, LLVMMetadataRef SP); + +/** + * Get the line associated with a given subprogram. + * \param Subprogram The subprogram object. + * + * @see DISubprogram::getLine() + */ +unsigned LLVMDISubprogramGetLine(LLVMMetadataRef Subprogram); + +/** + * Get the debug location for the given instruction. + * + * @see llvm::Instruction::getDebugLoc() + */ +LLVMMetadataRef LLVMInstructionGetDebugLoc(LLVMValueRef Inst); + +/** + * Set the debug location for the given instruction. + * + * To clear the location metadata of the given instruction, pass NULL to \p Loc. + * + * @see llvm::Instruction::setDebugLoc() + */ +void LLVMInstructionSetDebugLoc(LLVMValueRef Inst, LLVMMetadataRef Loc); + +/** + * Obtain the enumerated type of a Metadata instance. + * + * @see llvm::Metadata::getMetadataID() + */ +LLVMMetadataKind LLVMGetMetadataKind(LLVMMetadataRef Metadata); + +LLVM_C_EXTERN_C_END + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/Disassembler.h b/third_party/llvm-10.0/llvm/include/llvm-c/Disassembler.h new file mode 100644 index 0000000..b1cb35d --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/Disassembler.h
@@ -0,0 +1,110 @@ +/*===-- llvm-c/Disassembler.h - Disassembler Public C Interface ---*- C -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header provides a public interface to a disassembler library. *| +|* LLVM provides an implementation of this interface. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_DISASSEMBLER_H +#define LLVM_C_DISASSEMBLER_H + +#include "llvm-c/DisassemblerTypes.h" +#include "llvm-c/ExternC.h" + +/** + * @defgroup LLVMCDisassembler Disassembler + * @ingroup LLVMC + * + * @{ + */ + +LLVM_C_EXTERN_C_BEGIN + +/** + * Create a disassembler for the TripleName. Symbolic disassembly is supported + * by passing a block of information in the DisInfo parameter and specifying the + * TagType and callback functions as described above. These can all be passed + * as NULL. If successful, this returns a disassembler context. If not, it + * returns NULL. This function is equivalent to calling + * LLVMCreateDisasmCPUFeatures() with an empty CPU name and feature set. + */ +LLVMDisasmContextRef LLVMCreateDisasm(const char *TripleName, void *DisInfo, + int TagType, LLVMOpInfoCallback GetOpInfo, + LLVMSymbolLookupCallback SymbolLookUp); + +/** + * Create a disassembler for the TripleName and a specific CPU. Symbolic + * disassembly is supported by passing a block of information in the DisInfo + * parameter and specifying the TagType and callback functions as described + * above. These can all be passed * as NULL. If successful, this returns a + * disassembler context. If not, it returns NULL. This function is equivalent + * to calling LLVMCreateDisasmCPUFeatures() with an empty feature set. + */ +LLVMDisasmContextRef LLVMCreateDisasmCPU(const char *Triple, const char *CPU, + void *DisInfo, int TagType, + LLVMOpInfoCallback GetOpInfo, + LLVMSymbolLookupCallback SymbolLookUp); + +/** + * Create a disassembler for the TripleName, a specific CPU and specific feature + * string. Symbolic disassembly is supported by passing a block of information + * in the DisInfo parameter and specifying the TagType and callback functions as + * described above. These can all be passed * as NULL. If successful, this + * returns a disassembler context. If not, it returns NULL. + */ +LLVMDisasmContextRef +LLVMCreateDisasmCPUFeatures(const char *Triple, const char *CPU, + const char *Features, void *DisInfo, int TagType, + LLVMOpInfoCallback GetOpInfo, + LLVMSymbolLookupCallback SymbolLookUp); + +/** + * Set the disassembler's options. Returns 1 if it can set the Options and 0 + * otherwise. + */ +int LLVMSetDisasmOptions(LLVMDisasmContextRef DC, uint64_t Options); + +/* The option to produce marked up assembly. */ +#define LLVMDisassembler_Option_UseMarkup 1 +/* The option to print immediates as hex. */ +#define LLVMDisassembler_Option_PrintImmHex 2 +/* The option use the other assembler printer variant */ +#define LLVMDisassembler_Option_AsmPrinterVariant 4 +/* The option to set comment on instructions */ +#define LLVMDisassembler_Option_SetInstrComments 8 + /* The option to print latency information alongside instructions */ +#define LLVMDisassembler_Option_PrintLatency 16 + +/** + * Dispose of a disassembler context. + */ +void LLVMDisasmDispose(LLVMDisasmContextRef DC); + +/** + * Disassemble a single instruction using the disassembler context specified in + * the parameter DC. The bytes of the instruction are specified in the + * parameter Bytes, and contains at least BytesSize number of bytes. The + * instruction is at the address specified by the PC parameter. If a valid + * instruction can be disassembled, its string is returned indirectly in + * OutString whose size is specified in the parameter OutStringSize. This + * function returns the number of bytes in the instruction or zero if there was + * no valid instruction. + */ +size_t LLVMDisasmInstruction(LLVMDisasmContextRef DC, uint8_t *Bytes, + uint64_t BytesSize, uint64_t PC, + char *OutString, size_t OutStringSize); + +/** + * @} + */ + +LLVM_C_EXTERN_C_END + +#endif /* LLVM_C_DISASSEMBLER_H */
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/DisassemblerTypes.h b/third_party/llvm-10.0/llvm/include/llvm-c/DisassemblerTypes.h new file mode 100644 index 0000000..389e5ee --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/DisassemblerTypes.h
@@ -0,0 +1,160 @@ +/*===-- llvm-c/DisassemblerTypedefs.h -----------------------------*- C -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_DISASSEMBLER_TYPES_H +#define LLVM_DISASSEMBLER_TYPES_H + +#include "llvm-c/DataTypes.h" +#ifdef __cplusplus +#include <cstddef> +#else +#include <stddef.h> +#endif + +/** + * An opaque reference to a disassembler context. + */ +typedef void *LLVMDisasmContextRef; + +/** + * The type for the operand information call back function. This is called to + * get the symbolic information for an operand of an instruction. Typically + * this is from the relocation information, symbol table, etc. That block of + * information is saved when the disassembler context is created and passed to + * the call back in the DisInfo parameter. The instruction containing operand + * is at the PC parameter. For some instruction sets, there can be more than + * one operand with symbolic information. To determine the symbolic operand + * information for each operand, the bytes for the specific operand in the + * instruction are specified by the Offset parameter and its byte widith is the + * size parameter. For instructions sets with fixed widths and one symbolic + * operand per instruction, the Offset parameter will be zero and Size parameter + * will be the instruction width. The information is returned in TagBuf and is + * Triple specific with its specific information defined by the value of + * TagType for that Triple. If symbolic information is returned the function + * returns 1, otherwise it returns 0. + */ +typedef int (*LLVMOpInfoCallback)(void *DisInfo, uint64_t PC, + uint64_t Offset, uint64_t Size, + int TagType, void *TagBuf); + +/** + * The initial support in LLVM MC for the most general form of a relocatable + * expression is "AddSymbol - SubtractSymbol + Offset". For some Darwin targets + * this full form is encoded in the relocation information so that AddSymbol and + * SubtractSymbol can be link edited independent of each other. Many other + * platforms only allow a relocatable expression of the form AddSymbol + Offset + * to be encoded. + * + * The LLVMOpInfoCallback() for the TagType value of 1 uses the struct + * LLVMOpInfo1. The value of the relocatable expression for the operand, + * including any PC adjustment, is passed in to the call back in the Value + * field. The symbolic information about the operand is returned using all + * the fields of the structure with the Offset of the relocatable expression + * returned in the Value field. It is possible that some symbols in the + * relocatable expression were assembly temporary symbols, for example + * "Ldata - LpicBase + constant", and only the Values of the symbols without + * symbol names are present in the relocation information. The VariantKind + * type is one of the Target specific #defines below and is used to print + * operands like "_foo@GOT", ":lower16:_foo", etc. + */ +struct LLVMOpInfoSymbol1 { + uint64_t Present; /* 1 if this symbol is present */ + const char *Name; /* symbol name if not NULL */ + uint64_t Value; /* symbol value if name is NULL */ +}; + +struct LLVMOpInfo1 { + struct LLVMOpInfoSymbol1 AddSymbol; + struct LLVMOpInfoSymbol1 SubtractSymbol; + uint64_t Value; + uint64_t VariantKind; +}; + +/** + * The operand VariantKinds for symbolic disassembly. + */ +#define LLVMDisassembler_VariantKind_None 0 /* all targets */ + +/** + * The ARM target VariantKinds. + */ +#define LLVMDisassembler_VariantKind_ARM_HI16 1 /* :upper16: */ +#define LLVMDisassembler_VariantKind_ARM_LO16 2 /* :lower16: */ + +/** + * The ARM64 target VariantKinds. + */ +#define LLVMDisassembler_VariantKind_ARM64_PAGE 1 /* @page */ +#define LLVMDisassembler_VariantKind_ARM64_PAGEOFF 2 /* @pageoff */ +#define LLVMDisassembler_VariantKind_ARM64_GOTPAGE 3 /* @gotpage */ +#define LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF 4 /* @gotpageoff */ +#define LLVMDisassembler_VariantKind_ARM64_TLVP 5 /* @tvlppage */ +#define LLVMDisassembler_VariantKind_ARM64_TLVOFF 6 /* @tvlppageoff */ + +/** + * The type for the symbol lookup function. This may be called by the + * disassembler for things like adding a comment for a PC plus a constant + * offset load instruction to use a symbol name instead of a load address value. + * It is passed the block information is saved when the disassembler context is + * created and the ReferenceValue to look up as a symbol. If no symbol is found + * for the ReferenceValue NULL is returned. The ReferenceType of the + * instruction is passed indirectly as is the PC of the instruction in + * ReferencePC. If the output reference can be determined its type is returned + * indirectly in ReferenceType along with ReferenceName if any, or that is set + * to NULL. + */ +typedef const char *(*LLVMSymbolLookupCallback)(void *DisInfo, + uint64_t ReferenceValue, + uint64_t *ReferenceType, + uint64_t ReferencePC, + const char **ReferenceName); +/** + * The reference types on input and output. + */ +/* No input reference type or no output reference type. */ +#define LLVMDisassembler_ReferenceType_InOut_None 0 + +/* The input reference is from a branch instruction. */ +#define LLVMDisassembler_ReferenceType_In_Branch 1 +/* The input reference is from a PC relative load instruction. */ +#define LLVMDisassembler_ReferenceType_In_PCrel_Load 2 + +/* The input reference is from an ARM64::ADRP instruction. */ +#define LLVMDisassembler_ReferenceType_In_ARM64_ADRP 0x100000001 +/* The input reference is from an ARM64::ADDXri instruction. */ +#define LLVMDisassembler_ReferenceType_In_ARM64_ADDXri 0x100000002 +/* The input reference is from an ARM64::LDRXui instruction. */ +#define LLVMDisassembler_ReferenceType_In_ARM64_LDRXui 0x100000003 +/* The input reference is from an ARM64::LDRXl instruction. */ +#define LLVMDisassembler_ReferenceType_In_ARM64_LDRXl 0x100000004 +/* The input reference is from an ARM64::ADR instruction. */ +#define LLVMDisassembler_ReferenceType_In_ARM64_ADR 0x100000005 + +/* The output reference is to as symbol stub. */ +#define LLVMDisassembler_ReferenceType_Out_SymbolStub 1 +/* The output reference is to a symbol address in a literal pool. */ +#define LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr 2 +/* The output reference is to a cstring address in a literal pool. */ +#define LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr 3 + +/* The output reference is to a Objective-C CoreFoundation string. */ +#define LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref 4 +/* The output reference is to a Objective-C message. */ +#define LLVMDisassembler_ReferenceType_Out_Objc_Message 5 +/* The output reference is to a Objective-C message ref. */ +#define LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref 6 +/* The output reference is to a Objective-C selector ref. */ +#define LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref 7 +/* The output reference is to a Objective-C class ref. */ +#define LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref 8 + +/* The output reference is to a C++ symbol name. */ +#define LLVMDisassembler_ReferenceType_DeMangled_Name 9 + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/Error.h b/third_party/llvm-10.0/llvm/include/llvm-c/Error.h new file mode 100644 index 0000000..92f81bf --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/Error.h
@@ -0,0 +1,67 @@ +/*===------- llvm-c/Error.h - llvm::Error class C Interface -------*- C -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file defines the C interface to LLVM's Error class. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_ERROR_H +#define LLVM_C_ERROR_H + +#include "llvm-c/ExternC.h" + +LLVM_C_EXTERN_C_BEGIN + +#define LLVMErrorSuccess 0 + +/** + * Opaque reference to an error instance. Null serves as the 'success' value. + */ +typedef struct LLVMOpaqueError *LLVMErrorRef; + +/** + * Error type identifier. + */ +typedef const void *LLVMErrorTypeId; + +/** + * Returns the type id for the given error instance, which must be a failure + * value (i.e. non-null). + */ +LLVMErrorTypeId LLVMGetErrorTypeId(LLVMErrorRef Err); + +/** + * Dispose of the given error without handling it. This operation consumes the + * error, and the given LLVMErrorRef value is not usable once this call returns. + * Note: This method *only* needs to be called if the error is not being passed + * to some other consuming operation, e.g. LLVMGetErrorMessage. + */ +void LLVMConsumeError(LLVMErrorRef Err); + +/** + * Returns the given string's error message. This operation consumes the error, + * and the given LLVMErrorRef value is not usable once this call returns. + * The caller is responsible for disposing of the string by calling + * LLVMDisposeErrorMessage. + */ +char *LLVMGetErrorMessage(LLVMErrorRef Err); + +/** + * Dispose of the given error message. + */ +void LLVMDisposeErrorMessage(char *ErrMsg); + +/** + * Returns the type id for llvm StringError. + */ +LLVMErrorTypeId LLVMGetStringErrorTypeId(void); + +LLVM_C_EXTERN_C_END + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/ErrorHandling.h b/third_party/llvm-10.0/llvm/include/llvm-c/ErrorHandling.h new file mode 100644 index 0000000..c6f7ff3 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/ErrorHandling.h
@@ -0,0 +1,47 @@ +/*===-- llvm-c/ErrorHandling.h - Error Handling C Interface -------*- C -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file defines the C interface to LLVM's error handling mechanism. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_ERROR_HANDLING_H +#define LLVM_C_ERROR_HANDLING_H + +#include "llvm-c/ExternC.h" + +LLVM_C_EXTERN_C_BEGIN + +typedef void (*LLVMFatalErrorHandler)(const char *Reason); + +/** + * Install a fatal error handler. By default, if LLVM detects a fatal error, it + * will call exit(1). This may not be appropriate in many contexts. For example, + * doing exit(1) will bypass many crash reporting/tracing system tools. This + * function allows you to install a callback that will be invoked prior to the + * call to exit(1). + */ +void LLVMInstallFatalErrorHandler(LLVMFatalErrorHandler Handler); + +/** + * Reset the fatal error handler. This resets LLVM's fatal error handling + * behavior to the default. + */ +void LLVMResetFatalErrorHandler(void); + +/** + * Enable LLVM's built-in stack trace code. This intercepts the OS's crash + * signals and prints which component of LLVM you were in at the time if the + * crash. + */ +void LLVMEnablePrettyStackTrace(void); + +LLVM_C_EXTERN_C_END + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/ExecutionEngine.h b/third_party/llvm-10.0/llvm/include/llvm-c/ExecutionEngine.h new file mode 100644 index 0000000..f31b97a --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/ExecutionEngine.h
@@ -0,0 +1,197 @@ +/*===-- llvm-c/ExecutionEngine.h - ExecutionEngine Lib C Iface --*- C++ -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to libLLVMExecutionEngine.o, which *| +|* implements various analyses of the LLVM IR. *| +|* *| +|* Many exotic languages can interoperate with C code but have a harder time *| +|* with C++ due to name mangling. So in addition to C, this interface enables *| +|* tools written in such languages. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_EXECUTIONENGINE_H +#define LLVM_C_EXECUTIONENGINE_H + +#include "llvm-c/ExternC.h" +#include "llvm-c/Target.h" +#include "llvm-c/TargetMachine.h" +#include "llvm-c/Types.h" + +LLVM_C_EXTERN_C_BEGIN + +/** + * @defgroup LLVMCExecutionEngine Execution Engine + * @ingroup LLVMC + * + * @{ + */ + +void LLVMLinkInMCJIT(void); +void LLVMLinkInInterpreter(void); + +typedef struct LLVMOpaqueGenericValue *LLVMGenericValueRef; +typedef struct LLVMOpaqueExecutionEngine *LLVMExecutionEngineRef; +typedef struct LLVMOpaqueMCJITMemoryManager *LLVMMCJITMemoryManagerRef; + +struct LLVMMCJITCompilerOptions { + unsigned OptLevel; + LLVMCodeModel CodeModel; + LLVMBool NoFramePointerElim; + LLVMBool EnableFastISel; + LLVMMCJITMemoryManagerRef MCJMM; +}; + +/*===-- Operations on generic values --------------------------------------===*/ + +LLVMGenericValueRef LLVMCreateGenericValueOfInt(LLVMTypeRef Ty, + unsigned long long N, + LLVMBool IsSigned); + +LLVMGenericValueRef LLVMCreateGenericValueOfPointer(void *P); + +LLVMGenericValueRef LLVMCreateGenericValueOfFloat(LLVMTypeRef Ty, double N); + +unsigned LLVMGenericValueIntWidth(LLVMGenericValueRef GenValRef); + +unsigned long long LLVMGenericValueToInt(LLVMGenericValueRef GenVal, + LLVMBool IsSigned); + +void *LLVMGenericValueToPointer(LLVMGenericValueRef GenVal); + +double LLVMGenericValueToFloat(LLVMTypeRef TyRef, LLVMGenericValueRef GenVal); + +void LLVMDisposeGenericValue(LLVMGenericValueRef GenVal); + +/*===-- Operations on execution engines -----------------------------------===*/ + +LLVMBool LLVMCreateExecutionEngineForModule(LLVMExecutionEngineRef *OutEE, + LLVMModuleRef M, + char **OutError); + +LLVMBool LLVMCreateInterpreterForModule(LLVMExecutionEngineRef *OutInterp, + LLVMModuleRef M, + char **OutError); + +LLVMBool LLVMCreateJITCompilerForModule(LLVMExecutionEngineRef *OutJIT, + LLVMModuleRef M, + unsigned OptLevel, + char **OutError); + +void LLVMInitializeMCJITCompilerOptions( + struct LLVMMCJITCompilerOptions *Options, size_t SizeOfOptions); + +/** + * Create an MCJIT execution engine for a module, with the given options. It is + * the responsibility of the caller to ensure that all fields in Options up to + * the given SizeOfOptions are initialized. It is correct to pass a smaller + * value of SizeOfOptions that omits some fields. The canonical way of using + * this is: + * + * LLVMMCJITCompilerOptions options; + * LLVMInitializeMCJITCompilerOptions(&options, sizeof(options)); + * ... fill in those options you care about + * LLVMCreateMCJITCompilerForModule(&jit, mod, &options, sizeof(options), + * &error); + * + * Note that this is also correct, though possibly suboptimal: + * + * LLVMCreateMCJITCompilerForModule(&jit, mod, 0, 0, &error); + */ +LLVMBool LLVMCreateMCJITCompilerForModule( + LLVMExecutionEngineRef *OutJIT, LLVMModuleRef M, + struct LLVMMCJITCompilerOptions *Options, size_t SizeOfOptions, + char **OutError); + +void LLVMDisposeExecutionEngine(LLVMExecutionEngineRef EE); + +void LLVMRunStaticConstructors(LLVMExecutionEngineRef EE); + +void LLVMRunStaticDestructors(LLVMExecutionEngineRef EE); + +int LLVMRunFunctionAsMain(LLVMExecutionEngineRef EE, LLVMValueRef F, + unsigned ArgC, const char * const *ArgV, + const char * const *EnvP); + +LLVMGenericValueRef LLVMRunFunction(LLVMExecutionEngineRef EE, LLVMValueRef F, + unsigned NumArgs, + LLVMGenericValueRef *Args); + +void LLVMFreeMachineCodeForFunction(LLVMExecutionEngineRef EE, LLVMValueRef F); + +void LLVMAddModule(LLVMExecutionEngineRef EE, LLVMModuleRef M); + +LLVMBool LLVMRemoveModule(LLVMExecutionEngineRef EE, LLVMModuleRef M, + LLVMModuleRef *OutMod, char **OutError); + +LLVMBool LLVMFindFunction(LLVMExecutionEngineRef EE, const char *Name, + LLVMValueRef *OutFn); + +void *LLVMRecompileAndRelinkFunction(LLVMExecutionEngineRef EE, + LLVMValueRef Fn); + +LLVMTargetDataRef LLVMGetExecutionEngineTargetData(LLVMExecutionEngineRef EE); +LLVMTargetMachineRef +LLVMGetExecutionEngineTargetMachine(LLVMExecutionEngineRef EE); + +void LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global, + void* Addr); + +void *LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global); + +uint64_t LLVMGetGlobalValueAddress(LLVMExecutionEngineRef EE, const char *Name); + +uint64_t LLVMGetFunctionAddress(LLVMExecutionEngineRef EE, const char *Name); + +/*===-- Operations on memory managers -------------------------------------===*/ + +typedef uint8_t *(*LLVMMemoryManagerAllocateCodeSectionCallback)( + void *Opaque, uintptr_t Size, unsigned Alignment, unsigned SectionID, + const char *SectionName); +typedef uint8_t *(*LLVMMemoryManagerAllocateDataSectionCallback)( + void *Opaque, uintptr_t Size, unsigned Alignment, unsigned SectionID, + const char *SectionName, LLVMBool IsReadOnly); +typedef LLVMBool (*LLVMMemoryManagerFinalizeMemoryCallback)( + void *Opaque, char **ErrMsg); +typedef void (*LLVMMemoryManagerDestroyCallback)(void *Opaque); + +/** + * Create a simple custom MCJIT memory manager. This memory manager can + * intercept allocations in a module-oblivious way. This will return NULL + * if any of the passed functions are NULL. + * + * @param Opaque An opaque client object to pass back to the callbacks. + * @param AllocateCodeSection Allocate a block of memory for executable code. + * @param AllocateDataSection Allocate a block of memory for data. + * @param FinalizeMemory Set page permissions and flush cache. Return 0 on + * success, 1 on error. + */ +LLVMMCJITMemoryManagerRef LLVMCreateSimpleMCJITMemoryManager( + void *Opaque, + LLVMMemoryManagerAllocateCodeSectionCallback AllocateCodeSection, + LLVMMemoryManagerAllocateDataSectionCallback AllocateDataSection, + LLVMMemoryManagerFinalizeMemoryCallback FinalizeMemory, + LLVMMemoryManagerDestroyCallback Destroy); + +void LLVMDisposeMCJITMemoryManager(LLVMMCJITMemoryManagerRef MM); + +/*===-- JIT Event Listener functions -------------------------------------===*/ + +LLVMJITEventListenerRef LLVMCreateGDBRegistrationListener(void); +LLVMJITEventListenerRef LLVMCreateIntelJITEventListener(void); +LLVMJITEventListenerRef LLVMCreateOProfileJITEventListener(void); +LLVMJITEventListenerRef LLVMCreatePerfJITEventListener(void); + +/** + * @} + */ + +LLVM_C_EXTERN_C_END + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/ExternC.h b/third_party/llvm-10.0/llvm/include/llvm-c/ExternC.h new file mode 100644 index 0000000..4240f7c --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/ExternC.h
@@ -0,0 +1,39 @@ +/*===- llvm-c/ExternC.h - Wrapper for 'extern "C"' ----------------*- C -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file defines an 'extern "C"' wrapper *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_EXTERN_C_H +#define LLVM_C_EXTERN_C_H + +#ifdef __clang__ +#define LLVM_C_STRICT_PROTOTYPES_BEGIN \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic error \"-Wstrict-prototypes\"") +#define LLVM_C_STRICT_PROTOTYPES_END _Pragma("clang diagnostic pop") +#else +#define LLVM_C_STRICT_PROTOTYPES_BEGIN +#define LLVM_C_STRICT_PROTOTYPES_END +#endif + +#ifdef __cplusplus +#define LLVM_C_EXTERN_C_BEGIN \ + extern "C" { \ + LLVM_C_STRICT_PROTOTYPES_BEGIN +#define LLVM_C_EXTERN_C_END \ + LLVM_C_STRICT_PROTOTYPES_END \ + } +#else +#define LLVM_C_EXTERN_C_BEGIN LLVM_C_STRICT_PROTOTYPES_BEGIN +#define LLVM_C_EXTERN_C_END LLVM_C_STRICT_PROTOTYPES_END +#endif + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/IRReader.h b/third_party/llvm-10.0/llvm/include/llvm-c/IRReader.h new file mode 100644 index 0000000..5a3f633 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/IRReader.h
@@ -0,0 +1,37 @@ +/*===-- llvm-c/IRReader.h - IR Reader C Interface -----------------*- C -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file defines the C interface to the IR Reader. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_IRREADER_H +#define LLVM_C_IRREADER_H + +#include "llvm-c/ExternC.h" +#include "llvm-c/Types.h" + +LLVM_C_EXTERN_C_BEGIN + +/** + * Read LLVM IR from a memory buffer and convert it into an in-memory Module + * object. Returns 0 on success. + * Optionally returns a human-readable description of any errors that + * occurred during parsing IR. OutMessage must be disposed with + * LLVMDisposeMessage. + * + * @see llvm::ParseIR() + */ +LLVMBool LLVMParseIRInContext(LLVMContextRef ContextRef, + LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutM, + char **OutMessage); + +LLVM_C_EXTERN_C_END + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/Initialization.h b/third_party/llvm-10.0/llvm/include/llvm-c/Initialization.h new file mode 100644 index 0000000..0d59de8 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/Initialization.h
@@ -0,0 +1,53 @@ +/*===-- llvm-c/Initialization.h - Initialization C Interface ------*- C -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to LLVM initialization routines, *| +|* which must be called before you can use the functionality provided by *| +|* the corresponding LLVM library. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_INITIALIZATION_H +#define LLVM_C_INITIALIZATION_H + +#include "llvm-c/ExternC.h" +#include "llvm-c/Types.h" + +LLVM_C_EXTERN_C_BEGIN + +/** + * @defgroup LLVMCInitialization Initialization Routines + * @ingroup LLVMC + * + * This module contains routines used to initialize the LLVM system. + * + * @{ + */ + +void LLVMInitializeCore(LLVMPassRegistryRef R); +void LLVMInitializeTransformUtils(LLVMPassRegistryRef R); +void LLVMInitializeScalarOpts(LLVMPassRegistryRef R); +void LLVMInitializeObjCARCOpts(LLVMPassRegistryRef R); +void LLVMInitializeVectorization(LLVMPassRegistryRef R); +void LLVMInitializeInstCombine(LLVMPassRegistryRef R); +void LLVMInitializeAggressiveInstCombiner(LLVMPassRegistryRef R); +void LLVMInitializeIPO(LLVMPassRegistryRef R); +void LLVMInitializeInstrumentation(LLVMPassRegistryRef R); +void LLVMInitializeAnalysis(LLVMPassRegistryRef R); +void LLVMInitializeIPA(LLVMPassRegistryRef R); +void LLVMInitializeCodeGen(LLVMPassRegistryRef R); +void LLVMInitializeTarget(LLVMPassRegistryRef R); + +/** + * @} + */ + +LLVM_C_EXTERN_C_END + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/LinkTimeOptimizer.h b/third_party/llvm-10.0/llvm/include/llvm-c/LinkTimeOptimizer.h new file mode 100644 index 0000000..9ae65b8 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/LinkTimeOptimizer.h
@@ -0,0 +1,66 @@ +//===-- llvm/LinkTimeOptimizer.h - LTO Public C Interface -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This header provides a C API to use the LLVM link time optimization +// library. This is intended to be used by linkers which are C-only in +// their implementation for performing LTO. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_C_LINKTIMEOPTIMIZER_H +#define LLVM_C_LINKTIMEOPTIMIZER_H + +#include "llvm-c/ExternC.h" + +LLVM_C_EXTERN_C_BEGIN + +/** + * @defgroup LLVMCLinkTimeOptimizer Link Time Optimization + * @ingroup LLVMC + * + * @{ + */ + + /// This provides a dummy type for pointers to the LTO object. + typedef void* llvm_lto_t; + + /// This provides a C-visible enumerator to manage status codes. + /// This should map exactly onto the C++ enumerator LTOStatus. + typedef enum llvm_lto_status { + LLVM_LTO_UNKNOWN, + LLVM_LTO_OPT_SUCCESS, + LLVM_LTO_READ_SUCCESS, + LLVM_LTO_READ_FAILURE, + LLVM_LTO_WRITE_FAILURE, + LLVM_LTO_NO_TARGET, + LLVM_LTO_NO_WORK, + LLVM_LTO_MODULE_MERGE_FAILURE, + LLVM_LTO_ASM_FAILURE, + + // Added C-specific error codes + LLVM_LTO_NULL_OBJECT + } llvm_lto_status_t; + + /// This provides C interface to initialize link time optimizer. This allows + /// linker to use dlopen() interface to dynamically load LinkTimeOptimizer. + /// extern "C" helps, because dlopen() interface uses name to find the symbol. + extern llvm_lto_t llvm_create_optimizer(void); + extern void llvm_destroy_optimizer(llvm_lto_t lto); + + extern llvm_lto_status_t llvm_read_object_file + (llvm_lto_t lto, const char* input_filename); + extern llvm_lto_status_t llvm_optimize_modules + (llvm_lto_t lto, const char* output_filename); + +/** + * @} + */ + + LLVM_C_EXTERN_C_END + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/Linker.h b/third_party/llvm-10.0/llvm/include/llvm-c/Linker.h new file mode 100644 index 0000000..1ad9cc9 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/Linker.h
@@ -0,0 +1,38 @@ +/*===-- llvm-c/Linker.h - Module Linker C Interface -------------*- C++ -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file defines the C interface to the module/file/archive linker. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_LINKER_H +#define LLVM_C_LINKER_H + +#include "llvm-c/ExternC.h" +#include "llvm-c/Types.h" + +LLVM_C_EXTERN_C_BEGIN + +/* This enum is provided for backwards-compatibility only. It has no effect. */ +typedef enum { + LLVMLinkerDestroySource = 0, /* This is the default behavior. */ + LLVMLinkerPreserveSource_Removed = 1 /* This option has been deprecated and + should not be used. */ +} LLVMLinkerMode; + +/* Links the source module into the destination module. The source module is + * destroyed. + * The return value is true if an error occurred, false otherwise. + * Use the diagnostic handler to get any diagnostic message. +*/ +LLVMBool LLVMLinkModules2(LLVMModuleRef Dest, LLVMModuleRef Src); + +LLVM_C_EXTERN_C_END + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/Object.h b/third_party/llvm-10.0/llvm/include/llvm-c/Object.h new file mode 100644 index 0000000..9a9596a --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/Object.h
@@ -0,0 +1,230 @@ +/*===-- llvm-c/Object.h - Object Lib C Iface --------------------*- C++ -*-===*/ +/* */ +/* Part of the LLVM Project, under the Apache License v2.0 with LLVM */ +/* Exceptions. */ +/* See https://llvm.org/LICENSE.txt for license information. */ +/* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ +/* */ +/*===----------------------------------------------------------------------===*/ +/* */ +/* This header declares the C interface to libLLVMObject.a, which */ +/* implements object file reading and writing. */ +/* */ +/* Many exotic languages can interoperate with C code but have a harder time */ +/* with C++ due to name mangling. So in addition to C, this interface enables */ +/* tools written in such languages. */ +/* */ +/*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_OBJECT_H +#define LLVM_C_OBJECT_H + +#include "llvm-c/ExternC.h" +#include "llvm-c/Types.h" +#include "llvm/Config/llvm-config.h" + +LLVM_C_EXTERN_C_BEGIN + +/** + * @defgroup LLVMCObject Object file reading and writing + * @ingroup LLVMC + * + * @{ + */ + +// Opaque type wrappers +typedef struct LLVMOpaqueSectionIterator *LLVMSectionIteratorRef; +typedef struct LLVMOpaqueSymbolIterator *LLVMSymbolIteratorRef; +typedef struct LLVMOpaqueRelocationIterator *LLVMRelocationIteratorRef; + +typedef enum { + LLVMBinaryTypeArchive, /**< Archive file. */ + LLVMBinaryTypeMachOUniversalBinary, /**< Mach-O Universal Binary file. */ + LLVMBinaryTypeCOFFImportFile, /**< COFF Import file. */ + LLVMBinaryTypeIR, /**< LLVM IR. */ + LLVMBinaryTypeWinRes, /**< Windows resource (.res) file. */ + LLVMBinaryTypeCOFF, /**< COFF Object file. */ + LLVMBinaryTypeELF32L, /**< ELF 32-bit, little endian. */ + LLVMBinaryTypeELF32B, /**< ELF 32-bit, big endian. */ + LLVMBinaryTypeELF64L, /**< ELF 64-bit, little endian. */ + LLVMBinaryTypeELF64B, /**< ELF 64-bit, big endian. */ + LLVMBinaryTypeMachO32L, /**< MachO 32-bit, little endian. */ + LLVMBinaryTypeMachO32B, /**< MachO 32-bit, big endian. */ + LLVMBinaryTypeMachO64L, /**< MachO 64-bit, little endian. */ + LLVMBinaryTypeMachO64B, /**< MachO 64-bit, big endian. */ + LLVMBinaryTypeWasm, /**< Web Assembly. */ +} LLVMBinaryType; + +/** + * Create a binary file from the given memory buffer. + * + * The exact type of the binary file will be inferred automatically, and the + * appropriate implementation selected. The context may be NULL except if + * the resulting file is an LLVM IR file. + * + * The memory buffer is not consumed by this function. It is the responsibilty + * of the caller to free it with \c LLVMDisposeMemoryBuffer. + * + * If NULL is returned, the \p ErrorMessage parameter is populated with the + * error's description. It is then the caller's responsibility to free this + * message by calling \c LLVMDisposeMessage. + * + * @see llvm::object::createBinary + */ +LLVMBinaryRef LLVMCreateBinary(LLVMMemoryBufferRef MemBuf, + LLVMContextRef Context, + char **ErrorMessage); + +/** + * Dispose of a binary file. + * + * The binary file does not own its backing buffer. It is the responsibilty + * of the caller to free it with \c LLVMDisposeMemoryBuffer. + */ +void LLVMDisposeBinary(LLVMBinaryRef BR); + +/** + * Retrieves a copy of the memory buffer associated with this object file. + * + * The returned buffer is merely a shallow copy and does not own the actual + * backing buffer of the binary. Nevertheless, it is the responsibility of the + * caller to free it with \c LLVMDisposeMemoryBuffer. + * + * @see llvm::object::getMemoryBufferRef + */ +LLVMMemoryBufferRef LLVMBinaryCopyMemoryBuffer(LLVMBinaryRef BR); + +/** + * Retrieve the specific type of a binary. + * + * @see llvm::object::Binary::getType + */ +LLVMBinaryType LLVMBinaryGetType(LLVMBinaryRef BR); + +/* + * For a Mach-O universal binary file, retrieves the object file corresponding + * to the given architecture if it is present as a slice. + * + * If NULL is returned, the \p ErrorMessage parameter is populated with the + * error's description. It is then the caller's responsibility to free this + * message by calling \c LLVMDisposeMessage. + * + * It is the responsiblity of the caller to free the returned object file by + * calling \c LLVMDisposeBinary. + */ +LLVMBinaryRef LLVMMachOUniversalBinaryCopyObjectForArch(LLVMBinaryRef BR, + const char *Arch, + size_t ArchLen, + char **ErrorMessage); + +/** + * Retrieve a copy of the section iterator for this object file. + * + * If there are no sections, the result is NULL. + * + * The returned iterator is merely a shallow copy. Nevertheless, it is + * the responsibility of the caller to free it with + * \c LLVMDisposeSectionIterator. + * + * @see llvm::object::sections() + */ +LLVMSectionIteratorRef LLVMObjectFileCopySectionIterator(LLVMBinaryRef BR); + +/** + * Returns whether the given section iterator is at the end. + * + * @see llvm::object::section_end + */ +LLVMBool LLVMObjectFileIsSectionIteratorAtEnd(LLVMBinaryRef BR, + LLVMSectionIteratorRef SI); + +/** + * Retrieve a copy of the symbol iterator for this object file. + * + * If there are no symbols, the result is NULL. + * + * The returned iterator is merely a shallow copy. Nevertheless, it is + * the responsibility of the caller to free it with + * \c LLVMDisposeSymbolIterator. + * + * @see llvm::object::symbols() + */ +LLVMSymbolIteratorRef LLVMObjectFileCopySymbolIterator(LLVMBinaryRef BR); + +/** + * Returns whether the given symbol iterator is at the end. + * + * @see llvm::object::symbol_end + */ +LLVMBool LLVMObjectFileIsSymbolIteratorAtEnd(LLVMBinaryRef BR, + LLVMSymbolIteratorRef SI); + +void LLVMDisposeSectionIterator(LLVMSectionIteratorRef SI); + +void LLVMMoveToNextSection(LLVMSectionIteratorRef SI); +void LLVMMoveToContainingSection(LLVMSectionIteratorRef Sect, + LLVMSymbolIteratorRef Sym); + +// ObjectFile Symbol iterators +void LLVMDisposeSymbolIterator(LLVMSymbolIteratorRef SI); +void LLVMMoveToNextSymbol(LLVMSymbolIteratorRef SI); + +// SectionRef accessors +const char *LLVMGetSectionName(LLVMSectionIteratorRef SI); +uint64_t LLVMGetSectionSize(LLVMSectionIteratorRef SI); +const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI); +uint64_t LLVMGetSectionAddress(LLVMSectionIteratorRef SI); +LLVMBool LLVMGetSectionContainsSymbol(LLVMSectionIteratorRef SI, + LLVMSymbolIteratorRef Sym); + +// Section Relocation iterators +LLVMRelocationIteratorRef LLVMGetRelocations(LLVMSectionIteratorRef Section); +void LLVMDisposeRelocationIterator(LLVMRelocationIteratorRef RI); +LLVMBool LLVMIsRelocationIteratorAtEnd(LLVMSectionIteratorRef Section, + LLVMRelocationIteratorRef RI); +void LLVMMoveToNextRelocation(LLVMRelocationIteratorRef RI); + + +// SymbolRef accessors +const char *LLVMGetSymbolName(LLVMSymbolIteratorRef SI); +uint64_t LLVMGetSymbolAddress(LLVMSymbolIteratorRef SI); +uint64_t LLVMGetSymbolSize(LLVMSymbolIteratorRef SI); + +// RelocationRef accessors +uint64_t LLVMGetRelocationOffset(LLVMRelocationIteratorRef RI); +LLVMSymbolIteratorRef LLVMGetRelocationSymbol(LLVMRelocationIteratorRef RI); +uint64_t LLVMGetRelocationType(LLVMRelocationIteratorRef RI); +// NOTE: Caller takes ownership of returned string of the two +// following functions. +const char *LLVMGetRelocationTypeName(LLVMRelocationIteratorRef RI); +const char *LLVMGetRelocationValueString(LLVMRelocationIteratorRef RI); + +/** Deprecated: Use LLVMBinaryRef instead. */ +typedef struct LLVMOpaqueObjectFile *LLVMObjectFileRef; + +/** Deprecated: Use LLVMCreateBinary instead. */ +LLVMObjectFileRef LLVMCreateObjectFile(LLVMMemoryBufferRef MemBuf); + +/** Deprecated: Use LLVMDisposeBinary instead. */ +void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile); + +/** Deprecated: Use LLVMObjectFileCopySectionIterator instead. */ +LLVMSectionIteratorRef LLVMGetSections(LLVMObjectFileRef ObjectFile); + +/** Deprecated: Use LLVMObjectFileIsSectionIteratorAtEnd instead. */ +LLVMBool LLVMIsSectionIteratorAtEnd(LLVMObjectFileRef ObjectFile, + LLVMSectionIteratorRef SI); + +/** Deprecated: Use LLVMObjectFileCopySymbolIterator instead. */ +LLVMSymbolIteratorRef LLVMGetSymbols(LLVMObjectFileRef ObjectFile); + +/** Deprecated: Use LLVMObjectFileIsSymbolIteratorAtEnd instead. */ +LLVMBool LLVMIsSymbolIteratorAtEnd(LLVMObjectFileRef ObjectFile, + LLVMSymbolIteratorRef SI); +/** + * @} + */ + +LLVM_C_EXTERN_C_END + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/OrcBindings.h b/third_party/llvm-10.0/llvm/include/llvm-c/OrcBindings.h new file mode 100644 index 0000000..11cdade --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/OrcBindings.h
@@ -0,0 +1,169 @@ +/*===----------- llvm-c/OrcBindings.h - Orc Lib C Iface ---------*- C++ -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to libLLVMOrcJIT.a, which implements *| +|* JIT compilation of LLVM IR. *| +|* *| +|* Many exotic languages can interoperate with C code but have a harder time *| +|* with C++ due to name mangling. So in addition to C, this interface enables *| +|* tools written in such languages. *| +|* *| +|* Note: This interface is experimental. It is *NOT* stable, and may be *| +|* changed without warning. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_ORCBINDINGS_H +#define LLVM_C_ORCBINDINGS_H + +#include "llvm-c/Error.h" +#include "llvm-c/ExternC.h" +#include "llvm-c/Object.h" +#include "llvm-c/TargetMachine.h" + +LLVM_C_EXTERN_C_BEGIN + +typedef struct LLVMOrcOpaqueJITStack *LLVMOrcJITStackRef; +typedef uint64_t LLVMOrcModuleHandle; +typedef uint64_t LLVMOrcTargetAddress; +typedef uint64_t (*LLVMOrcSymbolResolverFn)(const char *Name, void *LookupCtx); +typedef uint64_t (*LLVMOrcLazyCompileCallbackFn)(LLVMOrcJITStackRef JITStack, + void *CallbackCtx); + +/** + * Create an ORC JIT stack. + * + * The client owns the resulting stack, and must call OrcDisposeInstance(...) + * to destroy it and free its memory. The JIT stack will take ownership of the + * TargetMachine, which will be destroyed when the stack is destroyed. The + * client should not attempt to dispose of the Target Machine, or it will result + * in a double-free. + */ +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 + */ +void LLVMOrcGetMangledSymbol(LLVMOrcJITStackRef JITStack, char **MangledSymbol, + const char *Symbol); + +/** + * Dispose of a mangled symbol. + */ +void LLVMOrcDisposeMangledSymbol(char *MangledSymbol); + +/** + * Create a lazy compile callback. + */ +LLVMErrorRef LLVMOrcCreateLazyCompileCallback( + LLVMOrcJITStackRef JITStack, LLVMOrcTargetAddress *RetAddr, + LLVMOrcLazyCompileCallbackFn Callback, void *CallbackCtx); + +/** + * Create a named indirect call stub. + */ +LLVMErrorRef LLVMOrcCreateIndirectStub(LLVMOrcJITStackRef JITStack, + const char *StubName, + LLVMOrcTargetAddress InitAddr); + +/** + * Set the pointer for the given indirect stub. + */ +LLVMErrorRef LLVMOrcSetIndirectStubPointer(LLVMOrcJITStackRef JITStack, + const char *StubName, + LLVMOrcTargetAddress NewAddr); + +/** + * Add module to be eagerly compiled. + */ +LLVMErrorRef LLVMOrcAddEagerlyCompiledIR(LLVMOrcJITStackRef JITStack, + LLVMOrcModuleHandle *RetHandle, + LLVMModuleRef Mod, + LLVMOrcSymbolResolverFn SymbolResolver, + void *SymbolResolverCtx); + +/** + * Add module to be lazily compiled one function at a time. + */ +LLVMErrorRef LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack, + LLVMOrcModuleHandle *RetHandle, + LLVMModuleRef Mod, + LLVMOrcSymbolResolverFn SymbolResolver, + void *SymbolResolverCtx); + +/** + * Add an object file. + * + * This method takes ownership of the given memory buffer and attempts to add + * it to the JIT as an object file. + * Clients should *not* dispose of the 'Obj' argument: the JIT will manage it + * from this call onwards. + */ +LLVMErrorRef LLVMOrcAddObjectFile(LLVMOrcJITStackRef JITStack, + LLVMOrcModuleHandle *RetHandle, + LLVMMemoryBufferRef Obj, + LLVMOrcSymbolResolverFn SymbolResolver, + void *SymbolResolverCtx); + +/** + * Remove a module set from the JIT. + * + * This works for all modules that can be added via OrcAdd*, including object + * files. + */ +LLVMErrorRef LLVMOrcRemoveModule(LLVMOrcJITStackRef JITStack, + LLVMOrcModuleHandle H); + +/** + * Get symbol address from JIT instance. + */ +LLVMErrorRef LLVMOrcGetSymbolAddress(LLVMOrcJITStackRef JITStack, + LLVMOrcTargetAddress *RetAddr, + const char *SymbolName); + +/** + * Get symbol address from JIT instance, searching only the specified + * handle. + */ +LLVMErrorRef LLVMOrcGetSymbolAddressIn(LLVMOrcJITStackRef JITStack, + LLVMOrcTargetAddress *RetAddr, + LLVMOrcModuleHandle H, + const char *SymbolName); + +/** + * Dispose of an ORC JIT stack. + */ +LLVMErrorRef LLVMOrcDisposeInstance(LLVMOrcJITStackRef JITStack); + +/** + * Register a JIT Event Listener. + * + * A NULL listener is ignored. + */ +void LLVMOrcRegisterJITEventListener(LLVMOrcJITStackRef JITStack, LLVMJITEventListenerRef L); + +/** + * Unegister a JIT Event Listener. + * + * A NULL listener is ignored. + */ +void LLVMOrcUnregisterJITEventListener(LLVMOrcJITStackRef JITStack, LLVMJITEventListenerRef L); + +LLVM_C_EXTERN_C_END + +#endif /* LLVM_C_ORCBINDINGS_H */
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/Remarks.h b/third_party/llvm-10.0/llvm/include/llvm-c/Remarks.h new file mode 100644 index 0000000..ffe647a --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/Remarks.h
@@ -0,0 +1,344 @@ +/*===-- llvm-c/Remarks.h - Remarks Public C Interface -------------*- C -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header provides a public interface to a remark diagnostics library. *| +|* LLVM provides an implementation of this interface. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_REMARKS_H +#define LLVM_C_REMARKS_H + +#include "llvm-c/ExternC.h" +#include "llvm-c/Types.h" +#ifdef __cplusplus +#include <cstddef> +#else +#include <stddef.h> +#endif /* !defined(__cplusplus) */ + +LLVM_C_EXTERN_C_BEGIN + +/** + * @defgroup LLVMCREMARKS Remarks + * @ingroup LLVMC + * + * @{ + */ + +// 0 -> 1: Bitstream remarks support. +#define REMARKS_API_VERSION 1 + +/** + * The type of the emitted remark. + */ +enum LLVMRemarkType { + LLVMRemarkTypeUnknown, + LLVMRemarkTypePassed, + LLVMRemarkTypeMissed, + LLVMRemarkTypeAnalysis, + LLVMRemarkTypeAnalysisFPCommute, + LLVMRemarkTypeAnalysisAliasing, + LLVMRemarkTypeFailure +}; + +/** + * String containing a buffer and a length. The buffer is not guaranteed to be + * zero-terminated. + * + * \since REMARKS_API_VERSION=0 + */ +typedef struct LLVMRemarkOpaqueString *LLVMRemarkStringRef; + +/** + * Returns the buffer holding the string. + * + * \since REMARKS_API_VERSION=0 + */ +extern const char *LLVMRemarkStringGetData(LLVMRemarkStringRef String); + +/** + * Returns the size of the string. + * + * \since REMARKS_API_VERSION=0 + */ +extern uint32_t LLVMRemarkStringGetLen(LLVMRemarkStringRef String); + +/** + * DebugLoc containing File, Line and Column. + * + * \since REMARKS_API_VERSION=0 + */ +typedef struct LLVMRemarkOpaqueDebugLoc *LLVMRemarkDebugLocRef; + +/** + * Return the path to the source file for a debug location. + * + * \since REMARKS_API_VERSION=0 + */ +extern LLVMRemarkStringRef +LLVMRemarkDebugLocGetSourceFilePath(LLVMRemarkDebugLocRef DL); + +/** + * Return the line in the source file for a debug location. + * + * \since REMARKS_API_VERSION=0 + */ +extern uint32_t LLVMRemarkDebugLocGetSourceLine(LLVMRemarkDebugLocRef DL); + +/** + * Return the column in the source file for a debug location. + * + * \since REMARKS_API_VERSION=0 + */ +extern uint32_t LLVMRemarkDebugLocGetSourceColumn(LLVMRemarkDebugLocRef DL); + +/** + * Element of the "Args" list. The key might give more information about what + * the semantics of the value are, e.g. "Callee" will tell you that the value + * is a symbol that names a function. + * + * \since REMARKS_API_VERSION=0 + */ +typedef struct LLVMRemarkOpaqueArg *LLVMRemarkArgRef; + +/** + * Returns the key of an argument. The key defines what the value is, and the + * same key can appear multiple times in the list of arguments. + * + * \since REMARKS_API_VERSION=0 + */ +extern LLVMRemarkStringRef LLVMRemarkArgGetKey(LLVMRemarkArgRef Arg); + +/** + * Returns the value of an argument. This is a string that can contain newlines. + * + * \since REMARKS_API_VERSION=0 + */ +extern LLVMRemarkStringRef LLVMRemarkArgGetValue(LLVMRemarkArgRef Arg); + +/** + * Returns the debug location that is attached to the value of this argument. + * + * If there is no debug location, the return value will be `NULL`. + * + * \since REMARKS_API_VERSION=0 + */ +extern LLVMRemarkDebugLocRef LLVMRemarkArgGetDebugLoc(LLVMRemarkArgRef Arg); + +/** + * A remark emitted by the compiler. + * + * \since REMARKS_API_VERSION=0 + */ +typedef struct LLVMRemarkOpaqueEntry *LLVMRemarkEntryRef; + +/** + * Free the resources used by the remark entry. + * + * \since REMARKS_API_VERSION=0 + */ +extern void LLVMRemarkEntryDispose(LLVMRemarkEntryRef Remark); + +/** + * The type of the remark. For example, it can allow users to only keep the + * missed optimizations from the compiler. + * + * \since REMARKS_API_VERSION=0 + */ +extern enum LLVMRemarkType LLVMRemarkEntryGetType(LLVMRemarkEntryRef Remark); + +/** + * Get the name of the pass that emitted this remark. + * + * \since REMARKS_API_VERSION=0 + */ +extern LLVMRemarkStringRef +LLVMRemarkEntryGetPassName(LLVMRemarkEntryRef Remark); + +/** + * Get an identifier of the remark. + * + * \since REMARKS_API_VERSION=0 + */ +extern LLVMRemarkStringRef +LLVMRemarkEntryGetRemarkName(LLVMRemarkEntryRef Remark); + +/** + * Get the name of the function being processed when the remark was emitted. + * + * \since REMARKS_API_VERSION=0 + */ +extern LLVMRemarkStringRef +LLVMRemarkEntryGetFunctionName(LLVMRemarkEntryRef Remark); + +/** + * Returns the debug location that is attached to this remark. + * + * If there is no debug location, the return value will be `NULL`. + * + * \since REMARKS_API_VERSION=0 + */ +extern LLVMRemarkDebugLocRef +LLVMRemarkEntryGetDebugLoc(LLVMRemarkEntryRef Remark); + +/** + * Return the hotness of the remark. + * + * A hotness of `0` means this value is not set. + * + * \since REMARKS_API_VERSION=0 + */ +extern uint64_t LLVMRemarkEntryGetHotness(LLVMRemarkEntryRef Remark); + +/** + * The number of arguments the remark holds. + * + * \since REMARKS_API_VERSION=0 + */ +extern uint32_t LLVMRemarkEntryGetNumArgs(LLVMRemarkEntryRef Remark); + +/** + * Get a new iterator to iterate over a remark's argument. + * + * If there are no arguments in \p Remark, the return value will be `NULL`. + * + * The lifetime of the returned value is bound to the lifetime of \p Remark. + * + * \since REMARKS_API_VERSION=0 + */ +extern LLVMRemarkArgRef LLVMRemarkEntryGetFirstArg(LLVMRemarkEntryRef Remark); + +/** + * Get the next argument in \p Remark from the position of \p It. + * + * Returns `NULL` if there are no more arguments available. + * + * The lifetime of the returned value is bound to the lifetime of \p Remark. + * + * \since REMARKS_API_VERSION=0 + */ +extern LLVMRemarkArgRef LLVMRemarkEntryGetNextArg(LLVMRemarkArgRef It, + LLVMRemarkEntryRef Remark); + +typedef struct LLVMRemarkOpaqueParser *LLVMRemarkParserRef; + +/** + * Creates a remark parser that can be used to parse the buffer located in \p + * Buf of size \p Size bytes. + * + * \p Buf cannot be `NULL`. + * + * This function should be paired with LLVMRemarkParserDispose() to avoid + * leaking resources. + * + * \since REMARKS_API_VERSION=0 + */ +extern LLVMRemarkParserRef LLVMRemarkParserCreateYAML(const void *Buf, + uint64_t Size); + +/** + * Creates a remark parser that can be used to parse the buffer located in \p + * Buf of size \p Size bytes. + * + * \p Buf cannot be `NULL`. + * + * This function should be paired with LLVMRemarkParserDispose() to avoid + * leaking resources. + * + * \since REMARKS_API_VERSION=1 + */ +extern LLVMRemarkParserRef LLVMRemarkParserCreateBitstream(const void *Buf, + uint64_t Size); + +/** + * Returns the next remark in the file. + * + * The value pointed to by the return value needs to be disposed using a call to + * LLVMRemarkEntryDispose(). + * + * All the entries in the returned value that are of LLVMRemarkStringRef type + * will become invalidated once a call to LLVMRemarkParserDispose is made. + * + * If the parser reaches the end of the buffer, the return value will be `NULL`. + * + * In the case of an error, the return value will be `NULL`, and: + * + * 1) LLVMRemarkParserHasError() will return `1`. + * + * 2) LLVMRemarkParserGetErrorMessage() will return a descriptive error + * message. + * + * An error may occur if: + * + * 1) An argument is invalid. + * + * 2) There is a parsing error. This can occur on things like malformed YAML. + * + * 3) There is a Remark semantic error. This can occur on well-formed files with + * missing or extra fields. + * + * Here is a quick example of the usage: + * + * ``` + * LLVMRemarkParserRef Parser = LLVMRemarkParserCreateYAML(Buf, Size); + * LLVMRemarkEntryRef Remark = NULL; + * while ((Remark = LLVMRemarkParserGetNext(Parser))) { + * // use Remark + * LLVMRemarkEntryDispose(Remark); // Release memory. + * } + * bool HasError = LLVMRemarkParserHasError(Parser); + * LLVMRemarkParserDispose(Parser); + * ``` + * + * \since REMARKS_API_VERSION=0 + */ +extern LLVMRemarkEntryRef LLVMRemarkParserGetNext(LLVMRemarkParserRef Parser); + +/** + * Returns `1` if the parser encountered an error while parsing the buffer. + * + * \since REMARKS_API_VERSION=0 + */ +extern LLVMBool LLVMRemarkParserHasError(LLVMRemarkParserRef Parser); + +/** + * Returns a null-terminated string containing an error message. + * + * In case of no error, the result is `NULL`. + * + * The memory of the string is bound to the lifetime of \p Parser. If + * LLVMRemarkParserDispose() is called, the memory of the string will be + * released. + * + * \since REMARKS_API_VERSION=0 + */ +extern const char *LLVMRemarkParserGetErrorMessage(LLVMRemarkParserRef Parser); + +/** + * Releases all the resources used by \p Parser. + * + * \since REMARKS_API_VERSION=0 + */ +extern void LLVMRemarkParserDispose(LLVMRemarkParserRef Parser); + +/** + * Returns the version of the remarks library. + * + * \since REMARKS_API_VERSION=0 + */ +extern uint32_t LLVMRemarkVersion(void); + +/** + * @} // endgoup LLVMCREMARKS + */ + +LLVM_C_EXTERN_C_END + +#endif /* LLVM_C_REMARKS_H */
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/Support.h b/third_party/llvm-10.0/llvm/include/llvm-c/Support.h new file mode 100644 index 0000000..866df32 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/Support.h
@@ -0,0 +1,62 @@ +/*===-- llvm-c/Support.h - Support C Interface --------------------*- C -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file defines the C interface to the LLVM support library. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_SUPPORT_H +#define LLVM_C_SUPPORT_H + +#include "llvm-c/DataTypes.h" +#include "llvm-c/ExternC.h" +#include "llvm-c/Types.h" + +LLVM_C_EXTERN_C_BEGIN + +/** + * This function permanently loads the dynamic library at the given path. + * It is safe to call this function multiple times for the same library. + * + * @see sys::DynamicLibrary::LoadLibraryPermanently() + */ +LLVMBool LLVMLoadLibraryPermanently(const char* Filename); + +/** + * This function parses the given arguments using the LLVM command line parser. + * Note that the only stable thing about this function is its signature; you + * cannot rely on any particular set of command line arguments being interpreted + * the same way across LLVM versions. + * + * @see llvm::cl::ParseCommandLineOptions() + */ +void LLVMParseCommandLineOptions(int argc, const char *const *argv, + const char *Overview); + +/** + * This function will search through all previously loaded dynamic + * libraries for the symbol \p symbolName. If it is found, the address of + * that symbol is returned. If not, null is returned. + * + * @see sys::DynamicLibrary::SearchForAddressOfSymbol() + */ +void *LLVMSearchForAddressOfSymbol(const char *symbolName); + +/** + * This functions permanently adds the symbol \p symbolName with the + * value \p symbolValue. These symbols are searched before any + * libraries. + * + * @see sys::DynamicLibrary::AddSymbol() + */ +void LLVMAddSymbol(const char *symbolName, void *symbolValue); + +LLVM_C_EXTERN_C_END + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/Target.h b/third_party/llvm-10.0/llvm/include/llvm-c/Target.h new file mode 100644 index 0000000..518b46d --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/Target.h
@@ -0,0 +1,292 @@ +/*===-- llvm-c/Target.h - Target Lib C Iface --------------------*- C++ -*-===*/ +/* */ +/* Part of the LLVM Project, under the Apache License v2.0 with LLVM */ +/* Exceptions. */ +/* See https://llvm.org/LICENSE.txt for license information. */ +/* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ +/* */ +/*===----------------------------------------------------------------------===*/ +/* */ +/* This header declares the C interface to libLLVMTarget.a, which */ +/* implements target information. */ +/* */ +/* Many exotic languages can interoperate with C code but have a harder time */ +/* with C++ due to name mangling. So in addition to C, this interface enables */ +/* tools written in such languages. */ +/* */ +/*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_TARGET_H +#define LLVM_C_TARGET_H + +#include "llvm-c/ExternC.h" +#include "llvm-c/Types.h" +#include "llvm/Config/llvm-config.h" + +LLVM_C_EXTERN_C_BEGIN + +/** + * @defgroup LLVMCTarget Target information + * @ingroup LLVMC + * + * @{ + */ + +enum LLVMByteOrdering { LLVMBigEndian, LLVMLittleEndian }; + +typedef struct LLVMOpaqueTargetData *LLVMTargetDataRef; +typedef struct LLVMOpaqueTargetLibraryInfotData *LLVMTargetLibraryInfoRef; + +/* Declare all of the target-initialization functions that are available. */ +#define LLVM_TARGET(TargetName) \ + void LLVMInitialize##TargetName##TargetInfo(void); +#include "llvm/Config/Targets.def" +#undef LLVM_TARGET /* Explicit undef to make SWIG happier */ + +#define LLVM_TARGET(TargetName) void LLVMInitialize##TargetName##Target(void); +#include "llvm/Config/Targets.def" +#undef LLVM_TARGET /* Explicit undef to make SWIG happier */ + +#define LLVM_TARGET(TargetName) \ + void LLVMInitialize##TargetName##TargetMC(void); +#include "llvm/Config/Targets.def" +#undef LLVM_TARGET /* Explicit undef to make SWIG happier */ + +/* Declare all of the available assembly printer initialization functions. */ +#define LLVM_ASM_PRINTER(TargetName) \ + void LLVMInitialize##TargetName##AsmPrinter(void); +#include "llvm/Config/AsmPrinters.def" +#undef LLVM_ASM_PRINTER /* Explicit undef to make SWIG happier */ + +/* Declare all of the available assembly parser initialization functions. */ +#define LLVM_ASM_PARSER(TargetName) \ + void LLVMInitialize##TargetName##AsmParser(void); +#include "llvm/Config/AsmParsers.def" +#undef LLVM_ASM_PARSER /* Explicit undef to make SWIG happier */ + +/* Declare all of the available disassembler initialization functions. */ +#define LLVM_DISASSEMBLER(TargetName) \ + void LLVMInitialize##TargetName##Disassembler(void); +#include "llvm/Config/Disassemblers.def" +#undef LLVM_DISASSEMBLER /* Explicit undef to make SWIG happier */ + +/** LLVMInitializeAllTargetInfos - The main program should call this function if + it wants access to all available targets that LLVM is configured to + support. */ +static inline void LLVMInitializeAllTargetInfos(void) { +#define LLVM_TARGET(TargetName) LLVMInitialize##TargetName##TargetInfo(); +#include "llvm/Config/Targets.def" +#undef LLVM_TARGET /* Explicit undef to make SWIG happier */ +} + +/** LLVMInitializeAllTargets - The main program should call this function if it + wants to link in all available targets that LLVM is configured to + support. */ +static inline void LLVMInitializeAllTargets(void) { +#define LLVM_TARGET(TargetName) LLVMInitialize##TargetName##Target(); +#include "llvm/Config/Targets.def" +#undef LLVM_TARGET /* Explicit undef to make SWIG happier */ +} + +/** LLVMInitializeAllTargetMCs - The main program should call this function if + it wants access to all available target MC that LLVM is configured to + support. */ +static inline void LLVMInitializeAllTargetMCs(void) { +#define LLVM_TARGET(TargetName) LLVMInitialize##TargetName##TargetMC(); +#include "llvm/Config/Targets.def" +#undef LLVM_TARGET /* Explicit undef to make SWIG happier */ +} + +/** LLVMInitializeAllAsmPrinters - The main program should call this function if + it wants all asm printers that LLVM is configured to support, to make them + available via the TargetRegistry. */ +static inline void LLVMInitializeAllAsmPrinters(void) { +#define LLVM_ASM_PRINTER(TargetName) LLVMInitialize##TargetName##AsmPrinter(); +#include "llvm/Config/AsmPrinters.def" +#undef LLVM_ASM_PRINTER /* Explicit undef to make SWIG happier */ +} + +/** LLVMInitializeAllAsmParsers - The main program should call this function if + it wants all asm parsers that LLVM is configured to support, to make them + available via the TargetRegistry. */ +static inline void LLVMInitializeAllAsmParsers(void) { +#define LLVM_ASM_PARSER(TargetName) LLVMInitialize##TargetName##AsmParser(); +#include "llvm/Config/AsmParsers.def" +#undef LLVM_ASM_PARSER /* Explicit undef to make SWIG happier */ +} + +/** LLVMInitializeAllDisassemblers - The main program should call this function + if it wants all disassemblers that LLVM is configured to support, to make + them available via the TargetRegistry. */ +static inline void LLVMInitializeAllDisassemblers(void) { +#define LLVM_DISASSEMBLER(TargetName) \ + LLVMInitialize##TargetName##Disassembler(); +#include "llvm/Config/Disassemblers.def" +#undef LLVM_DISASSEMBLER /* Explicit undef to make SWIG happier */ +} + +/** LLVMInitializeNativeTarget - The main program should call this function to + initialize the native target corresponding to the host. This is useful + for JIT applications to ensure that the target gets linked in correctly. */ +static inline LLVMBool LLVMInitializeNativeTarget(void) { + /* If we have a native target, initialize it to ensure it is linked in. */ +#ifdef LLVM_NATIVE_TARGET + LLVM_NATIVE_TARGETINFO(); + LLVM_NATIVE_TARGET(); + LLVM_NATIVE_TARGETMC(); + return 0; +#else + return 1; +#endif +} + +/** LLVMInitializeNativeTargetAsmParser - The main program should call this + function to initialize the parser for the native target corresponding to the + host. */ +static inline LLVMBool LLVMInitializeNativeAsmParser(void) { +#ifdef LLVM_NATIVE_ASMPARSER + LLVM_NATIVE_ASMPARSER(); + return 0; +#else + return 1; +#endif +} + +/** LLVMInitializeNativeTargetAsmPrinter - The main program should call this + function to initialize the printer for the native target corresponding to + the host. */ +static inline LLVMBool LLVMInitializeNativeAsmPrinter(void) { +#ifdef LLVM_NATIVE_ASMPRINTER + LLVM_NATIVE_ASMPRINTER(); + return 0; +#else + return 1; +#endif +} + +/** LLVMInitializeNativeTargetDisassembler - The main program should call this + function to initialize the disassembler for the native target corresponding + to the host. */ +static inline LLVMBool LLVMInitializeNativeDisassembler(void) { +#ifdef LLVM_NATIVE_DISASSEMBLER + LLVM_NATIVE_DISASSEMBLER(); + return 0; +#else + return 1; +#endif +} + +/*===-- 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); + +/** 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. + See the method llvm::PassManagerBase::add. */ +void LLVMAddTargetLibraryInfo(LLVMTargetLibraryInfoRef TLI, + LLVMPassManagerRef PM); + +/** Converts target data to a target layout string. The string must be disposed + with LLVMDisposeMessage. + See the constructor llvm::DataLayout::DataLayout. */ +char *LLVMCopyStringRepOfTargetData(LLVMTargetDataRef TD); + +/** Returns the byte order of a target, either LLVMBigEndian or + LLVMLittleEndian. + See the method llvm::DataLayout::isLittleEndian. */ +enum LLVMByteOrdering LLVMByteOrder(LLVMTargetDataRef TD); + +/** Returns the pointer size in bytes for a target. + See the method llvm::DataLayout::getPointerSize. */ +unsigned LLVMPointerSize(LLVMTargetDataRef TD); + +/** Returns the pointer size in bytes for a target for a specified + address space. + See the method llvm::DataLayout::getPointerSize. */ +unsigned LLVMPointerSizeForAS(LLVMTargetDataRef TD, unsigned AS); + +/** Returns the integer type that is the same size as a pointer on a target. + See the method llvm::DataLayout::getIntPtrType. */ +LLVMTypeRef LLVMIntPtrType(LLVMTargetDataRef TD); + +/** Returns the integer type that is the same size as a pointer on a target. + This version allows the address space to be specified. + See the method llvm::DataLayout::getIntPtrType. */ +LLVMTypeRef LLVMIntPtrTypeForAS(LLVMTargetDataRef TD, unsigned AS); + +/** Returns the integer type that is the same size as a pointer on a target. + See the method llvm::DataLayout::getIntPtrType. */ +LLVMTypeRef LLVMIntPtrTypeInContext(LLVMContextRef C, LLVMTargetDataRef TD); + +/** Returns the integer type that is the same size as a pointer on a target. + This version allows the address space to be specified. + See the method llvm::DataLayout::getIntPtrType. */ +LLVMTypeRef LLVMIntPtrTypeForASInContext(LLVMContextRef C, LLVMTargetDataRef TD, + unsigned AS); + +/** Computes the size of a type in bytes for a target. + See the method llvm::DataLayout::getTypeSizeInBits. */ +unsigned long long LLVMSizeOfTypeInBits(LLVMTargetDataRef TD, LLVMTypeRef Ty); + +/** Computes the storage size of a type in bytes for a target. + See the method llvm::DataLayout::getTypeStoreSize. */ +unsigned long long LLVMStoreSizeOfType(LLVMTargetDataRef TD, LLVMTypeRef Ty); + +/** Computes the ABI size of a type in bytes for a target. + See the method llvm::DataLayout::getTypeAllocSize. */ +unsigned long long LLVMABISizeOfType(LLVMTargetDataRef TD, LLVMTypeRef Ty); + +/** Computes the ABI alignment of a type in bytes for a target. + See the method llvm::DataLayout::getTypeABISize. */ +unsigned LLVMABIAlignmentOfType(LLVMTargetDataRef TD, LLVMTypeRef Ty); + +/** Computes the call frame alignment of a type in bytes for a target. + See the method llvm::DataLayout::getTypeABISize. */ +unsigned LLVMCallFrameAlignmentOfType(LLVMTargetDataRef TD, LLVMTypeRef Ty); + +/** Computes the preferred alignment of a type in bytes for a target. + See the method llvm::DataLayout::getTypeABISize. */ +unsigned LLVMPreferredAlignmentOfType(LLVMTargetDataRef TD, LLVMTypeRef Ty); + +/** Computes the preferred alignment of a global variable in bytes for a target. + See the method llvm::DataLayout::getPreferredAlignment. */ +unsigned LLVMPreferredAlignmentOfGlobal(LLVMTargetDataRef TD, + LLVMValueRef GlobalVar); + +/** Computes the structure element that contains the byte offset for a target. + See the method llvm::StructLayout::getElementContainingOffset. */ +unsigned LLVMElementAtOffset(LLVMTargetDataRef TD, LLVMTypeRef StructTy, + unsigned long long Offset); + +/** Computes the byte offset of the indexed struct element for a target. + See the method llvm::StructLayout::getElementContainingOffset. */ +unsigned long long LLVMOffsetOfElement(LLVMTargetDataRef TD, + LLVMTypeRef StructTy, unsigned Element); + +/** + * @} + */ + +LLVM_C_EXTERN_C_END + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/TargetMachine.h b/third_party/llvm-10.0/llvm/include/llvm-c/TargetMachine.h new file mode 100644 index 0000000..f82edd9 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/TargetMachine.h
@@ -0,0 +1,161 @@ +/*===-- llvm-c/TargetMachine.h - Target Machine Library C Interface - C++ -*-=*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to the Target and TargetMachine *| +|* classes, which can be used to generate assembly or object files. *| +|* *| +|* Many exotic languages can interoperate with C code but have a harder time *| +|* with C++ due to name mangling. So in addition to C, this interface enables *| +|* tools written in such languages. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_TARGETMACHINE_H +#define LLVM_C_TARGETMACHINE_H + +#include "llvm-c/ExternC.h" +#include "llvm-c/Target.h" +#include "llvm-c/Types.h" + +LLVM_C_EXTERN_C_BEGIN + +typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef; +typedef struct LLVMTarget *LLVMTargetRef; + +typedef enum { + LLVMCodeGenLevelNone, + LLVMCodeGenLevelLess, + LLVMCodeGenLevelDefault, + LLVMCodeGenLevelAggressive +} LLVMCodeGenOptLevel; + +typedef enum { + LLVMRelocDefault, + LLVMRelocStatic, + LLVMRelocPIC, + LLVMRelocDynamicNoPic, + LLVMRelocROPI, + LLVMRelocRWPI, + LLVMRelocROPI_RWPI +} LLVMRelocMode; + +typedef enum { + LLVMCodeModelDefault, + LLVMCodeModelJITDefault, + LLVMCodeModelTiny, + LLVMCodeModelSmall, + LLVMCodeModelKernel, + LLVMCodeModelMedium, + LLVMCodeModelLarge +} LLVMCodeModel; + +typedef enum { + LLVMAssemblyFile, + LLVMObjectFile +} LLVMCodeGenFileType; + +/** Returns the first llvm::Target in the registered targets list. */ +LLVMTargetRef LLVMGetFirstTarget(void); +/** Returns the next llvm::Target given a previous one (or null if there's none) */ +LLVMTargetRef LLVMGetNextTarget(LLVMTargetRef T); + +/*===-- Target ------------------------------------------------------------===*/ +/** Finds the target corresponding to the given name and stores it in \p T. + Returns 0 on success. */ +LLVMTargetRef LLVMGetTargetFromName(const char *Name); + +/** Finds the target corresponding to the given triple and stores it in \p T. + Returns 0 on success. Optionally returns any error in ErrorMessage. + Use LLVMDisposeMessage to dispose the message. */ +LLVMBool LLVMGetTargetFromTriple(const char* Triple, LLVMTargetRef *T, + char **ErrorMessage); + +/** Returns the name of a target. See llvm::Target::getName */ +const char *LLVMGetTargetName(LLVMTargetRef T); + +/** Returns the description of a target. See llvm::Target::getDescription */ +const char *LLVMGetTargetDescription(LLVMTargetRef T); + +/** Returns if the target has a JIT */ +LLVMBool LLVMTargetHasJIT(LLVMTargetRef T); + +/** Returns if the target has a TargetMachine associated */ +LLVMBool LLVMTargetHasTargetMachine(LLVMTargetRef T); + +/** Returns if the target as an ASM backend (required for emitting output) */ +LLVMBool LLVMTargetHasAsmBackend(LLVMTargetRef T); + +/*===-- Target Machine ----------------------------------------------------===*/ +/** Creates a new llvm::TargetMachine. See llvm::Target::createTargetMachine */ +LLVMTargetMachineRef LLVMCreateTargetMachine(LLVMTargetRef T, + const char *Triple, const char *CPU, const char *Features, + LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc, LLVMCodeModel CodeModel); + +/** Dispose the LLVMTargetMachineRef instance generated by + LLVMCreateTargetMachine. */ +void LLVMDisposeTargetMachine(LLVMTargetMachineRef T); + +/** Returns the Target used in a TargetMachine */ +LLVMTargetRef LLVMGetTargetMachineTarget(LLVMTargetMachineRef T); + +/** Returns the triple used creating this target machine. See + llvm::TargetMachine::getTriple. The result needs to be disposed with + LLVMDisposeMessage. */ +char *LLVMGetTargetMachineTriple(LLVMTargetMachineRef T); + +/** Returns the cpu used creating this target machine. See + llvm::TargetMachine::getCPU. The result needs to be disposed with + LLVMDisposeMessage. */ +char *LLVMGetTargetMachineCPU(LLVMTargetMachineRef T); + +/** Returns the feature string used creating this target machine. See + llvm::TargetMachine::getFeatureString. The result needs to be disposed with + LLVMDisposeMessage. */ +char *LLVMGetTargetMachineFeatureString(LLVMTargetMachineRef T); + +/** Create a DataLayout based on the targetMachine. */ +LLVMTargetDataRef LLVMCreateTargetDataLayout(LLVMTargetMachineRef T); + +/** Set the target machine's ASM verbosity. */ +void LLVMSetTargetMachineAsmVerbosity(LLVMTargetMachineRef T, + LLVMBool VerboseAsm); + +/** Emits an asm or object file for the given module to the filename. This + wraps several c++ only classes (among them a file stream). Returns any + error in ErrorMessage. Use LLVMDisposeMessage to dispose the message. */ +LLVMBool LLVMTargetMachineEmitToFile(LLVMTargetMachineRef T, LLVMModuleRef M, + char *Filename, LLVMCodeGenFileType codegen, char **ErrorMessage); + +/** Compile the LLVM IR stored in \p M and store the result in \p OutMemBuf. */ +LLVMBool LLVMTargetMachineEmitToMemoryBuffer(LLVMTargetMachineRef T, LLVMModuleRef M, + LLVMCodeGenFileType codegen, char** ErrorMessage, LLVMMemoryBufferRef *OutMemBuf); + +/*===-- Triple ------------------------------------------------------------===*/ +/** Get a triple for the host machine as a string. The result needs to be + disposed with LLVMDisposeMessage. */ +char* LLVMGetDefaultTargetTriple(void); + +/** Normalize a target triple. The result needs to be disposed with + LLVMDisposeMessage. */ +char* LLVMNormalizeTargetTriple(const char* triple); + +/** Get the host CPU as a string. The result needs to be disposed with + LLVMDisposeMessage. */ +char* LLVMGetHostCPUName(void); + +/** Get the host CPU's features as a string. The result needs to be disposed + with LLVMDisposeMessage. */ +char* LLVMGetHostCPUFeatures(void); + +/** Adds the target-specific analysis passes to the pass manager. */ +void LLVMAddAnalysisPasses(LLVMTargetMachineRef T, LLVMPassManagerRef PM); + +LLVM_C_EXTERN_C_END + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/Transforms/AggressiveInstCombine.h b/third_party/llvm-10.0/llvm/include/llvm-c/Transforms/AggressiveInstCombine.h new file mode 100644 index 0000000..db061a7 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/Transforms/AggressiveInstCombine.h
@@ -0,0 +1,40 @@ +/*===-- AggressiveInstCombine.h ---------------------------------*- C++ -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to libLLVMAggressiveInstCombine.a, *| +|* which combines instructions to form fewer, simple IR instructions. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_TRANSFORMS_AGGRESSIVEINSTCOMBINE_H +#define LLVM_C_TRANSFORMS_AGGRESSIVEINSTCOMBINE_H + +#include "llvm-c/ExternC.h" +#include "llvm-c/Types.h" + +LLVM_C_EXTERN_C_BEGIN + +/** + * @defgroup LLVMCTransformsAggressiveInstCombine Aggressive Instruction Combining transformations + * @ingroup LLVMCTransforms + * + * @{ + */ + +/** See llvm::createAggressiveInstCombinerPass function. */ +void LLVMAddAggressiveInstCombinerPass(LLVMPassManagerRef PM); + +/** + * @} + */ + +LLVM_C_EXTERN_C_END + +#endif +
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/Transforms/Coroutines.h b/third_party/llvm-10.0/llvm/include/llvm-c/Transforms/Coroutines.h new file mode 100644 index 0000000..15798af --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/Transforms/Coroutines.h
@@ -0,0 +1,52 @@ +/*===-- Coroutines.h - Coroutines Library C Interface -----------*- C++ -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to libLLVMCoroutines.a, which *| +|* implements various scalar transformations of the LLVM IR. *| +|* *| +|* Many exotic languages can interoperate with C code but have a harder time *| +|* with C++ due to name mangling. So in addition to C, this interface enables *| +|* tools written in such languages. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_TRANSFORMS_COROUTINES_H +#define LLVM_C_TRANSFORMS_COROUTINES_H + +#include "llvm-c/ExternC.h" +#include "llvm-c/Types.h" + +LLVM_C_EXTERN_C_BEGIN + +/** + * @defgroup LLVMCTransformsCoroutines Coroutine transformations + * @ingroup LLVMCTransforms + * + * @{ + */ + +/** See llvm::createCoroEarlyLegacyPass function. */ +void LLVMAddCoroEarlyPass(LLVMPassManagerRef PM); + +/** See llvm::createCoroSplitLegacyPass function. */ +void LLVMAddCoroSplitPass(LLVMPassManagerRef PM); + +/** See llvm::createCoroElideLegacyPass function. */ +void LLVMAddCoroElidePass(LLVMPassManagerRef PM); + +/** See llvm::createCoroCleanupLegacyPass function. */ +void LLVMAddCoroCleanupPass(LLVMPassManagerRef PM); + +/** + * @} + */ + +LLVM_C_EXTERN_C_END + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/Transforms/IPO.h b/third_party/llvm-10.0/llvm/include/llvm-c/Transforms/IPO.h new file mode 100644 index 0000000..cde3d24 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/Transforms/IPO.h
@@ -0,0 +1,99 @@ +/*===-- IPO.h - Interprocedural Transformations C Interface -----*- C++ -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to libLLVMIPO.a, which implements *| +|* various interprocedural transformations of the LLVM IR. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_TRANSFORMS_IPO_H +#define LLVM_C_TRANSFORMS_IPO_H + +#include "llvm-c/ExternC.h" +#include "llvm-c/Types.h" + +LLVM_C_EXTERN_C_BEGIN + +/** + * @defgroup LLVMCTransformsIPO Interprocedural transformations + * @ingroup LLVMCTransforms + * + * @{ + */ + +/** See llvm::createArgumentPromotionPass function. */ +void LLVMAddArgumentPromotionPass(LLVMPassManagerRef PM); + +/** See llvm::createConstantMergePass function. */ +void LLVMAddConstantMergePass(LLVMPassManagerRef PM); + +/** See llvm::createMergeFunctionsPass function. */ +void LLVMAddMergeFunctionsPass(LLVMPassManagerRef PM); + +/** See llvm::createCalledValuePropagationPass function. */ +void LLVMAddCalledValuePropagationPass(LLVMPassManagerRef PM); + +/** See llvm::createDeadArgEliminationPass function. */ +void LLVMAddDeadArgEliminationPass(LLVMPassManagerRef PM); + +/** See llvm::createFunctionAttrsPass function. */ +void LLVMAddFunctionAttrsPass(LLVMPassManagerRef PM); + +/** See llvm::createFunctionInliningPass function. */ +void LLVMAddFunctionInliningPass(LLVMPassManagerRef PM); + +/** See llvm::createAlwaysInlinerPass function. */ +void LLVMAddAlwaysInlinerPass(LLVMPassManagerRef PM); + +/** See llvm::createGlobalDCEPass function. */ +void LLVMAddGlobalDCEPass(LLVMPassManagerRef PM); + +/** See llvm::createGlobalOptimizerPass function. */ +void LLVMAddGlobalOptimizerPass(LLVMPassManagerRef PM); + +/** See llvm::createIPConstantPropagationPass function. */ +void LLVMAddIPConstantPropagationPass(LLVMPassManagerRef PM); + +/** See llvm::createPruneEHPass function. */ +void LLVMAddPruneEHPass(LLVMPassManagerRef PM); + +/** See llvm::createIPSCCPPass function. */ +void LLVMAddIPSCCPPass(LLVMPassManagerRef PM); + +/** See llvm::createInternalizePass function. */ +void LLVMAddInternalizePass(LLVMPassManagerRef, unsigned AllButMain); + +/** + * Create and add the internalize pass to the given pass manager with the + * provided preservation callback. + * + * The context parameter is forwarded to the callback on each invocation. + * As such, it is the responsibility of the caller to extend its lifetime + * until execution of this pass has finished. + * + * @see llvm::createInternalizePass function. + */ +void LLVMAddInternalizePassWithMustPreservePredicate( + LLVMPassManagerRef PM, + void *Context, + LLVMBool (*MustPreserve)(LLVMValueRef, void *)); + +/** See llvm::createStripDeadPrototypesPass function. */ +void LLVMAddStripDeadPrototypesPass(LLVMPassManagerRef PM); + +/** See llvm::createStripSymbolsPass function. */ +void LLVMAddStripSymbolsPass(LLVMPassManagerRef PM); + +/** + * @} + */ + +LLVM_C_EXTERN_C_END + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/Transforms/InstCombine.h b/third_party/llvm-10.0/llvm/include/llvm-c/Transforms/InstCombine.h new file mode 100644 index 0000000..ebe17d6 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/Transforms/InstCombine.h
@@ -0,0 +1,40 @@ +/*===-- Scalar.h - Scalar Transformation Library C Interface ----*- C++ -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to libLLVMInstCombine.a, which *| +|* combines instructions to form fewer, simple IR instructions. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_TRANSFORMS_INSTCOMBINE_H +#define LLVM_C_TRANSFORMS_INSTCOMBINE_H + +#include "llvm-c/ExternC.h" +#include "llvm-c/Types.h" + +LLVM_C_EXTERN_C_BEGIN + +/** + * @defgroup LLVMCTransformsInstCombine Instruction Combining transformations + * @ingroup LLVMCTransforms + * + * @{ + */ + +/** See llvm::createInstructionCombiningPass function. */ +void LLVMAddInstructionCombiningPass(LLVMPassManagerRef PM); + +/** + * @} + */ + +LLVM_C_EXTERN_C_END + +#endif +
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/Transforms/PassManagerBuilder.h b/third_party/llvm-10.0/llvm/include/llvm-c/Transforms/PassManagerBuilder.h new file mode 100644 index 0000000..6e13e18 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/Transforms/PassManagerBuilder.h
@@ -0,0 +1,87 @@ +/*===-- llvm-c/Transform/PassManagerBuilder.h - PMB C Interface ---*- C -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to the PassManagerBuilder class. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_TRANSFORMS_PASSMANAGERBUILDER_H +#define LLVM_C_TRANSFORMS_PASSMANAGERBUILDER_H + +#include "llvm-c/ExternC.h" +#include "llvm-c/Types.h" + +typedef struct LLVMOpaquePassManagerBuilder *LLVMPassManagerBuilderRef; + +LLVM_C_EXTERN_C_BEGIN + +/** + * @defgroup LLVMCTransformsPassManagerBuilder Pass manager builder + * @ingroup LLVMCTransforms + * + * @{ + */ + +/** See llvm::PassManagerBuilder. */ +LLVMPassManagerBuilderRef LLVMPassManagerBuilderCreate(void); +void LLVMPassManagerBuilderDispose(LLVMPassManagerBuilderRef PMB); + +/** See llvm::PassManagerBuilder::OptLevel. */ +void +LLVMPassManagerBuilderSetOptLevel(LLVMPassManagerBuilderRef PMB, + unsigned OptLevel); + +/** See llvm::PassManagerBuilder::SizeLevel. */ +void +LLVMPassManagerBuilderSetSizeLevel(LLVMPassManagerBuilderRef PMB, + unsigned SizeLevel); + +/** See llvm::PassManagerBuilder::DisableUnitAtATime. */ +void +LLVMPassManagerBuilderSetDisableUnitAtATime(LLVMPassManagerBuilderRef PMB, + LLVMBool Value); + +/** See llvm::PassManagerBuilder::DisableUnrollLoops. */ +void +LLVMPassManagerBuilderSetDisableUnrollLoops(LLVMPassManagerBuilderRef PMB, + LLVMBool Value); + +/** See llvm::PassManagerBuilder::DisableSimplifyLibCalls */ +void +LLVMPassManagerBuilderSetDisableSimplifyLibCalls(LLVMPassManagerBuilderRef PMB, + LLVMBool Value); + +/** See llvm::PassManagerBuilder::Inliner. */ +void +LLVMPassManagerBuilderUseInlinerWithThreshold(LLVMPassManagerBuilderRef PMB, + unsigned Threshold); + +/** See llvm::PassManagerBuilder::populateFunctionPassManager. */ +void +LLVMPassManagerBuilderPopulateFunctionPassManager(LLVMPassManagerBuilderRef PMB, + LLVMPassManagerRef PM); + +/** See llvm::PassManagerBuilder::populateModulePassManager. */ +void +LLVMPassManagerBuilderPopulateModulePassManager(LLVMPassManagerBuilderRef PMB, + LLVMPassManagerRef PM); + +/** See llvm::PassManagerBuilder::populateLTOPassManager. */ +void LLVMPassManagerBuilderPopulateLTOPassManager(LLVMPassManagerBuilderRef PMB, + LLVMPassManagerRef PM, + LLVMBool Internalize, + LLVMBool RunInliner); + +/** + * @} + */ + +LLVM_C_EXTERN_C_END + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/Transforms/Scalar.h b/third_party/llvm-10.0/llvm/include/llvm-c/Transforms/Scalar.h new file mode 100644 index 0000000..93d79a2 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/Transforms/Scalar.h
@@ -0,0 +1,170 @@ +/*===-- Scalar.h - Scalar Transformation Library C Interface ----*- C++ -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to libLLVMScalarOpts.a, which *| +|* implements various scalar transformations of the LLVM IR. *| +|* *| +|* Many exotic languages can interoperate with C code but have a harder time *| +|* with C++ due to name mangling. So in addition to C, this interface enables *| +|* tools written in such languages. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_TRANSFORMS_SCALAR_H +#define LLVM_C_TRANSFORMS_SCALAR_H + +#include "llvm-c/ExternC.h" +#include "llvm-c/Types.h" + +LLVM_C_EXTERN_C_BEGIN + +/** + * @defgroup LLVMCTransformsScalar Scalar transformations + * @ingroup LLVMCTransforms + * + * @{ + */ + +/** See llvm::createAggressiveDCEPass function. */ +void LLVMAddAggressiveDCEPass(LLVMPassManagerRef PM); + +/** See llvm::createDeadCodeEliminationPass function. */ +void LLVMAddDCEPass(LLVMPassManagerRef PM); + +/** See llvm::createBitTrackingDCEPass function. */ +void LLVMAddBitTrackingDCEPass(LLVMPassManagerRef PM); + +/** See llvm::createAlignmentFromAssumptionsPass function. */ +void LLVMAddAlignmentFromAssumptionsPass(LLVMPassManagerRef PM); + +/** See llvm::createCFGSimplificationPass function. */ +void LLVMAddCFGSimplificationPass(LLVMPassManagerRef PM); + +/** See llvm::createDeadStoreEliminationPass function. */ +void LLVMAddDeadStoreEliminationPass(LLVMPassManagerRef PM); + +/** See llvm::createScalarizerPass function. */ +void LLVMAddScalarizerPass(LLVMPassManagerRef PM); + +/** See llvm::createMergedLoadStoreMotionPass function. */ +void LLVMAddMergedLoadStoreMotionPass(LLVMPassManagerRef PM); + +/** See llvm::createGVNPass function. */ +void LLVMAddGVNPass(LLVMPassManagerRef PM); + +/** See llvm::createGVNPass function. */ +void LLVMAddNewGVNPass(LLVMPassManagerRef PM); + +/** See llvm::createIndVarSimplifyPass function. */ +void LLVMAddIndVarSimplifyPass(LLVMPassManagerRef PM); + +/** See llvm::createInstructionCombiningPass function. */ +void LLVMAddInstructionCombiningPass(LLVMPassManagerRef PM); + +/** See llvm::createJumpThreadingPass function. */ +void LLVMAddJumpThreadingPass(LLVMPassManagerRef PM); + +/** See llvm::createLICMPass function. */ +void LLVMAddLICMPass(LLVMPassManagerRef PM); + +/** See llvm::createLoopDeletionPass function. */ +void LLVMAddLoopDeletionPass(LLVMPassManagerRef PM); + +/** See llvm::createLoopIdiomPass function */ +void LLVMAddLoopIdiomPass(LLVMPassManagerRef PM); + +/** See llvm::createLoopRotatePass function. */ +void LLVMAddLoopRotatePass(LLVMPassManagerRef PM); + +/** See llvm::createLoopRerollPass function. */ +void LLVMAddLoopRerollPass(LLVMPassManagerRef PM); + +/** See llvm::createLoopUnrollPass function. */ +void LLVMAddLoopUnrollPass(LLVMPassManagerRef PM); + +/** See llvm::createLoopUnrollAndJamPass function. */ +void LLVMAddLoopUnrollAndJamPass(LLVMPassManagerRef PM); + +/** See llvm::createLoopUnswitchPass function. */ +void LLVMAddLoopUnswitchPass(LLVMPassManagerRef PM); + +/** See llvm::createLowerAtomicPass function. */ +void LLVMAddLowerAtomicPass(LLVMPassManagerRef PM); + +/** See llvm::createMemCpyOptPass function. */ +void LLVMAddMemCpyOptPass(LLVMPassManagerRef PM); + +/** See llvm::createPartiallyInlineLibCallsPass function. */ +void LLVMAddPartiallyInlineLibCallsPass(LLVMPassManagerRef PM); + +/** See llvm::createReassociatePass function. */ +void LLVMAddReassociatePass(LLVMPassManagerRef PM); + +/** See llvm::createSCCPPass function. */ +void LLVMAddSCCPPass(LLVMPassManagerRef PM); + +/** See llvm::createSROAPass function. */ +void LLVMAddScalarReplAggregatesPass(LLVMPassManagerRef PM); + +/** See llvm::createSROAPass function. */ +void LLVMAddScalarReplAggregatesPassSSA(LLVMPassManagerRef PM); + +/** See llvm::createSROAPass function. */ +void LLVMAddScalarReplAggregatesPassWithThreshold(LLVMPassManagerRef PM, + int Threshold); + +/** See llvm::createSimplifyLibCallsPass function. */ +void LLVMAddSimplifyLibCallsPass(LLVMPassManagerRef PM); + +/** See llvm::createTailCallEliminationPass function. */ +void LLVMAddTailCallEliminationPass(LLVMPassManagerRef PM); + +/** See llvm::createConstantPropagationPass function. */ +void LLVMAddConstantPropagationPass(LLVMPassManagerRef PM); + +/** See llvm::demotePromoteMemoryToRegisterPass function. */ +void LLVMAddDemoteMemoryToRegisterPass(LLVMPassManagerRef PM); + +/** See llvm::createVerifierPass function. */ +void LLVMAddVerifierPass(LLVMPassManagerRef PM); + +/** See llvm::createCorrelatedValuePropagationPass function */ +void LLVMAddCorrelatedValuePropagationPass(LLVMPassManagerRef PM); + +/** See llvm::createEarlyCSEPass function */ +void LLVMAddEarlyCSEPass(LLVMPassManagerRef PM); + +/** See llvm::createEarlyCSEPass function */ +void LLVMAddEarlyCSEMemSSAPass(LLVMPassManagerRef PM); + +/** See llvm::createLowerExpectIntrinsicPass function */ +void LLVMAddLowerExpectIntrinsicPass(LLVMPassManagerRef PM); + +/** See llvm::createLowerConstantIntrinsicsPass function */ +void LLVMAddLowerConstantIntrinsicsPass(LLVMPassManagerRef PM); + +/** See llvm::createTypeBasedAliasAnalysisPass function */ +void LLVMAddTypeBasedAliasAnalysisPass(LLVMPassManagerRef PM); + +/** See llvm::createScopedNoAliasAAPass function */ +void LLVMAddScopedNoAliasAAPass(LLVMPassManagerRef PM); + +/** See llvm::createBasicAliasAnalysisPass function */ +void LLVMAddBasicAliasAnalysisPass(LLVMPassManagerRef PM); + +/** See llvm::createUnifyFunctionExitNodesPass function */ +void LLVMAddUnifyFunctionExitNodesPass(LLVMPassManagerRef PM); + +/** + * @} + */ + +LLVM_C_EXTERN_C_END + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/Transforms/Utils.h b/third_party/llvm-10.0/llvm/include/llvm-c/Transforms/Utils.h new file mode 100644 index 0000000..30d1ae6 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/Transforms/Utils.h
@@ -0,0 +1,50 @@ +/*===-- Utils.h - Transformation Utils Library C Interface ------*- C++ -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to libLLVMTransformUtils.a, which *| +|* implements various transformation utilities of the LLVM IR. *| +|* *| +|* Many exotic languages can interoperate with C code but have a harder time *| +|* with C++ due to name mangling. So in addition to C, this interface enables *| +|* tools written in such languages. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_TRANSFORMS_UTILS_H +#define LLVM_C_TRANSFORMS_UTILS_H + +#include "llvm-c/ExternC.h" +#include "llvm-c/Types.h" + +LLVM_C_EXTERN_C_BEGIN + +/** + * @defgroup LLVMCTransformsUtils Transformation Utilities + * @ingroup LLVMCTransforms + * + * @{ + */ + +/** See llvm::createLowerSwitchPass function. */ +void LLVMAddLowerSwitchPass(LLVMPassManagerRef PM); + +/** See llvm::createPromoteMemoryToRegisterPass function. */ +void LLVMAddPromoteMemoryToRegisterPass(LLVMPassManagerRef PM); + +/** See llvm::createAddDiscriminatorsPass function. */ +void LLVMAddAddDiscriminatorsPass(LLVMPassManagerRef PM); + +/** + * @} + */ + +LLVM_C_EXTERN_C_END + +#endif +
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/Transforms/Vectorize.h b/third_party/llvm-10.0/llvm/include/llvm-c/Transforms/Vectorize.h new file mode 100644 index 0000000..0de4583 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/Transforms/Vectorize.h
@@ -0,0 +1,47 @@ +/*===---------------------------Vectorize.h --------------------- -*- C -*-===*\ +|*===----------- Vectorization Transformation Library C Interface ---------===*| +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to libLLVMVectorize.a, which *| +|* implements various vectorization transformations of the LLVM IR. *| +|* *| +|* Many exotic languages can interoperate with C code but have a harder time *| +|* with C++ due to name mangling. So in addition to C, this interface enables *| +|* tools written in such languages. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_TRANSFORMS_VECTORIZE_H +#define LLVM_C_TRANSFORMS_VECTORIZE_H + +#include "llvm-c/ExternC.h" +#include "llvm-c/Types.h" + +LLVM_C_EXTERN_C_BEGIN + +/** + * @defgroup LLVMCTransformsVectorize Vectorization transformations + * @ingroup LLVMCTransforms + * + * @{ + */ + +/** See llvm::createLoopVectorizePass function. */ +void LLVMAddLoopVectorizePass(LLVMPassManagerRef PM); + +/** See llvm::createSLPVectorizerPass function. */ +void LLVMAddSLPVectorizePass(LLVMPassManagerRef PM); + +/** + * @} + */ + +LLVM_C_EXTERN_C_END + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/Types.h b/third_party/llvm-10.0/llvm/include/llvm-c/Types.h new file mode 100644 index 0000000..4e02498 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/Types.h
@@ -0,0 +1,176 @@ +/*===-- llvm-c/Support.h - C Interface Types declarations ---------*- C -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file defines types used by the C interface to LLVM. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_TYPES_H +#define LLVM_C_TYPES_H + +#include "llvm-c/DataTypes.h" +#include "llvm-c/ExternC.h" + +LLVM_C_EXTERN_C_BEGIN + +/** + * @defgroup LLVMCSupportTypes Types and Enumerations + * + * @{ + */ + +typedef int LLVMBool; + +/* Opaque types. */ + +/** + * LLVM uses a polymorphic type hierarchy which C cannot represent, therefore + * parameters must be passed as base types. Despite the declared types, most + * of the functions provided operate only on branches of the type hierarchy. + * The declared parameter names are descriptive and specify which type is + * required. Additionally, each type hierarchy is documented along with the + * functions that operate upon it. For more detail, refer to LLVM's C++ code. + * If in doubt, refer to Core.cpp, which performs parameter downcasts in the + * form unwrap<RequiredType>(Param). + */ + +/** + * Used to pass regions of memory through LLVM interfaces. + * + * @see llvm::MemoryBuffer + */ +typedef struct LLVMOpaqueMemoryBuffer *LLVMMemoryBufferRef; + +/** + * The top-level container for all LLVM global data. See the LLVMContext class. + */ +typedef struct LLVMOpaqueContext *LLVMContextRef; + +/** + * The top-level container for all other LLVM Intermediate Representation (IR) + * objects. + * + * @see llvm::Module + */ +typedef struct LLVMOpaqueModule *LLVMModuleRef; + +/** + * Each value in the LLVM IR has a type, an LLVMTypeRef. + * + * @see llvm::Type + */ +typedef struct LLVMOpaqueType *LLVMTypeRef; + +/** + * Represents an individual value in LLVM IR. + * + * This models llvm::Value. + */ +typedef struct LLVMOpaqueValue *LLVMValueRef; + +/** + * Represents a basic block of instructions in LLVM IR. + * + * This models llvm::BasicBlock. + */ +typedef struct LLVMOpaqueBasicBlock *LLVMBasicBlockRef; + +/** + * Represents an LLVM Metadata. + * + * This models llvm::Metadata. + */ +typedef struct LLVMOpaqueMetadata *LLVMMetadataRef; + +/** + * Represents an LLVM Named Metadata Node. + * + * This models llvm::NamedMDNode. + */ +typedef struct LLVMOpaqueNamedMDNode *LLVMNamedMDNodeRef; + +/** + * Represents an entry in a Global Object's metadata attachments. + * + * This models std::pair<unsigned, MDNode *> + */ +typedef struct LLVMOpaqueValueMetadataEntry LLVMValueMetadataEntry; + +/** + * Represents an LLVM basic block builder. + * + * This models llvm::IRBuilder. + */ +typedef struct LLVMOpaqueBuilder *LLVMBuilderRef; + +/** + * Represents an LLVM debug info builder. + * + * This models llvm::DIBuilder. + */ +typedef struct LLVMOpaqueDIBuilder *LLVMDIBuilderRef; + +/** + * Interface used to provide a module to JIT or interpreter. + * This is now just a synonym for llvm::Module, but we have to keep using the + * different type to keep binary compatibility. + */ +typedef struct LLVMOpaqueModuleProvider *LLVMModuleProviderRef; + +/** @see llvm::PassManagerBase */ +typedef struct LLVMOpaquePassManager *LLVMPassManagerRef; + +/** @see llvm::PassRegistry */ +typedef struct LLVMOpaquePassRegistry *LLVMPassRegistryRef; + +/** + * Used to get the users and usees of a Value. + * + * @see llvm::Use */ +typedef struct LLVMOpaqueUse *LLVMUseRef; + +/** + * Used to represent an attributes. + * + * @see llvm::Attribute + */ +typedef struct LLVMOpaqueAttributeRef *LLVMAttributeRef; + +/** + * @see llvm::DiagnosticInfo + */ +typedef struct LLVMOpaqueDiagnosticInfo *LLVMDiagnosticInfoRef; + +/** + * @see llvm::Comdat + */ +typedef struct LLVMComdat *LLVMComdatRef; + +/** + * @see llvm::Module::ModuleFlagEntry + */ +typedef struct LLVMOpaqueModuleFlagEntry LLVMModuleFlagEntry; + +/** + * @see llvm::JITEventListener + */ +typedef struct LLVMOpaqueJITEventListener *LLVMJITEventListenerRef; + +/** + * @see llvm::object::Binary + */ +typedef struct LLVMOpaqueBinary *LLVMBinaryRef; + +/** + * @} + */ + +LLVM_C_EXTERN_C_END + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/lto.h b/third_party/llvm-10.0/llvm/include/llvm-c/lto.h new file mode 100644 index 0000000..97a8f48 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/lto.h
@@ -0,0 +1,918 @@ +/*===-- llvm-c/lto.h - LTO Public C Interface ---------------------*- C -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header provides public interface to an abstract link time optimization*| +|* library. LLVM provides an implementation of this interface for use with *| +|* llvm bitcode files. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_LTO_H +#define LLVM_C_LTO_H + +#include "llvm-c/ExternC.h" + +#ifdef __cplusplus +#include <cstddef> +#else +#include <stddef.h> +#endif +#include <sys/types.h> + +#ifndef __cplusplus +#if !defined(_MSC_VER) +#include <stdbool.h> +typedef bool lto_bool_t; +#else +/* MSVC in particular does not have anything like _Bool or bool in C, but we can + at least make sure the type is the same size. The implementation side will + use C++ bool. */ +typedef unsigned char lto_bool_t; +#endif +#else +typedef bool lto_bool_t; +#endif + +/** + * @defgroup LLVMCLTO LTO + * @ingroup LLVMC + * + * @{ + */ + +#define LTO_API_VERSION 26 + +/** + * \since prior to LTO_API_VERSION=3 + */ +typedef enum { + LTO_SYMBOL_ALIGNMENT_MASK = 0x0000001F, /* log2 of alignment */ + LTO_SYMBOL_PERMISSIONS_MASK = 0x000000E0, + LTO_SYMBOL_PERMISSIONS_CODE = 0x000000A0, + LTO_SYMBOL_PERMISSIONS_DATA = 0x000000C0, + LTO_SYMBOL_PERMISSIONS_RODATA = 0x00000080, + LTO_SYMBOL_DEFINITION_MASK = 0x00000700, + LTO_SYMBOL_DEFINITION_REGULAR = 0x00000100, + LTO_SYMBOL_DEFINITION_TENTATIVE = 0x00000200, + LTO_SYMBOL_DEFINITION_WEAK = 0x00000300, + LTO_SYMBOL_DEFINITION_UNDEFINED = 0x00000400, + LTO_SYMBOL_DEFINITION_WEAKUNDEF = 0x00000500, + LTO_SYMBOL_SCOPE_MASK = 0x00003800, + LTO_SYMBOL_SCOPE_INTERNAL = 0x00000800, + LTO_SYMBOL_SCOPE_HIDDEN = 0x00001000, + LTO_SYMBOL_SCOPE_PROTECTED = 0x00002000, + LTO_SYMBOL_SCOPE_DEFAULT = 0x00001800, + LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN = 0x00002800, + LTO_SYMBOL_COMDAT = 0x00004000, + LTO_SYMBOL_ALIAS = 0x00008000 +} lto_symbol_attributes; + +/** + * \since prior to LTO_API_VERSION=3 + */ +typedef enum { + LTO_DEBUG_MODEL_NONE = 0, + LTO_DEBUG_MODEL_DWARF = 1 +} lto_debug_model; + +/** + * \since prior to LTO_API_VERSION=3 + */ +typedef enum { + LTO_CODEGEN_PIC_MODEL_STATIC = 0, + LTO_CODEGEN_PIC_MODEL_DYNAMIC = 1, + LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC = 2, + LTO_CODEGEN_PIC_MODEL_DEFAULT = 3 +} lto_codegen_model; + +/** opaque reference to a loaded object module */ +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; + +LLVM_C_EXTERN_C_BEGIN + +/** + * Returns a printable string. + * + * \since prior to LTO_API_VERSION=3 + */ +extern const char* +lto_get_version(void); + +/** + * Returns the last error string or NULL if last operation was successful. + * + * \since prior to LTO_API_VERSION=3 + */ +extern const char* +lto_get_error_message(void); + +/** + * Checks if a file is a loadable object file. + * + * \since prior to LTO_API_VERSION=3 + */ +extern lto_bool_t +lto_module_is_object_file(const char* path); + +/** + * Checks if a file is a loadable object compiled for requested target. + * + * \since prior to LTO_API_VERSION=3 + */ +extern lto_bool_t +lto_module_is_object_file_for_target(const char* path, + const char* target_triple_prefix); + +/** + * Return true if \p Buffer contains a bitcode file with ObjC code (category + * or class) in it. + * + * \since LTO_API_VERSION=20 + */ +extern lto_bool_t +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. + * + * \since prior to LTO_API_VERSION=3 + */ +extern lto_bool_t +lto_module_is_object_file_in_memory_for_target(const void* mem, size_t length, + const char* target_triple_prefix); + +/** + * Loads an object file from disk. + * Returns NULL on error (check lto_get_error_message() for details). + * + * \since prior to LTO_API_VERSION=3 + */ +extern lto_module_t +lto_module_create(const char* path); + +/** + * Loads an object file from memory. + * Returns NULL on error (check lto_get_error_message() for details). + * + * \since prior to LTO_API_VERSION=3 + */ +extern lto_module_t +lto_module_create_from_memory(const void* mem, size_t length); + +/** + * Loads an object file from memory with an extra path argument. + * Returns NULL on error (check lto_get_error_message() for details). + * + * \since LTO_API_VERSION=9 + */ +extern lto_module_t +lto_module_create_from_memory_with_path(const void* mem, size_t length, + const char *path); + +/** + * Loads an object file in its own context. + * + * Loads an object file in its own LLVMContext. This function call is + * thread-safe. However, modules created this way should not be merged into an + * lto_code_gen_t using \a lto_codegen_add_module(). + * + * Returns NULL on error (check lto_get_error_message() for details). + * + * \since LTO_API_VERSION=11 + */ +extern lto_module_t +lto_module_create_in_local_context(const void *mem, size_t length, + const char *path); + +/** + * Loads an object file in the codegen context. + * + * Loads an object file into the same context as \c cg. The module is safe to + * add using \a lto_codegen_add_module(). + * + * Returns NULL on error (check lto_get_error_message() for details). + * + * \since LTO_API_VERSION=11 + */ +extern lto_module_t +lto_module_create_in_codegen_context(const void *mem, size_t length, + const char *path, lto_code_gen_t cg); + +/** + * Loads an object file from disk. The seek point of fd is not preserved. + * Returns NULL on error (check lto_get_error_message() for details). + * + * \since LTO_API_VERSION=5 + */ +extern lto_module_t +lto_module_create_from_fd(int fd, const char *path, size_t file_size); + +/** + * Loads an object file from disk. The seek point of fd is not preserved. + * Returns NULL on error (check lto_get_error_message() for details). + * + * \since LTO_API_VERSION=5 + */ +extern lto_module_t +lto_module_create_from_fd_at_offset(int fd, const char *path, size_t file_size, + size_t map_size, off_t offset); + +/** + * Frees all memory internally allocated by the module. + * Upon return the lto_module_t is no longer valid. + * + * \since prior to LTO_API_VERSION=3 + */ +extern void +lto_module_dispose(lto_module_t mod); + +/** + * Returns triple string which the object module was compiled under. + * + * \since prior to LTO_API_VERSION=3 + */ +extern const char* +lto_module_get_target_triple(lto_module_t mod); + +/** + * Sets triple string with which the object will be codegened. + * + * \since LTO_API_VERSION=4 + */ +extern void +lto_module_set_target_triple(lto_module_t mod, const char *triple); + +/** + * Returns the number of symbols in the object module. + * + * \since prior to LTO_API_VERSION=3 + */ +extern unsigned int +lto_module_get_num_symbols(lto_module_t mod); + +/** + * Returns the name of the ith symbol in the object module. + * + * \since prior to LTO_API_VERSION=3 + */ +extern const char* +lto_module_get_symbol_name(lto_module_t mod, unsigned int index); + +/** + * Returns the attributes of the ith symbol in the object module. + * + * \since prior to LTO_API_VERSION=3 + */ +extern lto_symbol_attributes +lto_module_get_symbol_attribute(lto_module_t mod, unsigned int index); + +/** + * Returns the module's linker options. + * + * The linker options may consist of multiple flags. It is the linker's + * responsibility to split the flags using a platform-specific mechanism. + * + * \since LTO_API_VERSION=16 + */ +extern const char* +lto_module_get_linkeropts(lto_module_t mod); + +/** + * Diagnostic severity. + * + * \since LTO_API_VERSION=7 + */ +typedef enum { + LTO_DS_ERROR = 0, + LTO_DS_WARNING = 1, + LTO_DS_REMARK = 3, // Added in LTO_API_VERSION=10. + LTO_DS_NOTE = 2 +} lto_codegen_diagnostic_severity_t; + +/** + * Diagnostic handler type. + * \p severity defines the severity. + * \p diag is the actual diagnostic. + * The diagnostic is not prefixed by any of severity keyword, e.g., 'error: '. + * \p ctxt is used to pass the context set with the diagnostic handler. + * + * \since LTO_API_VERSION=7 + */ +typedef void (*lto_diagnostic_handler_t)( + lto_codegen_diagnostic_severity_t severity, const char *diag, void *ctxt); + +/** + * Set a diagnostic handler and the related context (void *). + * This is more general than lto_get_error_message, as the diagnostic handler + * can be called at anytime within lto. + * + * \since LTO_API_VERSION=7 + */ +extern void lto_codegen_set_diagnostic_handler(lto_code_gen_t, + lto_diagnostic_handler_t, + void *); + +/** + * Instantiates a code generator. + * Returns NULL on error (check lto_get_error_message() for details). + * + * All modules added using \a lto_codegen_add_module() must have been created + * in the same context as the codegen. + * + * \since prior to LTO_API_VERSION=3 + */ +extern lto_code_gen_t +lto_codegen_create(void); + +/** + * Instantiate a code generator in its own context. + * + * Instantiates a code generator in its own context. Modules added via \a + * lto_codegen_add_module() must have all been created in the same context, + * using \a lto_module_create_in_codegen_context(). + * + * \since LTO_API_VERSION=11 + */ +extern lto_code_gen_t +lto_codegen_create_in_local_context(void); + +/** + * Frees all code generator and all memory it internally allocated. + * Upon return the lto_code_gen_t is no longer valid. + * + * \since prior to LTO_API_VERSION=3 + */ +extern void +lto_codegen_dispose(lto_code_gen_t); + +/** + * Add an object module to the set of modules for which code will be generated. + * Returns true on error (check lto_get_error_message() for details). + * + * \c cg and \c mod must both be in the same context. See \a + * lto_codegen_create_in_local_context() and \a + * lto_module_create_in_codegen_context(). + * + * \since prior to LTO_API_VERSION=3 + */ +extern lto_bool_t +lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod); + +/** + * Sets the object module for code generation. This will transfer the ownership + * of the module to the code generator. + * + * \c cg and \c mod must both be in the same context. + * + * \since LTO_API_VERSION=13 + */ +extern void +lto_codegen_set_module(lto_code_gen_t cg, lto_module_t mod); + +/** + * Sets if debug info should be generated. + * Returns true on error (check lto_get_error_message() for details). + * + * \since prior to LTO_API_VERSION=3 + */ +extern lto_bool_t +lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model); + +/** + * Sets which PIC code model to generated. + * Returns true on error (check lto_get_error_message() for details). + * + * \since prior to LTO_API_VERSION=3 + */ +extern lto_bool_t +lto_codegen_set_pic_model(lto_code_gen_t cg, lto_codegen_model); + +/** + * Sets the cpu to generate code for. + * + * \since LTO_API_VERSION=4 + */ +extern void +lto_codegen_set_cpu(lto_code_gen_t cg, const char *cpu); + +/** + * Sets the location of the assembler tool to run. If not set, libLTO + * will use gcc to invoke the assembler. + * + * \since LTO_API_VERSION=3 + */ +extern void +lto_codegen_set_assembler_path(lto_code_gen_t cg, const char* path); + +/** + * Sets extra arguments that libLTO should pass to the assembler. + * + * \since LTO_API_VERSION=4 + */ +extern void +lto_codegen_set_assembler_args(lto_code_gen_t cg, const char **args, + int nargs); + +/** + * Adds to a list of all global symbols that must exist in the final generated + * code. If a function is not listed there, it might be inlined into every usage + * and optimized away. + * + * \since prior to LTO_API_VERSION=3 + */ +extern void +lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg, const char* symbol); + +/** + * Writes a new object file at the specified path that contains the + * merged contents of all modules added so far. + * Returns true on error (check lto_get_error_message() for details). + * + * \since LTO_API_VERSION=5 + */ +extern lto_bool_t +lto_codegen_write_merged_modules(lto_code_gen_t cg, const char* path); + +/** + * Generates code for all added modules into one native object file. + * This calls lto_codegen_optimize then lto_codegen_compile_optimized. + * + * On success returns a pointer to a generated mach-o/ELF buffer and + * length set to the buffer size. The buffer is owned by the + * lto_code_gen_t and will be freed when lto_codegen_dispose() + * is called, or lto_codegen_compile() is called again. + * On failure, returns NULL (check lto_get_error_message() for details). + * + * \since prior to LTO_API_VERSION=3 + */ +extern const void* +lto_codegen_compile(lto_code_gen_t cg, size_t* length); + +/** + * Generates code for all added modules into one native object file. + * This calls lto_codegen_optimize then lto_codegen_compile_optimized (instead + * of returning a generated mach-o/ELF buffer, it writes to a file). + * + * The name of the file is written to name. Returns true on error. + * + * \since LTO_API_VERSION=5 + */ +extern lto_bool_t +lto_codegen_compile_to_file(lto_code_gen_t cg, const char** name); + +/** + * Runs optimization for the merged module. Returns true on error. + * + * \since LTO_API_VERSION=12 + */ +extern lto_bool_t +lto_codegen_optimize(lto_code_gen_t cg); + +/** + * Generates code for the optimized merged module into one native object file. + * It will not run any IR optimizations on the merged module. + * + * On success returns a pointer to a generated mach-o/ELF buffer and length set + * to the buffer size. The buffer is owned by the lto_code_gen_t and will be + * freed when lto_codegen_dispose() is called, or + * lto_codegen_compile_optimized() is called again. On failure, returns NULL + * (check lto_get_error_message() for details). + * + * \since LTO_API_VERSION=12 + */ +extern const void* +lto_codegen_compile_optimized(lto_code_gen_t cg, size_t* length); + +/** + * Returns the runtime API version. + * + * \since LTO_API_VERSION=12 + */ +extern unsigned int +lto_api_version(void); + +/** + * Sets options to help debug codegen bugs. + * + * This function takes one or more options separated by spaces. + * Warning: passing file paths through this function may confuse the argument + * parser if the paths contain spaces. + * + * \since prior to LTO_API_VERSION=3 + */ +extern void +lto_codegen_debug_options(lto_code_gen_t cg, const char *); + +/** + * Same as the previous function, but takes every option separately through an + * array. + * + * \since prior to LTO_API_VERSION=26 + */ +extern void lto_codegen_debug_options_array(lto_code_gen_t cg, + const char *const *, int number); + +/** + * Initializes LLVM disassemblers. + * FIXME: This doesn't really belong here. + * + * \since LTO_API_VERSION=5 + */ +extern void +lto_initialize_disassembler(void); + +/** + * Sets if we should run internalize pass during optimization and code + * generation. + * + * \since LTO_API_VERSION=14 + */ +extern void +lto_codegen_set_should_internalize(lto_code_gen_t cg, + lto_bool_t ShouldInternalize); + +/** + * Set whether to embed uselists in bitcode. + * + * Sets whether \a lto_codegen_write_merged_modules() should embed uselists in + * output bitcode. This should be turned on for all -save-temps output. + * + * \since LTO_API_VERSION=15 + */ +extern void +lto_codegen_set_should_embed_uselists(lto_code_gen_t cg, + lto_bool_t ShouldEmbedUselists); + +/** Opaque reference to an LTO input file */ +typedef struct LLVMOpaqueLTOInput *lto_input_t; + +/** + * Creates an LTO input file from a buffer. The path + * argument is used for diagnotics as this function + * otherwise does not know which file the given buffer + * is associated with. + * + * \since LTO_API_VERSION=24 + */ +extern lto_input_t lto_input_create(const void *buffer, + size_t buffer_size, + const char *path); + +/** + * Frees all memory internally allocated by the LTO input file. + * Upon return the lto_module_t is no longer valid. + * + * \since LTO_API_VERSION=24 + */ +extern void lto_input_dispose(lto_input_t input); + +/** + * Returns the number of dependent library specifiers + * for the given LTO input file. + * + * \since LTO_API_VERSION=24 + */ +extern unsigned lto_input_get_num_dependent_libraries(lto_input_t input); + +/** + * Returns the ith dependent library specifier + * for the given LTO input file. The returned + * string is not null-terminated. + * + * \since LTO_API_VERSION=24 + */ +extern const char * lto_input_get_dependent_library(lto_input_t input, + size_t index, + size_t *size); + +/** + * Returns the list of libcall symbols that can be generated by LTO + * that might not be visible from the symbol table of bitcode files. + * + * \since prior to LTO_API_VERSION=25 + */ +extern const char *const *lto_runtime_lib_symbols_list(size_t *size); + +/** + * @} // endgoup LLVMCLTO + * @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); + +/** + * 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=21 + */ +unsigned int thinlto_module_get_num_object_files(thinlto_code_gen_t cg); + +/** + * Returns the path to the ith object file produced by the ThinLTO + * CodeGenerator. + * + * Client should use \p thinlto_module_get_num_object_files() to get the number + * of available objects. + * + * \since LTO_API_VERSION=21 + */ +const char *thinlto_module_get_object_file(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); + +/** + * 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); + +/** + * Set the path to a directory where to save generated object files. This + * path can be used by a linker to request on-disk files instead of in-memory + * buffers. When set, results are available through + * thinlto_module_get_object_file() instead of thinlto_module_get_object(). + * + * \since LTO_API_VERSION=21 + */ +void thinlto_set_generated_objects_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); + +/** + * @} // endgoup LLVMCTLTO + * @defgroup LLVMCTLTO_CACHING ThinLTO Cache Control + * @ingroup LLVMCTLTO + * + * These entry points control the ThinLTO cache. The cache is intended to + * support incremental builds, and thus needs to be persistent across builds. + * The client enables 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 limits the frequency at which the garbage collector + * will try to scan the cache directory to prune expired entries. + * Setting to a negative number disables the pruning. + * - 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 until + * 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 disables the + * pruning. An unspecified default value will be applied, and a value of 0 will + * force prunning to occur. + * + * \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 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 maximum size of the cache directory (in bytes). A value over the + * amount of available space on the disk will be reduced to the amount of + * available space. An unspecified default value will be applied. A value of 0 + * will be ignored. + * + * \since LTO_API_VERSION=22 + */ +extern void thinlto_codegen_set_cache_size_bytes(thinlto_code_gen_t cg, + unsigned max_size_bytes); + +/** + * Same as thinlto_codegen_set_cache_size_bytes, except the maximum size is in + * megabytes (2^20 bytes). + * + * \since LTO_API_VERSION=23 + */ +extern void +thinlto_codegen_set_cache_size_megabytes(thinlto_code_gen_t cg, + unsigned max_size_megabytes); + +/** + * Sets the maximum number of files in the cache directory. An unspecified + * default value will be applied. A value of 0 will be ignored. + * + * \since LTO_API_VERSION=22 + */ +extern void thinlto_codegen_set_cache_size_files(thinlto_code_gen_t cg, + unsigned max_size_files); + +/** + * @} // endgroup LLVMCTLTO_CACHING + */ + +LLVM_C_EXTERN_C_END + +#endif /* LLVM_C_LTO_H */
diff --git a/third_party/llvm-10.0/llvm/include/llvm-c/module.modulemap b/third_party/llvm-10.0/llvm/include/llvm-c/module.modulemap new file mode 100644 index 0000000..a456119 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm-c/module.modulemap
@@ -0,0 +1,4 @@ +module LLVM_C { + umbrella "." + module * { export * } +}
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/APFloat.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/APFloat.h new file mode 100644 index 0000000..ed25b2c --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/APFloat.h
@@ -0,0 +1,1295 @@ +//===- llvm/ADT/APFloat.h - Arbitrary Precision Floating Point ---*- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief +/// This file declares a class to represent arbitrary precision floating point +/// values and provide a variety of arithmetic operations on them. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_APFLOAT_H +#define LLVM_ADT_APFLOAT_H + +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/ErrorHandling.h" +#include <memory> + +#define APFLOAT_DISPATCH_ON_SEMANTICS(METHOD_CALL) \ + do { \ + if (usesLayout<IEEEFloat>(getSemantics())) \ + return U.IEEE.METHOD_CALL; \ + if (usesLayout<DoubleAPFloat>(getSemantics())) \ + return U.Double.METHOD_CALL; \ + llvm_unreachable("Unexpected semantics"); \ + } while (false) + +namespace llvm { + +struct fltSemantics; +class APSInt; +class StringRef; +class APFloat; +class raw_ostream; + +template <typename T> class Expected; +template <typename T> class SmallVectorImpl; + +/// Enum that represents what fraction of the LSB truncated bits of an fp number +/// represent. +/// +/// This essentially combines the roles of guard and sticky bits. +enum lostFraction { // Example of truncated bits: + lfExactlyZero, // 000000 + lfLessThanHalf, // 0xxxxx x's not all zero + lfExactlyHalf, // 100000 + lfMoreThanHalf // 1xxxxx x's not all zero +}; + +/// A self-contained host- and target-independent arbitrary-precision +/// floating-point software implementation. +/// +/// APFloat uses bignum integer arithmetic as provided by static functions in +/// the APInt class. The library will work with bignum integers whose parts are +/// any unsigned type at least 16 bits wide, but 64 bits is recommended. +/// +/// Written for clarity rather than speed, in particular with a view to use in +/// the front-end of a cross compiler so that target arithmetic can be correctly +/// performed on the host. Performance should nonetheless be reasonable, +/// particularly for its intended use. It may be useful as a base +/// implementation for a run-time library during development of a faster +/// target-specific one. +/// +/// All 5 rounding modes in the IEEE-754R draft are handled correctly for all +/// implemented operations. Currently implemented operations are add, subtract, +/// multiply, divide, fused-multiply-add, conversion-to-float, +/// conversion-to-integer and conversion-from-integer. New rounding modes +/// (e.g. away from zero) can be added with three or four lines of code. +/// +/// Four formats are built-in: IEEE single precision, double precision, +/// quadruple precision, and x87 80-bit extended double (when operating with +/// full extended precision). Adding a new format that obeys IEEE semantics +/// only requires adding two lines of code: a declaration and definition of the +/// format. +/// +/// All operations return the status of that operation as an exception bit-mask, +/// so multiple operations can be done consecutively with their results or-ed +/// together. The returned status can be useful for compiler diagnostics; e.g., +/// inexact, underflow and overflow can be easily diagnosed on constant folding, +/// and compiler optimizers can determine what exceptions would be raised by +/// folding operations and optimize, or perhaps not optimize, accordingly. +/// +/// At present, underflow tininess is detected after rounding; it should be +/// straight forward to add support for the before-rounding case too. +/// +/// The library reads hexadecimal floating point numbers as per C99, and +/// correctly rounds if necessary according to the specified rounding mode. +/// Syntax is required to have been validated by the caller. It also converts +/// floating point numbers to hexadecimal text as per the C99 %a and %A +/// conversions. The output precision (or alternatively the natural minimal +/// precision) can be specified; if the requested precision is less than the +/// natural precision the output is correctly rounded for the specified rounding +/// mode. +/// +/// It also reads decimal floating point numbers and correctly rounds according +/// to the specified rounding mode. +/// +/// Conversion to decimal text is not currently implemented. +/// +/// Non-zero finite numbers are represented internally as a sign bit, a 16-bit +/// signed exponent, and the significand as an array of integer parts. After +/// normalization of a number of precision P the exponent is within the range of +/// the format, and if the number is not denormal the P-th bit of the +/// significand is set as an explicit integer bit. For denormals the most +/// significant bit is shifted right so that the exponent is maintained at the +/// format's minimum, so that the smallest denormal has just the least +/// significant bit of the significand set. The sign of zeroes and infinities +/// is significant; the exponent and significand of such numbers is not stored, +/// but has a known implicit (deterministic) value: 0 for the significands, 0 +/// for zero exponent, all 1 bits for infinity exponent. For NaNs the sign and +/// significand are deterministic, although not really meaningful, and preserved +/// in non-conversion operations. The exponent is implicitly all 1 bits. +/// +/// APFloat does not provide any exception handling beyond default exception +/// handling. We represent Signaling NaNs via IEEE-754R 2008 6.2.1 should clause +/// by encoding Signaling NaNs with the first bit of its trailing significand as +/// 0. +/// +/// TODO +/// ==== +/// +/// Some features that may or may not be worth adding: +/// +/// Binary to decimal conversion (hard). +/// +/// Optional ability to detect underflow tininess before rounding. +/// +/// New formats: x87 in single and double precision mode (IEEE apart from +/// extended exponent range) (hard). +/// +/// New operations: sqrt, IEEE remainder, C90 fmod, nexttoward. +/// + +// This is the common type definitions shared by APFloat and its internal +// implementation classes. This struct should not define any non-static data +// members. +struct APFloatBase { + typedef APInt::WordType integerPart; + static const unsigned integerPartWidth = APInt::APINT_BITS_PER_WORD; + + /// A signed type to represent a floating point numbers unbiased exponent. + typedef int32_t ExponentType; + + /// \name Floating Point Semantics. + /// @{ + enum Semantics { + S_IEEEhalf, + S_IEEEsingle, + S_IEEEdouble, + S_x87DoubleExtended, + S_IEEEquad, + S_PPCDoubleDouble + }; + + static const llvm::fltSemantics &EnumToSemantics(Semantics S); + static Semantics SemanticsToEnum(const llvm::fltSemantics &Sem); + + static const fltSemantics &IEEEhalf() LLVM_READNONE; + static const fltSemantics &IEEEsingle() LLVM_READNONE; + static const fltSemantics &IEEEdouble() LLVM_READNONE; + static const fltSemantics &IEEEquad() LLVM_READNONE; + static const fltSemantics &PPCDoubleDouble() LLVM_READNONE; + static const fltSemantics &x87DoubleExtended() LLVM_READNONE; + + /// A Pseudo fltsemantic used to construct APFloats that cannot conflict with + /// anything real. + static const fltSemantics &Bogus() LLVM_READNONE; + + /// @} + + /// IEEE-754R 5.11: Floating Point Comparison Relations. + enum cmpResult { + cmpLessThan, + cmpEqual, + cmpGreaterThan, + cmpUnordered + }; + + /// IEEE-754R 4.3: Rounding-direction attributes. + enum roundingMode { + rmNearestTiesToEven, + rmTowardPositive, + rmTowardNegative, + rmTowardZero, + rmNearestTiesToAway + }; + + /// IEEE-754R 7: Default exception handling. + /// + /// opUnderflow or opOverflow are always returned or-ed with opInexact. + /// + /// APFloat models this behavior specified by IEEE-754: + /// "For operations producing results in floating-point format, the default + /// result of an operation that signals the invalid operation exception + /// shall be a quiet NaN." + enum opStatus { + opOK = 0x00, + opInvalidOp = 0x01, + opDivByZero = 0x02, + opOverflow = 0x04, + opUnderflow = 0x08, + opInexact = 0x10 + }; + + /// Category of internally-represented number. + enum fltCategory { + fcInfinity, + fcNaN, + fcNormal, + fcZero + }; + + /// Convenience enum used to construct an uninitialized APFloat. + enum uninitializedTag { + uninitialized + }; + + /// Enumeration of \c ilogb error results. + enum IlogbErrorKinds { + IEK_Zero = INT_MIN + 1, + IEK_NaN = INT_MIN, + IEK_Inf = INT_MAX + }; + + static unsigned int semanticsPrecision(const fltSemantics &); + static ExponentType semanticsMinExponent(const fltSemantics &); + static ExponentType semanticsMaxExponent(const fltSemantics &); + static unsigned int semanticsSizeInBits(const fltSemantics &); + + /// Returns the size of the floating point number (in bits) in the given + /// semantics. + static unsigned getSizeInBits(const fltSemantics &Sem); +}; + +namespace detail { + +class IEEEFloat final : public APFloatBase { +public: + /// \name Constructors + /// @{ + + IEEEFloat(const fltSemantics &); // Default construct to 0.0 + IEEEFloat(const fltSemantics &, integerPart); + IEEEFloat(const fltSemantics &, uninitializedTag); + IEEEFloat(const fltSemantics &, const APInt &); + explicit IEEEFloat(double d); + explicit IEEEFloat(float f); + IEEEFloat(const IEEEFloat &); + IEEEFloat(IEEEFloat &&); + ~IEEEFloat(); + + /// @} + + /// Returns whether this instance allocated memory. + bool needsCleanup() const { return partCount() > 1; } + + /// \name Convenience "constructors" + /// @{ + + /// @} + + /// \name Arithmetic + /// @{ + + opStatus add(const IEEEFloat &, roundingMode); + opStatus subtract(const IEEEFloat &, roundingMode); + opStatus multiply(const IEEEFloat &, roundingMode); + opStatus divide(const IEEEFloat &, roundingMode); + /// IEEE remainder. + opStatus remainder(const IEEEFloat &); + /// C fmod, or llvm frem. + opStatus mod(const IEEEFloat &); + opStatus fusedMultiplyAdd(const IEEEFloat &, const IEEEFloat &, roundingMode); + opStatus roundToIntegral(roundingMode); + /// IEEE-754R 5.3.1: nextUp/nextDown. + opStatus next(bool nextDown); + + /// @} + + /// \name Sign operations. + /// @{ + + void changeSign(); + + /// @} + + /// \name Conversions + /// @{ + + opStatus convert(const fltSemantics &, roundingMode, bool *); + opStatus convertToInteger(MutableArrayRef<integerPart>, unsigned int, bool, + roundingMode, bool *) const; + opStatus convertFromAPInt(const APInt &, bool, roundingMode); + opStatus convertFromSignExtendedInteger(const integerPart *, unsigned int, + bool, roundingMode); + opStatus convertFromZeroExtendedInteger(const integerPart *, unsigned int, + bool, roundingMode); + Expected<opStatus> convertFromString(StringRef, roundingMode); + APInt bitcastToAPInt() const; + double convertToDouble() const; + float convertToFloat() const; + + /// @} + + /// The definition of equality is not straightforward for floating point, so + /// we won't use operator==. Use one of the following, or write whatever it + /// is you really mean. + bool operator==(const IEEEFloat &) const = delete; + + /// IEEE comparison with another floating point number (NaNs compare + /// unordered, 0==-0). + cmpResult compare(const IEEEFloat &) const; + + /// Bitwise comparison for equality (QNaNs compare equal, 0!=-0). + bool bitwiseIsEqual(const IEEEFloat &) const; + + /// Write out a hexadecimal representation of the floating point value to DST, + /// which must be of sufficient size, in the C99 form [-]0xh.hhhhp[+-]d. + /// Return the number of characters written, excluding the terminating NUL. + unsigned int convertToHexString(char *dst, unsigned int hexDigits, + bool upperCase, roundingMode) const; + + /// \name IEEE-754R 5.7.2 General operations. + /// @{ + + /// IEEE-754R isSignMinus: Returns true if and only if the current value is + /// negative. + /// + /// This applies to zeros and NaNs as well. + bool isNegative() const { return sign; } + + /// IEEE-754R isNormal: Returns true if and only if the current value is normal. + /// + /// This implies that the current value of the float is not zero, subnormal, + /// infinite, or NaN following the definition of normality from IEEE-754R. + bool isNormal() const { return !isDenormal() && isFiniteNonZero(); } + + /// Returns true if and only if the current value is zero, subnormal, or + /// normal. + /// + /// This means that the value is not infinite or NaN. + bool isFinite() const { return !isNaN() && !isInfinity(); } + + /// Returns true if and only if the float is plus or minus zero. + bool isZero() const { return category == fcZero; } + + /// IEEE-754R isSubnormal(): Returns true if and only if the float is a + /// denormal. + bool isDenormal() const; + + /// IEEE-754R isInfinite(): Returns true if and only if the float is infinity. + bool isInfinity() const { return category == fcInfinity; } + + /// Returns true if and only if the float is a quiet or signaling NaN. + bool isNaN() const { return category == fcNaN; } + + /// Returns true if and only if the float is a signaling NaN. + bool isSignaling() const; + + /// @} + + /// \name Simple Queries + /// @{ + + fltCategory getCategory() const { return category; } + const fltSemantics &getSemantics() const { return *semantics; } + bool isNonZero() const { return category != fcZero; } + bool isFiniteNonZero() const { return isFinite() && !isZero(); } + bool isPosZero() const { return isZero() && !isNegative(); } + bool isNegZero() const { return isZero() && isNegative(); } + + /// Returns true if and only if the number has the smallest possible non-zero + /// magnitude in the current semantics. + bool isSmallest() const; + + /// Returns true if and only if the number has the largest possible finite + /// magnitude in the current semantics. + bool isLargest() const; + + /// Returns true if and only if the number is an exact integer. + bool isInteger() const; + + /// @} + + IEEEFloat &operator=(const IEEEFloat &); + IEEEFloat &operator=(IEEEFloat &&); + + /// Overload to compute a hash code for an APFloat value. + /// + /// Note that the use of hash codes for floating point values is in general + /// frought with peril. Equality is hard to define for these values. For + /// example, should negative and positive zero hash to different codes? Are + /// they equal or not? This hash value implementation specifically + /// emphasizes producing different codes for different inputs in order to + /// be used in canonicalization and memoization. As such, equality is + /// bitwiseIsEqual, and 0 != -0. + friend hash_code hash_value(const IEEEFloat &Arg); + + /// Converts this value into a decimal string. + /// + /// \param FormatPrecision The maximum number of digits of + /// precision to output. If there are fewer digits available, + /// zero padding will not be used unless the value is + /// integral and small enough to be expressed in + /// FormatPrecision digits. 0 means to use the natural + /// precision of the number. + /// \param FormatMaxPadding The maximum number of zeros to + /// consider inserting before falling back to scientific + /// notation. 0 means to always use scientific notation. + /// + /// \param TruncateZero Indicate whether to remove the trailing zero in + /// fraction part or not. Also setting this parameter to false forcing + /// producing of output more similar to default printf behavior. + /// Specifically the lower e is used as exponent delimiter and exponent + /// always contains no less than two digits. + /// + /// Number Precision MaxPadding Result + /// ------ --------- ---------- ------ + /// 1.01E+4 5 2 10100 + /// 1.01E+4 4 2 1.01E+4 + /// 1.01E+4 5 1 1.01E+4 + /// 1.01E-2 5 2 0.0101 + /// 1.01E-2 4 2 0.0101 + /// 1.01E-2 4 1 1.01E-2 + void toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision = 0, + unsigned FormatMaxPadding = 3, bool TruncateZero = true) const; + + /// If this value has an exact multiplicative inverse, store it in inv and + /// return true. + bool getExactInverse(APFloat *inv) const; + + /// Returns the exponent of the internal representation of the APFloat. + /// + /// Because the radix of APFloat is 2, this is equivalent to floor(log2(x)). + /// For special APFloat values, this returns special error codes: + /// + /// NaN -> \c IEK_NaN + /// 0 -> \c IEK_Zero + /// Inf -> \c IEK_Inf + /// + friend int ilogb(const IEEEFloat &Arg); + + /// Returns: X * 2^Exp for integral exponents. + friend IEEEFloat scalbn(IEEEFloat X, int Exp, roundingMode); + + friend IEEEFloat frexp(const IEEEFloat &X, int &Exp, roundingMode); + + /// \name Special value setters. + /// @{ + + void makeLargest(bool Neg = false); + void makeSmallest(bool Neg = false); + void makeNaN(bool SNaN = false, bool Neg = false, + const APInt *fill = nullptr); + void makeInf(bool Neg = false); + void makeZero(bool Neg = false); + void makeQuiet(); + + /// Returns the smallest (by magnitude) normalized finite number in the given + /// semantics. + /// + /// \param Negative - True iff the number should be negative + void makeSmallestNormalized(bool Negative = false); + + /// @} + + cmpResult compareAbsoluteValue(const IEEEFloat &) const; + +private: + /// \name Simple Queries + /// @{ + + integerPart *significandParts(); + const integerPart *significandParts() const; + unsigned int partCount() const; + + /// @} + + /// \name Significand operations. + /// @{ + + integerPart addSignificand(const IEEEFloat &); + integerPart subtractSignificand(const IEEEFloat &, integerPart); + lostFraction addOrSubtractSignificand(const IEEEFloat &, bool subtract); + lostFraction multiplySignificand(const IEEEFloat &, IEEEFloat); + lostFraction multiplySignificand(const IEEEFloat&); + lostFraction divideSignificand(const IEEEFloat &); + void incrementSignificand(); + void initialize(const fltSemantics *); + void shiftSignificandLeft(unsigned int); + lostFraction shiftSignificandRight(unsigned int); + unsigned int significandLSB() const; + unsigned int significandMSB() const; + void zeroSignificand(); + /// Return true if the significand excluding the integral bit is all ones. + bool isSignificandAllOnes() const; + /// Return true if the significand excluding the integral bit is all zeros. + bool isSignificandAllZeros() const; + + /// @} + + /// \name Arithmetic on special values. + /// @{ + + opStatus addOrSubtractSpecials(const IEEEFloat &, bool subtract); + opStatus divideSpecials(const IEEEFloat &); + opStatus multiplySpecials(const IEEEFloat &); + opStatus modSpecials(const IEEEFloat &); + + /// @} + + /// \name Miscellany + /// @{ + + bool convertFromStringSpecials(StringRef str); + opStatus normalize(roundingMode, lostFraction); + opStatus addOrSubtract(const IEEEFloat &, roundingMode, bool subtract); + opStatus handleOverflow(roundingMode); + bool roundAwayFromZero(roundingMode, lostFraction, unsigned int) const; + opStatus convertToSignExtendedInteger(MutableArrayRef<integerPart>, + unsigned int, bool, roundingMode, + bool *) const; + opStatus convertFromUnsignedParts(const integerPart *, unsigned int, + roundingMode); + Expected<opStatus> convertFromHexadecimalString(StringRef, roundingMode); + Expected<opStatus> convertFromDecimalString(StringRef, roundingMode); + char *convertNormalToHexString(char *, unsigned int, bool, + roundingMode) const; + opStatus roundSignificandWithExponent(const integerPart *, unsigned int, int, + roundingMode); + + /// @} + + APInt convertHalfAPFloatToAPInt() const; + APInt convertFloatAPFloatToAPInt() const; + APInt convertDoubleAPFloatToAPInt() const; + APInt convertQuadrupleAPFloatToAPInt() const; + APInt convertF80LongDoubleAPFloatToAPInt() const; + APInt convertPPCDoubleDoubleAPFloatToAPInt() const; + void initFromAPInt(const fltSemantics *Sem, const APInt &api); + void initFromHalfAPInt(const APInt &api); + void initFromFloatAPInt(const APInt &api); + void initFromDoubleAPInt(const APInt &api); + void initFromQuadrupleAPInt(const APInt &api); + void initFromF80LongDoubleAPInt(const APInt &api); + void initFromPPCDoubleDoubleAPInt(const APInt &api); + + void assign(const IEEEFloat &); + void copySignificand(const IEEEFloat &); + void freeSignificand(); + + /// Note: this must be the first data member. + /// The semantics that this value obeys. + const fltSemantics *semantics; + + /// A binary fraction with an explicit integer bit. + /// + /// The significand must be at least one bit wider than the target precision. + union Significand { + integerPart part; + integerPart *parts; + } significand; + + /// The signed unbiased exponent of the value. + ExponentType exponent; + + /// What kind of floating point number this is. + /// + /// Only 2 bits are required, but VisualStudio incorrectly sign extends it. + /// Using the extra bit keeps it from failing under VisualStudio. + fltCategory category : 3; + + /// Sign bit of the number. + unsigned int sign : 1; +}; + +hash_code hash_value(const IEEEFloat &Arg); +int ilogb(const IEEEFloat &Arg); +IEEEFloat scalbn(IEEEFloat X, int Exp, IEEEFloat::roundingMode); +IEEEFloat frexp(const IEEEFloat &Val, int &Exp, IEEEFloat::roundingMode RM); + +// This mode implements more precise float in terms of two APFloats. +// The interface and layout is designed for arbitray underlying semantics, +// though currently only PPCDoubleDouble semantics are supported, whose +// corresponding underlying semantics are IEEEdouble. +class DoubleAPFloat final : public APFloatBase { + // Note: this must be the first data member. + const fltSemantics *Semantics; + std::unique_ptr<APFloat[]> Floats; + + opStatus addImpl(const APFloat &a, const APFloat &aa, const APFloat &c, + const APFloat &cc, roundingMode RM); + + opStatus addWithSpecial(const DoubleAPFloat &LHS, const DoubleAPFloat &RHS, + DoubleAPFloat &Out, roundingMode RM); + +public: + DoubleAPFloat(const fltSemantics &S); + DoubleAPFloat(const fltSemantics &S, uninitializedTag); + DoubleAPFloat(const fltSemantics &S, integerPart); + DoubleAPFloat(const fltSemantics &S, const APInt &I); + DoubleAPFloat(const fltSemantics &S, APFloat &&First, APFloat &&Second); + DoubleAPFloat(const DoubleAPFloat &RHS); + DoubleAPFloat(DoubleAPFloat &&RHS); + + DoubleAPFloat &operator=(const DoubleAPFloat &RHS); + + DoubleAPFloat &operator=(DoubleAPFloat &&RHS) { + if (this != &RHS) { + this->~DoubleAPFloat(); + new (this) DoubleAPFloat(std::move(RHS)); + } + return *this; + } + + bool needsCleanup() const { return Floats != nullptr; } + + APFloat &getFirst() { return Floats[0]; } + const APFloat &getFirst() const { return Floats[0]; } + APFloat &getSecond() { return Floats[1]; } + const APFloat &getSecond() const { return Floats[1]; } + + opStatus add(const DoubleAPFloat &RHS, roundingMode RM); + opStatus subtract(const DoubleAPFloat &RHS, roundingMode RM); + opStatus multiply(const DoubleAPFloat &RHS, roundingMode RM); + opStatus divide(const DoubleAPFloat &RHS, roundingMode RM); + opStatus remainder(const DoubleAPFloat &RHS); + opStatus mod(const DoubleAPFloat &RHS); + opStatus fusedMultiplyAdd(const DoubleAPFloat &Multiplicand, + const DoubleAPFloat &Addend, roundingMode RM); + opStatus roundToIntegral(roundingMode RM); + void changeSign(); + cmpResult compareAbsoluteValue(const DoubleAPFloat &RHS) const; + + fltCategory getCategory() const; + bool isNegative() const; + + void makeInf(bool Neg); + void makeZero(bool Neg); + void makeLargest(bool Neg); + void makeSmallest(bool Neg); + void makeSmallestNormalized(bool Neg); + void makeNaN(bool SNaN, bool Neg, const APInt *fill); + + cmpResult compare(const DoubleAPFloat &RHS) const; + bool bitwiseIsEqual(const DoubleAPFloat &RHS) const; + APInt bitcastToAPInt() const; + Expected<opStatus> convertFromString(StringRef, roundingMode); + opStatus next(bool nextDown); + + opStatus convertToInteger(MutableArrayRef<integerPart> Input, + unsigned int Width, bool IsSigned, roundingMode RM, + bool *IsExact) const; + opStatus convertFromAPInt(const APInt &Input, bool IsSigned, roundingMode RM); + opStatus convertFromSignExtendedInteger(const integerPart *Input, + unsigned int InputSize, bool IsSigned, + roundingMode RM); + opStatus convertFromZeroExtendedInteger(const integerPart *Input, + unsigned int InputSize, bool IsSigned, + roundingMode RM); + unsigned int convertToHexString(char *DST, unsigned int HexDigits, + bool UpperCase, roundingMode RM) const; + + bool isDenormal() const; + bool isSmallest() const; + bool isLargest() const; + bool isInteger() const; + + void toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision, + unsigned FormatMaxPadding, bool TruncateZero = true) const; + + bool getExactInverse(APFloat *inv) const; + + friend int ilogb(const DoubleAPFloat &Arg); + friend DoubleAPFloat scalbn(DoubleAPFloat X, int Exp, roundingMode); + friend DoubleAPFloat frexp(const DoubleAPFloat &X, int &Exp, roundingMode); + friend hash_code hash_value(const DoubleAPFloat &Arg); +}; + +hash_code hash_value(const DoubleAPFloat &Arg); + +} // End detail namespace + +// This is a interface class that is currently forwarding functionalities from +// detail::IEEEFloat. +class APFloat : public APFloatBase { + typedef detail::IEEEFloat IEEEFloat; + typedef detail::DoubleAPFloat DoubleAPFloat; + + static_assert(std::is_standard_layout<IEEEFloat>::value, ""); + + union Storage { + const fltSemantics *semantics; + IEEEFloat IEEE; + DoubleAPFloat Double; + + explicit Storage(IEEEFloat F, const fltSemantics &S); + explicit Storage(DoubleAPFloat F, const fltSemantics &S) + : Double(std::move(F)) { + assert(&S == &PPCDoubleDouble()); + } + + template <typename... ArgTypes> + Storage(const fltSemantics &Semantics, ArgTypes &&... Args) { + if (usesLayout<IEEEFloat>(Semantics)) { + new (&IEEE) IEEEFloat(Semantics, std::forward<ArgTypes>(Args)...); + return; + } + if (usesLayout<DoubleAPFloat>(Semantics)) { + new (&Double) DoubleAPFloat(Semantics, std::forward<ArgTypes>(Args)...); + return; + } + llvm_unreachable("Unexpected semantics"); + } + + ~Storage() { + if (usesLayout<IEEEFloat>(*semantics)) { + IEEE.~IEEEFloat(); + return; + } + if (usesLayout<DoubleAPFloat>(*semantics)) { + Double.~DoubleAPFloat(); + return; + } + llvm_unreachable("Unexpected semantics"); + } + + Storage(const Storage &RHS) { + if (usesLayout<IEEEFloat>(*RHS.semantics)) { + new (this) IEEEFloat(RHS.IEEE); + return; + } + if (usesLayout<DoubleAPFloat>(*RHS.semantics)) { + new (this) DoubleAPFloat(RHS.Double); + return; + } + llvm_unreachable("Unexpected semantics"); + } + + Storage(Storage &&RHS) { + if (usesLayout<IEEEFloat>(*RHS.semantics)) { + new (this) IEEEFloat(std::move(RHS.IEEE)); + return; + } + if (usesLayout<DoubleAPFloat>(*RHS.semantics)) { + new (this) DoubleAPFloat(std::move(RHS.Double)); + return; + } + llvm_unreachable("Unexpected semantics"); + } + + Storage &operator=(const Storage &RHS) { + if (usesLayout<IEEEFloat>(*semantics) && + usesLayout<IEEEFloat>(*RHS.semantics)) { + IEEE = RHS.IEEE; + } else if (usesLayout<DoubleAPFloat>(*semantics) && + usesLayout<DoubleAPFloat>(*RHS.semantics)) { + Double = RHS.Double; + } else if (this != &RHS) { + this->~Storage(); + new (this) Storage(RHS); + } + return *this; + } + + Storage &operator=(Storage &&RHS) { + if (usesLayout<IEEEFloat>(*semantics) && + usesLayout<IEEEFloat>(*RHS.semantics)) { + IEEE = std::move(RHS.IEEE); + } else if (usesLayout<DoubleAPFloat>(*semantics) && + usesLayout<DoubleAPFloat>(*RHS.semantics)) { + Double = std::move(RHS.Double); + } else if (this != &RHS) { + this->~Storage(); + new (this) Storage(std::move(RHS)); + } + return *this; + } + } U; + + template <typename T> static bool usesLayout(const fltSemantics &Semantics) { + static_assert(std::is_same<T, IEEEFloat>::value || + std::is_same<T, DoubleAPFloat>::value, ""); + if (std::is_same<T, DoubleAPFloat>::value) { + return &Semantics == &PPCDoubleDouble(); + } + return &Semantics != &PPCDoubleDouble(); + } + + IEEEFloat &getIEEE() { + if (usesLayout<IEEEFloat>(*U.semantics)) + return U.IEEE; + if (usesLayout<DoubleAPFloat>(*U.semantics)) + return U.Double.getFirst().U.IEEE; + llvm_unreachable("Unexpected semantics"); + } + + const IEEEFloat &getIEEE() const { + if (usesLayout<IEEEFloat>(*U.semantics)) + return U.IEEE; + if (usesLayout<DoubleAPFloat>(*U.semantics)) + return U.Double.getFirst().U.IEEE; + llvm_unreachable("Unexpected semantics"); + } + + void makeZero(bool Neg) { APFLOAT_DISPATCH_ON_SEMANTICS(makeZero(Neg)); } + + void makeInf(bool Neg) { APFLOAT_DISPATCH_ON_SEMANTICS(makeInf(Neg)); } + + void makeNaN(bool SNaN, bool Neg, const APInt *fill) { + APFLOAT_DISPATCH_ON_SEMANTICS(makeNaN(SNaN, Neg, fill)); + } + + void makeLargest(bool Neg) { + APFLOAT_DISPATCH_ON_SEMANTICS(makeLargest(Neg)); + } + + void makeSmallest(bool Neg) { + APFLOAT_DISPATCH_ON_SEMANTICS(makeSmallest(Neg)); + } + + void makeSmallestNormalized(bool Neg) { + APFLOAT_DISPATCH_ON_SEMANTICS(makeSmallestNormalized(Neg)); + } + + // FIXME: This is due to clang 3.3 (or older version) always checks for the + // default constructor in an array aggregate initialization, even if no + // elements in the array is default initialized. + APFloat() : U(IEEEdouble()) { + llvm_unreachable("This is a workaround for old clang."); + } + + explicit APFloat(IEEEFloat F, const fltSemantics &S) : U(std::move(F), S) {} + explicit APFloat(DoubleAPFloat F, const fltSemantics &S) + : U(std::move(F), S) {} + + cmpResult compareAbsoluteValue(const APFloat &RHS) const { + assert(&getSemantics() == &RHS.getSemantics() && + "Should only compare APFloats with the same semantics"); + if (usesLayout<IEEEFloat>(getSemantics())) + return U.IEEE.compareAbsoluteValue(RHS.U.IEEE); + if (usesLayout<DoubleAPFloat>(getSemantics())) + return U.Double.compareAbsoluteValue(RHS.U.Double); + llvm_unreachable("Unexpected semantics"); + } + +public: + APFloat(const fltSemantics &Semantics) : U(Semantics) {} + APFloat(const fltSemantics &Semantics, StringRef S); + APFloat(const fltSemantics &Semantics, integerPart I) : U(Semantics, I) {} + template <typename T, typename = typename std::enable_if< + std::is_floating_point<T>::value>::type> + APFloat(const fltSemantics &Semantics, T V) = delete; + // TODO: Remove this constructor. This isn't faster than the first one. + APFloat(const fltSemantics &Semantics, uninitializedTag) + : U(Semantics, uninitialized) {} + APFloat(const fltSemantics &Semantics, const APInt &I) : U(Semantics, I) {} + explicit APFloat(double d) : U(IEEEFloat(d), IEEEdouble()) {} + explicit APFloat(float f) : U(IEEEFloat(f), IEEEsingle()) {} + APFloat(const APFloat &RHS) = default; + APFloat(APFloat &&RHS) = default; + + ~APFloat() = default; + + bool needsCleanup() const { APFLOAT_DISPATCH_ON_SEMANTICS(needsCleanup()); } + + /// Factory for Positive and Negative Zero. + /// + /// \param Negative True iff the number should be negative. + static APFloat getZero(const fltSemantics &Sem, bool Negative = false) { + APFloat Val(Sem, uninitialized); + Val.makeZero(Negative); + return Val; + } + + /// Factory for Positive and Negative Infinity. + /// + /// \param Negative True iff the number should be negative. + static APFloat getInf(const fltSemantics &Sem, bool Negative = false) { + APFloat Val(Sem, uninitialized); + Val.makeInf(Negative); + return Val; + } + + /// Factory for NaN values. + /// + /// \param Negative - True iff the NaN generated should be negative. + /// \param payload - The unspecified fill bits for creating the NaN, 0 by + /// default. The value is truncated as necessary. + static APFloat getNaN(const fltSemantics &Sem, bool Negative = false, + uint64_t payload = 0) { + if (payload) { + APInt intPayload(64, payload); + return getQNaN(Sem, Negative, &intPayload); + } else { + return getQNaN(Sem, Negative, nullptr); + } + } + + /// Factory for QNaN values. + static APFloat getQNaN(const fltSemantics &Sem, bool Negative = false, + const APInt *payload = nullptr) { + APFloat Val(Sem, uninitialized); + Val.makeNaN(false, Negative, payload); + return Val; + } + + /// Factory for SNaN values. + static APFloat getSNaN(const fltSemantics &Sem, bool Negative = false, + const APInt *payload = nullptr) { + APFloat Val(Sem, uninitialized); + Val.makeNaN(true, Negative, payload); + return Val; + } + + /// Returns the largest finite number in the given semantics. + /// + /// \param Negative - True iff the number should be negative + static APFloat getLargest(const fltSemantics &Sem, bool Negative = false) { + APFloat Val(Sem, uninitialized); + Val.makeLargest(Negative); + return Val; + } + + /// Returns the smallest (by magnitude) finite number in the given semantics. + /// Might be denormalized, which implies a relative loss of precision. + /// + /// \param Negative - True iff the number should be negative + static APFloat getSmallest(const fltSemantics &Sem, bool Negative = false) { + APFloat Val(Sem, uninitialized); + Val.makeSmallest(Negative); + return Val; + } + + /// Returns the smallest (by magnitude) normalized finite number in the given + /// semantics. + /// + /// \param Negative - True iff the number should be negative + static APFloat getSmallestNormalized(const fltSemantics &Sem, + bool Negative = false) { + APFloat Val(Sem, uninitialized); + Val.makeSmallestNormalized(Negative); + return Val; + } + + /// Returns a float which is bitcasted from an all one value int. + /// + /// \param BitWidth - Select float type + /// \param isIEEE - If 128 bit number, select between PPC and IEEE + static APFloat getAllOnesValue(unsigned BitWidth, bool isIEEE = false); + + /// Used to insert APFloat objects, or objects that contain APFloat objects, + /// into FoldingSets. + void Profile(FoldingSetNodeID &NID) const; + + opStatus add(const APFloat &RHS, roundingMode RM) { + assert(&getSemantics() == &RHS.getSemantics() && + "Should only call on two APFloats with the same semantics"); + if (usesLayout<IEEEFloat>(getSemantics())) + return U.IEEE.add(RHS.U.IEEE, RM); + if (usesLayout<DoubleAPFloat>(getSemantics())) + return U.Double.add(RHS.U.Double, RM); + llvm_unreachable("Unexpected semantics"); + } + opStatus subtract(const APFloat &RHS, roundingMode RM) { + assert(&getSemantics() == &RHS.getSemantics() && + "Should only call on two APFloats with the same semantics"); + if (usesLayout<IEEEFloat>(getSemantics())) + return U.IEEE.subtract(RHS.U.IEEE, RM); + if (usesLayout<DoubleAPFloat>(getSemantics())) + return U.Double.subtract(RHS.U.Double, RM); + llvm_unreachable("Unexpected semantics"); + } + opStatus multiply(const APFloat &RHS, roundingMode RM) { + assert(&getSemantics() == &RHS.getSemantics() && + "Should only call on two APFloats with the same semantics"); + if (usesLayout<IEEEFloat>(getSemantics())) + return U.IEEE.multiply(RHS.U.IEEE, RM); + if (usesLayout<DoubleAPFloat>(getSemantics())) + return U.Double.multiply(RHS.U.Double, RM); + llvm_unreachable("Unexpected semantics"); + } + opStatus divide(const APFloat &RHS, roundingMode RM) { + assert(&getSemantics() == &RHS.getSemantics() && + "Should only call on two APFloats with the same semantics"); + if (usesLayout<IEEEFloat>(getSemantics())) + return U.IEEE.divide(RHS.U.IEEE, RM); + if (usesLayout<DoubleAPFloat>(getSemantics())) + return U.Double.divide(RHS.U.Double, RM); + llvm_unreachable("Unexpected semantics"); + } + opStatus remainder(const APFloat &RHS) { + assert(&getSemantics() == &RHS.getSemantics() && + "Should only call on two APFloats with the same semantics"); + if (usesLayout<IEEEFloat>(getSemantics())) + return U.IEEE.remainder(RHS.U.IEEE); + if (usesLayout<DoubleAPFloat>(getSemantics())) + return U.Double.remainder(RHS.U.Double); + llvm_unreachable("Unexpected semantics"); + } + opStatus mod(const APFloat &RHS) { + assert(&getSemantics() == &RHS.getSemantics() && + "Should only call on two APFloats with the same semantics"); + if (usesLayout<IEEEFloat>(getSemantics())) + return U.IEEE.mod(RHS.U.IEEE); + if (usesLayout<DoubleAPFloat>(getSemantics())) + return U.Double.mod(RHS.U.Double); + llvm_unreachable("Unexpected semantics"); + } + opStatus fusedMultiplyAdd(const APFloat &Multiplicand, const APFloat &Addend, + roundingMode RM) { + assert(&getSemantics() == &Multiplicand.getSemantics() && + "Should only call on APFloats with the same semantics"); + assert(&getSemantics() == &Addend.getSemantics() && + "Should only call on APFloats with the same semantics"); + if (usesLayout<IEEEFloat>(getSemantics())) + return U.IEEE.fusedMultiplyAdd(Multiplicand.U.IEEE, Addend.U.IEEE, RM); + if (usesLayout<DoubleAPFloat>(getSemantics())) + return U.Double.fusedMultiplyAdd(Multiplicand.U.Double, Addend.U.Double, + RM); + llvm_unreachable("Unexpected semantics"); + } + opStatus roundToIntegral(roundingMode RM) { + APFLOAT_DISPATCH_ON_SEMANTICS(roundToIntegral(RM)); + } + + // TODO: bool parameters are not readable and a source of bugs. + // Do something. + opStatus next(bool nextDown) { + APFLOAT_DISPATCH_ON_SEMANTICS(next(nextDown)); + } + + /// Add two APFloats, rounding ties to the nearest even. + /// No error checking. + APFloat operator+(const APFloat &RHS) const { + APFloat Result(*this); + (void)Result.add(RHS, rmNearestTiesToEven); + return Result; + } + + /// Subtract two APFloats, rounding ties to the nearest even. + /// No error checking. + APFloat operator-(const APFloat &RHS) const { + APFloat Result(*this); + (void)Result.subtract(RHS, rmNearestTiesToEven); + return Result; + } + + /// Multiply two APFloats, rounding ties to the nearest even. + /// No error checking. + APFloat operator*(const APFloat &RHS) const { + APFloat Result(*this); + (void)Result.multiply(RHS, rmNearestTiesToEven); + return Result; + } + + /// Divide the first APFloat by the second, rounding ties to the nearest even. + /// No error checking. + APFloat operator/(const APFloat &RHS) const { + APFloat Result(*this); + (void)Result.divide(RHS, rmNearestTiesToEven); + return Result; + } + + void changeSign() { APFLOAT_DISPATCH_ON_SEMANTICS(changeSign()); } + void clearSign() { + if (isNegative()) + changeSign(); + } + void copySign(const APFloat &RHS) { + if (isNegative() != RHS.isNegative()) + changeSign(); + } + + /// A static helper to produce a copy of an APFloat value with its sign + /// copied from some other APFloat. + static APFloat copySign(APFloat Value, const APFloat &Sign) { + Value.copySign(Sign); + return Value; + } + + opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, + bool *losesInfo); + opStatus convertToInteger(MutableArrayRef<integerPart> Input, + unsigned int Width, bool IsSigned, roundingMode RM, + bool *IsExact) const { + APFLOAT_DISPATCH_ON_SEMANTICS( + convertToInteger(Input, Width, IsSigned, RM, IsExact)); + } + opStatus convertToInteger(APSInt &Result, roundingMode RM, + bool *IsExact) const; + opStatus convertFromAPInt(const APInt &Input, bool IsSigned, + roundingMode RM) { + APFLOAT_DISPATCH_ON_SEMANTICS(convertFromAPInt(Input, IsSigned, RM)); + } + opStatus convertFromSignExtendedInteger(const integerPart *Input, + unsigned int InputSize, bool IsSigned, + roundingMode RM) { + APFLOAT_DISPATCH_ON_SEMANTICS( + convertFromSignExtendedInteger(Input, InputSize, IsSigned, RM)); + } + opStatus convertFromZeroExtendedInteger(const integerPart *Input, + unsigned int InputSize, bool IsSigned, + roundingMode RM) { + APFLOAT_DISPATCH_ON_SEMANTICS( + convertFromZeroExtendedInteger(Input, InputSize, IsSigned, RM)); + } + Expected<opStatus> convertFromString(StringRef, roundingMode); + APInt bitcastToAPInt() const { + APFLOAT_DISPATCH_ON_SEMANTICS(bitcastToAPInt()); + } + double convertToDouble() const { return getIEEE().convertToDouble(); } + float convertToFloat() const { return getIEEE().convertToFloat(); } + + bool operator==(const APFloat &) const = delete; + + cmpResult compare(const APFloat &RHS) const { + assert(&getSemantics() == &RHS.getSemantics() && + "Should only compare APFloats with the same semantics"); + if (usesLayout<IEEEFloat>(getSemantics())) + return U.IEEE.compare(RHS.U.IEEE); + if (usesLayout<DoubleAPFloat>(getSemantics())) + return U.Double.compare(RHS.U.Double); + llvm_unreachable("Unexpected semantics"); + } + + bool bitwiseIsEqual(const APFloat &RHS) const { + if (&getSemantics() != &RHS.getSemantics()) + return false; + if (usesLayout<IEEEFloat>(getSemantics())) + return U.IEEE.bitwiseIsEqual(RHS.U.IEEE); + if (usesLayout<DoubleAPFloat>(getSemantics())) + return U.Double.bitwiseIsEqual(RHS.U.Double); + llvm_unreachable("Unexpected semantics"); + } + + /// We don't rely on operator== working on double values, as + /// it returns true for things that are clearly not equal, like -0.0 and 0.0. + /// As such, this method can be used to do an exact bit-for-bit comparison of + /// two floating point values. + /// + /// We leave the version with the double argument here because it's just so + /// convenient to write "2.0" and the like. Without this function we'd + /// have to duplicate its logic everywhere it's called. + bool isExactlyValue(double V) const { + bool ignored; + APFloat Tmp(V); + Tmp.convert(getSemantics(), APFloat::rmNearestTiesToEven, &ignored); + return bitwiseIsEqual(Tmp); + } + + unsigned int convertToHexString(char *DST, unsigned int HexDigits, + bool UpperCase, roundingMode RM) const { + APFLOAT_DISPATCH_ON_SEMANTICS( + convertToHexString(DST, HexDigits, UpperCase, RM)); + } + + bool isZero() const { return getCategory() == fcZero; } + bool isInfinity() const { return getCategory() == fcInfinity; } + bool isNaN() const { return getCategory() == fcNaN; } + + bool isNegative() const { return getIEEE().isNegative(); } + bool isDenormal() const { APFLOAT_DISPATCH_ON_SEMANTICS(isDenormal()); } + bool isSignaling() const { return getIEEE().isSignaling(); } + + bool isNormal() const { return !isDenormal() && isFiniteNonZero(); } + bool isFinite() const { return !isNaN() && !isInfinity(); } + + fltCategory getCategory() const { return getIEEE().getCategory(); } + const fltSemantics &getSemantics() const { return *U.semantics; } + bool isNonZero() const { return !isZero(); } + bool isFiniteNonZero() const { return isFinite() && !isZero(); } + bool isPosZero() const { return isZero() && !isNegative(); } + bool isNegZero() const { return isZero() && isNegative(); } + bool isSmallest() const { APFLOAT_DISPATCH_ON_SEMANTICS(isSmallest()); } + bool isLargest() const { APFLOAT_DISPATCH_ON_SEMANTICS(isLargest()); } + bool isInteger() const { APFLOAT_DISPATCH_ON_SEMANTICS(isInteger()); } + + APFloat &operator=(const APFloat &RHS) = default; + APFloat &operator=(APFloat &&RHS) = default; + + void toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision = 0, + unsigned FormatMaxPadding = 3, bool TruncateZero = true) const { + APFLOAT_DISPATCH_ON_SEMANTICS( + toString(Str, FormatPrecision, FormatMaxPadding, TruncateZero)); + } + + void print(raw_ostream &) const; + void dump() const; + + bool getExactInverse(APFloat *inv) const { + APFLOAT_DISPATCH_ON_SEMANTICS(getExactInverse(inv)); + } + + friend hash_code hash_value(const APFloat &Arg); + friend int ilogb(const APFloat &Arg) { return ilogb(Arg.getIEEE()); } + friend APFloat scalbn(APFloat X, int Exp, roundingMode RM); + friend APFloat frexp(const APFloat &X, int &Exp, roundingMode RM); + friend IEEEFloat; + friend DoubleAPFloat; +}; + +/// See friend declarations above. +/// +/// These additional declarations are required in order to compile LLVM with IBM +/// xlC compiler. +hash_code hash_value(const APFloat &Arg); +inline APFloat scalbn(APFloat X, int Exp, APFloat::roundingMode RM) { + if (APFloat::usesLayout<detail::IEEEFloat>(X.getSemantics())) + return APFloat(scalbn(X.U.IEEE, Exp, RM), X.getSemantics()); + if (APFloat::usesLayout<detail::DoubleAPFloat>(X.getSemantics())) + return APFloat(scalbn(X.U.Double, Exp, RM), X.getSemantics()); + llvm_unreachable("Unexpected semantics"); +} + +/// 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. +inline APFloat frexp(const APFloat &X, int &Exp, APFloat::roundingMode RM) { + if (APFloat::usesLayout<detail::IEEEFloat>(X.getSemantics())) + return APFloat(frexp(X.U.IEEE, Exp, RM), X.getSemantics()); + if (APFloat::usesLayout<detail::DoubleAPFloat>(X.getSemantics())) + return APFloat(frexp(X.U.Double, Exp, RM), X.getSemantics()); + llvm_unreachable("Unexpected semantics"); +} +/// Returns the absolute value of the argument. +inline APFloat abs(APFloat X) { + X.clearSign(); + return X; +} + +/// Returns the negated value of the argument. +inline APFloat neg(APFloat X) { + X.changeSign(); + return X; +} + +/// Implements IEEE minNum semantics. Returns the smaller of the 2 arguments if +/// both are not NaN. If either argument is a NaN, returns the other argument. +LLVM_READONLY +inline APFloat minnum(const APFloat &A, const APFloat &B) { + if (A.isNaN()) + return B; + if (B.isNaN()) + return A; + return (B.compare(A) == APFloat::cmpLessThan) ? B : A; +} + +/// Implements IEEE maxNum semantics. Returns the larger of the 2 arguments if +/// both are not NaN. If either argument is a NaN, returns the other argument. +LLVM_READONLY +inline APFloat maxnum(const APFloat &A, const APFloat &B) { + if (A.isNaN()) + return B; + if (B.isNaN()) + return A; + return (A.compare(B) == APFloat::cmpLessThan) ? B : A; +} + +/// Implements IEEE 754-2018 minimum semantics. Returns the smaller of 2 +/// arguments, propagating NaNs and treating -0 as less than +0. +LLVM_READONLY +inline APFloat minimum(const APFloat &A, const APFloat &B) { + if (A.isNaN()) + return A; + if (B.isNaN()) + return B; + if (A.isZero() && B.isZero() && (A.isNegative() != B.isNegative())) + return A.isNegative() ? A : B; + return (B.compare(A) == APFloat::cmpLessThan) ? B : A; +} + +/// Implements IEEE 754-2018 maximum semantics. Returns the larger of 2 +/// arguments, propagating NaNs and treating -0 as less than +0. +LLVM_READONLY +inline APFloat maximum(const APFloat &A, const APFloat &B) { + if (A.isNaN()) + return A; + if (B.isNaN()) + return B; + if (A.isZero() && B.isZero() && (A.isNegative() != B.isNegative())) + return A.isNegative() ? B : A; + return (A.compare(B) == APFloat::cmpLessThan) ? B : A; +} + +} // namespace llvm + +#undef APFLOAT_DISPATCH_ON_SEMANTICS +#endif // LLVM_ADT_APFLOAT_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/APInt.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/APInt.h new file mode 100644 index 0000000..0791a6d --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/APInt.h
@@ -0,0 +1,2290 @@ +//===-- llvm/ADT/APInt.h - For Arbitrary Precision Integer -----*- C++ -*--===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file implements a class to represent arbitrary precision +/// integral constant values and operations on them. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_APINT_H +#define LLVM_ADT_APINT_H + +#include "llvm/Support/Compiler.h" +#include "llvm/Support/MathExtras.h" +#include <cassert> +#include <climits> +#include <cstring> +#include <string> + +namespace llvm { +class FoldingSetNodeID; +class StringRef; +class hash_code; +class raw_ostream; + +template <typename T> class SmallVectorImpl; +template <typename T> class ArrayRef; +template <typename T> class Optional; + +class APInt; + +inline APInt operator-(APInt); + +//===----------------------------------------------------------------------===// +// APInt Class +//===----------------------------------------------------------------------===// + +/// Class for arbitrary precision integers. +/// +/// APInt is a functional replacement for common case unsigned integer type like +/// "unsigned", "unsigned long" or "uint64_t", but also allows non-byte-width +/// integer sizes and large integer value types such as 3-bits, 15-bits, or more +/// than 64-bits of precision. APInt provides a variety of arithmetic operators +/// and methods to manipulate integer values of any bit-width. It supports both +/// the typical integer arithmetic and comparison operations as well as bitwise +/// manipulation. +/// +/// The class has several invariants worth noting: +/// * All bit, byte, and word positions are zero-based. +/// * Once the bit width is set, it doesn't change except by the Truncate, +/// SignExtend, or ZeroExtend operations. +/// * All binary operators must be on APInt instances of the same bit width. +/// Attempting to use these operators on instances with different bit +/// widths will yield an assertion. +/// * The value is stored canonically as an unsigned value. For operations +/// where it makes a difference, there are both signed and unsigned variants +/// of the operation. For example, sdiv and udiv. However, because the bit +/// widths must be the same, operations such as Mul and Add produce the same +/// results regardless of whether the values are interpreted as signed or +/// not. +/// * In general, the class tries to follow the style of computation that LLVM +/// uses in its IR. This simplifies its use for LLVM. +/// +class LLVM_NODISCARD APInt { +public: + typedef uint64_t WordType; + + /// This enum is used to hold the constants we needed for APInt. + enum : unsigned { + /// Byte size of a word. + APINT_WORD_SIZE = sizeof(WordType), + /// Bits in a word. + APINT_BITS_PER_WORD = APINT_WORD_SIZE * CHAR_BIT + }; + + enum class Rounding { + DOWN, + TOWARD_ZERO, + UP, + }; + + static const WordType WORDTYPE_MAX = ~WordType(0); + +private: + /// This union is used to store the integer value. When the + /// integer bit-width <= 64, it uses VAL, otherwise it uses pVal. + union { + uint64_t VAL; ///< Used to store the <= 64 bits integer value. + uint64_t *pVal; ///< Used to store the >64 bits integer value. + } U; + + unsigned BitWidth; ///< The number of bits in this APInt. + + friend struct DenseMapAPIntKeyInfo; + + friend class APSInt; + + /// Fast internal constructor + /// + /// This constructor is used only internally for speed of construction of + /// temporaries. It is unsafe for general use so it is not public. + APInt(uint64_t *val, unsigned bits) : BitWidth(bits) { + U.pVal = val; + } + + /// Determine if this APInt just has one word to store value. + /// + /// \returns true if the number of bits <= 64, false otherwise. + bool isSingleWord() const { return BitWidth <= APINT_BITS_PER_WORD; } + + /// Determine which word a bit is in. + /// + /// \returns the word position for the specified bit position. + static unsigned whichWord(unsigned bitPosition) { + return bitPosition / APINT_BITS_PER_WORD; + } + + /// Determine which bit in a word a bit is in. + /// + /// \returns the bit position in a word for the specified bit position + /// in the APInt. + static unsigned whichBit(unsigned bitPosition) { + return bitPosition % APINT_BITS_PER_WORD; + } + + /// Get a single bit mask. + /// + /// \returns a uint64_t with only bit at "whichBit(bitPosition)" set + /// This method generates and returns a uint64_t (word) mask for a single + /// bit at a specific bit position. This is used to mask the bit in the + /// corresponding word. + static uint64_t maskBit(unsigned bitPosition) { + return 1ULL << whichBit(bitPosition); + } + + /// Clear unused high order bits + /// + /// This method is used internally to clear the top "N" bits in the high order + /// word that are not used by the APInt. This is needed after the most + /// significant word is assigned a value to ensure that those bits are + /// zero'd out. + APInt &clearUnusedBits() { + // Compute how many bits are used in the final word + unsigned WordBits = ((BitWidth-1) % APINT_BITS_PER_WORD) + 1; + + // Mask out the high bits. + uint64_t mask = WORDTYPE_MAX >> (APINT_BITS_PER_WORD - WordBits); + if (isSingleWord()) + U.VAL &= mask; + else + U.pVal[getNumWords() - 1] &= mask; + return *this; + } + + /// Get the word corresponding to a bit position + /// \returns the corresponding word for the specified bit position. + uint64_t getWord(unsigned bitPosition) const { + return isSingleWord() ? U.VAL : U.pVal[whichWord(bitPosition)]; + } + + /// Utility method to change the bit width of this APInt to new bit width, + /// allocating and/or deallocating as necessary. There is no guarantee on the + /// value of any bits upon return. Caller should populate the bits after. + void reallocate(unsigned NewBitWidth); + + /// Convert a char array into an APInt + /// + /// \param radix 2, 8, 10, 16, or 36 + /// Converts a string into a number. The string must be non-empty + /// and well-formed as a number of the given base. The bit-width + /// must be sufficient to hold the result. + /// + /// This is used by the constructors that take string arguments. + /// + /// StringRef::getAsInteger is superficially similar but (1) does + /// not assume that the string is well-formed and (2) grows the + /// result to hold the input. + void fromString(unsigned numBits, StringRef str, uint8_t radix); + + /// An internal division function for dividing APInts. + /// + /// This is used by the toString method to divide by the radix. It simply + /// 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 WordType *LHS, unsigned lhsWords, + const WordType *RHS, unsigned rhsWords, WordType *Quotient, + WordType *Remainder); + + /// out-of-line slow case for inline constructor + void initSlowCase(uint64_t val, bool isSigned); + + /// shared code between two array constructors + void initFromArray(ArrayRef<uint64_t> array); + + /// out-of-line slow case for inline copy constructor + void initSlowCase(const APInt &that); + + /// out-of-line slow case for shl + void shlSlowCase(unsigned ShiftAmt); + + /// out-of-line slow case for lshr. + void lshrSlowCase(unsigned ShiftAmt); + + /// out-of-line slow case for ashr. + void ashrSlowCase(unsigned ShiftAmt); + + /// out-of-line slow case for operator= + void AssignSlowCase(const APInt &RHS); + + /// out-of-line slow case for operator== + bool EqualSlowCase(const APInt &RHS) const LLVM_READONLY; + + /// out-of-line slow case for countLeadingZeros + unsigned countLeadingZerosSlowCase() const LLVM_READONLY; + + /// out-of-line slow case for countLeadingOnes. + unsigned countLeadingOnesSlowCase() const LLVM_READONLY; + + /// out-of-line slow case for countTrailingZeros. + unsigned countTrailingZerosSlowCase() const LLVM_READONLY; + + /// out-of-line slow case for countTrailingOnes + unsigned countTrailingOnesSlowCase() const LLVM_READONLY; + + /// out-of-line slow case for countPopulation + unsigned countPopulationSlowCase() const LLVM_READONLY; + + /// out-of-line slow case for intersects. + bool intersectsSlowCase(const APInt &RHS) const LLVM_READONLY; + + /// out-of-line slow case for isSubsetOf. + bool isSubsetOfSlowCase(const APInt &RHS) const LLVM_READONLY; + + /// out-of-line slow case for setBits. + void setBitsSlowCase(unsigned loBit, unsigned hiBit); + + /// out-of-line slow case for flipAllBits. + void flipAllBitsSlowCase(); + + /// out-of-line slow case for operator&=. + void AndAssignSlowCase(const APInt& RHS); + + /// out-of-line slow case for operator|=. + void OrAssignSlowCase(const APInt& RHS); + + /// out-of-line slow case for operator^=. + void XorAssignSlowCase(const APInt& RHS); + + /// Unsigned comparison. Returns -1, 0, or 1 if this APInt is less than, equal + /// to, or greater than RHS. + int compare(const APInt &RHS) const LLVM_READONLY; + + /// Signed comparison. Returns -1, 0, or 1 if this APInt is less than, equal + /// to, or greater than RHS. + int compareSigned(const APInt &RHS) const LLVM_READONLY; + +public: + /// \name Constructors + /// @{ + + /// Create a new APInt of numBits width, initialized as val. + /// + /// If isSigned is true then val is treated as if it were a signed value + /// (i.e. as an int64_t) and the appropriate sign extension to the bit width + /// will be done. Otherwise, no sign extension occurs (high order bits beyond + /// the range of val are zero filled). + /// + /// \param numBits the bit width of the constructed APInt + /// \param val the initial value of the APInt + /// \param isSigned how to treat signedness of val + APInt(unsigned numBits, uint64_t val, bool isSigned = false) + : BitWidth(numBits) { + assert(BitWidth && "bitwidth too small"); + if (isSingleWord()) { + U.VAL = val; + clearUnusedBits(); + } else { + initSlowCase(val, isSigned); + } + } + + /// Construct an APInt of numBits width, initialized as bigVal[]. + /// + /// Note that bigVal.size() can be smaller or larger than the corresponding + /// bit width but any extraneous bits will be dropped. + /// + /// \param numBits the bit width of the constructed APInt + /// \param bigVal a sequence of words to form the initial value of the APInt + APInt(unsigned numBits, ArrayRef<uint64_t> bigVal); + + /// Equivalent to APInt(numBits, ArrayRef<uint64_t>(bigVal, numWords)), but + /// deprecated because this constructor is prone to ambiguity with the + /// APInt(unsigned, uint64_t, bool) constructor. + /// + /// If this overload is ever deleted, care should be taken to prevent calls + /// from being incorrectly captured by the APInt(unsigned, uint64_t, bool) + /// constructor. + APInt(unsigned numBits, unsigned numWords, const uint64_t bigVal[]); + + /// Construct an APInt from a string representation. + /// + /// This constructor interprets the string \p str in the given radix. The + /// interpretation stops when the first character that is not suitable for the + /// radix is encountered, or the end of the string. Acceptable radix values + /// are 2, 8, 10, 16, and 36. It is an error for the value implied by the + /// string to require more bits than numBits. + /// + /// \param numBits the bit width of the constructed APInt + /// \param str the string to be interpreted + /// \param radix the radix to use for the conversion + APInt(unsigned numBits, StringRef str, uint8_t radix); + + /// Simply makes *this a copy of that. + /// Copy Constructor. + APInt(const APInt &that) : BitWidth(that.BitWidth) { + if (isSingleWord()) + U.VAL = that.U.VAL; + else + initSlowCase(that); + } + + /// Move Constructor. + APInt(APInt &&that) : BitWidth(that.BitWidth) { + memcpy(&U, &that.U, sizeof(U)); + that.BitWidth = 0; + } + + /// Destructor. + ~APInt() { + if (needsCleanup()) + delete[] U.pVal; + } + + /// Default constructor that creates an uninteresting APInt + /// representing a 1-bit zero value. + /// + /// This is useful for object deserialization (pair this with the static + /// method Read). + explicit APInt() : BitWidth(1) { U.VAL = 0; } + + /// Returns whether this instance allocated memory. + bool needsCleanup() const { return !isSingleWord(); } + + /// Used to insert APInt objects, or objects that contain APInt objects, into + /// FoldingSets. + void Profile(FoldingSetNodeID &id) const; + + /// @} + /// \name Value Tests + /// @{ + + /// Determine sign of this APInt. + /// + /// This tests the high bit of this APInt to determine if it is set. + /// + /// \returns true if this APInt is negative, false otherwise + bool isNegative() const { return (*this)[BitWidth - 1]; } + + /// Determine if this APInt Value is non-negative (>= 0) + /// + /// This tests the high bit of the APInt to determine if it is unset. + bool isNonNegative() const { return !isNegative(); } + + /// Determine if sign bit of this APInt is set. + /// + /// This tests the high bit of this APInt to determine if it is set. + /// + /// \returns true if this APInt has its sign bit set, false otherwise. + bool isSignBitSet() const { return (*this)[BitWidth-1]; } + + /// Determine if sign bit of this APInt is clear. + /// + /// This tests the high bit of this APInt to determine if it is clear. + /// + /// \returns true if this APInt has its sign bit clear, false otherwise. + bool isSignBitClear() const { return !isSignBitSet(); } + + /// Determine if this APInt Value is positive. + /// + /// This tests if the value of this APInt is positive (> 0). Note + /// that 0 is not a positive value. + /// + /// \returns true if this APInt is positive. + bool isStrictlyPositive() const { return isNonNegative() && !isNullValue(); } + + /// Determine if this APInt Value is non-positive (<= 0). + /// + /// \returns true if this APInt is non-positive. + bool isNonPositive() const { return !isStrictlyPositive(); } + + /// Determine if all bits are set + /// + /// This checks to see if the value has all bits of the APInt are set or not. + bool isAllOnesValue() const { + if (isSingleWord()) + return U.VAL == WORDTYPE_MAX >> (APINT_BITS_PER_WORD - BitWidth); + return countTrailingOnesSlowCase() == BitWidth; + } + + /// Determine if all bits are clear + /// + /// This checks to see if the value has all bits of the APInt are clear or + /// not. + bool isNullValue() const { return !*this; } + + /// Determine if this is a value of 1. + /// + /// This checks to see if the value of this APInt is one. + bool isOneValue() const { + if (isSingleWord()) + return U.VAL == 1; + return countLeadingZerosSlowCase() == BitWidth - 1; + } + + /// Determine if this is the largest unsigned value. + /// + /// This checks to see if the value of this APInt is the maximum unsigned + /// value for the APInt's bit width. + bool isMaxValue() const { return isAllOnesValue(); } + + /// Determine if this is the largest signed value. + /// + /// This checks to see if the value of this APInt is the maximum signed + /// value for the APInt's bit width. + bool isMaxSignedValue() const { + if (isSingleWord()) + return U.VAL == ((WordType(1) << (BitWidth - 1)) - 1); + return !isNegative() && countTrailingOnesSlowCase() == BitWidth - 1; + } + + /// Determine if this is the smallest unsigned value. + /// + /// This checks to see if the value of this APInt is the minimum unsigned + /// value for the APInt's bit width. + bool isMinValue() const { return isNullValue(); } + + /// Determine if this is the smallest signed value. + /// + /// This checks to see if the value of this APInt is the minimum signed + /// value for the APInt's bit width. + bool isMinSignedValue() const { + if (isSingleWord()) + return U.VAL == (WordType(1) << (BitWidth - 1)); + return isNegative() && countTrailingZerosSlowCase() == BitWidth - 1; + } + + /// Check if this APInt has an N-bits unsigned integer value. + bool isIntN(unsigned N) const { + assert(N && "N == 0 ???"); + return getActiveBits() <= N; + } + + /// Check if this APInt has an N-bits signed integer value. + bool isSignedIntN(unsigned N) const { + assert(N && "N == 0 ???"); + return getMinSignedBits() <= N; + } + + /// Check if this APInt's value is a power of two greater than zero. + /// + /// \returns true if the argument APInt value is a power of two > 0. + bool isPowerOf2() const { + if (isSingleWord()) + return isPowerOf2_64(U.VAL); + return countPopulationSlowCase() == 1; + } + + /// Check if the APInt's value is returned by getSignMask. + /// + /// \returns true if this is the value returned by getSignMask. + bool isSignMask() const { return isMinSignedValue(); } + + /// Convert APInt to a boolean value. + /// + /// This converts the APInt to a boolean value as a test against zero. + bool getBoolValue() const { return !!*this; } + + /// If this value is smaller than the specified limit, return it, otherwise + /// return the limit value. This causes the value to saturate to the limit. + uint64_t getLimitedValue(uint64_t Limit = UINT64_MAX) const { + return ugt(Limit) ? Limit : getZExtValue(); + } + + /// Check if the APInt consists of a repeated bit pattern. + /// + /// e.g. 0x01010101 satisfies isSplat(8). + /// \param SplatSizeInBits The size of the pattern in bits. Must divide bit + /// width without remainder. + bool isSplat(unsigned SplatSizeInBits) const; + + /// \returns true if this APInt value is a sequence of \param numBits ones + /// starting at the least significant bit with the remainder zero. + bool isMask(unsigned numBits) const { + assert(numBits != 0 && "numBits must be non-zero"); + assert(numBits <= BitWidth && "numBits out of range"); + if (isSingleWord()) + return U.VAL == (WORDTYPE_MAX >> (APINT_BITS_PER_WORD - numBits)); + unsigned Ones = countTrailingOnesSlowCase(); + return (numBits == Ones) && + ((Ones + countLeadingZerosSlowCase()) == BitWidth); + } + + /// \returns true if this APInt is a non-empty sequence of ones starting at + /// the least significant bit with the remainder zero. + /// Ex. isMask(0x0000FFFFU) == true. + bool isMask() const { + if (isSingleWord()) + return isMask_64(U.VAL); + unsigned Ones = countTrailingOnesSlowCase(); + return (Ones > 0) && ((Ones + countLeadingZerosSlowCase()) == BitWidth); + } + + /// Return true if this APInt value contains a sequence of ones with + /// the remainder zero. + bool isShiftedMask() const { + if (isSingleWord()) + return isShiftedMask_64(U.VAL); + unsigned Ones = countPopulationSlowCase(); + unsigned LeadZ = countLeadingZerosSlowCase(); + return (Ones + LeadZ + countTrailingZeros()) == BitWidth; + } + + /// @} + /// \name Value Generators + /// @{ + + /// Gets maximum unsigned value of APInt for specific bit width. + static APInt getMaxValue(unsigned numBits) { + return getAllOnesValue(numBits); + } + + /// Gets maximum signed value of APInt for a specific bit width. + static APInt getSignedMaxValue(unsigned numBits) { + APInt API = getAllOnesValue(numBits); + API.clearBit(numBits - 1); + return API; + } + + /// Gets minimum unsigned value of APInt for a specific bit width. + static APInt getMinValue(unsigned numBits) { return APInt(numBits, 0); } + + /// Gets minimum signed value of APInt for a specific bit width. + static APInt getSignedMinValue(unsigned numBits) { + APInt API(numBits, 0); + API.setBit(numBits - 1); + return API; + } + + /// Get the SignMask for a specific bit width. + /// + /// This is just a wrapper function of getSignedMinValue(), and it helps code + /// readability when we want to get a SignMask. + static APInt getSignMask(unsigned BitWidth) { + return getSignedMinValue(BitWidth); + } + + /// Get the all-ones value. + /// + /// \returns the all-ones value for an APInt of the specified bit-width. + static APInt getAllOnesValue(unsigned numBits) { + return APInt(numBits, WORDTYPE_MAX, true); + } + + /// Get the '0' value. + /// + /// \returns the '0' value for an APInt of the specified bit-width. + static APInt getNullValue(unsigned numBits) { return APInt(numBits, 0); } + + /// Compute an APInt containing numBits highbits from this APInt. + /// + /// Get an APInt with the same BitWidth as this APInt, just zero mask + /// the low bits and right shift to the least significant bit. + /// + /// \returns the high "numBits" bits of this APInt. + APInt getHiBits(unsigned numBits) const; + + /// Compute an APInt containing numBits lowbits from this APInt. + /// + /// Get an APInt with the same BitWidth as this APInt, just zero mask + /// the high bits. + /// + /// \returns the low "numBits" bits of this APInt. + APInt getLoBits(unsigned numBits) const; + + /// Return an APInt with exactly one bit set in the result. + static APInt getOneBitSet(unsigned numBits, unsigned BitNo) { + APInt Res(numBits, 0); + Res.setBit(BitNo); + return Res; + } + + /// Get a value with a block of bits set. + /// + /// Constructs an APInt value that has a contiguous range of bits set. The + /// bits from loBit (inclusive) to hiBit (exclusive) will be set. All other + /// bits will be zero. For example, with parameters(32, 0, 16) you would get + /// 0x0000FFFF. Please call getBitsSetWithWrap if \p loBit may be greater than + /// \p hiBit. + /// + /// \param numBits the intended bit width of the result + /// \param loBit the index of the lowest bit set. + /// \param hiBit the index of the highest bit set. + /// + /// \returns An APInt value with the requested bits set. + static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit) { + assert(loBit <= hiBit && "loBit greater than hiBit"); + APInt Res(numBits, 0); + Res.setBits(loBit, hiBit); + return Res; + } + + /// Wrap version of getBitsSet. + /// If \p hiBit is no less than \p loBit, this is same with getBitsSet. + /// If \p hiBit is less than \p loBit, the set bits "wrap". For example, with + /// parameters (32, 28, 4), you would get 0xF000000F. + static APInt getBitsSetWithWrap(unsigned numBits, unsigned loBit, + unsigned hiBit) { + APInt Res(numBits, 0); + Res.setBitsWithWrap(loBit, hiBit); + return Res; + } + + /// Get a value with upper bits starting at loBit set. + /// + /// Constructs an APInt value that has a contiguous range of bits set. The + /// bits from loBit (inclusive) to numBits (exclusive) will be set. All other + /// bits will be zero. For example, with parameters(32, 12) you would get + /// 0xFFFFF000. + /// + /// \param numBits the intended bit width of the result + /// \param loBit the index of the lowest bit to set. + /// + /// \returns An APInt value with the requested bits set. + static APInt getBitsSetFrom(unsigned numBits, unsigned loBit) { + APInt Res(numBits, 0); + Res.setBitsFrom(loBit); + return Res; + } + + /// Get a value with high bits set + /// + /// Constructs an APInt value that has the top hiBitsSet bits set. + /// + /// \param numBits the bitwidth of the result + /// \param hiBitsSet the number of high-order bits set in the result. + static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet) { + APInt Res(numBits, 0); + Res.setHighBits(hiBitsSet); + return Res; + } + + /// Get a value with low bits set + /// + /// Constructs an APInt value that has the bottom loBitsSet bits set. + /// + /// \param numBits the bitwidth of the result + /// \param loBitsSet the number of low-order bits set in the result. + static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet) { + APInt Res(numBits, 0); + Res.setLowBits(loBitsSet); + return Res; + } + + /// Return a value containing V broadcasted over NewLen bits. + static APInt getSplat(unsigned NewLen, const APInt &V); + + /// Determine if two APInts have the same value, after zero-extending + /// one of them (if needed!) to ensure that the bit-widths match. + static bool isSameValue(const APInt &I1, const APInt &I2) { + if (I1.getBitWidth() == I2.getBitWidth()) + return I1 == I2; + + if (I1.getBitWidth() > I2.getBitWidth()) + return I1 == I2.zext(I1.getBitWidth()); + + return I1.zext(I2.getBitWidth()) == I2; + } + + /// Overload to compute a hash_code for an APInt value. + friend hash_code hash_value(const APInt &Arg); + + /// This function returns a pointer to the internal storage of the APInt. + /// This is useful for writing out the APInt in binary form without any + /// conversions. + const uint64_t *getRawData() const { + if (isSingleWord()) + return &U.VAL; + return &U.pVal[0]; + } + + /// @} + /// \name Unary Operators + /// @{ + + /// Postfix increment operator. + /// + /// Increments *this by 1. + /// + /// \returns a new APInt value representing the original value of *this. + const APInt operator++(int) { + APInt API(*this); + ++(*this); + return API; + } + + /// Prefix increment operator. + /// + /// \returns *this incremented by one + APInt &operator++(); + + /// Postfix decrement operator. + /// + /// Decrements *this by 1. + /// + /// \returns a new APInt value representing the original value of *this. + const APInt operator--(int) { + APInt API(*this); + --(*this); + return API; + } + + /// Prefix decrement operator. + /// + /// \returns *this decremented by one. + APInt &operator--(); + + /// Logical negation operator. + /// + /// Performs logical negation operation on this APInt. + /// + /// \returns true if *this is zero, false otherwise. + bool operator!() const { + if (isSingleWord()) + return U.VAL == 0; + return countLeadingZerosSlowCase() == BitWidth; + } + + /// @} + /// \name Assignment Operators + /// @{ + + /// Copy assignment operator. + /// + /// \returns *this after assignment of RHS. + APInt &operator=(const APInt &RHS) { + // If the bitwidths are the same, we can avoid mucking with memory + if (isSingleWord() && RHS.isSingleWord()) { + U.VAL = RHS.U.VAL; + BitWidth = RHS.BitWidth; + return clearUnusedBits(); + } + + AssignSlowCase(RHS); + return *this; + } + + /// Move assignment operator. + APInt &operator=(APInt &&that) { +#ifdef _MSC_VER + // The MSVC std::shuffle implementation still does self-assignment. + if (this == &that) + return *this; +#endif + assert(this != &that && "Self-move not supported"); + if (!isSingleWord()) + delete[] U.pVal; + + // Use memcpy so that type based alias analysis sees both VAL and pVal + // as modified. + memcpy(&U, &that.U, sizeof(U)); + + BitWidth = that.BitWidth; + that.BitWidth = 0; + + return *this; + } + + /// Assignment operator. + /// + /// The RHS value is assigned to *this. If the significant bits in RHS exceed + /// the bit width, the excess bits are truncated. If the bit width is larger + /// than 64, the value is zero filled in the unspecified high order bits. + /// + /// \returns *this after assignment of RHS value. + APInt &operator=(uint64_t RHS) { + if (isSingleWord()) { + U.VAL = RHS; + clearUnusedBits(); + } else { + U.pVal[0] = RHS; + memset(U.pVal+1, 0, (getNumWords() - 1) * APINT_WORD_SIZE); + } + return *this; + } + + /// Bitwise AND assignment operator. + /// + /// Performs a bitwise AND operation on this APInt and RHS. The result is + /// assigned to *this. + /// + /// \returns *this after ANDing with RHS. + APInt &operator&=(const APInt &RHS) { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + U.VAL &= RHS.U.VAL; + else + AndAssignSlowCase(RHS); + return *this; + } + + /// Bitwise AND assignment operator. + /// + /// Performs a bitwise AND operation on this APInt and RHS. RHS is + /// logically zero-extended or truncated to match the bit-width of + /// the LHS. + APInt &operator&=(uint64_t RHS) { + if (isSingleWord()) { + U.VAL &= RHS; + return *this; + } + U.pVal[0] &= RHS; + memset(U.pVal+1, 0, (getNumWords() - 1) * APINT_WORD_SIZE); + return *this; + } + + /// Bitwise OR assignment operator. + /// + /// Performs a bitwise OR operation on this APInt and RHS. The result is + /// assigned *this; + /// + /// \returns *this after ORing with RHS. + APInt &operator|=(const APInt &RHS) { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + U.VAL |= RHS.U.VAL; + else + OrAssignSlowCase(RHS); + return *this; + } + + /// Bitwise OR assignment operator. + /// + /// Performs a bitwise OR operation on this APInt and RHS. RHS is + /// logically zero-extended or truncated to match the bit-width of + /// the LHS. + APInt &operator|=(uint64_t RHS) { + if (isSingleWord()) { + U.VAL |= RHS; + clearUnusedBits(); + } else { + U.pVal[0] |= RHS; + } + return *this; + } + + /// Bitwise XOR assignment operator. + /// + /// Performs a bitwise XOR operation on this APInt and RHS. The result is + /// assigned to *this. + /// + /// \returns *this after XORing with RHS. + APInt &operator^=(const APInt &RHS) { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + U.VAL ^= RHS.U.VAL; + else + XorAssignSlowCase(RHS); + return *this; + } + + /// Bitwise XOR assignment operator. + /// + /// Performs a bitwise XOR operation on this APInt and RHS. RHS is + /// logically zero-extended or truncated to match the bit-width of + /// the LHS. + APInt &operator^=(uint64_t RHS) { + if (isSingleWord()) { + U.VAL ^= RHS; + clearUnusedBits(); + } else { + U.pVal[0] ^= RHS; + } + return *this; + } + + /// Multiplication assignment operator. + /// + /// Multiplies this APInt by RHS and assigns the result to *this. + /// + /// \returns *this + APInt &operator*=(const APInt &RHS); + APInt &operator*=(uint64_t RHS); + + /// Addition assignment operator. + /// + /// Adds RHS to *this and assigns the result to *this. + /// + /// \returns *this + APInt &operator+=(const APInt &RHS); + APInt &operator+=(uint64_t RHS); + + /// Subtraction assignment operator. + /// + /// Subtracts RHS from *this and assigns the result to *this. + /// + /// \returns *this + APInt &operator-=(const APInt &RHS); + APInt &operator-=(uint64_t RHS); + + /// Left-shift assignment function. + /// + /// Shifts *this left by shiftAmt and assigns the result to *this. + /// + /// \returns *this after shifting left by ShiftAmt + APInt &operator<<=(unsigned ShiftAmt) { + assert(ShiftAmt <= BitWidth && "Invalid shift amount"); + if (isSingleWord()) { + if (ShiftAmt == BitWidth) + U.VAL = 0; + else + U.VAL <<= ShiftAmt; + return clearUnusedBits(); + } + shlSlowCase(ShiftAmt); + return *this; + } + + /// Left-shift assignment function. + /// + /// Shifts *this left by shiftAmt and assigns the result to *this. + /// + /// \returns *this after shifting left by ShiftAmt + APInt &operator<<=(const APInt &ShiftAmt); + + /// @} + /// \name Binary Operators + /// @{ + + /// Multiplication operator. + /// + /// Multiplies this APInt by RHS and returns the result. + APInt operator*(const APInt &RHS) const; + + /// Left logical shift operator. + /// + /// Shifts this APInt left by \p Bits and returns the result. + APInt operator<<(unsigned Bits) const { return shl(Bits); } + + /// Left logical shift operator. + /// + /// Shifts this APInt left by \p Bits and returns the result. + APInt operator<<(const APInt &Bits) const { return shl(Bits); } + + /// Arithmetic right-shift function. + /// + /// Arithmetic right-shift this APInt by shiftAmt. + APInt ashr(unsigned ShiftAmt) const { + APInt R(*this); + R.ashrInPlace(ShiftAmt); + return R; + } + + /// Arithmetic right-shift this APInt by ShiftAmt in place. + void ashrInPlace(unsigned ShiftAmt) { + assert(ShiftAmt <= BitWidth && "Invalid shift amount"); + if (isSingleWord()) { + int64_t SExtVAL = SignExtend64(U.VAL, BitWidth); + if (ShiftAmt == BitWidth) + U.VAL = SExtVAL >> (APINT_BITS_PER_WORD - 1); // Fill with sign bit. + else + U.VAL = SExtVAL >> ShiftAmt; + clearUnusedBits(); + return; + } + ashrSlowCase(ShiftAmt); + } + + /// Logical right-shift function. + /// + /// Logical right-shift this APInt by shiftAmt. + APInt lshr(unsigned shiftAmt) const { + APInt R(*this); + R.lshrInPlace(shiftAmt); + return R; + } + + /// Logical right-shift this APInt by ShiftAmt in place. + void lshrInPlace(unsigned ShiftAmt) { + assert(ShiftAmt <= BitWidth && "Invalid shift amount"); + if (isSingleWord()) { + if (ShiftAmt == BitWidth) + U.VAL = 0; + else + U.VAL >>= ShiftAmt; + return; + } + lshrSlowCase(ShiftAmt); + } + + /// Left-shift function. + /// + /// Left-shift this APInt by shiftAmt. + APInt shl(unsigned shiftAmt) const { + APInt R(*this); + R <<= shiftAmt; + return R; + } + + /// Rotate left by rotateAmt. + APInt rotl(unsigned rotateAmt) const; + + /// Rotate right by rotateAmt. + APInt rotr(unsigned rotateAmt) const; + + /// Arithmetic right-shift function. + /// + /// Arithmetic right-shift this APInt by shiftAmt. + APInt ashr(const APInt &ShiftAmt) const { + APInt R(*this); + R.ashrInPlace(ShiftAmt); + return R; + } + + /// Arithmetic right-shift this APInt by shiftAmt in place. + void ashrInPlace(const APInt &shiftAmt); + + /// Logical right-shift function. + /// + /// Logical right-shift this APInt by shiftAmt. + APInt lshr(const APInt &ShiftAmt) const { + APInt R(*this); + R.lshrInPlace(ShiftAmt); + return R; + } + + /// Logical right-shift this APInt by ShiftAmt in place. + void lshrInPlace(const APInt &ShiftAmt); + + /// Left-shift function. + /// + /// Left-shift this APInt by shiftAmt. + APInt shl(const APInt &ShiftAmt) const { + APInt R(*this); + R <<= ShiftAmt; + return R; + } + + /// Rotate left by rotateAmt. + APInt rotl(const APInt &rotateAmt) const; + + /// Rotate right by rotateAmt. + APInt rotr(const APInt &rotateAmt) const; + + /// Unsigned division operation. + /// + /// Perform an unsigned divide operation on this APInt by RHS. Both this and + /// RHS are treated as unsigned quantities for purposes of this division. + /// + /// \returns a new APInt value containing the division result, rounded towards + /// zero. + APInt udiv(const APInt &RHS) const; + APInt udiv(uint64_t RHS) const; + + /// Signed division function for APInt. + /// + /// Signed divide this APInt by APInt RHS. + /// + /// The result is rounded towards zero. + APInt sdiv(const APInt &RHS) const; + APInt sdiv(int64_t RHS) const; + + /// Unsigned remainder operation. + /// + /// Perform an unsigned remainder operation on this APInt with RHS being the + /// divisor. Both this and RHS are treated as unsigned quantities for purposes + /// of this operation. Note that this is a true remainder operation and not a + /// modulo operation because the sign follows the sign of the dividend which + /// is *this. + /// + /// \returns a new APInt value containing the remainder result + APInt urem(const APInt &RHS) const; + uint64_t urem(uint64_t RHS) const; + + /// Function for signed remainder operation. + /// + /// Signed remainder operation on APInt. + APInt srem(const APInt &RHS) const; + int64_t srem(int64_t RHS) const; + + /// Dual division/remainder interface. + /// + /// Sometimes it is convenient to divide two APInt values and obtain both the + /// quotient and remainder. This function does both operations in the same + /// computation making it a little more efficient. The pair of input arguments + /// may overlap with the pair of output arguments. It is safe to call + /// udivrem(X, Y, X, Y), for example. + static void udivrem(const APInt &LHS, const APInt &RHS, APInt &Quotient, + APInt &Remainder); + static void udivrem(const APInt &LHS, uint64_t RHS, APInt &Quotient, + uint64_t &Remainder); + + static void sdivrem(const APInt &LHS, const APInt &RHS, APInt &Quotient, + APInt &Remainder); + static void sdivrem(const APInt &LHS, int64_t RHS, APInt &Quotient, + int64_t &Remainder); + + // Operations that return overflow indicators. + APInt sadd_ov(const APInt &RHS, bool &Overflow) const; + APInt uadd_ov(const APInt &RHS, bool &Overflow) const; + APInt ssub_ov(const APInt &RHS, bool &Overflow) const; + APInt usub_ov(const APInt &RHS, bool &Overflow) const; + APInt sdiv_ov(const APInt &RHS, bool &Overflow) const; + APInt smul_ov(const APInt &RHS, bool &Overflow) const; + APInt umul_ov(const APInt &RHS, bool &Overflow) const; + APInt sshl_ov(const APInt &Amt, bool &Overflow) const; + APInt ushl_ov(const APInt &Amt, bool &Overflow) const; + + // Operations that saturate + APInt sadd_sat(const APInt &RHS) const; + APInt uadd_sat(const APInt &RHS) const; + APInt ssub_sat(const APInt &RHS) const; + APInt usub_sat(const APInt &RHS) const; + APInt smul_sat(const APInt &RHS) const; + APInt umul_sat(const APInt &RHS) const; + APInt sshl_sat(const APInt &RHS) const; + APInt ushl_sat(const APInt &RHS) const; + + /// Array-indexing support. + /// + /// \returns the bit value at bitPosition + bool operator[](unsigned bitPosition) const { + assert(bitPosition < getBitWidth() && "Bit position out of bounds!"); + return (maskBit(bitPosition) & getWord(bitPosition)) != 0; + } + + /// @} + /// \name Comparison Operators + /// @{ + + /// Equality operator. + /// + /// Compares this APInt with RHS for the validity of the equality + /// relationship. + bool operator==(const APInt &RHS) const { + assert(BitWidth == RHS.BitWidth && "Comparison requires equal bit widths"); + if (isSingleWord()) + return U.VAL == RHS.U.VAL; + return EqualSlowCase(RHS); + } + + /// Equality operator. + /// + /// Compares this APInt with a uint64_t for the validity of the equality + /// relationship. + /// + /// \returns true if *this == Val + bool operator==(uint64_t Val) const { + return (isSingleWord() || getActiveBits() <= 64) && getZExtValue() == Val; + } + + /// Equality comparison. + /// + /// Compares this APInt with RHS for the validity of the equality + /// relationship. + /// + /// \returns true if *this == Val + bool eq(const APInt &RHS) const { return (*this) == RHS; } + + /// Inequality operator. + /// + /// Compares this APInt with RHS for the validity of the inequality + /// relationship. + /// + /// \returns true if *this != Val + bool operator!=(const APInt &RHS) const { return !((*this) == RHS); } + + /// Inequality operator. + /// + /// Compares this APInt with a uint64_t for the validity of the inequality + /// relationship. + /// + /// \returns true if *this != Val + bool operator!=(uint64_t Val) const { return !((*this) == Val); } + + /// Inequality comparison + /// + /// Compares this APInt with RHS for the validity of the inequality + /// relationship. + /// + /// \returns true if *this != Val + bool ne(const APInt &RHS) const { return !((*this) == RHS); } + + /// Unsigned less than comparison + /// + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the less-than relationship. + /// + /// \returns true if *this < RHS when both are considered unsigned. + bool ult(const APInt &RHS) const { return compare(RHS) < 0; } + + /// Unsigned less than comparison + /// + /// Regards both *this as an unsigned quantity and compares it with RHS for + /// the validity of the less-than relationship. + /// + /// \returns true if *this < RHS when considered unsigned. + bool ult(uint64_t RHS) const { + // Only need to check active bits if not a single word. + return (isSingleWord() || getActiveBits() <= 64) && getZExtValue() < RHS; + } + + /// Signed less than comparison + /// + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-than relationship. + /// + /// \returns true if *this < RHS when both are considered signed. + bool slt(const APInt &RHS) const { return compareSigned(RHS) < 0; } + + /// Signed less than comparison + /// + /// Regards both *this as a signed quantity and compares it with RHS for + /// the validity of the less-than relationship. + /// + /// \returns true if *this < RHS when considered signed. + bool slt(int64_t RHS) const { + return (!isSingleWord() && getMinSignedBits() > 64) ? isNegative() + : getSExtValue() < RHS; + } + + /// Unsigned less or equal comparison + /// + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the less-or-equal relationship. + /// + /// \returns true if *this <= RHS when both are considered unsigned. + bool ule(const APInt &RHS) const { return compare(RHS) <= 0; } + + /// Unsigned less or equal comparison + /// + /// Regards both *this as an unsigned quantity and compares it with RHS for + /// the validity of the less-or-equal relationship. + /// + /// \returns true if *this <= RHS when considered unsigned. + bool ule(uint64_t RHS) const { return !ugt(RHS); } + + /// Signed less or equal comparison + /// + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-or-equal relationship. + /// + /// \returns true if *this <= RHS when both are considered signed. + bool sle(const APInt &RHS) const { return compareSigned(RHS) <= 0; } + + /// Signed less or equal comparison + /// + /// Regards both *this as a signed quantity and compares it with RHS for the + /// validity of the less-or-equal relationship. + /// + /// \returns true if *this <= RHS when considered signed. + bool sle(uint64_t RHS) const { return !sgt(RHS); } + + /// Unsigned greater than comparison + /// + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the greater-than relationship. + /// + /// \returns true if *this > RHS when both are considered unsigned. + bool ugt(const APInt &RHS) const { return !ule(RHS); } + + /// Unsigned greater than comparison + /// + /// Regards both *this as an unsigned quantity and compares it with RHS for + /// the validity of the greater-than relationship. + /// + /// \returns true if *this > RHS when considered unsigned. + bool ugt(uint64_t RHS) const { + // Only need to check active bits if not a single word. + return (!isSingleWord() && getActiveBits() > 64) || getZExtValue() > RHS; + } + + /// Signed greater than comparison + /// + /// Regards both *this and RHS as signed quantities and compares them for the + /// validity of the greater-than relationship. + /// + /// \returns true if *this > RHS when both are considered signed. + bool sgt(const APInt &RHS) const { return !sle(RHS); } + + /// Signed greater than comparison + /// + /// Regards both *this as a signed quantity and compares it with RHS for + /// the validity of the greater-than relationship. + /// + /// \returns true if *this > RHS when considered signed. + bool sgt(int64_t RHS) const { + return (!isSingleWord() && getMinSignedBits() > 64) ? !isNegative() + : getSExtValue() > RHS; + } + + /// Unsigned greater or equal comparison + /// + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the greater-or-equal relationship. + /// + /// \returns true if *this >= RHS when both are considered unsigned. + bool uge(const APInt &RHS) const { return !ult(RHS); } + + /// Unsigned greater or equal comparison + /// + /// Regards both *this as an unsigned quantity and compares it with RHS for + /// the validity of the greater-or-equal relationship. + /// + /// \returns true if *this >= RHS when considered unsigned. + bool uge(uint64_t RHS) const { return !ult(RHS); } + + /// Signed greater or equal comparison + /// + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the greater-or-equal relationship. + /// + /// \returns true if *this >= RHS when both are considered signed. + bool sge(const APInt &RHS) const { return !slt(RHS); } + + /// Signed greater or equal comparison + /// + /// Regards both *this as a signed quantity and compares it with RHS for + /// the validity of the greater-or-equal relationship. + /// + /// \returns true if *this >= RHS when considered signed. + bool sge(int64_t RHS) const { return !slt(RHS); } + + /// This operation tests if there are any pairs of corresponding bits + /// between this APInt and RHS that are both set. + bool intersects(const APInt &RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + return (U.VAL & RHS.U.VAL) != 0; + return intersectsSlowCase(RHS); + } + + /// This operation checks that all bits set in this APInt are also set in RHS. + bool isSubsetOf(const APInt &RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + return (U.VAL & ~RHS.U.VAL) == 0; + return isSubsetOfSlowCase(RHS); + } + + /// @} + /// \name Resizing Operators + /// @{ + + /// Truncate to new width. + /// + /// Truncate the APInt to a specified width. It is an error to specify a width + /// that is greater than or equal to the current width. + APInt trunc(unsigned width) const; + + /// Truncate to new width with unsigned saturation. + /// + /// If the APInt, treated as unsigned integer, can be losslessly truncated to + /// the new bitwidth, then return truncated APInt. Else, return max value. + APInt truncUSat(unsigned width) const; + + /// Truncate to new width with signed saturation. + /// + /// If this APInt, treated as signed integer, can be losslessly truncated to + /// the new bitwidth, then return truncated APInt. Else, return either + /// signed min value if the APInt was negative, or signed max value. + APInt truncSSat(unsigned width) const; + + /// Sign extend to a new width. + /// + /// This operation sign extends the APInt to a new width. If the high order + /// bit is set, the fill on the left will be done with 1 bits, otherwise zero. + /// It is an error to specify a width that is less than or equal to the + /// current width. + APInt sext(unsigned width) const; + + /// Zero extend to a new width. + /// + /// This operation zero extends the APInt to a new width. The high order bits + /// are filled with 0 bits. It is an error to specify a width that is less + /// than or equal to the current width. + APInt zext(unsigned width) const; + + /// Sign extend or truncate to width + /// + /// Make this APInt have the bit width given by \p width. The value is sign + /// extended, truncated, or left alone to make it that width. + APInt sextOrTrunc(unsigned width) const; + + /// Zero extend or truncate to width + /// + /// Make this APInt have the bit width given by \p width. The value is zero + /// extended, truncated, or left alone to make it that width. + APInt zextOrTrunc(unsigned width) const; + + /// Sign extend or truncate to width + /// + /// Make this APInt have the bit width given by \p width. The value is sign + /// extended, or left alone to make it that width. + APInt sextOrSelf(unsigned width) const; + + /// Zero extend or truncate to width + /// + /// Make this APInt have the bit width given by \p width. The value is zero + /// extended, or left alone to make it that width. + APInt zextOrSelf(unsigned width) const; + + /// @} + /// \name Bit Manipulation Operators + /// @{ + + /// Set every bit to 1. + void setAllBits() { + if (isSingleWord()) + U.VAL = WORDTYPE_MAX; + else + // Set all the bits in all the words. + memset(U.pVal, -1, getNumWords() * APINT_WORD_SIZE); + // Clear the unused ones + clearUnusedBits(); + } + + /// Set a given bit to 1. + /// + /// Set the given bit to 1 whose position is given as "bitPosition". + void setBit(unsigned BitPosition) { + assert(BitPosition < BitWidth && "BitPosition out of range"); + WordType Mask = maskBit(BitPosition); + if (isSingleWord()) + U.VAL |= Mask; + else + U.pVal[whichWord(BitPosition)] |= Mask; + } + + /// Set the sign bit to 1. + void setSignBit() { + setBit(BitWidth - 1); + } + + /// Set the bits from loBit (inclusive) to hiBit (exclusive) to 1. + /// This function handles "wrap" case when \p loBit > \p hiBit, and calls + /// setBits when \p loBit <= \p hiBit. + void setBitsWithWrap(unsigned loBit, unsigned hiBit) { + assert(hiBit <= BitWidth && "hiBit out of range"); + assert(loBit <= BitWidth && "loBit out of range"); + if (loBit <= hiBit) { + setBits(loBit, hiBit); + return; + } + setLowBits(hiBit); + setHighBits(BitWidth - loBit); + } + + /// Set the bits from loBit (inclusive) to hiBit (exclusive) to 1. + /// This function handles case when \p loBit <= \p hiBit. + void setBits(unsigned loBit, unsigned hiBit) { + assert(hiBit <= BitWidth && "hiBit out of range"); + assert(loBit <= BitWidth && "loBit out of range"); + assert(loBit <= hiBit && "loBit greater than hiBit"); + if (loBit == hiBit) + return; + if (loBit < APINT_BITS_PER_WORD && hiBit <= APINT_BITS_PER_WORD) { + uint64_t mask = WORDTYPE_MAX >> (APINT_BITS_PER_WORD - (hiBit - loBit)); + mask <<= loBit; + if (isSingleWord()) + U.VAL |= mask; + else + U.pVal[0] |= mask; + } else { + setBitsSlowCase(loBit, hiBit); + } + } + + /// Set the top bits starting from loBit. + void setBitsFrom(unsigned loBit) { + return setBits(loBit, BitWidth); + } + + /// Set the bottom loBits bits. + void setLowBits(unsigned loBits) { + return setBits(0, loBits); + } + + /// Set the top hiBits bits. + void setHighBits(unsigned hiBits) { + return setBits(BitWidth - hiBits, BitWidth); + } + + /// Set every bit to 0. + void clearAllBits() { + if (isSingleWord()) + U.VAL = 0; + else + memset(U.pVal, 0, getNumWords() * APINT_WORD_SIZE); + } + + /// Set a given bit to 0. + /// + /// Set the given bit to 0 whose position is given as "bitPosition". + void clearBit(unsigned BitPosition) { + assert(BitPosition < BitWidth && "BitPosition out of range"); + WordType Mask = ~maskBit(BitPosition); + if (isSingleWord()) + U.VAL &= Mask; + else + U.pVal[whichWord(BitPosition)] &= Mask; + } + + /// Set bottom loBits bits to 0. + void clearLowBits(unsigned loBits) { + assert(loBits <= BitWidth && "More bits than bitwidth"); + APInt Keep = getHighBitsSet(BitWidth, BitWidth - loBits); + *this &= Keep; + } + + /// Set the sign bit to 0. + void clearSignBit() { + clearBit(BitWidth - 1); + } + + /// Toggle every bit to its opposite value. + void flipAllBits() { + if (isSingleWord()) { + U.VAL ^= WORDTYPE_MAX; + clearUnusedBits(); + } else { + flipAllBitsSlowCase(); + } + } + + /// Toggles a given bit to its opposite value. + /// + /// Toggle a given bit to its opposite value whose position is given + /// as "bitPosition". + void flipBit(unsigned bitPosition); + + /// Negate this APInt in place. + void negate() { + flipAllBits(); + ++(*this); + } + + /// Insert the bits from a smaller APInt starting at bitPosition. + void insertBits(const APInt &SubBits, unsigned bitPosition); + void insertBits(uint64_t SubBits, unsigned bitPosition, unsigned numBits); + + /// Return an APInt with the extracted bits [bitPosition,bitPosition+numBits). + APInt extractBits(unsigned numBits, unsigned bitPosition) const; + uint64_t extractBitsAsZExtValue(unsigned numBits, unsigned bitPosition) const; + + /// @} + /// \name Value Characterization Functions + /// @{ + + /// Return the number of bits in the APInt. + unsigned getBitWidth() const { return BitWidth; } + + /// Get the number of words. + /// + /// Here one word's bitwidth equals to that of uint64_t. + /// + /// \returns the number of words to hold the integer value of this APInt. + unsigned getNumWords() const { return getNumWords(BitWidth); } + + /// Get the number of words. + /// + /// *NOTE* Here one word's bitwidth equals to that of uint64_t. + /// + /// \returns the number of words to hold the integer value with a given bit + /// width. + static unsigned getNumWords(unsigned BitWidth) { + return ((uint64_t)BitWidth + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD; + } + + /// Compute the number of active bits in the value + /// + /// This function returns the number of active bits which is defined as the + /// bit width minus the number of leading zeros. This is used in several + /// computations to see how "wide" the value is. + unsigned getActiveBits() const { return BitWidth - countLeadingZeros(); } + + /// Compute the number of active words in the value of this APInt. + /// + /// This is used in conjunction with getActiveData to extract the raw value of + /// the APInt. + unsigned getActiveWords() const { + unsigned numActiveBits = getActiveBits(); + return numActiveBits ? whichWord(numActiveBits - 1) + 1 : 1; + } + + /// Get the minimum bit size for this signed APInt + /// + /// Computes the minimum bit width for this APInt while considering it to be a + /// signed (and probably negative) value. If the value is not negative, this + /// function returns the same value as getActiveBits()+1. Otherwise, it + /// returns the smallest bit width that will retain the negative value. For + /// example, -1 can be written as 0b1 or 0xFFFFFFFFFF. 0b1 is shorter and so + /// for -1, this function will always return 1. + unsigned getMinSignedBits() const { + if (isNegative()) + return BitWidth - countLeadingOnes() + 1; + return getActiveBits() + 1; + } + + /// Get zero extended value + /// + /// This method attempts to return the value of this APInt as a zero extended + /// uint64_t. The bitwidth must be <= 64 or the value must fit within a + /// uint64_t. Otherwise an assertion will result. + uint64_t getZExtValue() const { + if (isSingleWord()) + return U.VAL; + assert(getActiveBits() <= 64 && "Too many bits for uint64_t"); + return U.pVal[0]; + } + + /// Get sign extended value + /// + /// This method attempts to return the value of this APInt as a sign extended + /// int64_t. The bit width must be <= 64 or the value must fit within an + /// int64_t. Otherwise an assertion will result. + int64_t getSExtValue() const { + if (isSingleWord()) + return SignExtend64(U.VAL, BitWidth); + assert(getMinSignedBits() <= 64 && "Too many bits for int64_t"); + return int64_t(U.pVal[0]); + } + + /// Get bits required for string value. + /// + /// This method determines how many bits are required to hold the APInt + /// equivalent of the string given by \p str. + static unsigned getBitsNeeded(StringRef str, uint8_t radix); + + /// The APInt version of the countLeadingZeros functions in + /// MathExtras.h. + /// + /// It counts the number of zeros from the most significant bit to the first + /// one bit. + /// + /// \returns BitWidth if the value is zero, otherwise returns the number of + /// zeros from the most significant bit to the first one bits. + unsigned countLeadingZeros() const { + if (isSingleWord()) { + unsigned unusedBits = APINT_BITS_PER_WORD - BitWidth; + return llvm::countLeadingZeros(U.VAL) - unusedBits; + } + return countLeadingZerosSlowCase(); + } + + /// Count the number of leading one bits. + /// + /// This function is an APInt version of the countLeadingOnes + /// functions in MathExtras.h. It counts the number of ones from the most + /// significant bit to the first zero bit. + /// + /// \returns 0 if the high order bit is not set, otherwise returns the number + /// of 1 bits from the most significant to the least + unsigned countLeadingOnes() const { + if (isSingleWord()) + return llvm::countLeadingOnes(U.VAL << (APINT_BITS_PER_WORD - BitWidth)); + return countLeadingOnesSlowCase(); + } + + /// Computes the number of leading bits of this APInt that are equal to its + /// sign bit. + unsigned getNumSignBits() const { + return isNegative() ? countLeadingOnes() : countLeadingZeros(); + } + + /// Count the number of trailing zero bits. + /// + /// This function is an APInt version of the countTrailingZeros + /// functions in MathExtras.h. It counts the number of zeros from the least + /// significant bit to the first set bit. + /// + /// \returns BitWidth if the value is zero, otherwise returns the number of + /// zeros from the least significant bit to the first one bit. + unsigned countTrailingZeros() const { + if (isSingleWord()) + return std::min(unsigned(llvm::countTrailingZeros(U.VAL)), BitWidth); + return countTrailingZerosSlowCase(); + } + + /// Count the number of trailing one bits. + /// + /// This function is an APInt version of the countTrailingOnes + /// functions in MathExtras.h. It counts the number of ones from the least + /// significant bit to the first zero bit. + /// + /// \returns BitWidth if the value is all ones, otherwise returns the number + /// of ones from the least significant bit to the first zero bit. + unsigned countTrailingOnes() const { + if (isSingleWord()) + return llvm::countTrailingOnes(U.VAL); + return countTrailingOnesSlowCase(); + } + + /// Count the number of bits set. + /// + /// This function is an APInt version of the countPopulation functions + /// in MathExtras.h. It counts the number of 1 bits in the APInt value. + /// + /// \returns 0 if the value is zero, otherwise returns the number of set bits. + unsigned countPopulation() const { + if (isSingleWord()) + return llvm::countPopulation(U.VAL); + return countPopulationSlowCase(); + } + + /// @} + /// \name Conversion Functions + /// @{ + void print(raw_ostream &OS, bool isSigned) const; + + /// Converts an APInt to a string and append it to Str. Str is commonly a + /// SmallString. + void toString(SmallVectorImpl<char> &Str, unsigned Radix, bool Signed, + bool formatAsCLiteral = false) const; + + /// Considers the APInt to be unsigned and converts it into a string in the + /// radix given. The radix can be 2, 8, 10 16, or 36. + void toStringUnsigned(SmallVectorImpl<char> &Str, unsigned Radix = 10) const { + toString(Str, Radix, false, false); + } + + /// Considers the APInt to be signed and converts it into a string in the + /// radix given. The radix can be 2, 8, 10, 16, or 36. + void toStringSigned(SmallVectorImpl<char> &Str, unsigned Radix = 10) const { + toString(Str, Radix, true, false); + } + + /// Return the APInt as a std::string. + /// + /// Note that this is an inefficient method. It is better to pass in a + /// SmallVector/SmallString to the methods above to avoid thrashing the heap + /// for the string. + std::string toString(unsigned Radix, bool Signed) const; + + /// \returns a byte-swapped representation of this APInt Value. + APInt byteSwap() const; + + /// \returns the value with the bit representation reversed of this APInt + /// Value. + APInt reverseBits() const; + + /// Converts this APInt to a double value. + double roundToDouble(bool isSigned) const; + + /// Converts this unsigned APInt to a double value. + double roundToDouble() const { return roundToDouble(false); } + + /// Converts this signed APInt to a double value. + double signedRoundToDouble() const { return roundToDouble(true); } + + /// Converts APInt bits to a double + /// + /// The conversion does not do a translation from integer to double, it just + /// re-interprets the bits as a double. Note that it is valid to do this on + /// any bit width. Exactly 64 bits will be translated. + double bitsToDouble() const { + return BitsToDouble(getWord(0)); + } + + /// Converts APInt bits to a float + /// + /// The conversion does not do a translation from integer to float, it just + /// re-interprets the bits as a float. Note that it is valid to do this on + /// any bit width. Exactly 32 bits will be translated. + float bitsToFloat() const { + return BitsToFloat(static_cast<uint32_t>(getWord(0))); + } + + /// Converts a double to APInt bits. + /// + /// The conversion does not do a translation from double to integer, it just + /// re-interprets the bits of the double. + static APInt doubleToBits(double V) { + return APInt(sizeof(double) * CHAR_BIT, DoubleToBits(V)); + } + + /// Converts a float to APInt bits. + /// + /// The conversion does not do a translation from float to integer, it just + /// re-interprets the bits of the float. + static APInt floatToBits(float V) { + return APInt(sizeof(float) * CHAR_BIT, FloatToBits(V)); + } + + /// @} + /// \name Mathematics Operations + /// @{ + + /// \returns the floor log base 2 of this APInt. + unsigned logBase2() const { return getActiveBits() - 1; } + + /// \returns the ceil log base 2 of this APInt. + unsigned ceilLogBase2() const { + APInt temp(*this); + --temp; + return temp.getActiveBits(); + } + + /// \returns the nearest log base 2 of this APInt. Ties round up. + /// + /// NOTE: When we have a BitWidth of 1, we define: + /// + /// log2(0) = UINT32_MAX + /// log2(1) = 0 + /// + /// to get around any mathematical concerns resulting from + /// referencing 2 in a space where 2 does no exist. + unsigned nearestLogBase2() const { + // Special case when we have a bitwidth of 1. If VAL is 1, then we + // get 0. If VAL is 0, we get WORDTYPE_MAX which gets truncated to + // UINT32_MAX. + if (BitWidth == 1) + return U.VAL - 1; + + // Handle the zero case. + if (isNullValue()) + return UINT32_MAX; + + // The non-zero case is handled by computing: + // + // nearestLogBase2(x) = logBase2(x) + x[logBase2(x)-1]. + // + // where x[i] is referring to the value of the ith bit of x. + unsigned lg = logBase2(); + return lg + unsigned((*this)[lg - 1]); + } + + /// \returns the log base 2 of this APInt if its an exact power of two, -1 + /// otherwise + int32_t exactLogBase2() const { + if (!isPowerOf2()) + return -1; + return logBase2(); + } + + /// Compute the square root + APInt sqrt() const; + + /// Get the absolute value; + /// + /// If *this is < 0 then return -(*this), otherwise *this; + APInt abs() const { + if (isNegative()) + return -(*this); + return *this; + } + + /// \returns the multiplicative inverse for a given modulo. + APInt multiplicativeInverse(const APInt &modulo) const; + + /// @} + /// \name Support for division by constant + /// @{ + + /// Calculate the magic number for signed division by a constant. + struct ms; + ms magic() const; + + /// Calculate the magic number for unsigned division by a constant. + struct mu; + mu magicu(unsigned LeadingZeros = 0) const; + + /// @} + /// \name Building-block Operations for APInt and APFloat + /// @{ + + // These building block operations operate on a representation of arbitrary + // precision, two's-complement, bignum integer values. They should be + // sufficient to implement APInt and APFloat bignum requirements. Inputs are + // generally a pointer to the base of an array of integer parts, representing + // an unsigned bignum, and a count of how many parts there are. + + /// Sets the least significant part of a bignum to the input value, and zeroes + /// out higher parts. + static void tcSet(WordType *, WordType, unsigned); + + /// Assign one bignum to another. + static void tcAssign(WordType *, const WordType *, unsigned); + + /// Returns true if a bignum is zero, false otherwise. + static bool tcIsZero(const WordType *, unsigned); + + /// Extract the given bit of a bignum; returns 0 or 1. Zero-based. + static int tcExtractBit(const WordType *, unsigned bit); + + /// Copy the bit vector of width srcBITS from SRC, starting at bit srcLSB, to + /// DST, of dstCOUNT parts, such that the bit srcLSB becomes the least + /// significant bit of DST. All high bits above srcBITS in DST are + /// zero-filled. + static void tcExtract(WordType *, unsigned dstCount, + const WordType *, unsigned srcBits, + unsigned srcLSB); + + /// Set the given bit of a bignum. Zero-based. + static void tcSetBit(WordType *, unsigned bit); + + /// Clear the given bit of a bignum. Zero-based. + static void tcClearBit(WordType *, unsigned bit); + + /// Returns the bit number of the least or most significant set bit of a + /// number. If the input number has no bits set -1U is returned. + static unsigned tcLSB(const WordType *, unsigned n); + static unsigned tcMSB(const WordType *parts, unsigned n); + + /// Negate a bignum in-place. + static void tcNegate(WordType *, unsigned); + + /// DST += RHS + CARRY where CARRY is zero or one. Returns the carry flag. + static WordType tcAdd(WordType *, const WordType *, + WordType carry, unsigned); + /// DST += RHS. Returns the carry flag. + static WordType tcAddPart(WordType *, WordType, unsigned); + + /// DST -= RHS + CARRY where CARRY is zero or one. Returns the carry flag. + static WordType tcSubtract(WordType *, const WordType *, + WordType carry, unsigned); + /// DST -= RHS. Returns the carry flag. + static WordType tcSubtractPart(WordType *, WordType, unsigned); + + /// DST += SRC * MULTIPLIER + PART if add is true + /// DST = SRC * MULTIPLIER + PART if add is false + /// + /// Requires 0 <= DSTPARTS <= SRCPARTS + 1. If DST overlaps SRC they must + /// start at the same point, i.e. DST == SRC. + /// + /// If DSTPARTS == SRC_PARTS + 1 no overflow occurs and zero is returned. + /// Otherwise DST is filled with the least significant DSTPARTS parts of the + /// result, and if all of the omitted higher parts were zero return zero, + /// otherwise overflow occurred and return one. + static int tcMultiplyPart(WordType *dst, const WordType *src, + WordType multiplier, WordType carry, + unsigned srcParts, unsigned dstParts, + bool add); + + /// DST = LHS * RHS, where DST has the same width as the operands and is + /// filled with the least significant parts of the result. Returns one if + /// overflow occurred, otherwise zero. DST must be disjoint from both + /// operands. + static int tcMultiply(WordType *, const WordType *, const WordType *, + unsigned); + + /// DST = LHS * RHS, where DST has width the sum of the widths of the + /// operands. No overflow occurs. DST must be disjoint from both operands. + static void tcFullMultiply(WordType *, const WordType *, + const WordType *, unsigned, unsigned); + + /// If RHS is zero LHS and REMAINDER are left unchanged, return one. + /// Otherwise set LHS to LHS / RHS with the fractional part discarded, set + /// REMAINDER to the remainder, return zero. i.e. + /// + /// OLD_LHS = RHS * LHS + REMAINDER + /// + /// SCRATCH is a bignum of the same size as the operands and result for use by + /// the routine; its contents need not be initialized and are destroyed. LHS, + /// REMAINDER and SCRATCH must be distinct. + static int tcDivide(WordType *lhs, const WordType *rhs, + WordType *remainder, WordType *scratch, + unsigned parts); + + /// Shift a bignum left Count bits. Shifted in bits are zero. There are no + /// restrictions on Count. + static void tcShiftLeft(WordType *, unsigned Words, unsigned Count); + + /// Shift a bignum right Count bits. Shifted in bits are zero. There are no + /// restrictions on Count. + static void tcShiftRight(WordType *, unsigned Words, unsigned Count); + + /// The obvious AND, OR and XOR and complement operations. + static void tcAnd(WordType *, const WordType *, unsigned); + static void tcOr(WordType *, const WordType *, unsigned); + static void tcXor(WordType *, const WordType *, unsigned); + static void tcComplement(WordType *, unsigned); + + /// Comparison (unsigned) of two bignums. + static int tcCompare(const WordType *, const WordType *, unsigned); + + /// Increment a bignum in-place. Return the carry flag. + static WordType tcIncrement(WordType *dst, unsigned parts) { + return tcAddPart(dst, 1, parts); + } + + /// Decrement a bignum in-place. Return the borrow flag. + static WordType tcDecrement(WordType *dst, unsigned parts) { + return tcSubtractPart(dst, 1, parts); + } + + /// Set the least significant BITS and clear the rest. + static void tcSetLeastSignificantBits(WordType *, unsigned, unsigned bits); + + /// debug method + void dump() const; + + /// @} +}; + +/// Magic data for optimising signed division by a constant. +struct APInt::ms { + APInt m; ///< magic number + unsigned s; ///< shift amount +}; + +/// Magic data for optimising unsigned division by a constant. +struct APInt::mu { + APInt m; ///< magic number + bool a; ///< add indicator + unsigned s; ///< shift amount +}; + +inline bool operator==(uint64_t V1, const APInt &V2) { return V2 == V1; } + +inline bool operator!=(uint64_t V1, const APInt &V2) { return V2 != V1; } + +/// Unary bitwise complement operator. +/// +/// \returns an APInt that is the bitwise complement of \p v. +inline APInt operator~(APInt v) { + v.flipAllBits(); + return v; +} + +inline APInt operator&(APInt a, const APInt &b) { + a &= b; + return a; +} + +inline APInt operator&(const APInt &a, APInt &&b) { + b &= a; + return std::move(b); +} + +inline APInt operator&(APInt a, uint64_t RHS) { + a &= RHS; + return a; +} + +inline APInt operator&(uint64_t LHS, APInt b) { + b &= LHS; + return b; +} + +inline APInt operator|(APInt a, const APInt &b) { + a |= b; + return a; +} + +inline APInt operator|(const APInt &a, APInt &&b) { + b |= a; + return std::move(b); +} + +inline APInt operator|(APInt a, uint64_t RHS) { + a |= RHS; + return a; +} + +inline APInt operator|(uint64_t LHS, APInt b) { + b |= LHS; + return b; +} + +inline APInt operator^(APInt a, const APInt &b) { + a ^= b; + return a; +} + +inline APInt operator^(const APInt &a, APInt &&b) { + b ^= a; + return std::move(b); +} + +inline APInt operator^(APInt a, uint64_t RHS) { + a ^= RHS; + return a; +} + +inline APInt operator^(uint64_t LHS, APInt b) { + b ^= LHS; + return b; +} + +inline raw_ostream &operator<<(raw_ostream &OS, const APInt &I) { + I.print(OS, true); + return OS; +} + +inline APInt operator-(APInt v) { + v.negate(); + return v; +} + +inline APInt operator+(APInt a, const APInt &b) { + a += b; + return a; +} + +inline APInt operator+(const APInt &a, APInt &&b) { + b += a; + return std::move(b); +} + +inline APInt operator+(APInt a, uint64_t RHS) { + a += RHS; + return a; +} + +inline APInt operator+(uint64_t LHS, APInt b) { + b += LHS; + return b; +} + +inline APInt operator-(APInt a, const APInt &b) { + a -= b; + return a; +} + +inline APInt operator-(const APInt &a, APInt &&b) { + b.negate(); + b += a; + return std::move(b); +} + +inline APInt operator-(APInt a, uint64_t RHS) { + a -= RHS; + return a; +} + +inline APInt operator-(uint64_t LHS, APInt b) { + b.negate(); + b += LHS; + return b; +} + +inline APInt operator*(APInt a, uint64_t RHS) { + a *= RHS; + return a; +} + +inline APInt operator*(uint64_t LHS, APInt b) { + b *= LHS; + return b; +} + + +namespace APIntOps { + +/// Determine the smaller of two APInts considered to be signed. +inline const APInt &smin(const APInt &A, const APInt &B) { + return A.slt(B) ? A : B; +} + +/// Determine the larger of two APInts considered to be signed. +inline const APInt &smax(const APInt &A, const APInt &B) { + return A.sgt(B) ? A : B; +} + +/// Determine the smaller of two APInts considered to be signed. +inline const APInt &umin(const APInt &A, const APInt &B) { + return A.ult(B) ? A : B; +} + +/// Determine the larger of two APInts considered to be unsigned. +inline const APInt &umax(const APInt &A, const APInt &B) { + return A.ugt(B) ? A : B; +} + +/// Compute GCD of two unsigned APInt values. +/// +/// This function returns the greatest common divisor of the two APInt values +/// using Stein's algorithm. +/// +/// \returns the greatest common divisor of A and B. +APInt GreatestCommonDivisor(APInt A, APInt B); + +/// Converts the given APInt to a double value. +/// +/// Treats the APInt as an unsigned value for conversion purposes. +inline double RoundAPIntToDouble(const APInt &APIVal) { + return APIVal.roundToDouble(); +} + +/// Converts the given APInt to a double value. +/// +/// Treats the APInt as a signed value for conversion purposes. +inline double RoundSignedAPIntToDouble(const APInt &APIVal) { + return APIVal.signedRoundToDouble(); +} + +/// Converts the given APInt to a float vlalue. +inline float RoundAPIntToFloat(const APInt &APIVal) { + return float(RoundAPIntToDouble(APIVal)); +} + +/// Converts the given APInt to a float value. +/// +/// Treats the APInt as a signed value for conversion purposes. +inline float RoundSignedAPIntToFloat(const APInt &APIVal) { + return float(APIVal.signedRoundToDouble()); +} + +/// Converts the given double value into a APInt. +/// +/// This function convert a double value to an APInt value. +APInt RoundDoubleToAPInt(double Double, unsigned width); + +/// Converts a float value into a APInt. +/// +/// Converts a float value into an APInt value. +inline APInt RoundFloatToAPInt(float Float, unsigned width) { + return RoundDoubleToAPInt(double(Float), width); +} + +/// Return A unsign-divided by B, rounded by the given rounding mode. +APInt RoundingUDiv(const APInt &A, const APInt &B, APInt::Rounding RM); + +/// Return A sign-divided by B, rounded by the given rounding mode. +APInt RoundingSDiv(const APInt &A, const APInt &B, APInt::Rounding RM); + +/// Let q(n) = An^2 + Bn + C, and BW = bit width of the value range +/// (e.g. 32 for i32). +/// This function finds the smallest number n, such that +/// (a) n >= 0 and q(n) = 0, or +/// (b) n >= 1 and q(n-1) and q(n), when evaluated in the set of all +/// integers, belong to two different intervals [Rk, Rk+R), +/// where R = 2^BW, and k is an integer. +/// The idea here is to find when q(n) "overflows" 2^BW, while at the +/// same time "allowing" subtraction. In unsigned modulo arithmetic a +/// subtraction (treated as addition of negated numbers) would always +/// count as an overflow, but here we want to allow values to decrease +/// and increase as long as they are within the same interval. +/// Specifically, adding of two negative numbers should not cause an +/// overflow (as long as the magnitude does not exceed the bit width). +/// On the other hand, given a positive number, adding a negative +/// number to it can give a negative result, which would cause the +/// value to go from [-2^BW, 0) to [0, 2^BW). In that sense, zero is +/// treated as a special case of an overflow. +/// +/// This function returns None if after finding k that minimizes the +/// positive solution to q(n) = kR, both solutions are contained between +/// two consecutive integers. +/// +/// There are cases where q(n) > T, and q(n+1) < T (assuming evaluation +/// in arithmetic modulo 2^BW, and treating the values as signed) by the +/// virtue of *signed* overflow. This function will *not* find such an n, +/// however it may find a value of n satisfying the inequalities due to +/// an *unsigned* overflow (if the values are treated as unsigned). +/// To find a solution for a signed overflow, treat it as a problem of +/// finding an unsigned overflow with a range with of BW-1. +/// +/// The returned value may have a different bit width from the input +/// coefficients. +Optional<APInt> SolveQuadraticEquationWrap(APInt A, APInt B, APInt C, + unsigned RangeWidth); + +/// Compare two values, and if they are different, return the position of the +/// most significant bit that is different in the values. +Optional<unsigned> GetMostSignificantDifferentBit(const APInt &A, + const APInt &B); + +} // End of APIntOps namespace + +// See friend declaration above. This additional declaration is required in +// order to compile LLVM with IBM xlC compiler. +hash_code hash_value(const APInt &Arg); + +/// StoreIntToMemory - Fills the StoreBytes bytes of memory starting from Dst +/// with the integer held in IntVal. +void StoreIntToMemory(const APInt &IntVal, uint8_t *Dst, unsigned StoreBytes); + +/// LoadIntFromMemory - Loads the integer stored in the LoadBytes bytes starting +/// from Src into IntVal, which is assumed to be wide enough and to hold zero. +void LoadIntFromMemory(APInt &IntVal, uint8_t *Src, unsigned LoadBytes); + +} // namespace llvm + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/APSInt.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/APSInt.h new file mode 100644 index 0000000..0f99182 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/APSInt.h
@@ -0,0 +1,353 @@ +//===-- llvm/ADT/APSInt.h - Arbitrary Precision Signed Int -----*- C++ -*--===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the APSInt class, which is a simple class that +// represents an arbitrary sized integer that knows its signedness. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_APSINT_H +#define LLVM_ADT_APSINT_H + +#include "llvm/ADT/APInt.h" + +namespace llvm { + +class LLVM_NODISCARD APSInt : public APInt { + bool IsUnsigned; + +public: + /// Default constructor that creates an uninitialized APInt. + explicit APSInt() : IsUnsigned(false) {} + + /// APSInt ctor - Create an APSInt with the specified width, default to + /// unsigned. + explicit APSInt(uint32_t BitWidth, bool isUnsigned = true) + : APInt(BitWidth, 0), IsUnsigned(isUnsigned) {} + + explicit APSInt(APInt I, bool isUnsigned = true) + : APInt(std::move(I)), IsUnsigned(isUnsigned) {} + + /// Construct an APSInt from a string representation. + /// + /// This constructor interprets the string \p Str using the radix of 10. + /// The interpretation stops at the end of the string. The bit width of the + /// constructed APSInt is determined automatically. + /// + /// \param Str the string to be interpreted. + explicit APSInt(StringRef Str); + + /// Determine sign of this APSInt. + /// + /// \returns true if this APSInt is negative, false otherwise + bool isNegative() const { return isSigned() && APInt::isNegative(); } + + /// Determine if this APSInt Value is non-negative (>= 0) + /// + /// \returns true if this APSInt is non-negative, false otherwise + bool isNonNegative() const { return !isNegative(); } + + /// Determine if this APSInt Value is positive. + /// + /// This tests if the value of this APSInt is positive (> 0). Note + /// that 0 is not a positive value. + /// + /// \returns true if this APSInt is positive. + bool isStrictlyPositive() const { return isNonNegative() && !isNullValue(); } + + APSInt &operator=(APInt RHS) { + // Retain our current sign. + APInt::operator=(std::move(RHS)); + return *this; + } + + APSInt &operator=(uint64_t RHS) { + // Retain our current sign. + APInt::operator=(RHS); + return *this; + } + + // Query sign information. + bool isSigned() const { return !IsUnsigned; } + bool isUnsigned() const { return IsUnsigned; } + void setIsUnsigned(bool Val) { IsUnsigned = Val; } + void setIsSigned(bool Val) { IsUnsigned = !Val; } + + /// toString - Append this APSInt to the specified SmallString. + void toString(SmallVectorImpl<char> &Str, unsigned Radix = 10) const { + APInt::toString(Str, Radix, isSigned()); + } + /// toString - Converts an APInt to a std::string. This is an inefficient + /// method; you should prefer passing in a SmallString instead. + std::string toString(unsigned Radix) const { + return APInt::toString(Radix, isSigned()); + } + using APInt::toString; + + /// Get the correctly-extended \c int64_t value. + int64_t getExtValue() const { + assert(getMinSignedBits() <= 64 && "Too many bits for int64_t"); + return isSigned() ? getSExtValue() : getZExtValue(); + } + + APSInt trunc(uint32_t width) const { + return APSInt(APInt::trunc(width), IsUnsigned); + } + + APSInt extend(uint32_t width) const { + if (IsUnsigned) + return APSInt(zext(width), IsUnsigned); + else + return APSInt(sext(width), IsUnsigned); + } + + APSInt extOrTrunc(uint32_t width) const { + if (IsUnsigned) + return APSInt(zextOrTrunc(width), IsUnsigned); + else + return APSInt(sextOrTrunc(width), IsUnsigned); + } + + const APSInt &operator%=(const APSInt &RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + if (IsUnsigned) + *this = urem(RHS); + else + *this = srem(RHS); + return *this; + } + const APSInt &operator/=(const APSInt &RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + if (IsUnsigned) + *this = udiv(RHS); + else + *this = sdiv(RHS); + return *this; + } + APSInt operator%(const APSInt &RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return IsUnsigned ? APSInt(urem(RHS), true) : APSInt(srem(RHS), false); + } + APSInt operator/(const APSInt &RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return IsUnsigned ? APSInt(udiv(RHS), true) : APSInt(sdiv(RHS), false); + } + + APSInt operator>>(unsigned Amt) const { + return IsUnsigned ? APSInt(lshr(Amt), true) : APSInt(ashr(Amt), false); + } + APSInt& operator>>=(unsigned Amt) { + if (IsUnsigned) + lshrInPlace(Amt); + else + ashrInPlace(Amt); + return *this; + } + + inline bool operator<(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return IsUnsigned ? ult(RHS) : slt(RHS); + } + inline bool operator>(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return IsUnsigned ? ugt(RHS) : sgt(RHS); + } + inline bool operator<=(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return IsUnsigned ? ule(RHS) : sle(RHS); + } + inline bool operator>=(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return IsUnsigned ? uge(RHS) : sge(RHS); + } + inline bool operator==(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return eq(RHS); + } + inline bool operator!=(const APSInt& RHS) const { + return !((*this) == RHS); + } + + bool operator==(int64_t RHS) const { + return compareValues(*this, get(RHS)) == 0; + } + bool operator!=(int64_t RHS) const { + return compareValues(*this, get(RHS)) != 0; + } + bool operator<=(int64_t RHS) const { + return compareValues(*this, get(RHS)) <= 0; + } + bool operator>=(int64_t RHS) const { + return compareValues(*this, get(RHS)) >= 0; + } + bool operator<(int64_t RHS) const { + return compareValues(*this, get(RHS)) < 0; + } + bool operator>(int64_t RHS) const { + return compareValues(*this, get(RHS)) > 0; + } + + // The remaining operators just wrap the logic of APInt, but retain the + // signedness information. + + APSInt operator<<(unsigned Bits) const { + return APSInt(static_cast<const APInt&>(*this) << Bits, IsUnsigned); + } + APSInt& operator<<=(unsigned Amt) { + static_cast<APInt&>(*this) <<= Amt; + return *this; + } + + APSInt& operator++() { + ++(static_cast<APInt&>(*this)); + return *this; + } + APSInt& operator--() { + --(static_cast<APInt&>(*this)); + return *this; + } + APSInt operator++(int) { + return APSInt(++static_cast<APInt&>(*this), IsUnsigned); + } + APSInt operator--(int) { + return APSInt(--static_cast<APInt&>(*this), IsUnsigned); + } + APSInt operator-() const { + return APSInt(-static_cast<const APInt&>(*this), IsUnsigned); + } + APSInt& operator+=(const APSInt& RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + static_cast<APInt&>(*this) += RHS; + return *this; + } + APSInt& operator-=(const APSInt& RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + static_cast<APInt&>(*this) -= RHS; + return *this; + } + APSInt& operator*=(const APSInt& RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + static_cast<APInt&>(*this) *= RHS; + return *this; + } + APSInt& operator&=(const APSInt& RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + static_cast<APInt&>(*this) &= RHS; + return *this; + } + APSInt& operator|=(const APSInt& RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + static_cast<APInt&>(*this) |= RHS; + return *this; + } + APSInt& operator^=(const APSInt& RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + static_cast<APInt&>(*this) ^= RHS; + return *this; + } + + APSInt operator&(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return APSInt(static_cast<const APInt&>(*this) & RHS, IsUnsigned); + } + + APSInt operator|(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return APSInt(static_cast<const APInt&>(*this) | RHS, IsUnsigned); + } + + APSInt operator^(const APSInt &RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return APSInt(static_cast<const APInt&>(*this) ^ RHS, IsUnsigned); + } + + APSInt operator*(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return APSInt(static_cast<const APInt&>(*this) * RHS, IsUnsigned); + } + APSInt operator+(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return APSInt(static_cast<const APInt&>(*this) + RHS, IsUnsigned); + } + APSInt operator-(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return APSInt(static_cast<const APInt&>(*this) - RHS, IsUnsigned); + } + APSInt operator~() const { + return APSInt(~static_cast<const APInt&>(*this), IsUnsigned); + } + + /// getMaxValue - Return the APSInt representing the maximum integer value + /// with the given bit width and signedness. + static APSInt getMaxValue(uint32_t numBits, bool Unsigned) { + return APSInt(Unsigned ? APInt::getMaxValue(numBits) + : APInt::getSignedMaxValue(numBits), Unsigned); + } + + /// getMinValue - Return the APSInt representing the minimum integer value + /// with the given bit width and signedness. + static APSInt getMinValue(uint32_t numBits, bool Unsigned) { + return APSInt(Unsigned ? APInt::getMinValue(numBits) + : APInt::getSignedMinValue(numBits), Unsigned); + } + + /// Determine if two APSInts have the same value, zero- or + /// sign-extending as needed. + static bool isSameValue(const APSInt &I1, const APSInt &I2) { + return !compareValues(I1, I2); + } + + /// Compare underlying values of two numbers. + static int compareValues(const APSInt &I1, const APSInt &I2) { + if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned()) + return I1.IsUnsigned ? I1.compare(I2) : I1.compareSigned(I2); + + // Check for a bit-width mismatch. + if (I1.getBitWidth() > I2.getBitWidth()) + return compareValues(I1, I2.extend(I1.getBitWidth())); + if (I2.getBitWidth() > I1.getBitWidth()) + return compareValues(I1.extend(I2.getBitWidth()), I2); + + // We have a signedness mismatch. Check for negative values and do an + // unsigned compare if both are positive. + if (I1.isSigned()) { + assert(!I2.isSigned() && "Expected signed mismatch"); + if (I1.isNegative()) + return -1; + } else { + assert(I2.isSigned() && "Expected signed mismatch"); + if (I2.isNegative()) + return 1; + } + + return I1.compare(I2); + } + + static APSInt get(int64_t X) { return APSInt(APInt(64, X), false); } + static APSInt getUnsigned(uint64_t X) { return APSInt(APInt(64, X), true); } + + /// Profile - Used to insert APSInt objects, or objects that contain APSInt + /// objects, into FoldingSets. + void Profile(FoldingSetNodeID& ID) const; +}; + +inline bool operator==(int64_t V1, const APSInt &V2) { return V2 == V1; } +inline bool operator!=(int64_t V1, const APSInt &V2) { return V2 != V1; } +inline bool operator<=(int64_t V1, const APSInt &V2) { return V2 >= V1; } +inline bool operator>=(int64_t V1, const APSInt &V2) { return V2 <= V1; } +inline bool operator<(int64_t V1, const APSInt &V2) { return V2 > V1; } +inline bool operator>(int64_t V1, const APSInt &V2) { return V2 < V1; } + +inline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) { + I.print(OS, I.isSigned()); + return OS; +} + +} // end namespace llvm + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/AllocatorList.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/AllocatorList.h new file mode 100644 index 0000000..405a2e4 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/AllocatorList.h
@@ -0,0 +1,240 @@ +//===- llvm/ADT/AllocatorList.h - Custom allocator list ---------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ALLOCATORLIST_H +#define LLVM_ADT_ALLOCATORLIST_H + +#include "llvm/ADT/ilist_node.h" +#include "llvm/ADT/iterator.h" +#include "llvm/ADT/simple_ilist.h" +#include "llvm/Support/Allocator.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <iterator> +#include <type_traits> +#include <utility> + +namespace llvm { + +/// A linked-list with a custom, local allocator. +/// +/// Expose a std::list-like interface that owns and uses a custom LLVM-style +/// allocator (e.g., BumpPtrAllocator), leveraging \a simple_ilist for the +/// implementation details. +/// +/// Because this list owns the allocator, calling \a splice() with a different +/// list isn't generally safe. As such, \a splice has been left out of the +/// interface entirely. +template <class T, class AllocatorT> class AllocatorList : AllocatorT { + struct Node : ilist_node<Node> { + Node(Node &&) = delete; + Node(const Node &) = delete; + Node &operator=(Node &&) = delete; + Node &operator=(const Node &) = delete; + + Node(T &&V) : V(std::move(V)) {} + Node(const T &V) : V(V) {} + template <class... Ts> Node(Ts &&... Vs) : V(std::forward<Ts>(Vs)...) {} + T V; + }; + + using list_type = simple_ilist<Node>; + + list_type List; + + AllocatorT &getAlloc() { return *this; } + const AllocatorT &getAlloc() const { return *this; } + + template <class... ArgTs> Node *create(ArgTs &&... Args) { + return new (getAlloc()) Node(std::forward<ArgTs>(Args)...); + } + + struct Cloner { + AllocatorList &AL; + + Cloner(AllocatorList &AL) : AL(AL) {} + + Node *operator()(const Node &N) const { return AL.create(N.V); } + }; + + struct Disposer { + AllocatorList &AL; + + Disposer(AllocatorList &AL) : AL(AL) {} + + void operator()(Node *N) const { + N->~Node(); + AL.getAlloc().Deallocate(N); + } + }; + +public: + using value_type = T; + using pointer = T *; + using reference = T &; + using const_pointer = const T *; + using const_reference = const T &; + using size_type = typename list_type::size_type; + using difference_type = typename list_type::difference_type; + +private: + template <class ValueT, class IteratorBase> + class IteratorImpl + : public iterator_adaptor_base<IteratorImpl<ValueT, IteratorBase>, + IteratorBase, + std::bidirectional_iterator_tag, ValueT> { + template <class OtherValueT, class OtherIteratorBase> + friend class IteratorImpl; + friend AllocatorList; + + using base_type = + iterator_adaptor_base<IteratorImpl<ValueT, IteratorBase>, IteratorBase, + std::bidirectional_iterator_tag, ValueT>; + + public: + using value_type = ValueT; + using pointer = ValueT *; + using reference = ValueT &; + + IteratorImpl() = default; + IteratorImpl(const IteratorImpl &) = default; + IteratorImpl &operator=(const IteratorImpl &) = default; + + explicit IteratorImpl(const IteratorBase &I) : base_type(I) {} + + template <class OtherValueT, class OtherIteratorBase> + IteratorImpl(const IteratorImpl<OtherValueT, OtherIteratorBase> &X, + typename std::enable_if<std::is_convertible< + OtherIteratorBase, IteratorBase>::value>::type * = nullptr) + : base_type(X.wrapped()) {} + + ~IteratorImpl() = default; + + reference operator*() const { return base_type::wrapped()->V; } + pointer operator->() const { return &operator*(); } + + friend bool operator==(const IteratorImpl &L, const IteratorImpl &R) { + return L.wrapped() == R.wrapped(); + } + friend bool operator!=(const IteratorImpl &L, const IteratorImpl &R) { + return !(L == R); + } + }; + +public: + using iterator = IteratorImpl<T, typename list_type::iterator>; + using reverse_iterator = + IteratorImpl<T, typename list_type::reverse_iterator>; + using const_iterator = + IteratorImpl<const T, typename list_type::const_iterator>; + using const_reverse_iterator = + IteratorImpl<const T, typename list_type::const_reverse_iterator>; + + AllocatorList() = default; + AllocatorList(AllocatorList &&X) + : AllocatorT(std::move(X.getAlloc())), List(std::move(X.List)) {} + + AllocatorList(const AllocatorList &X) { + List.cloneFrom(X.List, Cloner(*this), Disposer(*this)); + } + + AllocatorList &operator=(AllocatorList &&X) { + clear(); // Dispose of current nodes explicitly. + List = std::move(X.List); + getAlloc() = std::move(X.getAlloc()); + return *this; + } + + AllocatorList &operator=(const AllocatorList &X) { + List.cloneFrom(X.List, Cloner(*this), Disposer(*this)); + return *this; + } + + ~AllocatorList() { clear(); } + + void swap(AllocatorList &RHS) { + List.swap(RHS.List); + std::swap(getAlloc(), RHS.getAlloc()); + } + + bool empty() { return List.empty(); } + size_t size() { return List.size(); } + + iterator begin() { return iterator(List.begin()); } + iterator end() { return iterator(List.end()); } + const_iterator begin() const { return const_iterator(List.begin()); } + const_iterator end() const { return const_iterator(List.end()); } + reverse_iterator rbegin() { return reverse_iterator(List.rbegin()); } + reverse_iterator rend() { return reverse_iterator(List.rend()); } + const_reverse_iterator rbegin() const { + return const_reverse_iterator(List.rbegin()); + } + const_reverse_iterator rend() const { + return const_reverse_iterator(List.rend()); + } + + T &back() { return List.back().V; } + T &front() { return List.front().V; } + const T &back() const { return List.back().V; } + const T &front() const { return List.front().V; } + + template <class... Ts> iterator emplace(iterator I, Ts &&... Vs) { + return iterator(List.insert(I.wrapped(), *create(std::forward<Ts>(Vs)...))); + } + + iterator insert(iterator I, T &&V) { + return iterator(List.insert(I.wrapped(), *create(std::move(V)))); + } + iterator insert(iterator I, const T &V) { + return iterator(List.insert(I.wrapped(), *create(V))); + } + + template <class Iterator> + void insert(iterator I, Iterator First, Iterator Last) { + for (; First != Last; ++First) + List.insert(I.wrapped(), *create(*First)); + } + + iterator erase(iterator I) { + return iterator(List.eraseAndDispose(I.wrapped(), Disposer(*this))); + } + + iterator erase(iterator First, iterator Last) { + return iterator( + List.eraseAndDispose(First.wrapped(), Last.wrapped(), Disposer(*this))); + } + + void clear() { List.clearAndDispose(Disposer(*this)); } + void pop_back() { List.eraseAndDispose(--List.end(), Disposer(*this)); } + void pop_front() { List.eraseAndDispose(List.begin(), Disposer(*this)); } + void push_back(T &&V) { insert(end(), std::move(V)); } + void push_front(T &&V) { insert(begin(), std::move(V)); } + void push_back(const T &V) { insert(end(), V); } + void push_front(const T &V) { insert(begin(), V); } + template <class... Ts> void emplace_back(Ts &&... Vs) { + emplace(end(), std::forward<Ts>(Vs)...); + } + template <class... Ts> void emplace_front(Ts &&... Vs) { + emplace(begin(), std::forward<Ts>(Vs)...); + } + + /// Reset the underlying allocator. + /// + /// \pre \c empty() + void resetAlloc() { + assert(empty() && "Cannot reset allocator if not empty"); + getAlloc().Reset(); + } +}; + +template <class T> using BumpPtrList = AllocatorList<T, BumpPtrAllocator>; + +} // end namespace llvm + +#endif // LLVM_ADT_ALLOCATORLIST_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/Any.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/Any.h new file mode 100644 index 0000000..49657e0 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/Any.h
@@ -0,0 +1,159 @@ +//===- Any.h - Generic type erased holder of any type -----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file provides Any, a non-template class modeled in the spirit of +// std::any. The idea is to provide a type-safe replacement for C's void*. +// It can hold a value of any copy-constructible copy-assignable type +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ANY_H +#define LLVM_ADT_ANY_H + +#include "llvm/ADT/STLExtras.h" + +#include <cassert> +#include <memory> +#include <type_traits> + +namespace llvm { + +class Any { + template <typename T> struct TypeId { static const char Id; }; + + struct StorageBase { + virtual ~StorageBase() = default; + virtual std::unique_ptr<StorageBase> clone() const = 0; + virtual const void *id() const = 0; + }; + + template <typename T> struct StorageImpl : public StorageBase { + explicit StorageImpl(const T &Value) : Value(Value) {} + + explicit StorageImpl(T &&Value) : Value(std::move(Value)) {} + + std::unique_ptr<StorageBase> clone() const override { + return std::make_unique<StorageImpl<T>>(Value); + } + + const void *id() const override { return &TypeId<T>::Id; } + + T Value; + + private: + StorageImpl &operator=(const StorageImpl &Other) = delete; + StorageImpl(const StorageImpl &Other) = delete; + }; + +public: + Any() = default; + + Any(const Any &Other) + : Storage(Other.Storage ? Other.Storage->clone() : nullptr) {} + + // When T is Any or T is not copy-constructible we need to explicitly disable + // the forwarding constructor so that the copy constructor gets selected + // instead. + template < + typename T, + typename std::enable_if< + llvm::conjunction< + llvm::negation<std::is_same<typename std::decay<T>::type, Any>>, + // We also disable this overload when an `Any` object can be + // converted to the parameter type because in that case, this + // constructor may combine with that conversion during overload + // resolution for determining copy constructibility, and then + // when we try to determine copy constructibility below we may + // infinitely recurse. This is being evaluated by the standards + // committee as a potential DR in `std::any` as well, but we're + // going ahead and adopting it to work-around usage of `Any` with + // types that need to be implicitly convertible from an `Any`. + llvm::negation<std::is_convertible<Any, typename std::decay<T>::type>>, + std::is_copy_constructible<typename std::decay<T>::type>>::value, + int>::type = 0> + Any(T &&Value) { + using U = typename std::decay<T>::type; + Storage = std::make_unique<StorageImpl<U>>(std::forward<T>(Value)); + } + + Any(Any &&Other) : Storage(std::move(Other.Storage)) {} + + Any &swap(Any &Other) { + std::swap(Storage, Other.Storage); + return *this; + } + + Any &operator=(Any Other) { + Storage = std::move(Other.Storage); + return *this; + } + + bool hasValue() const { return !!Storage; } + + void reset() { Storage.reset(); } + +private: + template <class T> friend T any_cast(const Any &Value); + template <class T> friend T any_cast(Any &Value); + template <class T> friend T any_cast(Any &&Value); + template <class T> friend const T *any_cast(const Any *Value); + template <class T> friend T *any_cast(Any *Value); + template <typename T> friend bool any_isa(const Any &Value); + + std::unique_ptr<StorageBase> Storage; +}; + +template <typename T> const char Any::TypeId<T>::Id = 0; + + +template <typename T> bool any_isa(const Any &Value) { + if (!Value.Storage) + return false; + using U = + typename std::remove_cv<typename std::remove_reference<T>::type>::type; + return Value.Storage->id() == &Any::TypeId<U>::Id; +} + +template <class T> T any_cast(const Any &Value) { + using U = + typename std::remove_cv<typename std::remove_reference<T>::type>::type; + return static_cast<T>(*any_cast<U>(&Value)); +} + +template <class T> T any_cast(Any &Value) { + using U = + typename std::remove_cv<typename std::remove_reference<T>::type>::type; + return static_cast<T>(*any_cast<U>(&Value)); +} + +template <class T> T any_cast(Any &&Value) { + using U = + typename std::remove_cv<typename std::remove_reference<T>::type>::type; + return static_cast<T>(std::move(*any_cast<U>(&Value))); +} + +template <class T> const T *any_cast(const Any *Value) { + using U = + typename std::remove_cv<typename std::remove_reference<T>::type>::type; + assert(Value && any_isa<T>(*Value) && "Bad any cast!"); + if (!Value || !any_isa<U>(*Value)) + return nullptr; + return &static_cast<Any::StorageImpl<U> &>(*Value->Storage).Value; +} + +template <class T> T *any_cast(Any *Value) { + using U = typename std::decay<T>::type; + assert(Value && any_isa<U>(*Value) && "Bad any cast!"); + if (!Value || !any_isa<U>(*Value)) + return nullptr; + return &static_cast<Any::StorageImpl<U> &>(*Value->Storage).Value; +} + +} // end namespace llvm + +#endif // LLVM_ADT_ANY_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/ArrayRef.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/ArrayRef.h new file mode 100644 index 0000000..3d22442 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/ArrayRef.h
@@ -0,0 +1,550 @@ +//===- ArrayRef.h - Array Reference Wrapper ---------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ARRAYREF_H +#define LLVM_ADT_ARRAYREF_H + +#include "llvm/ADT/Hashing.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Compiler.h" +#include <algorithm> +#include <array> +#include <cassert> +#include <cstddef> +#include <initializer_list> +#include <iterator> +#include <memory> +#include <type_traits> +#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. + /// + /// This class does not own the underlying data, it is expected to be used in + /// situations where the data resides in some other buffer, whose lifetime + /// extends past that of the ArrayRef. For this reason, it is not in general + /// safe to store an ArrayRef. + /// + /// This is intended to be trivially copyable, so it should be passed by + /// value. + template<typename T> + class LLVM_NODISCARD ArrayRef { + public: + using iterator = const T *; + using const_iterator = const T *; + using size_type = size_t; + using reverse_iterator = std::reverse_iterator<iterator>; + + private: + /// The start of the array, in an external buffer. + const T *Data = nullptr; + + /// The number of elements. + size_type Length = 0; + + public: + /// @name Constructors + /// @{ + + /// Construct an empty ArrayRef. + /*implicit*/ ArrayRef() = default; + + /// Construct an empty ArrayRef from None. + /*implicit*/ ArrayRef(NoneType) {} + + /// Construct an ArrayRef from a single element. + /*implicit*/ ArrayRef(const T &OneElt) + : Data(&OneElt), Length(1) {} + + /// Construct an ArrayRef from a pointer and length. + /*implicit*/ ArrayRef(const T *data, size_t length) + : Data(data), Length(length) {} + + /// Construct an ArrayRef from a range. + ArrayRef(const T *begin, const T *end) + : Data(begin), Length(end - begin) {} + + /// Construct an ArrayRef from a SmallVector. This is templated in order to + /// avoid instantiating SmallVectorTemplateCommon<T> whenever we + /// copy-construct an ArrayRef. + template<typename U> + /*implicit*/ ArrayRef(const SmallVectorTemplateCommon<T, U> &Vec) + : Data(Vec.data()), Length(Vec.size()) { + } + + /// Construct an ArrayRef from a std::vector. + template<typename A> + /*implicit*/ ArrayRef(const std::vector<T, A> &Vec) + : Data(Vec.data()), Length(Vec.size()) {} + + /// Construct an ArrayRef from a std::array + template <size_t N> + /*implicit*/ constexpr ArrayRef(const std::array<T, N> &Arr) + : Data(Arr.data()), Length(N) {} + + /// Construct an ArrayRef from a C array. + template <size_t N> + /*implicit*/ constexpr ArrayRef(const T (&Arr)[N]) : Data(Arr), Length(N) {} + + /// Construct an ArrayRef from a std::initializer_list. +#if LLVM_GNUC_PREREQ(9, 0, 0) +// Disable gcc's warning in this constructor as it generates an enormous amount +// of messages. Anyone using ArrayRef should already be aware of the fact that +// it does not do lifetime extension. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winit-list-lifetime" +#endif + /*implicit*/ ArrayRef(const std::initializer_list<T> &Vec) + : Data(Vec.begin() == Vec.end() ? (T*)nullptr : Vec.begin()), + Length(Vec.size()) {} +#if LLVM_GNUC_PREREQ(9, 0, 0) +#pragma GCC diagnostic pop +#endif + + /// 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 * = 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 * = nullptr) + : Data(Vec.data()), Length(Vec.size()) { + } + + /// Construct an ArrayRef<const T*> from std::vector<T*>. This uses SFINAE + /// to ensure that only vectors of pointers can be converted. + template<typename U, typename A> + ArrayRef(const std::vector<U *, A> &Vec, + typename std::enable_if< + std::is_convertible<U *const *, T const *>::value>::type* = 0) + : Data(Vec.data()), Length(Vec.size()) {} + + /// @} + /// @name Simple Operations + /// @{ + + iterator begin() const { return Data; } + iterator end() const { return Data + Length; } + + reverse_iterator rbegin() const { return reverse_iterator(end()); } + reverse_iterator rend() const { return reverse_iterator(begin()); } + + /// empty - Check if the array is empty. + bool empty() const { return Length == 0; } + + const T *data() const { return Data; } + + /// size - Get the array size. + size_t size() const { return Length; } + + /// front - Get the first element. + const T &front() const { + assert(!empty()); + return Data[0]; + } + + /// back - Get the last element. + const T &back() const { + assert(!empty()); + return Data[Length-1]; + } + + // copy - Allocate copy in Allocator and return ArrayRef<T> to it. + template <typename Allocator> ArrayRef<T> copy(Allocator &A) { + T *Buff = A.template Allocate<T>(Length); + std::uninitialized_copy(begin(), end(), Buff); + return ArrayRef<T>(Buff, Length); + } + + /// equals - Check for element-wise equality. + bool equals(ArrayRef RHS) const { + if (Length != RHS.Length) + return false; + return std::equal(begin(), end(), RHS.begin()); + } + + /// slice(n, m) - Chop off the first N elements of the array, and keep M + /// elements in the array. + ArrayRef<T> slice(size_t N, size_t M) const { + assert(N+M <= size() && "Invalid specifier"); + return ArrayRef<T>(data()+N, M); + } + + /// slice(n) - Chop off the first N elements of the array. + ArrayRef<T> slice(size_t N) const { return slice(N, size() - N); } + + /// 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); + } + + /// 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); + } + + /// Return a copy of *this with the first N elements satisfying the + /// given predicate removed. + template <class PredicateT> ArrayRef<T> drop_while(PredicateT Pred) const { + return ArrayRef<T>(find_if_not(*this, Pred), end()); + } + + /// Return a copy of *this with the first N elements not satisfying + /// the given predicate removed. + template <class PredicateT> ArrayRef<T> drop_until(PredicateT Pred) const { + return ArrayRef<T>(find_if(*this, Pred), end()); + } + + /// Return a copy of *this with only the first \p N elements. + ArrayRef<T> take_front(size_t N = 1) const { + if (N >= size()) + return *this; + return drop_back(size() - N); + } + + /// Return a copy of *this with only the last \p N elements. + ArrayRef<T> take_back(size_t N = 1) const { + if (N >= size()) + return *this; + return drop_front(size() - N); + } + + /// Return the first N elements of this Array that satisfy the given + /// predicate. + template <class PredicateT> ArrayRef<T> take_while(PredicateT Pred) const { + return ArrayRef<T>(begin(), find_if_not(*this, Pred)); + } + + /// Return the first N elements of this Array that don't satisfy the + /// given predicate. + template <class PredicateT> ArrayRef<T> take_until(PredicateT Pred) const { + return ArrayRef<T>(begin(), find_if(*this, Pred)); + } + + /// @} + /// @name Operator Overloads + /// @{ + const T &operator[](size_t Index) const { + assert(Index < Length && "Invalid index!"); + return Data[Index]; + } + + /// Disallow accidental assignment from a temporary. + /// + /// The declaration here is extra complicated so that "arrayRef = {}" + /// continues to select the move assignment operator. + template <typename U> + typename std::enable_if<std::is_same<U, T>::value, ArrayRef<T>>::type & + operator=(U &&Temporary) = delete; + + /// Disallow accidental assignment from a temporary. + /// + /// The declaration here is extra complicated so that "arrayRef = {}" + /// continues to select the move assignment operator. + template <typename U> + typename std::enable_if<std::is_same<U, T>::value, ArrayRef<T>>::type & + operator=(std::initializer_list<U>) = delete; + + /// @} + /// @name Expensive Operations + /// @{ + std::vector<T> vec() const { + return std::vector<T>(Data, Data+Length); + } + + /// @} + /// @name Conversion operators + /// @{ + operator std::vector<T>() const { + return std::vector<T>(Data, Data+Length); + } + + /// @} + }; + + /// MutableArrayRef - Represent a mutable 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 and modify consecutive elements easily and + /// conveniently. + /// + /// This class does not own the underlying data, it is expected to be used in + /// situations where the data resides in some other buffer, whose lifetime + /// extends past that of the MutableArrayRef. For this reason, it is not in + /// general safe to store a MutableArrayRef. + /// + /// This is intended to be trivially copyable, so it should be passed by + /// value. + template<typename T> + class LLVM_NODISCARD MutableArrayRef : public ArrayRef<T> { + public: + using iterator = T *; + using reverse_iterator = std::reverse_iterator<iterator>; + + /// Construct an empty MutableArrayRef. + /*implicit*/ MutableArrayRef() = default; + + /// Construct an empty MutableArrayRef from None. + /*implicit*/ MutableArrayRef(NoneType) : ArrayRef<T>() {} + + /// Construct an MutableArrayRef from a single element. + /*implicit*/ MutableArrayRef(T &OneElt) : ArrayRef<T>(OneElt) {} + + /// Construct an MutableArrayRef from a pointer and length. + /*implicit*/ MutableArrayRef(T *data, size_t length) + : ArrayRef<T>(data, length) {} + + /// Construct an MutableArrayRef from a range. + MutableArrayRef(T *begin, T *end) : ArrayRef<T>(begin, end) {} + + /// Construct an MutableArrayRef from a SmallVector. + /*implicit*/ MutableArrayRef(SmallVectorImpl<T> &Vec) + : ArrayRef<T>(Vec) {} + + /// Construct a MutableArrayRef from a std::vector. + /*implicit*/ MutableArrayRef(std::vector<T> &Vec) + : ArrayRef<T>(Vec) {} + + /// Construct an ArrayRef from a std::array + template <size_t N> + /*implicit*/ constexpr MutableArrayRef(std::array<T, N> &Arr) + : ArrayRef<T>(Arr) {} + + /// Construct an MutableArrayRef from a C array. + template <size_t N> + /*implicit*/ constexpr MutableArrayRef(T (&Arr)[N]) : ArrayRef<T>(Arr) {} + + T *data() const { return const_cast<T*>(ArrayRef<T>::data()); } + + iterator begin() const { return data(); } + iterator end() const { return data() + this->size(); } + + reverse_iterator rbegin() const { return reverse_iterator(end()); } + reverse_iterator rend() const { return reverse_iterator(begin()); } + + /// front - Get the first element. + T &front() const { + assert(!this->empty()); + return data()[0]; + } + + /// back - Get the last element. + T &back() const { + assert(!this->empty()); + return data()[this->size()-1]; + } + + /// slice(n, m) - Chop off the first N elements of the array, and keep M + /// elements in the array. + MutableArrayRef<T> slice(size_t N, size_t M) const { + assert(N + M <= this->size() && "Invalid specifier"); + return MutableArrayRef<T>(this->data() + N, M); + } + + /// slice(n) - Chop off the first N elements of the array. + MutableArrayRef<T> slice(size_t N) const { + return slice(N, this->size() - N); + } + + /// 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); + } + + /// Return a copy of *this with the first N elements satisfying the + /// given predicate removed. + template <class PredicateT> + MutableArrayRef<T> drop_while(PredicateT Pred) const { + return MutableArrayRef<T>(find_if_not(*this, Pred), end()); + } + + /// Return a copy of *this with the first N elements not satisfying + /// the given predicate removed. + template <class PredicateT> + MutableArrayRef<T> drop_until(PredicateT Pred) const { + return MutableArrayRef<T>(find_if(*this, Pred), end()); + } + + /// Return a copy of *this with only the first \p N elements. + MutableArrayRef<T> take_front(size_t N = 1) const { + if (N >= this->size()) + return *this; + return drop_back(this->size() - N); + } + + /// Return a copy of *this with only the last \p N elements. + MutableArrayRef<T> take_back(size_t N = 1) const { + if (N >= this->size()) + return *this; + return drop_front(this->size() - N); + } + + /// Return the first N elements of this Array that satisfy the given + /// predicate. + template <class PredicateT> + MutableArrayRef<T> take_while(PredicateT Pred) const { + return MutableArrayRef<T>(begin(), find_if_not(*this, Pred)); + } + + /// Return the first N elements of this Array that don't satisfy the + /// given predicate. + template <class PredicateT> + MutableArrayRef<T> take_until(PredicateT Pred) const { + return MutableArrayRef<T>(begin(), find_if(*this, Pred)); + } + + /// @} + /// @name Operator Overloads + /// @{ + T &operator[](size_t Index) const { + assert(Index < this->size() && "Invalid index!"); + return data()[Index]; + } + }; + + /// This is a MutableArrayRef that owns its array. + template <typename T> class OwningArrayRef : public MutableArrayRef<T> { + public: + OwningArrayRef() = default; + OwningArrayRef(size_t Size) : MutableArrayRef<T>(new T[Size], Size) {} + + OwningArrayRef(ArrayRef<T> Data) + : MutableArrayRef<T>(new T[Data.size()], Data.size()) { + std::copy(Data.begin(), Data.end(), this->begin()); + } + + OwningArrayRef(OwningArrayRef &&Other) { *this = std::move(Other); } + + OwningArrayRef &operator=(OwningArrayRef &&Other) { + delete[] this->data(); + this->MutableArrayRef<T>::operator=(Other); + Other.MutableArrayRef<T>::operator=(MutableArrayRef<T>()); + return *this; + } + + ~OwningArrayRef() { delete[] this->data(); } + }; + + /// @name ArrayRef Convenience constructors + /// @{ + + /// Construct an ArrayRef from a single element. + template<typename T> + ArrayRef<T> makeArrayRef(const T &OneElt) { + return OneElt; + } + + /// Construct an ArrayRef from a pointer and length. + template<typename T> + ArrayRef<T> makeArrayRef(const T *data, size_t length) { + return ArrayRef<T>(data, length); + } + + /// Construct an ArrayRef from a range. + template<typename T> + ArrayRef<T> makeArrayRef(const T *begin, const T *end) { + return ArrayRef<T>(begin, end); + } + + /// Construct an ArrayRef from a SmallVector. + template <typename T> + ArrayRef<T> makeArrayRef(const SmallVectorImpl<T> &Vec) { + return Vec; + } + + /// Construct an ArrayRef from a SmallVector. + template <typename T, unsigned N> + ArrayRef<T> makeArrayRef(const SmallVector<T, N> &Vec) { + return Vec; + } + + /// Construct an ArrayRef from a std::vector. + template<typename T> + ArrayRef<T> makeArrayRef(const std::vector<T> &Vec) { + return Vec; + } + + /// Construct an ArrayRef from a std::array. + template <typename T, std::size_t N> + ArrayRef<T> makeArrayRef(const std::array<T, N> &Arr) { + return Arr; + } + + /// Construct an ArrayRef from an ArrayRef (no-op) (const) + template <typename T> ArrayRef<T> makeArrayRef(const ArrayRef<T> &Vec) { + return Vec; + } + + /// Construct an ArrayRef from an ArrayRef (no-op) + template <typename T> ArrayRef<T> &makeArrayRef(ArrayRef<T> &Vec) { + return Vec; + } + + /// Construct an ArrayRef from a C array. + template<typename T, size_t N> + ArrayRef<T> makeArrayRef(const T (&Arr)[N]) { + return ArrayRef<T>(Arr); + } + + /// Construct a MutableArrayRef from a single element. + template<typename T> + MutableArrayRef<T> makeMutableArrayRef(T &OneElt) { + return OneElt; + } + + /// Construct a MutableArrayRef from a pointer and length. + template<typename T> + MutableArrayRef<T> makeMutableArrayRef(T *data, size_t length) { + return MutableArrayRef<T>(data, length); + } + + /// @} + /// @name ArrayRef Comparison Operators + /// @{ + + template<typename T> + inline bool operator==(ArrayRef<T> LHS, ArrayRef<T> RHS) { + return LHS.equals(RHS); + } + + template<typename T> + inline bool operator!=(ArrayRef<T> LHS, ArrayRef<T> RHS) { + return !(LHS == RHS); + } + + /// @} + + template <typename T> hash_code hash_value(ArrayRef<T> S) { + return hash_combine_range(S.begin(), S.end()); + } + +} // end namespace llvm + +#endif // LLVM_ADT_ARRAYREF_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/BitVector.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/BitVector.h new file mode 100644 index 0000000..5284be8 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/BitVector.h
@@ -0,0 +1,945 @@ +//===- llvm/ADT/BitVector.h - Bit vectors -----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the BitVector class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_BITVECTOR_H +#define LLVM_ADT_BITVECTOR_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/MathExtras.h" +#include <algorithm> +#include <cassert> +#include <climits> +#include <cstdint> +#include <cstdlib> +#include <cstring> +#include <utility> + +namespace llvm { + +/// ForwardIterator for the bits that are set. +/// Iterators get invalidated when resize / reserve is called. +template <typename BitVectorT> class const_set_bits_iterator_impl { + const BitVectorT &Parent; + int Current = 0; + + void advance() { + assert(Current != -1 && "Trying to advance past end."); + Current = Parent.find_next(Current); + } + +public: + const_set_bits_iterator_impl(const BitVectorT &Parent, int Current) + : Parent(Parent), Current(Current) {} + explicit const_set_bits_iterator_impl(const BitVectorT &Parent) + : const_set_bits_iterator_impl(Parent, Parent.find_first()) {} + const_set_bits_iterator_impl(const const_set_bits_iterator_impl &) = default; + + const_set_bits_iterator_impl operator++(int) { + auto Prev = *this; + advance(); + return Prev; + } + + const_set_bits_iterator_impl &operator++() { + advance(); + return *this; + } + + unsigned operator*() const { return Current; } + + bool operator==(const const_set_bits_iterator_impl &Other) const { + assert(&Parent == &Other.Parent && + "Comparing iterators from different BitVectors"); + return Current == Other.Current; + } + + bool operator!=(const const_set_bits_iterator_impl &Other) const { + assert(&Parent == &Other.Parent && + "Comparing iterators from different BitVectors"); + return Current != Other.Current; + } +}; + +class BitVector { + typedef uintptr_t BitWord; + + enum { BITWORD_SIZE = (unsigned)sizeof(BitWord) * CHAR_BIT }; + + static_assert(BITWORD_SIZE == 64 || BITWORD_SIZE == 32, + "Unsupported word size"); + + MutableArrayRef<BitWord> Bits; // Actual bits. + unsigned Size; // Size of bitvector in bits. + +public: + typedef unsigned size_type; + // Encapsulation of a single bit. + class reference { + friend class BitVector; + + BitWord *WordRef; + unsigned BitPos; + + public: + reference(BitVector &b, unsigned Idx) { + WordRef = &b.Bits[Idx / BITWORD_SIZE]; + BitPos = Idx % BITWORD_SIZE; + } + + reference() = delete; + reference(const reference&) = default; + + reference &operator=(reference t) { + *this = bool(t); + return *this; + } + + reference& operator=(bool t) { + if (t) + *WordRef |= BitWord(1) << BitPos; + else + *WordRef &= ~(BitWord(1) << BitPos); + return *this; + } + + operator bool() const { + return ((*WordRef) & (BitWord(1) << BitPos)) != 0; + } + }; + + typedef const_set_bits_iterator_impl<BitVector> const_set_bits_iterator; + typedef const_set_bits_iterator set_iterator; + + const_set_bits_iterator set_bits_begin() const { + return const_set_bits_iterator(*this); + } + const_set_bits_iterator set_bits_end() const { + return const_set_bits_iterator(*this, -1); + } + iterator_range<const_set_bits_iterator> set_bits() const { + return make_range(set_bits_begin(), set_bits_end()); + } + + /// BitVector default ctor - Creates an empty bitvector. + BitVector() : Size(0) {} + + /// BitVector ctor - Creates a bitvector of specified number of bits. All + /// bits are initialized to the specified value. + explicit BitVector(unsigned s, bool t = false) : Size(s) { + size_t Capacity = NumBitWords(s); + Bits = allocate(Capacity); + init_words(Bits, t); + if (t) + clear_unused_bits(); + } + + /// BitVector copy ctor. + BitVector(const BitVector &RHS) : Size(RHS.size()) { + if (Size == 0) { + Bits = MutableArrayRef<BitWord>(); + return; + } + + size_t Capacity = NumBitWords(RHS.size()); + Bits = allocate(Capacity); + std::memcpy(Bits.data(), RHS.Bits.data(), Capacity * sizeof(BitWord)); + } + + BitVector(BitVector &&RHS) : Bits(RHS.Bits), Size(RHS.Size) { + RHS.Bits = MutableArrayRef<BitWord>(); + RHS.Size = 0; + } + + ~BitVector() { std::free(Bits.data()); } + + /// empty - Tests whether there are no bits in this bitvector. + bool empty() const { return Size == 0; } + + /// size - Returns the number of bits in this bitvector. + size_type size() const { return Size; } + + /// count - Returns the number of bits which are set. + size_type count() const { + unsigned NumBits = 0; + for (unsigned i = 0; i < NumBitWords(size()); ++i) + NumBits += countPopulation(Bits[i]); + return NumBits; + } + + /// any - Returns true if any bit is set. + bool any() const { + for (unsigned i = 0; i < NumBitWords(size()); ++i) + if (Bits[i] != 0) + return true; + return false; + } + + /// all - Returns true if all bits are set. + bool all() const { + for (unsigned i = 0; i < Size / BITWORD_SIZE; ++i) + if (Bits[i] != ~BitWord(0)) + return false; + + // If bits remain check that they are ones. The unused bits are always zero. + if (unsigned Remainder = Size % BITWORD_SIZE) + return Bits[Size / BITWORD_SIZE] == (BitWord(1) << Remainder) - 1; + + return true; + } + + /// none - Returns true if none of the bits are set. + bool none() const { + return !any(); + } + + /// find_first_in - Returns the index of the first set bit in the range + /// [Begin, End). Returns -1 if all bits in the range are unset. + int find_first_in(unsigned Begin, unsigned End) const { + assert(Begin <= End && End <= Size); + if (Begin == End) + return -1; + + unsigned FirstWord = Begin / BITWORD_SIZE; + unsigned LastWord = (End - 1) / BITWORD_SIZE; + + // Check subsequent words. + for (unsigned i = FirstWord; i <= LastWord; ++i) { + BitWord Copy = Bits[i]; + + if (i == FirstWord) { + unsigned FirstBit = Begin % BITWORD_SIZE; + Copy &= maskTrailingZeros<BitWord>(FirstBit); + } + + if (i == LastWord) { + unsigned LastBit = (End - 1) % BITWORD_SIZE; + Copy &= maskTrailingOnes<BitWord>(LastBit + 1); + } + if (Copy != 0) + return i * BITWORD_SIZE + countTrailingZeros(Copy); + } + return -1; + } + + /// find_last_in - Returns the index of the last set bit in the range + /// [Begin, End). Returns -1 if all bits in the range are unset. + int find_last_in(unsigned Begin, unsigned End) const { + assert(Begin <= End && End <= Size); + if (Begin == End) + return -1; + + unsigned LastWord = (End - 1) / BITWORD_SIZE; + unsigned FirstWord = Begin / BITWORD_SIZE; + + for (unsigned i = LastWord + 1; i >= FirstWord + 1; --i) { + unsigned CurrentWord = i - 1; + + BitWord Copy = Bits[CurrentWord]; + if (CurrentWord == LastWord) { + unsigned LastBit = (End - 1) % BITWORD_SIZE; + Copy &= maskTrailingOnes<BitWord>(LastBit + 1); + } + + if (CurrentWord == FirstWord) { + unsigned FirstBit = Begin % BITWORD_SIZE; + Copy &= maskTrailingZeros<BitWord>(FirstBit); + } + + if (Copy != 0) + return (CurrentWord + 1) * BITWORD_SIZE - countLeadingZeros(Copy) - 1; + } + + return -1; + } + + /// find_first_unset_in - Returns the index of the first unset bit in the + /// range [Begin, End). Returns -1 if all bits in the range are set. + int find_first_unset_in(unsigned Begin, unsigned End) const { + assert(Begin <= End && End <= Size); + if (Begin == End) + return -1; + + unsigned FirstWord = Begin / BITWORD_SIZE; + unsigned LastWord = (End - 1) / BITWORD_SIZE; + + // Check subsequent words. + for (unsigned i = FirstWord; i <= LastWord; ++i) { + BitWord Copy = Bits[i]; + + if (i == FirstWord) { + unsigned FirstBit = Begin % BITWORD_SIZE; + Copy |= maskTrailingOnes<BitWord>(FirstBit); + } + + if (i == LastWord) { + unsigned LastBit = (End - 1) % BITWORD_SIZE; + Copy |= maskTrailingZeros<BitWord>(LastBit + 1); + } + if (Copy != ~BitWord(0)) { + unsigned Result = i * BITWORD_SIZE + countTrailingOnes(Copy); + return Result < size() ? Result : -1; + } + } + return -1; + } + + /// find_last_unset_in - Returns the index of the last unset bit in the + /// range [Begin, End). Returns -1 if all bits in the range are set. + int find_last_unset_in(unsigned Begin, unsigned End) const { + assert(Begin <= End && End <= Size); + if (Begin == End) + return -1; + + unsigned LastWord = (End - 1) / BITWORD_SIZE; + unsigned FirstWord = Begin / BITWORD_SIZE; + + for (unsigned i = LastWord + 1; i >= FirstWord + 1; --i) { + unsigned CurrentWord = i - 1; + + BitWord Copy = Bits[CurrentWord]; + if (CurrentWord == LastWord) { + unsigned LastBit = (End - 1) % BITWORD_SIZE; + Copy |= maskTrailingZeros<BitWord>(LastBit + 1); + } + + if (CurrentWord == FirstWord) { + unsigned FirstBit = Begin % BITWORD_SIZE; + Copy |= maskTrailingOnes<BitWord>(FirstBit); + } + + if (Copy != ~BitWord(0)) { + unsigned Result = + (CurrentWord + 1) * BITWORD_SIZE - countLeadingOnes(Copy) - 1; + return Result < Size ? Result : -1; + } + } + return -1; + } + + /// find_first - Returns the index of the first set bit, -1 if none + /// of the bits are set. + int find_first() const { return find_first_in(0, Size); } + + /// find_last - Returns the index of the last set bit, -1 if none of the bits + /// are set. + int find_last() const { return find_last_in(0, Size); } + + /// find_next - 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 { return find_first_in(Prev + 1, Size); } + + /// find_prev - Returns the index of the first set bit that precedes the + /// the bit at \p PriorTo. Returns -1 if all previous bits are unset. + int find_prev(unsigned PriorTo) const { return find_last_in(0, PriorTo); } + + /// find_first_unset - Returns the index of the first unset bit, -1 if all + /// of the bits are set. + int find_first_unset() const { return find_first_unset_in(0, Size); } + + /// find_next_unset - Returns the index of the next unset bit following the + /// "Prev" bit. Returns -1 if all remaining bits are set. + int find_next_unset(unsigned Prev) const { + return find_first_unset_in(Prev + 1, Size); + } + + /// find_last_unset - Returns the index of the last unset bit, -1 if all of + /// the bits are set. + int find_last_unset() const { return find_last_unset_in(0, Size); } + + /// find_prev_unset - Returns the index of the first unset bit that precedes + /// the bit at \p PriorTo. Returns -1 if all previous bits are set. + int find_prev_unset(unsigned PriorTo) { + return find_last_unset_in(0, PriorTo); + } + + /// clear - Removes all bits from the bitvector. Does not change capacity. + void clear() { + Size = 0; + } + + /// resize - Grow or shrink the bitvector. + void resize(unsigned N, bool t = false) { + if (N > getBitCapacity()) { + unsigned OldCapacity = Bits.size(); + grow(N); + init_words(Bits.drop_front(OldCapacity), t); + } + + // Set any old unused bits that are now included in the BitVector. This + // may set bits that are not included in the new vector, but we will clear + // them back out below. + if (N > Size) + set_unused_bits(t); + + // Update the size, and clear out any bits that are now unused + unsigned OldSize = Size; + Size = N; + if (t || N < OldSize) + clear_unused_bits(); + } + + void reserve(unsigned N) { + if (N > getBitCapacity()) + grow(N); + } + + // Set, reset, flip + BitVector &set() { + init_words(Bits, true); + clear_unused_bits(); + return *this; + } + + BitVector &set(unsigned Idx) { + assert(Bits.data() && "Bits never allocated"); + Bits[Idx / BITWORD_SIZE] |= BitWord(1) << (Idx % BITWORD_SIZE); + return *this; + } + + /// set - Efficiently set a range of bits in [I, E) + BitVector &set(unsigned I, unsigned E) { + assert(I <= E && "Attempted to set backwards range!"); + assert(E <= size() && "Attempted to set out-of-bounds range!"); + + if (I == E) return *this; + + if (I / BITWORD_SIZE == E / BITWORD_SIZE) { + BitWord EMask = BitWord(1) << (E % BITWORD_SIZE); + BitWord IMask = BitWord(1) << (I % BITWORD_SIZE); + BitWord Mask = EMask - IMask; + Bits[I / BITWORD_SIZE] |= Mask; + return *this; + } + + BitWord PrefixMask = ~BitWord(0) << (I % BITWORD_SIZE); + Bits[I / BITWORD_SIZE] |= PrefixMask; + I = alignTo(I, BITWORD_SIZE); + + for (; I + BITWORD_SIZE <= E; I += BITWORD_SIZE) + Bits[I / BITWORD_SIZE] = ~BitWord(0); + + BitWord PostfixMask = (BitWord(1) << (E % BITWORD_SIZE)) - 1; + if (I < E) + Bits[I / BITWORD_SIZE] |= PostfixMask; + + return *this; + } + + BitVector &reset() { + init_words(Bits, false); + return *this; + } + + BitVector &reset(unsigned Idx) { + Bits[Idx / BITWORD_SIZE] &= ~(BitWord(1) << (Idx % BITWORD_SIZE)); + return *this; + } + + /// reset - Efficiently reset a range of bits in [I, E) + BitVector &reset(unsigned I, unsigned E) { + assert(I <= E && "Attempted to reset backwards range!"); + assert(E <= size() && "Attempted to reset out-of-bounds range!"); + + if (I == E) return *this; + + if (I / BITWORD_SIZE == E / BITWORD_SIZE) { + BitWord EMask = BitWord(1) << (E % BITWORD_SIZE); + BitWord IMask = BitWord(1) << (I % BITWORD_SIZE); + BitWord Mask = EMask - IMask; + Bits[I / BITWORD_SIZE] &= ~Mask; + return *this; + } + + BitWord PrefixMask = ~BitWord(0) << (I % BITWORD_SIZE); + Bits[I / BITWORD_SIZE] &= ~PrefixMask; + I = alignTo(I, BITWORD_SIZE); + + for (; I + BITWORD_SIZE <= E; I += BITWORD_SIZE) + Bits[I / BITWORD_SIZE] = BitWord(0); + + BitWord PostfixMask = (BitWord(1) << (E % BITWORD_SIZE)) - 1; + if (I < E) + Bits[I / BITWORD_SIZE] &= ~PostfixMask; + + return *this; + } + + BitVector &flip() { + for (unsigned i = 0; i < NumBitWords(size()); ++i) + Bits[i] = ~Bits[i]; + clear_unused_bits(); + return *this; + } + + BitVector &flip(unsigned Idx) { + Bits[Idx / BITWORD_SIZE] ^= BitWord(1) << (Idx % BITWORD_SIZE); + return *this; + } + + // Indexing. + reference operator[](unsigned Idx) { + assert (Idx < Size && "Out-of-bounds Bit access."); + return reference(*this, Idx); + } + + bool operator[](unsigned Idx) const { + assert (Idx < Size && "Out-of-bounds Bit access."); + BitWord Mask = BitWord(1) << (Idx % BITWORD_SIZE); + return (Bits[Idx / BITWORD_SIZE] & Mask) != 0; + } + + bool test(unsigned Idx) const { + return (*this)[Idx]; + } + + // Push single bit to end of vector. + void push_back(bool Val) { + unsigned OldSize = Size; + unsigned NewSize = Size + 1; + + // Resize, which will insert zeros. + // If we already fit then the unused bits will be already zero. + if (NewSize > getBitCapacity()) + resize(NewSize, false); + else + Size = NewSize; + + // If true, set single bit. + if (Val) + set(OldSize); + } + + /// Test if any common bits are set. + bool anyCommon(const BitVector &RHS) const { + unsigned ThisWords = NumBitWords(size()); + unsigned RHSWords = NumBitWords(RHS.size()); + for (unsigned i = 0, e = std::min(ThisWords, RHSWords); i != e; ++i) + if (Bits[i] & RHS.Bits[i]) + return true; + return false; + } + + // Comparison operators. + bool operator==(const BitVector &RHS) const { + unsigned ThisWords = NumBitWords(size()); + unsigned RHSWords = NumBitWords(RHS.size()); + unsigned i; + for (i = 0; i != std::min(ThisWords, RHSWords); ++i) + if (Bits[i] != RHS.Bits[i]) + return false; + + // Verify that any extra words are all zeros. + if (i != ThisWords) { + for (; i != ThisWords; ++i) + if (Bits[i]) + return false; + } else if (i != RHSWords) { + for (; i != RHSWords; ++i) + if (RHS.Bits[i]) + return false; + } + return true; + } + + bool operator!=(const BitVector &RHS) const { + return !(*this == RHS); + } + + /// Intersection, union, disjoint union. + BitVector &operator&=(const BitVector &RHS) { + unsigned ThisWords = NumBitWords(size()); + unsigned RHSWords = NumBitWords(RHS.size()); + unsigned i; + for (i = 0; i != std::min(ThisWords, RHSWords); ++i) + Bits[i] &= RHS.Bits[i]; + + // Any bits that are just in this bitvector become zero, because they aren't + // in the RHS bit vector. Any words only in RHS are ignored because they + // are already zero in the LHS. + for (; i != ThisWords; ++i) + Bits[i] = 0; + + return *this; + } + + /// reset - Reset bits that are set in RHS. Same as *this &= ~RHS. + BitVector &reset(const BitVector &RHS) { + unsigned ThisWords = NumBitWords(size()); + unsigned RHSWords = NumBitWords(RHS.size()); + unsigned i; + for (i = 0; i != std::min(ThisWords, RHSWords); ++i) + Bits[i] &= ~RHS.Bits[i]; + return *this; + } + + /// test - Check if (This - RHS) is zero. + /// This is the same as reset(RHS) and any(). + bool test(const BitVector &RHS) const { + unsigned ThisWords = NumBitWords(size()); + unsigned RHSWords = NumBitWords(RHS.size()); + unsigned i; + for (i = 0; i != std::min(ThisWords, RHSWords); ++i) + if ((Bits[i] & ~RHS.Bits[i]) != 0) + return true; + + for (; i != ThisWords ; ++i) + if (Bits[i] != 0) + return true; + + return false; + } + + BitVector &operator|=(const BitVector &RHS) { + if (size() < RHS.size()) + resize(RHS.size()); + for (size_t i = 0, e = NumBitWords(RHS.size()); i != e; ++i) + Bits[i] |= RHS.Bits[i]; + return *this; + } + + BitVector &operator^=(const BitVector &RHS) { + if (size() < RHS.size()) + resize(RHS.size()); + for (size_t i = 0, e = NumBitWords(RHS.size()); i != e; ++i) + Bits[i] ^= RHS.Bits[i]; + return *this; + } + + BitVector &operator>>=(unsigned N) { + assert(N <= Size); + if (LLVM_UNLIKELY(empty() || N == 0)) + return *this; + + unsigned NumWords = NumBitWords(Size); + assert(NumWords >= 1); + + wordShr(N / BITWORD_SIZE); + + unsigned BitDistance = N % BITWORD_SIZE; + if (BitDistance == 0) + return *this; + + // When the shift size is not a multiple of the word size, then we have + // a tricky situation where each word in succession needs to extract some + // of the bits from the next word and or them into this word while + // shifting this word to make room for the new bits. This has to be done + // for every word in the array. + + // Since we're shifting each word right, some bits will fall off the end + // of each word to the right, and empty space will be created on the left. + // The final word in the array will lose bits permanently, so starting at + // the beginning, work forwards shifting each word to the right, and + // OR'ing in the bits from the end of the next word to the beginning of + // the current word. + + // Example: + // Starting with {0xAABBCCDD, 0xEEFF0011, 0x22334455} and shifting right + // by 4 bits. + // Step 1: Word[0] >>= 4 ; 0x0ABBCCDD + // Step 2: Word[0] |= 0x10000000 ; 0x1ABBCCDD + // Step 3: Word[1] >>= 4 ; 0x0EEFF001 + // Step 4: Word[1] |= 0x50000000 ; 0x5EEFF001 + // Step 5: Word[2] >>= 4 ; 0x02334455 + // Result: { 0x1ABBCCDD, 0x5EEFF001, 0x02334455 } + const BitWord Mask = maskTrailingOnes<BitWord>(BitDistance); + const unsigned LSH = BITWORD_SIZE - BitDistance; + + for (unsigned I = 0; I < NumWords - 1; ++I) { + Bits[I] >>= BitDistance; + Bits[I] |= (Bits[I + 1] & Mask) << LSH; + } + + Bits[NumWords - 1] >>= BitDistance; + + return *this; + } + + BitVector &operator<<=(unsigned N) { + assert(N <= Size); + if (LLVM_UNLIKELY(empty() || N == 0)) + return *this; + + unsigned NumWords = NumBitWords(Size); + assert(NumWords >= 1); + + wordShl(N / BITWORD_SIZE); + + unsigned BitDistance = N % BITWORD_SIZE; + if (BitDistance == 0) + return *this; + + // When the shift size is not a multiple of the word size, then we have + // a tricky situation where each word in succession needs to extract some + // of the bits from the previous word and or them into this word while + // shifting this word to make room for the new bits. This has to be done + // for every word in the array. This is similar to the algorithm outlined + // in operator>>=, but backwards. + + // Since we're shifting each word left, some bits will fall off the end + // of each word to the left, and empty space will be created on the right. + // The first word in the array will lose bits permanently, so starting at + // the end, work backwards shifting each word to the left, and OR'ing + // in the bits from the end of the next word to the beginning of the + // current word. + + // Example: + // Starting with {0xAABBCCDD, 0xEEFF0011, 0x22334455} and shifting left + // by 4 bits. + // Step 1: Word[2] <<= 4 ; 0x23344550 + // Step 2: Word[2] |= 0x0000000E ; 0x2334455E + // Step 3: Word[1] <<= 4 ; 0xEFF00110 + // Step 4: Word[1] |= 0x0000000A ; 0xEFF0011A + // Step 5: Word[0] <<= 4 ; 0xABBCCDD0 + // Result: { 0xABBCCDD0, 0xEFF0011A, 0x2334455E } + const BitWord Mask = maskLeadingOnes<BitWord>(BitDistance); + const unsigned RSH = BITWORD_SIZE - BitDistance; + + for (int I = NumWords - 1; I > 0; --I) { + Bits[I] <<= BitDistance; + Bits[I] |= (Bits[I - 1] & Mask) >> RSH; + } + Bits[0] <<= BitDistance; + clear_unused_bits(); + + return *this; + } + + // Assignment operator. + const BitVector &operator=(const BitVector &RHS) { + if (this == &RHS) return *this; + + Size = RHS.size(); + unsigned RHSWords = NumBitWords(Size); + if (Size <= getBitCapacity()) { + if (Size) + std::memcpy(Bits.data(), RHS.Bits.data(), RHSWords * sizeof(BitWord)); + clear_unused_bits(); + return *this; + } + + // Grow the bitvector to have enough elements. + unsigned NewCapacity = RHSWords; + assert(NewCapacity > 0 && "negative capacity?"); + auto NewBits = allocate(NewCapacity); + std::memcpy(NewBits.data(), RHS.Bits.data(), NewCapacity * sizeof(BitWord)); + + // Destroy the old bits. + std::free(Bits.data()); + Bits = NewBits; + + return *this; + } + + const BitVector &operator=(BitVector &&RHS) { + if (this == &RHS) return *this; + + std::free(Bits.data()); + Bits = RHS.Bits; + Size = RHS.Size; + + RHS.Bits = MutableArrayRef<BitWord>(); + RHS.Size = 0; + + return *this; + } + + void swap(BitVector &RHS) { + std::swap(Bits, RHS.Bits); + std::swap(Size, RHS.Size); + } + + //===--------------------------------------------------------------------===// + // Portable bit mask operations. + //===--------------------------------------------------------------------===// + // + // These methods all operate on arrays of uint32_t, each holding 32 bits. The + // fixed word size makes it easier to work with literal bit vector constants + // in portable code. + // + // The LSB in each word is the lowest numbered bit. The size of a portable + // bit mask is always a whole multiple of 32 bits. If no bit mask size is + // given, the bit mask is assumed to cover the entire BitVector. + + /// setBitsInMask - Add '1' bits from Mask to this vector. Don't resize. + /// This computes "*this |= Mask". + void setBitsInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) { + applyMask<true, false>(Mask, MaskWords); + } + + /// clearBitsInMask - 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) { + applyMask<false, false>(Mask, MaskWords); + } + + /// setBitsNotInMask - 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) { + applyMask<true, true>(Mask, MaskWords); + } + + /// clearBitsNotInMask - 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) { + applyMask<false, true>(Mask, MaskWords); + } + +private: + /// Perform a logical left shift of \p Count words by moving everything + /// \p Count words to the right in memory. + /// + /// While confusing, words are stored from least significant at Bits[0] to + /// most significant at Bits[NumWords-1]. A logical shift left, however, + /// moves the current least significant bit to a higher logical index, and + /// fills the previous least significant bits with 0. Thus, we actually + /// need to move the bytes of the memory to the right, not to the left. + /// Example: + /// Words = [0xBBBBAAAA, 0xDDDDFFFF, 0x00000000, 0xDDDD0000] + /// represents a BitVector where 0xBBBBAAAA contain the least significant + /// bits. So if we want to shift the BitVector left by 2 words, we need to + /// turn this into 0x00000000 0x00000000 0xBBBBAAAA 0xDDDDFFFF by using a + /// memmove which moves right, not left. + void wordShl(uint32_t Count) { + if (Count == 0) + return; + + uint32_t NumWords = NumBitWords(Size); + + auto Src = Bits.take_front(NumWords).drop_back(Count); + auto Dest = Bits.take_front(NumWords).drop_front(Count); + + // Since we always move Word-sized chunks of data with src and dest both + // aligned to a word-boundary, we don't need to worry about endianness + // here. + std::memmove(Dest.begin(), Src.begin(), Dest.size() * sizeof(BitWord)); + std::memset(Bits.data(), 0, Count * sizeof(BitWord)); + clear_unused_bits(); + } + + /// Perform a logical right shift of \p Count words by moving those + /// words to the left in memory. See wordShl for more information. + /// + void wordShr(uint32_t Count) { + if (Count == 0) + return; + + uint32_t NumWords = NumBitWords(Size); + + auto Src = Bits.take_front(NumWords).drop_front(Count); + auto Dest = Bits.take_front(NumWords).drop_back(Count); + assert(Dest.size() == Src.size()); + + std::memmove(Dest.begin(), Src.begin(), Dest.size() * sizeof(BitWord)); + std::memset(Dest.end(), 0, Count * sizeof(BitWord)); + } + + MutableArrayRef<BitWord> allocate(size_t NumWords) { + BitWord *RawBits = static_cast<BitWord *>( + safe_malloc(NumWords * sizeof(BitWord))); + return MutableArrayRef<BitWord>(RawBits, NumWords); + } + + int next_unset_in_word(int WordIndex, BitWord Word) const { + unsigned Result = WordIndex * BITWORD_SIZE + countTrailingOnes(Word); + return Result < size() ? Result : -1; + } + + unsigned NumBitWords(unsigned S) const { + return (S + BITWORD_SIZE-1) / BITWORD_SIZE; + } + + // Set the unused bits in the high words. + void set_unused_bits(bool t = true) { + // Set high words first. + unsigned UsedWords = NumBitWords(Size); + if (Bits.size() > UsedWords) + init_words(Bits.drop_front(UsedWords), t); + + // Then set any stray high bits of the last used word. + unsigned ExtraBits = Size % BITWORD_SIZE; + if (ExtraBits) { + BitWord ExtraBitMask = ~BitWord(0) << ExtraBits; + if (t) + Bits[UsedWords-1] |= ExtraBitMask; + else + Bits[UsedWords-1] &= ~ExtraBitMask; + } + } + + // Clear the unused bits in the high words. + void clear_unused_bits() { + set_unused_bits(false); + } + + void grow(unsigned NewSize) { + size_t NewCapacity = std::max<size_t>(NumBitWords(NewSize), Bits.size() * 2); + assert(NewCapacity > 0 && "realloc-ing zero space"); + BitWord *NewBits = static_cast<BitWord *>( + safe_realloc(Bits.data(), NewCapacity * sizeof(BitWord))); + Bits = MutableArrayRef<BitWord>(NewBits, NewCapacity); + clear_unused_bits(); + } + + void init_words(MutableArrayRef<BitWord> B, bool t) { + if (B.size() > 0) + memset(B.data(), 0 - (int)t, B.size() * sizeof(BitWord)); + } + + template<bool AddBits, bool InvertMask> + void applyMask(const uint32_t *Mask, unsigned MaskWords) { + static_assert(BITWORD_SIZE % 32 == 0, "Unsupported BitWord size."); + MaskWords = std::min(MaskWords, (size() + 31) / 32); + const unsigned Scale = BITWORD_SIZE / 32; + unsigned i; + for (i = 0; MaskWords >= Scale; ++i, MaskWords -= Scale) { + BitWord BW = Bits[i]; + // This inner loop should unroll completely when BITWORD_SIZE > 32. + for (unsigned b = 0; b != BITWORD_SIZE; b += 32) { + uint32_t M = *Mask++; + if (InvertMask) M = ~M; + if (AddBits) BW |= BitWord(M) << b; + else BW &= ~(BitWord(M) << b); + } + Bits[i] = BW; + } + for (unsigned b = 0; MaskWords; b += 32, --MaskWords) { + uint32_t M = *Mask++; + if (InvertMask) M = ~M; + if (AddBits) Bits[i] |= BitWord(M) << b; + else Bits[i] &= ~(BitWord(M) << b); + } + if (AddBits) + clear_unused_bits(); + } + +public: + /// Return the size (in bytes) of the bit vector. + size_t getMemorySize() const { return Bits.size() * sizeof(BitWord); } + size_t getBitCapacity() const { return Bits.size() * BITWORD_SIZE; } +}; + +inline size_t capacity_in_bytes(const BitVector &X) { + return X.getMemorySize(); +} + +} // end namespace llvm + +namespace std { + /// Implement std::swap in terms of BitVector swap. + inline void + swap(llvm::BitVector &LHS, llvm::BitVector &RHS) { + LHS.swap(RHS); + } +} // end namespace std + +#endif // LLVM_ADT_BITVECTOR_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/BitmaskEnum.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/BitmaskEnum.h new file mode 100644 index 0000000..1a18bc7 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/BitmaskEnum.h
@@ -0,0 +1,152 @@ +//===-- llvm/ADT/BitmaskEnum.h ----------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#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
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/BreadthFirstIterator.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/BreadthFirstIterator.h new file mode 100644 index 0000000..e97d766 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/BreadthFirstIterator.h
@@ -0,0 +1,162 @@ +//===- llvm/ADT/BreadthFirstIterator.h - Breadth First iterator -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file builds on the ADT/GraphTraits.h file to build a generic breadth +// first graph iterator. This file exposes the following functions/types: +// +// bf_begin/bf_end/bf_iterator +// * Normal breadth-first iteration - visit a graph level-by-level. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_BREADTHFIRSTITERATOR_H +#define LLVM_ADT_BREADTHFIRSTITERATOR_H + +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/iterator_range.h" +#include <iterator> +#include <queue> +#include <utility> + +namespace llvm { + +// bf_iterator_storage - A private class which is used to figure out where to +// store the visited set. We only provide a non-external variant for now. +template <class SetType> class bf_iterator_storage { +public: + SetType Visited; +}; + +// The visited state for the iteration is a simple set. +template <typename NodeRef, unsigned SmallSize = 8> +using bf_iterator_default_set = SmallPtrSet<NodeRef, SmallSize>; + +// Generic Breadth first search iterator. +template <class GraphT, + class SetType = + bf_iterator_default_set<typename GraphTraits<GraphT>::NodeRef>, + class GT = GraphTraits<GraphT>> +class bf_iterator + : public std::iterator<std::forward_iterator_tag, typename GT::NodeRef>, + public bf_iterator_storage<SetType> { + using super = std::iterator<std::forward_iterator_tag, typename GT::NodeRef>; + + using NodeRef = typename GT::NodeRef; + using ChildItTy = typename GT::ChildIteratorType; + + // First element is the node reference, second is the next child to visit. + using QueueElement = std::pair<NodeRef, Optional<ChildItTy>>; + + // Visit queue - used to maintain BFS ordering. + // Optional<> because we need markers for levels. + std::queue<Optional<QueueElement>> VisitQueue; + + // Current level. + unsigned Level; + +private: + inline bf_iterator(NodeRef Node) { + this->Visited.insert(Node); + Level = 0; + + // Also, insert a dummy node as marker. + VisitQueue.push(QueueElement(Node, None)); + VisitQueue.push(None); + } + + inline bf_iterator() = default; + + inline void toNext() { + Optional<QueueElement> Head = VisitQueue.front(); + QueueElement H = Head.getValue(); + NodeRef Node = H.first; + Optional<ChildItTy> &ChildIt = H.second; + + if (!ChildIt) + ChildIt.emplace(GT::child_begin(Node)); + while (*ChildIt != GT::child_end(Node)) { + NodeRef Next = *(*ChildIt)++; + + // Already visited? + if (this->Visited.insert(Next).second) + VisitQueue.push(QueueElement(Next, None)); + } + VisitQueue.pop(); + + // Go to the next element skipping markers if needed. + if (!VisitQueue.empty()) { + Head = VisitQueue.front(); + if (Head != None) + return; + Level += 1; + VisitQueue.pop(); + + // Don't push another marker if this is the last + // element. + if (!VisitQueue.empty()) + VisitQueue.push(None); + } + } + +public: + using pointer = typename super::pointer; + + // Provide static begin and end methods as our public "constructors" + static bf_iterator begin(const GraphT &G) { + return bf_iterator(GT::getEntryNode(G)); + } + + static bf_iterator end(const GraphT &G) { return bf_iterator(); } + + bool operator==(const bf_iterator &RHS) const { + return VisitQueue == RHS.VisitQueue; + } + + bool operator!=(const bf_iterator &RHS) const { return !(*this == RHS); } + + const NodeRef &operator*() const { return VisitQueue.front()->first; } + + // This is a nonstandard operator-> that dereferences the pointer an extra + // time so that you can actually call methods on the node, because the + // contained type is a pointer. + NodeRef operator->() const { return **this; } + + bf_iterator &operator++() { // Pre-increment + toNext(); + return *this; + } + + bf_iterator operator++(int) { // Post-increment + bf_iterator ItCopy = *this; + ++*this; + return ItCopy; + } + + unsigned getLevel() const { return Level; } +}; + +// Provide global constructors that automatically figure out correct types. +template <class T> bf_iterator<T> bf_begin(const T &G) { + return bf_iterator<T>::begin(G); +} + +template <class T> bf_iterator<T> bf_end(const T &G) { + return bf_iterator<T>::end(G); +} + +// Provide an accessor method to use them in range-based patterns. +template <class T> iterator_range<bf_iterator<T>> breadth_first(const T &G) { + return make_range(bf_begin(G), bf_end(G)); +} + +} // end namespace llvm + +#endif // LLVM_ADT_BREADTHFIRSTITERATOR_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/CachedHashString.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/CachedHashString.h new file mode 100644 index 0000000..80144fb --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/CachedHashString.h
@@ -0,0 +1,184 @@ +//===- llvm/ADT/CachedHashString.h - Prehashed string/StringRef -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines CachedHashString and CachedHashStringRef. These are owning +// and not-owning string types that store their hash in addition to their string +// data. +// +// Unlike std::string, CachedHashString can be used in DenseSet/DenseMap +// (because, unlike std::string, CachedHashString lets us have empty and +// tombstone values). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_CACHED_HASH_STRING_H +#define LLVM_ADT_CACHED_HASH_STRING_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +/// A container which contains a StringRef plus a precomputed hash. +class CachedHashStringRef { + const char *P; + uint32_t Size; + uint32_t Hash; + +public: + // Explicit because hashing a string isn't free. + explicit CachedHashStringRef(StringRef S) + : CachedHashStringRef(S, DenseMapInfo<StringRef>::getHashValue(S)) {} + + CachedHashStringRef(StringRef S, uint32_t Hash) + : P(S.data()), Size(S.size()), Hash(Hash) { + assert(S.size() <= std::numeric_limits<uint32_t>::max()); + } + + StringRef val() const { return StringRef(P, Size); } + const char *data() const { return P; } + uint32_t size() const { return Size; } + uint32_t hash() const { return Hash; } +}; + +template <> struct DenseMapInfo<CachedHashStringRef> { + static CachedHashStringRef getEmptyKey() { + return CachedHashStringRef(DenseMapInfo<StringRef>::getEmptyKey(), 0); + } + static CachedHashStringRef getTombstoneKey() { + return CachedHashStringRef(DenseMapInfo<StringRef>::getTombstoneKey(), 1); + } + static unsigned getHashValue(const CachedHashStringRef &S) { + assert(!isEqual(S, getEmptyKey()) && "Cannot hash the empty key!"); + assert(!isEqual(S, getTombstoneKey()) && "Cannot hash the tombstone key!"); + return S.hash(); + } + static bool isEqual(const CachedHashStringRef &LHS, + const CachedHashStringRef &RHS) { + return LHS.hash() == RHS.hash() && + DenseMapInfo<StringRef>::isEqual(LHS.val(), RHS.val()); + } +}; + +/// A container which contains a string, which it owns, plus a precomputed hash. +/// +/// We do not null-terminate the string. +class CachedHashString { + friend struct DenseMapInfo<CachedHashString>; + + char *P; + uint32_t Size; + uint32_t Hash; + + static char *getEmptyKeyPtr() { return DenseMapInfo<char *>::getEmptyKey(); } + static char *getTombstoneKeyPtr() { + return DenseMapInfo<char *>::getTombstoneKey(); + } + + bool isEmptyOrTombstone() const { + return P == getEmptyKeyPtr() || P == getTombstoneKeyPtr(); + } + + struct ConstructEmptyOrTombstoneTy {}; + + CachedHashString(ConstructEmptyOrTombstoneTy, char *EmptyOrTombstonePtr) + : P(EmptyOrTombstonePtr), Size(0), Hash(0) { + assert(isEmptyOrTombstone()); + } + + // TODO: Use small-string optimization to avoid allocating. + +public: + explicit CachedHashString(const char *S) : CachedHashString(StringRef(S)) {} + + // Explicit because copying and hashing a string isn't free. + explicit CachedHashString(StringRef S) + : CachedHashString(S, DenseMapInfo<StringRef>::getHashValue(S)) {} + + CachedHashString(StringRef S, uint32_t Hash) + : P(new char[S.size()]), Size(S.size()), Hash(Hash) { + memcpy(P, S.data(), S.size()); + } + + // Ideally this class would not be copyable. But SetVector requires copyable + // keys, and we want this to be usable there. + CachedHashString(const CachedHashString &Other) + : Size(Other.Size), Hash(Other.Hash) { + if (Other.isEmptyOrTombstone()) { + P = Other.P; + } else { + P = new char[Size]; + memcpy(P, Other.P, Size); + } + } + + CachedHashString &operator=(CachedHashString Other) { + swap(*this, Other); + return *this; + } + + CachedHashString(CachedHashString &&Other) noexcept + : P(Other.P), Size(Other.Size), Hash(Other.Hash) { + Other.P = getEmptyKeyPtr(); + } + + ~CachedHashString() { + if (!isEmptyOrTombstone()) + delete[] P; + } + + StringRef val() const { return StringRef(P, Size); } + uint32_t size() const { return Size; } + uint32_t hash() const { return Hash; } + + operator StringRef() const { return val(); } + operator CachedHashStringRef() const { + return CachedHashStringRef(val(), Hash); + } + + friend void swap(CachedHashString &LHS, CachedHashString &RHS) { + using std::swap; + swap(LHS.P, RHS.P); + swap(LHS.Size, RHS.Size); + swap(LHS.Hash, RHS.Hash); + } +}; + +template <> struct DenseMapInfo<CachedHashString> { + static CachedHashString getEmptyKey() { + return CachedHashString(CachedHashString::ConstructEmptyOrTombstoneTy(), + CachedHashString::getEmptyKeyPtr()); + } + static CachedHashString getTombstoneKey() { + return CachedHashString(CachedHashString::ConstructEmptyOrTombstoneTy(), + CachedHashString::getTombstoneKeyPtr()); + } + static unsigned getHashValue(const CachedHashString &S) { + assert(!isEqual(S, getEmptyKey()) && "Cannot hash the empty key!"); + assert(!isEqual(S, getTombstoneKey()) && "Cannot hash the tombstone key!"); + return S.hash(); + } + static bool isEqual(const CachedHashString &LHS, + const CachedHashString &RHS) { + if (LHS.hash() != RHS.hash()) + return false; + if (LHS.P == CachedHashString::getEmptyKeyPtr()) + return RHS.P == CachedHashString::getEmptyKeyPtr(); + if (LHS.P == CachedHashString::getTombstoneKeyPtr()) + return RHS.P == CachedHashString::getTombstoneKeyPtr(); + + // This is safe because if RHS.P is the empty or tombstone key, it will have + // length 0, so we'll never dereference its pointer. + return LHS.val() == RHS.val(); + } +}; + +} // namespace llvm + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/DAGDeltaAlgorithm.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/DAGDeltaAlgorithm.h new file mode 100644 index 0000000..d4cdc3c --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/DAGDeltaAlgorithm.h
@@ -0,0 +1,78 @@ +//===- DAGDeltaAlgorithm.h - A DAG Minimization Algorithm ------*- C++ -*--===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_DAGDELTAALGORITHM_H +#define LLVM_ADT_DAGDELTAALGORITHM_H + +#include <set> +#include <utility> +#include <vector> + +namespace llvm { + +/// DAGDeltaAlgorithm - Implements a "delta debugging" algorithm for minimizing +/// directed acyclic graphs using a predicate function. +/// +/// The result of the algorithm is a subset of the input change set which is +/// guaranteed to satisfy the predicate, assuming that the input set did. For +/// well formed predicates, the result set is guaranteed to be such that +/// removing any single element not required by the dependencies on the other +/// elements would falsify the predicate. +/// +/// The DAG should be used to represent dependencies in the changes which are +/// likely to hold across the predicate function. That is, for a particular +/// changeset S and predicate P: +/// +/// P(S) => P(S union pred(S)) +/// +/// The minization algorithm uses this dependency information to attempt to +/// eagerly prune large subsets of changes. As with \see DeltaAlgorithm, the DAG +/// is not required to satisfy this property, but the algorithm will run +/// substantially fewer tests with appropriate dependencies. \see DeltaAlgorithm +/// for more information on the properties which the predicate function itself +/// should satisfy. +class DAGDeltaAlgorithm { + virtual void anchor(); + +public: + using change_ty = unsigned; + using edge_ty = std::pair<change_ty, change_ty>; + + // FIXME: Use a decent data structure. + using changeset_ty = std::set<change_ty>; + using changesetlist_ty = std::vector<changeset_ty>; + +public: + virtual ~DAGDeltaAlgorithm() = default; + + /// Run - Minimize the DAG formed by the \p Changes vertices and the + /// \p Dependencies edges by executing \see ExecuteOneTest() on subsets of + /// changes and returning the smallest set which still satisfies the test + /// predicate and the input \p Dependencies. + /// + /// \param Changes The list of changes. + /// + /// \param Dependencies The list of dependencies amongst changes. For each + /// (x,y) in \p Dependencies, both x and y must be in \p Changes. The + /// minimization algorithm guarantees that for each tested changed set S, + /// \f$ x \in S \f$ implies \f$ y \in S \f$. It is an error to have cyclic + /// dependencies. + changeset_ty Run(const changeset_ty &Changes, + const std::vector<edge_ty> &Dependencies); + + /// UpdatedSearchState - Callback used when the search state changes. + virtual void UpdatedSearchState(const changeset_ty &Changes, + const changesetlist_ty &Sets, + const changeset_ty &Required) {} + + /// ExecuteOneTest - Execute a single test predicate on the change set \p S. + virtual bool ExecuteOneTest(const changeset_ty &S) = 0; +}; + +} // end namespace llvm + +#endif // LLVM_ADT_DAGDELTAALGORITHM_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/DeltaAlgorithm.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/DeltaAlgorithm.h new file mode 100644 index 0000000..114b954 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/DeltaAlgorithm.h
@@ -0,0 +1,92 @@ +//===- DeltaAlgorithm.h - A Set Minimization Algorithm ---------*- C++ -*--===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_DELTAALGORITHM_H +#define LLVM_ADT_DELTAALGORITHM_H + +#include <set> +#include <vector> + +namespace llvm { + +/// DeltaAlgorithm - Implements the delta debugging algorithm (A. Zeller '99) +/// for minimizing arbitrary sets using a predicate function. +/// +/// The result of the algorithm is a subset of the input change set which is +/// guaranteed to satisfy the predicate, assuming that the input set did. For +/// well formed predicates, the result set is guaranteed to be such that +/// removing any single element would falsify the predicate. +/// +/// For best results the predicate function *should* (but need not) satisfy +/// certain properties, in particular: +/// (1) The predicate should return false on an empty set and true on the full +/// set. +/// (2) If the predicate returns true for a set of changes, it should return +/// true for all supersets of that set. +/// +/// It is not an error to provide a predicate that does not satisfy these +/// requirements, and the algorithm will generally produce reasonable +/// results. However, it may run substantially more tests than with a good +/// predicate. +class DeltaAlgorithm { +public: + using change_ty = unsigned; + // FIXME: Use a decent data structure. + using changeset_ty = std::set<change_ty>; + using changesetlist_ty = std::vector<changeset_ty>; + +private: + /// Cache of failed test results. Successful test results are never cached + /// since we always reduce following a success. + std::set<changeset_ty> FailedTestsCache; + + /// GetTestResult - Get the test result for the \p Changes from the + /// cache, executing the test if necessary. + /// + /// \param Changes - The change set to test. + /// \return - The test result. + bool GetTestResult(const changeset_ty &Changes); + + /// Split - Partition a set of changes \p S into one or two subsets. + void Split(const changeset_ty &S, changesetlist_ty &Res); + + /// Delta - Minimize a set of \p Changes which has been partioned into + /// smaller sets, by attempting to remove individual subsets. + changeset_ty Delta(const changeset_ty &Changes, + const changesetlist_ty &Sets); + + /// Search - Search for a subset (or subsets) in \p Sets which can be + /// removed from \p Changes while still satisfying the predicate. + /// + /// \param Res - On success, a subset of Changes which satisfies the + /// predicate. + /// \return - True on success. + bool Search(const changeset_ty &Changes, const changesetlist_ty &Sets, + changeset_ty &Res); + +protected: + /// UpdatedSearchState - Callback used when the search state changes. + virtual void UpdatedSearchState(const changeset_ty &Changes, + const changesetlist_ty &Sets) {} + + /// ExecuteOneTest - Execute a single test predicate on the change set \p S. + virtual bool ExecuteOneTest(const changeset_ty &S) = 0; + + DeltaAlgorithm& operator=(const DeltaAlgorithm&) = default; + +public: + virtual ~DeltaAlgorithm(); + + /// Run - Minimize the set \p Changes by executing \see ExecuteOneTest() on + /// subsets of changes and returning the smallest set which still satisfies + /// the test predicate. + changeset_ty Run(const changeset_ty &Changes); +}; + +} // end namespace llvm + +#endif // LLVM_ADT_DELTAALGORITHM_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/DenseMap.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/DenseMap.h new file mode 100644 index 0000000..148d319 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/DenseMap.h
@@ -0,0 +1,1275 @@ +//===- llvm/ADT/DenseMap.h - Dense probed hash table ------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the DenseMap class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_DENSEMAP_H +#define LLVM_ADT_DENSEMAP_H + +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/ADT/EpochTracker.h" +#include "llvm/Support/AlignOf.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/ReverseIteration.h" +#include "llvm/Support/type_traits.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstring> +#include <initializer_list> +#include <iterator> +#include <new> +#include <type_traits> +#include <utility> + +namespace llvm { + +namespace detail { + +// We extend a pair to allow users to override the bucket type with their own +// implementation without requiring two members. +template <typename KeyT, typename ValueT> +struct DenseMapPair : public std::pair<KeyT, ValueT> { + using std::pair<KeyT, ValueT>::pair; + + KeyT &getFirst() { return std::pair<KeyT, ValueT>::first; } + const KeyT &getFirst() const { return std::pair<KeyT, ValueT>::first; } + ValueT &getSecond() { return std::pair<KeyT, ValueT>::second; } + const ValueT &getSecond() const { return std::pair<KeyT, ValueT>::second; } +}; + +} // end namespace detail + +template <typename KeyT, typename ValueT, + typename KeyInfoT = DenseMapInfo<KeyT>, + typename Bucket = llvm::detail::DenseMapPair<KeyT, ValueT>, + bool IsConst = false> +class DenseMapIterator; + +template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT, + typename BucketT> +class DenseMapBase : public DebugEpochBase { + template <typename T> + using const_arg_type_t = typename const_pointer_or_const_ref<T>::type; + +public: + using size_type = unsigned; + using key_type = KeyT; + using mapped_type = ValueT; + using value_type = BucketT; + + using iterator = DenseMapIterator<KeyT, ValueT, KeyInfoT, BucketT>; + using const_iterator = + DenseMapIterator<KeyT, ValueT, KeyInfoT, BucketT, true>; + + inline iterator begin() { + // When the map is empty, avoid the overhead of advancing/retreating past + // empty buckets. + if (empty()) + return end(); + if (shouldReverseIterate<KeyT>()) + return makeIterator(getBucketsEnd() - 1, getBuckets(), *this); + return makeIterator(getBuckets(), getBucketsEnd(), *this); + } + inline iterator end() { + return makeIterator(getBucketsEnd(), getBucketsEnd(), *this, true); + } + inline const_iterator begin() const { + if (empty()) + return end(); + if (shouldReverseIterate<KeyT>()) + return makeConstIterator(getBucketsEnd() - 1, getBuckets(), *this); + return makeConstIterator(getBuckets(), getBucketsEnd(), *this); + } + inline const_iterator end() const { + return makeConstIterator(getBucketsEnd(), getBucketsEnd(), *this, true); + } + + LLVM_NODISCARD bool empty() const { + return getNumEntries() == 0; + } + unsigned size() const { return getNumEntries(); } + + /// 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 (NumBuckets > getNumBuckets()) + grow(NumBuckets); + } + + void clear() { + incrementEpoch(); + if (getNumEntries() == 0 && getNumTombstones() == 0) return; + + // If the capacity of the array is huge, and the # elements used is small, + // shrink the array. + if (getNumEntries() * 4 < getNumBuckets() && getNumBuckets() > 64) { + shrink_and_clear(); + return; + } + + const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); + if (is_trivially_copyable<KeyT>::value && + is_trivially_copyable<ValueT>::value) { + // Use a simpler loop when these are trivial types. + for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) + P->getFirst() = EmptyKey; + } else { + unsigned NumEntries = getNumEntries(); + for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) { + if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey)) { + if (!KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) { + P->getSecond().~ValueT(); + --NumEntries; + } + P->getFirst() = EmptyKey; + } + } + assert(NumEntries == 0 && "Node count imbalance!"); + } + setNumEntries(0); + setNumTombstones(0); + } + + /// Return 1 if the specified key is in the map, 0 otherwise. + size_type count(const_arg_type_t<KeyT> Val) const { + const BucketT *TheBucket; + return LookupBucketFor(Val, TheBucket) ? 1 : 0; + } + + iterator find(const_arg_type_t<KeyT> Val) { + BucketT *TheBucket; + if (LookupBucketFor(Val, TheBucket)) + return makeIterator(TheBucket, getBucketsEnd(), *this, true); + return end(); + } + const_iterator find(const_arg_type_t<KeyT> Val) const { + const BucketT *TheBucket; + if (LookupBucketFor(Val, TheBucket)) + return makeConstIterator(TheBucket, getBucketsEnd(), *this, true); + return end(); + } + + /// Alternate version of find() 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<class LookupKeyT> + iterator find_as(const LookupKeyT &Val) { + BucketT *TheBucket; + if (LookupBucketFor(Val, TheBucket)) + return makeIterator(TheBucket, getBucketsEnd(), *this, true); + return end(); + } + template<class LookupKeyT> + const_iterator find_as(const LookupKeyT &Val) const { + const BucketT *TheBucket; + if (LookupBucketFor(Val, TheBucket)) + return makeConstIterator(TheBucket, getBucketsEnd(), *this, true); + return end(); + } + + /// lookup - Return the entry for the specified key, or a default + /// constructed value if no such entry exists. + ValueT lookup(const_arg_type_t<KeyT> Val) const { + const BucketT *TheBucket; + if (LookupBucketFor(Val, TheBucket)) + return TheBucket->getSecond(); + return ValueT(); + } + + // Inserts key,value pair into the map if the key isn't already in the map. + // If the key is already in the map, it returns false and doesn't update the + // value. + std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) { + return try_emplace(KV.first, KV.second); + } + + // Inserts key,value pair into the map if the key isn't already in the map. + // If the key is already in the map, it returns false and doesn't update the + // value. + std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) { + return try_emplace(std::move(KV.first), std::move(KV.second)); + } + + // Inserts key,value pair into the map if the key isn't already in the map. + // The value is constructed in-place if the key is not in the map, otherwise + // it is not moved. + template <typename... Ts> + std::pair<iterator, bool> try_emplace(KeyT &&Key, Ts &&... Args) { + BucketT *TheBucket; + if (LookupBucketFor(Key, TheBucket)) + return std::make_pair( + makeIterator(TheBucket, getBucketsEnd(), *this, true), + false); // Already in map. + + // Otherwise, insert the new element. + TheBucket = + InsertIntoBucket(TheBucket, std::move(Key), std::forward<Ts>(Args)...); + return std::make_pair( + makeIterator(TheBucket, getBucketsEnd(), *this, true), + true); + } + + // Inserts key,value pair into the map if the key isn't already in the map. + // The value is constructed in-place if the key is not in the map, otherwise + // it is not moved. + template <typename... Ts> + std::pair<iterator, bool> try_emplace(const KeyT &Key, Ts &&... Args) { + BucketT *TheBucket; + if (LookupBucketFor(Key, TheBucket)) + return std::make_pair( + makeIterator(TheBucket, getBucketsEnd(), *this, true), + false); // Already in map. + + // Otherwise, insert the new element. + TheBucket = InsertIntoBucket(TheBucket, Key, std::forward<Ts>(Args)...); + return std::make_pair( + makeIterator(TheBucket, getBucketsEnd(), *this, true), + 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( + makeIterator(TheBucket, getBucketsEnd(), *this, true), + false); // Already in map. + + // Otherwise, insert the new element. + TheBucket = InsertIntoBucketWithLookup(TheBucket, std::move(KV.first), + std::move(KV.second), Val); + return std::make_pair( + makeIterator(TheBucket, getBucketsEnd(), *this, true), + true); + } + + /// insert - Range insertion of pairs. + template<typename InputIt> + void insert(InputIt I, InputIt E) { + for (; I != E; ++I) + insert(*I); + } + + bool erase(const KeyT &Val) { + BucketT *TheBucket; + if (!LookupBucketFor(Val, TheBucket)) + return false; // not in map. + + TheBucket->getSecond().~ValueT(); + TheBucket->getFirst() = getTombstoneKey(); + decrementNumEntries(); + incrementNumTombstones(); + return true; + } + void erase(iterator I) { + BucketT *TheBucket = &*I; + TheBucket->getSecond().~ValueT(); + TheBucket->getFirst() = getTombstoneKey(); + decrementNumEntries(); + incrementNumTombstones(); + } + + value_type& FindAndConstruct(const KeyT &Key) { + BucketT *TheBucket; + if (LookupBucketFor(Key, TheBucket)) + return *TheBucket; + + return *InsertIntoBucket(TheBucket, Key); + } + + ValueT &operator[](const KeyT &Key) { + return FindAndConstruct(Key).second; + } + + value_type& FindAndConstruct(KeyT &&Key) { + BucketT *TheBucket; + if (LookupBucketFor(Key, TheBucket)) + return *TheBucket; + + return *InsertIntoBucket(TheBucket, std::move(Key)); + } + + ValueT &operator[](KeyT &&Key) { + return FindAndConstruct(std::move(Key)).second; + } + + /// isPointerIntoBucketsArray - Return true if the specified pointer points + /// somewhere into the DenseMap's array of buckets (i.e. either to a key or + /// value in the DenseMap). + bool isPointerIntoBucketsArray(const void *Ptr) const { + return Ptr >= getBuckets() && Ptr < getBucketsEnd(); + } + + /// getPointerIntoBucketsArray() - Return an opaque pointer into the buckets + /// array. In conjunction with the previous method, this can be used to + /// determine whether an insertion caused the DenseMap to reallocate. + const void *getPointerIntoBucketsArray() const { return getBuckets(); } + +protected: + DenseMapBase() = default; + + void destroyAll() { + if (getNumBuckets() == 0) // Nothing to do. + return; + + const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); + for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) { + if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) + P->getSecond().~ValueT(); + P->getFirst().~KeyT(); + } + } + + void initEmpty() { + setNumEntries(0); + setNumTombstones(0); + + assert((getNumBuckets() & (getNumBuckets()-1)) == 0 && + "# initial buckets must be a power of two!"); + const KeyT EmptyKey = getEmptyKey(); + for (BucketT *B = getBuckets(), *E = getBucketsEnd(); B != E; ++B) + ::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(); + + // Insert all the old elements. + const KeyT EmptyKey = getEmptyKey(); + const KeyT TombstoneKey = getTombstoneKey(); + for (BucketT *B = OldBucketsBegin, *E = OldBucketsEnd; B != E; ++B) { + if (!KeyInfoT::isEqual(B->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(B->getFirst(), TombstoneKey)) { + // Insert the key/value into the new table. + BucketT *DestBucket; + bool FoundVal = LookupBucketFor(B->getFirst(), DestBucket); + (void)FoundVal; // silence warning. + assert(!FoundVal && "Key already in new map?"); + DestBucket->getFirst() = std::move(B->getFirst()); + ::new (&DestBucket->getSecond()) ValueT(std::move(B->getSecond())); + incrementNumEntries(); + + // Free the value. + B->getSecond().~ValueT(); + } + B->getFirst().~KeyT(); + } + } + + template <typename OtherBaseT> + void copyFrom( + const DenseMapBase<OtherBaseT, KeyT, ValueT, KeyInfoT, BucketT> &other) { + assert(&other != this); + assert(getNumBuckets() == other.getNumBuckets()); + + setNumEntries(other.getNumEntries()); + setNumTombstones(other.getNumTombstones()); + + if (is_trivially_copyable<KeyT>::value && + is_trivially_copyable<ValueT>::value) + memcpy(reinterpret_cast<void *>(getBuckets()), other.getBuckets(), + getNumBuckets() * sizeof(BucketT)); + else + for (size_t i = 0; i < getNumBuckets(); ++i) { + ::new (&getBuckets()[i].getFirst()) + KeyT(other.getBuckets()[i].getFirst()); + if (!KeyInfoT::isEqual(getBuckets()[i].getFirst(), getEmptyKey()) && + !KeyInfoT::isEqual(getBuckets()[i].getFirst(), getTombstoneKey())) + ::new (&getBuckets()[i].getSecond()) + ValueT(other.getBuckets()[i].getSecond()); + } + } + + static unsigned getHashValue(const KeyT &Val) { + return KeyInfoT::getHashValue(Val); + } + + template<typename LookupKeyT> + static unsigned getHashValue(const LookupKeyT &Val) { + return KeyInfoT::getHashValue(Val); + } + + static const KeyT getEmptyKey() { + static_assert(std::is_base_of<DenseMapBase, DerivedT>::value, + "Must pass the derived type to this template!"); + return KeyInfoT::getEmptyKey(); + } + + static const KeyT getTombstoneKey() { + return KeyInfoT::getTombstoneKey(); + } + +private: + iterator makeIterator(BucketT *P, BucketT *E, + DebugEpochBase &Epoch, + bool NoAdvance=false) { + if (shouldReverseIterate<KeyT>()) { + BucketT *B = P == getBucketsEnd() ? getBuckets() : P + 1; + return iterator(B, E, Epoch, NoAdvance); + } + return iterator(P, E, Epoch, NoAdvance); + } + + const_iterator makeConstIterator(const BucketT *P, const BucketT *E, + const DebugEpochBase &Epoch, + const bool NoAdvance=false) const { + if (shouldReverseIterate<KeyT>()) { + const BucketT *B = P == getBucketsEnd() ? getBuckets() : P + 1; + return const_iterator(B, E, Epoch, NoAdvance); + } + return const_iterator(P, E, Epoch, NoAdvance); + } + + unsigned getNumEntries() const { + return static_cast<const DerivedT *>(this)->getNumEntries(); + } + + void setNumEntries(unsigned Num) { + static_cast<DerivedT *>(this)->setNumEntries(Num); + } + + void incrementNumEntries() { + setNumEntries(getNumEntries() + 1); + } + + void decrementNumEntries() { + setNumEntries(getNumEntries() - 1); + } + + unsigned getNumTombstones() const { + return static_cast<const DerivedT *>(this)->getNumTombstones(); + } + + void setNumTombstones(unsigned Num) { + static_cast<DerivedT *>(this)->setNumTombstones(Num); + } + + void incrementNumTombstones() { + setNumTombstones(getNumTombstones() + 1); + } + + void decrementNumTombstones() { + setNumTombstones(getNumTombstones() - 1); + } + + const BucketT *getBuckets() const { + return static_cast<const DerivedT *>(this)->getBuckets(); + } + + BucketT *getBuckets() { + return static_cast<DerivedT *>(this)->getBuckets(); + } + + unsigned getNumBuckets() const { + return static_cast<const DerivedT *>(this)->getNumBuckets(); + } + + BucketT *getBucketsEnd() { + return getBuckets() + getNumBuckets(); + } + + const BucketT *getBucketsEnd() const { + return getBuckets() + getNumBuckets(); + } + + void grow(unsigned AtLeast) { + static_cast<DerivedT *>(this)->grow(AtLeast); + } + + void shrink_and_clear() { + static_cast<DerivedT *>(this)->shrink_and_clear(); + } + + template <typename KeyArg, typename... ValueArgs> + BucketT *InsertIntoBucket(BucketT *TheBucket, KeyArg &&Key, + ValueArgs &&... Values) { + TheBucket = InsertIntoBucketImpl(Key, Key, TheBucket); + + TheBucket->getFirst() = std::forward<KeyArg>(Key); + ::new (&TheBucket->getSecond()) ValueT(std::forward<ValueArgs>(Values)...); + return TheBucket; + } + + template <typename LookupKeyT> + BucketT *InsertIntoBucketWithLookup(BucketT *TheBucket, KeyT &&Key, + ValueT &&Value, LookupKeyT &Lookup) { + 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 + // the buckets are empty (meaning that many are filled with tombstones), + // grow the table. + // + // The later case is tricky. For example, if we had one empty bucket with + // tons of tombstones, failing lookups (e.g. for insertion) would have to + // probe almost the entire table until it found the empty bucket. If the + // table completely filled with tombstones, no lookup would ever succeed, + // causing infinite loops in lookup. + unsigned NewNumEntries = getNumEntries() + 1; + unsigned NumBuckets = getNumBuckets(); + if (LLVM_UNLIKELY(NewNumEntries * 4 >= NumBuckets * 3)) { + this->grow(NumBuckets * 2); + LookupBucketFor(Lookup, TheBucket); + NumBuckets = getNumBuckets(); + } else if (LLVM_UNLIKELY(NumBuckets-(NewNumEntries+getNumTombstones()) <= + NumBuckets/8)) { + this->grow(NumBuckets); + LookupBucketFor(Lookup, TheBucket); + } + assert(TheBucket); + + // Only update the state after we've grown our bucket space appropriately + // so that when growing buckets we have self-consistent entry count. + incrementNumEntries(); + + // If we are writing over a tombstone, remember this. + const KeyT EmptyKey = getEmptyKey(); + if (!KeyInfoT::isEqual(TheBucket->getFirst(), EmptyKey)) + decrementNumTombstones(); + + return TheBucket; + } + + /// LookupBucketFor - Lookup the appropriate bucket for Val, returning it in + /// FoundBucket. If the bucket contains the key and a value, this returns + /// true, otherwise it returns a bucket with an empty marker or tombstone and + /// returns false. + template<typename LookupKeyT> + bool LookupBucketFor(const LookupKeyT &Val, + const BucketT *&FoundBucket) const { + const BucketT *BucketsPtr = getBuckets(); + const unsigned NumBuckets = getNumBuckets(); + + if (NumBuckets == 0) { + FoundBucket = nullptr; + return false; + } + + // FoundTombstone - Keep track of whether we find a tombstone while probing. + const BucketT *FoundTombstone = nullptr; + const KeyT EmptyKey = getEmptyKey(); + const KeyT TombstoneKey = getTombstoneKey(); + assert(!KeyInfoT::isEqual(Val, EmptyKey) && + !KeyInfoT::isEqual(Val, TombstoneKey) && + "Empty/Tombstone value shouldn't be inserted into map!"); + + unsigned BucketNo = getHashValue(Val) & (NumBuckets-1); + unsigned ProbeAmt = 1; + while (true) { + const BucketT *ThisBucket = BucketsPtr + BucketNo; + // Found Val's bucket? If so, return it. + if (LLVM_LIKELY(KeyInfoT::isEqual(Val, ThisBucket->getFirst()))) { + FoundBucket = ThisBucket; + return true; + } + + // If we found an empty bucket, the key doesn't exist in the set. + // Insert it and return the default value. + if (LLVM_LIKELY(KeyInfoT::isEqual(ThisBucket->getFirst(), EmptyKey))) { + // If we've already seen a tombstone while probing, fill it in instead + // of the empty bucket we eventually probed to. + FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket; + return false; + } + + // If this is a tombstone, remember it. If Val ends up not in the map, we + // prefer to return it than something that would require more probing. + if (KeyInfoT::isEqual(ThisBucket->getFirst(), TombstoneKey) && + !FoundTombstone) + FoundTombstone = ThisBucket; // Remember the first tombstone found. + + // Otherwise, it's a hash collision or a tombstone, continue quadratic + // probing. + BucketNo += ProbeAmt++; + BucketNo &= (NumBuckets-1); + } + } + + template <typename LookupKeyT> + bool LookupBucketFor(const LookupKeyT &Val, BucketT *&FoundBucket) { + const BucketT *ConstFoundBucket; + bool Result = const_cast<const DenseMapBase *>(this) + ->LookupBucketFor(Val, ConstFoundBucket); + FoundBucket = const_cast<BucketT *>(ConstFoundBucket); + return Result; + } + +public: + /// Return the approximate size (in bytes) of the actual map. + /// This is just the raw memory used by DenseMap. + /// If entries are pointers to objects, the size of the referenced objects + /// are not included. + size_t getMemorySize() const { + return getNumBuckets() * sizeof(BucketT); + } +}; + +/// Equality comparison for DenseMap. +/// +/// Iterates over elements of LHS confirming that each (key, value) pair in LHS +/// is also in RHS, and that no additional pairs are in RHS. +/// Equivalent to N calls to RHS.find and N value comparisons. Amortized +/// complexity is linear, worst case is O(N^2) (if every hash collides). +template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT, + typename BucketT> +bool operator==( + const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &LHS, + const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &RHS) { + if (LHS.size() != RHS.size()) + return false; + + for (auto &KV : LHS) { + auto I = RHS.find(KV.first); + if (I == RHS.end() || I->second != KV.second) + return false; + } + + return true; +} + +/// Inequality comparison for DenseMap. +/// +/// Equivalent to !(LHS == RHS). See operator== for performance notes. +template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT, + typename BucketT> +bool operator!=( + const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &LHS, + const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &RHS) { + return !(LHS == RHS); +} + +template <typename KeyT, typename ValueT, + typename KeyInfoT = DenseMapInfo<KeyT>, + typename BucketT = llvm::detail::DenseMapPair<KeyT, ValueT>> +class DenseMap : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>, + KeyT, ValueT, KeyInfoT, BucketT> { + friend class DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT>; + + // Lift some types from the dependent base class into this class for + // simplicity of referring to them. + using BaseT = DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT>; + + BucketT *Buckets; + unsigned NumEntries; + unsigned NumTombstones; + unsigned NumBuckets; + +public: + /// 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); + copyFrom(other); + } + + DenseMap(DenseMap &&other) : BaseT() { + init(0); + swap(other); + } + + template<typename InputIt> + DenseMap(const InputIt &I, const InputIt &E) { + init(std::distance(I, E)); + this->insert(I, E); + } + + DenseMap(std::initializer_list<typename BaseT::value_type> Vals) { + init(Vals.size()); + this->insert(Vals.begin(), Vals.end()); + } + + ~DenseMap() { + this->destroyAll(); + deallocate_buffer(Buckets, sizeof(BucketT) * NumBuckets, alignof(BucketT)); + } + + void swap(DenseMap& RHS) { + this->incrementEpoch(); + RHS.incrementEpoch(); + std::swap(Buckets, RHS.Buckets); + std::swap(NumEntries, RHS.NumEntries); + std::swap(NumTombstones, RHS.NumTombstones); + std::swap(NumBuckets, RHS.NumBuckets); + } + + DenseMap& operator=(const DenseMap& other) { + if (&other != this) + copyFrom(other); + return *this; + } + + DenseMap& operator=(DenseMap &&other) { + this->destroyAll(); + deallocate_buffer(Buckets, sizeof(BucketT) * NumBuckets, alignof(BucketT)); + init(0); + swap(other); + return *this; + } + + void copyFrom(const DenseMap& other) { + this->destroyAll(); + deallocate_buffer(Buckets, sizeof(BucketT) * NumBuckets, alignof(BucketT)); + if (allocateBuckets(other.NumBuckets)) { + this->BaseT::copyFrom(other); + } else { + NumEntries = 0; + NumTombstones = 0; + } + } + + void init(unsigned InitNumEntries) { + auto InitBuckets = BaseT::getMinBucketToReserveForEntries(InitNumEntries); + if (allocateBuckets(InitBuckets)) { + this->BaseT::initEmpty(); + } else { + NumEntries = 0; + NumTombstones = 0; + } + } + + void grow(unsigned AtLeast) { + unsigned OldNumBuckets = NumBuckets; + BucketT *OldBuckets = Buckets; + + allocateBuckets(std::max<unsigned>(64, static_cast<unsigned>(NextPowerOf2(AtLeast-1)))); + assert(Buckets); + if (!OldBuckets) { + this->BaseT::initEmpty(); + return; + } + + this->moveFromOldBuckets(OldBuckets, OldBuckets+OldNumBuckets); + + // Free the old table. + deallocate_buffer(OldBuckets, sizeof(BucketT) * OldNumBuckets, + alignof(BucketT)); + } + + void shrink_and_clear() { + unsigned OldNumBuckets = NumBuckets; + unsigned OldNumEntries = NumEntries; + this->destroyAll(); + + // Reduce the number of buckets. + unsigned NewNumBuckets = 0; + if (OldNumEntries) + NewNumBuckets = std::max(64, 1 << (Log2_32_Ceil(OldNumEntries) + 1)); + if (NewNumBuckets == NumBuckets) { + this->BaseT::initEmpty(); + return; + } + + deallocate_buffer(Buckets, sizeof(BucketT) * OldNumBuckets, + alignof(BucketT)); + init(NewNumBuckets); + } + +private: + unsigned getNumEntries() const { + return NumEntries; + } + + void setNumEntries(unsigned Num) { + NumEntries = Num; + } + + unsigned getNumTombstones() const { + return NumTombstones; + } + + void setNumTombstones(unsigned Num) { + NumTombstones = Num; + } + + BucketT *getBuckets() const { + return Buckets; + } + + unsigned getNumBuckets() const { + return NumBuckets; + } + + bool allocateBuckets(unsigned Num) { + NumBuckets = Num; + if (NumBuckets == 0) { + Buckets = nullptr; + return false; + } + + Buckets = static_cast<BucketT *>( + allocate_buffer(sizeof(BucketT) * NumBuckets, alignof(BucketT))); + return true; + } +}; + +template <typename KeyT, typename ValueT, unsigned InlineBuckets = 4, + typename KeyInfoT = DenseMapInfo<KeyT>, + typename BucketT = llvm::detail::DenseMapPair<KeyT, ValueT>> +class SmallDenseMap + : public DenseMapBase< + SmallDenseMap<KeyT, ValueT, InlineBuckets, KeyInfoT, BucketT>, KeyT, + ValueT, KeyInfoT, BucketT> { + friend class DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT, BucketT>; + + // Lift some types from the dependent base class into this class for + // simplicity of referring to them. + using BaseT = DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT, BucketT>; + + static_assert(isPowerOf2_64(InlineBuckets), + "InlineBuckets must be a power of 2."); + + unsigned Small : 1; + unsigned NumEntries : 31; + unsigned NumTombstones; + + struct LargeRep { + BucketT *Buckets; + unsigned NumBuckets; + }; + + /// A "union" of an inline bucket array and the struct representing + /// a large bucket. This union will be discriminated by the 'Small' bit. + AlignedCharArrayUnion<BucketT[InlineBuckets], LargeRep> storage; + +public: + explicit SmallDenseMap(unsigned NumInitBuckets = 0) { + init(NumInitBuckets); + } + + SmallDenseMap(const SmallDenseMap &other) : BaseT() { + init(0); + copyFrom(other); + } + + SmallDenseMap(SmallDenseMap &&other) : BaseT() { + init(0); + swap(other); + } + + template<typename InputIt> + SmallDenseMap(const InputIt &I, const InputIt &E) { + init(NextPowerOf2(std::distance(I, E))); + this->insert(I, E); + } + + ~SmallDenseMap() { + this->destroyAll(); + deallocateBuckets(); + } + + void swap(SmallDenseMap& RHS) { + unsigned TmpNumEntries = RHS.NumEntries; + RHS.NumEntries = NumEntries; + NumEntries = TmpNumEntries; + std::swap(NumTombstones, RHS.NumTombstones); + + const KeyT EmptyKey = this->getEmptyKey(); + const KeyT TombstoneKey = this->getTombstoneKey(); + if (Small && RHS.Small) { + // If we're swapping inline bucket arrays, we have to cope with some of + // the tricky bits of DenseMap's storage system: the buckets are not + // fully initialized. Thus we swap every key, but we may have + // a one-directional move of the value. + for (unsigned i = 0, e = InlineBuckets; i != e; ++i) { + BucketT *LHSB = &getInlineBuckets()[i], + *RHSB = &RHS.getInlineBuckets()[i]; + bool hasLHSValue = (!KeyInfoT::isEqual(LHSB->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(LHSB->getFirst(), TombstoneKey)); + bool hasRHSValue = (!KeyInfoT::isEqual(RHSB->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(RHSB->getFirst(), TombstoneKey)); + if (hasLHSValue && hasRHSValue) { + // Swap together if we can... + std::swap(*LHSB, *RHSB); + continue; + } + // Swap separately and handle any assymetry. + std::swap(LHSB->getFirst(), RHSB->getFirst()); + if (hasLHSValue) { + ::new (&RHSB->getSecond()) ValueT(std::move(LHSB->getSecond())); + LHSB->getSecond().~ValueT(); + } else if (hasRHSValue) { + ::new (&LHSB->getSecond()) ValueT(std::move(RHSB->getSecond())); + RHSB->getSecond().~ValueT(); + } + } + return; + } + if (!Small && !RHS.Small) { + std::swap(getLargeRep()->Buckets, RHS.getLargeRep()->Buckets); + std::swap(getLargeRep()->NumBuckets, RHS.getLargeRep()->NumBuckets); + return; + } + + SmallDenseMap &SmallSide = Small ? *this : RHS; + SmallDenseMap &LargeSide = Small ? RHS : *this; + + // First stash the large side's rep and move the small side across. + LargeRep TmpRep = std::move(*LargeSide.getLargeRep()); + LargeSide.getLargeRep()->~LargeRep(); + LargeSide.Small = true; + // This is similar to the standard move-from-old-buckets, but the bucket + // count hasn't actually rotated in this case. So we have to carefully + // move construct the keys and values into their new locations, but there + // is no need to re-hash things. + for (unsigned i = 0, e = InlineBuckets; i != e; ++i) { + BucketT *NewB = &LargeSide.getInlineBuckets()[i], + *OldB = &SmallSide.getInlineBuckets()[i]; + ::new (&NewB->getFirst()) KeyT(std::move(OldB->getFirst())); + OldB->getFirst().~KeyT(); + if (!KeyInfoT::isEqual(NewB->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(NewB->getFirst(), TombstoneKey)) { + ::new (&NewB->getSecond()) ValueT(std::move(OldB->getSecond())); + OldB->getSecond().~ValueT(); + } + } + + // The hard part of moving the small buckets across is done, just move + // the TmpRep into its new home. + SmallSide.Small = false; + new (SmallSide.getLargeRep()) LargeRep(std::move(TmpRep)); + } + + SmallDenseMap& operator=(const SmallDenseMap& other) { + if (&other != this) + copyFrom(other); + return *this; + } + + SmallDenseMap& operator=(SmallDenseMap &&other) { + this->destroyAll(); + deallocateBuckets(); + init(0); + swap(other); + return *this; + } + + void copyFrom(const SmallDenseMap& other) { + this->destroyAll(); + deallocateBuckets(); + Small = true; + if (other.getNumBuckets() > InlineBuckets) { + Small = false; + new (getLargeRep()) LargeRep(allocateBuckets(other.getNumBuckets())); + } + this->BaseT::copyFrom(other); + } + + void init(unsigned InitBuckets) { + Small = true; + if (InitBuckets > InlineBuckets) { + Small = false; + new (getLargeRep()) LargeRep(allocateBuckets(InitBuckets)); + } + this->BaseT::initEmpty(); + } + + void grow(unsigned AtLeast) { + if (AtLeast > InlineBuckets) + AtLeast = std::max<unsigned>(64, NextPowerOf2(AtLeast-1)); + + if (Small) { + // First move the inline buckets into a temporary storage. + AlignedCharArrayUnion<BucketT[InlineBuckets]> TmpStorage; + BucketT *TmpBegin = reinterpret_cast<BucketT *>(TmpStorage.buffer); + BucketT *TmpEnd = TmpBegin; + + // Loop over the buckets, moving non-empty, non-tombstones into the + // temporary storage. Have the loop move the TmpEnd forward as it goes. + const KeyT EmptyKey = this->getEmptyKey(); + const KeyT TombstoneKey = this->getTombstoneKey(); + for (BucketT *P = getBuckets(), *E = P + InlineBuckets; P != E; ++P) { + if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) { + assert(size_t(TmpEnd - TmpBegin) < InlineBuckets && + "Too many inline buckets!"); + ::new (&TmpEnd->getFirst()) KeyT(std::move(P->getFirst())); + ::new (&TmpEnd->getSecond()) ValueT(std::move(P->getSecond())); + ++TmpEnd; + P->getSecond().~ValueT(); + } + P->getFirst().~KeyT(); + } + + // AtLeast == InlineBuckets can happen if there are many tombstones, + // and grow() is used to remove them. Usually we always switch to the + // large rep here. + if (AtLeast > InlineBuckets) { + Small = false; + new (getLargeRep()) LargeRep(allocateBuckets(AtLeast)); + } + this->moveFromOldBuckets(TmpBegin, TmpEnd); + return; + } + + LargeRep OldRep = std::move(*getLargeRep()); + getLargeRep()->~LargeRep(); + if (AtLeast <= InlineBuckets) { + Small = true; + } else { + new (getLargeRep()) LargeRep(allocateBuckets(AtLeast)); + } + + this->moveFromOldBuckets(OldRep.Buckets, OldRep.Buckets+OldRep.NumBuckets); + + // Free the old table. + deallocate_buffer(OldRep.Buckets, sizeof(BucketT) * OldRep.NumBuckets, + alignof(BucketT)); + } + + void shrink_and_clear() { + unsigned OldSize = this->size(); + this->destroyAll(); + + // Reduce the number of buckets. + unsigned NewNumBuckets = 0; + if (OldSize) { + NewNumBuckets = 1 << (Log2_32_Ceil(OldSize) + 1); + if (NewNumBuckets > InlineBuckets && NewNumBuckets < 64u) + NewNumBuckets = 64; + } + if ((Small && NewNumBuckets <= InlineBuckets) || + (!Small && NewNumBuckets == getLargeRep()->NumBuckets)) { + this->BaseT::initEmpty(); + return; + } + + deallocateBuckets(); + init(NewNumBuckets); + } + +private: + unsigned getNumEntries() const { + return NumEntries; + } + + void setNumEntries(unsigned Num) { + // NumEntries is hardcoded to be 31 bits wide. + assert(Num < (1U << 31) && "Cannot support more than 1<<31 entries"); + NumEntries = Num; + } + + unsigned getNumTombstones() const { + return NumTombstones; + } + + void setNumTombstones(unsigned Num) { + NumTombstones = Num; + } + + const BucketT *getInlineBuckets() const { + assert(Small); + // Note that this cast does not violate aliasing rules as we assert that + // the memory's dynamic type is the small, inline bucket buffer, and the + // 'storage.buffer' static type is 'char *'. + return reinterpret_cast<const BucketT *>(storage.buffer); + } + + BucketT *getInlineBuckets() { + return const_cast<BucketT *>( + const_cast<const SmallDenseMap *>(this)->getInlineBuckets()); + } + + const LargeRep *getLargeRep() const { + assert(!Small); + // Note, same rule about aliasing as with getInlineBuckets. + return reinterpret_cast<const LargeRep *>(storage.buffer); + } + + LargeRep *getLargeRep() { + return const_cast<LargeRep *>( + const_cast<const SmallDenseMap *>(this)->getLargeRep()); + } + + const BucketT *getBuckets() const { + return Small ? getInlineBuckets() : getLargeRep()->Buckets; + } + + BucketT *getBuckets() { + return const_cast<BucketT *>( + const_cast<const SmallDenseMap *>(this)->getBuckets()); + } + + unsigned getNumBuckets() const { + return Small ? InlineBuckets : getLargeRep()->NumBuckets; + } + + void deallocateBuckets() { + if (Small) + return; + + deallocate_buffer(getLargeRep()->Buckets, + sizeof(BucketT) * getLargeRep()->NumBuckets, + alignof(BucketT)); + getLargeRep()->~LargeRep(); + } + + LargeRep allocateBuckets(unsigned Num) { + assert(Num > InlineBuckets && "Must allocate more buckets than are inline"); + LargeRep Rep = {static_cast<BucketT *>(allocate_buffer( + sizeof(BucketT) * Num, alignof(BucketT))), + Num}; + return Rep; + } +}; + +template <typename KeyT, typename ValueT, typename KeyInfoT, typename Bucket, + bool IsConst> +class DenseMapIterator : DebugEpochBase::HandleBase { + friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true>; + friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, false>; + + using ConstIterator = DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true>; + +public: + using difference_type = ptrdiff_t; + using value_type = + typename std::conditional<IsConst, const Bucket, Bucket>::type; + using pointer = value_type *; + using reference = value_type &; + using iterator_category = std::forward_iterator_tag; + +private: + pointer Ptr = nullptr; + pointer End = nullptr; + +public: + DenseMapIterator() = default; + + DenseMapIterator(pointer Pos, pointer E, const DebugEpochBase &Epoch, + bool NoAdvance = false) + : DebugEpochBase::HandleBase(&Epoch), Ptr(Pos), End(E) { + assert(isHandleInSync() && "invalid construction!"); + + if (NoAdvance) return; + if (shouldReverseIterate<KeyT>()) { + RetreatPastEmptyBuckets(); + return; + } + AdvancePastEmptyBuckets(); + } + + // Converting ctor from non-const iterators to const iterators. SFINAE'd out + // for const iterator destinations so it doesn't end up as a user defined copy + // constructor. + template <bool IsConstSrc, + typename = typename std::enable_if<!IsConstSrc && IsConst>::type> + DenseMapIterator( + const DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, IsConstSrc> &I) + : DebugEpochBase::HandleBase(I), Ptr(I.Ptr), End(I.End) {} + + reference operator*() const { + assert(isHandleInSync() && "invalid iterator access!"); + if (shouldReverseIterate<KeyT>()) + return Ptr[-1]; + return *Ptr; + } + pointer operator->() const { + assert(isHandleInSync() && "invalid iterator access!"); + if (shouldReverseIterate<KeyT>()) + return &(Ptr[-1]); + return Ptr; + } + + bool operator==(const ConstIterator &RHS) const { + assert((!Ptr || isHandleInSync()) && "handle not in sync!"); + assert((!RHS.Ptr || RHS.isHandleInSync()) && "handle not in sync!"); + assert(getEpochAddress() == RHS.getEpochAddress() && + "comparing incomparable iterators!"); + return Ptr == RHS.Ptr; + } + bool operator!=(const ConstIterator &RHS) const { + assert((!Ptr || isHandleInSync()) && "handle not in sync!"); + assert((!RHS.Ptr || RHS.isHandleInSync()) && "handle not in sync!"); + assert(getEpochAddress() == RHS.getEpochAddress() && + "comparing incomparable iterators!"); + return Ptr != RHS.Ptr; + } + + inline DenseMapIterator& operator++() { // Preincrement + assert(isHandleInSync() && "invalid iterator access!"); + if (shouldReverseIterate<KeyT>()) { + --Ptr; + RetreatPastEmptyBuckets(); + return *this; + } + ++Ptr; + AdvancePastEmptyBuckets(); + return *this; + } + DenseMapIterator operator++(int) { // Postincrement + assert(isHandleInSync() && "invalid iterator access!"); + DenseMapIterator tmp = *this; ++*this; return tmp; + } + +private: + void AdvancePastEmptyBuckets() { + assert(Ptr <= End); + const KeyT Empty = KeyInfoT::getEmptyKey(); + const KeyT Tombstone = KeyInfoT::getTombstoneKey(); + + while (Ptr != End && (KeyInfoT::isEqual(Ptr->getFirst(), Empty) || + KeyInfoT::isEqual(Ptr->getFirst(), Tombstone))) + ++Ptr; + } + + void RetreatPastEmptyBuckets() { + assert(Ptr >= End); + const KeyT Empty = KeyInfoT::getEmptyKey(); + const KeyT Tombstone = KeyInfoT::getTombstoneKey(); + + while (Ptr != End && (KeyInfoT::isEqual(Ptr[-1].getFirst(), Empty) || + KeyInfoT::isEqual(Ptr[-1].getFirst(), Tombstone))) + --Ptr; + } +}; + +template <typename KeyT, typename ValueT, typename KeyInfoT> +inline size_t capacity_in_bytes(const DenseMap<KeyT, ValueT, KeyInfoT> &X) { + return X.getMemorySize(); +} + +} // end namespace llvm + +#endif // LLVM_ADT_DENSEMAP_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/DenseMapInfo.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/DenseMapInfo.h new file mode 100644 index 0000000..bd4c60c --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/DenseMapInfo.h
@@ -0,0 +1,300 @@ +//===- llvm/ADT/DenseMapInfo.h - Type traits for DenseMap -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines DenseMapInfo traits for DenseMap. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_DENSEMAPINFO_H +#define LLVM_ADT_DENSEMAPINFO_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Hashing.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/PointerLikeTypeTraits.h" +#include "llvm/Support/TypeSize.h" +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <utility> + +namespace llvm { + +template<typename T> +struct DenseMapInfo { + //static inline T getEmptyKey(); + //static inline T getTombstoneKey(); + //static unsigned getHashValue(const T &Val); + //static bool isEqual(const T &LHS, const T &RHS); +}; + +// Provide DenseMapInfo for all pointers. +template<typename T> +struct DenseMapInfo<T*> { + static inline T* getEmptyKey() { + uintptr_t Val = static_cast<uintptr_t>(-1); + Val <<= PointerLikeTypeTraits<T*>::NumLowBitsAvailable; + return reinterpret_cast<T*>(Val); + } + + static inline T* getTombstoneKey() { + uintptr_t Val = static_cast<uintptr_t>(-2); + Val <<= PointerLikeTypeTraits<T*>::NumLowBitsAvailable; + return reinterpret_cast<T*>(Val); + } + + static unsigned getHashValue(const T *PtrVal) { + return (unsigned((uintptr_t)PtrVal) >> 4) ^ + (unsigned((uintptr_t)PtrVal) >> 9); + } + + static bool isEqual(const T *LHS, const T *RHS) { return LHS == RHS; } +}; + +// Provide DenseMapInfo for chars. +template<> struct DenseMapInfo<char> { + static inline char getEmptyKey() { return ~0; } + static inline char getTombstoneKey() { return ~0 - 1; } + static unsigned getHashValue(const char& Val) { return Val * 37U; } + + static bool isEqual(const char &LHS, const char &RHS) { + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for unsigned chars. +template <> struct DenseMapInfo<unsigned char> { + static inline unsigned char getEmptyKey() { return ~0; } + static inline unsigned char getTombstoneKey() { return ~0 - 1; } + static unsigned getHashValue(const unsigned char &Val) { return Val * 37U; } + + static bool isEqual(const unsigned char &LHS, const unsigned char &RHS) { + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for unsigned shorts. +template <> struct DenseMapInfo<unsigned short> { + static inline unsigned short getEmptyKey() { return 0xFFFF; } + static inline unsigned short getTombstoneKey() { return 0xFFFF - 1; } + static unsigned getHashValue(const unsigned short &Val) { return Val * 37U; } + + static bool isEqual(const unsigned short &LHS, const unsigned short &RHS) { + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for unsigned ints. +template<> struct DenseMapInfo<unsigned> { + static inline unsigned getEmptyKey() { return ~0U; } + static inline unsigned getTombstoneKey() { return ~0U - 1; } + static unsigned getHashValue(const unsigned& Val) { return Val * 37U; } + + static bool isEqual(const unsigned& LHS, const unsigned& RHS) { + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for unsigned longs. +template<> struct DenseMapInfo<unsigned long> { + static inline unsigned long getEmptyKey() { return ~0UL; } + static inline unsigned long getTombstoneKey() { return ~0UL - 1L; } + + static unsigned getHashValue(const unsigned long& Val) { + return (unsigned)(Val * 37UL); + } + + static bool isEqual(const unsigned long& LHS, const unsigned long& RHS) { + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for unsigned long longs. +template<> struct DenseMapInfo<unsigned long long> { + static inline unsigned long long getEmptyKey() { return ~0ULL; } + static inline unsigned long long getTombstoneKey() { return ~0ULL - 1ULL; } + + static unsigned getHashValue(const unsigned long long& Val) { + return (unsigned)(Val * 37ULL); + } + + static bool isEqual(const unsigned long long& LHS, + const unsigned long long& RHS) { + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for shorts. +template <> struct DenseMapInfo<short> { + static inline short getEmptyKey() { return 0x7FFF; } + static inline short getTombstoneKey() { return -0x7FFF - 1; } + static unsigned getHashValue(const short &Val) { return Val * 37U; } + static bool isEqual(const short &LHS, const short &RHS) { return LHS == RHS; } +}; + +// Provide DenseMapInfo for ints. +template<> struct DenseMapInfo<int> { + static inline int getEmptyKey() { return 0x7fffffff; } + static inline int getTombstoneKey() { return -0x7fffffff - 1; } + static unsigned getHashValue(const int& Val) { return (unsigned)(Val * 37U); } + + static bool isEqual(const int& LHS, const int& RHS) { + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for longs. +template<> struct DenseMapInfo<long> { + static inline long getEmptyKey() { + return (1UL << (sizeof(long) * 8 - 1)) - 1UL; + } + + static inline long getTombstoneKey() { return getEmptyKey() - 1L; } + + static unsigned getHashValue(const long& Val) { + return (unsigned)(Val * 37UL); + } + + static bool isEqual(const long& LHS, const long& RHS) { + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for long longs. +template<> struct DenseMapInfo<long long> { + static inline long long getEmptyKey() { return 0x7fffffffffffffffLL; } + static inline long long getTombstoneKey() { return -0x7fffffffffffffffLL-1; } + + static unsigned getHashValue(const long long& Val) { + return (unsigned)(Val * 37ULL); + } + + static bool isEqual(const long long& LHS, + const long long& RHS) { + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for all pairs whose members have info. +template<typename T, typename U> +struct DenseMapInfo<std::pair<T, U>> { + using Pair = std::pair<T, U>; + using FirstInfo = DenseMapInfo<T>; + using SecondInfo = DenseMapInfo<U>; + + static inline Pair getEmptyKey() { + return std::make_pair(FirstInfo::getEmptyKey(), + SecondInfo::getEmptyKey()); + } + + static inline Pair getTombstoneKey() { + return std::make_pair(FirstInfo::getTombstoneKey(), + SecondInfo::getTombstoneKey()); + } + + static unsigned getHashValue(const Pair& PairVal) { + uint64_t key = (uint64_t)FirstInfo::getHashValue(PairVal.first) << 32 + | (uint64_t)SecondInfo::getHashValue(PairVal.second); + key += ~(key << 32); + key ^= (key >> 22); + key += ~(key << 13); + key ^= (key >> 8); + key += (key << 3); + key ^= (key >> 15); + key += ~(key << 27); + key ^= (key >> 31); + return (unsigned)key; + } + + static bool isEqual(const Pair &LHS, const Pair &RHS) { + return FirstInfo::isEqual(LHS.first, RHS.first) && + SecondInfo::isEqual(LHS.second, RHS.second); + } +}; + +// Provide DenseMapInfo for StringRefs. +template <> struct DenseMapInfo<StringRef> { + static inline StringRef getEmptyKey() { + return StringRef(reinterpret_cast<const char *>(~static_cast<uintptr_t>(0)), + 0); + } + + static inline StringRef getTombstoneKey() { + return StringRef(reinterpret_cast<const char *>(~static_cast<uintptr_t>(1)), + 0); + } + + static unsigned getHashValue(StringRef Val) { + assert(Val.data() != getEmptyKey().data() && "Cannot hash the empty key!"); + assert(Val.data() != getTombstoneKey().data() && + "Cannot hash the tombstone key!"); + return (unsigned)(hash_value(Val)); + } + + static bool isEqual(StringRef LHS, StringRef RHS) { + if (RHS.data() == getEmptyKey().data()) + return LHS.data() == getEmptyKey().data(); + if (RHS.data() == getTombstoneKey().data()) + return LHS.data() == getTombstoneKey().data(); + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for ArrayRefs. +template <typename T> struct DenseMapInfo<ArrayRef<T>> { + static inline ArrayRef<T> getEmptyKey() { + return ArrayRef<T>(reinterpret_cast<const T *>(~static_cast<uintptr_t>(0)), + size_t(0)); + } + + static inline ArrayRef<T> getTombstoneKey() { + return ArrayRef<T>(reinterpret_cast<const T *>(~static_cast<uintptr_t>(1)), + size_t(0)); + } + + static unsigned getHashValue(ArrayRef<T> Val) { + assert(Val.data() != getEmptyKey().data() && "Cannot hash the empty key!"); + assert(Val.data() != getTombstoneKey().data() && + "Cannot hash the tombstone key!"); + return (unsigned)(hash_value(Val)); + } + + static bool isEqual(ArrayRef<T> LHS, ArrayRef<T> RHS) { + if (RHS.data() == getEmptyKey().data()) + return LHS.data() == getEmptyKey().data(); + if (RHS.data() == getTombstoneKey().data()) + return LHS.data() == getTombstoneKey().data(); + return LHS == RHS; + } +}; + +template <> struct DenseMapInfo<hash_code> { + static inline hash_code getEmptyKey() { return hash_code(-1); } + static inline hash_code getTombstoneKey() { return hash_code(-2); } + static unsigned getHashValue(hash_code val) { return val; } + static bool isEqual(hash_code LHS, hash_code RHS) { return LHS == RHS; } +}; + +template <> struct DenseMapInfo<ElementCount> { + static inline ElementCount getEmptyKey() { return {~0U, true}; } + static inline ElementCount getTombstoneKey() { return {~0U - 1, false}; } + static unsigned getHashValue(const ElementCount& EltCnt) { + if (EltCnt.Scalable) + return (EltCnt.Min * 37U) - 1U; + + return EltCnt.Min * 37U; + } + + static bool isEqual(const ElementCount& LHS, const ElementCount& RHS) { + return LHS == RHS; + } +}; + +} // end namespace llvm + +#endif // LLVM_ADT_DENSEMAPINFO_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/DenseSet.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/DenseSet.h new file mode 100644 index 0000000..9afb715 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/DenseSet.h
@@ -0,0 +1,283 @@ +//===- llvm/ADT/DenseSet.h - Dense probed hash table ------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the DenseSet and SmallDenseSet classes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_DENSESET_H +#define LLVM_ADT_DENSESET_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/type_traits.h" +#include <algorithm> +#include <cstddef> +#include <initializer_list> +#include <iterator> +#include <utility> + +namespace llvm { + +namespace detail { + +struct DenseSetEmpty {}; + +// Use the empty base class trick so we can create a DenseMap where the buckets +// contain only a single item. +template <typename KeyT> class DenseSetPair : public DenseSetEmpty { + KeyT key; + +public: + KeyT &getFirst() { return key; } + const KeyT &getFirst() const { return key; } + DenseSetEmpty &getSecond() { return *this; } + const DenseSetEmpty &getSecond() const { return *this; } +}; + +/// Base class for DenseSet and DenseSmallSet. +/// +/// MapTy should be either +/// +/// DenseMap<ValueT, detail::DenseSetEmpty, ValueInfoT, +/// detail::DenseSetPair<ValueT>> +/// +/// or the equivalent SmallDenseMap type. ValueInfoT must implement the +/// DenseMapInfo "concept". +template <typename ValueT, typename MapTy, typename ValueInfoT> +class DenseSetImpl { + static_assert(sizeof(typename MapTy::value_type) == sizeof(ValueT), + "DenseMap buckets unexpectedly large!"); + MapTy TheMap; + + template <typename T> + using const_arg_type_t = typename const_pointer_or_const_ref<T>::type; + +public: + using key_type = ValueT; + using value_type = ValueT; + using size_type = unsigned; + + explicit DenseSetImpl(unsigned InitialReserve = 0) : TheMap(InitialReserve) {} + + DenseSetImpl(std::initializer_list<ValueT> Elems) + : DenseSetImpl(PowerOf2Ceil(Elems.size())) { + insert(Elems.begin(), Elems.end()); + } + + bool empty() const { return TheMap.empty(); } + size_type size() const { return TheMap.size(); } + size_t getMemorySize() const { return TheMap.getMemorySize(); } + + /// Grow the DenseSet so that it has at least Size buckets. Will not shrink + /// the Size of the set. + void resize(size_t Size) { TheMap.resize(Size); } + + /// Grow the DenseSet so that it can contain at least \p NumEntries items + /// before resizing again. + void reserve(size_t Size) { TheMap.reserve(Size); } + + void clear() { + TheMap.clear(); + } + + /// Return 1 if the specified key is in the set, 0 otherwise. + size_type count(const_arg_type_t<ValueT> V) const { + return TheMap.count(V); + } + + bool erase(const ValueT &V) { + return TheMap.erase(V); + } + + void swap(DenseSetImpl &RHS) { TheMap.swap(RHS.TheMap); } + + // Iterators. + + class ConstIterator; + + class Iterator { + typename MapTy::iterator I; + friend class DenseSetImpl; + friend class ConstIterator; + + public: + using difference_type = typename MapTy::iterator::difference_type; + using value_type = ValueT; + using pointer = value_type *; + using reference = value_type &; + using iterator_category = std::forward_iterator_tag; + + Iterator() = default; + Iterator(const typename MapTy::iterator &i) : I(i) {} + + ValueT &operator*() { return I->getFirst(); } + const ValueT &operator*() const { return I->getFirst(); } + ValueT *operator->() { return &I->getFirst(); } + const ValueT *operator->() const { return &I->getFirst(); } + + Iterator& operator++() { ++I; return *this; } + Iterator 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; } + }; + + class ConstIterator { + typename MapTy::const_iterator I; + friend class DenseSetImpl; + friend class Iterator; + + public: + using difference_type = typename MapTy::const_iterator::difference_type; + using value_type = ValueT; + using pointer = const value_type *; + using reference = const value_type &; + using iterator_category = std::forward_iterator_tag; + + ConstIterator() = default; + ConstIterator(const Iterator &B) : I(B.I) {} + ConstIterator(const typename MapTy::const_iterator &i) : I(i) {} + + const ValueT &operator*() const { return I->getFirst(); } + const ValueT *operator->() const { 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; } + }; + + using iterator = Iterator; + using const_iterator = ConstIterator; + + iterator begin() { return Iterator(TheMap.begin()); } + iterator end() { return Iterator(TheMap.end()); } + + const_iterator begin() const { return ConstIterator(TheMap.begin()); } + const_iterator end() const { return ConstIterator(TheMap.end()); } + + iterator find(const_arg_type_t<ValueT> V) { return Iterator(TheMap.find(V)); } + const_iterator find(const_arg_type_t<ValueT> V) const { + return ConstIterator(TheMap.find(V)); + } + + /// Alternative version of find() 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 <class LookupKeyT> + iterator find_as(const LookupKeyT &Val) { + return Iterator(TheMap.find_as(Val)); + } + template <class LookupKeyT> + const_iterator find_as(const LookupKeyT &Val) const { + return ConstIterator(TheMap.find_as(Val)); + } + + void erase(Iterator I) { return TheMap.erase(I.I); } + void erase(ConstIterator CI) { return TheMap.erase(CI.I); } + + std::pair<iterator, bool> insert(const ValueT &V) { + detail::DenseSetEmpty Empty; + return TheMap.try_emplace(V, Empty); + } + + std::pair<iterator, bool> insert(ValueT &&V) { + detail::DenseSetEmpty Empty; + return TheMap.try_emplace(std::move(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 TheMap.insert_as({V, detail::DenseSetEmpty()}, LookupKey); + } + template <typename LookupKeyT> + std::pair<iterator, bool> insert_as(ValueT &&V, const LookupKeyT &LookupKey) { + return TheMap.insert_as({std::move(V), detail::DenseSetEmpty()}, LookupKey); + } + + // Range insertion of values. + template<typename InputIt> + void insert(InputIt I, InputIt E) { + for (; I != E; ++I) + insert(*I); + } +}; + +/// Equality comparison for DenseSet. +/// +/// Iterates over elements of LHS confirming that each element is also a member +/// of RHS, and that RHS contains no additional values. +/// Equivalent to N calls to RHS.count. Amortized complexity is linear, worst +/// case is O(N^2) (if every hash collides). +template <typename ValueT, typename MapTy, typename ValueInfoT> +bool operator==(const DenseSetImpl<ValueT, MapTy, ValueInfoT> &LHS, + const DenseSetImpl<ValueT, MapTy, ValueInfoT> &RHS) { + if (LHS.size() != RHS.size()) + return false; + + for (auto &E : LHS) + if (!RHS.count(E)) + return false; + + return true; +} + +/// Inequality comparison for DenseSet. +/// +/// Equivalent to !(LHS == RHS). See operator== for performance notes. +template <typename ValueT, typename MapTy, typename ValueInfoT> +bool operator!=(const DenseSetImpl<ValueT, MapTy, ValueInfoT> &LHS, + const DenseSetImpl<ValueT, MapTy, ValueInfoT> &RHS) { + return !(LHS == RHS); +} + +} // end namespace detail + +/// Implements a dense probed hash-table based set. +template <typename ValueT, typename ValueInfoT = DenseMapInfo<ValueT>> +class DenseSet : public detail::DenseSetImpl< + ValueT, DenseMap<ValueT, detail::DenseSetEmpty, ValueInfoT, + detail::DenseSetPair<ValueT>>, + ValueInfoT> { + using BaseT = + detail::DenseSetImpl<ValueT, + DenseMap<ValueT, detail::DenseSetEmpty, ValueInfoT, + detail::DenseSetPair<ValueT>>, + ValueInfoT>; + +public: + using BaseT::BaseT; +}; + +/// Implements a dense probed hash-table based set with some number of buckets +/// stored inline. +template <typename ValueT, unsigned InlineBuckets = 4, + typename ValueInfoT = DenseMapInfo<ValueT>> +class SmallDenseSet + : public detail::DenseSetImpl< + ValueT, SmallDenseMap<ValueT, detail::DenseSetEmpty, InlineBuckets, + ValueInfoT, detail::DenseSetPair<ValueT>>, + ValueInfoT> { + using BaseT = detail::DenseSetImpl< + ValueT, SmallDenseMap<ValueT, detail::DenseSetEmpty, InlineBuckets, + ValueInfoT, detail::DenseSetPair<ValueT>>, + ValueInfoT>; + +public: + using BaseT::BaseT; +}; + +} // end namespace llvm + +#endif // LLVM_ADT_DENSESET_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/DepthFirstIterator.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/DepthFirstIterator.h new file mode 100644 index 0000000..11967f5 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/DepthFirstIterator.h
@@ -0,0 +1,307 @@ +//===- llvm/ADT/DepthFirstIterator.h - Depth First iterator -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file builds on the ADT/GraphTraits.h file to build generic depth +// first graph iterator. This file exposes the following functions/types: +// +// df_begin/df_end/df_iterator +// * Normal depth-first iteration - visit a node and then all of its children. +// +// idf_begin/idf_end/idf_iterator +// * Depth-first iteration on the 'inverse' graph. +// +// df_ext_begin/df_ext_end/df_ext_iterator +// * Normal depth-first iteration - visit a node and then all of its children. +// This iterator stores the 'visited' set in an external set, which allows +// it to be more efficient, and allows external clients to use the set for +// other purposes. +// +// idf_ext_begin/idf_ext_end/idf_ext_iterator +// * Depth-first iteration on the 'inverse' graph. +// This iterator stores the 'visited' set in an external set, which allows +// it to be more efficient, and allows external clients to use the set for +// other purposes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_DEPTHFIRSTITERATOR_H +#define LLVM_ADT_DEPTHFIRSTITERATOR_H + +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/iterator_range.h" +#include <iterator> +#include <set> +#include <utility> +#include <vector> + +namespace llvm { + +// df_iterator_storage - A private class which is used to figure out where to +// store the visited set. +template<class SetType, bool External> // Non-external set +class df_iterator_storage { +public: + SetType Visited; +}; + +template<class SetType> +class df_iterator_storage<SetType, true> { +public: + df_iterator_storage(SetType &VSet) : Visited(VSet) {} + df_iterator_storage(const df_iterator_storage &S) : Visited(S.Visited) {} + + SetType &Visited; +}; + +// The visited stated for the iteration is a simple set augmented with +// one more method, completed, which is invoked when all children of a +// node have been processed. It is intended to distinguish of back and +// cross edges in the spanning tree but is not used in the common case. +template <typename NodeRef, unsigned SmallSize=8> +struct df_iterator_default_set : public SmallPtrSet<NodeRef, SmallSize> { + using BaseSet = SmallPtrSet<NodeRef, SmallSize>; + using iterator = typename BaseSet::iterator; + + std::pair<iterator,bool> insert(NodeRef N) { return BaseSet::insert(N); } + template <typename IterT> + void insert(IterT Begin, IterT End) { BaseSet::insert(Begin,End); } + + void completed(NodeRef) {} +}; + +// Generic Depth First Iterator +template <class GraphT, + class SetType = + df_iterator_default_set<typename GraphTraits<GraphT>::NodeRef>, + bool ExtStorage = false, class GT = GraphTraits<GraphT>> +class df_iterator + : public std::iterator<std::forward_iterator_tag, typename GT::NodeRef>, + public df_iterator_storage<SetType, ExtStorage> { + using super = std::iterator<std::forward_iterator_tag, typename GT::NodeRef>; + using NodeRef = typename GT::NodeRef; + using ChildItTy = typename GT::ChildIteratorType; + + // First element is node reference, second is the 'next child' to visit. + // The second child is initialized lazily to pick up graph changes during the + // DFS. + using StackElement = std::pair<NodeRef, Optional<ChildItTy>>; + + // VisitStack - Used to maintain the ordering. Top = current block + std::vector<StackElement> VisitStack; + +private: + inline df_iterator(NodeRef Node) { + this->Visited.insert(Node); + VisitStack.push_back(StackElement(Node, None)); + } + + inline df_iterator() = default; // End is when stack is empty + + inline df_iterator(NodeRef Node, SetType &S) + : df_iterator_storage<SetType, ExtStorage>(S) { + if (this->Visited.insert(Node).second) + VisitStack.push_back(StackElement(Node, None)); + } + + inline df_iterator(SetType &S) + : df_iterator_storage<SetType, ExtStorage>(S) { + // End is when stack is empty + } + + inline void toNext() { + do { + NodeRef Node = VisitStack.back().first; + Optional<ChildItTy> &Opt = VisitStack.back().second; + + if (!Opt) + Opt.emplace(GT::child_begin(Node)); + + // Notice that we directly mutate *Opt here, so that + // VisitStack.back().second actually gets updated as the iterator + // increases. + while (*Opt != GT::child_end(Node)) { + NodeRef Next = *(*Opt)++; + // Has our next sibling been visited? + if (this->Visited.insert(Next).second) { + // No, do it now. + VisitStack.push_back(StackElement(Next, None)); + return; + } + } + this->Visited.completed(Node); + + // Oops, ran out of successors... go up a level on the stack. + VisitStack.pop_back(); + } while (!VisitStack.empty()); + } + +public: + using pointer = typename super::pointer; + + // Provide static begin and end methods as our public "constructors" + static df_iterator begin(const GraphT &G) { + return df_iterator(GT::getEntryNode(G)); + } + static df_iterator end(const GraphT &G) { return df_iterator(); } + + // Static begin and end methods as our public ctors for external iterators + static df_iterator begin(const GraphT &G, SetType &S) { + return df_iterator(GT::getEntryNode(G), S); + } + static df_iterator end(const GraphT &G, SetType &S) { return df_iterator(S); } + + bool operator==(const df_iterator &x) const { + return VisitStack == x.VisitStack; + } + bool operator!=(const df_iterator &x) const { return !(*this == x); } + + const NodeRef &operator*() const { return VisitStack.back().first; } + + // This is a nonstandard operator-> that dereferences the pointer an extra + // time... so that you can actually call methods ON the Node, because + // the contained type is a pointer. This allows BBIt->getTerminator() f.e. + // + NodeRef operator->() const { return **this; } + + df_iterator &operator++() { // Preincrement + toNext(); + return *this; + } + + /// Skips all children of the current node and traverses to next node + /// + /// Note: This function takes care of incrementing the iterator. If you + /// always increment and call this function, you risk walking off the end. + df_iterator &skipChildren() { + VisitStack.pop_back(); + if (!VisitStack.empty()) + toNext(); + return *this; + } + + df_iterator operator++(int) { // Postincrement + df_iterator tmp = *this; + ++*this; + return tmp; + } + + // nodeVisited - return true if this iterator has already visited the + // specified node. This is public, and will probably be used to iterate over + // nodes that a depth first iteration did not find: ie unreachable nodes. + // + bool nodeVisited(NodeRef Node) const { + return this->Visited.count(Node) != 0; + } + + /// getPathLength - Return the length of the path from the entry node to the + /// current node, counting both nodes. + unsigned getPathLength() const { return VisitStack.size(); } + + /// getPath - Return the n'th node in the path from the entry node to the + /// current node. + NodeRef getPath(unsigned n) const { return VisitStack[n].first; } +}; + +// Provide global constructors that automatically figure out correct types... +// +template <class T> +df_iterator<T> df_begin(const T& G) { + return df_iterator<T>::begin(G); +} + +template <class T> +df_iterator<T> df_end(const T& G) { + return df_iterator<T>::end(G); +} + +// Provide an accessor method to use them in range-based patterns. +template <class T> +iterator_range<df_iterator<T>> depth_first(const T& G) { + return make_range(df_begin(G), df_end(G)); +} + +// Provide global definitions of external depth first iterators... +template <class T, class SetTy = std::set<typename GraphTraits<T>::NodeRef>> +struct df_ext_iterator : public df_iterator<T, SetTy, true> { + df_ext_iterator(const df_iterator<T, SetTy, true> &V) + : df_iterator<T, SetTy, true>(V) {} +}; + +template <class T, class SetTy> +df_ext_iterator<T, SetTy> df_ext_begin(const T& G, SetTy &S) { + return df_ext_iterator<T, SetTy>::begin(G, S); +} + +template <class T, class SetTy> +df_ext_iterator<T, SetTy> df_ext_end(const T& G, SetTy &S) { + return df_ext_iterator<T, SetTy>::end(G, S); +} + +template <class T, class SetTy> +iterator_range<df_ext_iterator<T, SetTy>> depth_first_ext(const T& G, + SetTy &S) { + return make_range(df_ext_begin(G, S), df_ext_end(G, S)); +} + +// Provide global definitions of inverse depth first iterators... +template <class T, + class SetTy = + df_iterator_default_set<typename GraphTraits<T>::NodeRef>, + bool External = false> +struct idf_iterator : public df_iterator<Inverse<T>, SetTy, External> { + idf_iterator(const df_iterator<Inverse<T>, SetTy, External> &V) + : df_iterator<Inverse<T>, SetTy, External>(V) {} +}; + +template <class T> +idf_iterator<T> idf_begin(const T& G) { + return idf_iterator<T>::begin(Inverse<T>(G)); +} + +template <class T> +idf_iterator<T> idf_end(const T& G){ + return idf_iterator<T>::end(Inverse<T>(G)); +} + +// Provide an accessor method to use them in range-based patterns. +template <class T> +iterator_range<idf_iterator<T>> inverse_depth_first(const T& G) { + return make_range(idf_begin(G), idf_end(G)); +} + +// Provide global definitions of external inverse depth first iterators... +template <class T, class SetTy = std::set<typename GraphTraits<T>::NodeRef>> +struct idf_ext_iterator : public idf_iterator<T, SetTy, true> { + idf_ext_iterator(const idf_iterator<T, SetTy, true> &V) + : idf_iterator<T, SetTy, true>(V) {} + idf_ext_iterator(const df_iterator<Inverse<T>, SetTy, true> &V) + : idf_iterator<T, SetTy, true>(V) {} +}; + +template <class T, class SetTy> +idf_ext_iterator<T, SetTy> idf_ext_begin(const T& G, SetTy &S) { + return idf_ext_iterator<T, SetTy>::begin(Inverse<T>(G), S); +} + +template <class T, class SetTy> +idf_ext_iterator<T, SetTy> idf_ext_end(const T& G, SetTy &S) { + return idf_ext_iterator<T, SetTy>::end(Inverse<T>(G), S); +} + +template <class T, class SetTy> +iterator_range<idf_ext_iterator<T, SetTy>> inverse_depth_first_ext(const T& G, + SetTy &S) { + return make_range(idf_ext_begin(G, S), idf_ext_end(G, S)); +} + +} // end namespace llvm + +#endif // LLVM_ADT_DEPTHFIRSTITERATOR_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/DirectedGraph.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/DirectedGraph.h new file mode 100644 index 0000000..cfe98e1 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/DirectedGraph.h
@@ -0,0 +1,273 @@ +//===- llvm/ADT/DirectedGraph.h - Directed Graph ----------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the interface and a base class implementation for a +// directed graph. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_DIRECTEDGRAPH_H +#define LLVM_ADT_DIRECTEDGRAPH_H + +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +/// Represent an edge in the directed graph. +/// The edge contains the target node it connects to. +template <class NodeType, class EdgeType> class DGEdge { +public: + DGEdge() = delete; + /// Create an edge pointing to the given node \p N. + explicit DGEdge(NodeType &N) : TargetNode(N) {} + explicit DGEdge(const DGEdge<NodeType, EdgeType> &E) + : TargetNode(E.TargetNode) {} + DGEdge<NodeType, EdgeType> &operator=(const DGEdge<NodeType, EdgeType> &E) { + TargetNode = E.TargetNode; + return *this; + } + + /// Static polymorphism: delegate implementation (via isEqualTo) to the + /// derived class. + bool operator==(const EdgeType &E) const { return getDerived().isEqualTo(E); } + bool operator!=(const EdgeType &E) const { return !operator==(E); } + + /// Retrieve the target node this edge connects to. + const NodeType &getTargetNode() const { return TargetNode; } + NodeType &getTargetNode() { + return const_cast<NodeType &>( + static_cast<const DGEdge<NodeType, EdgeType> &>(*this).getTargetNode()); + } + + /// Set the target node this edge connects to. + void setTargetNode(const NodeType &N) { TargetNode = N; } + +protected: + // As the default implementation use address comparison for equality. + bool isEqualTo(const EdgeType &E) const { return this == &E; } + + // Cast the 'this' pointer to the derived type and return a reference. + EdgeType &getDerived() { return *static_cast<EdgeType *>(this); } + const EdgeType &getDerived() const { + return *static_cast<const EdgeType *>(this); + } + + // The target node this edge connects to. + NodeType &TargetNode; +}; + +/// Represent a node in the directed graph. +/// The node has a (possibly empty) list of outgoing edges. +template <class NodeType, class EdgeType> class DGNode { +public: + using EdgeListTy = SetVector<EdgeType *>; + using iterator = typename EdgeListTy::iterator; + using const_iterator = typename EdgeListTy::const_iterator; + + /// Create a node with a single outgoing edge \p E. + explicit DGNode(EdgeType &E) : Edges() { Edges.insert(&E); } + DGNode() = default; + + explicit DGNode(const DGNode<NodeType, EdgeType> &N) : Edges(N.Edges) {} + DGNode(DGNode<NodeType, EdgeType> &&N) : Edges(std::move(N.Edges)) {} + + DGNode<NodeType, EdgeType> &operator=(const DGNode<NodeType, EdgeType> &N) { + Edges = N.Edges; + return *this; + } + DGNode<NodeType, EdgeType> &operator=(const DGNode<NodeType, EdgeType> &&N) { + Edges = std::move(N.Edges); + return *this; + } + + /// Static polymorphism: delegate implementation (via isEqualTo) to the + /// derived class. + bool operator==(const NodeType &N) const { return getDerived().isEqualTo(N); } + bool operator!=(const NodeType &N) const { return !operator==(N); } + + const_iterator begin() const { return Edges.begin(); } + const_iterator end() const { return Edges.end(); } + iterator begin() { return Edges.begin(); } + iterator end() { return Edges.end(); } + const EdgeType &front() const { return *Edges.front(); } + EdgeType &front() { return *Edges.front(); } + const EdgeType &back() const { return *Edges.back(); } + EdgeType &back() { return *Edges.back(); } + + /// Collect in \p EL, all the edges from this node to \p N. + /// Return true if at least one edge was found, and false otherwise. + /// Note that this implementation allows more than one edge to connect + /// a given pair of nodes. + bool findEdgesTo(const NodeType &N, SmallVectorImpl<EdgeType *> &EL) const { + assert(EL.empty() && "Expected the list of edges to be empty."); + for (auto *E : Edges) + if (E->getTargetNode() == N) + EL.push_back(E); + return !EL.empty(); + } + + /// Add the given edge \p E to this node, if it doesn't exist already. Returns + /// true if the edge is added and false otherwise. + bool addEdge(EdgeType &E) { return Edges.insert(&E); } + + /// Remove the given edge \p E from this node, if it exists. + void removeEdge(EdgeType &E) { Edges.remove(&E); } + + /// Test whether there is an edge that goes from this node to \p N. + bool hasEdgeTo(const NodeType &N) const { + return (findEdgeTo(N) != Edges.end()); + } + + /// Retrieve the outgoing edges for the node. + const EdgeListTy &getEdges() const { return Edges; } + EdgeListTy &getEdges() { + return const_cast<EdgeListTy &>( + static_cast<const DGNode<NodeType, EdgeType> &>(*this).Edges); + } + + /// Clear the outgoing edges. + void clear() { Edges.clear(); } + +protected: + // As the default implementation use address comparison for equality. + bool isEqualTo(const NodeType &N) const { return this == &N; } + + // Cast the 'this' pointer to the derived type and return a reference. + NodeType &getDerived() { return *static_cast<NodeType *>(this); } + const NodeType &getDerived() const { + return *static_cast<const NodeType *>(this); + } + + /// Find an edge to \p N. If more than one edge exists, this will return + /// the first one in the list of edges. + const_iterator findEdgeTo(const NodeType &N) const { + return llvm::find_if( + Edges, [&N](const EdgeType *E) { return E->getTargetNode() == N; }); + } + + // The list of outgoing edges. + EdgeListTy Edges; +}; + +/// Directed graph +/// +/// The graph is represented by a table of nodes. +/// Each node contains a (possibly empty) list of outgoing edges. +/// Each edge contains the target node it connects to. +template <class NodeType, class EdgeType> class DirectedGraph { +protected: + using NodeListTy = SmallVector<NodeType *, 10>; + using EdgeListTy = SmallVector<EdgeType *, 10>; +public: + using iterator = typename NodeListTy::iterator; + using const_iterator = typename NodeListTy::const_iterator; + using DGraphType = DirectedGraph<NodeType, EdgeType>; + + DirectedGraph() = default; + explicit DirectedGraph(NodeType &N) : Nodes() { addNode(N); } + DirectedGraph(const DGraphType &G) : Nodes(G.Nodes) {} + DirectedGraph(DGraphType &&RHS) : Nodes(std::move(RHS.Nodes)) {} + DGraphType &operator=(const DGraphType &G) { + Nodes = G.Nodes; + return *this; + } + DGraphType &operator=(const DGraphType &&G) { + Nodes = std::move(G.Nodes); + return *this; + } + + const_iterator begin() const { return Nodes.begin(); } + const_iterator end() const { return Nodes.end(); } + iterator begin() { return Nodes.begin(); } + iterator end() { return Nodes.end(); } + const NodeType &front() const { return *Nodes.front(); } + NodeType &front() { return *Nodes.front(); } + const NodeType &back() const { return *Nodes.back(); } + NodeType &back() { return *Nodes.back(); } + + size_t size() const { return Nodes.size(); } + + /// Find the given node \p N in the table. + const_iterator findNode(const NodeType &N) const { + return llvm::find_if(Nodes, + [&N](const NodeType *Node) { return *Node == N; }); + } + iterator findNode(const NodeType &N) { + return const_cast<iterator>( + static_cast<const DGraphType &>(*this).findNode(N)); + } + + /// Add the given node \p N to the graph if it is not already present. + bool addNode(NodeType &N) { + if (findNode(N) != Nodes.end()) + return false; + Nodes.push_back(&N); + return true; + } + + /// Collect in \p EL all edges that are coming into node \p N. Return true + /// if at least one edge was found, and false otherwise. + bool findIncomingEdgesToNode(const NodeType &N, SmallVectorImpl<EdgeType*> &EL) const { + assert(EL.empty() && "Expected the list of edges to be empty."); + EdgeListTy TempList; + for (auto *Node : Nodes) { + if (*Node == N) + continue; + Node->findEdgesTo(N, TempList); + EL.insert(EL.end(), TempList.begin(), TempList.end()); + TempList.clear(); + } + return !EL.empty(); + } + + /// Remove the given node \p N from the graph. If the node has incoming or + /// outgoing edges, they are also removed. Return true if the node was found + /// and then removed, and false if the node was not found in the graph to + /// begin with. + bool removeNode(NodeType &N) { + iterator IT = findNode(N); + if (IT == Nodes.end()) + return false; + // Remove incoming edges. + EdgeListTy EL; + for (auto *Node : Nodes) { + if (*Node == N) + continue; + Node->findEdgesTo(N, EL); + for (auto *E : EL) + Node->removeEdge(*E); + EL.clear(); + } + N.clear(); + Nodes.erase(IT); + return true; + } + + /// Assuming nodes \p Src and \p Dst are already in the graph, connect node \p + /// Src to node \p Dst using the provided edge \p E. Return true if \p Src is + /// not already connected to \p Dst via \p E, and false otherwise. + bool connect(NodeType &Src, NodeType &Dst, EdgeType &E) { + assert(findNode(Src) != Nodes.end() && "Src node should be present."); + assert(findNode(Dst) != Nodes.end() && "Dst node should be present."); + assert((E.getTargetNode() == Dst) && + "Target of the given edge does not match Dst."); + return Src.addEdge(E); + } + +protected: + // The list of nodes in the graph. + NodeListTy Nodes; +}; + +} // namespace llvm + +#endif // LLVM_ADT_DIRECTEDGRAPH_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/EnumeratedArray.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/EnumeratedArray.h new file mode 100644 index 0000000..a952811 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/EnumeratedArray.h
@@ -0,0 +1,48 @@ +//===- llvm/ADT/EnumeratedArray.h - Enumerated Array-------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines an array type that can be indexed using scoped enum values. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ENUMERATEDARRAY_H +#define LLVM_ADT_ENUMERATEDARRAY_H + +#include <cassert> + +namespace llvm { + +template <typename ValueType, typename Enumeration, + Enumeration LargestEnum = Enumeration::Last, typename IndexType = int, + IndexType Size = 1 + static_cast<IndexType>(LargestEnum)> +class EnumeratedArray { +public: + EnumeratedArray() = default; + EnumeratedArray(ValueType V) { + for (IndexType IX = 0; IX < Size; ++IX) { + Underlying[IX] = V; + } + } + inline const ValueType &operator[](const Enumeration Index) const { + auto IX = static_cast<const IndexType>(Index); + assert(IX >= 0 && IX < Size && "Index is out of bounds."); + return Underlying[IX]; + } + inline ValueType &operator[](const Enumeration Index) { + return const_cast<ValueType &>( + static_cast<const EnumeratedArray<ValueType, Enumeration, LargestEnum, + IndexType, Size> &>(*this)[Index]); + } + +private: + ValueType Underlying[Size]; +}; + +} // namespace llvm + +#endif // LLVM_ADT_ENUMERATEDARRAY_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/EpochTracker.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/EpochTracker.h new file mode 100644 index 0000000..a782b47 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/EpochTracker.h
@@ -0,0 +1,98 @@ +//===- llvm/ADT/EpochTracker.h - ADT epoch tracking --------------*- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the DebugEpochBase and DebugEpochBase::HandleBase classes. +// These can be used to write iterators that are fail-fast when LLVM is built +// with asserts enabled. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_EPOCH_TRACKER_H +#define LLVM_ADT_EPOCH_TRACKER_H + +#include "llvm/Config/abi-breaking.h" + +#include <cstdint> + +namespace llvm { + +#if LLVM_ENABLE_ABI_BREAKING_CHECKS + +/// A base class for data structure classes wishing to make iterators +/// ("handles") pointing into themselves fail-fast. When building without +/// asserts, this class is empty and does nothing. +/// +/// DebugEpochBase does not by itself track handles pointing into itself. The +/// expectation is that routines touching the handles will poll on +/// isHandleInSync at appropriate points to assert that the handle they're using +/// is still valid. +/// +class DebugEpochBase { + uint64_t Epoch; + +public: + DebugEpochBase() : Epoch(0) {} + + /// Calling incrementEpoch invalidates all handles pointing into the + /// calling instance. + void incrementEpoch() { ++Epoch; } + + /// The destructor calls incrementEpoch to make use-after-free bugs + /// more likely to crash deterministically. + ~DebugEpochBase() { incrementEpoch(); } + + /// A base class for iterator classes ("handles") that wish to poll for + /// iterator invalidating modifications in the underlying data structure. + /// When LLVM is built without asserts, this class is empty and does nothing. + /// + /// HandleBase does not track the parent data structure by itself. It expects + /// the routines modifying the data structure to call incrementEpoch when they + /// make an iterator-invalidating modification. + /// + class HandleBase { + const uint64_t *EpochAddress; + uint64_t EpochAtCreation; + + public: + HandleBase() : EpochAddress(nullptr), EpochAtCreation(UINT64_MAX) {} + + explicit HandleBase(const DebugEpochBase *Parent) + : EpochAddress(&Parent->Epoch), EpochAtCreation(Parent->Epoch) {} + + /// Returns true if the DebugEpochBase this Handle is linked to has + /// not called incrementEpoch on itself since the creation of this + /// HandleBase instance. + bool isHandleInSync() const { return *EpochAddress == EpochAtCreation; } + + /// Returns a pointer to the epoch word stored in the data structure + /// this handle points into. Can be used to check if two iterators point + /// into the same data structure. + const void *getEpochAddress() const { return EpochAddress; } + }; +}; + +#else + +class DebugEpochBase { +public: + void incrementEpoch() {} + + class HandleBase { + public: + HandleBase() = default; + explicit HandleBase(const DebugEpochBase *) {} + bool isHandleInSync() const { return true; } + const void *getEpochAddress() const { return nullptr; } + }; +}; + +#endif // LLVM_ENABLE_ABI_BREAKING_CHECKS + +} // namespace llvm + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/EquivalenceClasses.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/EquivalenceClasses.h new file mode 100644 index 0000000..2cb7108 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/EquivalenceClasses.h
@@ -0,0 +1,297 @@ +//===- llvm/ADT/EquivalenceClasses.h - Generic Equiv. Classes ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Generic implementation of equivalence classes through the use Tarjan's +// efficient union-find algorithm. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_EQUIVALENCECLASSES_H +#define LLVM_ADT_EQUIVALENCECLASSES_H + +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <iterator> +#include <set> + +namespace llvm { + +/// EquivalenceClasses - This represents a collection of equivalence classes and +/// supports three efficient operations: insert an element into a class of its +/// own, union two classes, and find the class for a given element. In +/// addition to these modification methods, it is possible to iterate over all +/// of the equivalence classes and all of the elements in a class. +/// +/// This implementation is an efficient implementation that only stores one copy +/// of the element being indexed per entry in the set, and allows any arbitrary +/// type to be indexed (as long as it can be ordered with operator<). +/// +/// Here is a simple example using integers: +/// +/// \code +/// EquivalenceClasses<int> EC; +/// EC.unionSets(1, 2); // insert 1, 2 into the same set +/// EC.insert(4); EC.insert(5); // insert 4, 5 into own sets +/// EC.unionSets(5, 1); // merge the set for 1 with 5's set. +/// +/// for (EquivalenceClasses<int>::iterator I = EC.begin(), E = EC.end(); +/// I != E; ++I) { // Iterate over all of the equivalence sets. +/// if (!I->isLeader()) continue; // Ignore non-leader sets. +/// for (EquivalenceClasses<int>::member_iterator MI = EC.member_begin(I); +/// MI != EC.member_end(); ++MI) // Loop over members in this set. +/// cerr << *MI << " "; // Print member. +/// cerr << "\n"; // Finish set. +/// } +/// \endcode +/// +/// This example prints: +/// 4 +/// 5 1 2 +/// +template <class ElemTy> +class EquivalenceClasses { + /// ECValue - The EquivalenceClasses data structure is just a set of these. + /// Each of these represents a relation for a value. First it stores the + /// value itself, which provides the ordering that the set queries. Next, it + /// provides a "next pointer", which is used to enumerate all of the elements + /// in the unioned set. Finally, it defines either a "end of list pointer" or + /// "leader pointer" depending on whether the value itself is a leader. A + /// "leader pointer" points to the node that is the leader for this element, + /// if the node is not a leader. A "end of list pointer" points to the last + /// node in the list of members of this list. Whether or not a node is a + /// leader is determined by a bit stolen from one of the pointers. + class ECValue { + friend class EquivalenceClasses; + + mutable const ECValue *Leader, *Next; + ElemTy Data; + + // ECValue ctor - Start out with EndOfList pointing to this node, Next is + // Null, isLeader = true. + ECValue(const ElemTy &Elt) + : Leader(this), Next((ECValue*)(intptr_t)1), Data(Elt) {} + + const ECValue *getLeader() const { + if (isLeader()) return this; + if (Leader->isLeader()) return Leader; + // Path compression. + return Leader = Leader->getLeader(); + } + + const ECValue *getEndOfList() const { + assert(isLeader() && "Cannot get the end of a list for a non-leader!"); + return Leader; + } + + void setNext(const ECValue *NewNext) const { + assert(getNext() == nullptr && "Already has a next pointer!"); + Next = (const ECValue*)((intptr_t)NewNext | (intptr_t)isLeader()); + } + + public: + ECValue(const ECValue &RHS) : Leader(this), Next((ECValue*)(intptr_t)1), + Data(RHS.Data) { + // Only support copying of singleton nodes. + assert(RHS.isLeader() && RHS.getNext() == nullptr && "Not a singleton!"); + } + + bool operator<(const ECValue &UFN) const { return Data < UFN.Data; } + + bool isLeader() const { return (intptr_t)Next & 1; } + const ElemTy &getData() const { return Data; } + + const ECValue *getNext() const { + return (ECValue*)((intptr_t)Next & ~(intptr_t)1); + } + + template<typename T> + bool operator<(const T &Val) const { return Data < Val; } + }; + + /// TheMapping - This implicitly provides a mapping from ElemTy values to the + /// ECValues, it just keeps the key as part of the value. + std::set<ECValue> TheMapping; + +public: + EquivalenceClasses() = default; + EquivalenceClasses(const EquivalenceClasses &RHS) { + operator=(RHS); + } + + const EquivalenceClasses &operator=(const EquivalenceClasses &RHS) { + TheMapping.clear(); + for (iterator I = RHS.begin(), E = RHS.end(); I != E; ++I) + if (I->isLeader()) { + member_iterator MI = RHS.member_begin(I); + member_iterator LeaderIt = member_begin(insert(*MI)); + for (++MI; MI != member_end(); ++MI) + unionSets(LeaderIt, member_begin(insert(*MI))); + } + return *this; + } + + //===--------------------------------------------------------------------===// + // Inspection methods + // + + /// iterator* - Provides a way to iterate over all values in the set. + using iterator = typename std::set<ECValue>::const_iterator; + + iterator begin() const { return TheMapping.begin(); } + iterator end() const { return TheMapping.end(); } + + bool empty() const { return TheMapping.empty(); } + + /// member_* Iterate over the members of an equivalence class. + class member_iterator; + member_iterator member_begin(iterator I) const { + // Only leaders provide anything to iterate over. + return member_iterator(I->isLeader() ? &*I : nullptr); + } + member_iterator member_end() const { + return member_iterator(nullptr); + } + + /// findValue - Return an iterator to the specified value. If it does not + /// exist, end() is returned. + iterator findValue(const ElemTy &V) const { + return TheMapping.find(V); + } + + /// getLeaderValue - Return the leader for the specified value that is in the + /// set. It is an error to call this method for a value that is not yet in + /// the set. For that, call getOrInsertLeaderValue(V). + const ElemTy &getLeaderValue(const ElemTy &V) const { + member_iterator MI = findLeader(V); + assert(MI != member_end() && "Value is not in the set!"); + return *MI; + } + + /// getOrInsertLeaderValue - Return the leader for the specified value that is + /// in the set. If the member is not in the set, it is inserted, then + /// returned. + const ElemTy &getOrInsertLeaderValue(const ElemTy &V) { + member_iterator MI = findLeader(insert(V)); + assert(MI != member_end() && "Value is not in the set!"); + return *MI; + } + + /// getNumClasses - Return the number of equivalence classes in this set. + /// Note that this is a linear time operation. + unsigned getNumClasses() const { + unsigned NC = 0; + for (iterator I = begin(), E = end(); I != E; ++I) + if (I->isLeader()) ++NC; + return NC; + } + + //===--------------------------------------------------------------------===// + // Mutation methods + + /// insert - Insert a new value into the union/find set, ignoring the request + /// if the value already exists. + iterator insert(const ElemTy &Data) { + return TheMapping.insert(ECValue(Data)).first; + } + + /// findLeader - Given a value in the set, return a member iterator for the + /// equivalence class it is in. This does the path-compression part that + /// makes union-find "union findy". This returns an end iterator if the value + /// is not in the equivalence class. + member_iterator findLeader(iterator I) const { + if (I == TheMapping.end()) return member_end(); + return member_iterator(I->getLeader()); + } + member_iterator findLeader(const ElemTy &V) const { + return findLeader(TheMapping.find(V)); + } + + /// union - Merge the two equivalence sets for the specified values, inserting + /// them if they do not already exist in the equivalence set. + member_iterator unionSets(const ElemTy &V1, const ElemTy &V2) { + iterator V1I = insert(V1), V2I = insert(V2); + return unionSets(findLeader(V1I), findLeader(V2I)); + } + member_iterator unionSets(member_iterator L1, member_iterator L2) { + assert(L1 != member_end() && L2 != member_end() && "Illegal inputs!"); + if (L1 == L2) return L1; // Unifying the same two sets, noop. + + // Otherwise, this is a real union operation. Set the end of the L1 list to + // point to the L2 leader node. + const ECValue &L1LV = *L1.Node, &L2LV = *L2.Node; + L1LV.getEndOfList()->setNext(&L2LV); + + // Update L1LV's end of list pointer. + L1LV.Leader = L2LV.getEndOfList(); + + // Clear L2's leader flag: + L2LV.Next = L2LV.getNext(); + + // L2's leader is now L1. + L2LV.Leader = &L1LV; + return L1; + } + + // isEquivalent - Return true if V1 is equivalent to V2. This can happen if + // V1 is equal to V2 or if they belong to one equivalence class. + bool isEquivalent(const ElemTy &V1, const ElemTy &V2) const { + // Fast path: any element is equivalent to itself. + if (V1 == V2) + return true; + auto It = findLeader(V1); + return It != member_end() && It == findLeader(V2); + } + + class member_iterator : public std::iterator<std::forward_iterator_tag, + const ElemTy, ptrdiff_t> { + friend class EquivalenceClasses; + + using super = std::iterator<std::forward_iterator_tag, + const ElemTy, ptrdiff_t>; + + const ECValue *Node; + + public: + using size_type = size_t; + using pointer = typename super::pointer; + using reference = typename super::reference; + + explicit member_iterator() = default; + explicit member_iterator(const ECValue *N) : Node(N) {} + + reference operator*() const { + assert(Node != nullptr && "Dereferencing end()!"); + return Node->getData(); + } + pointer operator->() const { return &operator*(); } + + member_iterator &operator++() { + assert(Node != nullptr && "++'d off the end of the list!"); + Node = Node->getNext(); + return *this; + } + + member_iterator operator++(int) { // postincrement operators. + member_iterator tmp = *this; + ++*this; + return tmp; + } + + bool operator==(const member_iterator &RHS) const { + return Node == RHS.Node; + } + bool operator!=(const member_iterator &RHS) const { + return Node != RHS.Node; + } + }; +}; + +} // end namespace llvm + +#endif // LLVM_ADT_EQUIVALENCECLASSES_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/FloatingPointMode.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/FloatingPointMode.h new file mode 100644 index 0000000..670b236 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/FloatingPointMode.h
@@ -0,0 +1,62 @@ +//===- llvm/Support/FloatingPointMode.h -------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Utilities for dealing with flags related to floating point mode controls. +// +//===----------------------------------------------------------------------===/ + +#ifndef LLVM_FLOATINGPOINTMODE_H +#define LLVM_FLOATINGPOINTMODE_H + +#include "llvm/ADT/StringSwitch.h" + +namespace llvm { + +/// Represent handled modes for denormal (aka subnormal) modes in the floating +/// point environment. +enum class DenormalMode { + Invalid = -1, + + /// IEEE-754 denormal numbers preserved. + IEEE, + + /// The sign of a flushed-to-zero number is preserved in the sign of 0 + PreserveSign, + + /// Denormals are flushed to positive zero. + PositiveZero +}; + +/// Parse the expected names from the denormal-fp-math attribute. +inline DenormalMode parseDenormalFPAttribute(StringRef Str) { + // Assume ieee on unspecified attribute. + return StringSwitch<DenormalMode>(Str) + .Cases("", "ieee", DenormalMode::IEEE) + .Case("preserve-sign", DenormalMode::PreserveSign) + .Case("positive-zero", DenormalMode::PositiveZero) + .Default(DenormalMode::Invalid); +} + +/// Return the name used for the denormal handling mode used by the the +/// expected names from the denormal-fp-math attribute. +inline StringRef denormalModeName(DenormalMode Mode) { + switch (Mode) { + case DenormalMode::IEEE: + return "ieee"; + case DenormalMode::PreserveSign: + return "preserve-sign"; + case DenormalMode::PositiveZero: + return "positive-zero"; + default: + return ""; + } +} + +} + +#endif // LLVM_FLOATINGPOINTMODE_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/FoldingSet.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/FoldingSet.h new file mode 100644 index 0000000..4968b1e --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/FoldingSet.h
@@ -0,0 +1,761 @@ +//===- llvm/ADT/FoldingSet.h - Uniquing Hash Set ----------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines a hash set that can be used to remove duplication of nodes +// in a graph. This code was originally created by Chris Lattner for use with +// SelectionDAGCSEMap, but was isolated to provide use across the llvm code set. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_FOLDINGSET_H +#define LLVM_ADT_FOLDINGSET_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/iterator.h" +#include "llvm/Support/Allocator.h" +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <utility> + +namespace llvm { + +/// This folding set used for two purposes: +/// 1. Given information about a node we want to create, look up the unique +/// instance of the node in the set. If the node already exists, return +/// it, otherwise return the bucket it should be inserted into. +/// 2. Given a node that has already been created, remove it from the set. +/// +/// This class is implemented as a single-link chained hash table, where the +/// "buckets" are actually the nodes themselves (the next pointer is in the +/// node). The last node points back to the bucket to simplify node removal. +/// +/// Any node that is to be included in the folding set must be a subclass of +/// FoldingSetNode. The node class must also define a Profile method used to +/// establish the unique bits of data for the node. The Profile method is +/// passed a FoldingSetNodeID object which is used to gather the bits. Just +/// call one of the Add* functions defined in the FoldingSetBase::NodeID class. +/// NOTE: That the folding set does not own the nodes and it is the +/// responsibility of the user to dispose of the nodes. +/// +/// Eg. +/// class MyNode : public FoldingSetNode { +/// private: +/// std::string Name; +/// unsigned Value; +/// public: +/// MyNode(const char *N, unsigned V) : Name(N), Value(V) {} +/// ... +/// void Profile(FoldingSetNodeID &ID) const { +/// ID.AddString(Name); +/// ID.AddInteger(Value); +/// } +/// ... +/// }; +/// +/// To define the folding set itself use the FoldingSet template; +/// +/// Eg. +/// FoldingSet<MyNode> MyFoldingSet; +/// +/// Four public methods are available to manipulate the folding set; +/// +/// 1) If you have an existing node that you want add to the set but unsure +/// that the node might already exist then call; +/// +/// MyNode *M = MyFoldingSet.GetOrInsertNode(N); +/// +/// If The result is equal to the input then the node has been inserted. +/// Otherwise, the result is the node existing in the folding set, and the +/// input can be discarded (use the result instead.) +/// +/// 2) If you are ready to construct a node but want to check if it already +/// exists, then call FindNodeOrInsertPos with a FoldingSetNodeID of the bits to +/// check; +/// +/// FoldingSetNodeID ID; +/// ID.AddString(Name); +/// ID.AddInteger(Value); +/// void *InsertPoint; +/// +/// MyNode *M = MyFoldingSet.FindNodeOrInsertPos(ID, InsertPoint); +/// +/// If found then M will be non-NULL, else InsertPoint will point to where it +/// should be inserted using InsertNode. +/// +/// 3) If you get a NULL result from FindNodeOrInsertPos then you can insert a +/// new node with InsertNode; +/// +/// MyFoldingSet.InsertNode(M, InsertPoint); +/// +/// 4) Finally, if you want to remove a node from the folding set call; +/// +/// bool WasRemoved = MyFoldingSet.RemoveNode(M); +/// +/// The result indicates whether the node existed in the folding set. + +class FoldingSetNodeID; +class StringRef; + +//===----------------------------------------------------------------------===// +/// FoldingSetBase - Implements the folding set functionality. The main +/// structure is an array of buckets. Each bucket is indexed by the hash of +/// the nodes it contains. The bucket itself points to the nodes contained +/// in the bucket via a singly linked list. The last node in the list points +/// back to the bucket to facilitate node removal. +/// +class FoldingSetBase { + virtual void anchor(); // Out of line virtual method. + +protected: + /// Buckets - Array of bucket chains. + void **Buckets; + + /// NumBuckets - Length of the Buckets array. Always a power of 2. + unsigned NumBuckets; + + /// NumNodes - Number of nodes in the folding set. Growth occurs when NumNodes + /// is greater than twice the number of buckets. + unsigned NumNodes; + + explicit FoldingSetBase(unsigned Log2InitSize = 6); + FoldingSetBase(FoldingSetBase &&Arg); + FoldingSetBase &operator=(FoldingSetBase &&RHS); + ~FoldingSetBase(); + +public: + //===--------------------------------------------------------------------===// + /// Node - This class is used to maintain the singly linked bucket list in + /// a folding set. + class Node { + private: + // NextInFoldingSetBucket - next link in the bucket list. + void *NextInFoldingSetBucket = nullptr; + + public: + Node() = default; + + // Accessors + void *getNextInBucket() const { return NextInFoldingSetBucket; } + void SetNextInBucket(void *N) { NextInFoldingSetBucket = N; } + }; + + /// clear - Remove all nodes from the folding set. + void clear(); + + /// size - Returns the number of nodes in the folding set. + unsigned size() const { return NumNodes; } + + /// 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. + virtual void GetNodeProfile(Node *N, FoldingSetNodeID &ID) const = 0; + + /// NodeEquals - Instantiations of the FoldingSet template implement + /// this function to compare the given node with the given ID. + virtual bool NodeEquals(Node *N, const FoldingSetNodeID &ID, unsigned IDHash, + FoldingSetNodeID &TempID) const=0; + + /// ComputeNodeHash - Instantiations of the FoldingSet template implement + /// this function to compute a hash value for the given node. + virtual unsigned ComputeNodeHash(Node *N, FoldingSetNodeID &TempID) const = 0; + + // The below methods are protected to encourage subclasses to provide a more + // type-safe API. + + /// RemoveNode - Remove a node from the folding set, returning true if one + /// was removed or false if the node was not in the folding set. + bool RemoveNode(Node *N); + + /// GetOrInsertNode - If there is an existing simple Node exactly + /// equal to the specified node, return it. Otherwise, insert 'N' and return + /// it instead. + Node *GetOrInsertNode(Node *N); + + /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists, + /// return it. If not, return the insertion token that will make insertion + /// faster. + Node *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos); + + /// InsertNode - Insert the specified node into the folding set, knowing that + /// it is not already in the folding set. InsertPos must be obtained from + /// FindNodeOrInsertPos. + void InsertNode(Node *N, void *InsertPos); +}; + +//===----------------------------------------------------------------------===// + +/// DefaultFoldingSetTrait - This class provides default implementations +/// for FoldingSetTrait implementations. +template<typename T> struct DefaultFoldingSetTrait { + static void Profile(const T &X, FoldingSetNodeID &ID) { + X.Profile(ID); + } + static void Profile(T &X, FoldingSetNodeID &ID) { + X.Profile(ID); + } + + // Equals - Test if the profile for X would match ID, using TempID + // to compute a temporary ID if necessary. The default implementation + // just calls Profile and does a regular comparison. Implementations + // can override this to provide more efficient implementations. + static inline bool Equals(T &X, const FoldingSetNodeID &ID, unsigned IDHash, + FoldingSetNodeID &TempID); + + // ComputeHash - Compute a hash value for X, using TempID to + // compute a temporary ID if necessary. The default implementation + // just calls Profile and does a regular hash computation. + // Implementations can override this to provide more efficient + // implementations. + static inline unsigned ComputeHash(T &X, FoldingSetNodeID &TempID); +}; + +/// FoldingSetTrait - This trait class is used to define behavior of how +/// to "profile" (in the FoldingSet parlance) an object of a given type. +/// The default behavior is to invoke a 'Profile' method on an object, but +/// through template specialization the behavior can be tailored for specific +/// types. Combined with the FoldingSetNodeWrapper class, one can add objects +/// to FoldingSets that were not originally designed to have that behavior. +template<typename T> struct FoldingSetTrait + : public DefaultFoldingSetTrait<T> {}; + +/// DefaultContextualFoldingSetTrait - Like DefaultFoldingSetTrait, but +/// for ContextualFoldingSets. +template<typename T, typename Ctx> +struct DefaultContextualFoldingSetTrait { + static void Profile(T &X, FoldingSetNodeID &ID, Ctx Context) { + X.Profile(ID, Context); + } + + static inline bool Equals(T &X, const FoldingSetNodeID &ID, unsigned IDHash, + FoldingSetNodeID &TempID, Ctx Context); + static inline unsigned ComputeHash(T &X, FoldingSetNodeID &TempID, + Ctx Context); +}; + +/// ContextualFoldingSetTrait - Like FoldingSetTrait, but for +/// ContextualFoldingSets. +template<typename T, typename Ctx> struct ContextualFoldingSetTrait + : public DefaultContextualFoldingSetTrait<T, Ctx> {}; + +//===--------------------------------------------------------------------===// +/// FoldingSetNodeIDRef - This class describes a reference to an interned +/// FoldingSetNodeID, which can be a useful to store node id data rather +/// than using plain FoldingSetNodeIDs, since the 32-element SmallVector +/// is often much larger than necessary, and the possibility of heap +/// allocation means it requires a non-trivial destructor call. +class FoldingSetNodeIDRef { + const unsigned *Data = nullptr; + size_t Size = 0; + +public: + FoldingSetNodeIDRef() = default; + FoldingSetNodeIDRef(const unsigned *D, size_t S) : Data(D), Size(S) {} + + /// ComputeHash - Compute a strong hash value for this FoldingSetNodeIDRef, + /// used to lookup the node in the FoldingSetBase. + unsigned ComputeHash() const; + + bool operator==(FoldingSetNodeIDRef) const; + + bool operator!=(FoldingSetNodeIDRef RHS) const { return !(*this == RHS); } + + /// Used to compare the "ordering" of two nodes as defined by the + /// profiled bits and their ordering defined by memcmp(). + bool operator<(FoldingSetNodeIDRef) const; + + const unsigned *getData() const { return Data; } + size_t getSize() const { return Size; } +}; + +//===--------------------------------------------------------------------===// +/// FoldingSetNodeID - This class is used to gather all the unique data bits of +/// a node. When all the bits are gathered this class is used to produce a +/// hash value for the node. +class FoldingSetNodeID { + /// Bits - Vector of all the data bits that make the node unique. + /// Use a SmallVector to avoid a heap allocation in the common case. + SmallVector<unsigned, 32> Bits; + +public: + FoldingSetNodeID() = default; + + FoldingSetNodeID(FoldingSetNodeIDRef Ref) + : Bits(Ref.getData(), Ref.getData() + Ref.getSize()) {} + + /// Add* - Add various data types to Bit data. + void AddPointer(const void *Ptr); + void AddInteger(signed I); + void AddInteger(unsigned I); + void AddInteger(long I); + void AddInteger(unsigned long I); + void AddInteger(long long I); + void AddInteger(unsigned long long I); + void AddBoolean(bool B) { AddInteger(B ? 1U : 0U); } + void AddString(StringRef String); + void AddNodeID(const FoldingSetNodeID &ID); + + template <typename T> + inline void Add(const T &x) { FoldingSetTrait<T>::Profile(x, *this); } + + /// clear - Clear the accumulated profile, allowing this FoldingSetNodeID + /// object to be used to compute a new profile. + inline void clear() { Bits.clear(); } + + /// ComputeHash - Compute a strong hash value for this FoldingSetNodeID, used + /// to lookup the node in the FoldingSetBase. + unsigned ComputeHash() const; + + /// operator== - Used to compare two nodes to each other. + bool operator==(const FoldingSetNodeID &RHS) const; + bool operator==(const FoldingSetNodeIDRef RHS) const; + + bool operator!=(const FoldingSetNodeID &RHS) const { return !(*this == RHS); } + bool operator!=(const FoldingSetNodeIDRef RHS) const { return !(*this ==RHS);} + + /// Used to compare the "ordering" of two nodes as defined by the + /// profiled bits and their ordering defined by memcmp(). + bool operator<(const FoldingSetNodeID &RHS) const; + bool operator<(const FoldingSetNodeIDRef RHS) const; + + /// Intern - Copy this node's data to a memory region allocated from the + /// given allocator and return a FoldingSetNodeIDRef describing the + /// interned data. + FoldingSetNodeIDRef Intern(BumpPtrAllocator &Allocator) const; +}; + +// Convenience type to hide the implementation of the folding set. +using FoldingSetNode = FoldingSetBase::Node; +template<class T> class FoldingSetIterator; +template<class T> class FoldingSetBucketIterator; + +// Definitions of FoldingSetTrait and ContextualFoldingSetTrait functions, which +// require the definition of FoldingSetNodeID. +template<typename T> +inline bool +DefaultFoldingSetTrait<T>::Equals(T &X, const FoldingSetNodeID &ID, + unsigned /*IDHash*/, + FoldingSetNodeID &TempID) { + FoldingSetTrait<T>::Profile(X, TempID); + return TempID == ID; +} +template<typename T> +inline unsigned +DefaultFoldingSetTrait<T>::ComputeHash(T &X, FoldingSetNodeID &TempID) { + FoldingSetTrait<T>::Profile(X, TempID); + return TempID.ComputeHash(); +} +template<typename T, typename Ctx> +inline bool +DefaultContextualFoldingSetTrait<T, Ctx>::Equals(T &X, + const FoldingSetNodeID &ID, + unsigned /*IDHash*/, + FoldingSetNodeID &TempID, + Ctx Context) { + ContextualFoldingSetTrait<T, Ctx>::Profile(X, TempID, Context); + return TempID == ID; +} +template<typename T, typename Ctx> +inline unsigned +DefaultContextualFoldingSetTrait<T, Ctx>::ComputeHash(T &X, + FoldingSetNodeID &TempID, + Ctx Context) { + ContextualFoldingSetTrait<T, Ctx>::Profile(X, TempID, Context); + return TempID.ComputeHash(); +} + +//===----------------------------------------------------------------------===// +/// FoldingSetImpl - An implementation detail that lets us share code between +/// FoldingSet and ContextualFoldingSet. +template <class T> class FoldingSetImpl : public FoldingSetBase { +protected: + explicit FoldingSetImpl(unsigned Log2InitSize) + : FoldingSetBase(Log2InitSize) {} + + FoldingSetImpl(FoldingSetImpl &&Arg) = default; + FoldingSetImpl &operator=(FoldingSetImpl &&RHS) = default; + ~FoldingSetImpl() = default; + +public: + using iterator = FoldingSetIterator<T>; + + iterator begin() { return iterator(Buckets); } + iterator end() { return iterator(Buckets+NumBuckets); } + + using const_iterator = FoldingSetIterator<const T>; + + const_iterator begin() const { return const_iterator(Buckets); } + const_iterator end() const { return const_iterator(Buckets+NumBuckets); } + + using bucket_iterator = FoldingSetBucketIterator<T>; + + bucket_iterator bucket_begin(unsigned hash) { + return bucket_iterator(Buckets + (hash & (NumBuckets-1))); + } + + bucket_iterator bucket_end(unsigned hash) { + return bucket_iterator(Buckets + (hash & (NumBuckets-1)), true); + } + + /// RemoveNode - Remove a node from the folding set, returning true if one + /// was removed or false if the node was not in the folding set. + bool RemoveNode(T *N) { return FoldingSetBase::RemoveNode(N); } + + /// GetOrInsertNode - If there is an existing simple Node exactly + /// equal to the specified node, return it. Otherwise, insert 'N' and + /// return it instead. + T *GetOrInsertNode(T *N) { + return static_cast<T *>(FoldingSetBase::GetOrInsertNode(N)); + } + + /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists, + /// return it. If not, return the insertion token that will make insertion + /// faster. + T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) { + return static_cast<T *>(FoldingSetBase::FindNodeOrInsertPos(ID, InsertPos)); + } + + /// InsertNode - Insert the specified node into the folding set, knowing that + /// it is not already in the folding set. InsertPos must be obtained from + /// FindNodeOrInsertPos. + void InsertNode(T *N, void *InsertPos) { + FoldingSetBase::InsertNode(N, InsertPos); + } + + /// InsertNode - Insert the specified node into the folding set, knowing that + /// it is not already in the folding set. + void InsertNode(T *N) { + T *Inserted = GetOrInsertNode(N); + (void)Inserted; + assert(Inserted == N && "Node already inserted!"); + } +}; + +//===----------------------------------------------------------------------===// +/// FoldingSet - This template class is used to instantiate a specialized +/// implementation of the folding set to the node class T. T must be a +/// subclass of FoldingSetNode and implement a Profile function. +/// +/// Note that this set type is movable and move-assignable. However, its +/// moved-from state is not a valid state for anything other than +/// move-assigning and destroying. This is primarily to enable movable APIs +/// that incorporate these objects. +template <class T> class FoldingSet final : public FoldingSetImpl<T> { + using Super = FoldingSetImpl<T>; + using Node = typename Super::Node; + + /// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a + /// way to convert nodes into a unique specifier. + void GetNodeProfile(Node *N, FoldingSetNodeID &ID) const override { + T *TN = static_cast<T *>(N); + FoldingSetTrait<T>::Profile(*TN, ID); + } + + /// NodeEquals - Instantiations may optionally provide a way to compare a + /// node with a specified ID. + bool NodeEquals(Node *N, const FoldingSetNodeID &ID, unsigned IDHash, + FoldingSetNodeID &TempID) const override { + T *TN = static_cast<T *>(N); + return FoldingSetTrait<T>::Equals(*TN, ID, IDHash, TempID); + } + + /// ComputeNodeHash - Instantiations may optionally provide a way to compute a + /// hash value directly from a node. + unsigned ComputeNodeHash(Node *N, FoldingSetNodeID &TempID) const override { + T *TN = static_cast<T *>(N); + return FoldingSetTrait<T>::ComputeHash(*TN, TempID); + } + +public: + explicit FoldingSet(unsigned Log2InitSize = 6) : Super(Log2InitSize) {} + FoldingSet(FoldingSet &&Arg) = default; + FoldingSet &operator=(FoldingSet &&RHS) = default; +}; + +//===----------------------------------------------------------------------===// +/// ContextualFoldingSet - This template class is a further refinement +/// of FoldingSet which provides a context argument when calling +/// Profile on its nodes. Currently, that argument is fixed at +/// initialization time. +/// +/// T must be a subclass of FoldingSetNode and implement a Profile +/// function with signature +/// void Profile(FoldingSetNodeID &, Ctx); +template <class T, class Ctx> +class ContextualFoldingSet final : public FoldingSetImpl<T> { + // Unfortunately, this can't derive from FoldingSet<T> because the + // construction of the vtable for FoldingSet<T> requires + // FoldingSet<T>::GetNodeProfile to be instantiated, which in turn + // requires a single-argument T::Profile(). + + using Super = FoldingSetImpl<T>; + using Node = typename Super::Node; + + Ctx Context; + + /// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a + /// way to convert nodes into a unique specifier. + void GetNodeProfile(Node *N, FoldingSetNodeID &ID) const override { + T *TN = static_cast<T *>(N); + ContextualFoldingSetTrait<T, Ctx>::Profile(*TN, ID, Context); + } + + bool NodeEquals(Node *N, const FoldingSetNodeID &ID, unsigned IDHash, + FoldingSetNodeID &TempID) const override { + T *TN = static_cast<T *>(N); + return ContextualFoldingSetTrait<T, Ctx>::Equals(*TN, ID, IDHash, TempID, + Context); + } + + unsigned ComputeNodeHash(Node *N, FoldingSetNodeID &TempID) const override { + T *TN = static_cast<T *>(N); + return ContextualFoldingSetTrait<T, Ctx>::ComputeHash(*TN, TempID, Context); + } + +public: + explicit ContextualFoldingSet(Ctx Context, unsigned Log2InitSize = 6) + : Super(Log2InitSize), Context(Context) {} + + Ctx getContext() const { return Context; } +}; + +//===----------------------------------------------------------------------===// +/// FoldingSetVector - This template class combines a FoldingSet and a vector +/// to provide the interface of FoldingSet but with deterministic iteration +/// order based on the insertion order. T must be a subclass of FoldingSetNode +/// and implement a Profile function. +template <class T, class VectorT = SmallVector<T*, 8>> +class FoldingSetVector { + FoldingSet<T> Set; + VectorT Vector; + +public: + explicit FoldingSetVector(unsigned Log2InitSize = 6) : Set(Log2InitSize) {} + + using iterator = pointee_iterator<typename VectorT::iterator>; + + iterator begin() { return Vector.begin(); } + iterator end() { return Vector.end(); } + + using const_iterator = pointee_iterator<typename VectorT::const_iterator>; + + const_iterator begin() const { return Vector.begin(); } + const_iterator end() const { return Vector.end(); } + + /// clear - Remove all nodes from the folding set. + void clear() { Set.clear(); Vector.clear(); } + + /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists, + /// return it. If not, return the insertion token that will make insertion + /// faster. + T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) { + return Set.FindNodeOrInsertPos(ID, InsertPos); + } + + /// GetOrInsertNode - If there is an existing simple Node exactly + /// equal to the specified node, return it. Otherwise, insert 'N' and + /// return it instead. + T *GetOrInsertNode(T *N) { + T *Result = Set.GetOrInsertNode(N); + if (Result == N) Vector.push_back(N); + return Result; + } + + /// InsertNode - Insert the specified node into the folding set, knowing that + /// it is not already in the folding set. InsertPos must be obtained from + /// FindNodeOrInsertPos. + void InsertNode(T *N, void *InsertPos) { + Set.InsertNode(N, InsertPos); + Vector.push_back(N); + } + + /// InsertNode - Insert the specified node into the folding set, knowing that + /// it is not already in the folding set. + void InsertNode(T *N) { + Set.InsertNode(N); + Vector.push_back(N); + } + + /// size - Returns the number of nodes in the folding set. + unsigned size() const { return Set.size(); } + + /// empty - Returns true if there are no nodes in the folding set. + bool empty() const { return Set.empty(); } +}; + +//===----------------------------------------------------------------------===// +/// FoldingSetIteratorImpl - This is the common iterator support shared by all +/// folding sets, which knows how to walk the folding set hash table. +class FoldingSetIteratorImpl { +protected: + FoldingSetNode *NodePtr; + + FoldingSetIteratorImpl(void **Bucket); + + void advance(); + +public: + bool operator==(const FoldingSetIteratorImpl &RHS) const { + return NodePtr == RHS.NodePtr; + } + bool operator!=(const FoldingSetIteratorImpl &RHS) const { + return NodePtr != RHS.NodePtr; + } +}; + +template <class T> class FoldingSetIterator : public FoldingSetIteratorImpl { +public: + explicit FoldingSetIterator(void **Bucket) : FoldingSetIteratorImpl(Bucket) {} + + T &operator*() const { + return *static_cast<T*>(NodePtr); + } + + T *operator->() const { + return static_cast<T*>(NodePtr); + } + + inline FoldingSetIterator &operator++() { // Preincrement + advance(); + return *this; + } + FoldingSetIterator operator++(int) { // Postincrement + FoldingSetIterator tmp = *this; ++*this; return tmp; + } +}; + +//===----------------------------------------------------------------------===// +/// FoldingSetBucketIteratorImpl - This is the common bucket iterator support +/// shared by all folding sets, which knows how to walk a particular bucket +/// of a folding set hash table. +class FoldingSetBucketIteratorImpl { +protected: + void *Ptr; + + explicit FoldingSetBucketIteratorImpl(void **Bucket); + + FoldingSetBucketIteratorImpl(void **Bucket, bool) : Ptr(Bucket) {} + + void advance() { + void *Probe = static_cast<FoldingSetNode*>(Ptr)->getNextInBucket(); + uintptr_t x = reinterpret_cast<uintptr_t>(Probe) & ~0x1; + Ptr = reinterpret_cast<void*>(x); + } + +public: + bool operator==(const FoldingSetBucketIteratorImpl &RHS) const { + return Ptr == RHS.Ptr; + } + bool operator!=(const FoldingSetBucketIteratorImpl &RHS) const { + return Ptr != RHS.Ptr; + } +}; + +template <class T> +class FoldingSetBucketIterator : public FoldingSetBucketIteratorImpl { +public: + explicit FoldingSetBucketIterator(void **Bucket) : + FoldingSetBucketIteratorImpl(Bucket) {} + + FoldingSetBucketIterator(void **Bucket, bool) : + FoldingSetBucketIteratorImpl(Bucket, true) {} + + T &operator*() const { return *static_cast<T*>(Ptr); } + T *operator->() const { return static_cast<T*>(Ptr); } + + inline FoldingSetBucketIterator &operator++() { // Preincrement + advance(); + return *this; + } + FoldingSetBucketIterator operator++(int) { // Postincrement + FoldingSetBucketIterator tmp = *this; ++*this; return tmp; + } +}; + +//===----------------------------------------------------------------------===// +/// FoldingSetNodeWrapper - This template class is used to "wrap" arbitrary +/// types in an enclosing object so that they can be inserted into FoldingSets. +template <typename T> +class FoldingSetNodeWrapper : public FoldingSetNode { + T data; + +public: + template <typename... Ts> + explicit FoldingSetNodeWrapper(Ts &&... Args) + : data(std::forward<Ts>(Args)...) {} + + void Profile(FoldingSetNodeID &ID) { FoldingSetTrait<T>::Profile(data, ID); } + + T &getValue() { return data; } + const T &getValue() const { return data; } + + operator T&() { return data; } + operator const T&() const { return data; } +}; + +//===----------------------------------------------------------------------===// +/// FastFoldingSetNode - This is a subclass of FoldingSetNode which stores +/// a FoldingSetNodeID value rather than requiring the node to recompute it +/// each time it is needed. This trades space for speed (which can be +/// significant if the ID is long), and it also permits nodes to drop +/// information that would otherwise only be required for recomputing an ID. +class FastFoldingSetNode : public FoldingSetNode { + FoldingSetNodeID FastID; + +protected: + explicit FastFoldingSetNode(const FoldingSetNodeID &ID) : FastID(ID) {} + +public: + void Profile(FoldingSetNodeID &ID) const { ID.AddNodeID(FastID); } +}; + +//===----------------------------------------------------------------------===// +// Partial specializations of FoldingSetTrait. + +template<typename T> struct FoldingSetTrait<T*> { + static inline void Profile(T *X, FoldingSetNodeID &ID) { + ID.AddPointer(X); + } +}; +template <typename T1, typename T2> +struct FoldingSetTrait<std::pair<T1, T2>> { + static inline void Profile(const std::pair<T1, T2> &P, + FoldingSetNodeID &ID) { + ID.Add(P.first); + ID.Add(P.second); + } +}; + +} // end namespace llvm + +#endif // LLVM_ADT_FOLDINGSET_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/FunctionExtras.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/FunctionExtras.h new file mode 100644 index 0000000..121aa52 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/FunctionExtras.h
@@ -0,0 +1,292 @@ +//===- FunctionExtras.h - Function type erasure utilities -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// \file +/// This file provides a collection of function (or more generally, callable) +/// type erasure utilities supplementing those provided by the standard library +/// in `<function>`. +/// +/// It provides `unique_function`, which works like `std::function` but supports +/// move-only callable objects. +/// +/// Future plans: +/// - Add a `function` that provides const, volatile, and ref-qualified support, +/// which doesn't work with `std::function`. +/// - Provide support for specifying multiple signatures to type erase callable +/// objects with an overload set, such as those produced by generic lambdas. +/// - Expand to include a copyable utility that directly replaces std::function +/// but brings the above improvements. +/// +/// Note that LLVM's utilities are greatly simplified by not supporting +/// allocators. +/// +/// If the standard library ever begins to provide comparable facilities we can +/// consider switching to those. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_FUNCTION_EXTRAS_H +#define LLVM_ADT_FUNCTION_EXTRAS_H + +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/Support/type_traits.h" +#include <memory> + +namespace llvm { + +template <typename FunctionT> class unique_function; + +template <typename ReturnT, typename... ParamTs> +class unique_function<ReturnT(ParamTs...)> { + static constexpr size_t InlineStorageSize = sizeof(void *) * 3; + + // MSVC has a bug and ICEs if we give it a particular dependent value + // expression as part of the `std::conditional` below. To work around this, + // we build that into a template struct's constexpr bool. + template <typename T> struct IsSizeLessThanThresholdT { + static constexpr bool value = sizeof(T) <= (2 * sizeof(void *)); + }; + + // Provide a type function to map parameters that won't observe extra copies + // or moves and which are small enough to likely pass in register to values + // and all other types to l-value reference types. We use this to compute the + // types used in our erased call utility to minimize copies and moves unless + // doing so would force things unnecessarily into memory. + // + // The heuristic used is related to common ABI register passing conventions. + // It doesn't have to be exact though, and in one way it is more strict + // because we want to still be able to observe either moves *or* copies. + template <typename T> + using AdjustedParamT = typename std::conditional< + !std::is_reference<T>::value && + llvm::is_trivially_copy_constructible<T>::value && + llvm::is_trivially_move_constructible<T>::value && + IsSizeLessThanThresholdT<T>::value, + T, T &>::type; + + // The type of the erased function pointer we use as a callback to dispatch to + // the stored callable when it is trivial to move and destroy. + using CallPtrT = ReturnT (*)(void *CallableAddr, + AdjustedParamT<ParamTs>... Params); + using MovePtrT = void (*)(void *LHSCallableAddr, void *RHSCallableAddr); + using DestroyPtrT = void (*)(void *CallableAddr); + + /// A struct to hold a single trivial callback with sufficient alignment for + /// our bitpacking. + struct alignas(8) TrivialCallback { + CallPtrT CallPtr; + }; + + /// A struct we use to aggregate three callbacks when we need full set of + /// operations. + struct alignas(8) NonTrivialCallbacks { + CallPtrT CallPtr; + MovePtrT MovePtr; + DestroyPtrT DestroyPtr; + }; + + // Create a pointer union between either a pointer to a static trivial call + // pointer in a struct or a pointer to a static struct of the call, move, and + // destroy pointers. + using CallbackPointerUnionT = + PointerUnion<TrivialCallback *, NonTrivialCallbacks *>; + + // The main storage buffer. This will either have a pointer to out-of-line + // storage or an inline buffer storing the callable. + union StorageUnionT { + // For out-of-line storage we keep a pointer to the underlying storage and + // the size. This is enough to deallocate the memory. + struct OutOfLineStorageT { + void *StoragePtr; + size_t Size; + size_t Alignment; + } OutOfLineStorage; + static_assert( + sizeof(OutOfLineStorageT) <= InlineStorageSize, + "Should always use all of the out-of-line storage for inline storage!"); + + // For in-line storage, we just provide an aligned character buffer. We + // provide three pointers worth of storage here. + typename std::aligned_storage<InlineStorageSize, alignof(void *)>::type + InlineStorage; + } StorageUnion; + + // A compressed pointer to either our dispatching callback or our table of + // dispatching callbacks and the flag for whether the callable itself is + // stored inline or not. + PointerIntPair<CallbackPointerUnionT, 1, bool> CallbackAndInlineFlag; + + bool isInlineStorage() const { return CallbackAndInlineFlag.getInt(); } + + bool isTrivialCallback() const { + return CallbackAndInlineFlag.getPointer().template is<TrivialCallback *>(); + } + + CallPtrT getTrivialCallback() const { + return CallbackAndInlineFlag.getPointer().template get<TrivialCallback *>()->CallPtr; + } + + NonTrivialCallbacks *getNonTrivialCallbacks() const { + return CallbackAndInlineFlag.getPointer() + .template get<NonTrivialCallbacks *>(); + } + + void *getInlineStorage() { return &StorageUnion.InlineStorage; } + + void *getOutOfLineStorage() { + return StorageUnion.OutOfLineStorage.StoragePtr; + } + size_t getOutOfLineStorageSize() const { + return StorageUnion.OutOfLineStorage.Size; + } + size_t getOutOfLineStorageAlignment() const { + return StorageUnion.OutOfLineStorage.Alignment; + } + + void setOutOfLineStorage(void *Ptr, size_t Size, size_t Alignment) { + StorageUnion.OutOfLineStorage = {Ptr, Size, Alignment}; + } + + template <typename CallableT> + static ReturnT CallImpl(void *CallableAddr, AdjustedParamT<ParamTs>... Params) { + return (*reinterpret_cast<CallableT *>(CallableAddr))( + std::forward<ParamTs>(Params)...); + } + + template <typename CallableT> + static void MoveImpl(void *LHSCallableAddr, void *RHSCallableAddr) noexcept { + new (LHSCallableAddr) + CallableT(std::move(*reinterpret_cast<CallableT *>(RHSCallableAddr))); + } + + template <typename CallableT> + static void DestroyImpl(void *CallableAddr) noexcept { + reinterpret_cast<CallableT *>(CallableAddr)->~CallableT(); + } + +public: + unique_function() = default; + unique_function(std::nullptr_t /*null_callable*/) {} + + ~unique_function() { + if (!CallbackAndInlineFlag.getPointer()) + return; + + // Cache this value so we don't re-check it after type-erased operations. + bool IsInlineStorage = isInlineStorage(); + + if (!isTrivialCallback()) + getNonTrivialCallbacks()->DestroyPtr( + IsInlineStorage ? getInlineStorage() : getOutOfLineStorage()); + + if (!IsInlineStorage) + deallocate_buffer(getOutOfLineStorage(), getOutOfLineStorageSize(), + getOutOfLineStorageAlignment()); + } + + unique_function(unique_function &&RHS) noexcept { + // Copy the callback and inline flag. + CallbackAndInlineFlag = RHS.CallbackAndInlineFlag; + + // If the RHS is empty, just copying the above is sufficient. + if (!RHS) + return; + + if (!isInlineStorage()) { + // The out-of-line case is easiest to move. + StorageUnion.OutOfLineStorage = RHS.StorageUnion.OutOfLineStorage; + } else if (isTrivialCallback()) { + // Move is trivial, just memcpy the bytes across. + memcpy(getInlineStorage(), RHS.getInlineStorage(), InlineStorageSize); + } else { + // Non-trivial move, so dispatch to a type-erased implementation. + getNonTrivialCallbacks()->MovePtr(getInlineStorage(), + RHS.getInlineStorage()); + } + + // Clear the old callback and inline flag to get back to as-if-null. + RHS.CallbackAndInlineFlag = {}; + +#ifndef NDEBUG + // In debug builds, we also scribble across the rest of the storage. + memset(RHS.getInlineStorage(), 0xAD, InlineStorageSize); +#endif + } + + unique_function &operator=(unique_function &&RHS) noexcept { + if (this == &RHS) + return *this; + + // Because we don't try to provide any exception safety guarantees we can + // implement move assignment very simply by first destroying the current + // object and then move-constructing over top of it. + this->~unique_function(); + new (this) unique_function(std::move(RHS)); + return *this; + } + + template <typename CallableT> unique_function(CallableT Callable) { + bool IsInlineStorage = true; + void *CallableAddr = getInlineStorage(); + if (sizeof(CallableT) > InlineStorageSize || + alignof(CallableT) > alignof(decltype(StorageUnion.InlineStorage))) { + IsInlineStorage = false; + // Allocate out-of-line storage. FIXME: Use an explicit alignment + // parameter in C++17 mode. + auto Size = sizeof(CallableT); + auto Alignment = alignof(CallableT); + CallableAddr = allocate_buffer(Size, Alignment); + setOutOfLineStorage(CallableAddr, Size, Alignment); + } + + // Now move into the storage. + new (CallableAddr) CallableT(std::move(Callable)); + + // See if we can create a trivial callback. We need the callable to be + // trivially moved and trivially destroyed so that we don't have to store + // type erased callbacks for those operations. + // + // FIXME: We should use constexpr if here and below to avoid instantiating + // the non-trivial static objects when unnecessary. While the linker should + // remove them, it is still wasteful. + if (llvm::is_trivially_move_constructible<CallableT>::value && + std::is_trivially_destructible<CallableT>::value) { + // We need to create a nicely aligned object. We use a static variable + // for this because it is a trivial struct. + static TrivialCallback Callback = { &CallImpl<CallableT> }; + + CallbackAndInlineFlag = {&Callback, IsInlineStorage}; + return; + } + + // Otherwise, we need to point at an object that contains all the different + // type erased behaviors needed. Create a static instance of the struct type + // here and then use a pointer to that. + static NonTrivialCallbacks Callbacks = { + &CallImpl<CallableT>, &MoveImpl<CallableT>, &DestroyImpl<CallableT>}; + + CallbackAndInlineFlag = {&Callbacks, IsInlineStorage}; + } + + ReturnT operator()(ParamTs... Params) { + void *CallableAddr = + isInlineStorage() ? getInlineStorage() : getOutOfLineStorage(); + + return (isTrivialCallback() + ? getTrivialCallback() + : getNonTrivialCallbacks()->CallPtr)(CallableAddr, Params...); + } + + explicit operator bool() const { + return (bool)CallbackAndInlineFlag.getPointer(); + } +}; + +} // end namespace llvm + +#endif // LLVM_ADT_FUNCTION_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/GraphTraits.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/GraphTraits.h new file mode 100644 index 0000000..3ce9122 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/GraphTraits.h
@@ -0,0 +1,142 @@ +//===- llvm/ADT/GraphTraits.h - Graph traits template -----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the little GraphTraits<X> template class that should be +// specialized by classes that want to be iteratable by generic graph iterators. +// +// This file also defines the marker class Inverse that is used to iterate over +// graphs in a graph defined, inverse ordering... +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_GRAPHTRAITS_H +#define LLVM_ADT_GRAPHTRAITS_H + +#include "llvm/ADT/iterator_range.h" + +namespace llvm { + +// GraphTraits - This class should be specialized by different graph types... +// which is why the default version is empty. +// +// This template evolved from supporting `BasicBlock` to also later supporting +// more complex types (e.g. CFG and DomTree). +// +// GraphTraits can be used to create a view over a graph interpreting it +// differently without requiring a copy of the original graph. This could +// be achieved by carrying more data in NodeRef. See LoopBodyTraits for one +// example. +template<class GraphType> +struct GraphTraits { + // Elements to provide: + + // typedef NodeRef - Type of Node token in the graph, which should + // be cheap to copy. + // typedef ChildIteratorType - Type used to iterate over children in graph, + // dereference to a NodeRef. + + // static NodeRef getEntryNode(const GraphType &) + // Return the entry node of the graph + + // static ChildIteratorType child_begin(NodeRef) + // static ChildIteratorType child_end (NodeRef) + // Return iterators that point to the beginning and ending of the child + // node list for the specified node. + + // typedef ...iterator nodes_iterator; - dereference to a NodeRef + // static nodes_iterator nodes_begin(GraphType *G) + // static nodes_iterator nodes_end (GraphType *G) + // nodes_iterator/begin/end - Allow iteration over all nodes in the graph + + // typedef EdgeRef - Type of Edge token in the graph, which should + // be cheap to copy. + // typedef ChildEdgeIteratorType - Type used to iterate over children edges in + // graph, dereference to a EdgeRef. + + // static ChildEdgeIteratorType child_edge_begin(NodeRef) + // static ChildEdgeIteratorType child_edge_end(NodeRef) + // Return iterators that point to the beginning and ending of the + // edge list for the given callgraph node. + // + // static NodeRef edge_dest(EdgeRef) + // Return the destination node of an edge. + + // static unsigned size (GraphType *G) + // Return total number of nodes in the graph + + // If anyone tries to use this class without having an appropriate + // specialization, make an error. If you get this error, it's because you + // need to include the appropriate specialization of GraphTraits<> for your + // graph, or you need to define it for a new graph type. Either that or + // your argument to XXX_begin(...) is unknown or needs to have the proper .h + // file #include'd. + using NodeRef = typename GraphType::UnknownGraphTypeError; +}; + +// Inverse - This class is used as a little marker class to tell the graph +// iterator to iterate over the graph in a graph defined "Inverse" ordering. +// Not all graphs define an inverse ordering, and if they do, it depends on +// the graph exactly what that is. Here's an example of usage with the +// df_iterator: +// +// idf_iterator<Method*> I = idf_begin(M), E = idf_end(M); +// for (; I != E; ++I) { ... } +// +// Which is equivalent to: +// df_iterator<Inverse<Method*>> I = idf_begin(M), E = idf_end(M); +// for (; I != E; ++I) { ... } +// +template <class GraphType> +struct Inverse { + const GraphType &Graph; + + inline Inverse(const GraphType &G) : Graph(G) {} +}; + +// Provide a partial specialization of GraphTraits so that the inverse of an +// inverse falls back to the original graph. +template <class T> struct GraphTraits<Inverse<Inverse<T>>> : GraphTraits<T> {}; + +// Provide iterator ranges for the graph traits nodes and children +template <class GraphType> +iterator_range<typename GraphTraits<GraphType>::nodes_iterator> +nodes(const GraphType &G) { + return make_range(GraphTraits<GraphType>::nodes_begin(G), + GraphTraits<GraphType>::nodes_end(G)); +} +template <class GraphType> +iterator_range<typename GraphTraits<Inverse<GraphType>>::nodes_iterator> +inverse_nodes(const GraphType &G) { + return make_range(GraphTraits<Inverse<GraphType>>::nodes_begin(G), + GraphTraits<Inverse<GraphType>>::nodes_end(G)); +} + +template <class GraphType> +iterator_range<typename GraphTraits<GraphType>::ChildIteratorType> +children(const typename GraphTraits<GraphType>::NodeRef &G) { + return make_range(GraphTraits<GraphType>::child_begin(G), + GraphTraits<GraphType>::child_end(G)); +} + +template <class GraphType> +iterator_range<typename GraphTraits<Inverse<GraphType>>::ChildIteratorType> +inverse_children(const typename GraphTraits<GraphType>::NodeRef &G) { + return make_range(GraphTraits<Inverse<GraphType>>::child_begin(G), + GraphTraits<Inverse<GraphType>>::child_end(G)); +} + +template <class GraphType> +iterator_range<typename GraphTraits<GraphType>::ChildEdgeIteratorType> +children_edges(const typename GraphTraits<GraphType>::NodeRef &G) { + return make_range(GraphTraits<GraphType>::child_edge_begin(G), + GraphTraits<GraphType>::child_edge_end(G)); +} + +} // end namespace llvm + +#endif // LLVM_ADT_GRAPHTRAITS_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/Hashing.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/Hashing.h new file mode 100644 index 0000000..adcc5cf --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/Hashing.h
@@ -0,0 +1,659 @@ +//===-- llvm/ADT/Hashing.h - Utilities for hashing --------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the newly proposed standard C++ interfaces for hashing +// arbitrary data and building hash functions for user-defined types. This +// interface was originally proposed in N3333[1] and is currently under review +// for inclusion in a future TR and/or standard. +// +// The primary interfaces provide are comprised of one type and three functions: +// +// -- 'hash_code' class is an opaque type representing the hash code for some +// data. It is the intended product of hashing, and can be used to implement +// hash tables, checksumming, and other common uses of hashes. It is not an +// integer type (although it can be converted to one) because it is risky +// to assume much about the internals of a hash_code. In particular, each +// execution of the program has a high probability of producing a different +// hash_code for a given input. Thus their values are not stable to save or +// persist, and should only be used during the execution for the +// construction of hashing datastructures. +// +// -- 'hash_value' is a function designed to be overloaded for each +// user-defined type which wishes to be used within a hashing context. It +// should be overloaded within the user-defined type's namespace and found +// via ADL. Overloads for primitive types are provided by this library. +// +// -- 'hash_combine' and 'hash_combine_range' are functions designed to aid +// programmers in easily and intuitively combining a set of data into +// a single hash_code for their object. They should only logically be used +// within the implementation of a 'hash_value' routine or similar context. +// +// Note that 'hash_combine_range' contains very special logic for hashing +// a contiguous array of integers or pointers. This logic is *extremely* fast, +// on a modern Intel "Gainestown" Xeon (Nehalem uarch) @2.2 GHz, these were +// benchmarked at over 6.5 GiB/s for large keys, and <20 cycles/hash for keys +// under 32-bytes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_HASHING_H +#define LLVM_ADT_HASHING_H + +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/SwapByteOrder.h" +#include "llvm/Support/type_traits.h" +#include <algorithm> +#include <cassert> +#include <cstring> +#include <string> +#include <utility> + +namespace llvm { + +/// An opaque object representing a hash code. +/// +/// This object represents the result of hashing some entity. It is intended to +/// be used to implement hashtables or other hashing-based data structures. +/// While it wraps and exposes a numeric value, this value should not be +/// trusted to be stable or predictable across processes or executions. +/// +/// In order to obtain the hash_code for an object 'x': +/// \code +/// using llvm::hash_value; +/// llvm::hash_code code = hash_value(x); +/// \endcode +class hash_code { + size_t value; + +public: + /// Default construct a hash_code. + /// Note that this leaves the value uninitialized. + hash_code() = default; + + /// Form a hash code directly from a numerical value. + hash_code(size_t value) : value(value) {} + + /// Convert the hash code to its numerical value for use. + /*explicit*/ operator size_t() const { return value; } + + friend bool operator==(const hash_code &lhs, const hash_code &rhs) { + return lhs.value == rhs.value; + } + friend bool operator!=(const hash_code &lhs, const hash_code &rhs) { + return lhs.value != rhs.value; + } + + /// Allow a hash_code to be directly run through hash_value. + friend size_t hash_value(const hash_code &code) { return code.value; } +}; + +/// Compute a hash_code for any integer value. +/// +/// Note that this function is intended to compute the same hash_code for +/// a particular value without regard to the pre-promotion type. This is in +/// contrast to hash_combine which may produce different hash_codes for +/// differing argument types even if they would implicit promote to a common +/// type without changing the value. +template <typename T> +typename std::enable_if<is_integral_or_enum<T>::value, hash_code>::type +hash_value(T value); + +/// Compute a hash_code for a pointer's address. +/// +/// N.B.: This hashes the *address*. Not the value and not the type. +template <typename T> hash_code hash_value(const T *ptr); + +/// Compute a hash_code for a pair of objects. +template <typename T, typename U> +hash_code hash_value(const std::pair<T, U> &arg); + +/// Compute a hash_code for a standard string. +template <typename T> +hash_code hash_value(const std::basic_string<T> &arg); + + +/// Override the execution seed with a fixed value. +/// +/// This hashing library uses a per-execution seed designed to change on each +/// run with high probability in order to ensure that the hash codes are not +/// attackable and to ensure that output which is intended to be stable does +/// not rely on the particulars of the hash codes produced. +/// +/// That said, there are use cases where it is important to be able to +/// reproduce *exactly* a specific behavior. To that end, we provide a function +/// which will forcibly set the seed to a fixed value. This must be done at the +/// start of the program, before any hashes are computed. Also, it cannot be +/// undone. This makes it thread-hostile and very hard to use outside of +/// immediately on start of a simple program designed for reproducible +/// behavior. +void set_fixed_execution_hash_seed(uint64_t fixed_value); + + +// All of the implementation details of actually computing the various hash +// code values are held within this namespace. These routines are included in +// the header file mainly to allow inlining and constant propagation. +namespace hashing { +namespace detail { + +inline uint64_t fetch64(const char *p) { + uint64_t result; + memcpy(&result, p, sizeof(result)); + if (sys::IsBigEndianHost) + sys::swapByteOrder(result); + return result; +} + +inline uint32_t fetch32(const char *p) { + uint32_t result; + memcpy(&result, p, sizeof(result)); + if (sys::IsBigEndianHost) + sys::swapByteOrder(result); + return result; +} + +/// Some primes between 2^63 and 2^64 for various uses. +static const uint64_t k0 = 0xc3a5c85c97cb3127ULL; +static const uint64_t k1 = 0xb492b66fbe98f273ULL; +static const uint64_t k2 = 0x9ae16a3b2f90404fULL; +static const uint64_t k3 = 0xc949d7c7509e6557ULL; + +/// Bitwise right rotate. +/// Normally this will compile to a single instruction, especially if the +/// shift is a manifest constant. +inline uint64_t rotate(uint64_t val, size_t shift) { + // Avoid shifting by 64: doing so yields an undefined result. + return shift == 0 ? val : ((val >> shift) | (val << (64 - shift))); +} + +inline uint64_t shift_mix(uint64_t val) { + return val ^ (val >> 47); +} + +inline uint64_t hash_16_bytes(uint64_t low, uint64_t high) { + // Murmur-inspired hashing. + const uint64_t kMul = 0x9ddfea08eb382d69ULL; + uint64_t a = (low ^ high) * kMul; + a ^= (a >> 47); + uint64_t b = (high ^ a) * kMul; + b ^= (b >> 47); + b *= kMul; + return b; +} + +inline uint64_t hash_1to3_bytes(const char *s, size_t len, uint64_t seed) { + uint8_t a = s[0]; + uint8_t b = s[len >> 1]; + uint8_t c = s[len - 1]; + uint32_t y = static_cast<uint32_t>(a) + (static_cast<uint32_t>(b) << 8); + uint32_t z = static_cast<uint32_t>(len) + (static_cast<uint32_t>(c) << 2); + return shift_mix(y * k2 ^ z * k3 ^ seed) * k2; +} + +inline uint64_t hash_4to8_bytes(const char *s, size_t len, uint64_t seed) { + uint64_t a = fetch32(s); + return hash_16_bytes(len + (a << 3), seed ^ fetch32(s + len - 4)); +} + +inline uint64_t hash_9to16_bytes(const char *s, size_t len, uint64_t seed) { + uint64_t a = fetch64(s); + uint64_t b = fetch64(s + len - 8); + return hash_16_bytes(seed ^ a, rotate(b + len, len)) ^ b; +} + +inline uint64_t hash_17to32_bytes(const char *s, size_t len, uint64_t seed) { + uint64_t a = fetch64(s) * k1; + uint64_t b = fetch64(s + 8); + uint64_t c = fetch64(s + len - 8) * k2; + uint64_t d = fetch64(s + len - 16) * k0; + return hash_16_bytes(rotate(a - b, 43) + rotate(c ^ seed, 30) + d, + a + rotate(b ^ k3, 20) - c + len + seed); +} + +inline uint64_t hash_33to64_bytes(const char *s, size_t len, uint64_t seed) { + uint64_t z = fetch64(s + 24); + uint64_t a = fetch64(s) + (len + fetch64(s + len - 16)) * k0; + uint64_t b = rotate(a + z, 52); + uint64_t c = rotate(a, 37); + a += fetch64(s + 8); + c += rotate(a, 7); + a += fetch64(s + 16); + uint64_t vf = a + z; + uint64_t vs = b + rotate(a, 31) + c; + a = fetch64(s + 16) + fetch64(s + len - 32); + z = fetch64(s + len - 8); + b = rotate(a + z, 52); + c = rotate(a, 37); + a += fetch64(s + len - 24); + c += rotate(a, 7); + a += fetch64(s + len - 16); + uint64_t wf = a + z; + uint64_t ws = b + rotate(a, 31) + c; + uint64_t r = shift_mix((vf + ws) * k2 + (wf + vs) * k0); + return shift_mix((seed ^ (r * k0)) + vs) * k2; +} + +inline uint64_t hash_short(const char *s, size_t length, uint64_t seed) { + if (length >= 4 && length <= 8) + return hash_4to8_bytes(s, length, seed); + if (length > 8 && length <= 16) + return hash_9to16_bytes(s, length, seed); + if (length > 16 && length <= 32) + return hash_17to32_bytes(s, length, seed); + if (length > 32) + return hash_33to64_bytes(s, length, seed); + if (length != 0) + return hash_1to3_bytes(s, length, seed); + + return k2 ^ seed; +} + +/// The intermediate state used during hashing. +/// Currently, the algorithm for computing hash codes is based on CityHash and +/// keeps 56 bytes of arbitrary state. +struct hash_state { + uint64_t h0 = 0, h1 = 0, h2 = 0, h3 = 0, h4 = 0, h5 = 0, h6 = 0; + + /// Create a new hash_state structure and initialize it based on the + /// seed and the first 64-byte chunk. + /// This effectively performs the initial mix. + static hash_state create(const char *s, uint64_t seed) { + hash_state state = { + 0, seed, hash_16_bytes(seed, k1), rotate(seed ^ k1, 49), + seed * k1, shift_mix(seed), 0 }; + state.h6 = hash_16_bytes(state.h4, state.h5); + state.mix(s); + return state; + } + + /// Mix 32-bytes from the input sequence into the 16-bytes of 'a' + /// and 'b', including whatever is already in 'a' and 'b'. + static void mix_32_bytes(const char *s, uint64_t &a, uint64_t &b) { + a += fetch64(s); + uint64_t c = fetch64(s + 24); + b = rotate(b + a + c, 21); + uint64_t d = a; + a += fetch64(s + 8) + fetch64(s + 16); + b += rotate(a, 44) + d; + a += c; + } + + /// Mix in a 64-byte buffer of data. + /// We mix all 64 bytes even when the chunk length is smaller, but we + /// record the actual length. + void mix(const char *s) { + h0 = rotate(h0 + h1 + h3 + fetch64(s + 8), 37) * k1; + h1 = rotate(h1 + h4 + fetch64(s + 48), 42) * k1; + h0 ^= h6; + h1 += h3 + fetch64(s + 40); + h2 = rotate(h2 + h5, 33) * k1; + h3 = h4 * k1; + h4 = h0 + h5; + mix_32_bytes(s, h3, h4); + h5 = h2 + h6; + h6 = h1 + fetch64(s + 16); + mix_32_bytes(s + 32, h5, h6); + std::swap(h2, h0); + } + + /// Compute the final 64-bit hash code value based on the current + /// state and the length of bytes hashed. + uint64_t finalize(size_t length) { + return hash_16_bytes(hash_16_bytes(h3, h5) + shift_mix(h1) * k1 + h2, + hash_16_bytes(h4, h6) + shift_mix(length) * k1 + h0); + } +}; + + +/// A global, fixed seed-override variable. +/// +/// This variable can be set using the \see llvm::set_fixed_execution_seed +/// function. See that function for details. Do not, under any circumstances, +/// set or read this variable. +extern uint64_t fixed_seed_override; + +inline uint64_t get_execution_seed() { + // FIXME: This needs to be a per-execution seed. This is just a placeholder + // implementation. Switching to a per-execution seed is likely to flush out + // instability bugs and so will happen as its own commit. + // + // However, if there is a fixed seed override set the first time this is + // called, return that instead of the per-execution seed. + const uint64_t seed_prime = 0xff51afd7ed558ccdULL; + static uint64_t seed = fixed_seed_override ? fixed_seed_override : seed_prime; + return seed; +} + + +/// Trait to indicate whether a type's bits can be hashed directly. +/// +/// A type trait which is true if we want to combine values for hashing by +/// reading the underlying data. It is false if values of this type must +/// first be passed to hash_value, and the resulting hash_codes combined. +// +// FIXME: We want to replace is_integral_or_enum and is_pointer here with +// a predicate which asserts that comparing the underlying storage of two +// values of the type for equality is equivalent to comparing the two values +// for equality. For all the platforms we care about, this holds for integers +// and pointers, but there are platforms where it doesn't and we would like to +// support user-defined types which happen to satisfy this property. +template <typename T> struct is_hashable_data + : std::integral_constant<bool, ((is_integral_or_enum<T>::value || + std::is_pointer<T>::value) && + 64 % sizeof(T) == 0)> {}; + +// Special case std::pair to detect when both types are viable and when there +// is no alignment-derived padding in the pair. This is a bit of a lie because +// std::pair isn't truly POD, but it's close enough in all reasonable +// implementations for our use case of hashing the underlying data. +template <typename T, typename U> struct is_hashable_data<std::pair<T, U> > + : std::integral_constant<bool, (is_hashable_data<T>::value && + is_hashable_data<U>::value && + (sizeof(T) + sizeof(U)) == + sizeof(std::pair<T, U>))> {}; + +/// Helper to get the hashable data representation for a type. +/// This variant is enabled when the type itself can be used. +template <typename T> +typename std::enable_if<is_hashable_data<T>::value, T>::type +get_hashable_data(const T &value) { + return value; +} +/// Helper to get the hashable data representation for a type. +/// This variant is enabled when we must first call hash_value and use the +/// result as our data. +template <typename T> +typename std::enable_if<!is_hashable_data<T>::value, size_t>::type +get_hashable_data(const T &value) { + using ::llvm::hash_value; + return hash_value(value); +} + +/// Helper to store data from a value into a buffer and advance the +/// pointer into that buffer. +/// +/// This routine first checks whether there is enough space in the provided +/// buffer, and if not immediately returns false. If there is space, it +/// copies the underlying bytes of value into the buffer, advances the +/// buffer_ptr past the copied bytes, and returns true. +template <typename T> +bool store_and_advance(char *&buffer_ptr, char *buffer_end, const T& value, + size_t offset = 0) { + size_t store_size = sizeof(value) - offset; + if (buffer_ptr + store_size > buffer_end) + return false; + const char *value_data = reinterpret_cast<const char *>(&value); + memcpy(buffer_ptr, value_data + offset, store_size); + buffer_ptr += store_size; + return true; +} + +/// Implement the combining of integral values into a hash_code. +/// +/// This overload is selected when the value type of the iterator is +/// integral. Rather than computing a hash_code for each object and then +/// combining them, this (as an optimization) directly combines the integers. +template <typename InputIteratorT> +hash_code hash_combine_range_impl(InputIteratorT first, InputIteratorT last) { + const uint64_t seed = get_execution_seed(); + char buffer[64], *buffer_ptr = buffer; + char *const buffer_end = std::end(buffer); + while (first != last && store_and_advance(buffer_ptr, buffer_end, + get_hashable_data(*first))) + ++first; + if (first == last) + return hash_short(buffer, buffer_ptr - buffer, seed); + assert(buffer_ptr == buffer_end); + + hash_state state = state.create(buffer, seed); + size_t length = 64; + while (first != last) { + // Fill up the buffer. We don't clear it, which re-mixes the last round + // when only a partial 64-byte chunk is left. + buffer_ptr = buffer; + while (first != last && store_and_advance(buffer_ptr, buffer_end, + get_hashable_data(*first))) + ++first; + + // Rotate the buffer if we did a partial fill in order to simulate doing + // a mix of the last 64-bytes. That is how the algorithm works when we + // have a contiguous byte sequence, and we want to emulate that here. + std::rotate(buffer, buffer_ptr, buffer_end); + + // Mix this chunk into the current state. + state.mix(buffer); + length += buffer_ptr - buffer; + }; + + return state.finalize(length); +} + +/// Implement the combining of integral values into a hash_code. +/// +/// This overload is selected when the value type of the iterator is integral +/// and when the input iterator is actually a pointer. Rather than computing +/// a hash_code for each object and then combining them, this (as an +/// optimization) directly combines the integers. Also, because the integers +/// are stored in contiguous memory, this routine avoids copying each value +/// and directly reads from the underlying memory. +template <typename ValueT> +typename std::enable_if<is_hashable_data<ValueT>::value, hash_code>::type +hash_combine_range_impl(ValueT *first, ValueT *last) { + const uint64_t seed = get_execution_seed(); + const char *s_begin = reinterpret_cast<const char *>(first); + const char *s_end = reinterpret_cast<const char *>(last); + const size_t length = std::distance(s_begin, s_end); + if (length <= 64) + return hash_short(s_begin, length, seed); + + const char *s_aligned_end = s_begin + (length & ~63); + hash_state state = state.create(s_begin, seed); + s_begin += 64; + while (s_begin != s_aligned_end) { + state.mix(s_begin); + s_begin += 64; + } + if (length & 63) + state.mix(s_end - 64); + + return state.finalize(length); +} + +} // namespace detail +} // namespace hashing + + +/// Compute a hash_code for a sequence of values. +/// +/// This hashes a sequence of values. It produces the same hash_code as +/// 'hash_combine(a, b, c, ...)', but can run over arbitrary sized sequences +/// and is significantly faster given pointers and types which can be hashed as +/// a sequence of bytes. +template <typename InputIteratorT> +hash_code hash_combine_range(InputIteratorT first, InputIteratorT last) { + return ::llvm::hashing::detail::hash_combine_range_impl(first, last); +} + + +// Implementation details for hash_combine. +namespace hashing { +namespace detail { + +/// Helper class to manage the recursive combining of hash_combine +/// arguments. +/// +/// This class exists to manage the state and various calls involved in the +/// recursive combining of arguments used in hash_combine. It is particularly +/// useful at minimizing the code in the recursive calls to ease the pain +/// caused by a lack of variadic functions. +struct hash_combine_recursive_helper { + char buffer[64] = {}; + hash_state state; + const uint64_t seed; + +public: + /// Construct a recursive hash combining helper. + /// + /// This sets up the state for a recursive hash combine, including getting + /// the seed and buffer setup. + hash_combine_recursive_helper() + : seed(get_execution_seed()) {} + + /// Combine one chunk of data into the current in-flight hash. + /// + /// This merges one chunk of data into the hash. First it tries to buffer + /// the data. If the buffer is full, it hashes the buffer into its + /// hash_state, empties it, and then merges the new chunk in. This also + /// handles cases where the data straddles the end of the buffer. + template <typename T> + char *combine_data(size_t &length, char *buffer_ptr, char *buffer_end, T data) { + if (!store_and_advance(buffer_ptr, buffer_end, data)) { + // Check for skew which prevents the buffer from being packed, and do + // a partial store into the buffer to fill it. This is only a concern + // with the variadic combine because that formation can have varying + // argument types. + size_t partial_store_size = buffer_end - buffer_ptr; + memcpy(buffer_ptr, &data, partial_store_size); + + // If the store fails, our buffer is full and ready to hash. We have to + // either initialize the hash state (on the first full buffer) or mix + // this buffer into the existing hash state. Length tracks the *hashed* + // length, not the buffered length. + if (length == 0) { + state = state.create(buffer, seed); + length = 64; + } else { + // Mix this chunk into the current state and bump length up by 64. + state.mix(buffer); + length += 64; + } + // Reset the buffer_ptr to the head of the buffer for the next chunk of + // data. + buffer_ptr = buffer; + + // Try again to store into the buffer -- this cannot fail as we only + // store types smaller than the buffer. + if (!store_and_advance(buffer_ptr, buffer_end, data, + partial_store_size)) + llvm_unreachable("buffer smaller than stored type"); + } + return buffer_ptr; + } + + /// Recursive, variadic combining method. + /// + /// This function recurses through each argument, combining that argument + /// into a single hash. + template <typename T, typename ...Ts> + hash_code combine(size_t length, char *buffer_ptr, char *buffer_end, + const T &arg, const Ts &...args) { + buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg)); + + // Recurse to the next argument. + return combine(length, buffer_ptr, buffer_end, args...); + } + + /// Base case for recursive, variadic combining. + /// + /// The base case when combining arguments recursively is reached when all + /// arguments have been handled. It flushes the remaining buffer and + /// constructs a hash_code. + hash_code combine(size_t length, char *buffer_ptr, char *buffer_end) { + // Check whether the entire set of values fit in the buffer. If so, we'll + // use the optimized short hashing routine and skip state entirely. + if (length == 0) + return hash_short(buffer, buffer_ptr - buffer, seed); + + // Mix the final buffer, rotating it if we did a partial fill in order to + // simulate doing a mix of the last 64-bytes. That is how the algorithm + // works when we have a contiguous byte sequence, and we want to emulate + // that here. + std::rotate(buffer, buffer_ptr, buffer_end); + + // Mix this chunk into the current state. + state.mix(buffer); + length += buffer_ptr - buffer; + + return state.finalize(length); + } +}; + +} // namespace detail +} // namespace hashing + +/// Combine values into a single hash_code. +/// +/// This routine accepts a varying number of arguments of any type. It will +/// attempt to combine them into a single hash_code. For user-defined types it +/// attempts to call a \see hash_value overload (via ADL) for the type. For +/// integer and pointer types it directly combines their data into the +/// resulting hash_code. +/// +/// The result is suitable for returning from a user's hash_value +/// *implementation* for their user-defined type. Consumers of a type should +/// *not* call this routine, they should instead call 'hash_value'. +template <typename ...Ts> hash_code hash_combine(const Ts &...args) { + // Recursively hash each argument using a helper class. + ::llvm::hashing::detail::hash_combine_recursive_helper helper; + return helper.combine(0, helper.buffer, helper.buffer + 64, args...); +} + +// Implementation details for implementations of hash_value overloads provided +// here. +namespace hashing { +namespace detail { + +/// Helper to hash the value of a single integer. +/// +/// Overloads for smaller integer types are not provided to ensure consistent +/// behavior in the presence of integral promotions. Essentially, +/// "hash_value('4')" and "hash_value('0' + 4)" should be the same. +inline hash_code hash_integer_value(uint64_t value) { + // Similar to hash_4to8_bytes but using a seed instead of length. + const uint64_t seed = get_execution_seed(); + const char *s = reinterpret_cast<const char *>(&value); + const uint64_t a = fetch32(s); + return hash_16_bytes(seed + (a << 3), fetch32(s + 4)); +} + +} // namespace detail +} // namespace hashing + +// Declared and documented above, but defined here so that any of the hashing +// infrastructure is available. +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( + static_cast<uint64_t>(value)); +} + +// Declared and documented above, but defined here so that any of the hashing +// infrastructure is available. +template <typename T> hash_code hash_value(const T *ptr) { + return ::llvm::hashing::detail::hash_integer_value( + reinterpret_cast<uintptr_t>(ptr)); +} + +// Declared and documented above, but defined here so that any of the hashing +// infrastructure is available. +template <typename T, typename U> +hash_code hash_value(const std::pair<T, U> &arg) { + return hash_combine(arg.first, arg.second); +} + +// Declared and documented above, but defined here so that any of the hashing +// infrastructure is available. +template <typename T> +hash_code hash_value(const std::basic_string<T> &arg) { + return hash_combine_range(arg.begin(), arg.end()); +} + +} // namespace llvm + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/ImmutableList.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/ImmutableList.h new file mode 100644 index 0000000..c9ee494 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/ImmutableList.h
@@ -0,0 +1,246 @@ +//==--- ImmutableList.h - Immutable (functional) list interface --*- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the ImmutableList class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_IMMUTABLELIST_H +#define LLVM_ADT_IMMUTABLELIST_H + +#include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/Allocator.h" +#include <cassert> +#include <cstdint> +#include <new> + +namespace llvm { + +template <typename T> class ImmutableListFactory; + +template <typename T> +class ImmutableListImpl : public FoldingSetNode { + friend class ImmutableListFactory<T>; + + T Head; + const ImmutableListImpl* Tail; + + template <typename ElemT> + ImmutableListImpl(ElemT &&head, const ImmutableListImpl *tail = nullptr) + : Head(std::forward<ElemT>(head)), Tail(tail) {} + +public: + ImmutableListImpl(const ImmutableListImpl &) = delete; + ImmutableListImpl &operator=(const ImmutableListImpl &) = delete; + + const T& getHead() const { return Head; } + const ImmutableListImpl* getTail() const { return Tail; } + + static inline void Profile(FoldingSetNodeID& ID, const T& H, + const ImmutableListImpl* L){ + ID.AddPointer(L); + ID.Add(H); + } + + void Profile(FoldingSetNodeID& ID) { + Profile(ID, Head, Tail); + } +}; + +/// ImmutableList - This class represents an immutable (functional) list. +/// It is implemented as a smart pointer (wraps ImmutableListImpl), so it +/// it is intended to always be copied by value as if it were a pointer. +/// This interface matches ImmutableSet and ImmutableMap. ImmutableList +/// objects should almost never be created directly, and instead should +/// be created by ImmutableListFactory objects that manage the lifetime +/// of a group of lists. When the factory object is reclaimed, all lists +/// created by that factory are released as well. +template <typename T> +class ImmutableList { +public: + using value_type = T; + using Factory = ImmutableListFactory<T>; + + static_assert(std::is_trivially_destructible<T>::value, + "T must be trivially destructible!"); + +private: + const ImmutableListImpl<T>* X; + +public: + // This constructor should normally only be called by ImmutableListFactory<T>. + // There may be cases, however, when one needs to extract the internal pointer + // and reconstruct a list object from that pointer. + ImmutableList(const ImmutableListImpl<T>* x = nullptr) : X(x) {} + + const ImmutableListImpl<T>* getInternalPointer() const { + return X; + } + + class iterator { + const ImmutableListImpl<T>* L = nullptr; + + public: + iterator() = default; + iterator(ImmutableList l) : L(l.getInternalPointer()) {} + + iterator& operator++() { L = L->getTail(); return *this; } + bool operator==(const iterator& I) const { return L == I.L; } + bool operator!=(const iterator& I) const { return L != I.L; } + const value_type& operator*() const { return L->getHead(); } + const typename std::remove_reference<value_type>::type* operator->() const { + return &L->getHead(); + } + + ImmutableList getList() const { return L; } + }; + + /// begin - Returns an iterator referring to the head of the list, or + /// an iterator denoting the end of the list if the list is empty. + iterator begin() const { return iterator(X); } + + /// end - Returns an iterator denoting the end of the list. This iterator + /// does not refer to a valid list element. + iterator end() const { return iterator(); } + + /// isEmpty - Returns true if the list is empty. + bool isEmpty() const { return !X; } + + bool contains(const T& V) const { + for (iterator I = begin(), E = end(); I != E; ++I) { + if (*I == V) + return true; + } + return false; + } + + /// isEqual - Returns true if two lists are equal. Because all lists created + /// from the same ImmutableListFactory are uniqued, this has O(1) complexity + /// because it the contents of the list do not need to be compared. Note + /// that you should only compare two lists created from the same + /// ImmutableListFactory. + bool isEqual(const ImmutableList& L) const { return X == L.X; } + + bool operator==(const ImmutableList& L) const { return isEqual(L); } + + /// getHead - Returns the head of the list. + const T& getHead() const { + assert(!isEmpty() && "Cannot get the head of an empty list."); + return X->getHead(); + } + + /// getTail - Returns the tail of the list, which is another (possibly empty) + /// ImmutableList. + ImmutableList getTail() const { + return X ? X->getTail() : nullptr; + } + + void Profile(FoldingSetNodeID& ID) const { + ID.AddPointer(X); + } +}; + +template <typename T> +class ImmutableListFactory { + using ListTy = ImmutableListImpl<T>; + using CacheTy = FoldingSet<ListTy>; + + CacheTy Cache; + uintptr_t Allocator; + + bool ownsAllocator() const { + return (Allocator & 0x1) == 0; + } + + BumpPtrAllocator& getAllocator() const { + return *reinterpret_cast<BumpPtrAllocator*>(Allocator & ~0x1); + } + +public: + ImmutableListFactory() + : Allocator(reinterpret_cast<uintptr_t>(new BumpPtrAllocator())) {} + + ImmutableListFactory(BumpPtrAllocator& Alloc) + : Allocator(reinterpret_cast<uintptr_t>(&Alloc) | 0x1) {} + + ~ImmutableListFactory() { + if (ownsAllocator()) delete &getAllocator(); + } + + template <typename ElemT> + LLVM_NODISCARD ImmutableList<T> concat(ElemT &&Head, ImmutableList<T> Tail) { + // Profile the new list to see if it already exists in our cache. + FoldingSetNodeID ID; + void* InsertPos; + + const ListTy* TailImpl = Tail.getInternalPointer(); + ListTy::Profile(ID, Head, TailImpl); + ListTy* L = Cache.FindNodeOrInsertPos(ID, InsertPos); + + if (!L) { + // The list does not exist in our cache. Create it. + BumpPtrAllocator& A = getAllocator(); + L = (ListTy*) A.Allocate<ListTy>(); + new (L) ListTy(std::forward<ElemT>(Head), TailImpl); + + // Insert the new list into the cache. + Cache.InsertNode(L, InsertPos); + } + + return L; + } + + template <typename ElemT> + LLVM_NODISCARD ImmutableList<T> add(ElemT &&Data, ImmutableList<T> L) { + return concat(std::forward<ElemT>(Data), L); + } + + template <typename ...CtorArgs> + LLVM_NODISCARD ImmutableList<T> emplace(ImmutableList<T> Tail, + CtorArgs &&...Args) { + return concat(T(std::forward<CtorArgs>(Args)...), Tail); + } + + ImmutableList<T> getEmptyList() const { + return ImmutableList<T>(nullptr); + } + + template <typename ElemT> + ImmutableList<T> create(ElemT &&Data) { + return concat(std::forward<ElemT>(Data), getEmptyList()); + } +}; + +//===----------------------------------------------------------------------===// +// Partially-specialized Traits. +//===----------------------------------------------------------------------===// + +template<typename T> struct DenseMapInfo; +template<typename T> struct DenseMapInfo<ImmutableList<T>> { + static inline ImmutableList<T> getEmptyKey() { + return reinterpret_cast<ImmutableListImpl<T>*>(-1); + } + + static inline ImmutableList<T> getTombstoneKey() { + return reinterpret_cast<ImmutableListImpl<T>*>(-2); + } + + static unsigned getHashValue(ImmutableList<T> X) { + uintptr_t PtrVal = reinterpret_cast<uintptr_t>(X.getInternalPointer()); + return (unsigned((uintptr_t)PtrVal) >> 4) ^ + (unsigned((uintptr_t)PtrVal) >> 9); + } + + static bool isEqual(ImmutableList<T> X1, ImmutableList<T> X2) { + return X1 == X2; + } +}; + +} // end namespace llvm + +#endif // LLVM_ADT_IMMUTABLELIST_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/ImmutableMap.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/ImmutableMap.h new file mode 100644 index 0000000..86fd7fe --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/ImmutableMap.h
@@ -0,0 +1,414 @@ +//===--- ImmutableMap.h - Immutable (functional) map interface --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the ImmutableMap class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_IMMUTABLEMAP_H +#define LLVM_ADT_IMMUTABLEMAP_H + +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/ImmutableSet.h" +#include "llvm/Support/Allocator.h" +#include <utility> + +namespace llvm { + +/// ImutKeyValueInfo -Traits class used by ImmutableMap. While both the first +/// and second elements in a pair are used to generate profile information, +/// only the first element (the key) is used by isEqual and isLess. +template <typename T, typename S> +struct ImutKeyValueInfo { + using value_type = const std::pair<T,S>; + using value_type_ref = const value_type&; + using key_type = const T; + using key_type_ref = const T&; + using data_type = const S; + using data_type_ref = const S&; + + static inline key_type_ref KeyOfValue(value_type_ref V) { + return V.first; + } + + static inline data_type_ref DataOfValue(value_type_ref V) { + return V.second; + } + + static inline bool isEqual(key_type_ref L, key_type_ref R) { + return ImutContainerInfo<T>::isEqual(L,R); + } + static inline bool isLess(key_type_ref L, key_type_ref R) { + return ImutContainerInfo<T>::isLess(L,R); + } + + static inline bool isDataEqual(data_type_ref L, data_type_ref R) { + return ImutContainerInfo<S>::isEqual(L,R); + } + + static inline void Profile(FoldingSetNodeID& ID, value_type_ref V) { + ImutContainerInfo<T>::Profile(ID, V.first); + ImutContainerInfo<S>::Profile(ID, V.second); + } +}; + +template <typename KeyT, typename ValT, + typename ValInfo = ImutKeyValueInfo<KeyT,ValT>> +class ImmutableMap { +public: + using value_type = typename ValInfo::value_type; + using value_type_ref = typename ValInfo::value_type_ref; + using key_type = typename ValInfo::key_type; + using key_type_ref = typename ValInfo::key_type_ref; + using data_type = typename ValInfo::data_type; + using data_type_ref = typename ValInfo::data_type_ref; + using TreeTy = ImutAVLTree<ValInfo>; + +protected: + TreeTy* Root; + +public: + /// Constructs a map from a pointer to a tree root. In general one + /// should use a Factory object to create maps instead of directly + /// invoking the constructor, but there are cases where make this + /// constructor public is useful. + explicit ImmutableMap(const TreeTy* R) : Root(const_cast<TreeTy*>(R)) { + if (Root) { Root->retain(); } + } + + ImmutableMap(const ImmutableMap &X) : Root(X.Root) { + if (Root) { Root->retain(); } + } + + ~ImmutableMap() { + if (Root) { Root->release(); } + } + + ImmutableMap &operator=(const ImmutableMap &X) { + if (Root != X.Root) { + if (X.Root) { X.Root->retain(); } + if (Root) { Root->release(); } + Root = X.Root; + } + return *this; + } + + class Factory { + typename TreeTy::Factory F; + const bool Canonicalize; + + public: + Factory(bool canonicalize = true) : Canonicalize(canonicalize) {} + + Factory(BumpPtrAllocator &Alloc, bool canonicalize = true) + : F(Alloc), Canonicalize(canonicalize) {} + + Factory(const Factory &) = delete; + Factory &operator=(const Factory &) = delete; + + ImmutableMap getEmptyMap() { return ImmutableMap(F.getEmptyTree()); } + + LLVM_NODISCARD ImmutableMap add(ImmutableMap Old, key_type_ref K, + data_type_ref D) { + TreeTy *T = F.add(Old.Root, std::pair<key_type,data_type>(K,D)); + return ImmutableMap(Canonicalize ? F.getCanonicalTree(T): T); + } + + LLVM_NODISCARD ImmutableMap remove(ImmutableMap Old, key_type_ref K) { + TreeTy *T = F.remove(Old.Root,K); + return ImmutableMap(Canonicalize ? F.getCanonicalTree(T): T); + } + + typename TreeTy::Factory *getTreeFactory() const { + return const_cast<typename TreeTy::Factory *>(&F); + } + }; + + bool contains(key_type_ref K) const { + return Root ? Root->contains(K) : false; + } + + bool operator==(const ImmutableMap &RHS) const { + return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root; + } + + bool operator!=(const ImmutableMap &RHS) const { + return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root; + } + + TreeTy *getRoot() const { + if (Root) { Root->retain(); } + return Root; + } + + TreeTy *getRootWithoutRetain() const { return Root; } + + void manualRetain() { + if (Root) Root->retain(); + } + + void manualRelease() { + if (Root) Root->release(); + } + + bool isEmpty() const { return !Root; } + + //===--------------------------------------------------===// + // Foreach - A limited form of map iteration. + //===--------------------------------------------------===// + +private: + template <typename Callback> + struct CBWrapper { + Callback C; + + void operator()(value_type_ref V) { C(V.first,V.second); } + }; + + template <typename Callback> + struct CBWrapperRef { + Callback &C; + + CBWrapperRef(Callback& c) : C(c) {} + + void operator()(value_type_ref V) { C(V.first,V.second); } + }; + +public: + template <typename Callback> + void foreach(Callback& C) { + if (Root) { + CBWrapperRef<Callback> CB(C); + Root->foreach(CB); + } + } + + template <typename Callback> + void foreach() { + if (Root) { + CBWrapper<Callback> CB; + Root->foreach(CB); + } + } + + //===--------------------------------------------------===// + // For testing. + //===--------------------------------------------------===// + + void verify() const { if (Root) Root->verify(); } + + //===--------------------------------------------------===// + // Iterators. + //===--------------------------------------------------===// + + class iterator : public ImutAVLValueIterator<ImmutableMap> { + friend class ImmutableMap; + + iterator() = default; + explicit iterator(TreeTy *Tree) : iterator::ImutAVLValueIterator(Tree) {} + + public: + key_type_ref getKey() const { return (*this)->first; } + data_type_ref getData() const { return (*this)->second; } + }; + + iterator begin() const { return iterator(Root); } + iterator end() const { return iterator(); } + + data_type* lookup(key_type_ref K) const { + if (Root) { + TreeTy* T = Root->find(K); + if (T) return &T->getValue().second; + } + + return nullptr; + } + + /// getMaxElement - Returns the <key,value> pair in the ImmutableMap for + /// which key is the highest in the ordering of keys in the map. This + /// method returns NULL if the map is empty. + value_type* getMaxElement() const { + return Root ? &(Root->getMaxElement()->getValue()) : nullptr; + } + + //===--------------------------------------------------===// + // Utility methods. + //===--------------------------------------------------===// + + unsigned getHeight() const { return Root ? Root->getHeight() : 0; } + + static inline void Profile(FoldingSetNodeID& ID, const ImmutableMap& M) { + ID.AddPointer(M.Root); + } + + inline void Profile(FoldingSetNodeID& ID) const { + return Profile(ID,*this); + } +}; + +// NOTE: This will possibly become the new implementation of ImmutableMap some day. +template <typename KeyT, typename ValT, +typename ValInfo = ImutKeyValueInfo<KeyT,ValT>> +class ImmutableMapRef { +public: + using value_type = typename ValInfo::value_type; + using value_type_ref = typename ValInfo::value_type_ref; + using key_type = typename ValInfo::key_type; + using key_type_ref = typename ValInfo::key_type_ref; + using data_type = typename ValInfo::data_type; + using data_type_ref = typename ValInfo::data_type_ref; + using TreeTy = ImutAVLTree<ValInfo>; + using FactoryTy = typename TreeTy::Factory; + +protected: + TreeTy *Root; + FactoryTy *Factory; + +public: + /// Constructs a map from a pointer to a tree root. In general one + /// should use a Factory object to create maps instead of directly + /// invoking the constructor, but there are cases where make this + /// constructor public is useful. + explicit ImmutableMapRef(const TreeTy *R, FactoryTy *F) + : Root(const_cast<TreeTy *>(R)), Factory(F) { + if (Root) { + Root->retain(); + } + } + + explicit ImmutableMapRef(const ImmutableMap<KeyT, ValT> &X, + typename ImmutableMap<KeyT, ValT>::Factory &F) + : Root(X.getRootWithoutRetain()), + Factory(F.getTreeFactory()) { + if (Root) { Root->retain(); } + } + + ImmutableMapRef(const ImmutableMapRef &X) : Root(X.Root), Factory(X.Factory) { + if (Root) { + Root->retain(); + } + } + + ~ImmutableMapRef() { + if (Root) + Root->release(); + } + + ImmutableMapRef &operator=(const ImmutableMapRef &X) { + if (Root != X.Root) { + if (X.Root) + X.Root->retain(); + + if (Root) + Root->release(); + + Root = X.Root; + Factory = X.Factory; + } + return *this; + } + + static inline ImmutableMapRef getEmptyMap(FactoryTy *F) { + return ImmutableMapRef(0, F); + } + + void manualRetain() { + if (Root) Root->retain(); + } + + void manualRelease() { + if (Root) Root->release(); + } + + ImmutableMapRef add(key_type_ref K, data_type_ref D) const { + TreeTy *NewT = Factory->add(Root, std::pair<key_type, data_type>(K, D)); + return ImmutableMapRef(NewT, Factory); + } + + ImmutableMapRef remove(key_type_ref K) const { + TreeTy *NewT = Factory->remove(Root, K); + return ImmutableMapRef(NewT, Factory); + } + + bool contains(key_type_ref K) const { + return Root ? Root->contains(K) : false; + } + + ImmutableMap<KeyT, ValT> asImmutableMap() const { + return ImmutableMap<KeyT, ValT>(Factory->getCanonicalTree(Root)); + } + + bool operator==(const ImmutableMapRef &RHS) const { + return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root; + } + + bool operator!=(const ImmutableMapRef &RHS) const { + return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root; + } + + bool isEmpty() const { return !Root; } + + //===--------------------------------------------------===// + // For testing. + //===--------------------------------------------------===// + + void verify() const { + if (Root) + Root->verify(); + } + + //===--------------------------------------------------===// + // Iterators. + //===--------------------------------------------------===// + + class iterator : public ImutAVLValueIterator<ImmutableMapRef> { + friend class ImmutableMapRef; + + iterator() = default; + explicit iterator(TreeTy *Tree) : iterator::ImutAVLValueIterator(Tree) {} + + public: + key_type_ref getKey() const { return (*this)->first; } + data_type_ref getData() const { return (*this)->second; } + }; + + iterator begin() const { return iterator(Root); } + iterator end() const { return iterator(); } + + data_type *lookup(key_type_ref K) const { + if (Root) { + TreeTy* T = Root->find(K); + if (T) return &T->getValue().second; + } + + return nullptr; + } + + /// getMaxElement - Returns the <key,value> pair in the ImmutableMap for + /// which key is the highest in the ordering of keys in the map. This + /// method returns NULL if the map is empty. + value_type* getMaxElement() const { + return Root ? &(Root->getMaxElement()->getValue()) : 0; + } + + //===--------------------------------------------------===// + // Utility methods. + //===--------------------------------------------------===// + + unsigned getHeight() const { return Root ? Root->getHeight() : 0; } + + static inline void Profile(FoldingSetNodeID &ID, const ImmutableMapRef &M) { + ID.AddPointer(M.Root); + } + + inline void Profile(FoldingSetNodeID &ID) const { return Profile(ID, *this); } +}; + +} // end namespace llvm + +#endif // LLVM_ADT_IMMUTABLEMAP_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/ImmutableSet.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/ImmutableSet.h new file mode 100644 index 0000000..a6a6abf --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/ImmutableSet.h
@@ -0,0 +1,1222 @@ +//===--- ImmutableSet.h - Immutable (functional) set interface --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the ImutAVLTree and ImmutableSet classes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_IMMUTABLESET_H +#define LLVM_ADT_IMMUTABLESET_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/iterator.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/ErrorHandling.h" +#include <cassert> +#include <cstdint> +#include <functional> +#include <iterator> +#include <new> +#include <vector> + +namespace llvm { + +//===----------------------------------------------------------------------===// +// Immutable AVL-Tree Definition. +//===----------------------------------------------------------------------===// + +template <typename ImutInfo> class ImutAVLFactory; +template <typename ImutInfo> class ImutIntervalAVLFactory; +template <typename ImutInfo> class ImutAVLTreeInOrderIterator; +template <typename ImutInfo> class ImutAVLTreeGenericIterator; + +template <typename ImutInfo > +class ImutAVLTree { +public: + using key_type_ref = typename ImutInfo::key_type_ref; + using value_type = typename ImutInfo::value_type; + using value_type_ref = typename ImutInfo::value_type_ref; + using Factory = ImutAVLFactory<ImutInfo>; + using iterator = ImutAVLTreeInOrderIterator<ImutInfo>; + + friend class ImutAVLFactory<ImutInfo>; + friend class ImutIntervalAVLFactory<ImutInfo>; + friend class ImutAVLTreeGenericIterator<ImutInfo>; + + //===----------------------------------------------------===// + // Public Interface. + //===----------------------------------------------------===// + + /// Return a pointer to the left subtree. This value + /// is NULL if there is no left subtree. + ImutAVLTree *getLeft() const { return left; } + + /// Return a pointer to the right subtree. This value is + /// NULL if there is no right subtree. + ImutAVLTree *getRight() const { return right; } + + /// getHeight - Returns the height of the tree. A tree with no subtrees + /// has a height of 1. + unsigned getHeight() const { return height; } + + /// getValue - Returns the data value associated with the tree node. + const value_type& getValue() const { return value; } + + /// find - Finds the subtree associated with the specified key value. + /// This method returns NULL if no matching subtree is found. + ImutAVLTree* find(key_type_ref K) { + ImutAVLTree *T = this; + while (T) { + key_type_ref CurrentKey = ImutInfo::KeyOfValue(T->getValue()); + if (ImutInfo::isEqual(K,CurrentKey)) + return T; + else if (ImutInfo::isLess(K,CurrentKey)) + T = T->getLeft(); + else + T = T->getRight(); + } + return nullptr; + } + + /// getMaxElement - Find the subtree associated with the highest ranged + /// key value. + ImutAVLTree* getMaxElement() { + ImutAVLTree *T = this; + ImutAVLTree *Right = T->getRight(); + while (Right) { T = Right; Right = T->getRight(); } + return T; + } + + /// size - Returns the number of nodes in the tree, which includes + /// both leaves and non-leaf nodes. + unsigned size() const { + unsigned n = 1; + if (const ImutAVLTree* L = getLeft()) + n += L->size(); + if (const ImutAVLTree* R = getRight()) + n += R->size(); + return n; + } + + /// begin - Returns an iterator that iterates over the nodes of the tree + /// in an inorder traversal. The returned iterator thus refers to the + /// the tree node with the minimum data element. + iterator begin() const { return iterator(this); } + + /// end - Returns an iterator for the tree that denotes the end of an + /// inorder traversal. + iterator end() const { return iterator(); } + + bool isElementEqual(value_type_ref V) const { + // Compare the keys. + if (!ImutInfo::isEqual(ImutInfo::KeyOfValue(getValue()), + ImutInfo::KeyOfValue(V))) + return false; + + // Also compare the data values. + if (!ImutInfo::isDataEqual(ImutInfo::DataOfValue(getValue()), + ImutInfo::DataOfValue(V))) + return false; + + return true; + } + + bool isElementEqual(const ImutAVLTree* RHS) const { + return isElementEqual(RHS->getValue()); + } + + /// isEqual - Compares two trees for structural equality and returns true + /// if they are equal. This worst case performance of this operation is + // linear in the sizes of the trees. + bool isEqual(const ImutAVLTree& RHS) const { + if (&RHS == this) + return true; + + iterator LItr = begin(), LEnd = end(); + iterator RItr = RHS.begin(), REnd = RHS.end(); + + while (LItr != LEnd && RItr != REnd) { + if (&*LItr == &*RItr) { + LItr.skipSubTree(); + RItr.skipSubTree(); + continue; + } + + if (!LItr->isElementEqual(&*RItr)) + return false; + + ++LItr; + ++RItr; + } + + return LItr == LEnd && RItr == REnd; + } + + /// isNotEqual - Compares two trees for structural inequality. Performance + /// is the same is isEqual. + bool isNotEqual(const ImutAVLTree& RHS) const { return !isEqual(RHS); } + + /// contains - Returns true if this tree contains a subtree (node) that + /// has an data element that matches the specified key. Complexity + /// is logarithmic in the size of the tree. + bool contains(key_type_ref K) { return (bool) find(K); } + + /// foreach - A member template the accepts invokes operator() on a functor + /// object (specifed by Callback) for every node/subtree in the tree. + /// Nodes are visited using an inorder traversal. + template <typename Callback> + void foreach(Callback& C) { + if (ImutAVLTree* L = getLeft()) + L->foreach(C); + + C(value); + + if (ImutAVLTree* R = getRight()) + R->foreach(C); + } + + /// validateTree - A utility method that checks that the balancing and + /// ordering invariants of the tree are satisifed. It is a recursive + /// method that returns the height of the tree, which is then consumed + /// by the enclosing validateTree call. External callers should ignore the + /// return value. An invalid tree will cause an assertion to fire in + /// a debug build. + unsigned validateTree() const { + unsigned HL = getLeft() ? getLeft()->validateTree() : 0; + unsigned HR = getRight() ? getRight()->validateTree() : 0; + (void) HL; + (void) HR; + + assert(getHeight() == ( HL > HR ? HL : HR ) + 1 + && "Height calculation wrong"); + + assert((HL > HR ? HL-HR : HR-HL) <= 2 + && "Balancing invariant violated"); + + assert((!getLeft() || + ImutInfo::isLess(ImutInfo::KeyOfValue(getLeft()->getValue()), + ImutInfo::KeyOfValue(getValue()))) && + "Value in left child is not less that current value"); + + assert((!getRight() || + ImutInfo::isLess(ImutInfo::KeyOfValue(getValue()), + ImutInfo::KeyOfValue(getRight()->getValue()))) && + "Current value is not less that value of right child"); + + return getHeight(); + } + + //===----------------------------------------------------===// + // Internal values. + //===----------------------------------------------------===// + +private: + Factory *factory; + ImutAVLTree *left; + ImutAVLTree *right; + ImutAVLTree *prev = nullptr; + ImutAVLTree *next = nullptr; + + unsigned height : 28; + bool IsMutable : 1; + bool IsDigestCached : 1; + bool IsCanonicalized : 1; + + value_type value; + uint32_t digest = 0; + uint32_t refCount = 0; + + //===----------------------------------------------------===// + // Internal methods (node manipulation; used by Factory). + //===----------------------------------------------------===// + +private: + /// ImutAVLTree - Internal constructor that is only called by + /// ImutAVLFactory. + ImutAVLTree(Factory *f, ImutAVLTree* l, ImutAVLTree* r, value_type_ref v, + unsigned height) + : factory(f), left(l), right(r), height(height), IsMutable(true), + IsDigestCached(false), IsCanonicalized(false), value(v) + { + if (left) left->retain(); + if (right) right->retain(); + } + + /// isMutable - Returns true if the left and right subtree references + /// (as well as height) can be changed. If this method returns false, + /// the tree is truly immutable. Trees returned from an ImutAVLFactory + /// object should always have this method return true. Further, if this + /// method returns false for an instance of ImutAVLTree, all subtrees + /// will also have this method return false. The converse is not true. + bool isMutable() const { return IsMutable; } + + /// hasCachedDigest - Returns true if the digest for this tree is cached. + /// This can only be true if the tree is immutable. + bool hasCachedDigest() const { return IsDigestCached; } + + //===----------------------------------------------------===// + // Mutating operations. A tree root can be manipulated as + // long as its reference has not "escaped" from internal + // methods of a factory object (see below). When a tree + // pointer is externally viewable by client code, the + // internal "mutable bit" is cleared to mark the tree + // immutable. Note that a tree that still has its mutable + // bit set may have children (subtrees) that are themselves + // immutable. + //===----------------------------------------------------===// + + /// markImmutable - Clears the mutable flag for a tree. After this happens, + /// it is an error to call setLeft(), setRight(), and setHeight(). + void markImmutable() { + assert(isMutable() && "Mutable flag already removed."); + IsMutable = false; + } + + /// markedCachedDigest - Clears the NoCachedDigest flag for a tree. + void markedCachedDigest() { + assert(!hasCachedDigest() && "NoCachedDigest flag already removed."); + IsDigestCached = true; + } + + /// setHeight - Changes the height of the tree. Used internally by + /// ImutAVLFactory. + void setHeight(unsigned h) { + assert(isMutable() && "Only a mutable tree can have its height changed."); + height = h; + } + + static uint32_t computeDigest(ImutAVLTree *L, ImutAVLTree *R, + value_type_ref V) { + uint32_t digest = 0; + + if (L) + digest += L->computeDigest(); + + // Compute digest of stored data. + FoldingSetNodeID ID; + ImutInfo::Profile(ID,V); + digest += ID.ComputeHash(); + + if (R) + digest += R->computeDigest(); + + return digest; + } + + uint32_t computeDigest() { + // Check the lowest bit to determine if digest has actually been + // pre-computed. + if (hasCachedDigest()) + return digest; + + uint32_t X = computeDigest(getLeft(), getRight(), getValue()); + digest = X; + markedCachedDigest(); + return X; + } + + //===----------------------------------------------------===// + // Reference count operations. + //===----------------------------------------------------===// + +public: + void retain() { ++refCount; } + + void release() { + assert(refCount > 0); + if (--refCount == 0) + destroy(); + } + + void destroy() { + if (left) + left->release(); + if (right) + right->release(); + if (IsCanonicalized) { + if (next) + next->prev = prev; + + if (prev) + prev->next = next; + else + factory->Cache[factory->maskCacheIndex(computeDigest())] = next; + } + + // We need to clear the mutability bit in case we are + // destroying the node as part of a sweep in ImutAVLFactory::recoverNodes(). + IsMutable = false; + factory->freeNodes.push_back(this); + } +}; + +//===----------------------------------------------------------------------===// +// Immutable AVL-Tree Factory class. +//===----------------------------------------------------------------------===// + +template <typename ImutInfo > +class ImutAVLFactory { + friend class ImutAVLTree<ImutInfo>; + + using TreeTy = ImutAVLTree<ImutInfo>; + using value_type_ref = typename TreeTy::value_type_ref; + using key_type_ref = typename TreeTy::key_type_ref; + using CacheTy = DenseMap<unsigned, TreeTy*>; + + CacheTy Cache; + uintptr_t Allocator; + std::vector<TreeTy*> createdNodes; + std::vector<TreeTy*> freeNodes; + + bool ownsAllocator() const { + return (Allocator & 0x1) == 0; + } + + BumpPtrAllocator& getAllocator() const { + return *reinterpret_cast<BumpPtrAllocator*>(Allocator & ~0x1); + } + + //===--------------------------------------------------===// + // Public interface. + //===--------------------------------------------------===// + +public: + ImutAVLFactory() + : Allocator(reinterpret_cast<uintptr_t>(new BumpPtrAllocator())) {} + + ImutAVLFactory(BumpPtrAllocator& Alloc) + : Allocator(reinterpret_cast<uintptr_t>(&Alloc) | 0x1) {} + + ~ImutAVLFactory() { + if (ownsAllocator()) delete &getAllocator(); + } + + TreeTy* add(TreeTy* T, value_type_ref V) { + T = add_internal(V,T); + markImmutable(T); + recoverNodes(); + return T; + } + + TreeTy* remove(TreeTy* T, key_type_ref V) { + T = remove_internal(V,T); + markImmutable(T); + recoverNodes(); + return T; + } + + TreeTy* getEmptyTree() const { return nullptr; } + +protected: + //===--------------------------------------------------===// + // A bunch of quick helper functions used for reasoning + // about the properties of trees and their children. + // These have succinct names so that the balancing code + // is as terse (and readable) as possible. + //===--------------------------------------------------===// + + bool isEmpty(TreeTy* T) const { return !T; } + unsigned getHeight(TreeTy* T) const { return T ? T->getHeight() : 0; } + TreeTy* getLeft(TreeTy* T) const { return T->getLeft(); } + TreeTy* getRight(TreeTy* T) const { return T->getRight(); } + value_type_ref getValue(TreeTy* T) const { return T->value; } + + // Make sure the index is not the Tombstone or Entry key of the DenseMap. + static unsigned maskCacheIndex(unsigned I) { return (I & ~0x02); } + + unsigned incrementHeight(TreeTy* L, TreeTy* R) const { + unsigned hl = getHeight(L); + unsigned hr = getHeight(R); + return (hl > hr ? hl : hr) + 1; + } + + static bool compareTreeWithSection(TreeTy* T, + typename TreeTy::iterator& TI, + typename TreeTy::iterator& TE) { + typename TreeTy::iterator I = T->begin(), E = T->end(); + for ( ; I!=E ; ++I, ++TI) { + if (TI == TE || !I->isElementEqual(&*TI)) + return false; + } + return true; + } + + //===--------------------------------------------------===// + // "createNode" is used to generate new tree roots that link + // to other trees. The functon may also simply move links + // in an existing root if that root is still marked mutable. + // This is necessary because otherwise our balancing code + // would leak memory as it would create nodes that are + // then discarded later before the finished tree is + // returned to the caller. + //===--------------------------------------------------===// + + TreeTy* createNode(TreeTy* L, value_type_ref V, TreeTy* R) { + BumpPtrAllocator& A = getAllocator(); + TreeTy* T; + if (!freeNodes.empty()) { + T = freeNodes.back(); + freeNodes.pop_back(); + assert(T != L); + assert(T != R); + } else { + T = (TreeTy*) A.Allocate<TreeTy>(); + } + new (T) TreeTy(this, L, R, V, incrementHeight(L,R)); + createdNodes.push_back(T); + return T; + } + + TreeTy* createNode(TreeTy* newLeft, TreeTy* oldTree, TreeTy* newRight) { + return createNode(newLeft, getValue(oldTree), newRight); + } + + void recoverNodes() { + for (unsigned i = 0, n = createdNodes.size(); i < n; ++i) { + TreeTy *N = createdNodes[i]; + if (N->isMutable() && N->refCount == 0) + N->destroy(); + } + createdNodes.clear(); + } + + /// balanceTree - Used by add_internal and remove_internal to + /// balance a newly created tree. + TreeTy* balanceTree(TreeTy* L, value_type_ref V, TreeTy* R) { + unsigned hl = getHeight(L); + unsigned hr = getHeight(R); + + if (hl > hr + 2) { + assert(!isEmpty(L) && "Left tree cannot be empty to have a height >= 2"); + + TreeTy *LL = getLeft(L); + TreeTy *LR = getRight(L); + + if (getHeight(LL) >= getHeight(LR)) + return createNode(LL, L, createNode(LR,V,R)); + + assert(!isEmpty(LR) && "LR cannot be empty because it has a height >= 1"); + + TreeTy *LRL = getLeft(LR); + TreeTy *LRR = getRight(LR); + + return createNode(createNode(LL,L,LRL), LR, createNode(LRR,V,R)); + } + + if (hr > hl + 2) { + assert(!isEmpty(R) && "Right tree cannot be empty to have a height >= 2"); + + TreeTy *RL = getLeft(R); + TreeTy *RR = getRight(R); + + if (getHeight(RR) >= getHeight(RL)) + return createNode(createNode(L,V,RL), R, RR); + + assert(!isEmpty(RL) && "RL cannot be empty because it has a height >= 1"); + + TreeTy *RLL = getLeft(RL); + TreeTy *RLR = getRight(RL); + + return createNode(createNode(L,V,RLL), RL, createNode(RLR,R,RR)); + } + + return createNode(L,V,R); + } + + /// add_internal - Creates a new tree that includes the specified + /// data and the data from the original tree. If the original tree + /// already contained the data item, the original tree is returned. + TreeTy* add_internal(value_type_ref V, TreeTy* T) { + if (isEmpty(T)) + return createNode(T, V, T); + assert(!T->isMutable()); + + key_type_ref K = ImutInfo::KeyOfValue(V); + key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T)); + + if (ImutInfo::isEqual(K,KCurrent)) + return createNode(getLeft(T), V, getRight(T)); + else if (ImutInfo::isLess(K,KCurrent)) + return balanceTree(add_internal(V, getLeft(T)), getValue(T), getRight(T)); + else + return balanceTree(getLeft(T), getValue(T), add_internal(V, getRight(T))); + } + + /// remove_internal - Creates a new tree that includes all the data + /// from the original tree except the specified data. If the + /// specified data did not exist in the original tree, the original + /// tree is returned. + TreeTy* remove_internal(key_type_ref K, TreeTy* T) { + if (isEmpty(T)) + return T; + + assert(!T->isMutable()); + + key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T)); + + if (ImutInfo::isEqual(K,KCurrent)) { + return combineTrees(getLeft(T), getRight(T)); + } else if (ImutInfo::isLess(K,KCurrent)) { + return balanceTree(remove_internal(K, getLeft(T)), + getValue(T), getRight(T)); + } else { + return balanceTree(getLeft(T), getValue(T), + remove_internal(K, getRight(T))); + } + } + + TreeTy* combineTrees(TreeTy* L, TreeTy* R) { + if (isEmpty(L)) + return R; + if (isEmpty(R)) + return L; + TreeTy* OldNode; + TreeTy* newRight = removeMinBinding(R,OldNode); + return balanceTree(L, getValue(OldNode), newRight); + } + + TreeTy* removeMinBinding(TreeTy* T, TreeTy*& Noderemoved) { + assert(!isEmpty(T)); + if (isEmpty(getLeft(T))) { + Noderemoved = T; + return getRight(T); + } + return balanceTree(removeMinBinding(getLeft(T), Noderemoved), + getValue(T), getRight(T)); + } + + /// markImmutable - Clears the mutable bits of a root and all of its + /// descendants. + void markImmutable(TreeTy* T) { + if (!T || !T->isMutable()) + return; + T->markImmutable(); + markImmutable(getLeft(T)); + markImmutable(getRight(T)); + } + +public: + TreeTy *getCanonicalTree(TreeTy *TNew) { + if (!TNew) + return nullptr; + + if (TNew->IsCanonicalized) + return TNew; + + // Search the hashtable for another tree with the same digest, and + // if find a collision compare those trees by their contents. + unsigned digest = TNew->computeDigest(); + TreeTy *&entry = Cache[maskCacheIndex(digest)]; + do { + if (!entry) + break; + for (TreeTy *T = entry ; T != nullptr; T = T->next) { + // Compare the Contents('T') with Contents('TNew') + typename TreeTy::iterator TI = T->begin(), TE = T->end(); + if (!compareTreeWithSection(TNew, TI, TE)) + continue; + if (TI != TE) + continue; // T has more contents than TNew. + // Trees did match! Return 'T'. + if (TNew->refCount == 0) + TNew->destroy(); + return T; + } + entry->prev = TNew; + TNew->next = entry; + } + while (false); + + entry = TNew; + TNew->IsCanonicalized = true; + return TNew; + } +}; + +//===----------------------------------------------------------------------===// +// Immutable AVL-Tree Iterators. +//===----------------------------------------------------------------------===// + +template <typename ImutInfo> +class ImutAVLTreeGenericIterator + : public std::iterator<std::bidirectional_iterator_tag, + ImutAVLTree<ImutInfo>> { + SmallVector<uintptr_t,20> stack; + +public: + enum VisitFlag { VisitedNone=0x0, VisitedLeft=0x1, VisitedRight=0x3, + Flags=0x3 }; + + using TreeTy = ImutAVLTree<ImutInfo>; + + ImutAVLTreeGenericIterator() = default; + ImutAVLTreeGenericIterator(const TreeTy *Root) { + if (Root) stack.push_back(reinterpret_cast<uintptr_t>(Root)); + } + + TreeTy &operator*() const { + assert(!stack.empty()); + return *reinterpret_cast<TreeTy *>(stack.back() & ~Flags); + } + TreeTy *operator->() const { return &*this; } + + uintptr_t getVisitState() const { + assert(!stack.empty()); + return stack.back() & Flags; + } + + bool atEnd() const { return stack.empty(); } + + bool atBeginning() const { + return stack.size() == 1 && getVisitState() == VisitedNone; + } + + void skipToParent() { + assert(!stack.empty()); + stack.pop_back(); + if (stack.empty()) + return; + switch (getVisitState()) { + case VisitedNone: + stack.back() |= VisitedLeft; + break; + case VisitedLeft: + stack.back() |= VisitedRight; + break; + default: + llvm_unreachable("Unreachable."); + } + } + + bool operator==(const ImutAVLTreeGenericIterator &x) const { + return stack == x.stack; + } + + bool operator!=(const ImutAVLTreeGenericIterator &x) const { + return !(*this == x); + } + + ImutAVLTreeGenericIterator &operator++() { + assert(!stack.empty()); + TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags); + assert(Current); + switch (getVisitState()) { + case VisitedNone: + if (TreeTy* L = Current->getLeft()) + stack.push_back(reinterpret_cast<uintptr_t>(L)); + else + stack.back() |= VisitedLeft; + break; + case VisitedLeft: + if (TreeTy* R = Current->getRight()) + stack.push_back(reinterpret_cast<uintptr_t>(R)); + else + stack.back() |= VisitedRight; + break; + case VisitedRight: + skipToParent(); + break; + default: + llvm_unreachable("Unreachable."); + } + return *this; + } + + ImutAVLTreeGenericIterator &operator--() { + assert(!stack.empty()); + TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags); + assert(Current); + switch (getVisitState()) { + case VisitedNone: + stack.pop_back(); + break; + case VisitedLeft: + stack.back() &= ~Flags; // Set state to "VisitedNone." + if (TreeTy* L = Current->getLeft()) + stack.push_back(reinterpret_cast<uintptr_t>(L) | VisitedRight); + break; + case VisitedRight: + stack.back() &= ~Flags; + stack.back() |= VisitedLeft; + if (TreeTy* R = Current->getRight()) + stack.push_back(reinterpret_cast<uintptr_t>(R) | VisitedRight); + break; + default: + llvm_unreachable("Unreachable."); + } + return *this; + } +}; + +template <typename ImutInfo> +class ImutAVLTreeInOrderIterator + : public std::iterator<std::bidirectional_iterator_tag, + ImutAVLTree<ImutInfo>> { + using InternalIteratorTy = ImutAVLTreeGenericIterator<ImutInfo>; + + InternalIteratorTy InternalItr; + +public: + using TreeTy = ImutAVLTree<ImutInfo>; + + ImutAVLTreeInOrderIterator(const TreeTy* Root) : InternalItr(Root) { + if (Root) + ++*this; // Advance to first element. + } + + ImutAVLTreeInOrderIterator() : InternalItr() {} + + bool operator==(const ImutAVLTreeInOrderIterator &x) const { + return InternalItr == x.InternalItr; + } + + bool operator!=(const ImutAVLTreeInOrderIterator &x) const { + return !(*this == x); + } + + TreeTy &operator*() const { return *InternalItr; } + TreeTy *operator->() const { return &*InternalItr; } + + ImutAVLTreeInOrderIterator &operator++() { + do ++InternalItr; + while (!InternalItr.atEnd() && + InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft); + + return *this; + } + + ImutAVLTreeInOrderIterator &operator--() { + do --InternalItr; + while (!InternalItr.atBeginning() && + InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft); + + return *this; + } + + void skipSubTree() { + InternalItr.skipToParent(); + + while (!InternalItr.atEnd() && + InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft) + ++InternalItr; + } +}; + +/// Generic iterator that wraps a T::TreeTy::iterator and exposes +/// iterator::getValue() on dereference. +template <typename T> +struct ImutAVLValueIterator + : iterator_adaptor_base< + ImutAVLValueIterator<T>, typename T::TreeTy::iterator, + typename std::iterator_traits< + typename T::TreeTy::iterator>::iterator_category, + const typename T::value_type> { + ImutAVLValueIterator() = default; + explicit ImutAVLValueIterator(typename T::TreeTy *Tree) + : ImutAVLValueIterator::iterator_adaptor_base(Tree) {} + + typename ImutAVLValueIterator::reference operator*() const { + return this->I->getValue(); + } +}; + +//===----------------------------------------------------------------------===// +// Trait classes for Profile information. +//===----------------------------------------------------------------------===// + +/// Generic profile template. The default behavior is to invoke the +/// profile method of an object. Specializations for primitive integers +/// and generic handling of pointers is done below. +template <typename T> +struct ImutProfileInfo { + using value_type = const T; + using value_type_ref = const T&; + + static void Profile(FoldingSetNodeID &ID, value_type_ref X) { + FoldingSetTrait<T>::Profile(X,ID); + } +}; + +/// Profile traits for integers. +template <typename T> +struct ImutProfileInteger { + using value_type = const T; + using value_type_ref = const T&; + + static void Profile(FoldingSetNodeID &ID, value_type_ref X) { + ID.AddInteger(X); + } +}; + +#define PROFILE_INTEGER_INFO(X)\ +template<> struct ImutProfileInfo<X> : ImutProfileInteger<X> {}; + +PROFILE_INTEGER_INFO(char) +PROFILE_INTEGER_INFO(unsigned char) +PROFILE_INTEGER_INFO(short) +PROFILE_INTEGER_INFO(unsigned short) +PROFILE_INTEGER_INFO(unsigned) +PROFILE_INTEGER_INFO(signed) +PROFILE_INTEGER_INFO(long) +PROFILE_INTEGER_INFO(unsigned long) +PROFILE_INTEGER_INFO(long long) +PROFILE_INTEGER_INFO(unsigned long long) + +#undef PROFILE_INTEGER_INFO + +/// Profile traits for booleans. +template <> +struct ImutProfileInfo<bool> { + using value_type = const bool; + using value_type_ref = const bool&; + + static void Profile(FoldingSetNodeID &ID, value_type_ref X) { + ID.AddBoolean(X); + } +}; + +/// Generic profile trait for pointer types. We treat pointers as +/// references to unique objects. +template <typename T> +struct ImutProfileInfo<T*> { + using value_type = const T*; + using value_type_ref = value_type; + + static void Profile(FoldingSetNodeID &ID, value_type_ref X) { + ID.AddPointer(X); + } +}; + +//===----------------------------------------------------------------------===// +// Trait classes that contain element comparison operators and type +// definitions used by ImutAVLTree, ImmutableSet, and ImmutableMap. These +// inherit from the profile traits (ImutProfileInfo) to include operations +// for element profiling. +//===----------------------------------------------------------------------===// + +/// ImutContainerInfo - Generic definition of comparison operations for +/// elements of immutable containers that defaults to using +/// std::equal_to<> and std::less<> to perform comparison of elements. +template <typename T> +struct ImutContainerInfo : public ImutProfileInfo<T> { + using value_type = typename ImutProfileInfo<T>::value_type; + using value_type_ref = typename ImutProfileInfo<T>::value_type_ref; + using key_type = value_type; + using key_type_ref = value_type_ref; + using data_type = bool; + using data_type_ref = bool; + + static key_type_ref KeyOfValue(value_type_ref D) { return D; } + static data_type_ref DataOfValue(value_type_ref) { return true; } + + static bool isEqual(key_type_ref LHS, key_type_ref RHS) { + return std::equal_to<key_type>()(LHS,RHS); + } + + static bool isLess(key_type_ref LHS, key_type_ref RHS) { + return std::less<key_type>()(LHS,RHS); + } + + static bool isDataEqual(data_type_ref, data_type_ref) { return true; } +}; + +/// ImutContainerInfo - Specialization for pointer values to treat pointers +/// as references to unique objects. Pointers are thus compared by +/// their addresses. +template <typename T> +struct ImutContainerInfo<T*> : public ImutProfileInfo<T*> { + using value_type = typename ImutProfileInfo<T*>::value_type; + using value_type_ref = typename ImutProfileInfo<T*>::value_type_ref; + using key_type = value_type; + using key_type_ref = value_type_ref; + using data_type = bool; + using data_type_ref = bool; + + static key_type_ref KeyOfValue(value_type_ref D) { return D; } + static data_type_ref DataOfValue(value_type_ref) { return true; } + + static bool isEqual(key_type_ref LHS, key_type_ref RHS) { return LHS == RHS; } + + static bool isLess(key_type_ref LHS, key_type_ref RHS) { return LHS < RHS; } + + static bool isDataEqual(data_type_ref, data_type_ref) { return true; } +}; + +//===----------------------------------------------------------------------===// +// Immutable Set +//===----------------------------------------------------------------------===// + +template <typename ValT, typename ValInfo = ImutContainerInfo<ValT>> +class ImmutableSet { +public: + using value_type = typename ValInfo::value_type; + using value_type_ref = typename ValInfo::value_type_ref; + using TreeTy = ImutAVLTree<ValInfo>; + +private: + TreeTy *Root; + +public: + /// Constructs a set from a pointer to a tree root. In general one + /// should use a Factory object to create sets instead of directly + /// invoking the constructor, but there are cases where make this + /// constructor public is useful. + explicit ImmutableSet(TreeTy* R) : Root(R) { + if (Root) { Root->retain(); } + } + + ImmutableSet(const ImmutableSet &X) : Root(X.Root) { + if (Root) { Root->retain(); } + } + + ~ImmutableSet() { + if (Root) { Root->release(); } + } + + ImmutableSet &operator=(const ImmutableSet &X) { + if (Root != X.Root) { + if (X.Root) { X.Root->retain(); } + if (Root) { Root->release(); } + Root = X.Root; + } + return *this; + } + + class Factory { + typename TreeTy::Factory F; + const bool Canonicalize; + + public: + Factory(bool canonicalize = true) + : Canonicalize(canonicalize) {} + + Factory(BumpPtrAllocator& Alloc, bool canonicalize = true) + : F(Alloc), Canonicalize(canonicalize) {} + + Factory(const Factory& RHS) = delete; + void operator=(const Factory& RHS) = delete; + + /// getEmptySet - Returns an immutable set that contains no elements. + ImmutableSet getEmptySet() { + return ImmutableSet(F.getEmptyTree()); + } + + /// add - Creates a new immutable set that contains all of the values + /// of the original set with the addition of the specified value. If + /// the original set already included the value, then the original set is + /// returned and no memory is allocated. The time and space complexity + /// of this operation is logarithmic in the size of the original set. + /// The memory allocated to represent the set is released when the + /// factory object that created the set is destroyed. + LLVM_NODISCARD ImmutableSet add(ImmutableSet Old, value_type_ref V) { + TreeTy *NewT = F.add(Old.Root, V); + return ImmutableSet(Canonicalize ? F.getCanonicalTree(NewT) : NewT); + } + + /// remove - Creates a new immutable set that contains all of the values + /// of the original set with the exception of the specified value. If + /// the original set did not contain the value, the original set is + /// returned and no memory is allocated. The time and space complexity + /// of this operation is logarithmic in the size of the original set. + /// The memory allocated to represent the set is released when the + /// factory object that created the set is destroyed. + LLVM_NODISCARD ImmutableSet remove(ImmutableSet Old, value_type_ref V) { + TreeTy *NewT = F.remove(Old.Root, V); + return ImmutableSet(Canonicalize ? F.getCanonicalTree(NewT) : NewT); + } + + BumpPtrAllocator& getAllocator() { return F.getAllocator(); } + + typename TreeTy::Factory *getTreeFactory() const { + return const_cast<typename TreeTy::Factory *>(&F); + } + }; + + friend class Factory; + + /// Returns true if the set contains the specified value. + bool contains(value_type_ref V) const { + return Root ? Root->contains(V) : false; + } + + bool operator==(const ImmutableSet &RHS) const { + return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root; + } + + bool operator!=(const ImmutableSet &RHS) const { + return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root; + } + + TreeTy *getRoot() { + if (Root) { Root->retain(); } + return Root; + } + + TreeTy *getRootWithoutRetain() const { + return Root; + } + + /// isEmpty - Return true if the set contains no elements. + bool isEmpty() const { return !Root; } + + /// isSingleton - Return true if the set contains exactly one element. + /// This method runs in constant time. + bool isSingleton() const { return getHeight() == 1; } + + template <typename Callback> + void foreach(Callback& C) { if (Root) Root->foreach(C); } + + template <typename Callback> + void foreach() { if (Root) { Callback C; Root->foreach(C); } } + + //===--------------------------------------------------===// + // Iterators. + //===--------------------------------------------------===// + + using iterator = ImutAVLValueIterator<ImmutableSet>; + + iterator begin() const { return iterator(Root); } + iterator end() const { return iterator(); } + + //===--------------------------------------------------===// + // Utility methods. + //===--------------------------------------------------===// + + unsigned getHeight() const { return Root ? Root->getHeight() : 0; } + + static void Profile(FoldingSetNodeID &ID, const ImmutableSet &S) { + ID.AddPointer(S.Root); + } + + void Profile(FoldingSetNodeID &ID) const { return Profile(ID, *this); } + + //===--------------------------------------------------===// + // For testing. + //===--------------------------------------------------===// + + void validateTree() const { if (Root) Root->validateTree(); } +}; + +// NOTE: This may some day replace the current ImmutableSet. +template <typename ValT, typename ValInfo = ImutContainerInfo<ValT>> +class ImmutableSetRef { +public: + using value_type = typename ValInfo::value_type; + using value_type_ref = typename ValInfo::value_type_ref; + using TreeTy = ImutAVLTree<ValInfo>; + using FactoryTy = typename TreeTy::Factory; + +private: + TreeTy *Root; + FactoryTy *Factory; + +public: + /// Constructs a set from a pointer to a tree root. In general one + /// should use a Factory object to create sets instead of directly + /// invoking the constructor, but there are cases where make this + /// constructor public is useful. + explicit ImmutableSetRef(TreeTy* R, FactoryTy *F) + : Root(R), + Factory(F) { + if (Root) { Root->retain(); } + } + + ImmutableSetRef(const ImmutableSetRef &X) + : Root(X.Root), + Factory(X.Factory) { + if (Root) { Root->retain(); } + } + + ~ImmutableSetRef() { + if (Root) { Root->release(); } + } + + ImmutableSetRef &operator=(const ImmutableSetRef &X) { + if (Root != X.Root) { + if (X.Root) { X.Root->retain(); } + if (Root) { Root->release(); } + Root = X.Root; + Factory = X.Factory; + } + return *this; + } + + static ImmutableSetRef getEmptySet(FactoryTy *F) { + return ImmutableSetRef(0, F); + } + + ImmutableSetRef add(value_type_ref V) { + return ImmutableSetRef(Factory->add(Root, V), Factory); + } + + ImmutableSetRef remove(value_type_ref V) { + return ImmutableSetRef(Factory->remove(Root, V), Factory); + } + + /// Returns true if the set contains the specified value. + bool contains(value_type_ref V) const { + return Root ? Root->contains(V) : false; + } + + ImmutableSet<ValT> asImmutableSet(bool canonicalize = true) const { + return ImmutableSet<ValT>(canonicalize ? + Factory->getCanonicalTree(Root) : Root); + } + + TreeTy *getRootWithoutRetain() const { + return Root; + } + + bool operator==(const ImmutableSetRef &RHS) const { + return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root; + } + + bool operator!=(const ImmutableSetRef &RHS) const { + return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root; + } + + /// isEmpty - Return true if the set contains no elements. + bool isEmpty() const { return !Root; } + + /// isSingleton - Return true if the set contains exactly one element. + /// This method runs in constant time. + bool isSingleton() const { return getHeight() == 1; } + + //===--------------------------------------------------===// + // Iterators. + //===--------------------------------------------------===// + + using iterator = ImutAVLValueIterator<ImmutableSetRef>; + + iterator begin() const { return iterator(Root); } + iterator end() const { return iterator(); } + + //===--------------------------------------------------===// + // Utility methods. + //===--------------------------------------------------===// + + unsigned getHeight() const { return Root ? Root->getHeight() : 0; } + + static void Profile(FoldingSetNodeID &ID, const ImmutableSetRef &S) { + ID.AddPointer(S.Root); + } + + void Profile(FoldingSetNodeID &ID) const { return Profile(ID, *this); } + + //===--------------------------------------------------===// + // For testing. + //===--------------------------------------------------===// + + void validateTree() const { if (Root) Root->validateTree(); } +}; + +} // end namespace llvm + +#endif // LLVM_ADT_IMMUTABLESET_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/IndexedMap.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/IndexedMap.h new file mode 100644 index 0000000..b44f16b --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/IndexedMap.h
@@ -0,0 +1,84 @@ +//===- llvm/ADT/IndexedMap.h - An index map implementation ------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements an indexed map. The index map template takes two +// types. The first is the mapped type and the second is a functor +// that maps its argument to a size_t. On instantiation a "null" value +// can be provided to be used as a "does not exist" indicator in the +// map. A member function grow() is provided that given the value of +// the maximally indexed key (the argument of the functor) makes sure +// the map has enough space for it. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_INDEXEDMAP_H +#define LLVM_ADT_INDEXEDMAP_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" +#include <cassert> + +namespace llvm { + +template <typename T, typename ToIndexT = identity<unsigned>> + class IndexedMap { + using IndexT = typename ToIndexT::argument_type; + // Prefer SmallVector with zero inline storage over std::vector. IndexedMaps + // can grow very large and SmallVector grows more efficiently as long as T + // is trivially copyable. + using StorageT = SmallVector<T, 0>; + + StorageT storage_; + T nullVal_; + ToIndexT toIndex_; + + public: + IndexedMap() : nullVal_(T()) {} + + explicit IndexedMap(const T& val) : nullVal_(val) {} + + typename StorageT::reference operator[](IndexT n) { + assert(toIndex_(n) < storage_.size() && "index out of bounds!"); + return storage_[toIndex_(n)]; + } + + typename StorageT::const_reference operator[](IndexT n) const { + assert(toIndex_(n) < storage_.size() && "index out of bounds!"); + return storage_[toIndex_(n)]; + } + + void reserve(typename StorageT::size_type s) { + storage_.reserve(s); + } + + void resize(typename StorageT::size_type s) { + storage_.resize(s, nullVal_); + } + + void clear() { + storage_.clear(); + } + + void grow(IndexT n) { + unsigned NewSize = toIndex_(n) + 1; + if (NewSize > storage_.size()) + resize(NewSize); + } + + bool inBounds(IndexT n) const { + return toIndex_(n) < storage_.size(); + } + + typename StorageT::size_type size() const { + return storage_.size(); + } + }; + +} // end namespace llvm + +#endif // LLVM_ADT_INDEXEDMAP_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/IntEqClasses.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/IntEqClasses.h new file mode 100644 index 0000000..08f46a3 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/IntEqClasses.h
@@ -0,0 +1,87 @@ +//===-- llvm/ADT/IntEqClasses.h - Equiv. Classes of Integers ----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Equivalence classes for small integers. This is a mapping of the integers +// 0 .. N-1 into M equivalence classes numbered 0 .. M-1. +// +// Initially each integer has its own equivalence class. Classes are joined by +// passing a representative member of each class to join(). +// +// Once the classes are built, compress() will number them 0 .. M-1 and prevent +// further changes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_INTEQCLASSES_H +#define LLVM_ADT_INTEQCLASSES_H + +#include "llvm/ADT/SmallVector.h" + +namespace llvm { + +class IntEqClasses { + /// EC - When uncompressed, map each integer to a smaller member of its + /// equivalence class. The class leader is the smallest member and maps to + /// itself. + /// + /// When compressed, EC[i] is the equivalence class of i. + SmallVector<unsigned, 8> EC; + + /// NumClasses - The number of equivalence classes when compressed, or 0 when + /// uncompressed. + unsigned NumClasses; + +public: + /// IntEqClasses - Create an equivalence class mapping for 0 .. N-1. + IntEqClasses(unsigned N = 0) : NumClasses(0) { grow(N); } + + /// grow - Increase capacity to hold 0 .. N-1, putting new integers in unique + /// equivalence classes. + /// This requires an uncompressed map. + void grow(unsigned N); + + /// clear - Clear all classes so that grow() will assign a unique class to + /// every integer. + void clear() { + EC.clear(); + NumClasses = 0; + } + + /// Join the equivalence classes of a and b. After joining classes, + /// findLeader(a) == findLeader(b). This requires an uncompressed map. + /// Returns the new leader. + unsigned join(unsigned a, unsigned b); + + /// findLeader - Compute the leader of a's equivalence class. This is the + /// smallest member of the class. + /// This requires an uncompressed map. + unsigned findLeader(unsigned a) const; + + /// compress - Compress equivalence classes by numbering them 0 .. M. + /// This makes the equivalence class map immutable. + void compress(); + + /// getNumClasses - Return the number of equivalence classes after compress() + /// was called. + unsigned getNumClasses() const { return NumClasses; } + + /// operator[] - Return a's equivalence class number, 0 .. getNumClasses()-1. + /// This requires a compressed map. + unsigned operator[](unsigned a) const { + assert(NumClasses && "operator[] called before compress()"); + return EC[a]; + } + + /// uncompress - Change back to the uncompressed representation that allows + /// editing. + void uncompress(); +}; + +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/IntervalMap.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/IntervalMap.h new file mode 100644 index 0000000..a02876e --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/IntervalMap.h
@@ -0,0 +1,2167 @@ +//===- llvm/ADT/IntervalMap.h - A sorted interval map -----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements a coalescing interval map for small objects. +// +// KeyT objects are mapped to ValT objects. Intervals of keys that map to the +// same value are represented in a compressed form. +// +// Iterators provide ordered access to the compressed intervals rather than the +// individual keys, and insert and erase operations use key intervals as well. +// +// Like SmallVector, IntervalMap will store the first N intervals in the map +// object itself without any allocations. When space is exhausted it switches to +// a B+-tree representation with very small overhead for small key and value +// objects. +// +// A Traits class specifies how keys are compared. It also allows IntervalMap to +// work with both closed and half-open intervals. +// +// Keys and values are not stored next to each other in a std::pair, so we don't +// provide such a value_type. Dereferencing iterators only returns the mapped +// value. The interval bounds are accessible through the start() and stop() +// iterator methods. +// +// IntervalMap is optimized for small key and value objects, 4 or 8 bytes each +// is the optimal size. For large objects use std::map instead. +// +//===----------------------------------------------------------------------===// +// +// Synopsis: +// +// template <typename KeyT, typename ValT, unsigned N, typename Traits> +// class IntervalMap { +// public: +// typedef KeyT key_type; +// typedef ValT mapped_type; +// typedef RecyclingAllocator<...> Allocator; +// class iterator; +// class const_iterator; +// +// explicit IntervalMap(Allocator&); +// ~IntervalMap(): +// +// bool empty() const; +// KeyT start() const; +// KeyT stop() const; +// ValT lookup(KeyT x, Value NotFound = Value()) const; +// +// const_iterator begin() const; +// const_iterator end() const; +// iterator begin(); +// iterator end(); +// const_iterator find(KeyT x) const; +// iterator find(KeyT x); +// +// void insert(KeyT a, KeyT b, ValT y); +// void clear(); +// }; +// +// template <typename KeyT, typename ValT, unsigned N, typename Traits> +// class IntervalMap::const_iterator : +// public std::iterator<std::bidirectional_iterator_tag, ValT> { +// public: +// bool operator==(const const_iterator &) const; +// bool operator!=(const const_iterator &) const; +// bool valid() const; +// +// const KeyT &start() const; +// const KeyT &stop() const; +// const ValT &value() const; +// const ValT &operator*() const; +// const ValT *operator->() const; +// +// const_iterator &operator++(); +// const_iterator &operator++(int); +// const_iterator &operator--(); +// const_iterator &operator--(int); +// void goToBegin(); +// void goToEnd(); +// void find(KeyT x); +// void advanceTo(KeyT x); +// }; +// +// template <typename KeyT, typename ValT, unsigned N, typename Traits> +// class IntervalMap::iterator : public const_iterator { +// public: +// void insert(KeyT a, KeyT b, Value y); +// void erase(); +// }; +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_INTERVALMAP_H +#define LLVM_ADT_INTERVALMAP_H + +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/bit.h" +#include "llvm/Support/AlignOf.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/RecyclingAllocator.h" +#include <algorithm> +#include <cassert> +#include <cstdint> +#include <iterator> +#include <new> +#include <utility> + +namespace llvm { + +//===----------------------------------------------------------------------===// +//--- Key traits ---// +//===----------------------------------------------------------------------===// +// +// The IntervalMap works with closed or half-open intervals. +// Adjacent intervals that map to the same value are coalesced. +// +// The IntervalMapInfo traits class is used to determine if a key is contained +// in an interval, and if two intervals are adjacent so they can be coalesced. +// The provided implementation works for closed integer intervals, other keys +// probably need a specialized version. +// +// The point x is contained in [a;b] when !startLess(x, a) && !stopLess(b, x). +// +// It is assumed that (a;b] half-open intervals are not used, only [a;b) is +// allowed. This is so that stopLess(a, b) can be used to determine if two +// intervals overlap. +// +//===----------------------------------------------------------------------===// + +template <typename T> +struct IntervalMapInfo { + /// startLess - Return true if x is not in [a;b]. + /// This is x < a both for closed intervals and for [a;b) half-open intervals. + static inline bool startLess(const T &x, const T &a) { + return x < a; + } + + /// stopLess - Return true if x is not in [a;b]. + /// This is b < x for a closed interval, b <= x for [a;b) half-open intervals. + static inline bool stopLess(const T &b, const T &x) { + return b < x; + } + + /// adjacent - Return true when the intervals [x;a] and [b;y] can coalesce. + /// This is a+1 == b for closed intervals, a == b for half-open intervals. + static inline bool adjacent(const T &a, const T &b) { + return a+1 == b; + } + + /// nonEmpty - Return true if [a;b] is non-empty. + /// This is a <= b for a closed interval, a < b for [a;b) half-open intervals. + static inline bool nonEmpty(const T &a, const T &b) { + return a <= b; + } +}; + +template <typename T> +struct IntervalMapHalfOpenInfo { + /// startLess - Return true if x is not in [a;b). + static inline bool startLess(const T &x, const T &a) { + return x < a; + } + + /// stopLess - Return true if x is not in [a;b). + static inline bool stopLess(const T &b, const T &x) { + return b <= x; + } + + /// adjacent - Return true when the intervals [x;a) and [b;y) can coalesce. + static inline bool adjacent(const T &a, const T &b) { + return a == b; + } + + /// nonEmpty - Return true if [a;b) is non-empty. + static inline bool nonEmpty(const T &a, const T &b) { + return a < b; + } +}; + +/// IntervalMapImpl - Namespace used for IntervalMap implementation details. +/// It should be considered private to the implementation. +namespace IntervalMapImpl { + +using IdxPair = std::pair<unsigned,unsigned>; + +//===----------------------------------------------------------------------===// +//--- IntervalMapImpl::NodeBase ---// +//===----------------------------------------------------------------------===// +// +// Both leaf and branch nodes store vectors of pairs. +// Leaves store ((KeyT, KeyT), ValT) pairs, branches use (NodeRef, KeyT). +// +// Keys and values are stored in separate arrays to avoid padding caused by +// different object alignments. This also helps improve locality of reference +// when searching the keys. +// +// The nodes don't know how many elements they contain - that information is +// stored elsewhere. Omitting the size field prevents padding and allows a node +// to fill the allocated cache lines completely. +// +// These are typical key and value sizes, the node branching factor (N), and +// wasted space when nodes are sized to fit in three cache lines (192 bytes): +// +// T1 T2 N Waste Used by +// 4 4 24 0 Branch<4> (32-bit pointers) +// 8 4 16 0 Leaf<4,4>, Branch<4> +// 8 8 12 0 Leaf<4,8>, Branch<8> +// 16 4 9 12 Leaf<8,4> +// 16 8 8 0 Leaf<8,8> +// +//===----------------------------------------------------------------------===// + +template <typename T1, typename T2, unsigned N> +class NodeBase { +public: + enum { Capacity = N }; + + T1 first[N]; + T2 second[N]; + + /// copy - Copy elements from another node. + /// @param Other Node elements are copied from. + /// @param i Beginning of the source range in other. + /// @param j Beginning of the destination range in this. + /// @param Count Number of elements to copy. + template <unsigned M> + void copy(const NodeBase<T1, T2, M> &Other, unsigned i, + unsigned j, unsigned Count) { + assert(i + Count <= M && "Invalid source range"); + assert(j + Count <= N && "Invalid dest range"); + for (unsigned e = i + Count; i != e; ++i, ++j) { + first[j] = Other.first[i]; + second[j] = Other.second[i]; + } + } + + /// moveLeft - Move elements to the left. + /// @param i Beginning of the source range. + /// @param j Beginning of the destination range. + /// @param Count Number of elements to copy. + void moveLeft(unsigned i, unsigned j, unsigned Count) { + assert(j <= i && "Use moveRight shift elements right"); + copy(*this, i, j, Count); + } + + /// moveRight - Move elements to the right. + /// @param i Beginning of the source range. + /// @param j Beginning of the destination range. + /// @param Count Number of elements to copy. + void moveRight(unsigned i, unsigned j, unsigned Count) { + assert(i <= j && "Use moveLeft shift elements left"); + assert(j + Count <= N && "Invalid range"); + while (Count--) { + first[j + Count] = first[i + Count]; + second[j + Count] = second[i + Count]; + } + } + + /// erase - Erase elements [i;j). + /// @param i Beginning of the range to erase. + /// @param j End of the range. (Exclusive). + /// @param Size Number of elements in node. + void erase(unsigned i, unsigned j, unsigned Size) { + moveLeft(j, i, Size - j); + } + + /// erase - Erase element at i. + /// @param i Index of element to erase. + /// @param Size Number of elements in node. + void erase(unsigned i, unsigned Size) { + erase(i, i+1, Size); + } + + /// shift - Shift elements [i;size) 1 position to the right. + /// @param i Beginning of the range to move. + /// @param Size Number of elements in node. + void shift(unsigned i, unsigned Size) { + moveRight(i, i + 1, Size - i); + } + + /// transferToLeftSib - Transfer elements to a left sibling node. + /// @param Size Number of elements in this. + /// @param Sib Left sibling node. + /// @param SSize Number of elements in sib. + /// @param Count Number of elements to transfer. + void transferToLeftSib(unsigned Size, NodeBase &Sib, unsigned SSize, + unsigned Count) { + Sib.copy(*this, 0, SSize, Count); + erase(0, Count, Size); + } + + /// transferToRightSib - Transfer elements to a right sibling node. + /// @param Size Number of elements in this. + /// @param Sib Right sibling node. + /// @param SSize Number of elements in sib. + /// @param Count Number of elements to transfer. + void transferToRightSib(unsigned Size, NodeBase &Sib, unsigned SSize, + unsigned Count) { + Sib.moveRight(0, Count, SSize); + Sib.copy(*this, Size-Count, 0, Count); + } + + /// adjustFromLeftSib - Adjust the number if elements in this node by moving + /// elements to or from a left sibling node. + /// @param Size Number of elements in this. + /// @param Sib Right sibling node. + /// @param SSize Number of elements in sib. + /// @param Add The number of elements to add to this node, possibly < 0. + /// @return Number of elements added to this node, possibly negative. + int adjustFromLeftSib(unsigned Size, NodeBase &Sib, unsigned SSize, int Add) { + if (Add > 0) { + // We want to grow, copy from sib. + unsigned Count = std::min(std::min(unsigned(Add), SSize), N - Size); + Sib.transferToRightSib(SSize, *this, Size, Count); + return Count; + } else { + // We want to shrink, copy to sib. + unsigned Count = std::min(std::min(unsigned(-Add), Size), N - SSize); + transferToLeftSib(Size, Sib, SSize, Count); + return -Count; + } + } +}; + +/// IntervalMapImpl::adjustSiblingSizes - Move elements between sibling nodes. +/// @param Node Array of pointers to sibling nodes. +/// @param Nodes Number of nodes. +/// @param CurSize Array of current node sizes, will be overwritten. +/// @param NewSize Array of desired node sizes. +template <typename NodeT> +void adjustSiblingSizes(NodeT *Node[], unsigned Nodes, + unsigned CurSize[], const unsigned NewSize[]) { + // Move elements right. + for (int n = Nodes - 1; n; --n) { + if (CurSize[n] == NewSize[n]) + continue; + for (int m = n - 1; m != -1; --m) { + int d = Node[n]->adjustFromLeftSib(CurSize[n], *Node[m], CurSize[m], + NewSize[n] - CurSize[n]); + CurSize[m] -= d; + CurSize[n] += d; + // Keep going if the current node was exhausted. + if (CurSize[n] >= NewSize[n]) + break; + } + } + + if (Nodes == 0) + return; + + // Move elements left. + for (unsigned n = 0; n != Nodes - 1; ++n) { + if (CurSize[n] == NewSize[n]) + continue; + for (unsigned m = n + 1; m != Nodes; ++m) { + int d = Node[m]->adjustFromLeftSib(CurSize[m], *Node[n], CurSize[n], + CurSize[n] - NewSize[n]); + CurSize[m] += d; + CurSize[n] -= d; + // Keep going if the current node was exhausted. + if (CurSize[n] >= NewSize[n]) + break; + } + } + +#ifndef NDEBUG + for (unsigned n = 0; n != Nodes; n++) + assert(CurSize[n] == NewSize[n] && "Insufficient element shuffle"); +#endif +} + +/// IntervalMapImpl::distribute - Compute a new distribution of node elements +/// after an overflow or underflow. Reserve space for a new element at Position, +/// and compute the node that will hold Position after redistributing node +/// elements. +/// +/// It is required that +/// +/// Elements == sum(CurSize), and +/// Elements + Grow <= Nodes * Capacity. +/// +/// NewSize[] will be filled in such that: +/// +/// sum(NewSize) == Elements, and +/// NewSize[i] <= Capacity. +/// +/// The returned index is the node where Position will go, so: +/// +/// sum(NewSize[0..idx-1]) <= Position +/// sum(NewSize[0..idx]) >= Position +/// +/// The last equality, sum(NewSize[0..idx]) == Position, can only happen when +/// Grow is set and NewSize[idx] == Capacity-1. The index points to the node +/// before the one holding the Position'th element where there is room for an +/// insertion. +/// +/// @param Nodes The number of nodes. +/// @param Elements Total elements in all nodes. +/// @param Capacity The capacity of each node. +/// @param CurSize Array[Nodes] of current node sizes, or NULL. +/// @param NewSize Array[Nodes] to receive the new node sizes. +/// @param Position Insert position. +/// @param Grow Reserve space for a new element at Position. +/// @return (node, offset) for Position. +IdxPair distribute(unsigned Nodes, unsigned Elements, unsigned Capacity, + const unsigned *CurSize, unsigned NewSize[], + unsigned Position, bool Grow); + +//===----------------------------------------------------------------------===// +//--- IntervalMapImpl::NodeSizer ---// +//===----------------------------------------------------------------------===// +// +// Compute node sizes from key and value types. +// +// The branching factors are chosen to make nodes fit in three cache lines. +// This may not be possible if keys or values are very large. Such large objects +// are handled correctly, but a std::map would probably give better performance. +// +//===----------------------------------------------------------------------===// + +enum { + // Cache line size. Most architectures have 32 or 64 byte cache lines. + // We use 64 bytes here because it provides good branching factors. + Log2CacheLine = 6, + CacheLineBytes = 1 << Log2CacheLine, + DesiredNodeBytes = 3 * CacheLineBytes +}; + +template <typename KeyT, typename ValT> +struct NodeSizer { + enum { + // Compute the leaf node branching factor that makes a node fit in three + // cache lines. The branching factor must be at least 3, or some B+-tree + // balancing algorithms won't work. + // LeafSize can't be larger than CacheLineBytes. This is required by the + // PointerIntPair used by NodeRef. + DesiredLeafSize = DesiredNodeBytes / + static_cast<unsigned>(2*sizeof(KeyT)+sizeof(ValT)), + MinLeafSize = 3, + LeafSize = DesiredLeafSize > MinLeafSize ? DesiredLeafSize : MinLeafSize + }; + + using LeafBase = NodeBase<std::pair<KeyT, KeyT>, ValT, LeafSize>; + + enum { + // Now that we have the leaf branching factor, compute the actual allocation + // unit size by rounding up to a whole number of cache lines. + AllocBytes = (sizeof(LeafBase) + CacheLineBytes-1) & ~(CacheLineBytes-1), + + // Determine the branching factor for branch nodes. + BranchSize = AllocBytes / + static_cast<unsigned>(sizeof(KeyT) + sizeof(void*)) + }; + + /// Allocator - The recycling allocator used for both branch and leaf nodes. + /// This typedef is very likely to be identical for all IntervalMaps with + /// reasonably sized entries, so the same allocator can be shared among + /// different kinds of maps. + using Allocator = + RecyclingAllocator<BumpPtrAllocator, char, AllocBytes, CacheLineBytes>; +}; + +//===----------------------------------------------------------------------===// +//--- IntervalMapImpl::NodeRef ---// +//===----------------------------------------------------------------------===// +// +// B+-tree nodes can be leaves or branches, so we need a polymorphic node +// pointer that can point to both kinds. +// +// All nodes are cache line aligned and the low 6 bits of a node pointer are +// always 0. These bits are used to store the number of elements in the +// referenced node. Besides saving space, placing node sizes in the parents +// allow tree balancing algorithms to run without faulting cache lines for nodes +// that may not need to be modified. +// +// A NodeRef doesn't know whether it references a leaf node or a branch node. +// It is the responsibility of the caller to use the correct types. +// +// Nodes are never supposed to be empty, and it is invalid to store a node size +// of 0 in a NodeRef. The valid range of sizes is 1-64. +// +//===----------------------------------------------------------------------===// + +class NodeRef { + struct CacheAlignedPointerTraits { + static inline void *getAsVoidPointer(void *P) { return P; } + static inline void *getFromVoidPointer(void *P) { return P; } + enum { NumLowBitsAvailable = Log2CacheLine }; + }; + PointerIntPair<void*, Log2CacheLine, unsigned, CacheAlignedPointerTraits> pip; + +public: + /// NodeRef - Create a null ref. + NodeRef() = default; + + /// operator bool - Detect a null ref. + explicit operator bool() const { return pip.getOpaqueValue(); } + + /// NodeRef - Create a reference to the node p with n elements. + template <typename NodeT> + NodeRef(NodeT *p, unsigned n) : pip(p, n - 1) { + assert(n <= NodeT::Capacity && "Size too big for node"); + } + + /// size - Return the number of elements in the referenced node. + unsigned size() const { return pip.getInt() + 1; } + + /// setSize - Update the node size. + void setSize(unsigned n) { pip.setInt(n - 1); } + + /// subtree - Access the i'th subtree reference in a branch node. + /// This depends on branch nodes storing the NodeRef array as their first + /// member. + NodeRef &subtree(unsigned i) const { + return reinterpret_cast<NodeRef*>(pip.getPointer())[i]; + } + + /// get - Dereference as a NodeT reference. + template <typename NodeT> + NodeT &get() const { + return *reinterpret_cast<NodeT*>(pip.getPointer()); + } + + bool operator==(const NodeRef &RHS) const { + if (pip == RHS.pip) + return true; + assert(pip.getPointer() != RHS.pip.getPointer() && "Inconsistent NodeRefs"); + return false; + } + + bool operator!=(const NodeRef &RHS) const { + return !operator==(RHS); + } +}; + +//===----------------------------------------------------------------------===// +//--- IntervalMapImpl::LeafNode ---// +//===----------------------------------------------------------------------===// +// +// Leaf nodes store up to N disjoint intervals with corresponding values. +// +// The intervals are kept sorted and fully coalesced so there are no adjacent +// intervals mapping to the same value. +// +// These constraints are always satisfied: +// +// - Traits::stopLess(start(i), stop(i)) - Non-empty, sane intervals. +// +// - Traits::stopLess(stop(i), start(i + 1) - Sorted. +// +// - value(i) != value(i + 1) || !Traits::adjacent(stop(i), start(i + 1)) +// - Fully coalesced. +// +//===----------------------------------------------------------------------===// + +template <typename KeyT, typename ValT, unsigned N, typename Traits> +class LeafNode : public NodeBase<std::pair<KeyT, KeyT>, ValT, N> { +public: + const KeyT &start(unsigned i) const { return this->first[i].first; } + const KeyT &stop(unsigned i) const { return this->first[i].second; } + const ValT &value(unsigned i) const { return this->second[i]; } + + KeyT &start(unsigned i) { return this->first[i].first; } + KeyT &stop(unsigned i) { return this->first[i].second; } + ValT &value(unsigned i) { return this->second[i]; } + + /// findFrom - Find the first interval after i that may contain x. + /// @param i Starting index for the search. + /// @param Size Number of elements in node. + /// @param x Key to search for. + /// @return First index with !stopLess(key[i].stop, x), or size. + /// This is the first interval that can possibly contain x. + unsigned findFrom(unsigned i, unsigned Size, KeyT x) const { + assert(i <= Size && Size <= N && "Bad indices"); + assert((i == 0 || Traits::stopLess(stop(i - 1), x)) && + "Index is past the needed point"); + while (i != Size && Traits::stopLess(stop(i), x)) ++i; + return i; + } + + /// safeFind - Find an interval that is known to exist. This is the same as + /// findFrom except is it assumed that x is at least within range of the last + /// interval. + /// @param i Starting index for the search. + /// @param x Key to search for. + /// @return First index with !stopLess(key[i].stop, x), never size. + /// This is the first interval that can possibly contain x. + unsigned safeFind(unsigned i, KeyT x) const { + assert(i < N && "Bad index"); + assert((i == 0 || Traits::stopLess(stop(i - 1), x)) && + "Index is past the needed point"); + while (Traits::stopLess(stop(i), x)) ++i; + assert(i < N && "Unsafe intervals"); + return i; + } + + /// safeLookup - Lookup mapped value for a safe key. + /// It is assumed that x is within range of the last entry. + /// @param x Key to search for. + /// @param NotFound Value to return if x is not in any interval. + /// @return The mapped value at x or NotFound. + ValT safeLookup(KeyT x, ValT NotFound) const { + unsigned i = safeFind(0, x); + return Traits::startLess(x, start(i)) ? NotFound : value(i); + } + + unsigned insertFrom(unsigned &Pos, unsigned Size, KeyT a, KeyT b, ValT y); +}; + +/// insertFrom - Add mapping of [a;b] to y if possible, coalescing as much as +/// possible. This may cause the node to grow by 1, or it may cause the node +/// to shrink because of coalescing. +/// @param Pos Starting index = insertFrom(0, size, a) +/// @param Size Number of elements in node. +/// @param a Interval start. +/// @param b Interval stop. +/// @param y Value be mapped. +/// @return (insert position, new size), or (i, Capacity+1) on overflow. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +unsigned LeafNode<KeyT, ValT, N, Traits>:: +insertFrom(unsigned &Pos, unsigned Size, KeyT a, KeyT b, ValT y) { + unsigned i = Pos; + assert(i <= Size && Size <= N && "Invalid index"); + assert(!Traits::stopLess(b, a) && "Invalid interval"); + + // Verify the findFrom invariant. + assert((i == 0 || Traits::stopLess(stop(i - 1), a))); + assert((i == Size || !Traits::stopLess(stop(i), a))); + assert((i == Size || Traits::stopLess(b, start(i))) && "Overlapping insert"); + + // Coalesce with previous interval. + if (i && value(i - 1) == y && Traits::adjacent(stop(i - 1), a)) { + Pos = i - 1; + // Also coalesce with next interval? + if (i != Size && value(i) == y && Traits::adjacent(b, start(i))) { + stop(i - 1) = stop(i); + this->erase(i, Size); + return Size - 1; + } + stop(i - 1) = b; + return Size; + } + + // Detect overflow. + if (i == N) + return N + 1; + + // Add new interval at end. + if (i == Size) { + start(i) = a; + stop(i) = b; + value(i) = y; + return Size + 1; + } + + // Try to coalesce with following interval. + if (value(i) == y && Traits::adjacent(b, start(i))) { + start(i) = a; + return Size; + } + + // We must insert before i. Detect overflow. + if (Size == N) + return N + 1; + + // Insert before i. + this->shift(i, Size); + start(i) = a; + stop(i) = b; + value(i) = y; + return Size + 1; +} + +//===----------------------------------------------------------------------===// +//--- IntervalMapImpl::BranchNode ---// +//===----------------------------------------------------------------------===// +// +// A branch node stores references to 1--N subtrees all of the same height. +// +// The key array in a branch node holds the rightmost stop key of each subtree. +// It is redundant to store the last stop key since it can be found in the +// parent node, but doing so makes tree balancing a lot simpler. +// +// It is unusual for a branch node to only have one subtree, but it can happen +// in the root node if it is smaller than the normal nodes. +// +// When all of the leaf nodes from all the subtrees are concatenated, they must +// satisfy the same constraints as a single leaf node. They must be sorted, +// sane, and fully coalesced. +// +//===----------------------------------------------------------------------===// + +template <typename KeyT, typename ValT, unsigned N, typename Traits> +class BranchNode : public NodeBase<NodeRef, KeyT, N> { +public: + const KeyT &stop(unsigned i) const { return this->second[i]; } + const NodeRef &subtree(unsigned i) const { return this->first[i]; } + + KeyT &stop(unsigned i) { return this->second[i]; } + NodeRef &subtree(unsigned i) { return this->first[i]; } + + /// findFrom - Find the first subtree after i that may contain x. + /// @param i Starting index for the search. + /// @param Size Number of elements in node. + /// @param x Key to search for. + /// @return First index with !stopLess(key[i], x), or size. + /// This is the first subtree that can possibly contain x. + unsigned findFrom(unsigned i, unsigned Size, KeyT x) const { + assert(i <= Size && Size <= N && "Bad indices"); + assert((i == 0 || Traits::stopLess(stop(i - 1), x)) && + "Index to findFrom is past the needed point"); + while (i != Size && Traits::stopLess(stop(i), x)) ++i; + return i; + } + + /// safeFind - Find a subtree that is known to exist. This is the same as + /// findFrom except is it assumed that x is in range. + /// @param i Starting index for the search. + /// @param x Key to search for. + /// @return First index with !stopLess(key[i], x), never size. + /// This is the first subtree that can possibly contain x. + unsigned safeFind(unsigned i, KeyT x) const { + assert(i < N && "Bad index"); + assert((i == 0 || Traits::stopLess(stop(i - 1), x)) && + "Index is past the needed point"); + while (Traits::stopLess(stop(i), x)) ++i; + assert(i < N && "Unsafe intervals"); + return i; + } + + /// safeLookup - Get the subtree containing x, Assuming that x is in range. + /// @param x Key to search for. + /// @return Subtree containing x + NodeRef safeLookup(KeyT x) const { + return subtree(safeFind(0, x)); + } + + /// insert - Insert a new (subtree, stop) pair. + /// @param i Insert position, following entries will be shifted. + /// @param Size Number of elements in node. + /// @param Node Subtree to insert. + /// @param Stop Last key in subtree. + void insert(unsigned i, unsigned Size, NodeRef Node, KeyT Stop) { + assert(Size < N && "branch node overflow"); + assert(i <= Size && "Bad insert position"); + this->shift(i, Size); + subtree(i) = Node; + stop(i) = Stop; + } +}; + +//===----------------------------------------------------------------------===// +//--- IntervalMapImpl::Path ---// +//===----------------------------------------------------------------------===// +// +// A Path is used by iterators to represent a position in a B+-tree, and the +// path to get there from the root. +// +// The Path class also contains the tree navigation code that doesn't have to +// be templatized. +// +//===----------------------------------------------------------------------===// + +class Path { + /// Entry - Each step in the path is a node pointer and an offset into that + /// node. + struct Entry { + void *node; + unsigned size; + unsigned offset; + + Entry(void *Node, unsigned Size, unsigned Offset) + : node(Node), size(Size), offset(Offset) {} + + Entry(NodeRef Node, unsigned Offset) + : node(&Node.subtree(0)), size(Node.size()), offset(Offset) {} + + NodeRef &subtree(unsigned i) const { + return reinterpret_cast<NodeRef*>(node)[i]; + } + }; + + /// path - The path entries, path[0] is the root node, path.back() is a leaf. + SmallVector<Entry, 4> path; + +public: + // Node accessors. + template <typename NodeT> NodeT &node(unsigned Level) const { + return *reinterpret_cast<NodeT*>(path[Level].node); + } + unsigned size(unsigned Level) const { return path[Level].size; } + unsigned offset(unsigned Level) const { return path[Level].offset; } + unsigned &offset(unsigned Level) { return path[Level].offset; } + + // Leaf accessors. + template <typename NodeT> NodeT &leaf() const { + return *reinterpret_cast<NodeT*>(path.back().node); + } + unsigned leafSize() const { return path.back().size; } + unsigned leafOffset() const { return path.back().offset; } + unsigned &leafOffset() { return path.back().offset; } + + /// valid - Return true if path is at a valid node, not at end(). + bool valid() const { + return !path.empty() && path.front().offset < path.front().size; + } + + /// height - Return the height of the tree corresponding to this path. + /// This matches map->height in a full path. + unsigned height() const { return path.size() - 1; } + + /// subtree - Get the subtree referenced from Level. When the path is + /// consistent, node(Level + 1) == subtree(Level). + /// @param Level 0..height-1. The leaves have no subtrees. + NodeRef &subtree(unsigned Level) const { + return path[Level].subtree(path[Level].offset); + } + + /// reset - Reset cached information about node(Level) from subtree(Level -1). + /// @param Level 1..height. THe node to update after parent node changed. + void reset(unsigned Level) { + path[Level] = Entry(subtree(Level - 1), offset(Level)); + } + + /// push - Add entry to path. + /// @param Node Node to add, should be subtree(path.size()-1). + /// @param Offset Offset into Node. + void push(NodeRef Node, unsigned Offset) { + path.push_back(Entry(Node, Offset)); + } + + /// pop - Remove the last path entry. + void pop() { + path.pop_back(); + } + + /// setSize - Set the size of a node both in the path and in the tree. + /// @param Level 0..height. Note that setting the root size won't change + /// map->rootSize. + /// @param Size New node size. + void setSize(unsigned Level, unsigned Size) { + path[Level].size = Size; + if (Level) + subtree(Level - 1).setSize(Size); + } + + /// setRoot - Clear the path and set a new root node. + /// @param Node New root node. + /// @param Size New root size. + /// @param Offset Offset into root node. + void setRoot(void *Node, unsigned Size, unsigned Offset) { + path.clear(); + path.push_back(Entry(Node, Size, Offset)); + } + + /// replaceRoot - Replace the current root node with two new entries after the + /// tree height has increased. + /// @param Root The new root node. + /// @param Size Number of entries in the new root. + /// @param Offsets Offsets into the root and first branch nodes. + void replaceRoot(void *Root, unsigned Size, IdxPair Offsets); + + /// getLeftSibling - Get the left sibling node at Level, or a null NodeRef. + /// @param Level Get the sibling to node(Level). + /// @return Left sibling, or NodeRef(). + NodeRef getLeftSibling(unsigned Level) const; + + /// moveLeft - Move path to the left sibling at Level. Leave nodes below Level + /// unaltered. + /// @param Level Move node(Level). + void moveLeft(unsigned Level); + + /// fillLeft - Grow path to Height by taking leftmost branches. + /// @param Height The target height. + void fillLeft(unsigned Height) { + while (height() < Height) + push(subtree(height()), 0); + } + + /// getLeftSibling - Get the left sibling node at Level, or a null NodeRef. + /// @param Level Get the sinbling to node(Level). + /// @return Left sibling, or NodeRef(). + NodeRef getRightSibling(unsigned Level) const; + + /// moveRight - Move path to the left sibling at Level. Leave nodes below + /// Level unaltered. + /// @param Level Move node(Level). + void moveRight(unsigned Level); + + /// atBegin - Return true if path is at begin(). + bool atBegin() const { + for (unsigned i = 0, e = path.size(); i != e; ++i) + if (path[i].offset != 0) + return false; + return true; + } + + /// atLastEntry - Return true if the path is at the last entry of the node at + /// Level. + /// @param Level Node to examine. + bool atLastEntry(unsigned Level) const { + return path[Level].offset == path[Level].size - 1; + } + + /// legalizeForInsert - Prepare the path for an insertion at Level. When the + /// path is at end(), node(Level) may not be a legal node. legalizeForInsert + /// ensures that node(Level) is real by moving back to the last node at Level, + /// and setting offset(Level) to size(Level) if required. + /// @param Level The level where an insertion is about to take place. + void legalizeForInsert(unsigned Level) { + if (valid()) + return; + moveLeft(Level); + ++path[Level].offset; + } +}; + +} // end namespace IntervalMapImpl + +//===----------------------------------------------------------------------===// +//--- IntervalMap ----// +//===----------------------------------------------------------------------===// + +template <typename KeyT, typename ValT, + unsigned N = IntervalMapImpl::NodeSizer<KeyT, ValT>::LeafSize, + typename Traits = IntervalMapInfo<KeyT>> +class IntervalMap { + using Sizer = IntervalMapImpl::NodeSizer<KeyT, ValT>; + using Leaf = IntervalMapImpl::LeafNode<KeyT, ValT, Sizer::LeafSize, Traits>; + using Branch = + IntervalMapImpl::BranchNode<KeyT, ValT, Sizer::BranchSize, Traits>; + using RootLeaf = IntervalMapImpl::LeafNode<KeyT, ValT, N, Traits>; + using IdxPair = IntervalMapImpl::IdxPair; + + // The RootLeaf capacity is given as a template parameter. We must compute the + // corresponding RootBranch capacity. + enum { + DesiredRootBranchCap = (sizeof(RootLeaf) - sizeof(KeyT)) / + (sizeof(KeyT) + sizeof(IntervalMapImpl::NodeRef)), + RootBranchCap = DesiredRootBranchCap ? DesiredRootBranchCap : 1 + }; + + using RootBranch = + IntervalMapImpl::BranchNode<KeyT, ValT, RootBranchCap, Traits>; + + // When branched, we store a global start key as well as the branch node. + struct RootBranchData { + KeyT start; + RootBranch node; + }; + +public: + using Allocator = typename Sizer::Allocator; + using KeyType = KeyT; + using ValueType = ValT; + using KeyTraits = Traits; + +private: + // The root data is either a RootLeaf or a RootBranchData instance. + alignas(RootLeaf) alignas(RootBranchData) + AlignedCharArrayUnion<RootLeaf, RootBranchData> data; + + // Tree height. + // 0: Leaves in root. + // 1: Root points to leaf. + // 2: root->branch->leaf ... + unsigned height; + + // Number of entries in the root node. + unsigned rootSize; + + // Allocator used for creating external nodes. + Allocator &allocator; + + /// Represent data as a node type without breaking aliasing rules. + template <typename T> + T &dataAs() const { + return *bit_cast<T *>(const_cast<char *>(data.buffer)); + } + + const RootLeaf &rootLeaf() const { + assert(!branched() && "Cannot acces leaf data in branched root"); + return dataAs<RootLeaf>(); + } + RootLeaf &rootLeaf() { + assert(!branched() && "Cannot acces leaf data in branched root"); + return dataAs<RootLeaf>(); + } + + RootBranchData &rootBranchData() const { + assert(branched() && "Cannot access branch data in non-branched root"); + return dataAs<RootBranchData>(); + } + RootBranchData &rootBranchData() { + assert(branched() && "Cannot access branch data in non-branched root"); + return dataAs<RootBranchData>(); + } + + const RootBranch &rootBranch() const { return rootBranchData().node; } + RootBranch &rootBranch() { return rootBranchData().node; } + KeyT rootBranchStart() const { return rootBranchData().start; } + KeyT &rootBranchStart() { return rootBranchData().start; } + + template <typename NodeT> NodeT *newNode() { + return new(allocator.template Allocate<NodeT>()) NodeT(); + } + + template <typename NodeT> void deleteNode(NodeT *P) { + P->~NodeT(); + allocator.Deallocate(P); + } + + IdxPair branchRoot(unsigned Position); + IdxPair splitRoot(unsigned Position); + + void switchRootToBranch() { + rootLeaf().~RootLeaf(); + height = 1; + new (&rootBranchData()) RootBranchData(); + } + + void switchRootToLeaf() { + rootBranchData().~RootBranchData(); + height = 0; + new(&rootLeaf()) RootLeaf(); + } + + bool branched() const { return height > 0; } + + ValT treeSafeLookup(KeyT x, ValT NotFound) const; + void visitNodes(void (IntervalMap::*f)(IntervalMapImpl::NodeRef, + unsigned Level)); + void deleteNode(IntervalMapImpl::NodeRef Node, unsigned Level); + +public: + explicit IntervalMap(Allocator &a) : height(0), rootSize(0), allocator(a) { + assert((uintptr_t(data.buffer) & (alignof(RootLeaf) - 1)) == 0 && + "Insufficient alignment"); + new(&rootLeaf()) RootLeaf(); + } + + ~IntervalMap() { + clear(); + rootLeaf().~RootLeaf(); + } + + /// empty - Return true when no intervals are mapped. + bool empty() const { + return rootSize == 0; + } + + /// start - Return the smallest mapped key in a non-empty map. + KeyT start() const { + assert(!empty() && "Empty IntervalMap has no start"); + return !branched() ? rootLeaf().start(0) : rootBranchStart(); + } + + /// stop - Return the largest mapped key in a non-empty map. + KeyT stop() const { + assert(!empty() && "Empty IntervalMap has no stop"); + return !branched() ? rootLeaf().stop(rootSize - 1) : + rootBranch().stop(rootSize - 1); + } + + /// lookup - Return the mapped value at x or NotFound. + ValT lookup(KeyT x, ValT NotFound = ValT()) const { + if (empty() || Traits::startLess(x, start()) || Traits::stopLess(stop(), x)) + return NotFound; + return branched() ? treeSafeLookup(x, NotFound) : + rootLeaf().safeLookup(x, NotFound); + } + + /// insert - Add a mapping of [a;b] to y, coalesce with adjacent intervals. + /// It is assumed that no key in the interval is mapped to another value, but + /// overlapping intervals already mapped to y will be coalesced. + void insert(KeyT a, KeyT b, ValT y) { + if (branched() || rootSize == RootLeaf::Capacity) + return find(a).insert(a, b, y); + + // Easy insert into root leaf. + unsigned p = rootLeaf().findFrom(0, rootSize, a); + rootSize = rootLeaf().insertFrom(p, rootSize, a, b, y); + } + + /// clear - Remove all entries. + void clear(); + + class const_iterator; + class iterator; + friend class const_iterator; + friend class iterator; + + const_iterator begin() const { + const_iterator I(*this); + I.goToBegin(); + return I; + } + + iterator begin() { + iterator I(*this); + I.goToBegin(); + return I; + } + + const_iterator end() const { + const_iterator I(*this); + I.goToEnd(); + return I; + } + + iterator end() { + iterator I(*this); + I.goToEnd(); + return I; + } + + /// find - Return an iterator pointing to the first interval ending at or + /// after x, or end(). + const_iterator find(KeyT x) const { + const_iterator I(*this); + I.find(x); + return I; + } + + iterator find(KeyT x) { + iterator I(*this); + I.find(x); + return I; + } + + /// overlaps(a, b) - Return true if the intervals in this map overlap with the + /// interval [a;b]. + bool overlaps(KeyT a, KeyT b) { + assert(Traits::nonEmpty(a, b)); + const_iterator I = find(a); + if (!I.valid()) + return false; + // [a;b] and [x;y] overlap iff x<=b and a<=y. The find() call guarantees the + // second part (y = find(a).stop()), so it is sufficient to check the first + // one. + return !Traits::stopLess(b, I.start()); + } +}; + +/// treeSafeLookup - Return the mapped value at x or NotFound, assuming a +/// branched root. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +ValT IntervalMap<KeyT, ValT, N, Traits>:: +treeSafeLookup(KeyT x, ValT NotFound) const { + assert(branched() && "treeLookup assumes a branched root"); + + IntervalMapImpl::NodeRef NR = rootBranch().safeLookup(x); + for (unsigned h = height-1; h; --h) + NR = NR.get<Branch>().safeLookup(x); + return NR.get<Leaf>().safeLookup(x, NotFound); +} + +// branchRoot - Switch from a leaf root to a branched root. +// Return the new (root offset, node offset) corresponding to Position. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +IntervalMapImpl::IdxPair IntervalMap<KeyT, ValT, N, Traits>:: +branchRoot(unsigned Position) { + using namespace IntervalMapImpl; + // How many external leaf nodes to hold RootLeaf+1? + const unsigned Nodes = RootLeaf::Capacity / Leaf::Capacity + 1; + + // Compute element distribution among new nodes. + unsigned size[Nodes]; + IdxPair NewOffset(0, Position); + + // Is is very common for the root node to be smaller than external nodes. + if (Nodes == 1) + size[0] = rootSize; + else + NewOffset = distribute(Nodes, rootSize, Leaf::Capacity, nullptr, size, + Position, true); + + // Allocate new nodes. + unsigned pos = 0; + NodeRef node[Nodes]; + for (unsigned n = 0; n != Nodes; ++n) { + Leaf *L = newNode<Leaf>(); + L->copy(rootLeaf(), pos, 0, size[n]); + node[n] = NodeRef(L, size[n]); + pos += size[n]; + } + + // Destroy the old leaf node, construct branch node instead. + switchRootToBranch(); + for (unsigned n = 0; n != Nodes; ++n) { + rootBranch().stop(n) = node[n].template get<Leaf>().stop(size[n]-1); + rootBranch().subtree(n) = node[n]; + } + rootBranchStart() = node[0].template get<Leaf>().start(0); + rootSize = Nodes; + return NewOffset; +} + +// splitRoot - Split the current BranchRoot into multiple Branch nodes. +// Return the new (root offset, node offset) corresponding to Position. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +IntervalMapImpl::IdxPair IntervalMap<KeyT, ValT, N, Traits>:: +splitRoot(unsigned Position) { + using namespace IntervalMapImpl; + // How many external leaf nodes to hold RootBranch+1? + const unsigned Nodes = RootBranch::Capacity / Branch::Capacity + 1; + + // Compute element distribution among new nodes. + unsigned Size[Nodes]; + IdxPair NewOffset(0, Position); + + // Is is very common for the root node to be smaller than external nodes. + if (Nodes == 1) + Size[0] = rootSize; + else + NewOffset = distribute(Nodes, rootSize, Leaf::Capacity, nullptr, Size, + Position, true); + + // Allocate new nodes. + unsigned Pos = 0; + NodeRef Node[Nodes]; + for (unsigned n = 0; n != Nodes; ++n) { + Branch *B = newNode<Branch>(); + B->copy(rootBranch(), Pos, 0, Size[n]); + Node[n] = NodeRef(B, Size[n]); + Pos += Size[n]; + } + + for (unsigned n = 0; n != Nodes; ++n) { + rootBranch().stop(n) = Node[n].template get<Branch>().stop(Size[n]-1); + rootBranch().subtree(n) = Node[n]; + } + rootSize = Nodes; + ++height; + return NewOffset; +} + +/// visitNodes - Visit each external node. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +visitNodes(void (IntervalMap::*f)(IntervalMapImpl::NodeRef, unsigned Height)) { + if (!branched()) + return; + SmallVector<IntervalMapImpl::NodeRef, 4> Refs, NextRefs; + + // Collect level 0 nodes from the root. + for (unsigned i = 0; i != rootSize; ++i) + Refs.push_back(rootBranch().subtree(i)); + + // Visit all branch nodes. + for (unsigned h = height - 1; h; --h) { + for (unsigned i = 0, e = Refs.size(); i != e; ++i) { + for (unsigned j = 0, s = Refs[i].size(); j != s; ++j) + NextRefs.push_back(Refs[i].subtree(j)); + (this->*f)(Refs[i], h); + } + Refs.clear(); + Refs.swap(NextRefs); + } + + // Visit all leaf nodes. + for (unsigned i = 0, e = Refs.size(); i != e; ++i) + (this->*f)(Refs[i], 0); +} + +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +deleteNode(IntervalMapImpl::NodeRef Node, unsigned Level) { + if (Level) + deleteNode(&Node.get<Branch>()); + else + deleteNode(&Node.get<Leaf>()); +} + +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +clear() { + if (branched()) { + visitNodes(&IntervalMap::deleteNode); + switchRootToLeaf(); + } + rootSize = 0; +} + +//===----------------------------------------------------------------------===// +//--- IntervalMap::const_iterator ----// +//===----------------------------------------------------------------------===// + +template <typename KeyT, typename ValT, unsigned N, typename Traits> +class IntervalMap<KeyT, ValT, N, Traits>::const_iterator : + public std::iterator<std::bidirectional_iterator_tag, ValT> { + +protected: + friend class IntervalMap; + + // The map referred to. + IntervalMap *map = nullptr; + + // We store a full path from the root to the current position. + // The path may be partially filled, but never between iterator calls. + IntervalMapImpl::Path path; + + explicit const_iterator(const IntervalMap &map) : + map(const_cast<IntervalMap*>(&map)) {} + + bool branched() const { + assert(map && "Invalid iterator"); + return map->branched(); + } + + void setRoot(unsigned Offset) { + if (branched()) + path.setRoot(&map->rootBranch(), map->rootSize, Offset); + else + path.setRoot(&map->rootLeaf(), map->rootSize, Offset); + } + + void pathFillFind(KeyT x); + void treeFind(KeyT x); + void treeAdvanceTo(KeyT x); + + /// unsafeStart - Writable access to start() for iterator. + KeyT &unsafeStart() const { + assert(valid() && "Cannot access invalid iterator"); + return branched() ? path.leaf<Leaf>().start(path.leafOffset()) : + path.leaf<RootLeaf>().start(path.leafOffset()); + } + + /// unsafeStop - Writable access to stop() for iterator. + KeyT &unsafeStop() const { + assert(valid() && "Cannot access invalid iterator"); + return branched() ? path.leaf<Leaf>().stop(path.leafOffset()) : + path.leaf<RootLeaf>().stop(path.leafOffset()); + } + + /// unsafeValue - Writable access to value() for iterator. + ValT &unsafeValue() const { + assert(valid() && "Cannot access invalid iterator"); + return branched() ? path.leaf<Leaf>().value(path.leafOffset()) : + path.leaf<RootLeaf>().value(path.leafOffset()); + } + +public: + /// const_iterator - Create an iterator that isn't pointing anywhere. + const_iterator() = default; + + /// setMap - Change the map iterated over. This call must be followed by a + /// call to goToBegin(), goToEnd(), or find() + void setMap(const IntervalMap &m) { map = const_cast<IntervalMap*>(&m); } + + /// valid - Return true if the current position is valid, false for end(). + bool valid() const { return path.valid(); } + + /// atBegin - Return true if the current position is the first map entry. + bool atBegin() const { return path.atBegin(); } + + /// start - Return the beginning of the current interval. + const KeyT &start() const { return unsafeStart(); } + + /// stop - Return the end of the current interval. + const KeyT &stop() const { return unsafeStop(); } + + /// value - Return the mapped value at the current interval. + const ValT &value() const { return unsafeValue(); } + + const ValT &operator*() const { return value(); } + + bool operator==(const const_iterator &RHS) const { + assert(map == RHS.map && "Cannot compare iterators from different maps"); + if (!valid()) + return !RHS.valid(); + if (path.leafOffset() != RHS.path.leafOffset()) + return false; + return &path.template leaf<Leaf>() == &RHS.path.template leaf<Leaf>(); + } + + bool operator!=(const const_iterator &RHS) const { + return !operator==(RHS); + } + + /// goToBegin - Move to the first interval in map. + void goToBegin() { + setRoot(0); + if (branched()) + path.fillLeft(map->height); + } + + /// goToEnd - Move beyond the last interval in map. + void goToEnd() { + setRoot(map->rootSize); + } + + /// preincrement - move to the next interval. + const_iterator &operator++() { + assert(valid() && "Cannot increment end()"); + if (++path.leafOffset() == path.leafSize() && branched()) + path.moveRight(map->height); + return *this; + } + + /// postincrement - Dont do that! + const_iterator operator++(int) { + const_iterator tmp = *this; + operator++(); + return tmp; + } + + /// predecrement - move to the previous interval. + const_iterator &operator--() { + if (path.leafOffset() && (valid() || !branched())) + --path.leafOffset(); + else + path.moveLeft(map->height); + return *this; + } + + /// postdecrement - Dont do that! + const_iterator operator--(int) { + const_iterator tmp = *this; + operator--(); + return tmp; + } + + /// find - Move to the first interval with stop >= x, or end(). + /// This is a full search from the root, the current position is ignored. + void find(KeyT x) { + if (branched()) + treeFind(x); + else + setRoot(map->rootLeaf().findFrom(0, map->rootSize, x)); + } + + /// advanceTo - Move to the first interval with stop >= x, or end(). + /// The search is started from the current position, and no earlier positions + /// can be found. This is much faster than find() for small moves. + void advanceTo(KeyT x) { + if (!valid()) + return; + if (branched()) + treeAdvanceTo(x); + else + path.leafOffset() = + map->rootLeaf().findFrom(path.leafOffset(), map->rootSize, x); + } +}; + +/// pathFillFind - Complete path by searching for x. +/// @param x Key to search for. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +const_iterator::pathFillFind(KeyT x) { + IntervalMapImpl::NodeRef NR = path.subtree(path.height()); + for (unsigned i = map->height - path.height() - 1; i; --i) { + unsigned p = NR.get<Branch>().safeFind(0, x); + path.push(NR, p); + NR = NR.subtree(p); + } + path.push(NR, NR.get<Leaf>().safeFind(0, x)); +} + +/// treeFind - Find in a branched tree. +/// @param x Key to search for. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +const_iterator::treeFind(KeyT x) { + setRoot(map->rootBranch().findFrom(0, map->rootSize, x)); + if (valid()) + pathFillFind(x); +} + +/// treeAdvanceTo - Find position after the current one. +/// @param x Key to search for. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +const_iterator::treeAdvanceTo(KeyT x) { + // Can we stay on the same leaf node? + if (!Traits::stopLess(path.leaf<Leaf>().stop(path.leafSize() - 1), x)) { + path.leafOffset() = path.leaf<Leaf>().safeFind(path.leafOffset(), x); + return; + } + + // Drop the current leaf. + path.pop(); + + // Search towards the root for a usable subtree. + if (path.height()) { + for (unsigned l = path.height() - 1; l; --l) { + if (!Traits::stopLess(path.node<Branch>(l).stop(path.offset(l)), x)) { + // The branch node at l+1 is usable + path.offset(l + 1) = + path.node<Branch>(l + 1).safeFind(path.offset(l + 1), x); + return pathFillFind(x); + } + path.pop(); + } + // Is the level-1 Branch usable? + if (!Traits::stopLess(map->rootBranch().stop(path.offset(0)), x)) { + path.offset(1) = path.node<Branch>(1).safeFind(path.offset(1), x); + return pathFillFind(x); + } + } + + // We reached the root. + setRoot(map->rootBranch().findFrom(path.offset(0), map->rootSize, x)); + if (valid()) + pathFillFind(x); +} + +//===----------------------------------------------------------------------===// +//--- IntervalMap::iterator ----// +//===----------------------------------------------------------------------===// + +template <typename KeyT, typename ValT, unsigned N, typename Traits> +class IntervalMap<KeyT, ValT, N, Traits>::iterator : public const_iterator { + friend class IntervalMap; + + using IdxPair = IntervalMapImpl::IdxPair; + + explicit iterator(IntervalMap &map) : const_iterator(map) {} + + void setNodeStop(unsigned Level, KeyT Stop); + bool insertNode(unsigned Level, IntervalMapImpl::NodeRef Node, KeyT Stop); + template <typename NodeT> bool overflow(unsigned Level); + void treeInsert(KeyT a, KeyT b, ValT y); + void eraseNode(unsigned Level); + void treeErase(bool UpdateRoot = true); + bool canCoalesceLeft(KeyT Start, ValT x); + bool canCoalesceRight(KeyT Stop, ValT x); + +public: + /// iterator - Create null iterator. + iterator() = default; + + /// setStart - Move the start of the current interval. + /// This may cause coalescing with the previous interval. + /// @param a New start key, must not overlap the previous interval. + void setStart(KeyT a); + + /// setStop - Move the end of the current interval. + /// This may cause coalescing with the following interval. + /// @param b New stop key, must not overlap the following interval. + void setStop(KeyT b); + + /// setValue - Change the mapped value of the current interval. + /// This may cause coalescing with the previous and following intervals. + /// @param x New value. + void setValue(ValT x); + + /// setStartUnchecked - Move the start of the current interval without + /// checking for coalescing or overlaps. + /// This should only be used when it is known that coalescing is not required. + /// @param a New start key. + void setStartUnchecked(KeyT a) { this->unsafeStart() = a; } + + /// setStopUnchecked - Move the end of the current interval without checking + /// for coalescing or overlaps. + /// This should only be used when it is known that coalescing is not required. + /// @param b New stop key. + void setStopUnchecked(KeyT b) { + this->unsafeStop() = b; + // Update keys in branch nodes as well. + if (this->path.atLastEntry(this->path.height())) + setNodeStop(this->path.height(), b); + } + + /// setValueUnchecked - Change the mapped value of the current interval + /// without checking for coalescing. + /// @param x New value. + void setValueUnchecked(ValT x) { this->unsafeValue() = x; } + + /// insert - Insert mapping [a;b] -> y before the current position. + void insert(KeyT a, KeyT b, ValT y); + + /// erase - Erase the current interval. + void erase(); + + iterator &operator++() { + const_iterator::operator++(); + return *this; + } + + iterator operator++(int) { + iterator tmp = *this; + operator++(); + return tmp; + } + + iterator &operator--() { + const_iterator::operator--(); + return *this; + } + + iterator operator--(int) { + iterator tmp = *this; + operator--(); + return tmp; + } +}; + +/// canCoalesceLeft - Can the current interval coalesce to the left after +/// changing start or value? +/// @param Start New start of current interval. +/// @param Value New value for current interval. +/// @return True when updating the current interval would enable coalescing. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +bool IntervalMap<KeyT, ValT, N, Traits>:: +iterator::canCoalesceLeft(KeyT Start, ValT Value) { + using namespace IntervalMapImpl; + Path &P = this->path; + if (!this->branched()) { + unsigned i = P.leafOffset(); + RootLeaf &Node = P.leaf<RootLeaf>(); + return i && Node.value(i-1) == Value && + Traits::adjacent(Node.stop(i-1), Start); + } + // Branched. + if (unsigned i = P.leafOffset()) { + Leaf &Node = P.leaf<Leaf>(); + return Node.value(i-1) == Value && Traits::adjacent(Node.stop(i-1), Start); + } else if (NodeRef NR = P.getLeftSibling(P.height())) { + unsigned i = NR.size() - 1; + Leaf &Node = NR.get<Leaf>(); + return Node.value(i) == Value && Traits::adjacent(Node.stop(i), Start); + } + return false; +} + +/// canCoalesceRight - Can the current interval coalesce to the right after +/// changing stop or value? +/// @param Stop New stop of current interval. +/// @param Value New value for current interval. +/// @return True when updating the current interval would enable coalescing. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +bool IntervalMap<KeyT, ValT, N, Traits>:: +iterator::canCoalesceRight(KeyT Stop, ValT Value) { + using namespace IntervalMapImpl; + Path &P = this->path; + unsigned i = P.leafOffset() + 1; + if (!this->branched()) { + if (i >= P.leafSize()) + return false; + RootLeaf &Node = P.leaf<RootLeaf>(); + return Node.value(i) == Value && Traits::adjacent(Stop, Node.start(i)); + } + // Branched. + if (i < P.leafSize()) { + Leaf &Node = P.leaf<Leaf>(); + return Node.value(i) == Value && Traits::adjacent(Stop, Node.start(i)); + } else if (NodeRef NR = P.getRightSibling(P.height())) { + Leaf &Node = NR.get<Leaf>(); + return Node.value(0) == Value && Traits::adjacent(Stop, Node.start(0)); + } + return false; +} + +/// setNodeStop - Update the stop key of the current node at level and above. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +iterator::setNodeStop(unsigned Level, KeyT Stop) { + // There are no references to the root node, so nothing to update. + if (!Level) + return; + IntervalMapImpl::Path &P = this->path; + // Update nodes pointing to the current node. + while (--Level) { + P.node<Branch>(Level).stop(P.offset(Level)) = Stop; + if (!P.atLastEntry(Level)) + return; + } + // Update root separately since it has a different layout. + P.node<RootBranch>(Level).stop(P.offset(Level)) = Stop; +} + +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +iterator::setStart(KeyT a) { + assert(Traits::nonEmpty(a, this->stop()) && "Cannot move start beyond stop"); + KeyT &CurStart = this->unsafeStart(); + if (!Traits::startLess(a, CurStart) || !canCoalesceLeft(a, this->value())) { + CurStart = a; + return; + } + // Coalesce with the interval to the left. + --*this; + a = this->start(); + erase(); + setStartUnchecked(a); +} + +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +iterator::setStop(KeyT b) { + assert(Traits::nonEmpty(this->start(), b) && "Cannot move stop beyond start"); + if (Traits::startLess(b, this->stop()) || + !canCoalesceRight(b, this->value())) { + setStopUnchecked(b); + return; + } + // Coalesce with interval to the right. + KeyT a = this->start(); + erase(); + setStartUnchecked(a); +} + +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +iterator::setValue(ValT x) { + setValueUnchecked(x); + if (canCoalesceRight(this->stop(), x)) { + KeyT a = this->start(); + erase(); + setStartUnchecked(a); + } + if (canCoalesceLeft(this->start(), x)) { + --*this; + KeyT a = this->start(); + erase(); + setStartUnchecked(a); + } +} + +/// insertNode - insert a node before the current path at level. +/// Leave the current path pointing at the new node. +/// @param Level path index of the node to be inserted. +/// @param Node The node to be inserted. +/// @param Stop The last index in the new node. +/// @return True if the tree height was increased. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +bool IntervalMap<KeyT, ValT, N, Traits>:: +iterator::insertNode(unsigned Level, IntervalMapImpl::NodeRef Node, KeyT Stop) { + assert(Level && "Cannot insert next to the root"); + bool SplitRoot = false; + IntervalMap &IM = *this->map; + IntervalMapImpl::Path &P = this->path; + + if (Level == 1) { + // Insert into the root branch node. + if (IM.rootSize < RootBranch::Capacity) { + IM.rootBranch().insert(P.offset(0), IM.rootSize, Node, Stop); + P.setSize(0, ++IM.rootSize); + P.reset(Level); + return SplitRoot; + } + + // We need to split the root while keeping our position. + SplitRoot = true; + IdxPair Offset = IM.splitRoot(P.offset(0)); + P.replaceRoot(&IM.rootBranch(), IM.rootSize, Offset); + + // Fall through to insert at the new higher level. + ++Level; + } + + // When inserting before end(), make sure we have a valid path. + P.legalizeForInsert(--Level); + + // Insert into the branch node at Level-1. + if (P.size(Level) == Branch::Capacity) { + // Branch node is full, handle handle the overflow. + assert(!SplitRoot && "Cannot overflow after splitting the root"); + SplitRoot = overflow<Branch>(Level); + Level += SplitRoot; + } + P.node<Branch>(Level).insert(P.offset(Level), P.size(Level), Node, Stop); + P.setSize(Level, P.size(Level) + 1); + if (P.atLastEntry(Level)) + setNodeStop(Level, Stop); + P.reset(Level + 1); + return SplitRoot; +} + +// insert +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +iterator::insert(KeyT a, KeyT b, ValT y) { + if (this->branched()) + return treeInsert(a, b, y); + IntervalMap &IM = *this->map; + IntervalMapImpl::Path &P = this->path; + + // Try simple root leaf insert. + unsigned Size = IM.rootLeaf().insertFrom(P.leafOffset(), IM.rootSize, a, b, y); + + // Was the root node insert successful? + if (Size <= RootLeaf::Capacity) { + P.setSize(0, IM.rootSize = Size); + return; + } + + // Root leaf node is full, we must branch. + IdxPair Offset = IM.branchRoot(P.leafOffset()); + P.replaceRoot(&IM.rootBranch(), IM.rootSize, Offset); + + // Now it fits in the new leaf. + treeInsert(a, b, y); +} + +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +iterator::treeInsert(KeyT a, KeyT b, ValT y) { + using namespace IntervalMapImpl; + Path &P = this->path; + + if (!P.valid()) + P.legalizeForInsert(this->map->height); + + // Check if this insertion will extend the node to the left. + if (P.leafOffset() == 0 && Traits::startLess(a, P.leaf<Leaf>().start(0))) { + // Node is growing to the left, will it affect a left sibling node? + if (NodeRef Sib = P.getLeftSibling(P.height())) { + Leaf &SibLeaf = Sib.get<Leaf>(); + unsigned SibOfs = Sib.size() - 1; + if (SibLeaf.value(SibOfs) == y && + Traits::adjacent(SibLeaf.stop(SibOfs), a)) { + // This insertion will coalesce with the last entry in SibLeaf. We can + // handle it in two ways: + // 1. Extend SibLeaf.stop to b and be done, or + // 2. Extend a to SibLeaf, erase the SibLeaf entry and continue. + // We prefer 1., but need 2 when coalescing to the right as well. + Leaf &CurLeaf = P.leaf<Leaf>(); + P.moveLeft(P.height()); + if (Traits::stopLess(b, CurLeaf.start(0)) && + (y != CurLeaf.value(0) || !Traits::adjacent(b, CurLeaf.start(0)))) { + // Easy, just extend SibLeaf and we're done. + setNodeStop(P.height(), SibLeaf.stop(SibOfs) = b); + return; + } else { + // We have both left and right coalescing. Erase the old SibLeaf entry + // and continue inserting the larger interval. + a = SibLeaf.start(SibOfs); + treeErase(/* UpdateRoot= */false); + } + } + } else { + // No left sibling means we are at begin(). Update cached bound. + this->map->rootBranchStart() = a; + } + } + + // When we are inserting at the end of a leaf node, we must update stops. + unsigned Size = P.leafSize(); + bool Grow = P.leafOffset() == Size; + Size = P.leaf<Leaf>().insertFrom(P.leafOffset(), Size, a, b, y); + + // Leaf insertion unsuccessful? Overflow and try again. + if (Size > Leaf::Capacity) { + overflow<Leaf>(P.height()); + Grow = P.leafOffset() == P.leafSize(); + Size = P.leaf<Leaf>().insertFrom(P.leafOffset(), P.leafSize(), a, b, y); + assert(Size <= Leaf::Capacity && "overflow() didn't make room"); + } + + // Inserted, update offset and leaf size. + P.setSize(P.height(), Size); + + // Insert was the last node entry, update stops. + if (Grow) + setNodeStop(P.height(), b); +} + +/// erase - erase the current interval and move to the next position. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +iterator::erase() { + IntervalMap &IM = *this->map; + IntervalMapImpl::Path &P = this->path; + assert(P.valid() && "Cannot erase end()"); + if (this->branched()) + return treeErase(); + IM.rootLeaf().erase(P.leafOffset(), IM.rootSize); + P.setSize(0, --IM.rootSize); +} + +/// treeErase - erase() for a branched tree. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +iterator::treeErase(bool UpdateRoot) { + IntervalMap &IM = *this->map; + IntervalMapImpl::Path &P = this->path; + Leaf &Node = P.leaf<Leaf>(); + + // Nodes are not allowed to become empty. + if (P.leafSize() == 1) { + IM.deleteNode(&Node); + eraseNode(IM.height); + // Update rootBranchStart if we erased begin(). + if (UpdateRoot && IM.branched() && P.valid() && P.atBegin()) + IM.rootBranchStart() = P.leaf<Leaf>().start(0); + return; + } + + // Erase current entry. + Node.erase(P.leafOffset(), P.leafSize()); + unsigned NewSize = P.leafSize() - 1; + P.setSize(IM.height, NewSize); + // When we erase the last entry, update stop and move to a legal position. + if (P.leafOffset() == NewSize) { + setNodeStop(IM.height, Node.stop(NewSize - 1)); + P.moveRight(IM.height); + } else if (UpdateRoot && P.atBegin()) + IM.rootBranchStart() = P.leaf<Leaf>().start(0); +} + +/// eraseNode - Erase the current node at Level from its parent and move path to +/// the first entry of the next sibling node. +/// The node must be deallocated by the caller. +/// @param Level 1..height, the root node cannot be erased. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +iterator::eraseNode(unsigned Level) { + assert(Level && "Cannot erase root node"); + IntervalMap &IM = *this->map; + IntervalMapImpl::Path &P = this->path; + + if (--Level == 0) { + IM.rootBranch().erase(P.offset(0), IM.rootSize); + P.setSize(0, --IM.rootSize); + // If this cleared the root, switch to height=0. + if (IM.empty()) { + IM.switchRootToLeaf(); + this->setRoot(0); + return; + } + } else { + // Remove node ref from branch node at Level. + Branch &Parent = P.node<Branch>(Level); + if (P.size(Level) == 1) { + // Branch node became empty, remove it recursively. + IM.deleteNode(&Parent); + eraseNode(Level); + } else { + // Branch node won't become empty. + Parent.erase(P.offset(Level), P.size(Level)); + unsigned NewSize = P.size(Level) - 1; + P.setSize(Level, NewSize); + // If we removed the last branch, update stop and move to a legal pos. + if (P.offset(Level) == NewSize) { + setNodeStop(Level, Parent.stop(NewSize - 1)); + P.moveRight(Level); + } + } + } + // Update path cache for the new right sibling position. + if (P.valid()) { + P.reset(Level + 1); + P.offset(Level + 1) = 0; + } +} + +/// overflow - Distribute entries of the current node evenly among +/// its siblings and ensure that the current node is not full. +/// This may require allocating a new node. +/// @tparam NodeT The type of node at Level (Leaf or Branch). +/// @param Level path index of the overflowing node. +/// @return True when the tree height was changed. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +template <typename NodeT> +bool IntervalMap<KeyT, ValT, N, Traits>:: +iterator::overflow(unsigned Level) { + using namespace IntervalMapImpl; + Path &P = this->path; + unsigned CurSize[4]; + NodeT *Node[4]; + unsigned Nodes = 0; + unsigned Elements = 0; + unsigned Offset = P.offset(Level); + + // Do we have a left sibling? + NodeRef LeftSib = P.getLeftSibling(Level); + if (LeftSib) { + Offset += Elements = CurSize[Nodes] = LeftSib.size(); + Node[Nodes++] = &LeftSib.get<NodeT>(); + } + + // Current node. + Elements += CurSize[Nodes] = P.size(Level); + Node[Nodes++] = &P.node<NodeT>(Level); + + // Do we have a right sibling? + NodeRef RightSib = P.getRightSibling(Level); + if (RightSib) { + Elements += CurSize[Nodes] = RightSib.size(); + Node[Nodes++] = &RightSib.get<NodeT>(); + } + + // Do we need to allocate a new node? + unsigned NewNode = 0; + if (Elements + 1 > Nodes * NodeT::Capacity) { + // Insert NewNode at the penultimate position, or after a single node. + NewNode = Nodes == 1 ? 1 : Nodes - 1; + CurSize[Nodes] = CurSize[NewNode]; + Node[Nodes] = Node[NewNode]; + CurSize[NewNode] = 0; + Node[NewNode] = this->map->template newNode<NodeT>(); + ++Nodes; + } + + // Compute the new element distribution. + unsigned NewSize[4]; + IdxPair NewOffset = distribute(Nodes, Elements, NodeT::Capacity, + CurSize, NewSize, Offset, true); + adjustSiblingSizes(Node, Nodes, CurSize, NewSize); + + // Move current location to the leftmost node. + if (LeftSib) + P.moveLeft(Level); + + // Elements have been rearranged, now update node sizes and stops. + bool SplitRoot = false; + unsigned Pos = 0; + while (true) { + KeyT Stop = Node[Pos]->stop(NewSize[Pos]-1); + if (NewNode && Pos == NewNode) { + SplitRoot = insertNode(Level, NodeRef(Node[Pos], NewSize[Pos]), Stop); + Level += SplitRoot; + } else { + P.setSize(Level, NewSize[Pos]); + setNodeStop(Level, Stop); + } + if (Pos + 1 == Nodes) + break; + P.moveRight(Level); + ++Pos; + } + + // Where was I? Find NewOffset. + while(Pos != NewOffset.first) { + P.moveLeft(Level); + --Pos; + } + P.offset(Level) = NewOffset.second; + return SplitRoot; +} + +//===----------------------------------------------------------------------===// +//--- IntervalMapOverlaps ----// +//===----------------------------------------------------------------------===// + +/// IntervalMapOverlaps - Iterate over the overlaps of mapped intervals in two +/// IntervalMaps. The maps may be different, but the KeyT and Traits types +/// should be the same. +/// +/// Typical uses: +/// +/// 1. Test for overlap: +/// bool overlap = IntervalMapOverlaps(a, b).valid(); +/// +/// 2. Enumerate overlaps: +/// for (IntervalMapOverlaps I(a, b); I.valid() ; ++I) { ... } +/// +template <typename MapA, typename MapB> +class IntervalMapOverlaps { + using KeyType = typename MapA::KeyType; + using Traits = typename MapA::KeyTraits; + + typename MapA::const_iterator posA; + typename MapB::const_iterator posB; + + /// advance - Move posA and posB forward until reaching an overlap, or until + /// either meets end. + /// Don't move the iterators if they are already overlapping. + void advance() { + if (!valid()) + return; + + if (Traits::stopLess(posA.stop(), posB.start())) { + // A ends before B begins. Catch up. + posA.advanceTo(posB.start()); + if (!posA.valid() || !Traits::stopLess(posB.stop(), posA.start())) + return; + } else if (Traits::stopLess(posB.stop(), posA.start())) { + // B ends before A begins. Catch up. + posB.advanceTo(posA.start()); + if (!posB.valid() || !Traits::stopLess(posA.stop(), posB.start())) + return; + } else + // Already overlapping. + return; + + while (true) { + // Make a.end > b.start. + posA.advanceTo(posB.start()); + if (!posA.valid() || !Traits::stopLess(posB.stop(), posA.start())) + return; + // Make b.end > a.start. + posB.advanceTo(posA.start()); + if (!posB.valid() || !Traits::stopLess(posA.stop(), posB.start())) + return; + } + } + +public: + /// IntervalMapOverlaps - Create an iterator for the overlaps of a and b. + IntervalMapOverlaps(const MapA &a, const MapB &b) + : posA(b.empty() ? a.end() : a.find(b.start())), + posB(posA.valid() ? b.find(posA.start()) : b.end()) { advance(); } + + /// valid - Return true if iterator is at an overlap. + bool valid() const { + return posA.valid() && posB.valid(); + } + + /// a - access the left hand side in the overlap. + const typename MapA::const_iterator &a() const { return posA; } + + /// b - access the right hand side in the overlap. + const typename MapB::const_iterator &b() const { return posB; } + + /// start - Beginning of the overlapping interval. + KeyType start() const { + KeyType ak = a().start(); + KeyType bk = b().start(); + return Traits::startLess(ak, bk) ? bk : ak; + } + + /// stop - End of the overlapping interval. + KeyType stop() const { + KeyType ak = a().stop(); + KeyType bk = b().stop(); + return Traits::startLess(ak, bk) ? ak : bk; + } + + /// skipA - Move to the next overlap that doesn't involve a(). + void skipA() { + ++posA; + advance(); + } + + /// skipB - Move to the next overlap that doesn't involve b(). + void skipB() { + ++posB; + advance(); + } + + /// Preincrement - Move to the next overlap. + IntervalMapOverlaps &operator++() { + // Bump the iterator that ends first. The other one may have more overlaps. + if (Traits::startLess(posB.stop(), posA.stop())) + skipB(); + else + skipA(); + return *this; + } + + /// advanceTo - Move to the first overlapping interval with + /// stopLess(x, stop()). + void advanceTo(KeyType x) { + if (!valid()) + return; + // Make sure advanceTo sees monotonic keys. + if (Traits::stopLess(posA.stop(), x)) + posA.advanceTo(x); + if (Traits::stopLess(posB.stop(), x)) + posB.advanceTo(x); + advance(); + } +}; + +} // end namespace llvm + +#endif // LLVM_ADT_INTERVALMAP_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/IntrusiveRefCntPtr.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/IntrusiveRefCntPtr.h new file mode 100644 index 0000000..6d97fe1 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/IntrusiveRefCntPtr.h
@@ -0,0 +1,269 @@ +//==- llvm/ADT/IntrusiveRefCntPtr.h - Smart Refcounting Pointer --*- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the RefCountedBase, ThreadSafeRefCountedBase, and +// IntrusiveRefCntPtr classes. +// +// IntrusiveRefCntPtr is a smart pointer to an object which maintains a +// reference count. (ThreadSafe)RefCountedBase is a mixin class that adds a +// refcount member variable and methods for updating the refcount. An object +// that inherits from (ThreadSafe)RefCountedBase deletes itself when its +// refcount hits zero. +// +// For example: +// +// class MyClass : public RefCountedBase<MyClass> {}; +// +// void foo() { +// // Constructing an IntrusiveRefCntPtr increases the pointee's refcount by +// // 1 (from 0 in this case). +// IntrusiveRefCntPtr<MyClass> Ptr1(new MyClass()); +// +// // Copying an IntrusiveRefCntPtr increases the pointee's refcount by 1. +// IntrusiveRefCntPtr<MyClass> Ptr2(Ptr1); +// +// // Constructing an IntrusiveRefCntPtr has no effect on the object's +// // refcount. After a move, the moved-from pointer is null. +// IntrusiveRefCntPtr<MyClass> Ptr3(std::move(Ptr1)); +// assert(Ptr1 == nullptr); +// +// // Clearing an IntrusiveRefCntPtr decreases the pointee's refcount by 1. +// Ptr2.reset(); +// +// // The object deletes itself when we return from the function, because +// // Ptr3's destructor decrements its refcount to 0. +// } +// +// You can use IntrusiveRefCntPtr with isa<T>(), dyn_cast<T>(), etc.: +// +// IntrusiveRefCntPtr<MyClass> Ptr(new MyClass()); +// OtherClass *Other = dyn_cast<OtherClass>(Ptr); // Ptr.get() not required +// +// IntrusiveRefCntPtr works with any class that +// +// - inherits from (ThreadSafe)RefCountedBase, +// - has Retain() and Release() methods, or +// - specializes IntrusiveRefCntPtrInfo. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_INTRUSIVEREFCNTPTR_H +#define LLVM_ADT_INTRUSIVEREFCNTPTR_H + +#include <atomic> +#include <cassert> +#include <cstddef> + +namespace llvm { + +/// A CRTP mixin class that adds reference counting to a type. +/// +/// The lifetime of an object which inherits from RefCountedBase is managed by +/// calls to Release() and Retain(), which increment and decrement the object's +/// refcount, respectively. When a Release() call decrements the refcount to 0, +/// the object deletes itself. +template <class Derived> class RefCountedBase { + mutable unsigned RefCount = 0; + +public: + RefCountedBase() = default; + RefCountedBase(const RefCountedBase &) {} + + void Retain() const { ++RefCount; } + + void Release() const { + assert(RefCount > 0 && "Reference count is already zero."); + if (--RefCount == 0) + delete static_cast<const Derived *>(this); + } +}; + +/// A thread-safe version of \c RefCountedBase. +template <class Derived> class ThreadSafeRefCountedBase { + mutable std::atomic<int> RefCount; + +protected: + ThreadSafeRefCountedBase() : RefCount(0) {} + +public: + void Retain() const { RefCount.fetch_add(1, std::memory_order_relaxed); } + + void Release() const { + int NewRefCount = RefCount.fetch_sub(1, std::memory_order_acq_rel) - 1; + assert(NewRefCount >= 0 && "Reference count was already zero."); + if (NewRefCount == 0) + delete static_cast<const Derived *>(this); + } +}; + +/// Class you can specialize to provide custom retain/release functionality for +/// a type. +/// +/// Usually specializing this class is not necessary, as IntrusiveRefCntPtr +/// works with any type which defines Retain() and Release() functions -- you +/// can define those functions yourself if RefCountedBase doesn't work for you. +/// +/// One case when you might want to specialize this type is if you have +/// - Foo.h defines type Foo and includes Bar.h, and +/// - Bar.h uses IntrusiveRefCntPtr<Foo> in inline functions. +/// +/// Because Foo.h includes Bar.h, Bar.h can't include Foo.h in order to pull in +/// the declaration of Foo. Without the declaration of Foo, normally Bar.h +/// wouldn't be able to use IntrusiveRefCntPtr<Foo>, which wants to call +/// T::Retain and T::Release. +/// +/// To resolve this, Bar.h could include a third header, FooFwd.h, which +/// forward-declares Foo and specializes IntrusiveRefCntPtrInfo<Foo>. Then +/// Bar.h could use IntrusiveRefCntPtr<Foo>, although it still couldn't call any +/// functions on Foo itself, because Foo would be an incomplete type. +template <typename T> struct IntrusiveRefCntPtrInfo { + static void retain(T *obj) { obj->Retain(); } + static void release(T *obj) { obj->Release(); } +}; + +/// A smart pointer to a reference-counted object that inherits from +/// RefCountedBase or ThreadSafeRefCountedBase. +/// +/// This class increments its pointee's reference count when it is created, and +/// decrements its refcount when it's destroyed (or is changed to point to a +/// different object). +template <typename T> class IntrusiveRefCntPtr { + T *Obj = nullptr; + +public: + using element_type = T; + + explicit IntrusiveRefCntPtr() = default; + IntrusiveRefCntPtr(T *obj) : Obj(obj) { retain(); } + IntrusiveRefCntPtr(const IntrusiveRefCntPtr &S) : Obj(S.Obj) { retain(); } + IntrusiveRefCntPtr(IntrusiveRefCntPtr &&S) : Obj(S.Obj) { S.Obj = nullptr; } + + template <class X> + IntrusiveRefCntPtr(IntrusiveRefCntPtr<X> &&S) : Obj(S.get()) { + S.Obj = nullptr; + } + + template <class X> + IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X> &S) : Obj(S.get()) { + retain(); + } + + ~IntrusiveRefCntPtr() { release(); } + + IntrusiveRefCntPtr &operator=(IntrusiveRefCntPtr S) { + swap(S); + return *this; + } + + T &operator*() const { return *Obj; } + T *operator->() const { return Obj; } + T *get() const { return Obj; } + explicit operator bool() const { return Obj; } + + void swap(IntrusiveRefCntPtr &other) { + T *tmp = other.Obj; + other.Obj = Obj; + Obj = tmp; + } + + void reset() { + release(); + Obj = nullptr; + } + + void resetWithoutRelease() { Obj = nullptr; } + +private: + void retain() { + if (Obj) + IntrusiveRefCntPtrInfo<T>::retain(Obj); + } + + void release() { + if (Obj) + IntrusiveRefCntPtrInfo<T>::release(Obj); + } + + template <typename X> friend class IntrusiveRefCntPtr; +}; + +template <class T, class U> +inline bool operator==(const IntrusiveRefCntPtr<T> &A, + const IntrusiveRefCntPtr<U> &B) { + return A.get() == B.get(); +} + +template <class T, class U> +inline bool operator!=(const IntrusiveRefCntPtr<T> &A, + const IntrusiveRefCntPtr<U> &B) { + return A.get() != B.get(); +} + +template <class T, class U> +inline bool operator==(const IntrusiveRefCntPtr<T> &A, U *B) { + return A.get() == B; +} + +template <class T, class U> +inline bool operator!=(const IntrusiveRefCntPtr<T> &A, U *B) { + return A.get() != B; +} + +template <class T, class U> +inline bool operator==(T *A, const IntrusiveRefCntPtr<U> &B) { + return A == B.get(); +} + +template <class T, class U> +inline bool operator!=(T *A, const IntrusiveRefCntPtr<U> &B) { + return A != B.get(); +} + +template <class T> +bool operator==(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) { + return !B; +} + +template <class T> +bool operator==(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) { + return B == A; +} + +template <class T> +bool operator!=(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) { + return !(A == B); +} + +template <class T> +bool operator!=(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) { + return !(A == B); +} + +// Make IntrusiveRefCntPtr work with dyn_cast, isa, and the other idioms from +// Casting.h. +template <typename From> struct simplify_type; + +template <class T> struct simplify_type<IntrusiveRefCntPtr<T>> { + using SimpleType = T *; + + static SimpleType getSimplifiedValue(IntrusiveRefCntPtr<T> &Val) { + return Val.get(); + } +}; + +template <class T> struct simplify_type<const IntrusiveRefCntPtr<T>> { + using SimpleType = /*const*/ T *; + + static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T> &Val) { + return Val.get(); + } +}; + +} // end namespace llvm + +#endif // LLVM_ADT_INTRUSIVEREFCNTPTR_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/MapVector.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/MapVector.h new file mode 100644 index 0000000..1de1124 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/MapVector.h
@@ -0,0 +1,239 @@ +//===- llvm/ADT/MapVector.h - Map w/ deterministic value order --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements a map that provides insertion order iteration. The +// interface is purposefully minimal. The key is assumed to be cheap to copy +// and 2 copies are kept, one for indexing in a DenseMap, one for iteration in +// a std::vector. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_MAPVECTOR_H +#define LLVM_ADT_MAPVECTOR_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <iterator> +#include <type_traits> +#include <utility> +#include <vector> + +namespace llvm { + +/// This class implements a map that also provides access to all stored values +/// in a deterministic order. The values are kept in a std::vector and the +/// mapping is done with DenseMap from Keys to indexes in that vector. +template<typename KeyT, typename ValueT, + typename MapType = DenseMap<KeyT, unsigned>, + typename VectorType = std::vector<std::pair<KeyT, ValueT>>> +class MapVector { + MapType Map; + VectorType Vector; + + static_assert( + std::is_integral<typename MapType::mapped_type>::value, + "The mapped_type of the specified Map must be an integral type"); + +public: + using value_type = typename VectorType::value_type; + using size_type = typename VectorType::size_type; + + using iterator = typename VectorType::iterator; + using const_iterator = typename VectorType::const_iterator; + using reverse_iterator = typename VectorType::reverse_iterator; + using const_reverse_iterator = typename VectorType::const_reverse_iterator; + + /// Clear the MapVector and return the underlying vector. + VectorType takeVector() { + Map.clear(); + return std::move(Vector); + } + + size_type size() const { return Vector.size(); } + + /// Grow the MapVector so that it can contain at least \p NumEntries items + /// before resizing again. + void reserve(size_type NumEntries) { + Map.reserve(NumEntries); + Vector.reserve(NumEntries); + } + + iterator begin() { return Vector.begin(); } + const_iterator begin() const { return Vector.begin(); } + iterator end() { return Vector.end(); } + const_iterator end() const { return Vector.end(); } + + reverse_iterator rbegin() { return Vector.rbegin(); } + const_reverse_iterator rbegin() const { return Vector.rbegin(); } + reverse_iterator rend() { return Vector.rend(); } + const_reverse_iterator rend() const { return Vector.rend(); } + + bool empty() const { + return Vector.empty(); + } + + std::pair<KeyT, ValueT> &front() { return Vector.front(); } + const std::pair<KeyT, ValueT> &front() const { return Vector.front(); } + std::pair<KeyT, ValueT> &back() { return Vector.back(); } + const std::pair<KeyT, ValueT> &back() const { return Vector.back(); } + + void clear() { + Map.clear(); + Vector.clear(); + } + + void swap(MapVector &RHS) { + std::swap(Map, RHS.Map); + std::swap(Vector, RHS.Vector); + } + + ValueT &operator[](const KeyT &Key) { + std::pair<KeyT, typename MapType::mapped_type> Pair = std::make_pair(Key, 0); + std::pair<typename MapType::iterator, bool> Result = Map.insert(Pair); + auto &I = Result.first->second; + if (Result.second) { + Vector.push_back(std::make_pair(Key, ValueT())); + I = Vector.size() - 1; + } + return Vector[I].second; + } + + // Returns a copy of the value. Only allowed if ValueT is copyable. + ValueT lookup(const KeyT &Key) const { + static_assert(std::is_copy_constructible<ValueT>::value, + "Cannot call lookup() if ValueT is not copyable."); + typename MapType::const_iterator Pos = Map.find(Key); + return Pos == Map.end()? ValueT() : Vector[Pos->second].second; + } + + std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) { + std::pair<KeyT, typename MapType::mapped_type> Pair = std::make_pair(KV.first, 0); + std::pair<typename MapType::iterator, bool> Result = Map.insert(Pair); + auto &I = Result.first->second; + if (Result.second) { + Vector.push_back(std::make_pair(KV.first, KV.second)); + I = Vector.size() - 1; + return std::make_pair(std::prev(end()), true); + } + return std::make_pair(begin() + I, false); + } + + std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) { + // Copy KV.first into the map, then move it into the vector. + std::pair<KeyT, typename MapType::mapped_type> Pair = std::make_pair(KV.first, 0); + std::pair<typename MapType::iterator, bool> Result = Map.insert(Pair); + auto &I = Result.first->second; + if (Result.second) { + Vector.push_back(std::move(KV)); + I = Vector.size() - 1; + return std::make_pair(std::prev(end()), true); + } + return std::make_pair(begin() + I, false); + } + + size_type count(const KeyT &Key) const { + typename MapType::const_iterator Pos = Map.find(Key); + return Pos == Map.end()? 0 : 1; + } + + iterator find(const KeyT &Key) { + typename MapType::const_iterator Pos = Map.find(Key); + return Pos == Map.end()? Vector.end() : + (Vector.begin() + Pos->second); + } + + const_iterator find(const KeyT &Key) const { + typename MapType::const_iterator Pos = Map.find(Key); + return Pos == Map.end()? Vector.end() : + (Vector.begin() + Pos->second); + } + + /// Remove the last element from the vector. + void pop_back() { + typename MapType::iterator Pos = Map.find(Vector.back().first); + Map.erase(Pos); + Vector.pop_back(); + } + + /// Remove the element given by Iterator. + /// + /// Returns an iterator to the element following the one which was removed, + /// which may be end(). + /// + /// \note This is a deceivingly expensive operation (linear time). It's + /// usually better to use \a remove_if() if possible. + typename VectorType::iterator erase(typename VectorType::iterator Iterator) { + Map.erase(Iterator->first); + auto Next = Vector.erase(Iterator); + if (Next == Vector.end()) + return Next; + + // Update indices in the map. + size_t Index = Next - Vector.begin(); + for (auto &I : Map) { + assert(I.second != Index && "Index was already erased!"); + if (I.second > Index) + --I.second; + } + return Next; + } + + /// Remove all elements with the key value Key. + /// + /// Returns the number of elements removed. + size_type erase(const KeyT &Key) { + auto Iterator = find(Key); + if (Iterator == end()) + return 0; + erase(Iterator); + return 1; + } + + /// Remove the elements that match the predicate. + /// + /// Erase all elements that match \c Pred in a single pass. Takes linear + /// time. + template <class Predicate> void remove_if(Predicate Pred); +}; + +template <typename KeyT, typename ValueT, typename MapType, typename VectorType> +template <class Function> +void MapVector<KeyT, ValueT, MapType, VectorType>::remove_if(Function Pred) { + auto O = Vector.begin(); + for (auto I = O, E = Vector.end(); I != E; ++I) { + if (Pred(*I)) { + // Erase from the map. + Map.erase(I->first); + continue; + } + + if (I != O) { + // Move the value and update the index in the map. + *O = std::move(*I); + Map[O->first] = O - Vector.begin(); + } + ++O; + } + // Erase trailing entries in the vector. + Vector.erase(O, Vector.end()); +} + +/// A MapVector that performs no allocations if smaller than a certain +/// size. +template <typename KeyT, typename ValueT, unsigned N> +struct SmallMapVector + : MapVector<KeyT, ValueT, SmallDenseMap<KeyT, unsigned, N>, + SmallVector<std::pair<KeyT, ValueT>, N>> { +}; + +} // end namespace llvm + +#endif // LLVM_ADT_MAPVECTOR_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/None.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/None.h new file mode 100644 index 0000000..004ca0a --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/None.h
@@ -0,0 +1,26 @@ +//===-- None.h - Simple null value for implicit construction ------*- C++ -*-=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file provides None, an enumerator for use in implicit constructors +// of various (usually templated) types to make such construction more +// terse. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_NONE_H +#define LLVM_ADT_NONE_H + +namespace llvm { +/// A simple null object to allow implicit construction of Optional<T> +/// and similar types without having to spell out the specialization's name. +// (constant value 1 in an attempt to workaround MSVC build issue... ) +enum class NoneType { None = 1 }; +const NoneType None = NoneType::None; +} + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/Optional.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/Optional.h new file mode 100644 index 0000000..c84f9aa --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/Optional.h
@@ -0,0 +1,445 @@ +//===- Optional.h - Simple variant for passing optional values --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file provides Optional, a template class modeled in the spirit of +// OCaml's 'opt' variant. The idea is to strongly type whether or not +// a value can be optional. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_OPTIONAL_H +#define LLVM_ADT_OPTIONAL_H + +#include "llvm/ADT/None.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/type_traits.h" +#include <cassert> +#include <memory> +#include <new> +#include <utility> + +namespace llvm { + +class raw_ostream; + +namespace optional_detail { + +struct in_place_t {}; + +/// Storage for any type. +template <typename T, bool = is_trivially_copyable<T>::value> +class OptionalStorage { + union { + char empty; + T value; + }; + bool hasVal; + +public: + ~OptionalStorage() { reset(); } + + OptionalStorage() noexcept : empty(), hasVal(false) {} + + OptionalStorage(OptionalStorage const &other) : OptionalStorage() { + if (other.hasValue()) { + emplace(other.value); + } + } + OptionalStorage(OptionalStorage &&other) : OptionalStorage() { + if (other.hasValue()) { + emplace(std::move(other.value)); + } + } + + template <class... Args> + explicit OptionalStorage(in_place_t, Args &&... args) + : value(std::forward<Args>(args)...), hasVal(true) {} + + void reset() noexcept { + if (hasVal) { + value.~T(); + hasVal = false; + } + } + + bool hasValue() const noexcept { return hasVal; } + + T &getValue() LLVM_LVALUE_FUNCTION noexcept { + assert(hasVal); + return value; + } + T const &getValue() const LLVM_LVALUE_FUNCTION noexcept { + assert(hasVal); + return value; + } +#if LLVM_HAS_RVALUE_REFERENCE_THIS + T &&getValue() && noexcept { + assert(hasVal); + return std::move(value); + } +#endif + + template <class... Args> void emplace(Args &&... args) { + reset(); + ::new ((void *)std::addressof(value)) T(std::forward<Args>(args)...); + hasVal = true; + } + + OptionalStorage &operator=(T const &y) { + if (hasValue()) { + value = y; + } else { + ::new ((void *)std::addressof(value)) T(y); + hasVal = true; + } + return *this; + } + OptionalStorage &operator=(T &&y) { + if (hasValue()) { + value = std::move(y); + } else { + ::new ((void *)std::addressof(value)) T(std::move(y)); + hasVal = true; + } + return *this; + } + + OptionalStorage &operator=(OptionalStorage const &other) { + if (other.hasValue()) { + if (hasValue()) { + value = other.value; + } else { + ::new ((void *)std::addressof(value)) T(other.value); + hasVal = true; + } + } else { + reset(); + } + return *this; + } + + OptionalStorage &operator=(OptionalStorage &&other) { + if (other.hasValue()) { + if (hasValue()) { + value = std::move(other.value); + } else { + ::new ((void *)std::addressof(value)) T(std::move(other.value)); + hasVal = true; + } + } else { + reset(); + } + return *this; + } +}; + +template <typename T> class OptionalStorage<T, true> { + union { + char empty; + T value; + }; + bool hasVal = false; + +public: + ~OptionalStorage() = default; + + OptionalStorage() noexcept : empty{} {} + + OptionalStorage(OptionalStorage const &other) = default; + OptionalStorage(OptionalStorage &&other) = default; + + OptionalStorage &operator=(OptionalStorage const &other) = default; + OptionalStorage &operator=(OptionalStorage &&other) = default; + + template <class... Args> + explicit OptionalStorage(in_place_t, Args &&... args) + : value(std::forward<Args>(args)...), hasVal(true) {} + + void reset() noexcept { + if (hasVal) { + value.~T(); + hasVal = false; + } + } + + bool hasValue() const noexcept { return hasVal; } + + T &getValue() LLVM_LVALUE_FUNCTION noexcept { + assert(hasVal); + return value; + } + T const &getValue() const LLVM_LVALUE_FUNCTION noexcept { + assert(hasVal); + return value; + } +#if LLVM_HAS_RVALUE_REFERENCE_THIS + T &&getValue() && noexcept { + assert(hasVal); + return std::move(value); + } +#endif + + template <class... Args> void emplace(Args &&... args) { + reset(); + ::new ((void *)std::addressof(value)) T(std::forward<Args>(args)...); + hasVal = true; + } + + OptionalStorage &operator=(T const &y) { + if (hasValue()) { + value = y; + } else { + ::new ((void *)std::addressof(value)) T(y); + hasVal = true; + } + return *this; + } + OptionalStorage &operator=(T &&y) { + if (hasValue()) { + value = std::move(y); + } else { + ::new ((void *)std::addressof(value)) T(std::move(y)); + hasVal = true; + } + return *this; + } +}; + +} // namespace optional_detail + +template <typename T> class Optional { + optional_detail::OptionalStorage<T> Storage; + +public: + using value_type = T; + + constexpr Optional() {} + constexpr Optional(NoneType) {} + + Optional(const T &y) : Storage(optional_detail::in_place_t{}, y) {} + Optional(const Optional &O) = default; + + Optional(T &&y) : Storage(optional_detail::in_place_t{}, std::move(y)) {} + Optional(Optional &&O) = default; + + Optional &operator=(T &&y) { + Storage = std::move(y); + return *this; + } + Optional &operator=(Optional &&O) = default; + + /// Create a new object by constructing it in place with the given arguments. + template <typename... ArgTypes> void emplace(ArgTypes &&... Args) { + Storage.emplace(std::forward<ArgTypes>(Args)...); + } + + static inline Optional create(const T *y) { + return y ? Optional(*y) : Optional(); + } + + Optional &operator=(const T &y) { + Storage = y; + return *this; + } + Optional &operator=(const Optional &O) = default; + + void reset() { Storage.reset(); } + + const T *getPointer() const { return &Storage.getValue(); } + T *getPointer() { return &Storage.getValue(); } + const T &getValue() const LLVM_LVALUE_FUNCTION { return Storage.getValue(); } + T &getValue() LLVM_LVALUE_FUNCTION { return Storage.getValue(); } + + explicit operator bool() const { return hasValue(); } + bool hasValue() const { return Storage.hasValue(); } + const T *operator->() const { return getPointer(); } + T *operator->() { return getPointer(); } + const T &operator*() const LLVM_LVALUE_FUNCTION { return getValue(); } + T &operator*() LLVM_LVALUE_FUNCTION { return getValue(); } + + template <typename U> + constexpr T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION { + return hasValue() ? getValue() : std::forward<U>(value); + } + + /// Apply a function to the value if present; otherwise return None. + template <class Function> + auto map(const Function &F) const + -> Optional<decltype(F(getValue()))> { + if (*this) return F(getValue()); + return None; + } + +#if LLVM_HAS_RVALUE_REFERENCE_THIS + T &&getValue() && { return std::move(Storage.getValue()); } + T &&operator*() && { return std::move(Storage.getValue()); } + + template <typename U> + T getValueOr(U &&value) && { + return hasValue() ? std::move(getValue()) : std::forward<U>(value); + } + + /// Apply a function to the value if present; otherwise return None. + template <class Function> + auto map(const Function &F) && + -> Optional<decltype(F(std::move(*this).getValue()))> { + if (*this) return F(std::move(*this).getValue()); + return None; + } +#endif +}; + +template <typename T, typename U> +bool operator==(const Optional<T> &X, const Optional<U> &Y) { + if (X && Y) + return *X == *Y; + return X.hasValue() == Y.hasValue(); +} + +template <typename T, typename U> +bool operator!=(const Optional<T> &X, const Optional<U> &Y) { + return !(X == Y); +} + +template <typename T, typename U> +bool operator<(const Optional<T> &X, const Optional<U> &Y) { + if (X && Y) + return *X < *Y; + return X.hasValue() < Y.hasValue(); +} + +template <typename T, typename U> +bool operator<=(const Optional<T> &X, const Optional<U> &Y) { + return !(Y < X); +} + +template <typename T, typename U> +bool operator>(const Optional<T> &X, const Optional<U> &Y) { + return Y < X; +} + +template <typename T, typename U> +bool operator>=(const Optional<T> &X, const Optional<U> &Y) { + return !(X < Y); +} + +template<typename T> +bool operator==(const Optional<T> &X, NoneType) { + return !X; +} + +template<typename T> +bool operator==(NoneType, const Optional<T> &X) { + return X == None; +} + +template<typename T> +bool operator!=(const Optional<T> &X, NoneType) { + return !(X == None); +} + +template<typename T> +bool operator!=(NoneType, const Optional<T> &X) { + return X != None; +} + +template <typename T> bool operator<(const Optional<T> &X, NoneType) { + return false; +} + +template <typename T> bool operator<(NoneType, const Optional<T> &X) { + return X.hasValue(); +} + +template <typename T> bool operator<=(const Optional<T> &X, NoneType) { + return !(None < X); +} + +template <typename T> bool operator<=(NoneType, const Optional<T> &X) { + return !(X < None); +} + +template <typename T> bool operator>(const Optional<T> &X, NoneType) { + return None < X; +} + +template <typename T> bool operator>(NoneType, const Optional<T> &X) { + return X < None; +} + +template <typename T> bool operator>=(const Optional<T> &X, NoneType) { + return None <= X; +} + +template <typename T> bool operator>=(NoneType, const Optional<T> &X) { + return X <= None; +} + +template <typename T> bool operator==(const Optional<T> &X, const T &Y) { + return X && *X == Y; +} + +template <typename T> bool operator==(const T &X, const Optional<T> &Y) { + return Y && X == *Y; +} + +template <typename T> bool operator!=(const Optional<T> &X, const T &Y) { + return !(X == Y); +} + +template <typename T> bool operator!=(const T &X, const Optional<T> &Y) { + return !(X == Y); +} + +template <typename T> bool operator<(const Optional<T> &X, const T &Y) { + return !X || *X < Y; +} + +template <typename T> bool operator<(const T &X, const Optional<T> &Y) { + return Y && X < *Y; +} + +template <typename T> bool operator<=(const Optional<T> &X, const T &Y) { + return !(Y < X); +} + +template <typename T> bool operator<=(const T &X, const Optional<T> &Y) { + return !(Y < X); +} + +template <typename T> bool operator>(const Optional<T> &X, const T &Y) { + return Y < X; +} + +template <typename T> bool operator>(const T &X, const Optional<T> &Y) { + return Y < X; +} + +template <typename T> bool operator>=(const Optional<T> &X, const T &Y) { + return !(X < Y); +} + +template <typename T> bool operator>=(const T &X, const Optional<T> &Y) { + return !(X < Y); +} + +raw_ostream &operator<<(raw_ostream &OS, NoneType); + +template <typename T, typename = decltype(std::declval<raw_ostream &>() + << std::declval<const T &>())> +raw_ostream &operator<<(raw_ostream &OS, const Optional<T> &O) { + if (O) + OS << *O; + else + OS << None; + return OS; +} + +} // end namespace llvm + +#endif // LLVM_ADT_OPTIONAL_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/PackedVector.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/PackedVector.h new file mode 100644 index 0000000..ae7f8cc --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/PackedVector.h
@@ -0,0 +1,150 @@ +//===- llvm/ADT/PackedVector.h - Packed values vector -----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the PackedVector class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_PACKEDVECTOR_H +#define LLVM_ADT_PACKEDVECTOR_H + +#include "llvm/ADT/BitVector.h" +#include <cassert> +#include <limits> + +namespace llvm { + +template <typename T, unsigned BitNum, typename BitVectorTy, bool isSigned> +class PackedVectorBase; + +// This won't be necessary if we can specialize members without specializing +// the parent template. +template <typename T, unsigned BitNum, typename BitVectorTy> +class PackedVectorBase<T, BitNum, BitVectorTy, false> { +protected: + static T getValue(const BitVectorTy &Bits, unsigned Idx) { + T val = T(); + for (unsigned i = 0; i != BitNum; ++i) + val = T(val | ((Bits[(Idx << (BitNum-1)) + i] ? 1UL : 0UL) << i)); + return val; + } + + static void setValue(BitVectorTy &Bits, unsigned Idx, T val) { + assert((val >> BitNum) == 0 && "value is too big"); + for (unsigned i = 0; i != BitNum; ++i) + Bits[(Idx << (BitNum-1)) + i] = val & (T(1) << i); + } +}; + +template <typename T, unsigned BitNum, typename BitVectorTy> +class PackedVectorBase<T, BitNum, BitVectorTy, true> { +protected: + static T getValue(const BitVectorTy &Bits, unsigned Idx) { + T val = T(); + for (unsigned i = 0; i != BitNum-1; ++i) + val = T(val | ((Bits[(Idx << (BitNum-1)) + i] ? 1UL : 0UL) << i)); + if (Bits[(Idx << (BitNum-1)) + BitNum-1]) + val = ~val; + return val; + } + + static void setValue(BitVectorTy &Bits, unsigned Idx, T val) { + if (val < 0) { + val = ~val; + Bits.set((Idx << (BitNum-1)) + BitNum-1); + } + assert((val >> (BitNum-1)) == 0 && "value is too big"); + for (unsigned i = 0; i != BitNum-1; ++i) + Bits[(Idx << (BitNum-1)) + i] = val & (T(1) << i); + } +}; + +/// Store a vector of values using a specific number of bits for each +/// value. Both signed and unsigned types can be used, e.g +/// @code +/// PackedVector<signed, 2> vec; +/// @endcode +/// will create a vector accepting values -2, -1, 0, 1. Any other value will hit +/// an assertion. +template <typename T, unsigned BitNum, typename BitVectorTy = BitVector> +class PackedVector : public PackedVectorBase<T, BitNum, BitVectorTy, + std::numeric_limits<T>::is_signed> { + BitVectorTy Bits; + using base = PackedVectorBase<T, BitNum, BitVectorTy, + std::numeric_limits<T>::is_signed>; + +public: + class reference { + PackedVector &Vec; + const unsigned Idx; + + public: + reference() = delete; + reference(PackedVector &vec, unsigned idx) : Vec(vec), Idx(idx) {} + + reference &operator=(T val) { + Vec.setValue(Vec.Bits, Idx, val); + return *this; + } + + operator T() const { + return Vec.getValue(Vec.Bits, Idx); + } + }; + + PackedVector() = default; + explicit PackedVector(unsigned size) : Bits(size << (BitNum-1)) {} + + bool empty() const { return Bits.empty(); } + + unsigned size() const { return Bits.size() >> (BitNum - 1); } + + void clear() { Bits.clear(); } + + void resize(unsigned N) { Bits.resize(N << (BitNum - 1)); } + + void reserve(unsigned N) { Bits.reserve(N << (BitNum-1)); } + + PackedVector &reset() { + Bits.reset(); + return *this; + } + + void push_back(T val) { + resize(size()+1); + (*this)[size()-1] = val; + } + + reference operator[](unsigned Idx) { + return reference(*this, Idx); + } + + T operator[](unsigned Idx) const { + return base::getValue(Bits, Idx); + } + + bool operator==(const PackedVector &RHS) const { + return Bits == RHS.Bits; + } + + bool operator!=(const PackedVector &RHS) const { + return Bits != RHS.Bits; + } + + PackedVector &operator|=(const PackedVector &RHS) { + Bits |= RHS.Bits; + return *this; + } +}; + +// Leave BitNum=0 undefined. +template <typename T> class PackedVector<T, 0>; + +} // end namespace llvm + +#endif // LLVM_ADT_PACKEDVECTOR_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/PointerEmbeddedInt.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/PointerEmbeddedInt.h new file mode 100644 index 0000000..3eb6edb --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/PointerEmbeddedInt.h
@@ -0,0 +1,119 @@ +//===- llvm/ADT/PointerEmbeddedInt.h ----------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_POINTEREMBEDDEDINT_H +#define LLVM_ADT_POINTEREMBEDDEDINT_H + +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/PointerLikeTypeTraits.h" +#include <cassert> +#include <climits> +#include <cstdint> +#include <type_traits> + +namespace llvm { + +/// Utility to embed an integer into a pointer-like type. This is specifically +/// intended to allow embedding integers where fewer bits are required than +/// exist in a pointer, and the integer can participate in abstractions along +/// side other pointer-like types. For example it can be placed into a \c +/// PointerSumType or \c PointerUnion. +/// +/// Note that much like pointers, an integer value of zero has special utility +/// due to boolean conversions. For example, a non-null value can be tested for +/// in the above abstractions without testing the particular active member. +/// Also, the default constructed value zero initializes the integer. +template <typename IntT, int Bits = sizeof(IntT) * CHAR_BIT> +class PointerEmbeddedInt { + uintptr_t Value = 0; + + // 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!"); + + enum : uintptr_t { + // We shift as many zeros into the value as we can while preserving the + // number of bits desired for the integer. + Shift = sizeof(uintptr_t) * CHAR_BIT - Bits, + + // We also want to be able to mask out the preserved bits for asserts. + Mask = static_cast<uintptr_t>(-1) << Bits + }; + + struct RawValueTag { + explicit RawValueTag() = default; + }; + + friend struct PointerLikeTypeTraits<PointerEmbeddedInt>; + + explicit PointerEmbeddedInt(uintptr_t Value, RawValueTag) : Value(Value) {} + +public: + PointerEmbeddedInt() = default; + + PointerEmbeddedInt(IntT I) { *this = I; } + + PointerEmbeddedInt &operator=(IntT I) { + assert((std::is_signed<IntT>::value ? isInt<Bits>(I) : isUInt<Bits>(I)) && + "Integer has bits outside those preserved!"); + Value = static_cast<uintptr_t>(I) << Shift; + return *this; + } + + // Note that this implicit conversion additionally allows all of the basic + // comparison operators to work transparently, etc. + 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 +// types. +template <typename IntT, int Bits> +struct PointerLikeTypeTraits<PointerEmbeddedInt<IntT, Bits>> { + using T = PointerEmbeddedInt<IntT, Bits>; + + static inline void *getAsVoidPointer(const T &P) { + return reinterpret_cast<void *>(P.Value); + } + + static inline T getFromVoidPointer(void *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), typename T::RawValueTag()); + } + + enum { NumLowBitsAvailable = T::Shift }; +}; + +// Teach DenseMap how to use PointerEmbeddedInt objects as keys if the Int type +// itself can be a key. +template <typename IntT, int Bits> +struct DenseMapInfo<PointerEmbeddedInt<IntT, Bits>> { + using T = PointerEmbeddedInt<IntT, Bits>; + using IntInfo = DenseMapInfo<IntT>; + + static inline T getEmptyKey() { return IntInfo::getEmptyKey(); } + static inline T getTombstoneKey() { return IntInfo::getTombstoneKey(); } + + static unsigned getHashValue(const T &Arg) { + return IntInfo::getHashValue(Arg); + } + + static bool isEqual(const T &LHS, const T &RHS) { return LHS == RHS; } +}; + +} // end namespace llvm + +#endif // LLVM_ADT_POINTEREMBEDDEDINT_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/PointerIntPair.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/PointerIntPair.h new file mode 100644 index 0000000..fa6bf15 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/PointerIntPair.h
@@ -0,0 +1,243 @@ +//===- llvm/ADT/PointerIntPair.h - Pair for pointer and int -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the PointerIntPair class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_POINTERINTPAIR_H +#define LLVM_ADT_POINTERINTPAIR_H + +#include "llvm/Support/Compiler.h" +#include "llvm/Support/PointerLikeTypeTraits.h" +#include "llvm/Support/type_traits.h" +#include <cassert> +#include <cstdint> +#include <limits> + +namespace llvm { + +template <typename T> struct DenseMapInfo; +template <typename PointerT, unsigned IntBits, typename PtrTraits> +struct PointerIntPairInfo; + +/// PointerIntPair - This class implements a pair of a pointer and small +/// integer. It is designed to represent this in the space required by one +/// pointer by bitmangling the integer into the low part of the pointer. This +/// can only be done for small integers: typically up to 3 bits, but it depends +/// on the number of bits available according to PointerLikeTypeTraits for the +/// type. +/// +/// Note that PointerIntPair always puts the IntVal part in the highest bits +/// possible. For example, PointerIntPair<void*, 1, bool> will put the bit for +/// the bool into bit #2, not bit #0, which allows the low two bits to be used +/// for something else. For example, this allows: +/// PointerIntPair<PointerIntPair<void*, 1, bool>, 1, bool> +/// ... and the two bools will land in different bits. +template <typename PointerTy, unsigned IntBits, typename IntType = unsigned, + typename PtrTraits = PointerLikeTypeTraits<PointerTy>, + typename Info = PointerIntPairInfo<PointerTy, IntBits, PtrTraits>> +class PointerIntPair { + // Used by MSVC visualizer and generally helpful for debugging/visualizing. + using InfoTy = Info; + intptr_t Value = 0; + +public: + constexpr PointerIntPair() = default; + + PointerIntPair(PointerTy PtrVal, IntType IntVal) { + setPointerAndInt(PtrVal, IntVal); + } + + explicit PointerIntPair(PointerTy PtrVal) { initWithPointer(PtrVal); } + + PointerTy getPointer() const { return Info::getPointer(Value); } + + IntType getInt() const { return (IntType)Info::getInt(Value); } + + void setPointer(PointerTy PtrVal) LLVM_LVALUE_FUNCTION { + Value = Info::updatePointer(Value, PtrVal); + } + + void setInt(IntType IntVal) LLVM_LVALUE_FUNCTION { + Value = Info::updateInt(Value, static_cast<intptr_t>(IntVal)); + } + + void initWithPointer(PointerTy PtrVal) LLVM_LVALUE_FUNCTION { + Value = Info::updatePointer(0, PtrVal); + } + + void setPointerAndInt(PointerTy PtrVal, IntType IntVal) LLVM_LVALUE_FUNCTION { + Value = Info::updateInt(Info::updatePointer(0, PtrVal), + static_cast<intptr_t>(IntVal)); + } + + PointerTy const *getAddrOfPointer() const { + return const_cast<PointerIntPair *>(this)->getAddrOfPointer(); + } + + PointerTy *getAddrOfPointer() { + assert(Value == reinterpret_cast<intptr_t>(getPointer()) && + "Can only return the address if IntBits is cleared and " + "PtrTraits doesn't change the pointer"); + return reinterpret_cast<PointerTy *>(&Value); + } + + void *getOpaqueValue() const { return reinterpret_cast<void *>(Value); } + + void setFromOpaqueValue(void *Val) LLVM_LVALUE_FUNCTION { + Value = reinterpret_cast<intptr_t>(Val); + } + + static PointerIntPair getFromOpaqueValue(void *V) { + PointerIntPair P; + P.setFromOpaqueValue(V); + return P; + } + + // Allow PointerIntPairs to be created from const void * if and only if the + // pointer type could be created from a const void *. + static PointerIntPair getFromOpaqueValue(const void *V) { + (void)PtrTraits::getFromVoidPointer(V); + return getFromOpaqueValue(const_cast<void *>(V)); + } + + bool operator==(const PointerIntPair &RHS) const { + return Value == RHS.Value; + } + + bool operator!=(const PointerIntPair &RHS) const { + return Value != RHS.Value; + } + + bool operator<(const PointerIntPair &RHS) const { return Value < RHS.Value; } + bool operator>(const PointerIntPair &RHS) const { return Value > RHS.Value; } + + bool operator<=(const PointerIntPair &RHS) const { + return Value <= RHS.Value; + } + + bool operator>=(const PointerIntPair &RHS) const { + return Value >= RHS.Value; + } +}; + +// Specialize is_trivially_copyable to avoid limitation of llvm::is_trivially_copyable +// when compiled with gcc 4.9. +template <typename PointerTy, unsigned IntBits, typename IntType, + typename PtrTraits, + typename Info> +struct is_trivially_copyable<PointerIntPair<PointerTy, IntBits, IntType, PtrTraits, Info>> : std::true_type { +#ifdef HAVE_STD_IS_TRIVIALLY_COPYABLE + static_assert(std::is_trivially_copyable<PointerIntPair<PointerTy, IntBits, IntType, PtrTraits, Info>>::value, + "inconsistent behavior between llvm:: and std:: implementation of is_trivially_copyable"); +#endif +}; + + +template <typename PointerT, unsigned IntBits, typename PtrTraits> +struct PointerIntPairInfo { + static_assert(PtrTraits::NumLowBitsAvailable < + std::numeric_limits<uintptr_t>::digits, + "cannot use a pointer type that has all bits free"); + static_assert(IntBits <= PtrTraits::NumLowBitsAvailable, + "PointerIntPair with integer size too large for pointer"); + enum : uintptr_t { + /// PointerBitMask - The bits that come from the pointer. + PointerBitMask = + ~(uintptr_t)(((intptr_t)1 << PtrTraits::NumLowBitsAvailable) - 1), + + /// IntShift - The number of low bits that we reserve for other uses, and + /// keep zero. + IntShift = (uintptr_t)PtrTraits::NumLowBitsAvailable - IntBits, + + /// IntMask - This is the unshifted mask for valid bits of the int type. + IntMask = (uintptr_t)(((intptr_t)1 << IntBits) - 1), + + // ShiftedIntMask - This is the bits for the integer shifted in place. + ShiftedIntMask = (uintptr_t)(IntMask << IntShift) + }; + + static PointerT getPointer(intptr_t Value) { + return PtrTraits::getFromVoidPointer( + reinterpret_cast<void *>(Value & PointerBitMask)); + } + + static intptr_t getInt(intptr_t Value) { + return (Value >> IntShift) & IntMask; + } + + static intptr_t updatePointer(intptr_t OrigValue, PointerT Ptr) { + intptr_t PtrWord = + reinterpret_cast<intptr_t>(PtrTraits::getAsVoidPointer(Ptr)); + assert((PtrWord & ~PointerBitMask) == 0 && + "Pointer is not sufficiently aligned"); + // Preserve all low bits, just update the pointer. + return PtrWord | (OrigValue & ~PointerBitMask); + } + + static intptr_t updateInt(intptr_t OrigValue, intptr_t Int) { + intptr_t IntWord = static_cast<intptr_t>(Int); + assert((IntWord & ~IntMask) == 0 && "Integer too large for field"); + + // Preserve all bits other than the ones we are updating. + return (OrigValue & ~ShiftedIntMask) | IntWord << IntShift; + } +}; + +// Provide specialization of DenseMapInfo for PointerIntPair. +template <typename PointerTy, unsigned IntBits, typename IntType> +struct DenseMapInfo<PointerIntPair<PointerTy, IntBits, IntType>> { + using Ty = PointerIntPair<PointerTy, IntBits, IntType>; + + static Ty getEmptyKey() { + uintptr_t Val = static_cast<uintptr_t>(-1); + Val <<= PointerLikeTypeTraits<Ty>::NumLowBitsAvailable; + return Ty::getFromOpaqueValue(reinterpret_cast<void *>(Val)); + } + + static Ty getTombstoneKey() { + uintptr_t Val = static_cast<uintptr_t>(-2); + Val <<= PointerLikeTypeTraits<PointerTy>::NumLowBitsAvailable; + return Ty::getFromOpaqueValue(reinterpret_cast<void *>(Val)); + } + + static unsigned getHashValue(Ty V) { + uintptr_t IV = reinterpret_cast<uintptr_t>(V.getOpaqueValue()); + return unsigned(IV) ^ unsigned(IV >> 9); + } + + static bool isEqual(const Ty &LHS, const Ty &RHS) { return LHS == RHS; } +}; + +// Teach SmallPtrSet that PointerIntPair is "basically a pointer". +template <typename PointerTy, unsigned IntBits, typename IntType, + typename PtrTraits> +struct PointerLikeTypeTraits< + PointerIntPair<PointerTy, IntBits, IntType, PtrTraits>> { + static inline void * + getAsVoidPointer(const PointerIntPair<PointerTy, IntBits, IntType> &P) { + return P.getOpaqueValue(); + } + + static inline PointerIntPair<PointerTy, IntBits, IntType> + getFromVoidPointer(void *P) { + return PointerIntPair<PointerTy, IntBits, IntType>::getFromOpaqueValue(P); + } + + static inline PointerIntPair<PointerTy, IntBits, IntType> + getFromVoidPointer(const void *P) { + return PointerIntPair<PointerTy, IntBits, IntType>::getFromOpaqueValue(P); + } + + enum { NumLowBitsAvailable = PtrTraits::NumLowBitsAvailable - IntBits }; +}; + +} // end namespace llvm + +#endif // LLVM_ADT_POINTERINTPAIR_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/PointerSumType.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/PointerSumType.h new file mode 100644 index 0000000..d467f83 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/PointerSumType.h
@@ -0,0 +1,294 @@ +//===- llvm/ADT/PointerSumType.h --------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_POINTERSUMTYPE_H +#define LLVM_ADT_POINTERSUMTYPE_H + +#include "llvm/ADT/bit.h" +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/Support/PointerLikeTypeTraits.h" +#include <cassert> +#include <cstdint> +#include <type_traits> + +namespace llvm { + +/// A compile time pair of an integer tag and the pointer-like type which it +/// indexes within a sum type. Also allows the user to specify a particular +/// traits class for pointer types with custom behavior such as over-aligned +/// allocation. +template <uintptr_t N, typename PointerArgT, + typename TraitsArgT = PointerLikeTypeTraits<PointerArgT>> +struct PointerSumTypeMember { + enum { Tag = N }; + using PointerT = PointerArgT; + using TraitsT = TraitsArgT; +}; + +namespace detail { + +template <typename TagT, typename... MemberTs> struct PointerSumTypeHelper; + +} // end namespace detail + +/// A sum type over pointer-like types. +/// +/// This is a normal tagged union across pointer-like types that uses the low +/// bits of the pointers to store the tag. +/// +/// Each member of the sum type is specified by passing a \c +/// PointerSumTypeMember specialization in the variadic member argument list. +/// This allows the user to control the particular tag value associated with +/// a particular type, use the same type for multiple different tags, and +/// customize the pointer-like traits used for a particular member. Note that +/// these *must* be specializations of \c PointerSumTypeMember, no other type +/// will suffice, even if it provides a compatible interface. +/// +/// This type implements all of the comparison operators and even hash table +/// support by comparing the underlying storage of the pointer values. It +/// doesn't support delegating to particular members for comparisons. +/// +/// It also default constructs to a zero tag with a null pointer, whatever that +/// would be. This means that the zero value for the tag type is significant +/// and may be desirable to set to a state that is particularly desirable to +/// default construct. +/// +/// Having a supported zero-valued tag also enables getting the address of a +/// pointer stored with that tag provided it is stored in its natural bit +/// representation. This works because in the case of a zero-valued tag, the +/// pointer's value is directly stored into this object and we can expose the +/// address of that internal storage. This is especially useful when building an +/// `ArrayRef` of a single pointer stored in a sum type. +/// +/// There is no support for constructing or accessing with a dynamic tag as +/// that would fundamentally violate the type safety provided by the sum type. +template <typename TagT, typename... MemberTs> class PointerSumType { + using HelperT = detail::PointerSumTypeHelper<TagT, MemberTs...>; + + // We keep both the raw value and the min tag value's pointer in a union. When + // the minimum tag value is zero, this allows code below to cleanly expose the + // address of the zero-tag pointer instead of just the zero-tag pointer + // itself. This is especially useful when building `ArrayRef`s out of a single + // pointer. However, we have to carefully access the union due to the active + // member potentially changing. When we *store* a new value, we directly + // access the union to allow us to store using the obvious types. However, + // when we *read* a value, we copy the underlying storage out to avoid relying + // on one member or the other being active. + union StorageT { + // Ensure we get a null default constructed value. We don't use a member + // initializer because some compilers seem to not implement those correctly + // for a union. + StorageT() : Value(0) {} + + uintptr_t Value; + + typename HelperT::template Lookup<HelperT::MinTag>::PointerT MinTagPointer; + }; + + StorageT Storage; + +public: + constexpr PointerSumType() = default; + + /// A typed setter to a given tagged member of the sum type. + template <TagT N> + void set(typename HelperT::template Lookup<N>::PointerT Pointer) { + void *V = HelperT::template Lookup<N>::TraitsT::getAsVoidPointer(Pointer); + assert((reinterpret_cast<uintptr_t>(V) & HelperT::TagMask) == 0 && + "Pointer is insufficiently aligned to store the discriminant!"); + Storage.Value = reinterpret_cast<uintptr_t>(V) | N; + } + + /// A typed constructor for a specific tagged member of the sum type. + template <TagT N> + static PointerSumType + create(typename HelperT::template Lookup<N>::PointerT Pointer) { + PointerSumType Result; + Result.set<N>(Pointer); + return Result; + } + + /// Clear the value to null with the min tag type. + void clear() { set<HelperT::MinTag>(nullptr); } + + TagT getTag() const { + return static_cast<TagT>(getOpaqueValue() & HelperT::TagMask); + } + + template <TagT N> bool is() const { return N == getTag(); } + + template <TagT N> typename HelperT::template Lookup<N>::PointerT get() const { + void *P = is<N>() ? getVoidPtr() : nullptr; + return HelperT::template Lookup<N>::TraitsT::getFromVoidPointer(P); + } + + template <TagT N> + typename HelperT::template Lookup<N>::PointerT cast() const { + assert(is<N>() && "This instance has a different active member."); + return HelperT::template Lookup<N>::TraitsT::getFromVoidPointer( + getVoidPtr()); + } + + /// If the tag is zero and the pointer's value isn't changed when being + /// stored, get the address of the stored value type-punned to the zero-tag's + /// pointer type. + typename HelperT::template Lookup<HelperT::MinTag>::PointerT const * + getAddrOfZeroTagPointer() const { + return const_cast<PointerSumType *>(this)->getAddrOfZeroTagPointer(); + } + + /// If the tag is zero and the pointer's value isn't changed when being + /// stored, get the address of the stored value type-punned to the zero-tag's + /// pointer type. + typename HelperT::template Lookup<HelperT::MinTag>::PointerT * + getAddrOfZeroTagPointer() { + static_assert(HelperT::MinTag == 0, "Non-zero minimum tag value!"); + assert(is<HelperT::MinTag>() && "The active tag is not zero!"); + // Store the initial value of the pointer when read out of our storage. + auto InitialPtr = get<HelperT::MinTag>(); + // Now update the active member of the union to be the actual pointer-typed + // member so that accessing it indirectly through the returned address is + // valid. + Storage.MinTagPointer = InitialPtr; + // Finally, validate that this was a no-op as expected by reading it back + // out using the same underlying-storage read as above. + assert(InitialPtr == get<HelperT::MinTag>() && + "Switching to typed storage changed the pointer returned!"); + // Now we can correctly return an address to typed storage. + return &Storage.MinTagPointer; + } + + explicit operator bool() const { + return getOpaqueValue() & HelperT::PointerMask; + } + bool operator==(const PointerSumType &R) const { + return getOpaqueValue() == R.getOpaqueValue(); + } + bool operator!=(const PointerSumType &R) const { + return getOpaqueValue() != R.getOpaqueValue(); + } + bool operator<(const PointerSumType &R) const { + return getOpaqueValue() < R.getOpaqueValue(); + } + bool operator>(const PointerSumType &R) const { + return getOpaqueValue() > R.getOpaqueValue(); + } + bool operator<=(const PointerSumType &R) const { + return getOpaqueValue() <= R.getOpaqueValue(); + } + bool operator>=(const PointerSumType &R) const { + return getOpaqueValue() >= R.getOpaqueValue(); + } + + uintptr_t getOpaqueValue() const { + // Read the underlying storage of the union, regardless of the active + // member. + return bit_cast<uintptr_t>(Storage); + } + +protected: + void *getVoidPtr() const { + return reinterpret_cast<void *>(getOpaqueValue() & HelperT::PointerMask); + } +}; + +namespace detail { + +/// A helper template for implementing \c PointerSumType. It provides fast +/// compile-time lookup of the member from a particular tag value, along with +/// useful constants and compile time checking infrastructure.. +template <typename TagT, typename... MemberTs> +struct PointerSumTypeHelper : MemberTs... { + // First we use a trick to allow quickly looking up information about + // a particular member of the sum type. This works because we arranged to + // have this type derive from all of the member type templates. We can select + // the matching member for a tag using type deduction during overload + // resolution. + template <TagT N, typename PointerT, typename TraitsT> + static PointerSumTypeMember<N, PointerT, TraitsT> + LookupOverload(PointerSumTypeMember<N, PointerT, TraitsT> *); + template <TagT N> static void LookupOverload(...); + template <TagT N> struct Lookup { + // Compute a particular member type by resolving the lookup helper ovorload. + using MemberT = decltype( + LookupOverload<N>(static_cast<PointerSumTypeHelper *>(nullptr))); + + /// The Nth member's pointer type. + using PointerT = typename MemberT::PointerT; + + /// The Nth member's traits type. + using TraitsT = typename MemberT::TraitsT; + }; + + // Next we need to compute the number of bits available for the discriminant + // by taking the min of the bits available for each member. Much of this + // would be amazingly easier with good constexpr support. + template <uintptr_t V, uintptr_t... Vs> + struct Min : std::integral_constant< + uintptr_t, (V < Min<Vs...>::value ? V : Min<Vs...>::value)> { + }; + template <uintptr_t V> + struct Min<V> : std::integral_constant<uintptr_t, V> {}; + enum { NumTagBits = Min<MemberTs::TraitsT::NumLowBitsAvailable...>::value }; + + // Also compute the smallest discriminant and various masks for convenience. + constexpr static TagT MinTag = + static_cast<TagT>(Min<MemberTs::Tag...>::value); + enum : uint64_t { + PointerMask = static_cast<uint64_t>(-1) << NumTagBits, + TagMask = ~PointerMask + }; + + // Finally we need a recursive template to do static checks of each + // member. + template <typename MemberT, typename... InnerMemberTs> + struct Checker : Checker<InnerMemberTs...> { + static_assert(MemberT::Tag < (1 << NumTagBits), + "This discriminant value requires too many bits!"); + }; + template <typename MemberT> struct Checker<MemberT> : std::true_type { + static_assert(MemberT::Tag < (1 << NumTagBits), + "This discriminant value requires too many bits!"); + }; + static_assert(Checker<MemberTs...>::value, + "Each member must pass the checker."); +}; + +} // end namespace detail + +// Teach DenseMap how to use PointerSumTypes as keys. +template <typename TagT, typename... MemberTs> +struct DenseMapInfo<PointerSumType<TagT, MemberTs...>> { + using SumType = PointerSumType<TagT, MemberTs...>; + using HelperT = detail::PointerSumTypeHelper<TagT, MemberTs...>; + enum { SomeTag = HelperT::MinTag }; + using SomePointerT = + typename HelperT::template Lookup<HelperT::MinTag>::PointerT; + using SomePointerInfo = DenseMapInfo<SomePointerT>; + + static inline SumType getEmptyKey() { + return SumType::create<SomeTag>(SomePointerInfo::getEmptyKey()); + } + + static inline SumType getTombstoneKey() { + return SumType::create<SomeTag>(SomePointerInfo::getTombstoneKey()); + } + + static unsigned getHashValue(const SumType &Arg) { + uintptr_t OpaqueValue = Arg.getOpaqueValue(); + return DenseMapInfo<uintptr_t>::getHashValue(OpaqueValue); + } + + static bool isEqual(const SumType &LHS, const SumType &RHS) { + return LHS == RHS; + } +}; + +} // end namespace llvm + +#endif // LLVM_ADT_POINTERSUMTYPE_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/PointerUnion.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/PointerUnion.h new file mode 100644 index 0000000..40b7b00 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/PointerUnion.h
@@ -0,0 +1,299 @@ +//===- llvm/ADT/PointerUnion.h - Discriminated Union of 2 Ptrs --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the PointerUnion class, which is a discriminated union of +// pointer types. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_POINTERUNION_H +#define LLVM_ADT_POINTERUNION_H + +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/Support/PointerLikeTypeTraits.h" +#include <cassert> +#include <cstddef> +#include <cstdint> + +namespace llvm { + +template <typename T> struct PointerUnionTypeSelectorReturn { + using Return = T; +}; + +/// Get a type based on whether two types are the same or not. +/// +/// For: +/// +/// \code +/// using Ret = typename PointerUnionTypeSelector<T1, T2, EQ, NE>::Return; +/// \endcode +/// +/// Ret will be EQ type if T1 is same as T2 or NE type otherwise. +template <typename T1, typename T2, typename RET_EQ, typename RET_NE> +struct PointerUnionTypeSelector { + using Return = typename PointerUnionTypeSelectorReturn<RET_NE>::Return; +}; + +template <typename T, typename RET_EQ, typename RET_NE> +struct PointerUnionTypeSelector<T, T, RET_EQ, RET_NE> { + using Return = typename PointerUnionTypeSelectorReturn<RET_EQ>::Return; +}; + +template <typename T1, typename T2, typename RET_EQ, typename RET_NE> +struct PointerUnionTypeSelectorReturn< + PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE>> { + using Return = + typename PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE>::Return; +}; + +namespace pointer_union_detail { + /// Determine the number of bits required to store integers with values < n. + /// This is ceil(log2(n)). + constexpr int bitsRequired(unsigned n) { + return n > 1 ? 1 + bitsRequired((n + 1) / 2) : 0; + } + + template <typename... Ts> constexpr int lowBitsAvailable() { + return std::min<int>({PointerLikeTypeTraits<Ts>::NumLowBitsAvailable...}); + } + + /// Find the index of a type in a list of types. TypeIndex<T, Us...>::Index + /// is the index of T in Us, or sizeof...(Us) if T does not appear in the + /// list. + template <typename T, typename ...Us> struct TypeIndex; + template <typename T, typename ...Us> struct TypeIndex<T, T, Us...> { + static constexpr int Index = 0; + }; + template <typename T, typename U, typename... Us> + struct TypeIndex<T, U, Us...> { + static constexpr int Index = 1 + TypeIndex<T, Us...>::Index; + }; + template <typename T> struct TypeIndex<T> { + static constexpr int Index = 0; + }; + + /// Find the first type in a list of types. + template <typename T, typename...> struct GetFirstType { + using type = T; + }; + + /// Provide PointerLikeTypeTraits for void* that is used by PointerUnion + /// for the template arguments. + template <typename ...PTs> class PointerUnionUIntTraits { + public: + static inline void *getAsVoidPointer(void *P) { return P; } + static inline void *getFromVoidPointer(void *P) { return P; } + static constexpr int NumLowBitsAvailable = lowBitsAvailable<PTs...>(); + }; + + /// Implement assignment in terms of construction. + template <typename Derived, typename T> struct AssignableFrom { + Derived &operator=(T t) { + return static_cast<Derived &>(*this) = Derived(t); + } + }; + + template <typename Derived, typename ValTy, int I, typename ...Types> + class PointerUnionMembers; + + template <typename Derived, typename ValTy, int I> + class PointerUnionMembers<Derived, ValTy, I> { + protected: + ValTy Val; + PointerUnionMembers() = default; + PointerUnionMembers(ValTy Val) : Val(Val) {} + + friend struct PointerLikeTypeTraits<Derived>; + }; + + template <typename Derived, typename ValTy, int I, typename Type, + typename ...Types> + class PointerUnionMembers<Derived, ValTy, I, Type, Types...> + : public PointerUnionMembers<Derived, ValTy, I + 1, Types...> { + using Base = PointerUnionMembers<Derived, ValTy, I + 1, Types...>; + public: + using Base::Base; + PointerUnionMembers() = default; + PointerUnionMembers(Type V) + : Base(ValTy(const_cast<void *>( + PointerLikeTypeTraits<Type>::getAsVoidPointer(V)), + I)) {} + + using Base::operator=; + Derived &operator=(Type V) { + this->Val = ValTy( + const_cast<void *>(PointerLikeTypeTraits<Type>::getAsVoidPointer(V)), + I); + return static_cast<Derived &>(*this); + }; + }; +} + +/// A discriminated union of two or more pointer types, with the discriminator +/// in the low bit of the pointer. +/// +/// This implementation is extremely efficient in space due to leveraging the +/// low bits of the pointer, while exposing a natural and type-safe API. +/// +/// Common use patterns would be something like this: +/// PointerUnion<int*, float*> P; +/// P = (int*)0; +/// printf("%d %d", P.is<int*>(), P.is<float*>()); // prints "1 0" +/// X = P.get<int*>(); // ok. +/// Y = P.get<float*>(); // runtime assertion failure. +/// Z = P.get<double*>(); // compile time failure. +/// P = (float*)0; +/// Y = P.get<float*>(); // ok. +/// X = P.get<int*>(); // runtime assertion failure. +template <typename... PTs> +class PointerUnion + : public pointer_union_detail::PointerUnionMembers< + PointerUnion<PTs...>, + PointerIntPair< + void *, pointer_union_detail::bitsRequired(sizeof...(PTs)), int, + pointer_union_detail::PointerUnionUIntTraits<PTs...>>, + 0, PTs...> { + // The first type is special because we want to directly cast a pointer to a + // default-initialized union to a pointer to the first type. But we don't + // want PointerUnion to be a 'template <typename First, typename ...Rest>' + // because it's much more convenient to have a name for the whole pack. So + // split off the first type here. + using First = typename pointer_union_detail::GetFirstType<PTs...>::type; + using Base = typename PointerUnion::PointerUnionMembers; + +public: + PointerUnion() = default; + + PointerUnion(std::nullptr_t) : PointerUnion() {} + using Base::Base; + + /// Test if the pointer held in the union is null, regardless of + /// which type it is. + bool isNull() const { return !this->Val.getPointer(); } + + explicit operator bool() const { return !isNull(); } + + /// Test if the Union currently holds the type matching T. + template <typename T> int is() const { + constexpr int Index = pointer_union_detail::TypeIndex<T, PTs...>::Index; + static_assert(Index < sizeof...(PTs), + "PointerUnion::is<T> given type not in the union"); + return this->Val.getInt() == Index; + } + + /// Returns the value of the specified pointer type. + /// + /// If the specified pointer type is incorrect, assert. + template <typename T> T get() const { + assert(is<T>() && "Invalid accessor called"); + return PointerLikeTypeTraits<T>::getFromVoidPointer(this->Val.getPointer()); + } + + /// Returns the current pointer if it is of the specified pointer type, + /// otherwises returns null. + template <typename T> T dyn_cast() const { + if (is<T>()) + return get<T>(); + return T(); + } + + /// If the union is set to the first pointer type get an address pointing to + /// it. + First const *getAddrOfPtr1() const { + return const_cast<PointerUnion *>(this)->getAddrOfPtr1(); + } + + /// If the union is set to the first pointer type get an address pointing to + /// it. + First *getAddrOfPtr1() { + assert(is<First>() && "Val is not the first pointer"); + assert( + PointerLikeTypeTraits<First>::getAsVoidPointer(get<First>()) == + this->Val.getPointer() && + "Can't get the address because PointerLikeTypeTraits changes the ptr"); + return const_cast<First *>( + reinterpret_cast<const First *>(this->Val.getAddrOfPointer())); + } + + /// Assignment from nullptr which just clears the union. + const PointerUnion &operator=(std::nullptr_t) { + this->Val.initWithPointer(nullptr); + return *this; + } + + /// Assignment from elements of the union. + using Base::operator=; + + void *getOpaqueValue() const { return this->Val.getOpaqueValue(); } + static inline PointerUnion getFromOpaqueValue(void *VP) { + PointerUnion V; + V.Val = decltype(V.Val)::getFromOpaqueValue(VP); + return V; + } +}; + +template <typename ...PTs> +bool operator==(PointerUnion<PTs...> lhs, PointerUnion<PTs...> rhs) { + return lhs.getOpaqueValue() == rhs.getOpaqueValue(); +} + +template <typename ...PTs> +bool operator!=(PointerUnion<PTs...> lhs, PointerUnion<PTs...> rhs) { + return lhs.getOpaqueValue() != rhs.getOpaqueValue(); +} + +template <typename ...PTs> +bool operator<(PointerUnion<PTs...> lhs, PointerUnion<PTs...> rhs) { + return lhs.getOpaqueValue() < rhs.getOpaqueValue(); +} + +// Teach SmallPtrSet that PointerUnion is "basically a pointer", that has +// # low bits available = min(PT1bits,PT2bits)-1. +template <typename ...PTs> +struct PointerLikeTypeTraits<PointerUnion<PTs...>> { + static inline void *getAsVoidPointer(const PointerUnion<PTs...> &P) { + return P.getOpaqueValue(); + } + + static inline PointerUnion<PTs...> getFromVoidPointer(void *P) { + return PointerUnion<PTs...>::getFromOpaqueValue(P); + } + + // The number of bits available are the min of the pointer types minus the + // bits needed for the discriminator. + static constexpr int NumLowBitsAvailable = PointerLikeTypeTraits<decltype( + PointerUnion<PTs...>::Val)>::NumLowBitsAvailable; +}; + +// Teach DenseMap how to use PointerUnions as keys. +template <typename ...PTs> struct DenseMapInfo<PointerUnion<PTs...>> { + using Union = PointerUnion<PTs...>; + using FirstInfo = + DenseMapInfo<typename pointer_union_detail::GetFirstType<PTs...>::type>; + + static inline Union getEmptyKey() { return Union(FirstInfo::getEmptyKey()); } + + static inline Union getTombstoneKey() { + return Union(FirstInfo::getTombstoneKey()); + } + + static unsigned getHashValue(const Union &UnionVal) { + intptr_t key = (intptr_t)UnionVal.getOpaqueValue(); + return DenseMapInfo<intptr_t>::getHashValue(key); + } + + static bool isEqual(const Union &LHS, const Union &RHS) { + return LHS == RHS; + } +}; + +} // end namespace llvm + +#endif // LLVM_ADT_POINTERUNION_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/PostOrderIterator.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/PostOrderIterator.h new file mode 100644 index 0000000..2fe7447 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/PostOrderIterator.h
@@ -0,0 +1,311 @@ +//===- llvm/ADT/PostOrderIterator.h - PostOrder iterator --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file builds on the ADT/GraphTraits.h file to build a generic graph +// post order iterator. This should work over any graph type that has a +// GraphTraits specialization. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_POSTORDERITERATOR_H +#define LLVM_ADT_POSTORDERITERATOR_H + +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/iterator_range.h" +#include <iterator> +#include <set> +#include <utility> +#include <vector> + +namespace llvm { + +// The po_iterator_storage template provides access to the set of already +// visited nodes during the po_iterator's depth-first traversal. +// +// The default implementation simply contains a set of visited nodes, while +// the External=true version uses a reference to an external set. +// +// It is possible to prune the depth-first traversal in several ways: +// +// - When providing an external set that already contains some graph nodes, +// those nodes won't be visited again. This is useful for restarting a +// post-order traversal on a graph with nodes that aren't dominated by a +// single node. +// +// - By providing a custom SetType class, unwanted graph nodes can be excluded +// by having the insert() function return false. This could for example +// confine a CFG traversal to blocks in a specific loop. +// +// - Finally, by specializing the po_iterator_storage template itself, graph +// edges can be pruned by returning false in the insertEdge() function. This +// could be used to remove loop back-edges from the CFG seen by po_iterator. +// +// A specialized po_iterator_storage class can observe both the pre-order and +// the post-order. The insertEdge() function is called in a pre-order, while +// the finishPostorder() function is called just before the po_iterator moves +// on to the next node. + +/// Default po_iterator_storage implementation with an internal set object. +template<class SetType, bool External> +class po_iterator_storage { + SetType Visited; + +public: + // Return true if edge destination should be visited. + template <typename NodeRef> + bool insertEdge(Optional<NodeRef> From, NodeRef To) { + return Visited.insert(To).second; + } + + // Called after all children of BB have been visited. + template <typename NodeRef> void finishPostorder(NodeRef BB) {} +}; + +/// Specialization of po_iterator_storage that references an external set. +template<class SetType> +class po_iterator_storage<SetType, true> { + SetType &Visited; + +public: + po_iterator_storage(SetType &VSet) : Visited(VSet) {} + po_iterator_storage(const po_iterator_storage &S) : Visited(S.Visited) {} + + // Return true if edge destination should be visited, called with From = 0 for + // the root node. + // Graph edges can be pruned by specializing this function. + template <class NodeRef> bool insertEdge(Optional<NodeRef> From, NodeRef To) { + return Visited.insert(To).second; + } + + // Called after all children of BB have been visited. + template <class NodeRef> void finishPostorder(NodeRef BB) {} +}; + +template <class GraphT, + class SetType = + SmallPtrSet<typename GraphTraits<GraphT>::NodeRef, 8>, + bool ExtStorage = false, class GT = GraphTraits<GraphT>> +class po_iterator + : public std::iterator<std::forward_iterator_tag, typename GT::NodeRef>, + public po_iterator_storage<SetType, ExtStorage> { + using super = std::iterator<std::forward_iterator_tag, typename GT::NodeRef>; + using NodeRef = typename GT::NodeRef; + using ChildItTy = typename GT::ChildIteratorType; + + // VisitStack - Used to maintain the ordering. Top = current block + // First element is basic block pointer, second is the 'next child' to visit + std::vector<std::pair<NodeRef, ChildItTy>> VisitStack; + + po_iterator(NodeRef BB) { + this->insertEdge(Optional<NodeRef>(), BB); + VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB))); + traverseChild(); + } + + po_iterator() = default; // End is when stack is empty. + + po_iterator(NodeRef BB, SetType &S) + : po_iterator_storage<SetType, ExtStorage>(S) { + if (this->insertEdge(Optional<NodeRef>(), BB)) { + VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB))); + traverseChild(); + } + } + + po_iterator(SetType &S) + : po_iterator_storage<SetType, ExtStorage>(S) { + } // End is when stack is empty. + + void traverseChild() { + while (VisitStack.back().second != GT::child_end(VisitStack.back().first)) { + NodeRef BB = *VisitStack.back().second++; + if (this->insertEdge(Optional<NodeRef>(VisitStack.back().first), BB)) { + // If the block is not visited... + VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB))); + } + } + } + +public: + using pointer = typename super::pointer; + + // Provide static "constructors"... + static po_iterator begin(GraphT G) { + return po_iterator(GT::getEntryNode(G)); + } + static po_iterator end(GraphT G) { return po_iterator(); } + + static po_iterator begin(GraphT G, SetType &S) { + return po_iterator(GT::getEntryNode(G), S); + } + static po_iterator end(GraphT G, SetType &S) { return po_iterator(S); } + + bool operator==(const po_iterator &x) const { + return VisitStack == x.VisitStack; + } + bool operator!=(const po_iterator &x) const { return !(*this == x); } + + const NodeRef &operator*() const { return VisitStack.back().first; } + + // This is a nonstandard operator-> that dereferences the pointer an extra + // time... so that you can actually call methods ON the BasicBlock, because + // the contained type is a pointer. This allows BBIt->getTerminator() f.e. + // + NodeRef operator->() const { return **this; } + + po_iterator &operator++() { // Preincrement + this->finishPostorder(VisitStack.back().first); + VisitStack.pop_back(); + if (!VisitStack.empty()) + traverseChild(); + return *this; + } + + po_iterator operator++(int) { // Postincrement + po_iterator tmp = *this; + ++*this; + return tmp; + } +}; + +// Provide global constructors that automatically figure out correct types... +// +template <class T> +po_iterator<T> po_begin(const T &G) { return po_iterator<T>::begin(G); } +template <class T> +po_iterator<T> po_end (const T &G) { return po_iterator<T>::end(G); } + +template <class T> iterator_range<po_iterator<T>> post_order(const T &G) { + return make_range(po_begin(G), po_end(G)); +} + +// Provide global definitions of external postorder iterators... +template <class T, class SetType = std::set<typename GraphTraits<T>::NodeRef>> +struct po_ext_iterator : public po_iterator<T, SetType, true> { + po_ext_iterator(const po_iterator<T, SetType, true> &V) : + po_iterator<T, SetType, true>(V) {} +}; + +template<class T, class SetType> +po_ext_iterator<T, SetType> po_ext_begin(T G, SetType &S) { + return po_ext_iterator<T, SetType>::begin(G, S); +} + +template<class T, class SetType> +po_ext_iterator<T, SetType> po_ext_end(T G, SetType &S) { + return po_ext_iterator<T, SetType>::end(G, S); +} + +template <class T, class SetType> +iterator_range<po_ext_iterator<T, SetType>> post_order_ext(const T &G, SetType &S) { + return make_range(po_ext_begin(G, S), po_ext_end(G, S)); +} + +// Provide global definitions of inverse post order iterators... +template <class T, class SetType = std::set<typename GraphTraits<T>::NodeRef>, + bool External = false> +struct ipo_iterator : public po_iterator<Inverse<T>, SetType, External> { + ipo_iterator(const po_iterator<Inverse<T>, SetType, External> &V) : + po_iterator<Inverse<T>, SetType, External> (V) {} +}; + +template <class T> +ipo_iterator<T> ipo_begin(const T &G) { + return ipo_iterator<T>::begin(G); +} + +template <class T> +ipo_iterator<T> ipo_end(const T &G){ + return ipo_iterator<T>::end(G); +} + +template <class T> +iterator_range<ipo_iterator<T>> inverse_post_order(const T &G) { + return make_range(ipo_begin(G), ipo_end(G)); +} + +// Provide global definitions of external inverse postorder iterators... +template <class T, class SetType = std::set<typename GraphTraits<T>::NodeRef>> +struct ipo_ext_iterator : public ipo_iterator<T, SetType, true> { + ipo_ext_iterator(const ipo_iterator<T, SetType, true> &V) : + ipo_iterator<T, SetType, true>(V) {} + ipo_ext_iterator(const po_iterator<Inverse<T>, SetType, true> &V) : + ipo_iterator<T, SetType, true>(V) {} +}; + +template <class T, class SetType> +ipo_ext_iterator<T, SetType> ipo_ext_begin(const T &G, SetType &S) { + return ipo_ext_iterator<T, SetType>::begin(G, S); +} + +template <class T, class SetType> +ipo_ext_iterator<T, SetType> ipo_ext_end(const T &G, SetType &S) { + return ipo_ext_iterator<T, SetType>::end(G, S); +} + +template <class T, class SetType> +iterator_range<ipo_ext_iterator<T, SetType>> +inverse_post_order_ext(const T &G, SetType &S) { + return make_range(ipo_ext_begin(G, S), ipo_ext_end(G, S)); +} + +//===--------------------------------------------------------------------===// +// Reverse Post Order CFG iterator code +//===--------------------------------------------------------------------===// +// +// This is used to visit basic blocks in a method in reverse post order. This +// class is awkward to use because I don't know a good incremental algorithm to +// computer RPO from a graph. Because of this, the construction of the +// ReversePostOrderTraversal object is expensive (it must walk the entire graph +// with a postorder iterator to build the data structures). The moral of this +// story is: Don't create more ReversePostOrderTraversal classes than necessary. +// +// Because it does the traversal in its constructor, it won't invalidate when +// BasicBlocks are removed, *but* it may contain erased blocks. Some places +// rely on this behavior (i.e. GVN). +// +// This class should be used like this: +// { +// ReversePostOrderTraversal<Function*> RPOT(FuncPtr); // Expensive to create +// for (rpo_iterator I = RPOT.begin(); I != RPOT.end(); ++I) { +// ... +// } +// for (rpo_iterator I = RPOT.begin(); I != RPOT.end(); ++I) { +// ... +// } +// } +// + +template<class GraphT, class GT = GraphTraits<GraphT>> +class ReversePostOrderTraversal { + using NodeRef = typename GT::NodeRef; + + std::vector<NodeRef> Blocks; // Block list in normal PO order + + void Initialize(NodeRef BB) { + std::copy(po_begin(BB), po_end(BB), std::back_inserter(Blocks)); + } + +public: + using rpo_iterator = typename std::vector<NodeRef>::reverse_iterator; + using const_rpo_iterator = typename std::vector<NodeRef>::const_reverse_iterator; + + ReversePostOrderTraversal(GraphT G) { Initialize(GT::getEntryNode(G)); } + + // Because we want a reverse post order, use reverse iterators from the vector + rpo_iterator begin() { return Blocks.rbegin(); } + const_rpo_iterator begin() const { return Blocks.crbegin(); } + rpo_iterator end() { return Blocks.rend(); } + const_rpo_iterator end() const { return Blocks.crend(); } +}; + +} // end namespace llvm + +#endif // LLVM_ADT_POSTORDERITERATOR_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/PriorityQueue.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/PriorityQueue.h new file mode 100644 index 0000000..cf79ee1 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/PriorityQueue.h
@@ -0,0 +1,82 @@ +//===- llvm/ADT/PriorityQueue.h - Priority queues ---------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the PriorityQueue class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_PRIORITYQUEUE_H +#define LLVM_ADT_PRIORITYQUEUE_H + +#include <algorithm> +#include <queue> + +namespace llvm { + +/// PriorityQueue - This class behaves like std::priority_queue and +/// provides a few additional convenience functions. +/// +template<class T, + class Sequence = std::vector<T>, + class Compare = std::less<typename Sequence::value_type> > +class PriorityQueue : public std::priority_queue<T, Sequence, Compare> { +public: + explicit PriorityQueue(const Compare &compare = Compare(), + const Sequence &sequence = Sequence()) + : std::priority_queue<T, Sequence, Compare>(compare, sequence) + {} + + template<class Iterator> + PriorityQueue(Iterator begin, Iterator end, + const Compare &compare = Compare(), + const Sequence &sequence = Sequence()) + : std::priority_queue<T, Sequence, Compare>(begin, end, compare, sequence) + {} + + /// erase_one - Erase one element from the queue, regardless of its + /// position. This operation performs a linear search to find an element + /// equal to t, but then uses all logarithmic-time algorithms to do + /// the erase operation. + /// + void erase_one(const T &t) { + // Linear-search to find the element. + typename Sequence::size_type i = find(this->c, t) - this->c.begin(); + + // Logarithmic-time heap bubble-up. + while (i != 0) { + typename Sequence::size_type parent = (i - 1) / 2; + this->c[i] = this->c[parent]; + i = parent; + } + + // The element we want to remove is now at the root, so we can use + // priority_queue's plain pop to remove it. + this->pop(); + } + + /// reheapify - If an element in the queue has changed in a way that + /// affects its standing in the comparison function, the queue's + /// internal state becomes invalid. Calling reheapify() resets the + /// queue's state, making it valid again. This operation has time + /// complexity proportional to the number of elements in the queue, + /// so don't plan to use it a lot. + /// + void reheapify() { + std::make_heap(this->c.begin(), this->c.end(), this->comp); + } + + /// clear - Erase all elements from the queue. + /// + void clear() { + this->c.clear(); + } +}; + +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/PriorityWorklist.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/PriorityWorklist.h new file mode 100644 index 0000000..96d22c8 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/PriorityWorklist.h
@@ -0,0 +1,265 @@ +//===- PriorityWorklist.h - Worklist with insertion priority ----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \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/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Compiler.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <iterator> +#include <type_traits> +#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: + using value_type = T; + using key_type = T; + using reference = T&; + using const_reference = const T&; + using size_type = typename MapT::size_type; + + /// Construct an empty PriorityWorklist + PriorityWorklist() = default; + + /// 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; + } + + /// Insert a sequence of new elements into the PriorityWorklist. + template <typename SequenceT> + typename std::enable_if<!std::is_convertible<SequenceT, T>::value>::type + insert(SequenceT &&Input) { + if (std::begin(Input) == std::end(Input)) + // Nothing to do for an empty input sequence. + return; + + // First pull the input sequence into the vector as a bulk append + // operation. + ptrdiff_t StartIndex = V.size(); + V.insert(V.end(), std::begin(Input), std::end(Input)); + // Now walk backwards fixing up the index map and deleting any duplicates. + for (ptrdiff_t i = V.size() - 1; i >= StartIndex; --i) { + auto InsertResult = M.insert({V[i], i}); + if (InsertResult.second) + continue; + + // If the existing index is before this insert's start, nuke that one and + // move it up. + ptrdiff_t &Index = InsertResult.first->second; + if (Index < StartIndex) { + V[Index] = T(); + Index = i; + continue; + } + + // Otherwise the existing one comes first so just clear out the value in + // this slot. + V[i] = T(); + } + } + + /// 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()); + } + + LLVM_NODISCARD T 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(remove_if(V, 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 = + remove_if(V, 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; + } + + /// Reverse the items in the PriorityWorklist. + /// + /// This does an in-place reversal. Other kinds of reverse aren't easy to + /// support in the face of the worklist semantics. + + /// 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() = default; +}; + +} // end namespace llvm + +#endif // LLVM_ADT_PRIORITYWORKLIST_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/SCCIterator.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/SCCIterator.h new file mode 100644 index 0000000..1e642b9 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/SCCIterator.h
@@ -0,0 +1,239 @@ +//===- ADT/SCCIterator.h - Strongly Connected Comp. Iter. -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This builds on the llvm/ADT/GraphTraits.h file to find the strongly +/// connected components (SCCs) of a graph in O(N+E) time using Tarjan's DFS +/// algorithm. +/// +/// The SCC iterator has the important property that if a node in SCC S1 has an +/// edge to a node in SCC S2, then it visits S1 *after* S2. +/// +/// To visit S1 *before* S2, use the scc_iterator on the Inverse graph. (NOTE: +/// This requires some simple wrappers and is not supported yet.) +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SCCITERATOR_H +#define LLVM_ADT_SCCITERATOR_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/iterator.h" +#include <cassert> +#include <cstddef> +#include <iterator> +#include <vector> + +namespace llvm { + +/// Enumerate the SCCs of a directed graph in reverse topological order +/// of the SCC DAG. +/// +/// This is implemented using Tarjan's DFS algorithm using an internal stack to +/// build up a vector of nodes in a particular SCC. Note that it is a forward +/// iterator and thus you cannot backtrack or re-visit nodes. +template <class GraphT, class GT = GraphTraits<GraphT>> +class scc_iterator : public iterator_facade_base< + scc_iterator<GraphT, GT>, std::forward_iterator_tag, + const std::vector<typename GT::NodeRef>, ptrdiff_t> { + using NodeRef = typename GT::NodeRef; + using ChildItTy = typename GT::ChildIteratorType; + using SccTy = std::vector<NodeRef>; + using reference = typename scc_iterator::reference; + + /// Element of VisitStack during DFS. + struct StackElement { + NodeRef Node; ///< The current node pointer. + ChildItTy NextChild; ///< The next child, modified inplace during DFS. + unsigned MinVisited; ///< Minimum uplink value of all children of Node. + + StackElement(NodeRef Node, const ChildItTy &Child, unsigned Min) + : Node(Node), NextChild(Child), MinVisited(Min) {} + + bool operator==(const StackElement &Other) const { + return Node == Other.Node && + NextChild == Other.NextChild && + MinVisited == Other.MinVisited; + } + }; + + /// The visit counters used to detect when a complete SCC is on the stack. + /// visitNum is the global counter. + /// + /// nodeVisitNumbers are per-node visit numbers, also used as DFS flags. + unsigned visitNum; + DenseMap<NodeRef, unsigned> nodeVisitNumbers; + + /// Stack holding nodes of the SCC. + std::vector<NodeRef> SCCNodeStack; + + /// The current SCC, retrieved using operator*(). + SccTy CurrentSCC; + + /// DFS stack, Used to maintain the ordering. The top contains the current + /// node, the next child to visit, and the minimum uplink value of all child + std::vector<StackElement> VisitStack; + + /// A single "visit" within the non-recursive DFS traversal. + void DFSVisitOne(NodeRef N); + + /// The stack-based DFS traversal; defined below. + void DFSVisitChildren(); + + /// Compute the next SCC using the DFS traversal. + void GetNextSCC(); + + scc_iterator(NodeRef entryN) : visitNum(0) { + DFSVisitOne(entryN); + GetNextSCC(); + } + + /// End is when the DFS stack is empty. + scc_iterator() = default; + +public: + static scc_iterator begin(const GraphT &G) { + return scc_iterator(GT::getEntryNode(G)); + } + static scc_iterator end(const GraphT &) { return scc_iterator(); } + + /// Direct loop termination test which is more efficient than + /// comparison with \c end(). + bool isAtEnd() const { + assert(!CurrentSCC.empty() || VisitStack.empty()); + return CurrentSCC.empty(); + } + + bool operator==(const scc_iterator &x) const { + return VisitStack == x.VisitStack && CurrentSCC == x.CurrentSCC; + } + + scc_iterator &operator++() { + GetNextSCC(); + return *this; + } + + reference operator*() const { + assert(!CurrentSCC.empty() && "Dereferencing END SCC iterator!"); + return CurrentSCC; + } + + /// Test if the current SCC has a loop. + /// + /// If the SCC has more than one node, this is trivially true. If not, it may + /// still contain a loop if the node has an edge back to itself. + bool hasLoop() const; + + /// This informs the \c scc_iterator that the specified \c Old node + /// has been deleted, and \c New is to be used in its place. + void ReplaceNode(NodeRef Old, NodeRef New) { + assert(nodeVisitNumbers.count(Old) && "Old not in scc_iterator?"); + // Do the assignment in two steps, in case 'New' is not yet in the map, and + // inserting it causes the map to grow. + auto tempVal = nodeVisitNumbers[Old]; + nodeVisitNumbers[New] = tempVal; + nodeVisitNumbers.erase(Old); + } +}; + +template <class GraphT, class GT> +void scc_iterator<GraphT, GT>::DFSVisitOne(NodeRef N) { + ++visitNum; + nodeVisitNumbers[N] = visitNum; + SCCNodeStack.push_back(N); + VisitStack.push_back(StackElement(N, GT::child_begin(N), visitNum)); +#if 0 // Enable if needed when debugging. + dbgs() << "TarjanSCC: Node " << N << + " : visitNum = " << visitNum << "\n"; +#endif +} + +template <class GraphT, class GT> +void scc_iterator<GraphT, GT>::DFSVisitChildren() { + assert(!VisitStack.empty()); + while (VisitStack.back().NextChild != GT::child_end(VisitStack.back().Node)) { + // TOS has at least one more child so continue DFS + NodeRef childN = *VisitStack.back().NextChild++; + typename DenseMap<NodeRef, unsigned>::iterator Visited = + nodeVisitNumbers.find(childN); + if (Visited == nodeVisitNumbers.end()) { + // this node has never been seen. + DFSVisitOne(childN); + continue; + } + + unsigned childNum = Visited->second; + if (VisitStack.back().MinVisited > childNum) + VisitStack.back().MinVisited = childNum; + } +} + +template <class GraphT, class GT> void scc_iterator<GraphT, GT>::GetNextSCC() { + CurrentSCC.clear(); // Prepare to compute the next SCC + while (!VisitStack.empty()) { + DFSVisitChildren(); + + // Pop the leaf on top of the VisitStack. + NodeRef visitingN = VisitStack.back().Node; + unsigned minVisitNum = VisitStack.back().MinVisited; + assert(VisitStack.back().NextChild == GT::child_end(visitingN)); + VisitStack.pop_back(); + + // Propagate MinVisitNum to parent so we can detect the SCC starting node. + if (!VisitStack.empty() && VisitStack.back().MinVisited > minVisitNum) + VisitStack.back().MinVisited = minVisitNum; + +#if 0 // Enable if needed when debugging. + dbgs() << "TarjanSCC: Popped node " << visitingN << + " : minVisitNum = " << minVisitNum << "; Node visit num = " << + nodeVisitNumbers[visitingN] << "\n"; +#endif + + if (minVisitNum != nodeVisitNumbers[visitingN]) + continue; + + // A full SCC is on the SCCNodeStack! It includes all nodes below + // visitingN on the stack. Copy those nodes to CurrentSCC, + // reset their minVisit values, and return (this suspends + // the DFS traversal till the next ++). + do { + CurrentSCC.push_back(SCCNodeStack.back()); + SCCNodeStack.pop_back(); + nodeVisitNumbers[CurrentSCC.back()] = ~0U; + } while (CurrentSCC.back() != visitingN); + return; + } +} + +template <class GraphT, class GT> +bool scc_iterator<GraphT, GT>::hasLoop() const { + assert(!CurrentSCC.empty() && "Dereferencing END SCC iterator!"); + if (CurrentSCC.size() > 1) + return true; + NodeRef N = CurrentSCC.front(); + for (ChildItTy CI = GT::child_begin(N), CE = GT::child_end(N); CI != CE; + ++CI) + if (*CI == N) + return true; + return false; + } + +/// Construct the begin iterator for a deduced graph type T. +template <class T> scc_iterator<T> scc_begin(const T &G) { + return scc_iterator<T>::begin(G); +} + +/// Construct the end iterator for a deduced graph type T. +template <class T> scc_iterator<T> scc_end(const T &G) { + return scc_iterator<T>::end(G); +} + +} // end namespace llvm + +#endif // LLVM_ADT_SCCITERATOR_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/STLExtras.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/STLExtras.h new file mode 100644 index 0000000..b61dab2 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/STLExtras.h
@@ -0,0 +1,1589 @@ +//===- llvm/ADT/STLExtras.h - Useful STL related functions ------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains some templates that are useful if you are working with the +// STL at all. +// +// No library is required when using these functions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STLEXTRAS_H +#define LLVM_ADT_STLEXTRAS_H + +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/iterator.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Config/abi-breaking.h" +#include "llvm/Support/ErrorHandling.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <functional> +#include <initializer_list> +#include <iterator> +#include <limits> +#include <memory> +#include <tuple> +#include <type_traits> +#include <utility> + +#ifdef EXPENSIVE_CHECKS +#include <random> // for std::mt19937 +#endif + +namespace llvm { + +// Only used by compiler if both template types are the same. Useful when +// using SFINAE to test for the existence of member functions. +template <typename T, T> struct SameType; + +namespace detail { + +template <typename RangeT> +using IterOfRange = decltype(std::begin(std::declval<RangeT &>())); + +} // end namespace detail + +//===----------------------------------------------------------------------===// +// Extra additions to <type_traits> +//===----------------------------------------------------------------------===// + +template <typename T> +struct negation : std::integral_constant<bool, !bool(T::value)> {}; + +template <typename...> struct conjunction : std::true_type {}; +template <typename B1> struct conjunction<B1> : B1 {}; +template <typename B1, typename... Bn> +struct conjunction<B1, Bn...> + : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {}; + +template <typename T> struct make_const_ptr { + using type = + typename std::add_pointer<typename std::add_const<T>::type>::type; +}; + +template <typename T> struct make_const_ref { + using type = typename std::add_lvalue_reference< + typename std::add_const<T>::type>::type; +}; + +//===----------------------------------------------------------------------===// +// Extra additions to <functional> +//===----------------------------------------------------------------------===// + +template <class Ty> struct identity { + using argument_type = Ty; + + Ty &operator()(Ty &self) const { + return self; + } + const Ty &operator()(const Ty &self) const { + return self; + } +}; + +/// An efficient, type-erasing, non-owning reference to a callable. This is +/// intended for use as the type of a function parameter that is not used +/// after the function in question returns. +/// +/// This class does not own the callable, so it is not in general safe to store +/// a function_ref. +template<typename Fn> class function_ref; + +template<typename Ret, typename ...Params> +class function_ref<Ret(Params...)> { + Ret (*callback)(intptr_t callable, Params ...params) = nullptr; + intptr_t callable; + + template<typename Callable> + static Ret callback_fn(intptr_t callable, Params ...params) { + return (*reinterpret_cast<Callable*>(callable))( + std::forward<Params>(params)...); + } + +public: + function_ref() = default; + function_ref(std::nullptr_t) {} + + template <typename Callable> + function_ref(Callable &&callable, + typename std::enable_if< + !std::is_same<typename std::remove_reference<Callable>::type, + function_ref>::value>::type * = nullptr) + : callback(callback_fn<typename std::remove_reference<Callable>::type>), + callable(reinterpret_cast<intptr_t>(&callable)) {} + + Ret operator()(Params ...params) const { + return callback(callable, std::forward<Params>(params)...); + } + + operator bool() const { return callback; } +}; + +// deleter - Very very very simple method that is used to invoke operator +// delete on something. It is used like this: +// +// for_each(V.begin(), B.end(), deleter<Interval>); +template <class T> +inline void deleter(T *Ptr) { + delete Ptr; +} + +//===----------------------------------------------------------------------===// +// Extra additions to <iterator> +//===----------------------------------------------------------------------===// + +namespace adl_detail { + +using std::begin; + +template <typename ContainerTy> +auto adl_begin(ContainerTy &&container) + -> decltype(begin(std::forward<ContainerTy>(container))) { + return begin(std::forward<ContainerTy>(container)); +} + +using std::end; + +template <typename ContainerTy> +auto adl_end(ContainerTy &&container) + -> decltype(end(std::forward<ContainerTy>(container))) { + return end(std::forward<ContainerTy>(container)); +} + +using std::swap; + +template <typename T> +void adl_swap(T &&lhs, T &&rhs) noexcept(noexcept(swap(std::declval<T>(), + std::declval<T>()))) { + swap(std::forward<T>(lhs), std::forward<T>(rhs)); +} + +} // end namespace adl_detail + +template <typename ContainerTy> +auto adl_begin(ContainerTy &&container) + -> decltype(adl_detail::adl_begin(std::forward<ContainerTy>(container))) { + return adl_detail::adl_begin(std::forward<ContainerTy>(container)); +} + +template <typename ContainerTy> +auto adl_end(ContainerTy &&container) + -> decltype(adl_detail::adl_end(std::forward<ContainerTy>(container))) { + return adl_detail::adl_end(std::forward<ContainerTy>(container)); +} + +template <typename T> +void adl_swap(T &&lhs, T &&rhs) noexcept( + noexcept(adl_detail::adl_swap(std::declval<T>(), std::declval<T>()))) { + adl_detail::adl_swap(std::forward<T>(lhs), std::forward<T>(rhs)); +} + +/// Test whether \p RangeOrContainer is empty. Similar to C++17 std::empty. +template <typename T> +constexpr bool empty(const T &RangeOrContainer) { + return adl_begin(RangeOrContainer) == adl_end(RangeOrContainer); +} + +/// Return a range covering \p RangeOrContainer with the first N elements +/// excluded. +template <typename T> +auto drop_begin(T &&RangeOrContainer, size_t N) -> + iterator_range<decltype(adl_begin(RangeOrContainer))> { + return make_range(std::next(adl_begin(RangeOrContainer), N), + adl_end(RangeOrContainer)); +} + +// mapped_iterator - This is a simple iterator adapter that causes a function to +// be applied whenever operator* is invoked on the iterator. + +template <typename ItTy, typename FuncTy, + typename FuncReturnTy = + decltype(std::declval<FuncTy>()(*std::declval<ItTy>()))> +class mapped_iterator + : public iterator_adaptor_base< + mapped_iterator<ItTy, FuncTy>, ItTy, + typename std::iterator_traits<ItTy>::iterator_category, + typename std::remove_reference<FuncReturnTy>::type> { +public: + mapped_iterator(ItTy U, FuncTy F) + : mapped_iterator::iterator_adaptor_base(std::move(U)), F(std::move(F)) {} + + ItTy getCurrent() { return this->I; } + + FuncReturnTy operator*() { return F(*this->I); } + +private: + FuncTy F; +}; + +// map_iterator - Provide a convenient way to create mapped_iterators, just like +// make_pair is useful for creating pairs... +template <class ItTy, class FuncTy> +inline mapped_iterator<ItTy, FuncTy> map_iterator(ItTy I, FuncTy F) { + return mapped_iterator<ItTy, FuncTy>(std::move(I), std::move(F)); +} + +template <class ContainerTy, class FuncTy> +auto map_range(ContainerTy &&C, FuncTy F) + -> decltype(make_range(map_iterator(C.begin(), F), + map_iterator(C.end(), F))) { + return make_range(map_iterator(C.begin(), F), map_iterator(C.end(), F)); +} + +/// Helper to determine if type T has a member called rbegin(). +template <typename Ty> class has_rbegin_impl { + using yes = char[1]; + using no = char[2]; + + template <typename Inner> + static yes& test(Inner *I, decltype(I->rbegin()) * = nullptr); + + template <typename> + static no& test(...); + +public: + static const bool value = sizeof(test<Ty>(nullptr)) == sizeof(yes); +}; + +/// Metafunction to determine if T& or T has a member called rbegin(). +template <typename Ty> +struct has_rbegin : has_rbegin_impl<typename std::remove_reference<Ty>::type> { +}; + +// Returns an iterator_range over the given container which iterates in reverse. +// Note that the container must have rbegin()/rend() methods for this to work. +template <typename ContainerTy> +auto reverse(ContainerTy &&C, + typename std::enable_if<has_rbegin<ContainerTy>::value>::type * = + nullptr) -> decltype(make_range(C.rbegin(), C.rend())) { + return make_range(C.rbegin(), C.rend()); +} + +// Returns a std::reverse_iterator wrapped around the given iterator. +template <typename IteratorTy> +std::reverse_iterator<IteratorTy> make_reverse_iterator(IteratorTy It) { + return std::reverse_iterator<IteratorTy>(It); +} + +// Returns an iterator_range over the given container which iterates in reverse. +// Note that the container must have begin()/end() methods which return +// bidirectional iterators for this to work. +template <typename ContainerTy> +auto reverse( + ContainerTy &&C, + typename std::enable_if<!has_rbegin<ContainerTy>::value>::type * = nullptr) + -> decltype(make_range(llvm::make_reverse_iterator(std::end(C)), + llvm::make_reverse_iterator(std::begin(C)))) { + return make_range(llvm::make_reverse_iterator(std::end(C)), + llvm::make_reverse_iterator(std::begin(C))); +} + +/// An iterator adaptor that filters the elements of given inner iterators. +/// +/// The predicate parameter should be a callable object that accepts the wrapped +/// iterator's reference type and returns a bool. When incrementing or +/// decrementing the iterator, it will call the predicate on each element and +/// skip any where it returns false. +/// +/// \code +/// int A[] = { 1, 2, 3, 4 }; +/// auto R = make_filter_range(A, [](int N) { return N % 2 == 1; }); +/// // R contains { 1, 3 }. +/// \endcode +/// +/// Note: filter_iterator_base implements support for forward iteration. +/// filter_iterator_impl exists to provide support for bidirectional iteration, +/// conditional on whether the wrapped iterator supports it. +template <typename WrappedIteratorT, typename PredicateT, typename IterTag> +class filter_iterator_base + : public iterator_adaptor_base< + filter_iterator_base<WrappedIteratorT, PredicateT, IterTag>, + WrappedIteratorT, + typename std::common_type< + IterTag, typename std::iterator_traits< + WrappedIteratorT>::iterator_category>::type> { + using BaseT = iterator_adaptor_base< + filter_iterator_base<WrappedIteratorT, PredicateT, IterTag>, + WrappedIteratorT, + typename std::common_type< + IterTag, typename std::iterator_traits< + WrappedIteratorT>::iterator_category>::type>; + +protected: + WrappedIteratorT End; + PredicateT Pred; + + void findNextValid() { + while (this->I != End && !Pred(*this->I)) + BaseT::operator++(); + } + + // Construct the iterator. The begin iterator needs to know where the end + // is, so that it can properly stop when it gets there. The end iterator only + // needs the predicate to support bidirectional iteration. + filter_iterator_base(WrappedIteratorT Begin, WrappedIteratorT End, + PredicateT Pred) + : BaseT(Begin), End(End), Pred(Pred) { + findNextValid(); + } + +public: + using BaseT::operator++; + + filter_iterator_base &operator++() { + BaseT::operator++(); + findNextValid(); + return *this; + } +}; + +/// Specialization of filter_iterator_base for forward iteration only. +template <typename WrappedIteratorT, typename PredicateT, + typename IterTag = std::forward_iterator_tag> +class filter_iterator_impl + : public filter_iterator_base<WrappedIteratorT, PredicateT, IterTag> { + using BaseT = filter_iterator_base<WrappedIteratorT, PredicateT, IterTag>; + +public: + filter_iterator_impl(WrappedIteratorT Begin, WrappedIteratorT End, + PredicateT Pred) + : BaseT(Begin, End, Pred) {} +}; + +/// Specialization of filter_iterator_base for bidirectional iteration. +template <typename WrappedIteratorT, typename PredicateT> +class filter_iterator_impl<WrappedIteratorT, PredicateT, + std::bidirectional_iterator_tag> + : public filter_iterator_base<WrappedIteratorT, PredicateT, + std::bidirectional_iterator_tag> { + using BaseT = filter_iterator_base<WrappedIteratorT, PredicateT, + std::bidirectional_iterator_tag>; + void findPrevValid() { + while (!this->Pred(*this->I)) + BaseT::operator--(); + } + +public: + using BaseT::operator--; + + filter_iterator_impl(WrappedIteratorT Begin, WrappedIteratorT End, + PredicateT Pred) + : BaseT(Begin, End, Pred) {} + + filter_iterator_impl &operator--() { + BaseT::operator--(); + findPrevValid(); + return *this; + } +}; + +namespace detail { + +template <bool is_bidirectional> struct fwd_or_bidi_tag_impl { + using type = std::forward_iterator_tag; +}; + +template <> struct fwd_or_bidi_tag_impl<true> { + using type = std::bidirectional_iterator_tag; +}; + +/// Helper which sets its type member to forward_iterator_tag if the category +/// of \p IterT does not derive from bidirectional_iterator_tag, and to +/// bidirectional_iterator_tag otherwise. +template <typename IterT> struct fwd_or_bidi_tag { + using type = typename fwd_or_bidi_tag_impl<std::is_base_of< + std::bidirectional_iterator_tag, + typename std::iterator_traits<IterT>::iterator_category>::value>::type; +}; + +} // namespace detail + +/// Defines filter_iterator to a suitable specialization of +/// filter_iterator_impl, based on the underlying iterator's category. +template <typename WrappedIteratorT, typename PredicateT> +using filter_iterator = filter_iterator_impl< + WrappedIteratorT, PredicateT, + typename detail::fwd_or_bidi_tag<WrappedIteratorT>::type>; + +/// Convenience function that takes a range of elements and a predicate, +/// and return a new filter_iterator range. +/// +/// FIXME: Currently if RangeT && is a rvalue reference to a temporary, the +/// lifetime of that temporary is not kept by the returned range object, and the +/// temporary is going to be dropped on the floor after the make_iterator_range +/// full expression that contains this function call. +template <typename RangeT, typename PredicateT> +iterator_range<filter_iterator<detail::IterOfRange<RangeT>, PredicateT>> +make_filter_range(RangeT &&Range, PredicateT Pred) { + using FilterIteratorT = + filter_iterator<detail::IterOfRange<RangeT>, PredicateT>; + return make_range( + FilterIteratorT(std::begin(std::forward<RangeT>(Range)), + std::end(std::forward<RangeT>(Range)), Pred), + FilterIteratorT(std::end(std::forward<RangeT>(Range)), + std::end(std::forward<RangeT>(Range)), Pred)); +} + +/// A pseudo-iterator adaptor that is designed to implement "early increment" +/// style loops. +/// +/// This is *not a normal iterator* and should almost never be used directly. It +/// is intended primarily to be used with range based for loops and some range +/// algorithms. +/// +/// The iterator isn't quite an `OutputIterator` or an `InputIterator` but +/// somewhere between them. The constraints of these iterators are: +/// +/// - On construction or after being incremented, it is comparable and +/// dereferencable. It is *not* incrementable. +/// - After being dereferenced, it is neither comparable nor dereferencable, it +/// is only incrementable. +/// +/// This means you can only dereference the iterator once, and you can only +/// increment it once between dereferences. +template <typename WrappedIteratorT> +class early_inc_iterator_impl + : public iterator_adaptor_base<early_inc_iterator_impl<WrappedIteratorT>, + WrappedIteratorT, std::input_iterator_tag> { + using BaseT = + iterator_adaptor_base<early_inc_iterator_impl<WrappedIteratorT>, + WrappedIteratorT, std::input_iterator_tag>; + + using PointerT = typename std::iterator_traits<WrappedIteratorT>::pointer; + +protected: +#if LLVM_ENABLE_ABI_BREAKING_CHECKS + bool IsEarlyIncremented = false; +#endif + +public: + early_inc_iterator_impl(WrappedIteratorT I) : BaseT(I) {} + + using BaseT::operator*; + typename BaseT::reference operator*() { +#if LLVM_ENABLE_ABI_BREAKING_CHECKS + assert(!IsEarlyIncremented && "Cannot dereference twice!"); + IsEarlyIncremented = true; +#endif + return *(this->I)++; + } + + using BaseT::operator++; + early_inc_iterator_impl &operator++() { +#if LLVM_ENABLE_ABI_BREAKING_CHECKS + assert(IsEarlyIncremented && "Cannot increment before dereferencing!"); + IsEarlyIncremented = false; +#endif + return *this; + } + + using BaseT::operator==; + bool operator==(const early_inc_iterator_impl &RHS) const { +#if LLVM_ENABLE_ABI_BREAKING_CHECKS + assert(!IsEarlyIncremented && "Cannot compare after dereferencing!"); +#endif + return BaseT::operator==(RHS); + } +}; + +/// Make a range that does early increment to allow mutation of the underlying +/// range without disrupting iteration. +/// +/// The underlying iterator will be incremented immediately after it is +/// dereferenced, allowing deletion of the current node or insertion of nodes to +/// not disrupt iteration provided they do not invalidate the *next* iterator -- +/// the current iterator can be invalidated. +/// +/// This requires a very exact pattern of use that is only really suitable to +/// range based for loops and other range algorithms that explicitly guarantee +/// to dereference exactly once each element, and to increment exactly once each +/// element. +template <typename RangeT> +iterator_range<early_inc_iterator_impl<detail::IterOfRange<RangeT>>> +make_early_inc_range(RangeT &&Range) { + using EarlyIncIteratorT = + early_inc_iterator_impl<detail::IterOfRange<RangeT>>; + return make_range(EarlyIncIteratorT(std::begin(std::forward<RangeT>(Range))), + EarlyIncIteratorT(std::end(std::forward<RangeT>(Range)))); +} + +// forward declarations required by zip_shortest/zip_first/zip_longest +template <typename R, typename UnaryPredicate> +bool all_of(R &&range, UnaryPredicate P); +template <typename R, typename UnaryPredicate> +bool any_of(R &&range, UnaryPredicate P); + +namespace detail { + +using std::declval; + +// We have to alias this since inlining the actual type at the usage site +// in the parameter list of iterator_facade_base<> below ICEs MSVC 2017. +template<typename... Iters> struct ZipTupleType { + using type = std::tuple<decltype(*declval<Iters>())...>; +}; + +template <typename ZipType, typename... Iters> +using zip_traits = iterator_facade_base< + ZipType, typename std::common_type<std::bidirectional_iterator_tag, + typename std::iterator_traits< + Iters>::iterator_category...>::type, + // ^ TODO: Implement random access methods. + typename ZipTupleType<Iters...>::type, + typename std::iterator_traits<typename std::tuple_element< + 0, std::tuple<Iters...>>::type>::difference_type, + // ^ FIXME: This follows boost::make_zip_iterator's assumption that all + // inner iterators have the same difference_type. It would fail if, for + // instance, the second field's difference_type were non-numeric while the + // first is. + typename ZipTupleType<Iters...>::type *, + typename ZipTupleType<Iters...>::type>; + +template <typename ZipType, typename... Iters> +struct zip_common : public zip_traits<ZipType, Iters...> { + using Base = zip_traits<ZipType, Iters...>; + using value_type = typename Base::value_type; + + std::tuple<Iters...> iterators; + +protected: + template <size_t... Ns> value_type deref(std::index_sequence<Ns...>) const { + return value_type(*std::get<Ns>(iterators)...); + } + + template <size_t... Ns> + decltype(iterators) tup_inc(std::index_sequence<Ns...>) const { + return std::tuple<Iters...>(std::next(std::get<Ns>(iterators))...); + } + + template <size_t... Ns> + decltype(iterators) tup_dec(std::index_sequence<Ns...>) const { + return std::tuple<Iters...>(std::prev(std::get<Ns>(iterators))...); + } + +public: + zip_common(Iters &&... ts) : iterators(std::forward<Iters>(ts)...) {} + + value_type operator*() { return deref(std::index_sequence_for<Iters...>{}); } + + const value_type operator*() const { + return deref(std::index_sequence_for<Iters...>{}); + } + + ZipType &operator++() { + iterators = tup_inc(std::index_sequence_for<Iters...>{}); + return *reinterpret_cast<ZipType *>(this); + } + + ZipType &operator--() { + static_assert(Base::IsBidirectional, + "All inner iterators must be at least bidirectional."); + iterators = tup_dec(std::index_sequence_for<Iters...>{}); + return *reinterpret_cast<ZipType *>(this); + } +}; + +template <typename... Iters> +struct zip_first : public zip_common<zip_first<Iters...>, Iters...> { + using Base = zip_common<zip_first<Iters...>, Iters...>; + + bool operator==(const zip_first<Iters...> &other) const { + return std::get<0>(this->iterators) == std::get<0>(other.iterators); + } + + zip_first(Iters &&... ts) : Base(std::forward<Iters>(ts)...) {} +}; + +template <typename... Iters> +class zip_shortest : public zip_common<zip_shortest<Iters...>, Iters...> { + template <size_t... Ns> + bool test(const zip_shortest<Iters...> &other, + std::index_sequence<Ns...>) const { + return all_of(std::initializer_list<bool>{std::get<Ns>(this->iterators) != + std::get<Ns>(other.iterators)...}, + identity<bool>{}); + } + +public: + using Base = zip_common<zip_shortest<Iters...>, Iters...>; + + zip_shortest(Iters &&... ts) : Base(std::forward<Iters>(ts)...) {} + + bool operator==(const zip_shortest<Iters...> &other) const { + return !test(other, std::index_sequence_for<Iters...>{}); + } +}; + +template <template <typename...> class ItType, typename... Args> class zippy { +public: + using iterator = ItType<decltype(std::begin(std::declval<Args>()))...>; + using iterator_category = typename iterator::iterator_category; + using value_type = typename iterator::value_type; + using difference_type = typename iterator::difference_type; + using pointer = typename iterator::pointer; + using reference = typename iterator::reference; + +private: + std::tuple<Args...> ts; + + template <size_t... Ns> + iterator begin_impl(std::index_sequence<Ns...>) const { + return iterator(std::begin(std::get<Ns>(ts))...); + } + template <size_t... Ns> iterator end_impl(std::index_sequence<Ns...>) const { + return iterator(std::end(std::get<Ns>(ts))...); + } + +public: + zippy(Args &&... ts_) : ts(std::forward<Args>(ts_)...) {} + + iterator begin() const { + return begin_impl(std::index_sequence_for<Args...>{}); + } + iterator end() const { return end_impl(std::index_sequence_for<Args...>{}); } +}; + +} // end namespace detail + +/// zip iterator for two or more iteratable types. +template <typename T, typename U, typename... Args> +detail::zippy<detail::zip_shortest, T, U, Args...> zip(T &&t, U &&u, + Args &&... args) { + return detail::zippy<detail::zip_shortest, T, U, Args...>( + std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...); +} + +/// zip iterator that, for the sake of efficiency, assumes the first iteratee to +/// be the shortest. +template <typename T, typename U, typename... Args> +detail::zippy<detail::zip_first, T, U, Args...> zip_first(T &&t, U &&u, + Args &&... args) { + return detail::zippy<detail::zip_first, T, U, Args...>( + std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...); +} + +namespace detail { +template <typename Iter> +static Iter next_or_end(const Iter &I, const Iter &End) { + if (I == End) + return End; + return std::next(I); +} + +template <typename Iter> +static auto deref_or_none(const Iter &I, const Iter &End) + -> llvm::Optional<typename std::remove_const< + typename std::remove_reference<decltype(*I)>::type>::type> { + if (I == End) + return None; + return *I; +} + +template <typename Iter> struct ZipLongestItemType { + using type = + llvm::Optional<typename std::remove_const<typename std::remove_reference< + decltype(*std::declval<Iter>())>::type>::type>; +}; + +template <typename... Iters> struct ZipLongestTupleType { + using type = std::tuple<typename ZipLongestItemType<Iters>::type...>; +}; + +template <typename... Iters> +class zip_longest_iterator + : public iterator_facade_base< + zip_longest_iterator<Iters...>, + typename std::common_type< + std::forward_iterator_tag, + typename std::iterator_traits<Iters>::iterator_category...>::type, + typename ZipLongestTupleType<Iters...>::type, + typename std::iterator_traits<typename std::tuple_element< + 0, std::tuple<Iters...>>::type>::difference_type, + typename ZipLongestTupleType<Iters...>::type *, + typename ZipLongestTupleType<Iters...>::type> { +public: + using value_type = typename ZipLongestTupleType<Iters...>::type; + +private: + std::tuple<Iters...> iterators; + std::tuple<Iters...> end_iterators; + + template <size_t... Ns> + bool test(const zip_longest_iterator<Iters...> &other, + std::index_sequence<Ns...>) const { + return llvm::any_of( + std::initializer_list<bool>{std::get<Ns>(this->iterators) != + std::get<Ns>(other.iterators)...}, + identity<bool>{}); + } + + template <size_t... Ns> value_type deref(std::index_sequence<Ns...>) const { + return value_type( + deref_or_none(std::get<Ns>(iterators), std::get<Ns>(end_iterators))...); + } + + template <size_t... Ns> + decltype(iterators) tup_inc(std::index_sequence<Ns...>) const { + return std::tuple<Iters...>( + next_or_end(std::get<Ns>(iterators), std::get<Ns>(end_iterators))...); + } + +public: + zip_longest_iterator(std::pair<Iters &&, Iters &&>... ts) + : iterators(std::forward<Iters>(ts.first)...), + end_iterators(std::forward<Iters>(ts.second)...) {} + + value_type operator*() { return deref(std::index_sequence_for<Iters...>{}); } + + value_type operator*() const { + return deref(std::index_sequence_for<Iters...>{}); + } + + zip_longest_iterator<Iters...> &operator++() { + iterators = tup_inc(std::index_sequence_for<Iters...>{}); + return *this; + } + + bool operator==(const zip_longest_iterator<Iters...> &other) const { + return !test(other, std::index_sequence_for<Iters...>{}); + } +}; + +template <typename... Args> class zip_longest_range { +public: + using iterator = + zip_longest_iterator<decltype(adl_begin(std::declval<Args>()))...>; + using iterator_category = typename iterator::iterator_category; + using value_type = typename iterator::value_type; + using difference_type = typename iterator::difference_type; + using pointer = typename iterator::pointer; + using reference = typename iterator::reference; + +private: + std::tuple<Args...> ts; + + template <size_t... Ns> + iterator begin_impl(std::index_sequence<Ns...>) const { + return iterator(std::make_pair(adl_begin(std::get<Ns>(ts)), + adl_end(std::get<Ns>(ts)))...); + } + + template <size_t... Ns> iterator end_impl(std::index_sequence<Ns...>) const { + return iterator(std::make_pair(adl_end(std::get<Ns>(ts)), + adl_end(std::get<Ns>(ts)))...); + } + +public: + zip_longest_range(Args &&... ts_) : ts(std::forward<Args>(ts_)...) {} + + iterator begin() const { + return begin_impl(std::index_sequence_for<Args...>{}); + } + iterator end() const { return end_impl(std::index_sequence_for<Args...>{}); } +}; +} // namespace detail + +/// Iterate over two or more iterators at the same time. Iteration continues +/// until all iterators reach the end. The llvm::Optional only contains a value +/// if the iterator has not reached the end. +template <typename T, typename U, typename... Args> +detail::zip_longest_range<T, U, Args...> zip_longest(T &&t, U &&u, + Args &&... args) { + return detail::zip_longest_range<T, U, Args...>( + std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...); +} + +/// Iterator wrapper that concatenates sequences together. +/// +/// This can concatenate different iterators, even with different types, into +/// a single iterator provided the value types of all the concatenated +/// iterators expose `reference` and `pointer` types that can be converted to +/// `ValueT &` and `ValueT *` respectively. It doesn't support more +/// interesting/customized pointer or reference types. +/// +/// Currently this only supports forward or higher iterator categories as +/// inputs and always exposes a forward iterator interface. +template <typename ValueT, typename... IterTs> +class concat_iterator + : public iterator_facade_base<concat_iterator<ValueT, IterTs...>, + std::forward_iterator_tag, ValueT> { + using BaseT = typename concat_iterator::iterator_facade_base; + + /// We store both the current and end iterators for each concatenated + /// sequence in a tuple of pairs. + /// + /// Note that something like iterator_range seems nice at first here, but the + /// range properties are of little benefit and end up getting in the way + /// because we need to do mutation on the current iterators. + std::tuple<IterTs...> Begins; + std::tuple<IterTs...> Ends; + + /// Attempts to increment a specific iterator. + /// + /// Returns true if it was able to increment the iterator. Returns false if + /// the iterator is already at the end iterator. + template <size_t Index> bool incrementHelper() { + auto &Begin = std::get<Index>(Begins); + auto &End = std::get<Index>(Ends); + if (Begin == End) + return false; + + ++Begin; + return true; + } + + /// Increments the first non-end iterator. + /// + /// It is an error to call this with all iterators at the end. + template <size_t... Ns> void increment(std::index_sequence<Ns...>) { + // Build a sequence of functions to increment each iterator if possible. + bool (concat_iterator::*IncrementHelperFns[])() = { + &concat_iterator::incrementHelper<Ns>...}; + + // Loop over them, and stop as soon as we succeed at incrementing one. + for (auto &IncrementHelperFn : IncrementHelperFns) + if ((this->*IncrementHelperFn)()) + return; + + llvm_unreachable("Attempted to increment an end concat iterator!"); + } + + /// Returns null if the specified iterator is at the end. Otherwise, + /// dereferences the iterator and returns the address of the resulting + /// reference. + template <size_t Index> ValueT *getHelper() const { + auto &Begin = std::get<Index>(Begins); + auto &End = std::get<Index>(Ends); + if (Begin == End) + return nullptr; + + return &*Begin; + } + + /// Finds the first non-end iterator, dereferences, and returns the resulting + /// reference. + /// + /// It is an error to call this with all iterators at the end. + template <size_t... Ns> ValueT &get(std::index_sequence<Ns...>) const { + // Build a sequence of functions to get from iterator if possible. + ValueT *(concat_iterator::*GetHelperFns[])() const = { + &concat_iterator::getHelper<Ns>...}; + + // Loop over them, and return the first result we find. + for (auto &GetHelperFn : GetHelperFns) + if (ValueT *P = (this->*GetHelperFn)()) + return *P; + + llvm_unreachable("Attempted to get a pointer from an end concat iterator!"); + } + +public: + /// Constructs an iterator from a squence of ranges. + /// + /// We need the full range to know how to switch between each of the + /// iterators. + template <typename... RangeTs> + explicit concat_iterator(RangeTs &&... Ranges) + : Begins(std::begin(Ranges)...), Ends(std::end(Ranges)...) {} + + using BaseT::operator++; + + concat_iterator &operator++() { + increment(std::index_sequence_for<IterTs...>()); + return *this; + } + + ValueT &operator*() const { + return get(std::index_sequence_for<IterTs...>()); + } + + bool operator==(const concat_iterator &RHS) const { + return Begins == RHS.Begins && Ends == RHS.Ends; + } +}; + +namespace detail { + +/// Helper to store a sequence of ranges being concatenated and access them. +/// +/// This is designed to facilitate providing actual storage when temporaries +/// are passed into the constructor such that we can use it as part of range +/// based for loops. +template <typename ValueT, typename... RangeTs> class concat_range { +public: + using iterator = + concat_iterator<ValueT, + decltype(std::begin(std::declval<RangeTs &>()))...>; + +private: + std::tuple<RangeTs...> Ranges; + + template <size_t... Ns> iterator begin_impl(std::index_sequence<Ns...>) { + return iterator(std::get<Ns>(Ranges)...); + } + template <size_t... Ns> iterator end_impl(std::index_sequence<Ns...>) { + return iterator(make_range(std::end(std::get<Ns>(Ranges)), + std::end(std::get<Ns>(Ranges)))...); + } + +public: + concat_range(RangeTs &&... Ranges) + : Ranges(std::forward<RangeTs>(Ranges)...) {} + + iterator begin() { return begin_impl(std::index_sequence_for<RangeTs...>{}); } + iterator end() { return end_impl(std::index_sequence_for<RangeTs...>{}); } +}; + +} // end namespace detail + +/// Concatenated range across two or more ranges. +/// +/// The desired value type must be explicitly specified. +template <typename ValueT, typename... RangeTs> +detail::concat_range<ValueT, RangeTs...> concat(RangeTs &&... Ranges) { + static_assert(sizeof...(RangeTs) > 1, + "Need more than one range to concatenate!"); + return detail::concat_range<ValueT, RangeTs...>( + std::forward<RangeTs>(Ranges)...); +} + +//===----------------------------------------------------------------------===// +// Extra additions to <utility> +//===----------------------------------------------------------------------===// + +/// Function object to check whether the first component of a std::pair +/// compares less than the first component of another std::pair. +struct less_first { + template <typename T> bool operator()(const T &lhs, const T &rhs) const { + return lhs.first < rhs.first; + } +}; + +/// Function object to check whether the second component of a std::pair +/// compares less than the second component of another std::pair. +struct less_second { + template <typename T> bool operator()(const T &lhs, const T &rhs) const { + return lhs.second < rhs.second; + } +}; + +/// \brief Function object to apply a binary function to the first component of +/// a std::pair. +template<typename FuncTy> +struct on_first { + FuncTy func; + + template <typename T> + auto operator()(const T &lhs, const T &rhs) const + -> decltype(func(lhs.first, rhs.first)) { + return func(lhs.first, rhs.first); + } +}; + +/// Utility type to build an inheritance chain that makes it easy to rank +/// overload candidates. +template <int N> struct rank : rank<N - 1> {}; +template <> struct rank<0> {}; + +/// traits class for checking whether type T is one of any of the given +/// types in the variadic list. +template <typename T, typename... Ts> struct is_one_of { + static const bool value = false; +}; + +template <typename T, typename U, typename... Ts> +struct is_one_of<T, U, Ts...> { + static const bool value = + std::is_same<T, U>::value || is_one_of<T, Ts...>::value; +}; + +/// traits class for checking whether type T is a base class for all +/// the given types in the variadic list. +template <typename T, typename... Ts> struct are_base_of { + static const bool value = true; +}; + +template <typename T, typename U, typename... Ts> +struct are_base_of<T, U, Ts...> { + static const bool value = + std::is_base_of<T, U>::value && are_base_of<T, Ts...>::value; +}; + +//===----------------------------------------------------------------------===// +// Extra additions for arrays +//===----------------------------------------------------------------------===// + +/// Find the length of an array. +template <class T, std::size_t N> +constexpr inline size_t array_lengthof(T (&)[N]) { + return N; +} + +/// Adapt std::less<T> for array_pod_sort. +template<typename T> +inline int array_pod_sort_comparator(const void *P1, const void *P2) { + if (std::less<T>()(*reinterpret_cast<const T*>(P1), + *reinterpret_cast<const T*>(P2))) + return -1; + if (std::less<T>()(*reinterpret_cast<const T*>(P2), + *reinterpret_cast<const T*>(P1))) + return 1; + return 0; +} + +/// get_array_pod_sort_comparator - This is an internal helper function used to +/// get type deduction of T right. +template<typename T> +inline int (*get_array_pod_sort_comparator(const T &)) + (const void*, const void*) { + return array_pod_sort_comparator<T>; +} + +#ifdef EXPENSIVE_CHECKS +namespace detail { + +inline unsigned presortShuffleEntropy() { + static unsigned Result(std::random_device{}()); + return Result; +} + +template <class IteratorTy> +inline void presortShuffle(IteratorTy Start, IteratorTy End) { + std::mt19937 Generator(presortShuffleEntropy()); + std::shuffle(Start, End, Generator); +} + +} // end namespace detail +#endif + +/// array_pod_sort - This sorts an array with the specified start and end +/// extent. This is just like std::sort, except that it calls qsort instead of +/// using an inlined template. qsort is slightly slower than std::sort, but +/// most sorts are not performance critical in LLVM and std::sort has to be +/// template instantiated for each type, leading to significant measured code +/// bloat. This function should generally be used instead of std::sort where +/// possible. +/// +/// This function assumes that you have simple POD-like types that can be +/// compared with std::less and can be moved with memcpy. If this isn't true, +/// you should use std::sort. +/// +/// NOTE: If qsort_r were portable, we could allow a custom comparator and +/// default to std::less. +template<class IteratorTy> +inline void array_pod_sort(IteratorTy Start, IteratorTy End) { + // Don't inefficiently call qsort with one element or trigger undefined + // behavior with an empty sequence. + auto NElts = End - Start; + if (NElts <= 1) return; +#ifdef EXPENSIVE_CHECKS + detail::presortShuffle<IteratorTy>(Start, End); +#endif + qsort(&*Start, NElts, sizeof(*Start), get_array_pod_sort_comparator(*Start)); +} + +template <class IteratorTy> +inline void array_pod_sort( + IteratorTy Start, IteratorTy End, + int (*Compare)( + const typename std::iterator_traits<IteratorTy>::value_type *, + const typename std::iterator_traits<IteratorTy>::value_type *)) { + // Don't inefficiently call qsort with one element or trigger undefined + // behavior with an empty sequence. + auto NElts = End - Start; + if (NElts <= 1) return; +#ifdef EXPENSIVE_CHECKS + detail::presortShuffle<IteratorTy>(Start, End); +#endif + qsort(&*Start, NElts, sizeof(*Start), + reinterpret_cast<int (*)(const void *, const void *)>(Compare)); +} + +// Provide wrappers to std::sort which shuffle the elements before sorting +// to help uncover non-deterministic behavior (PR35135). +template <typename IteratorTy> +inline void sort(IteratorTy Start, IteratorTy End) { +#ifdef EXPENSIVE_CHECKS + detail::presortShuffle<IteratorTy>(Start, End); +#endif + std::sort(Start, End); +} + +template <typename Container> inline void sort(Container &&C) { + llvm::sort(adl_begin(C), adl_end(C)); +} + +template <typename IteratorTy, typename Compare> +inline void sort(IteratorTy Start, IteratorTy End, Compare Comp) { +#ifdef EXPENSIVE_CHECKS + detail::presortShuffle<IteratorTy>(Start, End); +#endif + std::sort(Start, End, Comp); +} + +template <typename Container, typename Compare> +inline void sort(Container &&C, Compare Comp) { + llvm::sort(adl_begin(C), adl_end(C), Comp); +} + +//===----------------------------------------------------------------------===// +// Extra additions to <algorithm> +//===----------------------------------------------------------------------===// + +/// For a container of pointers, deletes the pointers and then clears the +/// container. +template<typename Container> +void DeleteContainerPointers(Container &C) { + for (auto V : C) + delete V; + C.clear(); +} + +/// In a container of pairs (usually a map) whose second element is a pointer, +/// deletes the second elements and then clears the container. +template<typename Container> +void DeleteContainerSeconds(Container &C) { + for (auto &V : C) + delete V.second; + C.clear(); +} + +/// Get the size of a range. This is a wrapper function around std::distance +/// which is only enabled when the operation is O(1). +template <typename R> +auto size(R &&Range, typename std::enable_if< + std::is_same<typename std::iterator_traits<decltype( + Range.begin())>::iterator_category, + std::random_access_iterator_tag>::value, + void>::type * = nullptr) + -> decltype(std::distance(Range.begin(), Range.end())) { + return std::distance(Range.begin(), Range.end()); +} + +/// Provide wrappers to std::for_each which take ranges instead of having to +/// pass begin/end explicitly. +template <typename R, typename UnaryPredicate> +UnaryPredicate for_each(R &&Range, UnaryPredicate P) { + return std::for_each(adl_begin(Range), adl_end(Range), P); +} + +/// Provide wrappers to std::all_of which take ranges instead of having to pass +/// begin/end explicitly. +template <typename R, typename UnaryPredicate> +bool all_of(R &&Range, UnaryPredicate P) { + return std::all_of(adl_begin(Range), adl_end(Range), P); +} + +/// Provide wrappers to std::any_of which take ranges instead of having to pass +/// begin/end explicitly. +template <typename R, typename UnaryPredicate> +bool any_of(R &&Range, UnaryPredicate P) { + return std::any_of(adl_begin(Range), adl_end(Range), P); +} + +/// Provide wrappers to std::none_of which take ranges instead of having to pass +/// begin/end explicitly. +template <typename R, typename UnaryPredicate> +bool none_of(R &&Range, UnaryPredicate P) { + return std::none_of(adl_begin(Range), adl_end(Range), P); +} + +/// Provide wrappers to std::find which take ranges instead of having to pass +/// begin/end explicitly. +template <typename R, typename T> +auto find(R &&Range, const T &Val) -> decltype(adl_begin(Range)) { + return std::find(adl_begin(Range), adl_end(Range), Val); +} + +/// Provide wrappers to std::find_if which take ranges instead of having to pass +/// begin/end explicitly. +template <typename R, typename UnaryPredicate> +auto find_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) { + return std::find_if(adl_begin(Range), adl_end(Range), P); +} + +template <typename R, typename UnaryPredicate> +auto find_if_not(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) { + return std::find_if_not(adl_begin(Range), adl_end(Range), P); +} + +/// Provide wrappers to std::remove_if which take ranges instead of having to +/// pass begin/end explicitly. +template <typename R, typename UnaryPredicate> +auto remove_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) { + return std::remove_if(adl_begin(Range), adl_end(Range), P); +} + +/// Provide wrappers to std::copy_if which take ranges instead of having to +/// pass begin/end explicitly. +template <typename R, typename OutputIt, typename UnaryPredicate> +OutputIt copy_if(R &&Range, OutputIt Out, UnaryPredicate P) { + return std::copy_if(adl_begin(Range), adl_end(Range), Out, P); +} + +template <typename R, typename OutputIt> +OutputIt copy(R &&Range, OutputIt Out) { + return std::copy(adl_begin(Range), adl_end(Range), Out); +} + +/// 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(adl_begin(Range), adl_end(Range), Element) != adl_end(Range); +} + +/// Wrapper function around std::count to count the number of times an element +/// \p Element occurs in the given range \p Range. +template <typename R, typename E> +auto count(R &&Range, const E &Element) -> + typename std::iterator_traits<decltype(adl_begin(Range))>::difference_type { + return std::count(adl_begin(Range), adl_end(Range), Element); +} + +/// 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(adl_begin(Range))>::difference_type { + return std::count_if(adl_begin(Range), adl_end(Range), P); +} + +/// Wrapper function around std::transform to apply a function to a range and +/// store the result elsewhere. +template <typename R, typename OutputIt, typename UnaryPredicate> +OutputIt transform(R &&Range, OutputIt d_first, UnaryPredicate P) { + return std::transform(adl_begin(Range), adl_end(Range), d_first, P); +} + +/// Provide wrappers to std::partition which take ranges instead of having to +/// pass begin/end explicitly. +template <typename R, typename UnaryPredicate> +auto partition(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) { + return std::partition(adl_begin(Range), adl_end(Range), P); +} + +/// Provide wrappers to std::lower_bound which take ranges instead of having to +/// pass begin/end explicitly. +template <typename R, typename T> +auto lower_bound(R &&Range, T &&Value) -> decltype(adl_begin(Range)) { + return std::lower_bound(adl_begin(Range), adl_end(Range), + std::forward<T>(Value)); +} + +template <typename R, typename T, typename Compare> +auto lower_bound(R &&Range, T &&Value, Compare C) + -> decltype(adl_begin(Range)) { + return std::lower_bound(adl_begin(Range), adl_end(Range), + std::forward<T>(Value), C); +} + +/// Provide wrappers to std::upper_bound which take ranges instead of having to +/// pass begin/end explicitly. +template <typename R, typename T> +auto upper_bound(R &&Range, T &&Value) -> decltype(adl_begin(Range)) { + return std::upper_bound(adl_begin(Range), adl_end(Range), + std::forward<T>(Value)); +} + +template <typename R, typename T, typename Compare> +auto upper_bound(R &&Range, T &&Value, Compare C) + -> decltype(adl_begin(Range)) { + return std::upper_bound(adl_begin(Range), adl_end(Range), + std::forward<T>(Value), C); +} + +template <typename R> +void stable_sort(R &&Range) { + std::stable_sort(adl_begin(Range), adl_end(Range)); +} + +template <typename R, typename Compare> +void stable_sort(R &&Range, Compare C) { + std::stable_sort(adl_begin(Range), adl_end(Range), C); +} + +/// Binary search for the first iterator in a range where a predicate is false. +/// Requires that C is always true below some limit, and always false above it. +template <typename R, typename Predicate, + typename Val = decltype(*adl_begin(std::declval<R>()))> +auto partition_point(R &&Range, Predicate P) -> decltype(adl_begin(Range)) { + return std::partition_point(adl_begin(Range), adl_end(Range), P); +} + +/// Wrapper function around std::equal to detect if all elements +/// in a container are same. +template <typename R> +bool is_splat(R &&Range) { + size_t range_size = size(Range); + return range_size != 0 && (range_size == 1 || + std::equal(adl_begin(Range) + 1, adl_end(Range), adl_begin(Range))); +} + +/// Provide a container algorithm similar to C++ Library Fundamentals v2's +/// `erase_if` which is equivalent to: +/// +/// C.erase(remove_if(C, pred), C.end()); +/// +/// This version works for any container with an erase method call accepting +/// two iterators. +template <typename Container, typename UnaryPredicate> +void erase_if(Container &C, UnaryPredicate P) { + C.erase(remove_if(C, P), C.end()); +} + +/// Given a sequence container Cont, replace the range [ContIt, ContEnd) with +/// the range [ValIt, ValEnd) (which is not from the same container). +template<typename Container, typename RandomAccessIterator> +void replace(Container &Cont, typename Container::iterator ContIt, + typename Container::iterator ContEnd, RandomAccessIterator ValIt, + RandomAccessIterator ValEnd) { + while (true) { + if (ValIt == ValEnd) { + Cont.erase(ContIt, ContEnd); + return; + } else if (ContIt == ContEnd) { + Cont.insert(ContIt, ValIt, ValEnd); + return; + } + *ContIt++ = *ValIt++; + } +} + +/// Given a sequence container Cont, replace the range [ContIt, ContEnd) with +/// the range R. +template<typename Container, typename Range = std::initializer_list< + typename Container::value_type>> +void replace(Container &Cont, typename Container::iterator ContIt, + typename Container::iterator ContEnd, Range R) { + replace(Cont, ContIt, ContEnd, R.begin(), R.end()); +} + +//===----------------------------------------------------------------------===// +// Extra additions to <memory> +//===----------------------------------------------------------------------===// + +struct FreeDeleter { + void operator()(void* v) { + ::free(v); + } +}; + +template<typename First, typename Second> +struct pair_hash { + size_t operator()(const std::pair<First, Second> &P) const { + return std::hash<First>()(P.first) * 31 + std::hash<Second>()(P.second); + } +}; + +/// Binary functor that adapts to any other binary functor after dereferencing +/// operands. +template <typename T> struct deref { + T func; + + // Could be further improved to cope with non-derivable functors and + // non-binary functors (should be a variadic template member function + // operator()). + template <typename A, typename B> + auto operator()(A &lhs, B &rhs) const -> decltype(func(*lhs, *rhs)) { + assert(lhs); + assert(rhs); + return func(*lhs, *rhs); + } +}; + +namespace detail { + +template <typename R> class enumerator_iter; + +template <typename R> struct result_pair { + using value_reference = + typename std::iterator_traits<IterOfRange<R>>::reference; + + friend class enumerator_iter<R>; + + result_pair() = default; + result_pair(std::size_t Index, IterOfRange<R> Iter) + : Index(Index), Iter(Iter) {} + + result_pair<R>(const result_pair<R> &Other) + : Index(Other.Index), Iter(Other.Iter) {} + result_pair<R> &operator=(const result_pair<R> &Other) { + Index = Other.Index; + Iter = Other.Iter; + return *this; + } + + std::size_t index() const { return Index; } + const value_reference value() const { return *Iter; } + value_reference value() { return *Iter; } + +private: + std::size_t Index = std::numeric_limits<std::size_t>::max(); + IterOfRange<R> Iter; +}; + +template <typename R> +class enumerator_iter + : public iterator_facade_base< + enumerator_iter<R>, std::forward_iterator_tag, result_pair<R>, + typename std::iterator_traits<IterOfRange<R>>::difference_type, + typename std::iterator_traits<IterOfRange<R>>::pointer, + typename std::iterator_traits<IterOfRange<R>>::reference> { + using result_type = result_pair<R>; + +public: + explicit enumerator_iter(IterOfRange<R> EndIter) + : Result(std::numeric_limits<size_t>::max(), EndIter) {} + + enumerator_iter(std::size_t Index, IterOfRange<R> Iter) + : Result(Index, Iter) {} + + result_type &operator*() { return Result; } + const result_type &operator*() const { return Result; } + + enumerator_iter<R> &operator++() { + assert(Result.Index != std::numeric_limits<size_t>::max()); + ++Result.Iter; + ++Result.Index; + return *this; + } + + bool operator==(const enumerator_iter<R> &RHS) const { + // Don't compare indices here, only iterators. It's possible for an end + // iterator to have different indices depending on whether it was created + // by calling std::end() versus incrementing a valid iterator. + return Result.Iter == RHS.Result.Iter; + } + + enumerator_iter<R>(const enumerator_iter<R> &Other) : Result(Other.Result) {} + enumerator_iter<R> &operator=(const enumerator_iter<R> &Other) { + Result = Other.Result; + return *this; + } + +private: + result_type Result; +}; + +template <typename R> class enumerator { +public: + explicit enumerator(R &&Range) : TheRange(std::forward<R>(Range)) {} + + enumerator_iter<R> begin() { + return enumerator_iter<R>(0, std::begin(TheRange)); + } + + enumerator_iter<R> end() { + return enumerator_iter<R>(std::end(TheRange)); + } + +private: + R TheRange; +}; + +} // end namespace detail + +/// Given an input range, returns a new range whose values are are pair (A,B) +/// such that A is the 0-based index of the item in the sequence, and B is +/// the value from the original sequence. Example: +/// +/// std::vector<char> Items = {'A', 'B', 'C', 'D'}; +/// for (auto X : enumerate(Items)) { +/// printf("Item %d - %c\n", X.index(), X.value()); +/// } +/// +/// Output: +/// Item 0 - A +/// Item 1 - B +/// Item 2 - C +/// Item 3 - D +/// +template <typename R> detail::enumerator<R> enumerate(R &&TheRange) { + return detail::enumerator<R>(std::forward<R>(TheRange)); +} + +namespace detail { + +template <typename F, typename Tuple, std::size_t... I> +auto apply_tuple_impl(F &&f, Tuple &&t, std::index_sequence<I...>) + -> decltype(std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...)) { + return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...); +} + +} // end namespace detail + +/// Given an input tuple (a1, a2, ..., an), pass the arguments of the +/// tuple variadically to f as if by calling f(a1, a2, ..., an) and +/// return the result. +template <typename F, typename Tuple> +auto apply_tuple(F &&f, Tuple &&t) -> decltype(detail::apply_tuple_impl( + std::forward<F>(f), std::forward<Tuple>(t), + std::make_index_sequence< + std::tuple_size<typename std::decay<Tuple>::type>::value>{})) { + using Indices = std::make_index_sequence< + std::tuple_size<typename std::decay<Tuple>::type>::value>; + + return detail::apply_tuple_impl(std::forward<F>(f), std::forward<Tuple>(t), + Indices{}); +} + +/// Return true if the sequence [Begin, End) has exactly N items. Runs in O(N) +/// time. Not meant for use with random-access iterators. +template <typename IterTy> +bool hasNItems( + IterTy &&Begin, IterTy &&End, unsigned N, + typename std::enable_if< + !std::is_same< + typename std::iterator_traits<typename std::remove_reference< + decltype(Begin)>::type>::iterator_category, + std::random_access_iterator_tag>::value, + void>::type * = nullptr) { + for (; N; --N, ++Begin) + if (Begin == End) + return false; // Too few. + return Begin == End; +} + +/// Return true if the sequence [Begin, End) has N or more items. Runs in O(N) +/// time. Not meant for use with random-access iterators. +template <typename IterTy> +bool hasNItemsOrMore( + IterTy &&Begin, IterTy &&End, unsigned N, + typename std::enable_if< + !std::is_same< + typename std::iterator_traits<typename std::remove_reference< + decltype(Begin)>::type>::iterator_category, + std::random_access_iterator_tag>::value, + void>::type * = nullptr) { + for (; N; --N, ++Begin) + if (Begin == End) + return false; // Too few. + return true; +} + +/// Returns a raw pointer that represents the same address as the argument. +/// +/// The late bound return should be removed once we move to C++14 to better +/// align with the C++20 declaration. Also, this implementation can be removed +/// once we move to C++20 where it's defined as std::to_addres() +/// +/// The std::pointer_traits<>::to_address(p) variations of these overloads has +/// not been implemented. +template <class Ptr> auto to_address(const Ptr &P) -> decltype(P.operator->()) { + return P.operator->(); +} +template <class T> constexpr T *to_address(T *P) { return P; } + +} // end namespace llvm + +#endif // LLVM_ADT_STLEXTRAS_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/ScopeExit.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/ScopeExit.h new file mode 100644 index 0000000..712d912 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/ScopeExit.h
@@ -0,0 +1,65 @@ +//===- llvm/ADT/ScopeExit.h - Execute code at scope exit --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the make_scope_exit function, which executes user-defined +// cleanup logic at scope exit. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SCOPE_EXIT_H +#define LLVM_ADT_SCOPE_EXIT_H + +#include "llvm/Support/Compiler.h" + +#include <type_traits> +#include <utility> + +namespace llvm { +namespace detail { + +template <typename Callable> class scope_exit { + Callable ExitFunction; + bool Engaged = true; // False once moved-from or release()d. + +public: + template <typename Fp> + explicit scope_exit(Fp &&F) : ExitFunction(std::forward<Fp>(F)) {} + + scope_exit(scope_exit &&Rhs) + : ExitFunction(std::move(Rhs.ExitFunction)), Engaged(Rhs.Engaged) { + Rhs.release(); + } + scope_exit(const scope_exit &) = delete; + scope_exit &operator=(scope_exit &&) = delete; + scope_exit &operator=(const scope_exit &) = delete; + + void release() { Engaged = false; } + + ~scope_exit() { + if (Engaged) + ExitFunction(); + } +}; + +} // end namespace detail + +// Keeps the callable object that is passed in, and execute it at the +// destruction of the returned object (usually at the scope exit where the +// returned object is kept). +// +// Interface is specified by p0052r2. +template <typename Callable> +LLVM_NODISCARD detail::scope_exit<typename std::decay<Callable>::type> +make_scope_exit(Callable &&F) { + return detail::scope_exit<typename std::decay<Callable>::type>( + std::forward<Callable>(F)); +} + +} // end namespace llvm + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/ScopedHashTable.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/ScopedHashTable.h new file mode 100644 index 0000000..40c49eb --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/ScopedHashTable.h
@@ -0,0 +1,263 @@ +//===- ScopedHashTable.h - A simple scoped hash table -----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements an efficient scoped hash table, which is useful for +// things like dominator-based optimizations. This allows clients to do things +// like this: +// +// ScopedHashTable<int, int> HT; +// { +// ScopedHashTableScope<int, int> Scope1(HT); +// HT.insert(0, 0); +// HT.insert(1, 1); +// { +// ScopedHashTableScope<int, int> Scope2(HT); +// HT.insert(0, 42); +// } +// } +// +// Looking up the value for "0" in the Scope2 block will return 42. Looking +// up the value for 0 before 42 is inserted or after Scope2 is popped will +// return 0. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SCOPEDHASHTABLE_H +#define LLVM_ADT_SCOPEDHASHTABLE_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/Support/Allocator.h" +#include <cassert> +#include <new> + +namespace llvm { + +template <typename K, typename V, typename KInfo = DenseMapInfo<K>, + typename AllocatorTy = MallocAllocator> +class ScopedHashTable; + +template <typename K, typename V> +class ScopedHashTableVal { + ScopedHashTableVal *NextInScope; + ScopedHashTableVal *NextForKey; + K Key; + V Val; + + ScopedHashTableVal(const K &key, const V &val) : Key(key), Val(val) {} + +public: + const K &getKey() const { return Key; } + const V &getValue() const { return Val; } + V &getValue() { return Val; } + + ScopedHashTableVal *getNextForKey() { return NextForKey; } + const ScopedHashTableVal *getNextForKey() const { return NextForKey; } + ScopedHashTableVal *getNextInScope() { return NextInScope; } + + template <typename AllocatorTy> + static ScopedHashTableVal *Create(ScopedHashTableVal *nextInScope, + ScopedHashTableVal *nextForKey, + const K &key, const V &val, + AllocatorTy &Allocator) { + ScopedHashTableVal *New = Allocator.template Allocate<ScopedHashTableVal>(); + // Set up the value. + new (New) ScopedHashTableVal(key, val); + New->NextInScope = nextInScope; + New->NextForKey = nextForKey; + return New; + } + + template <typename AllocatorTy> void Destroy(AllocatorTy &Allocator) { + // Free memory referenced by the item. + this->~ScopedHashTableVal(); + Allocator.Deallocate(this); + } +}; + +template <typename K, typename V, typename KInfo = DenseMapInfo<K>, + typename AllocatorTy = MallocAllocator> +class ScopedHashTableScope { + /// HT - The hashtable that we are active for. + ScopedHashTable<K, V, KInfo, AllocatorTy> &HT; + + /// PrevScope - This is the scope that we are shadowing in HT. + ScopedHashTableScope *PrevScope; + + /// LastValInScope - This is the last value that was inserted for this scope + /// or null if none have been inserted yet. + ScopedHashTableVal<K, V> *LastValInScope; + +public: + ScopedHashTableScope(ScopedHashTable<K, V, KInfo, AllocatorTy> &HT); + ScopedHashTableScope(ScopedHashTableScope &) = delete; + ScopedHashTableScope &operator=(ScopedHashTableScope &) = delete; + ~ScopedHashTableScope(); + + ScopedHashTableScope *getParentScope() { return PrevScope; } + const ScopedHashTableScope *getParentScope() const { return PrevScope; } + +private: + friend class ScopedHashTable<K, V, KInfo, AllocatorTy>; + + ScopedHashTableVal<K, V> *getLastValInScope() { + return LastValInScope; + } + + void setLastValInScope(ScopedHashTableVal<K, V> *Val) { + LastValInScope = Val; + } +}; + +template <typename K, typename V, typename KInfo = DenseMapInfo<K>> +class ScopedHashTableIterator { + ScopedHashTableVal<K, V> *Node; + +public: + ScopedHashTableIterator(ScopedHashTableVal<K, V> *node) : Node(node) {} + + V &operator*() const { + assert(Node && "Dereference end()"); + return Node->getValue(); + } + V *operator->() const { + return &Node->getValue(); + } + + bool operator==(const ScopedHashTableIterator &RHS) const { + return Node == RHS.Node; + } + bool operator!=(const ScopedHashTableIterator &RHS) const { + return Node != RHS.Node; + } + + inline ScopedHashTableIterator& operator++() { // Preincrement + assert(Node && "incrementing past end()"); + Node = Node->getNextForKey(); + return *this; + } + ScopedHashTableIterator operator++(int) { // Postincrement + ScopedHashTableIterator tmp = *this; ++*this; return tmp; + } +}; + +template <typename K, typename V, typename KInfo, typename AllocatorTy> +class ScopedHashTable { +public: + /// ScopeTy - This is a helpful typedef that allows clients to get easy access + /// to the name of the scope for this hash table. + using ScopeTy = ScopedHashTableScope<K, V, KInfo, AllocatorTy>; + using size_type = unsigned; + +private: + friend class ScopedHashTableScope<K, V, KInfo, AllocatorTy>; + + using ValTy = ScopedHashTableVal<K, V>; + + DenseMap<K, ValTy*, KInfo> TopLevelMap; + ScopeTy *CurScope = nullptr; + + AllocatorTy Allocator; + +public: + ScopedHashTable() = default; + ScopedHashTable(AllocatorTy A) : Allocator(A) {} + ScopedHashTable(const ScopedHashTable &) = delete; + ScopedHashTable &operator=(const ScopedHashTable &) = delete; + + ~ScopedHashTable() { + assert(!CurScope && TopLevelMap.empty() && "Scope imbalance!"); + } + + /// Access to the allocator. + AllocatorTy &getAllocator() { return Allocator; } + const AllocatorTy &getAllocator() const { return Allocator; } + + /// Return 1 if the specified key is in the table, 0 otherwise. + size_type count(const K &Key) const { + return TopLevelMap.count(Key); + } + + V lookup(const K &Key) const { + auto I = TopLevelMap.find(Key); + if (I != TopLevelMap.end()) + return I->second->getValue(); + + return V(); + } + + void insert(const K &Key, const V &Val) { + insertIntoScope(CurScope, Key, Val); + } + + using iterator = ScopedHashTableIterator<K, V, KInfo>; + + iterator end() { return iterator(0); } + + iterator begin(const K &Key) { + typename DenseMap<K, ValTy*, KInfo>::iterator I = + TopLevelMap.find(Key); + if (I == TopLevelMap.end()) return end(); + return iterator(I->second); + } + + ScopeTy *getCurScope() { return CurScope; } + const ScopeTy *getCurScope() const { return CurScope; } + + /// insertIntoScope - This inserts the specified key/value at the specified + /// (possibly not the current) scope. While it is ok to insert into a scope + /// that isn't the current one, it isn't ok to insert *underneath* an existing + /// value of the specified key. + void insertIntoScope(ScopeTy *S, const K &Key, const V &Val) { + assert(S && "No scope active!"); + ScopedHashTableVal<K, V> *&KeyEntry = TopLevelMap[Key]; + KeyEntry = ValTy::Create(S->getLastValInScope(), KeyEntry, Key, Val, + Allocator); + S->setLastValInScope(KeyEntry); + } +}; + +/// ScopedHashTableScope ctor - Install this as the current scope for the hash +/// table. +template <typename K, typename V, typename KInfo, typename Allocator> +ScopedHashTableScope<K, V, KInfo, Allocator>:: + ScopedHashTableScope(ScopedHashTable<K, V, KInfo, Allocator> &ht) : HT(ht) { + PrevScope = HT.CurScope; + HT.CurScope = this; + LastValInScope = nullptr; +} + +template <typename K, typename V, typename KInfo, typename Allocator> +ScopedHashTableScope<K, V, KInfo, Allocator>::~ScopedHashTableScope() { + assert(HT.CurScope == this && "Scope imbalance!"); + HT.CurScope = PrevScope; + + // Pop and delete all values corresponding to this scope. + while (ScopedHashTableVal<K, V> *ThisEntry = LastValInScope) { + // Pop this value out of the TopLevelMap. + if (!ThisEntry->getNextForKey()) { + assert(HT.TopLevelMap[ThisEntry->getKey()] == ThisEntry && + "Scope imbalance!"); + HT.TopLevelMap.erase(ThisEntry->getKey()); + } else { + ScopedHashTableVal<K, V> *&KeyEntry = HT.TopLevelMap[ThisEntry->getKey()]; + assert(KeyEntry == ThisEntry && "Scope imbalance!"); + KeyEntry = ThisEntry->getNextForKey(); + } + + // Pop this value out of the scope. + LastValInScope = ThisEntry->getNextInScope(); + + // Delete this entry. + ThisEntry->Destroy(HT.getAllocator()); + } +} + +} // end namespace llvm + +#endif // LLVM_ADT_SCOPEDHASHTABLE_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/Sequence.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/Sequence.h new file mode 100644 index 0000000..8c505f2 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/Sequence.h
@@ -0,0 +1,83 @@ +//===- Sequence.h - Utility for producing sequences of values ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// \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_SEQUENCE_H +#define LLVM_ADT_SEQUENCE_H + +#include "llvm/ADT/iterator.h" +#include "llvm/ADT/iterator_range.h" +#include <algorithm> +#include <iterator> +#include <utility> + +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> { + using BaseT = typename value_sequence_iterator::iterator_facade_base; + + ValueT Value; + +public: + using difference_type = typename BaseT::difference_type; + using reference = typename BaseT::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 namespace detail + +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)); +} + +} // end namespace llvm + +#endif // LLVM_ADT_SEQUENCE_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/SetOperations.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/SetOperations.h new file mode 100644 index 0000000..037256a --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/SetOperations.h
@@ -0,0 +1,70 @@ +//===-- llvm/ADT/SetOperations.h - Generic Set Operations -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines generic set operations that may be used on set's of +// different types, and different element types. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SETOPERATIONS_H +#define LLVM_ADT_SETOPERATIONS_H + +namespace llvm { + +/// set_union(A, B) - Compute A := A u B, return whether A changed. +/// +template <class S1Ty, class S2Ty> +bool set_union(S1Ty &S1, const S2Ty &S2) { + bool Changed = false; + + for (typename S2Ty::const_iterator SI = S2.begin(), SE = S2.end(); + SI != SE; ++SI) + if (S1.insert(*SI).second) + Changed = true; + + return Changed; +} + +/// set_intersect(A, B) - Compute A := A ^ B +/// Identical to set_intersection, except that it works on set<>'s and +/// is nicer to use. Functionally, this iterates through S1, removing +/// elements that are not contained in S2. +/// +template <class S1Ty, class S2Ty> +void set_intersect(S1Ty &S1, const S2Ty &S2) { + for (typename S1Ty::iterator I = S1.begin(); I != S1.end();) { + const auto &E = *I; + ++I; + if (!S2.count(E)) S1.erase(E); // Erase element if not in S2 + } +} + +/// set_difference(A, B) - Return A - B +/// +template <class S1Ty, class S2Ty> +S1Ty set_difference(const S1Ty &S1, const S2Ty &S2) { + S1Ty Result; + for (typename S1Ty::const_iterator SI = S1.begin(), SE = S1.end(); + SI != SE; ++SI) + if (!S2.count(*SI)) // if the element is not in set2 + Result.insert(*SI); + return Result; +} + +/// set_subtract(A, B) - Compute A := A - B +/// +template <class S1Ty, class S2Ty> +void set_subtract(S1Ty &S1, const S2Ty &S2) { + for (typename S2Ty::const_iterator SI = S2.begin(), SE = S2.end(); + SI != SE; ++SI) + S1.erase(*SI); +} + +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/SetVector.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/SetVector.h new file mode 100644 index 0000000..d0a0d28 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/SetVector.h
@@ -0,0 +1,311 @@ +//===- llvm/ADT/SetVector.h - Set with insert order iteration ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements a set that has insertion order iteration +// characteristics. This is useful for keeping a set of things that need to be +// visited later but in a deterministic order (insertion order). The interface +// is purposefully minimal. +// +// This file defines SetVector and SmallSetVector, which performs no allocations +// if the SetVector has less than a certain number of elements. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SETVECTOR_H +#define LLVM_ADT_SETVECTOR_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Compiler.h" +#include <algorithm> +#include <cassert> +#include <iterator> +#include <vector> + +namespace llvm { + +/// A vector that has set insertion semantics. +/// +/// This adapter class provides a way to keep a set of things that also has the +/// property of a deterministic iteration order. The order of iteration is the +/// order of insertion. +template <typename T, typename Vector = std::vector<T>, + typename Set = DenseSet<T>> +class SetVector { +public: + using value_type = T; + using key_type = T; + using reference = T&; + using const_reference = const T&; + using set_type = Set; + using vector_type = Vector; + using iterator = typename vector_type::const_iterator; + using const_iterator = typename vector_type::const_iterator; + using reverse_iterator = typename vector_type::const_reverse_iterator; + using const_reverse_iterator = typename vector_type::const_reverse_iterator; + using size_type = typename vector_type::size_type; + + /// Construct an empty SetVector + SetVector() = default; + + /// Initialize a SetVector with a range of elements + template<typename It> + SetVector(It Start, It End) { + insert(Start, End); + } + + ArrayRef<T> getArrayRef() const { return vector_; } + + /// Clear the SetVector and return the underlying vector. + Vector takeVector() { + set_.clear(); + return std::move(vector_); + } + + /// Determine if the SetVector is empty or not. + bool empty() const { + return vector_.empty(); + } + + /// Determine the number of elements in the SetVector. + size_type size() const { + return vector_.size(); + } + + /// Get an iterator to the beginning of the SetVector. + iterator begin() { + return vector_.begin(); + } + + /// Get a const_iterator to the beginning of the SetVector. + const_iterator begin() const { + return vector_.begin(); + } + + /// Get an iterator to the end of the SetVector. + iterator end() { + return vector_.end(); + } + + /// Get a const_iterator to the end of the SetVector. + const_iterator end() const { + return vector_.end(); + } + + /// Get an reverse_iterator to the end of the SetVector. + reverse_iterator rbegin() { + return vector_.rbegin(); + } + + /// Get a const_reverse_iterator to the end of the SetVector. + const_reverse_iterator rbegin() const { + return vector_.rbegin(); + } + + /// Get a reverse_iterator to the beginning of the SetVector. + reverse_iterator rend() { + return vector_.rend(); + } + + /// Get a const_reverse_iterator to the beginning of the SetVector. + const_reverse_iterator rend() const { + return vector_.rend(); + } + + /// Return the first element of the SetVector. + const T &front() const { + assert(!empty() && "Cannot call front() on empty SetVector!"); + return vector_.front(); + } + + /// Return the last element of the SetVector. + const T &back() const { + assert(!empty() && "Cannot call back() on empty SetVector!"); + return vector_.back(); + } + + /// Index into the SetVector. + const_reference operator[](size_type n) const { + assert(n < vector_.size() && "SetVector access out of range!"); + return vector_[n]; + } + + /// Insert a new element 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) + vector_.push_back(X); + return result; + } + + /// Insert a range of elements into the SetVector. + template<typename It> + void insert(It Start, It End) { + for (; Start != End; ++Start) + if (set_.insert(*Start).second) + vector_.push_back(*Start); + } + + /// Remove an item from the set vector. + bool remove(const value_type& X) { + if (set_.erase(X)) { + typename vector_type::iterator I = find(vector_, X); + assert(I != vector_.end() && "Corrupted SetVector instances!"); + vector_.erase(I); + return true; + } + 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); + } + + /// Remove 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(remove_if(V, P), V.end()); + /// \endcode + /// + /// However, SetVector 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 remove_if(UnaryPredicate P) { + typename vector_type::iterator I = + llvm::remove_if(vector_, TestAndEraseFromSet<UnaryPredicate>(P, set_)); + if (I == vector_.end()) + return false; + vector_.erase(I, vector_.end()); + return true; + } + + /// Count the number of elements of a given key in the SetVector. + /// \returns 0 if the element is not in the SetVector, 1 if it is. + size_type count(const key_type &key) const { + return set_.count(key); + } + + /// Completely clear the SetVector + void clear() { + set_.clear(); + vector_.clear(); + } + + /// Remove the last element of the SetVector. + void pop_back() { + assert(!empty() && "Cannot remove an element from an empty SetVector!"); + set_.erase(back()); + vector_.pop_back(); + } + + LLVM_NODISCARD T pop_back_val() { + T Ret = back(); + pop_back(); + return Ret; + } + + bool operator==(const SetVector &that) const { + return vector_ == that.vector_; + } + + bool operator!=(const SetVector &that) const { + return vector_ != that.vector_; + } + + /// 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; + } + + /// 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: + /// A wrapper predicate designed for use with std::remove_if. + /// + /// This predicate wraps a predicate suitable for use with std::remove_if to + /// call set_.erase(x) on each element which is slated for removal. + template <typename UnaryPredicate> + class TestAndEraseFromSet { + UnaryPredicate P; + set_type &set_; + + public: + TestAndEraseFromSet(UnaryPredicate P, set_type &set_) + : P(std::move(P)), set_(set_) {} + + template <typename ArgumentT> + bool operator()(const ArgumentT &Arg) { + if (P(Arg)) { + set_.erase(Arg); + return true; + } + return false; + } + }; + + set_type set_; ///< The set. + vector_type vector_; ///< The vector. +}; + +/// A SetVector that performs no allocations if smaller than +/// a certain size. +template <typename T, unsigned N> +class SmallSetVector + : public SetVector<T, SmallVector<T, N>, SmallDenseSet<T, N>> { +public: + SmallSetVector() = default; + + /// Initialize a SmallSetVector with a range of elements + template<typename It> + SmallSetVector(It Start, It End) { + this->insert(Start, End); + } +}; + +} // end namespace llvm + +#endif // LLVM_ADT_SETVECTOR_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/SmallBitVector.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/SmallBitVector.h new file mode 100644 index 0000000..61375c0 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/SmallBitVector.h
@@ -0,0 +1,714 @@ +//===- llvm/ADT/SmallBitVector.h - 'Normally small' bit vectors -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the SmallBitVector class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SMALLBITVECTOR_H +#define LLVM_ADT_SMALLBITVECTOR_H + +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/MathExtras.h" +#include <algorithm> +#include <cassert> +#include <climits> +#include <cstddef> +#include <cstdint> +#include <limits> +#include <utility> + +namespace llvm { + +/// 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 + // pointer to memory containing size, allocation size, and the array of bits. + uintptr_t X = 1; + + enum { + // The number of bits in this class. + NumBaseBits = sizeof(uintptr_t) * CHAR_BIT, + + // One bit is used to discriminate between small and large mode. The + // remaining bits are used for the small-mode representation. + SmallNumRawBits = NumBaseBits - 1, + + // A few more bits are used to store the size of the bit set in small mode. + // Theoretically this is a ceil-log2. These bits are encoded in the most + // significant bits of the raw bits. + SmallNumSizeBits = (NumBaseBits == 32 ? 5 : + NumBaseBits == 64 ? 6 : + SmallNumRawBits), + + // The remaining bits are used to store the actual set in small mode. + SmallNumDataBits = SmallNumRawBits - SmallNumSizeBits + }; + + static_assert(NumBaseBits == 64 || NumBaseBits == 32, + "Unsupported word size"); + +public: + using size_type = unsigned; + + // Encapsulation of a single bit. + class reference { + SmallBitVector &TheVector; + unsigned BitPos; + + public: + reference(SmallBitVector &b, unsigned Idx) : TheVector(b), BitPos(Idx) {} + + reference(const reference&) = default; + + reference& operator=(reference t) { + *this = bool(t); + return *this; + } + + reference& operator=(bool t) { + if (t) + TheVector.set(BitPos); + else + TheVector.reset(BitPos); + return *this; + } + + operator bool() const { + return const_cast<const SmallBitVector &>(TheVector).operator[](BitPos); + } + }; + +private: + BitVector *getPointer() const { + assert(!isSmall()); + return reinterpret_cast<BitVector *>(X); + } + + void switchToSmall(uintptr_t NewSmallBits, size_t NewSize) { + X = 1; + setSmallSize(NewSize); + setSmallBits(NewSmallBits); + } + + void switchToLarge(BitVector *BV) { + X = reinterpret_cast<uintptr_t>(BV); + assert(!isSmall() && "Tried to use an unaligned pointer"); + } + + // Return all the bits used for the "small" representation; this includes + // bits for the size as well as the element bits. + uintptr_t getSmallRawBits() const { + assert(isSmall()); + return X >> 1; + } + + void setSmallRawBits(uintptr_t NewRawBits) { + assert(isSmall()); + X = (NewRawBits << 1) | uintptr_t(1); + } + + // Return the size. + size_t getSmallSize() const { return getSmallRawBits() >> SmallNumDataBits; } + + void setSmallSize(size_t Size) { + setSmallRawBits(getSmallBits() | (Size << SmallNumDataBits)); + } + + // Return the element bits. + uintptr_t getSmallBits() const { + return getSmallRawBits() & ~(~uintptr_t(0) << getSmallSize()); + } + + void setSmallBits(uintptr_t NewBits) { + setSmallRawBits((NewBits & ~(~uintptr_t(0) << getSmallSize())) | + (getSmallSize() << SmallNumDataBits)); + } + +public: + /// Creates an empty bitvector. + SmallBitVector() = default; + + /// 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); + else + switchToLarge(new BitVector(s, t)); + } + + /// SmallBitVector copy ctor. + SmallBitVector(const SmallBitVector &RHS) { + if (RHS.isSmall()) + X = RHS.X; + else + switchToLarge(new BitVector(*RHS.getPointer())); + } + + SmallBitVector(SmallBitVector &&RHS) : X(RHS.X) { + RHS.X = 1; + } + + ~SmallBitVector() { + if (!isSmall()) + delete getPointer(); + } + + using const_set_bits_iterator = const_set_bits_iterator_impl<SmallBitVector>; + using set_iterator = const_set_bits_iterator; + + const_set_bits_iterator set_bits_begin() const { + return const_set_bits_iterator(*this); + } + + const_set_bits_iterator set_bits_end() const { + return const_set_bits_iterator(*this, -1); + } + + iterator_range<const_set_bits_iterator> set_bits() const { + return make_range(set_bits_begin(), set_bits_end()); + } + + bool isSmall() const { return X & uintptr_t(1); } + + /// Tests whether there are no bits in this bitvector. + bool empty() const { + return isSmall() ? getSmallSize() == 0 : getPointer()->empty(); + } + + /// Returns the number of bits in this bitvector. + size_t size() const { + return isSmall() ? getSmallSize() : getPointer()->size(); + } + + /// Returns the number of bits which are set. + size_type count() const { + if (isSmall()) { + uintptr_t Bits = getSmallBits(); + return countPopulation(Bits); + } + return getPointer()->count(); + } + + /// Returns true if any bit is set. + bool any() const { + if (isSmall()) + return getSmallBits() != 0; + return getPointer()->any(); + } + + /// Returns true if all bits are set. + bool all() const { + if (isSmall()) + return getSmallBits() == (uintptr_t(1) << getSmallSize()) - 1; + return getPointer()->all(); + } + + /// Returns true if none of the bits are set. + bool none() const { + if (isSmall()) + return getSmallBits() == 0; + return getPointer()->none(); + } + + /// 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(); + if (Bits == 0) + return -1; + return countTrailingZeros(Bits); + } + return getPointer()->find_first(); + } + + int find_last() const { + if (isSmall()) { + uintptr_t Bits = getSmallBits(); + if (Bits == 0) + return -1; + return NumBaseBits - countLeadingZeros(Bits) - 1; + } + return getPointer()->find_last(); + } + + /// Returns the index of the first unset bit, -1 if all of the bits are set. + int find_first_unset() const { + if (isSmall()) { + if (count() == getSmallSize()) + return -1; + + uintptr_t Bits = getSmallBits(); + return countTrailingOnes(Bits); + } + return getPointer()->find_first_unset(); + } + + int find_last_unset() const { + if (isSmall()) { + if (count() == getSmallSize()) + return -1; + + uintptr_t Bits = getSmallBits(); + // Set unused bits. + Bits |= ~uintptr_t(0) << getSmallSize(); + return NumBaseBits - countLeadingOnes(Bits) - 1; + } + return getPointer()->find_last_unset(); + } + + /// 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(); + // Mask off previous bits. + Bits &= ~uintptr_t(0) << (Prev + 1); + if (Bits == 0 || Prev + 1 >= getSmallSize()) + return -1; + return countTrailingZeros(Bits); + } + return getPointer()->find_next(Prev); + } + + /// Returns the index of the next unset bit following the "Prev" bit. + /// Returns -1 if the next unset bit is not found. + int find_next_unset(unsigned Prev) const { + if (isSmall()) { + ++Prev; + uintptr_t Bits = getSmallBits(); + // Mask in previous bits. + uintptr_t Mask = (uintptr_t(1) << Prev) - 1; + Bits |= Mask; + + if (Bits == ~uintptr_t(0) || Prev + 1 >= getSmallSize()) + return -1; + return countTrailingOnes(Bits); + } + return getPointer()->find_next_unset(Prev); + } + + /// find_prev - Returns the index of the first set bit that precedes the + /// the bit at \p PriorTo. Returns -1 if all previous bits are unset. + int find_prev(unsigned PriorTo) const { + if (isSmall()) { + if (PriorTo == 0) + return -1; + + --PriorTo; + uintptr_t Bits = getSmallBits(); + Bits &= maskTrailingOnes<uintptr_t>(PriorTo + 1); + if (Bits == 0) + return -1; + + return NumBaseBits - countLeadingZeros(Bits) - 1; + } + return getPointer()->find_prev(PriorTo); + } + + /// Clear all bits. + void clear() { + if (!isSmall()) + delete getPointer(); + switchToSmall(0, 0); + } + + /// Grow or shrink the bitvector. + void resize(unsigned N, bool t = false) { + if (!isSmall()) { + getPointer()->resize(N, t); + } else if (SmallNumDataBits >= N) { + uintptr_t NewBits = t ? ~uintptr_t(0) << getSmallSize() : 0; + setSmallSize(N); + setSmallBits(NewBits | getSmallBits()); + } else { + BitVector *BV = new BitVector(N, t); + uintptr_t OldBits = getSmallBits(); + for (size_t i = 0, e = getSmallSize(); i != e; ++i) + (*BV)[i] = (OldBits >> i) & 1; + switchToLarge(BV); + } + } + + void reserve(unsigned N) { + if (isSmall()) { + if (N > SmallNumDataBits) { + uintptr_t OldBits = getSmallRawBits(); + size_t SmallSize = getSmallSize(); + BitVector *BV = new BitVector(SmallSize); + for (size_t i = 0; i < SmallSize; ++i) + if ((OldBits >> i) & 1) + BV->set(i); + BV->reserve(N); + switchToLarge(BV); + } + } else { + getPointer()->reserve(N); + } + } + + // Set, reset, flip + SmallBitVector &set() { + if (isSmall()) + setSmallBits(~uintptr_t(0)); + else + getPointer()->set(); + return *this; + } + + SmallBitVector &set(unsigned Idx) { + if (isSmall()) { + assert(Idx <= static_cast<unsigned>( + std::numeric_limits<uintptr_t>::digits) && + "undefined behavior"); + setSmallBits(getSmallBits() | (uintptr_t(1) << Idx)); + } + else + getPointer()->set(Idx); + return *this; + } + + /// 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!"); + if (I == E) return *this; + if (isSmall()) { + uintptr_t EMask = ((uintptr_t)1) << E; + uintptr_t IMask = ((uintptr_t)1) << I; + uintptr_t Mask = EMask - IMask; + setSmallBits(getSmallBits() | Mask); + } else + getPointer()->set(I, E); + return *this; + } + + SmallBitVector &reset() { + if (isSmall()) + setSmallBits(0); + else + getPointer()->reset(); + return *this; + } + + SmallBitVector &reset(unsigned Idx) { + if (isSmall()) + setSmallBits(getSmallBits() & ~(uintptr_t(1) << Idx)); + else + getPointer()->reset(Idx); + return *this; + } + + /// 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!"); + if (I == E) return *this; + if (isSmall()) { + uintptr_t EMask = ((uintptr_t)1) << E; + uintptr_t IMask = ((uintptr_t)1) << I; + uintptr_t Mask = EMask - IMask; + setSmallBits(getSmallBits() & ~Mask); + } else + getPointer()->reset(I, E); + return *this; + } + + SmallBitVector &flip() { + if (isSmall()) + setSmallBits(~getSmallBits()); + else + getPointer()->flip(); + return *this; + } + + SmallBitVector &flip(unsigned Idx) { + if (isSmall()) + setSmallBits(getSmallBits() ^ (uintptr_t(1) << Idx)); + else + getPointer()->flip(Idx); + return *this; + } + + // No argument flip. + SmallBitVector operator~() const { + return SmallBitVector(*this).flip(); + } + + // Indexing. + reference operator[](unsigned Idx) { + assert(Idx < size() && "Out-of-bounds Bit access."); + return reference(*this, Idx); + } + + bool operator[](unsigned Idx) const { + assert(Idx < size() && "Out-of-bounds Bit access."); + if (isSmall()) + return ((getSmallBits() >> Idx) & 1) != 0; + return getPointer()->operator[](Idx); + } + + bool test(unsigned Idx) const { + return (*this)[Idx]; + } + + // Push single bit to end of vector. + void push_back(bool Val) { + resize(size() + 1, Val); + } + + /// Test if any common bits are set. + bool anyCommon(const SmallBitVector &RHS) const { + if (isSmall() && RHS.isSmall()) + return (getSmallBits() & RHS.getSmallBits()) != 0; + if (!isSmall() && !RHS.isSmall()) + return getPointer()->anyCommon(*RHS.getPointer()); + + for (unsigned i = 0, e = std::min(size(), RHS.size()); i != e; ++i) + if (test(i) && RHS.test(i)) + return true; + return false; + } + + // Comparison operators. + bool operator==(const SmallBitVector &RHS) const { + if (size() != RHS.size()) + return false; + if (isSmall() && RHS.isSmall()) + return getSmallBits() == RHS.getSmallBits(); + else if (!isSmall() && !RHS.isSmall()) + return *getPointer() == *RHS.getPointer(); + else { + for (size_t i = 0, e = size(); i != e; ++i) { + if ((*this)[i] != RHS[i]) + return false; + } + return true; + } + } + + bool operator!=(const SmallBitVector &RHS) const { + return !(*this == RHS); + } + + // Intersection, union, disjoint union. + // FIXME BitVector::operator&= does not resize the LHS but this does + SmallBitVector &operator&=(const SmallBitVector &RHS) { + resize(std::max(size(), RHS.size())); + if (isSmall() && RHS.isSmall()) + setSmallBits(getSmallBits() & RHS.getSmallBits()); + else if (!isSmall() && !RHS.isSmall()) + getPointer()->operator&=(*RHS.getPointer()); + else { + size_t i, e; + for (i = 0, e = std::min(size(), RHS.size()); i != e; ++i) + (*this)[i] = test(i) && RHS.test(i); + for (e = size(); i != e; ++i) + reset(i); + } + return *this; + } + + /// Reset bits that are set in RHS. Same as *this &= ~RHS. + SmallBitVector &reset(const SmallBitVector &RHS) { + if (isSmall() && RHS.isSmall()) + setSmallBits(getSmallBits() & ~RHS.getSmallBits()); + else if (!isSmall() && !RHS.isSmall()) + getPointer()->reset(*RHS.getPointer()); + else + for (unsigned i = 0, e = std::min(size(), RHS.size()); i != e; ++i) + if (RHS.test(i)) + reset(i); + + return *this; + } + + /// 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; + if (!isSmall() && !RHS.isSmall()) + return getPointer()->test(*RHS.getPointer()); + + unsigned i, e; + for (i = 0, e = std::min(size(), RHS.size()); i != e; ++i) + if (test(i) && !RHS.test(i)) + return true; + + for (e = size(); i != e; ++i) + if (test(i)) + return true; + + return false; + } + + SmallBitVector &operator|=(const SmallBitVector &RHS) { + resize(std::max(size(), RHS.size())); + if (isSmall() && RHS.isSmall()) + setSmallBits(getSmallBits() | RHS.getSmallBits()); + else if (!isSmall() && !RHS.isSmall()) + getPointer()->operator|=(*RHS.getPointer()); + else { + for (size_t i = 0, e = RHS.size(); i != e; ++i) + (*this)[i] = test(i) || RHS.test(i); + } + return *this; + } + + SmallBitVector &operator^=(const SmallBitVector &RHS) { + resize(std::max(size(), RHS.size())); + if (isSmall() && RHS.isSmall()) + setSmallBits(getSmallBits() ^ RHS.getSmallBits()); + else if (!isSmall() && !RHS.isSmall()) + getPointer()->operator^=(*RHS.getPointer()); + else { + for (size_t i = 0, e = RHS.size(); i != e; ++i) + (*this)[i] = test(i) != RHS.test(i); + } + return *this; + } + + SmallBitVector &operator<<=(unsigned N) { + if (isSmall()) + setSmallBits(getSmallBits() << N); + else + getPointer()->operator<<=(N); + return *this; + } + + SmallBitVector &operator>>=(unsigned N) { + if (isSmall()) + setSmallBits(getSmallBits() >> N); + else + getPointer()->operator>>=(N); + return *this; + } + + // Assignment operator. + const SmallBitVector &operator=(const SmallBitVector &RHS) { + if (isSmall()) { + if (RHS.isSmall()) + X = RHS.X; + else + switchToLarge(new BitVector(*RHS.getPointer())); + } else { + if (!RHS.isSmall()) + *getPointer() = *RHS.getPointer(); + else { + delete getPointer(); + X = RHS.X; + } + } + return *this; + } + + const SmallBitVector &operator=(SmallBitVector &&RHS) { + if (this != &RHS) { + clear(); + swap(RHS); + } + return *this; + } + + void swap(SmallBitVector &RHS) { + std::swap(X, RHS.X); + } + + /// 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()) + applyMask<true, false>(Mask, MaskWords); + else + getPointer()->setBitsInMask(Mask, MaskWords); + } + + /// 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); + else + getPointer()->clearBitsInMask(Mask, MaskWords); + } + + /// 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); + else + getPointer()->setBitsNotInMask(Mask, MaskWords); + } + + /// 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); + else + getPointer()->clearBitsNotInMask(Mask, MaskWords); + } + +private: + template <bool AddBits, bool InvertMask> + void applyMask(const uint32_t *Mask, unsigned MaskWords) { + assert(MaskWords <= sizeof(uintptr_t) && "Mask is larger than base!"); + uintptr_t M = Mask[0]; + if (NumBaseBits == 64) + M |= uint64_t(Mask[1]) << 32; + if (InvertMask) + M = ~M; + if (AddBits) + setSmallBits(getSmallBits() | M); + else + setSmallBits(getSmallBits() & ~M); + } +}; + +inline SmallBitVector +operator&(const SmallBitVector &LHS, const SmallBitVector &RHS) { + SmallBitVector Result(LHS); + Result &= RHS; + return Result; +} + +inline SmallBitVector +operator|(const SmallBitVector &LHS, const SmallBitVector &RHS) { + SmallBitVector Result(LHS); + Result |= RHS; + return Result; +} + +inline SmallBitVector +operator^(const SmallBitVector &LHS, const SmallBitVector &RHS) { + SmallBitVector Result(LHS); + Result ^= RHS; + return Result; +} + +} // end namespace llvm + +namespace std { + +/// Implement std::swap in terms of BitVector swap. +inline void +swap(llvm::SmallBitVector &LHS, llvm::SmallBitVector &RHS) { + LHS.swap(RHS); +} + +} // end namespace std + +#endif // LLVM_ADT_SMALLBITVECTOR_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/SmallPtrSet.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/SmallPtrSet.h new file mode 100644 index 0000000..1d82800 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/SmallPtrSet.h
@@ -0,0 +1,511 @@ +//===- llvm/ADT/SmallPtrSet.h - 'Normally small' pointer set ----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the SmallPtrSet class. See the doxygen comment for +// SmallPtrSetImplBase for more details on the algorithm used. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SMALLPTRSET_H +#define LLVM_ADT_SMALLPTRSET_H + +#include "llvm/ADT/EpochTracker.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/ReverseIteration.h" +#include "llvm/Support/type_traits.h" +#include <cassert> +#include <cstddef> +#include <cstdlib> +#include <cstring> +#include <initializer_list> +#include <iterator> +#include <utility> + +namespace llvm { + +/// SmallPtrSetImplBase - This is the common code shared among all the +/// SmallPtrSet<>'s, which is almost everything. SmallPtrSet has two modes, one +/// for small and one for large sets. +/// +/// Small sets use an array of pointers allocated in the SmallPtrSet object, +/// which is treated as a simple array of pointers. When a pointer is added to +/// the set, the array is scanned to see if the element already exists, if not +/// the element is 'pushed back' onto the array. If we run out of space in the +/// array, we grow into the 'large set' case. SmallSet should be used when the +/// sets are often small. In this case, no memory allocation is used, and only +/// light-weight and cache-efficient scanning is used. +/// +/// Large sets use a classic exponentially-probed hash table. Empty buckets are +/// represented with an illegal pointer value (-1) to allow null pointers to be +/// inserted. Tombstones are represented with another illegal pointer value +/// (-2), to allow deletion. The hash table is resized when the table is 3/4 or +/// more. When this happens, the table is doubled in size. +/// +class SmallPtrSetImplBase : public DebugEpochBase { + friend class SmallPtrSetIteratorImpl; + +protected: + /// SmallArray - Points to a fixed size set of buckets, used in 'small mode'. + const void **SmallArray; + /// CurArray - This is the current set of buckets. If equal to SmallArray, + /// then the set is in 'small mode'. + const void **CurArray; + /// CurArraySize - The allocated size of CurArray, always a power of two. + unsigned CurArraySize; + + /// 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, unsigned 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!"); + } + + ~SmallPtrSetImplBase() { + if (!isSmall()) + free(CurArray); + } + +public: + using size_type = unsigned; + + SmallPtrSetImplBase &operator=(const SmallPtrSetImplBase &) = delete; + + LLVM_NODISCARD bool empty() const { return size() == 0; } + size_type size() const { return NumNonEmpty - NumTombstones; } + + void clear() { + incrementEpoch(); + // If the capacity of the array is huge, and the # elements used is small, + // shrink the array. + if (!isSmall()) { + if (size() * 4 < CurArraySize && CurArraySize > 32) + return shrink_and_clear(); + // Fill the array with empty markers. + memset(CurArray, -1, CurArraySize * sizeof(void *)); + } + + NumNonEmpty = 0; + NumTombstones = 0; + } + +protected: + static void *getTombstoneMarker() { return reinterpret_cast<void*>(-2); } + + static void *getEmptyMarker() { + // Note that -1 is chosen to make clear() efficiently implementable with + // memset and because it's not a valid pointer value. + 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) { + 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; + incrementEpoch(); + return std::make_pair(LastTombstone, true); + } + + // Nope, there isn't. If we stay small, just 'pushback' now. + if (NumNonEmpty < CurArraySize) { + SmallArray[NumNonEmpty++] = Ptr; + incrementEpoch(); + 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 + /// that the derived class can check that the right type of pointer is passed + /// in. + bool erase_imp(const void * Ptr) { + const void *const *P = find_imp(Ptr); + if (P == EndPointer()) + return false; + + const void **Loc = const_cast<const void **>(P); + assert(*Loc == Ptr && "broken find!"); + *Loc = getTombstoneMarker(); + NumTombstones++; + return true; + } + + /// Returns the raw pointer needed to construct an iterator. If element not + /// found, this will be EndPointer. Otherwise, it will be a pointer to the + /// slot which stores Ptr; + const void *const * find_imp(const void * Ptr) const { + if (isSmall()) { + // Linear search for the item. + for (const void *const *APtr = SmallArray, + *const *E = SmallArray + NumNonEmpty; APtr != E; ++APtr) + if (*APtr == Ptr) + return APtr; + return EndPointer(); + } + + // Big set case. + auto *Bucket = FindBucketFor(Ptr); + if (*Bucket == Ptr) + return Bucket; + return EndPointer(); + } + +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(); + + /// Grow - Allocate a larger backing store for the buckets and move it over. + void Grow(unsigned NewSize); + +protected: + /// swap - Swaps the elements of two sets. + /// Note: This method assumes that both sets have the same small size. + void swap(SmallPtrSetImplBase &RHS); + + 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 +/// instances of SmallPtrSetIterator. +class SmallPtrSetIteratorImpl { +protected: + const void *const *Bucket; + const void *const *End; + +public: + explicit SmallPtrSetIteratorImpl(const void *const *BP, const void*const *E) + : Bucket(BP), End(E) { + if (shouldReverseIterate()) { + RetreatIfNotValid(); + return; + } + AdvanceIfNotValid(); + } + + bool operator==(const SmallPtrSetIteratorImpl &RHS) const { + return Bucket == RHS.Bucket; + } + bool operator!=(const SmallPtrSetIteratorImpl &RHS) const { + return Bucket != RHS.Bucket; + } + +protected: + /// AdvanceIfNotValid - If the current bucket isn't valid, advance to a bucket + /// that is. This is guaranteed to stop because the end() bucket is marked + /// valid. + void AdvanceIfNotValid() { + assert(Bucket <= End); + while (Bucket != End && + (*Bucket == SmallPtrSetImplBase::getEmptyMarker() || + *Bucket == SmallPtrSetImplBase::getTombstoneMarker())) + ++Bucket; + } + void RetreatIfNotValid() { + assert(Bucket >= End); + while (Bucket != End && + (Bucket[-1] == SmallPtrSetImplBase::getEmptyMarker() || + Bucket[-1] == SmallPtrSetImplBase::getTombstoneMarker())) { + --Bucket; + } + } +}; + +/// SmallPtrSetIterator - This implements a const_iterator for SmallPtrSet. +template <typename PtrTy> +class SmallPtrSetIterator : public SmallPtrSetIteratorImpl, + DebugEpochBase::HandleBase { + using PtrTraits = PointerLikeTypeTraits<PtrTy>; + +public: + using value_type = PtrTy; + using reference = PtrTy; + using pointer = PtrTy; + using difference_type = std::ptrdiff_t; + using iterator_category = std::forward_iterator_tag; + + explicit SmallPtrSetIterator(const void *const *BP, const void *const *E, + const DebugEpochBase &Epoch) + : SmallPtrSetIteratorImpl(BP, E), DebugEpochBase::HandleBase(&Epoch) {} + + // Most methods provided by baseclass. + + const PtrTy operator*() const { + assert(isHandleInSync() && "invalid iterator access!"); + if (shouldReverseIterate()) { + assert(Bucket > End); + return PtrTraits::getFromVoidPointer(const_cast<void *>(Bucket[-1])); + } + assert(Bucket < End); + return PtrTraits::getFromVoidPointer(const_cast<void*>(*Bucket)); + } + + inline SmallPtrSetIterator& operator++() { // Preincrement + assert(isHandleInSync() && "invalid iterator access!"); + if (shouldReverseIterate()) { + --Bucket; + RetreatIfNotValid(); + return *this; + } + ++Bucket; + AdvanceIfNotValid(); + return *this; + } + + SmallPtrSetIterator operator++(int) { // Postincrement + SmallPtrSetIterator tmp = *this; + ++*this; + return tmp; + } +}; + +/// RoundUpToPowerOfTwo - This is a helper template that rounds N up to the next +/// power of two (which means N itself if N is already a power of two). +template<unsigned N> +struct RoundUpToPowerOfTwo; + +/// RoundUpToPowerOfTwoH - If N is not a power of two, increase it. This is a +/// helper template used to implement RoundUpToPowerOfTwo. +template<unsigned N, bool isPowerTwo> +struct RoundUpToPowerOfTwoH { + enum { Val = N }; +}; +template<unsigned N> +struct RoundUpToPowerOfTwoH<N, false> { + enum { + // We could just use NextVal = N+1, but this converges faster. N|(N-1) sets + // the right-most zero bits to one all at once, e.g. 0b0011000 -> 0b0011111. + Val = RoundUpToPowerOfTwo<(N|(N-1)) + 1>::Val + }; +}; + +template<unsigned N> +struct RoundUpToPowerOfTwo { + enum { Val = RoundUpToPowerOfTwoH<N, (N&(N-1)) == 0>::Val }; +}; + +/// A templated base class for \c SmallPtrSet which provides the +/// typesafe interface that is common across all small sizes. +/// +/// This is particularly useful for passing around between interface boundaries +/// to avoid encoding a particular small size in the interface boundary. +template <typename PtrType> +class SmallPtrSetImpl : public SmallPtrSetImplBase { + using ConstPtrType = typename add_const_past_pointer<PtrType>::type; + using PtrTraits = PointerLikeTypeTraits<PtrType>; + using ConstPtrTraits = PointerLikeTypeTraits<ConstPtrType>; + +protected: + // Constructors that forward to the base. + SmallPtrSetImpl(const void **SmallStorage, const SmallPtrSetImpl &that) + : SmallPtrSetImplBase(SmallStorage, that) {} + SmallPtrSetImpl(const void **SmallStorage, unsigned SmallSize, + SmallPtrSetImpl &&that) + : SmallPtrSetImplBase(SmallStorage, SmallSize, std::move(that)) {} + explicit SmallPtrSetImpl(const void **SmallStorage, unsigned SmallSize) + : SmallPtrSetImplBase(SmallStorage, SmallSize) {} + +public: + using iterator = SmallPtrSetIterator<PtrType>; + using const_iterator = SmallPtrSetIterator<PtrType>; + using key_type = ConstPtrType; + using value_type = PtrType; + + SmallPtrSetImpl(const SmallPtrSetImpl &) = delete; + + /// Inserts Ptr if and only if there is no element in the container equal to + /// Ptr. 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 equal to Ptr. + std::pair<iterator, bool> insert(PtrType Ptr) { + auto p = insert_imp(PtrTraits::getAsVoidPointer(Ptr)); + return std::make_pair(makeIterator(p.first), p.second); + } + + /// erase - If the set contains the specified pointer, remove it and return + /// true, otherwise return false. + bool erase(PtrType Ptr) { + return erase_imp(PtrTraits::getAsVoidPointer(Ptr)); + } + /// count - Return 1 if the specified pointer is in the set, 0 otherwise. + size_type count(ConstPtrType Ptr) const { return find(Ptr) != end() ? 1 : 0; } + iterator find(ConstPtrType Ptr) const { + return makeIterator(find_imp(ConstPtrTraits::getAsVoidPointer(Ptr))); + } + + template <typename IterT> + void insert(IterT I, IterT E) { + for (; I != E; ++I) + insert(*I); + } + + void insert(std::initializer_list<PtrType> IL) { + insert(IL.begin(), IL.end()); + } + + iterator begin() const { + if (shouldReverseIterate()) + return makeIterator(EndPointer() - 1); + return makeIterator(CurArray); + } + iterator end() const { return makeIterator(EndPointer()); } + +private: + /// Create an iterator that dereferences to same place as the given pointer. + iterator makeIterator(const void *const *P) const { + if (shouldReverseIterate()) + return iterator(P == EndPointer() ? CurArray : P + 1, CurArray, *this); + return iterator(P, EndPointer(), *this); + } +}; + +/// Equality comparison for SmallPtrSet. +/// +/// Iterates over elements of LHS confirming that each value from LHS is also in +/// RHS, and that no additional values are in RHS. +template <typename PtrType> +bool operator==(const SmallPtrSetImpl<PtrType> &LHS, + const SmallPtrSetImpl<PtrType> &RHS) { + if (LHS.size() != RHS.size()) + return false; + + for (const auto *KV : LHS) + if (!RHS.count(KV)) + return false; + + return true; +} + +/// Inequality comparison for SmallPtrSet. +/// +/// Equivalent to !(LHS == RHS). +template <typename PtrType> +bool operator!=(const SmallPtrSetImpl<PtrType> &LHS, + const SmallPtrSetImpl<PtrType> &RHS) { + return !(LHS == RHS); +} + +/// SmallPtrSet - This class implements a set which is optimized for holding +/// SmallSize or less elements. This internally rounds up SmallSize to the next +/// power of two if it is not already a power of two. See the comments above +/// SmallPtrSetImplBase for details of the algorithm. +template<class PtrType, unsigned SmallSize> +class SmallPtrSet : public SmallPtrSetImpl<PtrType> { + // 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"); + + using BaseT = SmallPtrSetImpl<PtrType>; + + // Make sure that SmallSize is a power of two, round up if not. + enum { SmallSizePowTwo = RoundUpToPowerOfTwo<SmallSize>::Val }; + /// SmallStorage - Fixed size storage used in 'small mode'. + const void *SmallStorage[SmallSizePowTwo]; + +public: + SmallPtrSet() : BaseT(SmallStorage, SmallSizePowTwo) {} + SmallPtrSet(const SmallPtrSet &that) : BaseT(SmallStorage, that) {} + SmallPtrSet(SmallPtrSet &&that) + : BaseT(SmallStorage, SmallSizePowTwo, std::move(that)) {} + + template<typename It> + SmallPtrSet(It I, It E) : BaseT(SmallStorage, SmallSizePowTwo) { + this->insert(I, E); + } + + SmallPtrSet(std::initializer_list<PtrType> IL) + : BaseT(SmallStorage, SmallSizePowTwo) { + this->insert(IL.begin(), IL.end()); + } + + SmallPtrSet<PtrType, SmallSize> & + operator=(const SmallPtrSet<PtrType, SmallSize> &RHS) { + if (&RHS != this) + this->CopyFrom(RHS); + return *this; + } + + SmallPtrSet<PtrType, SmallSize> & + operator=(SmallPtrSet<PtrType, SmallSize> &&RHS) { + if (&RHS != this) + this->MoveFrom(SmallSizePowTwo, std::move(RHS)); + return *this; + } + + SmallPtrSet<PtrType, SmallSize> & + operator=(std::initializer_list<PtrType> IL) { + this->clear(); + this->insert(IL.begin(), IL.end()); + return *this; + } + + /// swap - Swaps the elements of two sets. + void swap(SmallPtrSet<PtrType, SmallSize> &RHS) { + SmallPtrSetImplBase::swap(RHS); + } +}; + +} // end namespace llvm + +namespace std { + + /// Implement std::swap in terms of SmallPtrSet swap. + template<class T, unsigned N> + inline void swap(llvm::SmallPtrSet<T, N> &LHS, llvm::SmallPtrSet<T, N> &RHS) { + LHS.swap(RHS); + } + +} // end namespace std + +#endif // LLVM_ADT_SMALLPTRSET_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/SmallSet.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/SmallSet.h new file mode 100644 index 0000000..a03fa7d --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/SmallSet.h
@@ -0,0 +1,278 @@ +//===- llvm/ADT/SmallSet.h - 'Normally small' sets --------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the SmallSet class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SMALLSET_H +#define LLVM_ADT_SMALLSET_H + +#include "llvm/ADT/None.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/iterator.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/type_traits.h" +#include <cstddef> +#include <functional> +#include <set> +#include <type_traits> +#include <utility> + +namespace llvm { + +/// SmallSetIterator - This class implements a const_iterator for SmallSet by +/// delegating to the underlying SmallVector or Set iterators. +template <typename T, unsigned N, typename C> +class SmallSetIterator + : public iterator_facade_base<SmallSetIterator<T, N, C>, + std::forward_iterator_tag, T> { +private: + using SetIterTy = typename std::set<T, C>::const_iterator; + using VecIterTy = typename SmallVector<T, N>::const_iterator; + using SelfTy = SmallSetIterator<T, N, C>; + + /// Iterators to the parts of the SmallSet containing the data. They are set + /// depending on isSmall. + union { + SetIterTy SetIter; + VecIterTy VecIter; + }; + + bool isSmall; + +public: + SmallSetIterator(SetIterTy SetIter) : SetIter(SetIter), isSmall(false) {} + + SmallSetIterator(VecIterTy VecIter) : VecIter(VecIter), isSmall(true) {} + + // Spell out destructor, copy/move constructor and assignment operators for + // MSVC STL, where set<T>::const_iterator is not trivially copy constructible. + ~SmallSetIterator() { + if (isSmall) + VecIter.~VecIterTy(); + else + SetIter.~SetIterTy(); + } + + SmallSetIterator(const SmallSetIterator &Other) : isSmall(Other.isSmall) { + if (isSmall) + VecIter = Other.VecIter; + else + // Use placement new, to make sure SetIter is properly constructed, even + // if it is not trivially copy-able (e.g. in MSVC). + new (&SetIter) SetIterTy(Other.SetIter); + } + + SmallSetIterator(SmallSetIterator &&Other) : isSmall(Other.isSmall) { + if (isSmall) + VecIter = std::move(Other.VecIter); + else + // Use placement new, to make sure SetIter is properly constructed, even + // if it is not trivially copy-able (e.g. in MSVC). + new (&SetIter) SetIterTy(std::move(Other.SetIter)); + } + + SmallSetIterator& operator=(const SmallSetIterator& Other) { + // Call destructor for SetIter, so it gets properly destroyed if it is + // not trivially destructible in case we are setting VecIter. + if (!isSmall) + SetIter.~SetIterTy(); + + isSmall = Other.isSmall; + if (isSmall) + VecIter = Other.VecIter; + else + new (&SetIter) SetIterTy(Other.SetIter); + return *this; + } + + SmallSetIterator& operator=(SmallSetIterator&& Other) { + // Call destructor for SetIter, so it gets properly destroyed if it is + // not trivially destructible in case we are setting VecIter. + if (!isSmall) + SetIter.~SetIterTy(); + + isSmall = Other.isSmall; + if (isSmall) + VecIter = std::move(Other.VecIter); + else + new (&SetIter) SetIterTy(std::move(Other.SetIter)); + return *this; + } + + bool operator==(const SmallSetIterator &RHS) const { + if (isSmall != RHS.isSmall) + return false; + if (isSmall) + return VecIter == RHS.VecIter; + return SetIter == RHS.SetIter; + } + + SmallSetIterator &operator++() { // Preincrement + if (isSmall) + VecIter++; + else + SetIter++; + return *this; + } + + const T &operator*() const { return isSmall ? *VecIter : *SetIter; } +}; + +/// SmallSet - This maintains a set of unique values, optimizing for the case +/// when the set is small (less than N). In this case, the set can be +/// maintained with no mallocs. If the set gets large, we expand to using an +/// std::set to maintain reasonable lookup times. +template <typename T, unsigned N, typename C = std::less<T>> +class SmallSet { + /// Use a SmallVector to hold the elements here (even though it will never + /// reach its 'large' stage) to avoid calling the default ctors of elements + /// we will never use. + SmallVector<T, N> Vector; + std::set<T, C> Set; + + using VIterator = typename SmallVector<T, N>::const_iterator; + using mutable_iterator = typename SmallVector<T, N>::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: + using size_type = size_t; + using const_iterator = SmallSetIterator<T, N, C>; + + SmallSet() = default; + + LLVM_NODISCARD bool empty() const { + return Vector.empty() && Set.empty(); + } + + size_type size() const { + return isSmall() ? Vector.size() : Set.size(); + } + + /// count - Return 1 if the element is in the set, 0 otherwise. + size_type count(const T &V) const { + if (isSmall()) { + // Since the collection is small, just do a linear search. + return vfind(V) == Vector.end() ? 0 : 1; + } else { + return Set.count(V); + } + } + + /// insert - Insert an element into the set if it isn't already there. + /// Returns true if the element is inserted (it was not in the set before). + /// The first value of the returned pair is unused and provided for + /// partial compatibility with the standard library self-associative container + /// concept. + // FIXME: Add iterators that abstract over the small and large form, and then + // return those here. + std::pair<NoneType, bool> insert(const T &V) { + if (!isSmall()) + return std::make_pair(None, Set.insert(V).second); + + VIterator I = vfind(V); + if (I != Vector.end()) // Don't reinsert if it already exists. + return std::make_pair(None, false); + if (Vector.size() < N) { + Vector.push_back(V); + return std::make_pair(None, true); + } + + // Otherwise, grow from vector to set. + while (!Vector.empty()) { + Set.insert(Vector.back()); + Vector.pop_back(); + } + Set.insert(V); + return std::make_pair(None, true); + } + + template <typename IterT> + void insert(IterT I, IterT E) { + for (; I != E; ++I) + insert(*I); + } + + bool erase(const T &V) { + if (!isSmall()) + return Set.erase(V); + for (mutable_iterator I = Vector.begin(), E = Vector.end(); I != E; ++I) + if (*I == V) { + Vector.erase(I); + return true; + } + return false; + } + + void clear() { + Vector.clear(); + Set.clear(); + } + + const_iterator begin() const { + if (isSmall()) + return {Vector.begin()}; + return {Set.begin()}; + } + + const_iterator end() const { + if (isSmall()) + return {Vector.end()}; + return {Set.end()}; + } + +private: + bool isSmall() const { return Set.empty(); } + + VIterator vfind(const T &V) const { + for (VIterator I = Vector.begin(), E = Vector.end(); I != E; ++I) + if (*I == V) + return I; + return Vector.end(); + } +}; + +/// If this set is of pointer values, transparently switch over to using +/// SmallPtrSet for performance. +template <typename PointeeType, unsigned N> +class SmallSet<PointeeType*, N> : public SmallPtrSet<PointeeType*, N> {}; + +/// Equality comparison for SmallSet. +/// +/// Iterates over elements of LHS confirming that each element is also a member +/// of RHS, and that RHS contains no additional values. +/// Equivalent to N calls to RHS.count. +/// For small-set mode amortized complexity is O(N^2) +/// For large-set mode amortized complexity is linear, worst case is O(N^2) (if +/// every hash collides). +template <typename T, unsigned LN, unsigned RN, typename C> +bool operator==(const SmallSet<T, LN, C> &LHS, const SmallSet<T, RN, C> &RHS) { + if (LHS.size() != RHS.size()) + return false; + + // All elements in LHS must also be in RHS + return all_of(LHS, [&RHS](const T &E) { return RHS.count(E); }); +} + +/// Inequality comparison for SmallSet. +/// +/// Equivalent to !(LHS == RHS). See operator== for performance notes. +template <typename T, unsigned LN, unsigned RN, typename C> +bool operator!=(const SmallSet<T, LN, C> &LHS, const SmallSet<T, RN, C> &RHS) { + return !(LHS == RHS); +} + +} // end namespace llvm + +#endif // LLVM_ADT_SMALLSET_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/SmallString.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/SmallString.h new file mode 100644 index 0000000..898be80 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/SmallString.h
@@ -0,0 +1,296 @@ +//===- llvm/ADT/SmallString.h - 'Normally small' strings --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the SmallString class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SMALLSTRING_H +#define LLVM_ADT_SMALLSTRING_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include <cstddef> + +namespace llvm { + +/// SmallString - A SmallString is just a SmallVector with methods and accessors +/// that make it work better as a string (e.g. operator+ etc). +template<unsigned InternalLen> +class SmallString : public SmallVector<char, InternalLen> { +public: + /// Default ctor - Initialize to empty. + SmallString() = default; + + /// Initialize from a StringRef. + SmallString(StringRef S) : SmallVector<char, InternalLen>(S.begin(), S.end()) {} + + /// Initialize with a range. + template<typename ItTy> + SmallString(ItTy S, ItTy E) : SmallVector<char, InternalLen>(S, E) {} + + // Note that in order to add new overloads for append & assign, we have to + // duplicate the inherited versions so as not to inadvertently hide them. + + /// @} + /// @name String Assignment + /// @{ + + /// Assign from a repeated element. + void assign(size_t NumElts, char Elt) { + this->SmallVectorImpl<char>::assign(NumElts, Elt); + } + + /// Assign from an iterator pair. + template<typename in_iter> + void assign(in_iter S, in_iter E) { + this->clear(); + SmallVectorImpl<char>::append(S, E); + } + + /// Assign from a StringRef. + void assign(StringRef RHS) { + this->clear(); + SmallVectorImpl<char>::append(RHS.begin(), RHS.end()); + } + + /// Assign from a SmallVector. + void assign(const SmallVectorImpl<char> &RHS) { + this->clear(); + SmallVectorImpl<char>::append(RHS.begin(), RHS.end()); + } + + /// @} + /// @name String Concatenation + /// @{ + + /// Append from an iterator pair. + template<typename in_iter> + void append(in_iter S, in_iter E) { + SmallVectorImpl<char>::append(S, E); + } + + void append(size_t NumInputs, char Elt) { + SmallVectorImpl<char>::append(NumInputs, Elt); + } + + /// Append from a StringRef. + void append(StringRef RHS) { + SmallVectorImpl<char>::append(RHS.begin(), RHS.end()); + } + + /// Append from a SmallVector. + void append(const SmallVectorImpl<char> &RHS) { + SmallVectorImpl<char>::append(RHS.begin(), RHS.end()); + } + + /// @} + /// @name String Comparison + /// @{ + + /// Check for string equality. This is more efficient than compare() when + /// the relative ordering of inequal strings isn't needed. + bool equals(StringRef RHS) const { + return str().equals(RHS); + } + + /// Check for string equality, ignoring case. + bool equals_lower(StringRef RHS) const { + return str().equals_lower(RHS); + } + + /// Compare two strings; the result is -1, 0, or 1 if this string is + /// lexicographically less than, equal to, or greater than the \p RHS. + int compare(StringRef RHS) const { + return str().compare(RHS); + } + + /// compare_lower - Compare two strings, ignoring case. + int compare_lower(StringRef RHS) const { + return str().compare_lower(RHS); + } + + /// compare_numeric - Compare two strings, treating sequences of digits as + /// numbers. + int compare_numeric(StringRef RHS) const { + return str().compare_numeric(RHS); + } + + /// @} + /// @name String Predicates + /// @{ + + /// startswith - Check if this string starts with the given \p Prefix. + bool startswith(StringRef Prefix) const { + return str().startswith(Prefix); + } + + /// endswith - Check if this string ends with the given \p Suffix. + bool endswith(StringRef Suffix) const { + return str().endswith(Suffix); + } + + /// @} + /// @name String Searching + /// @{ + + /// find - Search for the first character \p C in the string. + /// + /// \return - The index of the first occurrence of \p C, or npos if not + /// found. + size_t find(char C, size_t From = 0) const { + return str().find(C, From); + } + + /// Search for the first string \p Str in the string. + /// + /// \returns The index of the first occurrence of \p Str, or npos if not + /// found. + size_t find(StringRef Str, size_t From = 0) const { + return str().find(Str, From); + } + + /// Search for the last character \p C in the string. + /// + /// \returns The index of the last occurrence of \p C, or npos if not + /// found. + size_t rfind(char C, size_t From = StringRef::npos) const { + return str().rfind(C, From); + } + + /// Search for the last string \p Str in the string. + /// + /// \returns The index of the last occurrence of \p Str, or npos if not + /// found. + size_t rfind(StringRef Str) const { + return str().rfind(Str); + } + + /// Find the first character in the string that is \p C, or npos if not + /// found. Same as find. + size_t find_first_of(char C, size_t From = 0) const { + return str().find_first_of(C, From); + } + + /// Find the first character in the string that is in \p Chars, or npos if + /// not found. + /// + /// Complexity: O(size() + Chars.size()) + size_t find_first_of(StringRef Chars, size_t From = 0) const { + return str().find_first_of(Chars, From); + } + + /// Find the first character in the string that is not \p C or npos if not + /// found. + size_t find_first_not_of(char C, size_t From = 0) const { + return str().find_first_not_of(C, From); + } + + /// Find the first character in the string that is not in the string + /// \p Chars, or npos if not found. + /// + /// Complexity: O(size() + Chars.size()) + size_t find_first_not_of(StringRef Chars, size_t From = 0) const { + return str().find_first_not_of(Chars, From); + } + + /// Find the last character in the string that is \p C, or npos if not + /// found. + size_t find_last_of(char C, size_t From = StringRef::npos) const { + return str().find_last_of(C, From); + } + + /// Find the last character in the string that is in \p C, or npos if not + /// found. + /// + /// Complexity: O(size() + Chars.size()) + size_t find_last_of( + StringRef Chars, size_t From = StringRef::npos) const { + return str().find_last_of(Chars, From); + } + + /// @} + /// @name Helpful Algorithms + /// @{ + + /// Return the number of occurrences of \p C in the string. + size_t count(char C) const { + return str().count(C); + } + + /// Return the number of non-overlapped occurrences of \p Str in the + /// string. + size_t count(StringRef Str) const { + return str().count(Str); + } + + /// @} + /// @name Substring Operations + /// @{ + + /// Return a reference to the substring from [Start, Start + N). + /// + /// \param Start The index of the starting character in the substring; if + /// the index is npos or greater than the length of the string then the + /// empty substring will be returned. + /// + /// \param N The number of characters to included in the substring. If \p N + /// exceeds the number of characters remaining in the string, the string + /// suffix (starting with \p Start) will be returned. + StringRef substr(size_t Start, size_t N = StringRef::npos) const { + return str().substr(Start, N); + } + + /// Return a reference to the substring from [Start, End). + /// + /// \param Start The index of the starting character in the substring; if + /// the index is npos or greater than the length of the string then the + /// 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. + StringRef slice(size_t Start, size_t End) const { + return str().slice(Start, End); + } + + // Extra methods. + + /// Explicit conversion to StringRef. + StringRef str() const { return StringRef(this->begin(), this->size()); } + + // TODO: Make this const, if it's safe... + const char* c_str() { + this->push_back(0); + this->pop_back(); + return this->data(); + } + + /// Implicit conversion to StringRef. + operator StringRef() const { return str(); } + + // Extra operators. + const SmallString &operator=(StringRef RHS) { + this->clear(); + return *this += RHS; + } + + SmallString &operator+=(StringRef RHS) { + this->append(RHS.begin(), RHS.end()); + return *this; + } + SmallString &operator+=(char C) { + this->push_back(C); + return *this; + } +}; + +} // end namespace llvm + +#endif // LLVM_ADT_SMALLSTRING_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/SmallVector.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/SmallVector.h new file mode 100644 index 0000000..8c46aa9 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/SmallVector.h
@@ -0,0 +1,941 @@ +//===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the SmallVector class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SMALLVECTOR_H +#define LLVM_ADT_SMALLVECTOR_H + +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/AlignOf.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/MemAlloc.h" +#include "llvm/Support/type_traits.h" +#include "llvm/Support/ErrorHandling.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstdlib> +#include <cstring> +#include <initializer_list> +#include <iterator> +#include <memory> +#include <new> +#include <type_traits> +#include <utility> + +namespace llvm { + +/// This is all the non-templated stuff common to all SmallVectors. +class SmallVectorBase { +protected: + void *BeginX; + unsigned Size = 0, Capacity; + + SmallVectorBase() = delete; + SmallVectorBase(void *FirstEl, size_t TotalCapacity) + : BeginX(FirstEl), Capacity(TotalCapacity) {} + + /// This is an implementation of the grow() method which only works + /// on POD-like data types and is out of line to reduce code duplication. + void grow_pod(void *FirstEl, size_t MinCapacity, size_t TSize); + +public: + size_t size() const { return Size; } + size_t capacity() const { return Capacity; } + + LLVM_NODISCARD bool empty() const { return !Size; } + + /// Set the array size to \p N, which the current array must have enough + /// capacity for. + /// + /// This does not construct or destroy any elements in the vector. + /// + /// Clients can use this in conjunction with capacity() to write past the end + /// of the buffer when they know that more elements are available, and only + /// update the size later. This avoids the cost of value initializing elements + /// which will only be overwritten. + void set_size(size_t N) { + assert(N <= capacity()); + Size = N; + } +}; + +/// Figure out the offset of the first element. +template <class T, typename = void> struct SmallVectorAlignmentAndSize { + AlignedCharArrayUnion<SmallVectorBase> Base; + AlignedCharArrayUnion<T> FirstEl; +}; + +/// This is the part of SmallVectorTemplateBase which does not depend on whether +/// the type T is a POD. The extra dummy template argument is used by ArrayRef +/// to avoid unnecessarily requiring T to be complete. +template <typename T, typename = void> +class SmallVectorTemplateCommon : public SmallVectorBase { + /// Find the address of the first element. For this pointer math to be valid + /// with small-size of 0 for T with lots of alignment, it's important that + /// SmallVectorStorage is properly-aligned even for small-size of 0. + void *getFirstEl() const { + return const_cast<void *>(reinterpret_cast<const void *>( + reinterpret_cast<const char *>(this) + + offsetof(SmallVectorAlignmentAndSize<T>, FirstEl))); + } + // Space after 'FirstEl' is clobbered, do not add any instance vars after it. + +protected: + SmallVectorTemplateCommon(size_t Size) + : SmallVectorBase(getFirstEl(), Size) {} + + void grow_pod(size_t MinCapacity, size_t TSize) { + SmallVectorBase::grow_pod(getFirstEl(), MinCapacity, TSize); + } + + /// Return true if this is a smallvector which has not had dynamic + /// memory allocated for it. + bool isSmall() const { return BeginX == getFirstEl(); } + + /// Put this vector in a state of being small. + void resetToSmall() { + BeginX = getFirstEl(); + Size = Capacity = 0; // FIXME: Setting Capacity to 0 is suspect. + } + +public: + using size_type = size_t; + using difference_type = ptrdiff_t; + using value_type = T; + using iterator = T *; + using const_iterator = const T *; + + using const_reverse_iterator = std::reverse_iterator<const_iterator>; + using reverse_iterator = std::reverse_iterator<iterator>; + + using reference = T &; + using const_reference = const T &; + using pointer = T *; + using const_pointer = const T *; + + // forward iterator creation methods. + iterator begin() { return (iterator)this->BeginX; } + const_iterator begin() const { return (const_iterator)this->BeginX; } + iterator end() { return begin() + size(); } + const_iterator end() const { return begin() + size(); } + + // reverse iterator creation methods. + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin());} + + size_type size_in_bytes() const { return size() * sizeof(T); } + size_type max_size() const { return size_type(-1) / sizeof(T); } + + size_t capacity_in_bytes() const { return capacity() * sizeof(T); } + + /// Return a pointer to the vector's buffer, even if empty(). + pointer data() { return pointer(begin()); } + /// Return a pointer to the vector's buffer, even if empty(). + const_pointer data() const { return const_pointer(begin()); } + + reference operator[](size_type idx) { + assert(idx < size()); + return begin()[idx]; + } + const_reference operator[](size_type idx) const { + assert(idx < size()); + return begin()[idx]; + } + + reference front() { + assert(!empty()); + return begin()[0]; + } + const_reference front() const { + assert(!empty()); + return begin()[0]; + } + + reference back() { + assert(!empty()); + return end()[-1]; + } + const_reference back() const { + assert(!empty()); + return end()[-1]; + } +}; + +/// SmallVectorTemplateBase<TriviallyCopyable = false> - This is where we put method +/// implementations that are designed to work with non-POD-like T's. +template <typename T, bool = is_trivially_copyable<T>::value> +class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T> { +protected: + SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {} + + static void destroy_range(T *S, T *E) { + while (S != E) { + --E; + E->~T(); + } + } + + /// 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) { + 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", + /// constructing elements as needed. + template<typename It1, typename It2> + static void uninitialized_copy(It1 I, It1 E, It2 Dest) { + std::uninitialized_copy(I, E, Dest); + } + + /// Grow the allocated memory (without initializing new elements), doubling + /// the size of the allocated memory. Guarantees space for at least one more + /// element, or MinSize more elements if specified. + void grow(size_t MinSize = 0); + +public: + void push_back(const T &Elt) { + if (LLVM_UNLIKELY(this->size() >= this->capacity())) + this->grow(); + ::new ((void*) this->end()) T(Elt); + this->set_size(this->size() + 1); + } + + void push_back(T &&Elt) { + if (LLVM_UNLIKELY(this->size() >= this->capacity())) + this->grow(); + ::new ((void*) this->end()) T(::std::move(Elt)); + this->set_size(this->size() + 1); + } + + void pop_back() { + this->set_size(this->size() - 1); + this->end()->~T(); + } +}; + +// Define this out-of-line to dissuade the C++ compiler from inlining it. +template <typename T, bool TriviallyCopyable> +void SmallVectorTemplateBase<T, TriviallyCopyable>::grow(size_t MinSize) { + if (MinSize > UINT32_MAX) + report_bad_alloc_error("SmallVector capacity overflow during allocation"); + + // Always grow, even from zero. + size_t NewCapacity = size_t(NextPowerOf2(this->capacity() + 2)); + NewCapacity = std::min(std::max(NewCapacity, MinSize), size_t(UINT32_MAX)); + T *NewElts = static_cast<T*>(llvm::safe_malloc(NewCapacity*sizeof(T))); + + // Move the elements over. + this->uninitialized_move(this->begin(), this->end(), NewElts); + + // Destroy the original elements. + destroy_range(this->begin(), this->end()); + + // If this wasn't grown from the inline copy, deallocate the old space. + if (!this->isSmall()) + free(this->begin()); + + this->BeginX = NewElts; + this->Capacity = NewCapacity; +} + +/// SmallVectorTemplateBase<TriviallyCopyable = true> - This is where we put +/// method implementations that are designed to work with POD-like T's. +template <typename T> +class SmallVectorTemplateBase<T, true> : public SmallVectorTemplateCommon<T> { +protected: + SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {} + + // No need to do a destroy loop for POD's. + static void destroy_range(T *, T *) {} + + /// Move the range [I, E) onto the uninitialized memory + /// starting with "Dest", constructing elements into it as needed. + template<typename It1, typename It2> + static void uninitialized_move(It1 I, It1 E, It2 Dest) { + // Just do a copy. + uninitialized_copy(I, E, Dest); + } + + /// Copy the range [I, E) onto the uninitialized memory + /// starting with "Dest", constructing elements into it as needed. + template<typename It1, typename It2> + static void uninitialized_copy(It1 I, It1 E, It2 Dest) { + // Arbitrary iterator types; just use the basic implementation. + std::uninitialized_copy(I, E, Dest); + } + + /// Copy the range [I, E) onto the uninitialized memory + /// starting with "Dest", constructing elements into it as needed. + template <typename T1, typename T2> + static void uninitialized_copy( + T1 *I, T1 *E, T2 *Dest, + typename std::enable_if<std::is_same<typename std::remove_const<T1>::type, + T2>::value>::type * = nullptr) { + // Use memcpy for PODs iterated by pointers (which includes SmallVector + // iterators): std::uninitialized_copy optimizes to memmove, but we can + // use memcpy here. Note that I and E are iterators and thus might be + // invalid for memcpy if they are equal. + if (I != E) + memcpy(reinterpret_cast<void *>(Dest), I, (E - I) * sizeof(T)); + } + + /// Double the size of the allocated memory, guaranteeing space for at + /// least one more element or MinSize if specified. + void grow(size_t MinSize = 0) { this->grow_pod(MinSize, sizeof(T)); } + +public: + void push_back(const T &Elt) { + if (LLVM_UNLIKELY(this->size() >= this->capacity())) + this->grow(); + memcpy(reinterpret_cast<void *>(this->end()), &Elt, sizeof(T)); + this->set_size(this->size() + 1); + } + + void pop_back() { this->set_size(this->size() - 1); } +}; + +/// This class consists of common code factored out of the SmallVector class to +/// reduce code duplication based on the SmallVector 'N' template parameter. +template <typename T> +class SmallVectorImpl : public SmallVectorTemplateBase<T> { + using SuperClass = SmallVectorTemplateBase<T>; + +public: + using iterator = typename SuperClass::iterator; + using const_iterator = typename SuperClass::const_iterator; + using reference = typename SuperClass::reference; + using size_type = typename SuperClass::size_type; + +protected: + // Default ctor - Initialize to empty. + explicit SmallVectorImpl(unsigned N) + : SmallVectorTemplateBase<T>(N) {} + +public: + SmallVectorImpl(const SmallVectorImpl &) = delete; + + ~SmallVectorImpl() { + // Subclass has already destructed this vector's elements. + // If this wasn't grown from the inline copy, deallocate the old space. + if (!this->isSmall()) + free(this->begin()); + } + + void clear() { + this->destroy_range(this->begin(), this->end()); + this->Size = 0; + } + + void resize(size_type N) { + if (N < this->size()) { + this->destroy_range(this->begin()+N, this->end()); + this->set_size(N); + } else if (N > this->size()) { + if (this->capacity() < N) + this->grow(N); + for (auto I = this->end(), E = this->begin() + N; I != E; ++I) + new (&*I) T(); + this->set_size(N); + } + } + + void resize(size_type N, const T &NV) { + if (N < this->size()) { + this->destroy_range(this->begin()+N, this->end()); + this->set_size(N); + } else if (N > this->size()) { + if (this->capacity() < N) + this->grow(N); + std::uninitialized_fill(this->end(), this->begin()+N, NV); + this->set_size(N); + } + } + + void reserve(size_type N) { + if (this->capacity() < N) + this->grow(N); + } + + LLVM_NODISCARD T pop_back_val() { + T Result = ::std::move(this->back()); + this->pop_back(); + return Result; + } + + void swap(SmallVectorImpl &RHS); + + /// Add the specified range to the end of the SmallVector. + template <typename in_iter, + typename = typename std::enable_if<std::is_convertible< + typename std::iterator_traits<in_iter>::iterator_category, + std::input_iterator_tag>::value>::type> + void append(in_iter in_start, in_iter in_end) { + size_type NumInputs = std::distance(in_start, in_end); + if (NumInputs > this->capacity() - this->size()) + this->grow(this->size()+NumInputs); + + this->uninitialized_copy(in_start, in_end, this->end()); + this->set_size(this->size() + NumInputs); + } + + /// Append \p NumInputs copies of \p Elt to the end. + void append(size_type NumInputs, const T &Elt) { + if (NumInputs > this->capacity() - this->size()) + this->grow(this->size()+NumInputs); + + std::uninitialized_fill_n(this->end(), NumInputs, Elt); + this->set_size(this->size() + NumInputs); + } + + void append(std::initializer_list<T> IL) { + append(IL.begin(), IL.end()); + } + + // FIXME: Consider assigning over existing elements, rather than clearing & + // re-initializing them - for all assign(...) variants. + + void assign(size_type NumElts, const T &Elt) { + clear(); + if (this->capacity() < NumElts) + this->grow(NumElts); + this->set_size(NumElts); + std::uninitialized_fill(this->begin(), this->end(), Elt); + } + + template <typename in_iter, + typename = typename std::enable_if<std::is_convertible< + typename std::iterator_traits<in_iter>::iterator_category, + std::input_iterator_tag>::value>::type> + void assign(in_iter in_start, in_iter in_end) { + clear(); + append(in_start, in_end); + } + + void assign(std::initializer_list<T> IL) { + clear(); + append(IL); + } + + 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. + std::move(I+1, this->end(), I); + // Drop the last elt. + this->pop_back(); + return(N); + } + + 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 = std::move(E, this->end(), S); + // Drop the last elts. + this->destroy_range(I, this->end()); + this->set_size(I - this->begin()); + return(N); + } + + iterator insert(iterator I, T &&Elt) { + if (I == this->end()) { // Important special case for empty vector. + this->push_back(::std::move(Elt)); + return this->end()-1; + } + + assert(I >= this->begin() && "Insertion iterator is out of bounds."); + assert(I <= this->end() && "Inserting past the end of the vector."); + + if (this->size() >= this->capacity()) { + size_t EltNo = I-this->begin(); + this->grow(); + I = this->begin()+EltNo; + } + + ::new ((void*) this->end()) T(::std::move(this->back())); + // Push everything else over. + std::move_backward(I, this->end()-1, this->end()); + this->set_size(this->size() + 1); + + // If we just moved the element we're inserting, be sure to update + // the reference. + T *EltPtr = &Elt; + if (I <= EltPtr && EltPtr < this->end()) + ++EltPtr; + + *I = ::std::move(*EltPtr); + return I; + } + + iterator insert(iterator I, const T &Elt) { + if (I == this->end()) { // Important special case for empty vector. + this->push_back(Elt); + return this->end()-1; + } + + assert(I >= this->begin() && "Insertion iterator is out of bounds."); + assert(I <= this->end() && "Inserting past the end of the vector."); + + if (this->size() >= this->capacity()) { + size_t EltNo = I-this->begin(); + this->grow(); + I = this->begin()+EltNo; + } + ::new ((void*) this->end()) T(std::move(this->back())); + // Push everything else over. + std::move_backward(I, this->end()-1, this->end()); + this->set_size(this->size() + 1); + + // If we just moved the element we're inserting, be sure to update + // the reference. + const T *EltPtr = &Elt; + if (I <= EltPtr && EltPtr < this->end()) + ++EltPtr; + + *I = *EltPtr; + return I; + } + + iterator insert(iterator I, size_type NumToInsert, const T &Elt) { + // Convert iterator to elt# to avoid invalidating iterator when we reserve() + size_t InsertElt = I - this->begin(); + + if (I == this->end()) { // Important special case for empty vector. + append(NumToInsert, Elt); + return this->begin()+InsertElt; + } + + assert(I >= this->begin() && "Insertion iterator is out of bounds."); + assert(I <= this->end() && "Inserting past the end of the vector."); + + // Ensure there is enough space. + reserve(this->size() + NumToInsert); + + // Uninvalidate the iterator. + I = this->begin()+InsertElt; + + // If there are more elements between the insertion point and the end of the + // range than there are being inserted, we can use a simple approach to + // insertion. Since we already reserved space, we know that this won't + // reallocate the vector. + if (size_t(this->end()-I) >= NumToInsert) { + T *OldEnd = this->end(); + append(std::move_iterator<iterator>(this->end() - NumToInsert), + std::move_iterator<iterator>(this->end())); + + // Copy the existing elements that get replaced. + std::move_backward(I, OldEnd-NumToInsert, OldEnd); + + std::fill_n(I, NumToInsert, Elt); + return I; + } + + // Otherwise, we're inserting more elements than exist already, and we're + // not inserting at the end. + + // Move over the elements that we're about to overwrite. + T *OldEnd = this->end(); + this->set_size(this->size() + NumToInsert); + size_t NumOverwritten = OldEnd-I; + this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten); + + // Replace the overwritten part. + std::fill_n(I, NumOverwritten, Elt); + + // Insert the non-overwritten middle part. + std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt); + return I; + } + + template <typename ItTy, + typename = typename std::enable_if<std::is_convertible< + typename std::iterator_traits<ItTy>::iterator_category, + std::input_iterator_tag>::value>::type> + iterator insert(iterator I, ItTy From, ItTy To) { + // Convert iterator to elt# to avoid invalidating iterator when we reserve() + size_t InsertElt = I - this->begin(); + + if (I == this->end()) { // Important special case for empty vector. + append(From, To); + return this->begin()+InsertElt; + } + + assert(I >= this->begin() && "Insertion iterator is out of bounds."); + assert(I <= this->end() && "Inserting past the end of the vector."); + + size_t NumToInsert = std::distance(From, To); + + // Ensure there is enough space. + reserve(this->size() + NumToInsert); + + // Uninvalidate the iterator. + I = this->begin()+InsertElt; + + // If there are more elements between the insertion point and the end of the + // range than there are being inserted, we can use a simple approach to + // insertion. Since we already reserved space, we know that this won't + // reallocate the vector. + if (size_t(this->end()-I) >= NumToInsert) { + T *OldEnd = this->end(); + append(std::move_iterator<iterator>(this->end() - NumToInsert), + std::move_iterator<iterator>(this->end())); + + // Copy the existing elements that get replaced. + std::move_backward(I, OldEnd-NumToInsert, OldEnd); + + std::copy(From, To, I); + return I; + } + + // Otherwise, we're inserting more elements than exist already, and we're + // not inserting at the end. + + // Move over the elements that we're about to overwrite. + T *OldEnd = this->end(); + this->set_size(this->size() + NumToInsert); + size_t NumOverwritten = OldEnd-I; + this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten); + + // Replace the overwritten part. + for (T *J = I; NumOverwritten > 0; --NumOverwritten) { + *J = *From; + ++J; ++From; + } + + // Insert the non-overwritten middle part. + this->uninitialized_copy(From, To, OldEnd); + return I; + } + + void insert(iterator I, std::initializer_list<T> IL) { + insert(I, IL.begin(), IL.end()); + } + + template <typename... ArgTypes> reference emplace_back(ArgTypes &&... Args) { + if (LLVM_UNLIKELY(this->size() >= this->capacity())) + this->grow(); + ::new ((void *)this->end()) T(std::forward<ArgTypes>(Args)...); + this->set_size(this->size() + 1); + return this->back(); + } + + SmallVectorImpl &operator=(const SmallVectorImpl &RHS); + + SmallVectorImpl &operator=(SmallVectorImpl &&RHS); + + bool operator==(const SmallVectorImpl &RHS) const { + if (this->size() != RHS.size()) return false; + return std::equal(this->begin(), this->end(), RHS.begin()); + } + bool operator!=(const SmallVectorImpl &RHS) const { + return !(*this == RHS); + } + + bool operator<(const SmallVectorImpl &RHS) const { + return std::lexicographical_compare(this->begin(), this->end(), + RHS.begin(), RHS.end()); + } +}; + +template <typename T> +void SmallVectorImpl<T>::swap(SmallVectorImpl<T> &RHS) { + if (this == &RHS) return; + + // We can only avoid copying elements if neither vector is small. + if (!this->isSmall() && !RHS.isSmall()) { + std::swap(this->BeginX, RHS.BeginX); + std::swap(this->Size, RHS.Size); + std::swap(this->Capacity, RHS.Capacity); + return; + } + if (RHS.size() > this->capacity()) + this->grow(RHS.size()); + if (this->size() > RHS.capacity()) + RHS.grow(this->size()); + + // Swap the shared elements. + size_t NumShared = this->size(); + if (NumShared > RHS.size()) NumShared = RHS.size(); + for (size_type i = 0; i != NumShared; ++i) + std::swap((*this)[i], RHS[i]); + + // Copy over the extra elts. + if (this->size() > RHS.size()) { + size_t EltDiff = this->size() - RHS.size(); + this->uninitialized_copy(this->begin()+NumShared, this->end(), RHS.end()); + RHS.set_size(RHS.size() + EltDiff); + this->destroy_range(this->begin()+NumShared, this->end()); + this->set_size(NumShared); + } else if (RHS.size() > this->size()) { + size_t EltDiff = RHS.size() - this->size(); + this->uninitialized_copy(RHS.begin()+NumShared, RHS.end(), this->end()); + this->set_size(this->size() + EltDiff); + this->destroy_range(RHS.begin()+NumShared, RHS.end()); + RHS.set_size(NumShared); + } +} + +template <typename T> +SmallVectorImpl<T> &SmallVectorImpl<T>:: + operator=(const SmallVectorImpl<T> &RHS) { + // Avoid self-assignment. + if (this == &RHS) return *this; + + // If we already have sufficient space, assign the common elements, then + // destroy any excess. + size_t RHSSize = RHS.size(); + size_t CurSize = this->size(); + if (CurSize >= RHSSize) { + // Assign common elements. + iterator NewEnd; + if (RHSSize) + NewEnd = std::copy(RHS.begin(), RHS.begin()+RHSSize, this->begin()); + else + NewEnd = this->begin(); + + // Destroy excess elements. + this->destroy_range(NewEnd, this->end()); + + // Trim. + this->set_size(RHSSize); + return *this; + } + + // If we have to grow to have enough elements, destroy the current elements. + // This allows us to avoid copying them during the grow. + // FIXME: don't do this if they're efficiently moveable. + if (this->capacity() < RHSSize) { + // Destroy current elements. + this->destroy_range(this->begin(), this->end()); + this->set_size(0); + CurSize = 0; + this->grow(RHSSize); + } else if (CurSize) { + // Otherwise, use assignment for the already-constructed elements. + std::copy(RHS.begin(), RHS.begin()+CurSize, this->begin()); + } + + // Copy construct the new elements in place. + this->uninitialized_copy(RHS.begin()+CurSize, RHS.end(), + this->begin()+CurSize); + + // Set end. + this->set_size(RHSSize); + return *this; +} + +template <typename T> +SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) { + // Avoid self-assignment. + if (this == &RHS) return *this; + + // If the RHS isn't small, clear this vector and then steal its buffer. + if (!RHS.isSmall()) { + this->destroy_range(this->begin(), this->end()); + if (!this->isSmall()) free(this->begin()); + this->BeginX = RHS.BeginX; + this->Size = RHS.Size; + this->Capacity = RHS.Capacity; + RHS.resetToSmall(); + return *this; + } + + // If we already have sufficient space, assign the common elements, then + // destroy any excess. + size_t RHSSize = RHS.size(); + size_t CurSize = this->size(); + if (CurSize >= RHSSize) { + // Assign common elements. + iterator NewEnd = this->begin(); + if (RHSSize) + NewEnd = std::move(RHS.begin(), RHS.end(), NewEnd); + + // Destroy excess elements and trim the bounds. + this->destroy_range(NewEnd, this->end()); + this->set_size(RHSSize); + + // Clear the RHS. + RHS.clear(); + + return *this; + } + + // If we have to grow to have enough elements, destroy the current elements. + // This allows us to avoid copying them during the grow. + // FIXME: this may not actually make any sense if we can efficiently move + // elements. + if (this->capacity() < RHSSize) { + // Destroy current elements. + this->destroy_range(this->begin(), this->end()); + this->set_size(0); + CurSize = 0; + this->grow(RHSSize); + } else if (CurSize) { + // Otherwise, use assignment for the already-constructed elements. + std::move(RHS.begin(), RHS.begin()+CurSize, this->begin()); + } + + // Move-construct the new elements in place. + this->uninitialized_move(RHS.begin()+CurSize, RHS.end(), + this->begin()+CurSize); + + // Set end. + this->set_size(RHSSize); + + RHS.clear(); + return *this; +} + +/// Storage for the SmallVector elements. This is specialized for the N=0 case +/// to avoid allocating unnecessary storage. +template <typename T, unsigned N> +struct SmallVectorStorage { + AlignedCharArrayUnion<T> InlineElts[N]; +}; + +/// We need the storage to be properly aligned even for small-size of 0 so that +/// the pointer math in \a SmallVectorTemplateCommon::getFirstEl() is +/// well-defined. +template <typename T> struct alignas(alignof(T)) SmallVectorStorage<T, 0> {}; + +/// This is a 'vector' (really, a variable-sized array), optimized +/// for the case when the array is small. It contains some number of elements +/// in-place, which allows it to avoid heap allocation when the actual number of +/// elements is below that threshold. This allows normal "small" cases to be +/// fast without losing generality for large inputs. +/// +/// Note that this does not attempt to be exception safe. +/// +template <typename T, unsigned N> +class SmallVector : public SmallVectorImpl<T>, SmallVectorStorage<T, N> { +public: + SmallVector() : SmallVectorImpl<T>(N) {} + + ~SmallVector() { + // Destroy the constructed elements in the vector. + this->destroy_range(this->begin(), this->end()); + } + + explicit SmallVector(size_t Size, const T &Value = T()) + : SmallVectorImpl<T>(N) { + this->assign(Size, Value); + } + + template <typename ItTy, + typename = typename std::enable_if<std::is_convertible< + typename std::iterator_traits<ItTy>::iterator_category, + std::input_iterator_tag>::value>::type> + SmallVector(ItTy S, ItTy E) : SmallVectorImpl<T>(N) { + this->append(S, E); + } + + template <typename RangeTy> + explicit SmallVector(const iterator_range<RangeTy> &R) + : SmallVectorImpl<T>(N) { + this->append(R.begin(), R.end()); + } + + SmallVector(std::initializer_list<T> IL) : SmallVectorImpl<T>(N) { + this->assign(IL); + } + + SmallVector(const SmallVector &RHS) : SmallVectorImpl<T>(N) { + if (!RHS.empty()) + SmallVectorImpl<T>::operator=(RHS); + } + + const SmallVector &operator=(const SmallVector &RHS) { + SmallVectorImpl<T>::operator=(RHS); + return *this; + } + + SmallVector(SmallVector &&RHS) : SmallVectorImpl<T>(N) { + if (!RHS.empty()) + SmallVectorImpl<T>::operator=(::std::move(RHS)); + } + + SmallVector(SmallVectorImpl<T> &&RHS) : SmallVectorImpl<T>(N) { + if (!RHS.empty()) + SmallVectorImpl<T>::operator=(::std::move(RHS)); + } + + const SmallVector &operator=(SmallVector &&RHS) { + SmallVectorImpl<T>::operator=(::std::move(RHS)); + return *this; + } + + const SmallVector &operator=(SmallVectorImpl<T> &&RHS) { + SmallVectorImpl<T>::operator=(::std::move(RHS)); + return *this; + } + + const SmallVector &operator=(std::initializer_list<T> IL) { + this->assign(IL); + return *this; + } +}; + +template <typename T, unsigned N> +inline size_t capacity_in_bytes(const SmallVector<T, N> &X) { + return X.capacity_in_bytes(); +} + +/// Given a range of type R, iterate the entire range and return a +/// SmallVector with elements of the vector. This is useful, for example, +/// when you want to iterate a range and then sort the results. +template <unsigned Size, typename R> +SmallVector<typename std::remove_const<typename std::remove_reference< + decltype(*std::begin(std::declval<R &>()))>::type>::type, + Size> +to_vector(R &&Range) { + return {std::begin(Range), std::end(Range)}; +} + +} // end namespace llvm + +namespace std { + + /// Implement std::swap in terms of SmallVector swap. + template<typename T> + inline void + swap(llvm::SmallVectorImpl<T> &LHS, llvm::SmallVectorImpl<T> &RHS) { + LHS.swap(RHS); + } + + /// Implement std::swap in terms of SmallVector swap. + template<typename T, unsigned N> + inline void + swap(llvm::SmallVector<T, N> &LHS, llvm::SmallVector<T, N> &RHS) { + LHS.swap(RHS); + } + +} // end namespace std + +#endif // LLVM_ADT_SMALLVECTOR_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/SparseBitVector.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/SparseBitVector.h new file mode 100644 index 0000000..12850e1 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/SparseBitVector.h
@@ -0,0 +1,892 @@ +//===- llvm/ADT/SparseBitVector.h - Efficient Sparse BitVector --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the SparseBitVector class. See the doxygen comment for +// SparseBitVector for more details on the algorithm used. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SPARSEBITVECTOR_H +#define LLVM_ADT_SPARSEBITVECTOR_H + +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include <cassert> +#include <climits> +#include <cstring> +#include <iterator> +#include <list> + +namespace llvm { + +/// SparseBitVector is an implementation of a bitvector that is sparse by only +/// storing the elements that have non-zero bits set. In order to make this +/// fast for the most common cases, SparseBitVector is implemented as a linked +/// list of SparseBitVectorElements. We maintain a pointer to the last +/// SparseBitVectorElement accessed (in the form of a list iterator), in order +/// to make multiple in-order test/set constant time after the first one is +/// executed. Note that using vectors to store SparseBitVectorElement's does +/// not work out very well because it causes insertion in the middle to take +/// enormous amounts of time with a large amount of bits. Other structures that +/// have better worst cases for insertion in the middle (various balanced trees, +/// etc) do not perform as well in practice as a linked list with this iterator +/// kept up to date. They are also significantly more memory intensive. + +template <unsigned ElementSize = 128> struct SparseBitVectorElement { +public: + using BitWord = unsigned long; + using size_type = unsigned; + enum { + BITWORD_SIZE = sizeof(BitWord) * CHAR_BIT, + BITWORDS_PER_ELEMENT = (ElementSize + BITWORD_SIZE - 1) / BITWORD_SIZE, + BITS_PER_ELEMENT = ElementSize + }; + +private: + // Index of Element in terms of where first bit starts. + unsigned ElementIndex; + BitWord Bits[BITWORDS_PER_ELEMENT]; + + SparseBitVectorElement() { + ElementIndex = ~0U; + memset(&Bits[0], 0, sizeof (BitWord) * BITWORDS_PER_ELEMENT); + } + +public: + explicit SparseBitVectorElement(unsigned Idx) { + ElementIndex = Idx; + memset(&Bits[0], 0, sizeof (BitWord) * BITWORDS_PER_ELEMENT); + } + + // Comparison. + bool operator==(const SparseBitVectorElement &RHS) const { + if (ElementIndex != RHS.ElementIndex) + return false; + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) + if (Bits[i] != RHS.Bits[i]) + return false; + return true; + } + + bool operator!=(const SparseBitVectorElement &RHS) const { + return !(*this == RHS); + } + + // Return the bits that make up word Idx in our element. + BitWord word(unsigned Idx) const { + assert(Idx < BITWORDS_PER_ELEMENT); + return Bits[Idx]; + } + + unsigned index() const { + return ElementIndex; + } + + bool empty() const { + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) + if (Bits[i]) + return false; + return true; + } + + void set(unsigned Idx) { + Bits[Idx / BITWORD_SIZE] |= 1L << (Idx % BITWORD_SIZE); + } + + bool test_and_set(unsigned Idx) { + bool old = test(Idx); + if (!old) { + set(Idx); + return true; + } + return false; + } + + void reset(unsigned Idx) { + Bits[Idx / BITWORD_SIZE] &= ~(1L << (Idx % BITWORD_SIZE)); + } + + bool test(unsigned Idx) const { + return Bits[Idx / BITWORD_SIZE] & (1L << (Idx % BITWORD_SIZE)); + } + + size_type count() const { + unsigned NumBits = 0; + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) + NumBits += countPopulation(Bits[i]); + return NumBits; + } + + /// find_first - Returns the index of the first set bit. + int find_first() const { + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) + if (Bits[i] != 0) + return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); + llvm_unreachable("Illegal empty element"); + } + + /// find_last - Returns the index of the last set bit. + int find_last() const { + for (unsigned I = 0; I < BITWORDS_PER_ELEMENT; ++I) { + unsigned Idx = BITWORDS_PER_ELEMENT - I - 1; + if (Bits[Idx] != 0) + return Idx * BITWORD_SIZE + BITWORD_SIZE - + countLeadingZeros(Bits[Idx]) - 1; + } + llvm_unreachable("Illegal empty element"); + } + + /// find_next - Returns the index of the next set bit starting from the + /// "Curr" bit. Returns -1 if the next set bit is not found. + int find_next(unsigned Curr) const { + if (Curr >= BITS_PER_ELEMENT) + return -1; + + unsigned WordPos = Curr / BITWORD_SIZE; + unsigned BitPos = Curr % BITWORD_SIZE; + BitWord Copy = Bits[WordPos]; + assert(WordPos <= BITWORDS_PER_ELEMENT + && "Word Position outside of element"); + + // Mask off previous bits. + Copy &= ~0UL << BitPos; + + if (Copy != 0) + return WordPos * BITWORD_SIZE + countTrailingZeros(Copy); + + // Check subsequent words. + for (unsigned i = WordPos+1; i < BITWORDS_PER_ELEMENT; ++i) + if (Bits[i] != 0) + return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); + return -1; + } + + // Union this element with RHS and return true if this one changed. + bool unionWith(const SparseBitVectorElement &RHS) { + bool changed = false; + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) { + BitWord old = changed ? 0 : Bits[i]; + + Bits[i] |= RHS.Bits[i]; + if (!changed && old != Bits[i]) + changed = true; + } + return changed; + } + + // Return true if we have any bits in common with RHS + bool intersects(const SparseBitVectorElement &RHS) const { + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) { + if (RHS.Bits[i] & Bits[i]) + return true; + } + return false; + } + + // Intersect this Element with RHS and return true if this one changed. + // BecameZero is set to true if this element became all-zero bits. + bool intersectWith(const SparseBitVectorElement &RHS, + bool &BecameZero) { + bool changed = false; + bool allzero = true; + + BecameZero = false; + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) { + BitWord old = changed ? 0 : Bits[i]; + + Bits[i] &= RHS.Bits[i]; + if (Bits[i] != 0) + allzero = false; + + if (!changed && old != Bits[i]) + changed = true; + } + BecameZero = allzero; + return changed; + } + + // Intersect this Element with the complement of RHS and return true if this + // one changed. BecameZero is set to true if this element became all-zero + // bits. + bool intersectWithComplement(const SparseBitVectorElement &RHS, + bool &BecameZero) { + bool changed = false; + bool allzero = true; + + BecameZero = false; + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) { + BitWord old = changed ? 0 : Bits[i]; + + Bits[i] &= ~RHS.Bits[i]; + if (Bits[i] != 0) + allzero = false; + + if (!changed && old != Bits[i]) + changed = true; + } + BecameZero = allzero; + return changed; + } + + // Three argument version of intersectWithComplement that intersects + // RHS1 & ~RHS2 into this element + void intersectWithComplement(const SparseBitVectorElement &RHS1, + const SparseBitVectorElement &RHS2, + bool &BecameZero) { + bool allzero = true; + + BecameZero = false; + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) { + Bits[i] = RHS1.Bits[i] & ~RHS2.Bits[i]; + if (Bits[i] != 0) + allzero = false; + } + BecameZero = allzero; + } +}; + +template <unsigned ElementSize = 128> +class SparseBitVector { + using ElementList = std::list<SparseBitVectorElement<ElementSize>>; + using ElementListIter = typename ElementList::iterator; + using ElementListConstIter = typename ElementList::const_iterator; + enum { + BITWORD_SIZE = SparseBitVectorElement<ElementSize>::BITWORD_SIZE + }; + + ElementList Elements; + // Pointer to our current Element. This has no visible effect on the external + // state of a SparseBitVector, it's just used to improve performance in the + // common case of testing/modifying bits with similar indices. + mutable ElementListIter CurrElementIter; + + // This is like std::lower_bound, except we do linear searching from the + // current position. + ElementListIter FindLowerBoundImpl(unsigned ElementIndex) const { + + // We cache a non-const iterator so we're forced to resort to const_cast to + // get the begin/end in the case where 'this' is const. To avoid duplication + // of code with the only difference being whether the const cast is present + // 'this' is always const in this particular function and we sort out the + // difference in FindLowerBound and FindLowerBoundConst. + ElementListIter Begin = + const_cast<SparseBitVector<ElementSize> *>(this)->Elements.begin(); + ElementListIter End = + const_cast<SparseBitVector<ElementSize> *>(this)->Elements.end(); + + if (Elements.empty()) { + CurrElementIter = Begin; + return CurrElementIter; + } + + // Make sure our current iterator is valid. + if (CurrElementIter == End) + --CurrElementIter; + + // Search from our current iterator, either backwards or forwards, + // depending on what element we are looking for. + ElementListIter ElementIter = CurrElementIter; + if (CurrElementIter->index() == ElementIndex) { + return ElementIter; + } else if (CurrElementIter->index() > ElementIndex) { + while (ElementIter != Begin + && ElementIter->index() > ElementIndex) + --ElementIter; + } else { + while (ElementIter != End && + ElementIter->index() < ElementIndex) + ++ElementIter; + } + CurrElementIter = ElementIter; + return ElementIter; + } + ElementListConstIter FindLowerBoundConst(unsigned ElementIndex) const { + return FindLowerBoundImpl(ElementIndex); + } + ElementListIter FindLowerBound(unsigned ElementIndex) { + return FindLowerBoundImpl(ElementIndex); + } + + // Iterator to walk set bits in the bitmap. This iterator is a lot uglier + // than it would be, in order to be efficient. + class SparseBitVectorIterator { + private: + bool AtEnd; + + const SparseBitVector<ElementSize> *BitVector = nullptr; + + // Current element inside of bitmap. + ElementListConstIter Iter; + + // Current bit number inside of our bitmap. + unsigned BitNumber; + + // Current word number inside of our element. + unsigned WordNumber; + + // Current bits from the element. + typename SparseBitVectorElement<ElementSize>::BitWord Bits; + + // Move our iterator to the first non-zero bit in the bitmap. + void AdvanceToFirstNonZero() { + if (AtEnd) + return; + if (BitVector->Elements.empty()) { + AtEnd = true; + return; + } + Iter = BitVector->Elements.begin(); + BitNumber = Iter->index() * ElementSize; + unsigned BitPos = Iter->find_first(); + BitNumber += BitPos; + WordNumber = (BitNumber % ElementSize) / BITWORD_SIZE; + Bits = Iter->word(WordNumber); + Bits >>= BitPos % BITWORD_SIZE; + } + + // Move our iterator to the next non-zero bit. + void AdvanceToNextNonZero() { + if (AtEnd) + return; + + while (Bits && !(Bits & 1)) { + Bits >>= 1; + BitNumber += 1; + } + + // See if we ran out of Bits in this word. + if (!Bits) { + int NextSetBitNumber = Iter->find_next(BitNumber % ElementSize) ; + // If we ran out of set bits in this element, move to next element. + if (NextSetBitNumber == -1 || (BitNumber % ElementSize == 0)) { + ++Iter; + WordNumber = 0; + + // We may run out of elements in the bitmap. + if (Iter == BitVector->Elements.end()) { + AtEnd = true; + return; + } + // Set up for next non-zero word in bitmap. + BitNumber = Iter->index() * ElementSize; + NextSetBitNumber = Iter->find_first(); + BitNumber += NextSetBitNumber; + WordNumber = (BitNumber % ElementSize) / BITWORD_SIZE; + Bits = Iter->word(WordNumber); + Bits >>= NextSetBitNumber % BITWORD_SIZE; + } else { + WordNumber = (NextSetBitNumber % ElementSize) / BITWORD_SIZE; + Bits = Iter->word(WordNumber); + Bits >>= NextSetBitNumber % BITWORD_SIZE; + BitNumber = Iter->index() * ElementSize; + BitNumber += NextSetBitNumber; + } + } + } + + public: + SparseBitVectorIterator() = default; + + SparseBitVectorIterator(const SparseBitVector<ElementSize> *RHS, + bool end = false):BitVector(RHS) { + Iter = BitVector->Elements.begin(); + BitNumber = 0; + Bits = 0; + WordNumber = ~0; + AtEnd = end; + AdvanceToFirstNonZero(); + } + + // Preincrement. + inline SparseBitVectorIterator& operator++() { + ++BitNumber; + Bits >>= 1; + AdvanceToNextNonZero(); + return *this; + } + + // Postincrement. + inline SparseBitVectorIterator operator++(int) { + SparseBitVectorIterator tmp = *this; + ++*this; + return tmp; + } + + // Return the current set bit number. + unsigned operator*() const { + return BitNumber; + } + + bool operator==(const SparseBitVectorIterator &RHS) const { + // If they are both at the end, ignore the rest of the fields. + if (AtEnd && RHS.AtEnd) + return true; + // Otherwise they are the same if they have the same bit number and + // bitmap. + return AtEnd == RHS.AtEnd && RHS.BitNumber == BitNumber; + } + + bool operator!=(const SparseBitVectorIterator &RHS) const { + return !(*this == RHS); + } + }; + +public: + using iterator = SparseBitVectorIterator; + + SparseBitVector() : Elements(), CurrElementIter(Elements.begin()) {} + + SparseBitVector(const SparseBitVector &RHS) + : Elements(RHS.Elements), CurrElementIter(Elements.begin()) {} + SparseBitVector(SparseBitVector &&RHS) + : Elements(std::move(RHS.Elements)), CurrElementIter(Elements.begin()) {} + + // Clear. + void clear() { + Elements.clear(); + } + + // Assignment + SparseBitVector& operator=(const SparseBitVector& RHS) { + if (this == &RHS) + return *this; + + Elements = RHS.Elements; + CurrElementIter = Elements.begin(); + return *this; + } + SparseBitVector &operator=(SparseBitVector &&RHS) { + Elements = std::move(RHS.Elements); + CurrElementIter = Elements.begin(); + return *this; + } + + // Test, Reset, and Set a bit in the bitmap. + bool test(unsigned Idx) const { + if (Elements.empty()) + return false; + + unsigned ElementIndex = Idx / ElementSize; + ElementListConstIter ElementIter = FindLowerBoundConst(ElementIndex); + + // If we can't find an element that is supposed to contain this bit, there + // is nothing more to do. + if (ElementIter == Elements.end() || + ElementIter->index() != ElementIndex) + return false; + return ElementIter->test(Idx % ElementSize); + } + + void reset(unsigned Idx) { + if (Elements.empty()) + return; + + unsigned ElementIndex = Idx / ElementSize; + ElementListIter ElementIter = FindLowerBound(ElementIndex); + + // If we can't find an element that is supposed to contain this bit, there + // is nothing more to do. + if (ElementIter == Elements.end() || + ElementIter->index() != ElementIndex) + return; + ElementIter->reset(Idx % ElementSize); + + // When the element is zeroed out, delete it. + if (ElementIter->empty()) { + ++CurrElementIter; + Elements.erase(ElementIter); + } + } + + void set(unsigned Idx) { + unsigned ElementIndex = Idx / ElementSize; + ElementListIter ElementIter; + if (Elements.empty()) { + ElementIter = Elements.emplace(Elements.end(), ElementIndex); + } else { + ElementIter = FindLowerBound(ElementIndex); + + if (ElementIter == Elements.end() || + ElementIter->index() != ElementIndex) { + // We may have hit the beginning of our SparseBitVector, in which case, + // we may need to insert right after this element, which requires moving + // the current iterator forward one, because insert does insert before. + if (ElementIter != Elements.end() && + ElementIter->index() < ElementIndex) + ++ElementIter; + ElementIter = Elements.emplace(ElementIter, ElementIndex); + } + } + CurrElementIter = ElementIter; + + ElementIter->set(Idx % ElementSize); + } + + bool test_and_set(unsigned Idx) { + bool old = test(Idx); + if (!old) { + set(Idx); + return true; + } + return false; + } + + bool operator!=(const SparseBitVector &RHS) const { + return !(*this == RHS); + } + + bool operator==(const SparseBitVector &RHS) const { + ElementListConstIter Iter1 = Elements.begin(); + ElementListConstIter Iter2 = RHS.Elements.begin(); + + for (; Iter1 != Elements.end() && Iter2 != RHS.Elements.end(); + ++Iter1, ++Iter2) { + if (*Iter1 != *Iter2) + return false; + } + return Iter1 == Elements.end() && Iter2 == RHS.Elements.end(); + } + + // Union our bitmap with the RHS and return true if we changed. + bool operator|=(const SparseBitVector &RHS) { + if (this == &RHS) + return false; + + bool changed = false; + ElementListIter Iter1 = Elements.begin(); + ElementListConstIter Iter2 = RHS.Elements.begin(); + + // If RHS is empty, we are done + if (RHS.Elements.empty()) + return false; + + while (Iter2 != RHS.Elements.end()) { + if (Iter1 == Elements.end() || Iter1->index() > Iter2->index()) { + Elements.insert(Iter1, *Iter2); + ++Iter2; + changed = true; + } else if (Iter1->index() == Iter2->index()) { + changed |= Iter1->unionWith(*Iter2); + ++Iter1; + ++Iter2; + } else { + ++Iter1; + } + } + CurrElementIter = Elements.begin(); + return changed; + } + + // Intersect our bitmap with the RHS and return true if ours changed. + bool operator&=(const SparseBitVector &RHS) { + if (this == &RHS) + return false; + + bool changed = false; + ElementListIter Iter1 = Elements.begin(); + ElementListConstIter Iter2 = RHS.Elements.begin(); + + // Check if both bitmaps are empty. + if (Elements.empty() && RHS.Elements.empty()) + return false; + + // Loop through, intersecting as we go, erasing elements when necessary. + while (Iter2 != RHS.Elements.end()) { + if (Iter1 == Elements.end()) { + CurrElementIter = Elements.begin(); + return changed; + } + + if (Iter1->index() > Iter2->index()) { + ++Iter2; + } else if (Iter1->index() == Iter2->index()) { + bool BecameZero; + changed |= Iter1->intersectWith(*Iter2, BecameZero); + if (BecameZero) { + ElementListIter IterTmp = Iter1; + ++Iter1; + Elements.erase(IterTmp); + } else { + ++Iter1; + } + ++Iter2; + } else { + ElementListIter IterTmp = Iter1; + ++Iter1; + Elements.erase(IterTmp); + changed = true; + } + } + if (Iter1 != Elements.end()) { + Elements.erase(Iter1, Elements.end()); + changed = true; + } + CurrElementIter = Elements.begin(); + return changed; + } + + // Intersect our bitmap with the complement of the RHS and return true + // if ours changed. + bool intersectWithComplement(const SparseBitVector &RHS) { + if (this == &RHS) { + if (!empty()) { + clear(); + return true; + } + return false; + } + + bool changed = false; + ElementListIter Iter1 = Elements.begin(); + ElementListConstIter Iter2 = RHS.Elements.begin(); + + // If either our bitmap or RHS is empty, we are done + if (Elements.empty() || RHS.Elements.empty()) + return false; + + // Loop through, intersecting as we go, erasing elements when necessary. + while (Iter2 != RHS.Elements.end()) { + if (Iter1 == Elements.end()) { + CurrElementIter = Elements.begin(); + return changed; + } + + if (Iter1->index() > Iter2->index()) { + ++Iter2; + } else if (Iter1->index() == Iter2->index()) { + bool BecameZero; + changed |= Iter1->intersectWithComplement(*Iter2, BecameZero); + if (BecameZero) { + ElementListIter IterTmp = Iter1; + ++Iter1; + Elements.erase(IterTmp); + } else { + ++Iter1; + } + ++Iter2; + } else { + ++Iter1; + } + } + CurrElementIter = Elements.begin(); + return changed; + } + + bool intersectWithComplement(const SparseBitVector<ElementSize> *RHS) const { + return intersectWithComplement(*RHS); + } + + // Three argument version of intersectWithComplement. + // Result of RHS1 & ~RHS2 is stored into this bitmap. + void intersectWithComplement(const SparseBitVector<ElementSize> &RHS1, + const SparseBitVector<ElementSize> &RHS2) + { + if (this == &RHS1) { + intersectWithComplement(RHS2); + return; + } else if (this == &RHS2) { + SparseBitVector RHS2Copy(RHS2); + intersectWithComplement(RHS1, RHS2Copy); + return; + } + + Elements.clear(); + CurrElementIter = Elements.begin(); + ElementListConstIter Iter1 = RHS1.Elements.begin(); + ElementListConstIter Iter2 = RHS2.Elements.begin(); + + // If RHS1 is empty, we are done + // If RHS2 is empty, we still have to copy RHS1 + if (RHS1.Elements.empty()) + return; + + // Loop through, intersecting as we go, erasing elements when necessary. + while (Iter2 != RHS2.Elements.end()) { + if (Iter1 == RHS1.Elements.end()) + return; + + if (Iter1->index() > Iter2->index()) { + ++Iter2; + } else if (Iter1->index() == Iter2->index()) { + bool BecameZero = false; + Elements.emplace_back(Iter1->index()); + Elements.back().intersectWithComplement(*Iter1, *Iter2, BecameZero); + if (BecameZero) + Elements.pop_back(); + ++Iter1; + ++Iter2; + } else { + Elements.push_back(*Iter1++); + } + } + + // copy the remaining elements + std::copy(Iter1, RHS1.Elements.end(), std::back_inserter(Elements)); + } + + void intersectWithComplement(const SparseBitVector<ElementSize> *RHS1, + const SparseBitVector<ElementSize> *RHS2) { + intersectWithComplement(*RHS1, *RHS2); + } + + bool intersects(const SparseBitVector<ElementSize> *RHS) const { + return intersects(*RHS); + } + + // Return true if we share any bits in common with RHS + bool intersects(const SparseBitVector<ElementSize> &RHS) const { + ElementListConstIter Iter1 = Elements.begin(); + ElementListConstIter Iter2 = RHS.Elements.begin(); + + // Check if both bitmaps are empty. + if (Elements.empty() && RHS.Elements.empty()) + return false; + + // Loop through, intersecting stopping when we hit bits in common. + while (Iter2 != RHS.Elements.end()) { + if (Iter1 == Elements.end()) + return false; + + if (Iter1->index() > Iter2->index()) { + ++Iter2; + } else if (Iter1->index() == Iter2->index()) { + if (Iter1->intersects(*Iter2)) + return true; + ++Iter1; + ++Iter2; + } else { + ++Iter1; + } + } + return false; + } + + // Return true iff all bits set in this SparseBitVector are + // also set in RHS. + bool contains(const SparseBitVector<ElementSize> &RHS) const { + SparseBitVector<ElementSize> Result(*this); + Result &= RHS; + return (Result == RHS); + } + + // Return the first set bit in the bitmap. Return -1 if no bits are set. + int find_first() const { + if (Elements.empty()) + return -1; + const SparseBitVectorElement<ElementSize> &First = *(Elements.begin()); + return (First.index() * ElementSize) + First.find_first(); + } + + // Return the last set bit in the bitmap. Return -1 if no bits are set. + int find_last() const { + if (Elements.empty()) + return -1; + const SparseBitVectorElement<ElementSize> &Last = *(Elements.rbegin()); + return (Last.index() * ElementSize) + Last.find_last(); + } + + // Return true if the SparseBitVector is empty + bool empty() const { + return Elements.empty(); + } + + unsigned count() const { + unsigned BitCount = 0; + for (ElementListConstIter Iter = Elements.begin(); + Iter != Elements.end(); + ++Iter) + BitCount += Iter->count(); + + return BitCount; + } + + iterator begin() const { + return iterator(this); + } + + iterator end() const { + return iterator(this, true); + } +}; + +// Convenience functions to allow Or and And without dereferencing in the user +// code. + +template <unsigned ElementSize> +inline bool operator |=(SparseBitVector<ElementSize> &LHS, + const SparseBitVector<ElementSize> *RHS) { + return LHS |= *RHS; +} + +template <unsigned ElementSize> +inline bool operator |=(SparseBitVector<ElementSize> *LHS, + const SparseBitVector<ElementSize> &RHS) { + return LHS->operator|=(RHS); +} + +template <unsigned ElementSize> +inline bool operator &=(SparseBitVector<ElementSize> *LHS, + const SparseBitVector<ElementSize> &RHS) { + return LHS->operator&=(RHS); +} + +template <unsigned ElementSize> +inline bool operator &=(SparseBitVector<ElementSize> &LHS, + const SparseBitVector<ElementSize> *RHS) { + return LHS &= *RHS; +} + +// Convenience functions for infix union, intersection, difference operators. + +template <unsigned ElementSize> +inline SparseBitVector<ElementSize> +operator|(const SparseBitVector<ElementSize> &LHS, + const SparseBitVector<ElementSize> &RHS) { + SparseBitVector<ElementSize> Result(LHS); + Result |= RHS; + return Result; +} + +template <unsigned ElementSize> +inline SparseBitVector<ElementSize> +operator&(const SparseBitVector<ElementSize> &LHS, + const SparseBitVector<ElementSize> &RHS) { + SparseBitVector<ElementSize> Result(LHS); + Result &= RHS; + return Result; +} + +template <unsigned ElementSize> +inline SparseBitVector<ElementSize> +operator-(const SparseBitVector<ElementSize> &LHS, + const SparseBitVector<ElementSize> &RHS) { + SparseBitVector<ElementSize> Result; + Result.intersectWithComplement(LHS, RHS); + return Result; +} + +// Dump a SparseBitVector to a stream +template <unsigned ElementSize> +void dump(const SparseBitVector<ElementSize> &LHS, raw_ostream &out) { + out << "["; + + typename SparseBitVector<ElementSize>::iterator bi = LHS.begin(), + be = LHS.end(); + if (bi != be) { + out << *bi; + for (++bi; bi != be; ++bi) { + out << " " << *bi; + } + } + out << "]\n"; +} + +} // end namespace llvm + +#endif // LLVM_ADT_SPARSEBITVECTOR_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/SparseMultiSet.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/SparseMultiSet.h new file mode 100644 index 0000000..d9d3ff4 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/SparseMultiSet.h
@@ -0,0 +1,522 @@ +//===- llvm/ADT/SparseMultiSet.h - Sparse multiset --------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the SparseMultiSet class, which adds multiset behavior to +// the SparseSet. +// +// A sparse multiset holds a small number of objects identified by integer keys +// from a moderately sized universe. The sparse multiset uses more memory than +// other containers in order to provide faster operations. Any key can map to +// multiple values. A SparseMultiSetNode class is provided, which serves as a +// convenient base class for the contents of a SparseMultiSet. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SPARSEMULTISET_H +#define LLVM_ADT_SPARSEMULTISET_H + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SparseSet.h" +#include <cassert> +#include <cstdint> +#include <cstdlib> +#include <iterator> +#include <limits> +#include <utility> + +namespace llvm { + +/// Fast multiset implementation for objects that can be identified by small +/// unsigned keys. +/// +/// SparseMultiSet allocates memory proportional to the size of the key +/// universe, so it is not recommended for building composite data structures. +/// It is useful for algorithms that require a single set with fast operations. +/// +/// Compared to DenseSet and DenseMap, SparseMultiSet provides constant-time +/// fast clear() as fast as a vector. The find(), insert(), and erase() +/// operations are all constant time, and typically faster than a hash table. +/// The iteration order doesn't depend on numerical key values, it only depends +/// on the order of insert() and erase() operations. Iteration order is the +/// insertion order. Iteration is only provided over elements of equivalent +/// keys, but iterators are bidirectional. +/// +/// Compared to BitVector, SparseMultiSet<unsigned> uses 8x-40x more memory, but +/// offers constant-time clear() and size() operations as well as fast iteration +/// independent on the size of the universe. +/// +/// SparseMultiSet contains a dense vector holding all the objects and a sparse +/// array holding indexes into the dense vector. Most of the memory is used by +/// the sparse array which is the size of the key universe. The SparseT template +/// parameter provides a space/speed tradeoff for sets holding many elements. +/// +/// When SparseT is uint32_t, find() only touches up to 3 cache lines, but the +/// sparse array uses 4 x Universe bytes. +/// +/// When SparseT is uint8_t (the default), find() touches up to 3+[N/256] cache +/// lines, but the sparse array is 4x smaller. N is the number of elements in +/// the set. +/// +/// For sets that may grow to thousands of elements, SparseT should be set to +/// uint16_t or uint32_t. +/// +/// Multiset behavior is provided by providing doubly linked lists for values +/// that are inlined in the dense vector. SparseMultiSet is a good choice when +/// one desires a growable number of entries per key, as it will retain the +/// SparseSet algorithmic properties despite being growable. Thus, it is often a +/// better choice than a SparseSet of growable containers or a vector of +/// vectors. SparseMultiSet also keeps iterators valid after erasure (provided +/// the iterators don't point to the element erased), allowing for more +/// intuitive and fast removal. +/// +/// @tparam ValueT The type of objects in the set. +/// @tparam KeyFunctorT A functor that computes an unsigned index from KeyT. +/// @tparam SparseT An unsigned integer type. See above. +/// +template<typename ValueT, + typename KeyFunctorT = identity<unsigned>, + typename SparseT = uint8_t> +class SparseMultiSet { + static_assert(std::numeric_limits<SparseT>::is_integer && + !std::numeric_limits<SparseT>::is_signed, + "SparseT must be an unsigned integer type"); + + /// The actual data that's stored, as a doubly-linked list implemented via + /// indices into the DenseVector. The doubly linked list is implemented + /// circular in Prev indices, and INVALID-terminated in Next indices. This + /// provides efficient access to list tails. These nodes can also be + /// tombstones, in which case they are actually nodes in a single-linked + /// freelist of recyclable slots. + struct SMSNode { + static const unsigned INVALID = ~0U; + + ValueT Data; + unsigned Prev; + unsigned Next; + + SMSNode(ValueT D, unsigned P, unsigned N) : Data(D), Prev(P), Next(N) {} + + /// List tails have invalid Nexts. + bool isTail() const { + return Next == INVALID; + } + + /// Whether this node is a tombstone node, and thus is in our freelist. + bool isTombstone() const { + return Prev == INVALID; + } + + /// Since the list is circular in Prev, all non-tombstone nodes have a valid + /// Prev. + bool isValid() const { return Prev != INVALID; } + }; + + using KeyT = typename KeyFunctorT::argument_type; + using DenseT = SmallVector<SMSNode, 8>; + DenseT Dense; + SparseT *Sparse = nullptr; + unsigned Universe = 0; + KeyFunctorT KeyIndexOf; + SparseSetValFunctor<KeyT, ValueT, KeyFunctorT> ValIndexOf; + + /// We have a built-in recycler for reusing tombstone slots. This recycler + /// puts a singly-linked free list into tombstone slots, allowing us quick + /// erasure, iterator preservation, and dense size. + unsigned FreelistIdx = SMSNode::INVALID; + unsigned NumFree = 0; + + unsigned sparseIndex(const ValueT &Val) const { + assert(ValIndexOf(Val) < Universe && + "Invalid key in set. Did object mutate?"); + return ValIndexOf(Val); + } + unsigned sparseIndex(const SMSNode &N) const { return sparseIndex(N.Data); } + + /// Whether the given entry is the head of the list. List heads's previous + /// pointers are to the tail of the list, allowing for efficient access to the + /// list tail. D must be a valid entry node. + bool isHead(const SMSNode &D) const { + assert(D.isValid() && "Invalid node for head"); + return Dense[D.Prev].isTail(); + } + + /// Whether the given entry is a singleton entry, i.e. the only entry with + /// that key. + bool isSingleton(const SMSNode &N) const { + assert(N.isValid() && "Invalid node for singleton"); + // Is N its own predecessor? + return &Dense[N.Prev] == &N; + } + + /// Add in the given SMSNode. Uses a free entry in our freelist if + /// available. Returns the index of the added node. + unsigned addValue(const ValueT& V, unsigned Prev, unsigned Next) { + if (NumFree == 0) { + Dense.push_back(SMSNode(V, Prev, Next)); + return Dense.size() - 1; + } + + // Peel off a free slot + unsigned Idx = FreelistIdx; + unsigned NextFree = Dense[Idx].Next; + assert(Dense[Idx].isTombstone() && "Non-tombstone free?"); + + Dense[Idx] = SMSNode(V, Prev, Next); + FreelistIdx = NextFree; + --NumFree; + return Idx; + } + + /// Make the current index a new tombstone. Pushes it onto the freelist. + void makeTombstone(unsigned Idx) { + Dense[Idx].Prev = SMSNode::INVALID; + Dense[Idx].Next = FreelistIdx; + FreelistIdx = Idx; + ++NumFree; + } + +public: + using value_type = ValueT; + using reference = ValueT &; + using const_reference = const ValueT &; + using pointer = ValueT *; + using const_pointer = const ValueT *; + using size_type = unsigned; + + SparseMultiSet() = default; + SparseMultiSet(const SparseMultiSet &) = delete; + SparseMultiSet &operator=(const SparseMultiSet &) = delete; + ~SparseMultiSet() { free(Sparse); } + + /// Set the universe size which determines the largest key the set can hold. + /// The universe must be sized before any elements can be added. + /// + /// @param U Universe size. All object keys must be less than U. + /// + void setUniverse(unsigned U) { + // It's not hard to resize the universe on a non-empty set, but it doesn't + // seem like a likely use case, so we can add that code when we need it. + assert(empty() && "Can only resize universe on an empty map"); + // Hysteresis prevents needless reallocations. + if (U >= Universe/4 && U <= Universe) + return; + free(Sparse); + // The Sparse array doesn't actually need to be initialized, so malloc + // would be enough here, but that will cause tools like valgrind to + // complain about branching on uninitialized data. + Sparse = static_cast<SparseT*>(safe_calloc(U, sizeof(SparseT))); + Universe = U; + } + + /// Our iterators are iterators over the collection of objects that share a + /// key. + template<typename SMSPtrTy> + class iterator_base : public std::iterator<std::bidirectional_iterator_tag, + ValueT> { + friend class SparseMultiSet; + + SMSPtrTy SMS; + unsigned Idx; + unsigned SparseIdx; + + iterator_base(SMSPtrTy P, unsigned I, unsigned SI) + : SMS(P), Idx(I), SparseIdx(SI) {} + + /// Whether our iterator has fallen outside our dense vector. + bool isEnd() const { + if (Idx == SMSNode::INVALID) + return true; + + assert(Idx < SMS->Dense.size() && "Out of range, non-INVALID Idx?"); + return false; + } + + /// Whether our iterator is properly keyed, i.e. the SparseIdx is valid + bool isKeyed() const { return SparseIdx < SMS->Universe; } + + unsigned Prev() const { return SMS->Dense[Idx].Prev; } + unsigned Next() const { return SMS->Dense[Idx].Next; } + + void setPrev(unsigned P) { SMS->Dense[Idx].Prev = P; } + void setNext(unsigned N) { SMS->Dense[Idx].Next = N; } + + public: + using super = std::iterator<std::bidirectional_iterator_tag, ValueT>; + using value_type = typename super::value_type; + using difference_type = typename super::difference_type; + using pointer = typename super::pointer; + using reference = typename super::reference; + + reference operator*() const { + assert(isKeyed() && SMS->sparseIndex(SMS->Dense[Idx].Data) == SparseIdx && + "Dereferencing iterator of invalid key or index"); + + return SMS->Dense[Idx].Data; + } + pointer operator->() const { return &operator*(); } + + /// Comparison operators + bool operator==(const iterator_base &RHS) const { + // end compares equal + if (SMS == RHS.SMS && Idx == RHS.Idx) { + assert((isEnd() || SparseIdx == RHS.SparseIdx) && + "Same dense entry, but different keys?"); + return true; + } + + return false; + } + + bool operator!=(const iterator_base &RHS) const { + return !operator==(RHS); + } + + /// Increment and decrement operators + iterator_base &operator--() { // predecrement - Back up + assert(isKeyed() && "Decrementing an invalid iterator"); + assert((isEnd() || !SMS->isHead(SMS->Dense[Idx])) && + "Decrementing head of list"); + + // If we're at the end, then issue a new find() + if (isEnd()) + Idx = SMS->findIndex(SparseIdx).Prev(); + else + Idx = Prev(); + + return *this; + } + iterator_base &operator++() { // preincrement - Advance + assert(!isEnd() && isKeyed() && "Incrementing an invalid/end iterator"); + Idx = Next(); + return *this; + } + iterator_base operator--(int) { // postdecrement + iterator_base I(*this); + --*this; + return I; + } + iterator_base operator++(int) { // postincrement + iterator_base I(*this); + ++*this; + return I; + } + }; + + using iterator = iterator_base<SparseMultiSet *>; + using const_iterator = iterator_base<const SparseMultiSet *>; + + // Convenience types + using RangePair = std::pair<iterator, iterator>; + + /// Returns an iterator past this container. Note that such an iterator cannot + /// be decremented, but will compare equal to other end iterators. + iterator end() { return iterator(this, SMSNode::INVALID, SMSNode::INVALID); } + const_iterator end() const { + return const_iterator(this, SMSNode::INVALID, SMSNode::INVALID); + } + + /// Returns true if the set is empty. + /// + /// This is not the same as BitVector::empty(). + /// + bool empty() const { return size() == 0; } + + /// Returns the number of elements in the set. + /// + /// This is not the same as BitVector::size() which returns the size of the + /// universe. + /// + size_type size() const { + assert(NumFree <= Dense.size() && "Out-of-bounds free entries"); + return Dense.size() - NumFree; + } + + /// Clears the set. This is a very fast constant time operation. + /// + void clear() { + // Sparse does not need to be cleared, see find(). + Dense.clear(); + NumFree = 0; + FreelistIdx = SMSNode::INVALID; + } + + /// Find an element by its index. + /// + /// @param Idx A valid index to find. + /// @returns An iterator to the element identified by key, or end(). + /// + iterator findIndex(unsigned Idx) { + assert(Idx < Universe && "Key out of range"); + const unsigned Stride = std::numeric_limits<SparseT>::max() + 1u; + for (unsigned i = Sparse[Idx], e = Dense.size(); i < e; i += Stride) { + const unsigned FoundIdx = sparseIndex(Dense[i]); + // Check that we're pointing at the correct entry and that it is the head + // of a valid list. + if (Idx == FoundIdx && Dense[i].isValid() && isHead(Dense[i])) + return iterator(this, i, Idx); + // Stride is 0 when SparseT >= unsigned. We don't need to loop. + if (!Stride) + break; + } + return end(); + } + + /// Find an element by its key. + /// + /// @param Key A valid key to find. + /// @returns An iterator to the element identified by key, or end(). + /// + iterator find(const KeyT &Key) { + return findIndex(KeyIndexOf(Key)); + } + + const_iterator find(const KeyT &Key) const { + iterator I = const_cast<SparseMultiSet*>(this)->findIndex(KeyIndexOf(Key)); + return const_iterator(I.SMS, I.Idx, KeyIndexOf(Key)); + } + + /// Returns the number of elements identified by Key. This will be linear in + /// the number of elements of that key. + size_type count(const KeyT &Key) const { + unsigned Ret = 0; + for (const_iterator It = find(Key); It != end(); ++It) + ++Ret; + + return Ret; + } + + /// Returns true if this set contains an element identified by Key. + bool contains(const KeyT &Key) const { + return find(Key) != end(); + } + + /// Return the head and tail of the subset's list, otherwise returns end(). + iterator getHead(const KeyT &Key) { return find(Key); } + iterator getTail(const KeyT &Key) { + iterator I = find(Key); + if (I != end()) + I = iterator(this, I.Prev(), KeyIndexOf(Key)); + return I; + } + + /// The bounds of the range of items sharing Key K. First member is the head + /// of the list, and the second member is a decrementable end iterator for + /// that key. + RangePair equal_range(const KeyT &K) { + iterator B = find(K); + iterator E = iterator(this, SMSNode::INVALID, B.SparseIdx); + return make_pair(B, E); + } + + /// Insert a new element at the tail of the subset list. Returns an iterator + /// to the newly added entry. + iterator insert(const ValueT &Val) { + unsigned Idx = sparseIndex(Val); + iterator I = findIndex(Idx); + + unsigned NodeIdx = addValue(Val, SMSNode::INVALID, SMSNode::INVALID); + + if (I == end()) { + // Make a singleton list + Sparse[Idx] = NodeIdx; + Dense[NodeIdx].Prev = NodeIdx; + return iterator(this, NodeIdx, Idx); + } + + // Stick it at the end. + unsigned HeadIdx = I.Idx; + unsigned TailIdx = I.Prev(); + Dense[TailIdx].Next = NodeIdx; + Dense[HeadIdx].Prev = NodeIdx; + Dense[NodeIdx].Prev = TailIdx; + + return iterator(this, NodeIdx, Idx); + } + + /// Erases an existing element identified by a valid iterator. + /// + /// This invalidates iterators pointing at the same entry, but erase() returns + /// an iterator pointing to the next element in the subset's list. This makes + /// it possible to erase selected elements while iterating over the subset: + /// + /// tie(I, E) = Set.equal_range(Key); + /// while (I != E) + /// if (test(*I)) + /// I = Set.erase(I); + /// else + /// ++I; + /// + /// Note that if the last element in the subset list is erased, this will + /// return an end iterator which can be decremented to get the new tail (if it + /// exists): + /// + /// tie(B, I) = Set.equal_range(Key); + /// for (bool isBegin = B == I; !isBegin; /* empty */) { + /// isBegin = (--I) == B; + /// if (test(I)) + /// break; + /// I = erase(I); + /// } + iterator erase(iterator I) { + assert(I.isKeyed() && !I.isEnd() && !Dense[I.Idx].isTombstone() && + "erasing invalid/end/tombstone iterator"); + + // First, unlink the node from its list. Then swap the node out with the + // dense vector's last entry + iterator NextI = unlink(Dense[I.Idx]); + + // Put in a tombstone. + makeTombstone(I.Idx); + + return NextI; + } + + /// Erase all elements with the given key. This invalidates all + /// iterators of that key. + void eraseAll(const KeyT &K) { + for (iterator I = find(K); I != end(); /* empty */) + I = erase(I); + } + +private: + /// Unlink the node from its list. Returns the next node in the list. + iterator unlink(const SMSNode &N) { + if (isSingleton(N)) { + // Singleton is already unlinked + assert(N.Next == SMSNode::INVALID && "Singleton has next?"); + return iterator(this, SMSNode::INVALID, ValIndexOf(N.Data)); + } + + if (isHead(N)) { + // If we're the head, then update the sparse array and our next. + Sparse[sparseIndex(N)] = N.Next; + Dense[N.Next].Prev = N.Prev; + return iterator(this, N.Next, ValIndexOf(N.Data)); + } + + if (N.isTail()) { + // If we're the tail, then update our head and our previous. + findIndex(sparseIndex(N)).setPrev(N.Prev); + Dense[N.Prev].Next = N.Next; + + // Give back an end iterator that can be decremented + iterator I(this, N.Prev, ValIndexOf(N.Data)); + return ++I; + } + + // Otherwise, just drop us + Dense[N.Next].Prev = N.Prev; + Dense[N.Prev].Next = N.Next; + return iterator(this, N.Next, ValIndexOf(N.Data)); + } +}; + +} // end namespace llvm + +#endif // LLVM_ADT_SPARSEMULTISET_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/SparseSet.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/SparseSet.h new file mode 100644 index 0000000..a6eb9b9 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/SparseSet.h
@@ -0,0 +1,315 @@ +//===- llvm/ADT/SparseSet.h - Sparse set ------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the SparseSet class derived from the version described in +// Briggs, Torczon, "An efficient representation for sparse sets", ACM Letters +// on Programming Languages and Systems, Volume 2 Issue 1-4, March-Dec. 1993. +// +// A sparse set holds a small number of objects identified by integer keys from +// a moderately sized universe. The sparse set uses more memory than other +// containers in order to provide faster operations. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SPARSESET_H +#define LLVM_ADT_SPARSESET_H + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Allocator.h" +#include <cassert> +#include <cstdint> +#include <cstdlib> +#include <limits> +#include <utility> + +namespace llvm { + +/// SparseSetValTraits - Objects in a SparseSet are identified by keys that can +/// be uniquely converted to a small integer less than the set's universe. This +/// class allows the set to hold values that differ from the set's key type as +/// long as an index can still be derived from the value. SparseSet never +/// directly compares ValueT, only their indices, so it can map keys to +/// arbitrary values. SparseSetValTraits computes the index from the value +/// object. To compute the index from a key, SparseSet uses a separate +/// KeyFunctorT template argument. +/// +/// A simple type declaration, SparseSet<Type>, handles these cases: +/// - unsigned key, identity index, identity value +/// - unsigned key, identity index, fat value providing getSparseSetIndex() +/// +/// The type declaration SparseSet<Type, UnaryFunction> handles: +/// - unsigned key, remapped index, identity value (virtual registers) +/// - pointer key, pointer-derived index, identity value (node+ID) +/// - pointer key, pointer-derived index, fat value with getSparseSetIndex() +/// +/// Only other, unexpected cases require specializing SparseSetValTraits. +/// +/// For best results, ValueT should not require a destructor. +/// +template<typename ValueT> +struct SparseSetValTraits { + static unsigned getValIndex(const ValueT &Val) { + return Val.getSparseSetIndex(); + } +}; + +/// SparseSetValFunctor - Helper class for selecting SparseSetValTraits. The +/// generic implementation handles ValueT classes which either provide +/// getSparseSetIndex() or specialize SparseSetValTraits<>. +/// +template<typename KeyT, typename ValueT, typename KeyFunctorT> +struct SparseSetValFunctor { + unsigned operator()(const ValueT &Val) const { + return SparseSetValTraits<ValueT>::getValIndex(Val); + } +}; + +/// SparseSetValFunctor<KeyT, KeyT> - Helper class for the common case of +/// identity key/value sets. +template<typename KeyT, typename KeyFunctorT> +struct SparseSetValFunctor<KeyT, KeyT, KeyFunctorT> { + unsigned operator()(const KeyT &Key) const { + return KeyFunctorT()(Key); + } +}; + +/// SparseSet - Fast set implmentation for objects that can be identified by +/// small unsigned keys. +/// +/// SparseSet allocates memory proportional to the size of the key universe, so +/// it is not recommended for building composite data structures. It is useful +/// for algorithms that require a single set with fast operations. +/// +/// Compared to DenseSet and DenseMap, SparseSet provides constant-time fast +/// clear() and iteration as fast as a vector. The find(), insert(), and +/// erase() operations are all constant time, and typically faster than a hash +/// table. The iteration order doesn't depend on numerical key values, it only +/// depends on the order of insert() and erase() operations. When no elements +/// have been erased, the iteration order is the insertion order. +/// +/// Compared to BitVector, SparseSet<unsigned> uses 8x-40x more memory, but +/// offers constant-time clear() and size() operations as well as fast +/// iteration independent on the size of the universe. +/// +/// SparseSet contains a dense vector holding all the objects and a sparse +/// array holding indexes into the dense vector. Most of the memory is used by +/// the sparse array which is the size of the key universe. The SparseT +/// template parameter provides a space/speed tradeoff for sets holding many +/// elements. +/// +/// When SparseT is uint32_t, find() only touches 2 cache lines, but the sparse +/// array uses 4 x Universe bytes. +/// +/// When SparseT is uint8_t (the default), find() touches up to 2+[N/256] cache +/// lines, but the sparse array is 4x smaller. N is the number of elements in +/// the set. +/// +/// For sets that may grow to thousands of elements, SparseT should be set to +/// uint16_t or uint32_t. +/// +/// @tparam ValueT The type of objects in the set. +/// @tparam KeyFunctorT A functor that computes an unsigned index from KeyT. +/// @tparam SparseT An unsigned integer type. See above. +/// +template<typename ValueT, + typename KeyFunctorT = identity<unsigned>, + typename SparseT = uint8_t> +class SparseSet { + static_assert(std::numeric_limits<SparseT>::is_integer && + !std::numeric_limits<SparseT>::is_signed, + "SparseT must be an unsigned integer type"); + + using KeyT = typename KeyFunctorT::argument_type; + using DenseT = SmallVector<ValueT, 8>; + using size_type = unsigned; + DenseT Dense; + SparseT *Sparse = nullptr; + unsigned Universe = 0; + KeyFunctorT KeyIndexOf; + SparseSetValFunctor<KeyT, ValueT, KeyFunctorT> ValIndexOf; + +public: + using value_type = ValueT; + using reference = ValueT &; + using const_reference = const ValueT &; + using pointer = ValueT *; + using const_pointer = const ValueT *; + + SparseSet() = default; + SparseSet(const SparseSet &) = delete; + SparseSet &operator=(const SparseSet &) = delete; + ~SparseSet() { free(Sparse); } + + /// setUniverse - Set the universe size which determines the largest key the + /// set can hold. The universe must be sized before any elements can be + /// added. + /// + /// @param U Universe size. All object keys must be less than U. + /// + void setUniverse(unsigned U) { + // It's not hard to resize the universe on a non-empty set, but it doesn't + // seem like a likely use case, so we can add that code when we need it. + assert(empty() && "Can only resize universe on an empty map"); + // Hysteresis prevents needless reallocations. + if (U >= Universe/4 && U <= Universe) + return; + free(Sparse); + // The Sparse array doesn't actually need to be initialized, so malloc + // would be enough here, but that will cause tools like valgrind to + // complain about branching on uninitialized data. + Sparse = static_cast<SparseT*>(safe_calloc(U, sizeof(SparseT))); + Universe = U; + } + + // Import trivial vector stuff from DenseT. + using iterator = typename DenseT::iterator; + using const_iterator = typename DenseT::const_iterator; + + const_iterator begin() const { return Dense.begin(); } + const_iterator end() const { return Dense.end(); } + iterator begin() { return Dense.begin(); } + iterator end() { return Dense.end(); } + + /// empty - Returns true if the set is empty. + /// + /// This is not the same as BitVector::empty(). + /// + bool empty() const { return Dense.empty(); } + + /// size - Returns the number of elements in the set. + /// + /// This is not the same as BitVector::size() which returns the size of the + /// universe. + /// + size_type size() const { return Dense.size(); } + + /// clear - Clears the set. This is a very fast constant time operation. + /// + void clear() { + // Sparse does not need to be cleared, see find(). + Dense.clear(); + } + + /// findIndex - Find an element by its index. + /// + /// @param Idx A valid index to find. + /// @returns An iterator to the element identified by key, or end(). + /// + iterator findIndex(unsigned Idx) { + assert(Idx < Universe && "Key out of range"); + const unsigned Stride = std::numeric_limits<SparseT>::max() + 1u; + for (unsigned i = Sparse[Idx], e = size(); i < e; i += Stride) { + const unsigned FoundIdx = ValIndexOf(Dense[i]); + assert(FoundIdx < Universe && "Invalid key in set. Did object mutate?"); + if (Idx == FoundIdx) + return begin() + i; + // Stride is 0 when SparseT >= unsigned. We don't need to loop. + if (!Stride) + break; + } + return end(); + } + + /// find - Find an element by its key. + /// + /// @param Key A valid key to find. + /// @returns An iterator to the element identified by key, or end(). + /// + iterator find(const KeyT &Key) { + return findIndex(KeyIndexOf(Key)); + } + + const_iterator find(const KeyT &Key) const { + return const_cast<SparseSet*>(this)->findIndex(KeyIndexOf(Key)); + } + + /// count - Returns 1 if this set contains an element identified by Key, + /// 0 otherwise. + /// + size_type count(const KeyT &Key) const { + return find(Key) == end() ? 0 : 1; + } + + /// insert - Attempts to insert a new element. + /// + /// If Val is successfully inserted, return (I, true), where I is an iterator + /// pointing to the newly inserted element. + /// + /// If the set already contains an element with the same key as Val, return + /// (I, false), where I is an iterator pointing to the existing element. + /// + /// Insertion invalidates all iterators. + /// + std::pair<iterator, bool> insert(const ValueT &Val) { + unsigned Idx = ValIndexOf(Val); + iterator I = findIndex(Idx); + if (I != end()) + return std::make_pair(I, false); + Sparse[Idx] = size(); + Dense.push_back(Val); + return std::make_pair(end() - 1, true); + } + + /// array subscript - If an element already exists with this key, return it. + /// Otherwise, automatically construct a new value from Key, insert it, + /// and return the newly inserted element. + ValueT &operator[](const KeyT &Key) { + 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 + /// to the next element. This makes it possible to erase selected elements + /// while iterating over the set: + /// + /// for (SparseSet::iterator I = Set.begin(); I != Set.end();) + /// if (test(*I)) + /// I = Set.erase(I); + /// else + /// ++I; + /// + /// Note that end() changes when elements are erased, unlike std::list. + /// + iterator erase(iterator I) { + assert(unsigned(I - begin()) < size() && "Invalid iterator"); + if (I != end() - 1) { + *I = Dense.back(); + unsigned BackIdx = ValIndexOf(Dense.back()); + assert(BackIdx < Universe && "Invalid key in set. Did object mutate?"); + Sparse[BackIdx] = I - begin(); + } + // This depends on SmallVector::pop_back() not invalidating iterators. + // std::vector::pop_back() doesn't give that guarantee. + Dense.pop_back(); + return I; + } + + /// erase - Erases an element identified by Key, if it exists. + /// + /// @param Key The key identifying the element to erase. + /// @returns True when an element was erased, false if no element was found. + /// + bool erase(const KeyT &Key) { + iterator I = find(Key); + if (I == end()) + return false; + erase(I); + return true; + } +}; + +} // end namespace llvm + +#endif // LLVM_ADT_SPARSESET_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/Statistic.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/Statistic.h new file mode 100644 index 0000000..d7aff6c --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/Statistic.h
@@ -0,0 +1,222 @@ +//===-- llvm/ADT/Statistic.h - Easy way to expose stats ---------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the 'Statistic' class, which is designed to be an easy way +// to expose various metrics from passes. These statistics are printed at the +// end of a run (from llvm_shutdown), when the -stats command line option is +// passed on the command line. +// +// This is useful for reporting information like the number of instructions +// simplified, optimized or removed by various transformations, like this: +// +// static Statistic NumInstsKilled("gcse", "Number of instructions killed"); +// +// Later, in the code: ++NumInstsKilled; +// +// NOTE: Statistics *must* be declared as global variables. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STATISTIC_H +#define LLVM_ADT_STATISTIC_H + +#include "llvm/Config/llvm-config.h" +#include "llvm/Support/Compiler.h" +#include <atomic> +#include <memory> +#include <vector> + +// Determine whether statistics should be enabled. We must do it here rather +// than in CMake because multi-config generators cannot determine this at +// configure time. +#if !defined(NDEBUG) || LLVM_FORCE_ENABLE_STATS +#define LLVM_ENABLE_STATS 1 +#endif + +namespace llvm { + +class raw_ostream; +class raw_fd_ostream; +class StringRef; + +class StatisticBase { +public: + const char *DebugType; + const char *Name; + const char *Desc; + + StatisticBase(const char *DebugType, const char *Name, const char *Desc) + : DebugType(DebugType), Name(Name), Desc(Desc) {} + + const char *getDebugType() const { return DebugType; } + const char *getName() const { return Name; } + const char *getDesc() const { return Desc; } +}; + +class TrackingStatistic : public StatisticBase { +public: + std::atomic<unsigned> Value; + std::atomic<bool> Initialized; + + TrackingStatistic(const char *DebugType, const char *Name, const char *Desc) + : StatisticBase(DebugType, Name, Desc), Value(0), Initialized(false) {} + + unsigned getValue() const { return Value.load(std::memory_order_relaxed); } + + // Allow use of this class as the value itself. + operator unsigned() const { return getValue(); } + + const TrackingStatistic &operator=(unsigned Val) { + Value.store(Val, std::memory_order_relaxed); + return init(); + } + + const TrackingStatistic &operator++() { + Value.fetch_add(1, std::memory_order_relaxed); + return init(); + } + + unsigned operator++(int) { + init(); + return Value.fetch_add(1, std::memory_order_relaxed); + } + + const TrackingStatistic &operator--() { + Value.fetch_sub(1, std::memory_order_relaxed); + return init(); + } + + unsigned operator--(int) { + init(); + return Value.fetch_sub(1, std::memory_order_relaxed); + } + + const TrackingStatistic &operator+=(unsigned V) { + if (V == 0) + return *this; + Value.fetch_add(V, std::memory_order_relaxed); + return init(); + } + + const TrackingStatistic &operator-=(unsigned V) { + if (V == 0) + return *this; + Value.fetch_sub(V, std::memory_order_relaxed); + return init(); + } + + void updateMax(unsigned V) { + unsigned PrevMax = Value.load(std::memory_order_relaxed); + // Keep trying to update max until we succeed or another thread produces + // a bigger max than us. + while (V > PrevMax && !Value.compare_exchange_weak( + PrevMax, V, std::memory_order_relaxed)) { + } + init(); + } + +protected: + TrackingStatistic &init() { + if (!Initialized.load(std::memory_order_acquire)) + RegisterStatistic(); + return *this; + } + + void RegisterStatistic(); +}; + +class NoopStatistic : public StatisticBase { +public: + using StatisticBase::StatisticBase; + + unsigned getValue() const { return 0; } + + // Allow use of this class as the value itself. + operator unsigned() const { return 0; } + + const NoopStatistic &operator=(unsigned Val) { return *this; } + + const NoopStatistic &operator++() { return *this; } + + unsigned operator++(int) { return 0; } + + const NoopStatistic &operator--() { return *this; } + + unsigned operator--(int) { return 0; } + + const NoopStatistic &operator+=(const unsigned &V) { return *this; } + + const NoopStatistic &operator-=(const unsigned &V) { return *this; } + + void updateMax(unsigned V) {} +}; + +#if LLVM_ENABLE_STATS +using Statistic = TrackingStatistic; +#else +using Statistic = NoopStatistic; +#endif + +// 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, #VARNAME, DESC} + +// ALWAYS_ENABLED_STATISTIC - A macro to define a statistic like STATISTIC but +// it is enabled even if LLVM_ENABLE_STATS is off. +#define ALWAYS_ENABLED_STATISTIC(VARNAME, DESC) \ + static llvm::TrackingStatistic VARNAME = {DEBUG_TYPE, #VARNAME, DESC} + +/// Enable the collection and printing of statistics. +void EnableStatistics(bool DoPrintOnExit = true); + +/// Check if statistics are enabled. +bool AreStatisticsEnabled(); + +/// Return a file stream to print our output on. +std::unique_ptr<raw_fd_ostream> CreateInfoOutputFile(); + +/// Print statistics to the file returned by CreateInfoOutputFile(). +void PrintStatistics(); + +/// Print statistics to the given output stream. +void PrintStatistics(raw_ostream &OS); + +/// Print statistics in JSON format. This does include all global timers (\see +/// Timer, TimerGroup). Note that the timers are cleared after printing and will +/// not be printed in human readable form or in a second call of +/// PrintStatisticsJSON(). +void PrintStatisticsJSON(raw_ostream &OS); + +/// Get the statistics. This can be used to look up the value of +/// statistics without needing to parse JSON. +/// +/// This function does not prevent statistics being updated by other threads +/// during it's execution. It will return the value at the point that it is +/// read. However, it will prevent new statistics from registering until it +/// completes. +const std::vector<std::pair<StringRef, unsigned>> GetStatistics(); + +/// Reset the statistics. This can be used to zero and de-register the +/// statistics in order to measure a compilation. +/// +/// When this function begins to call destructors prior to returning, all +/// statistics will be zero and unregistered. However, that might not remain the +/// case by the time this function finishes returning. Whether update from other +/// threads are lost or merely deferred until during the function return is +/// timing sensitive. +/// +/// Callers who intend to use this to measure statistics for a single +/// compilation should ensure that no compilations are in progress at the point +/// this function is called and that only one compilation executes until calling +/// GetStatistics(). +void ResetStatistics(); + +} // end namespace llvm + +#endif // LLVM_ADT_STATISTIC_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/StringExtras.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/StringExtras.h new file mode 100644 index 0000000..ef1a11e --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/StringExtras.h
@@ -0,0 +1,401 @@ +//===- llvm/ADT/StringExtras.h - Useful string functions --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains some functions that are useful when dealing with strings. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STRINGEXTRAS_H +#define LLVM_ADT_STRINGEXTRAS_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <cstring> +#include <iterator> +#include <string> +#include <utility> + +namespace llvm { + +template<typename T> class SmallVectorImpl; +class raw_ostream; + +/// hexdigit - Return the hexadecimal character for the +/// given number \p X (which should be less than 16). +inline char hexdigit(unsigned X, bool LowerCase = false) { + const char HexChar = LowerCase ? 'a' : 'A'; + return X < 10 ? '0' + X : HexChar + X - 10; +} + +/// Given an array of c-style strings terminated by a null pointer, construct +/// a vector of StringRefs representing the same strings without the terminating +/// null string. +inline std::vector<StringRef> toStringRefArray(const char *const *Strings) { + std::vector<StringRef> Result; + while (*Strings) + Result.push_back(*Strings++); + return Result; +} + +/// Construct a string ref from a boolean. +inline StringRef toStringRef(bool B) { return StringRef(B ? "true" : "false"); } + +/// Construct a string ref from an array ref of unsigned chars. +inline StringRef toStringRef(ArrayRef<uint8_t> Input) { + return StringRef(reinterpret_cast<const char *>(Input.begin()), Input.size()); +} + +/// Construct a string ref from an array ref of unsigned chars. +inline ArrayRef<uint8_t> arrayRefFromStringRef(StringRef Input) { + return {Input.bytes_begin(), Input.bytes_end()}; +} + +/// Interpret the given character \p C as a hexadecimal digit and return its +/// value. +/// +/// If \p C is not a valid hex digit, -1U is returned. +inline unsigned hexDigitValue(char C) { + if (C >= '0' && C <= '9') return C-'0'; + if (C >= 'a' && C <= 'f') return C-'a'+10U; + if (C >= 'A' && C <= 'F') return C-'A'+10U; + return -1U; +} + +/// Checks if character \p C is one of the 10 decimal digits. +inline bool isDigit(char C) { return C >= '0' && C <= '9'; } + +/// Checks if character \p C is a hexadecimal numeric character. +inline bool isHexDigit(char C) { return hexDigitValue(C) != -1U; } + +/// Checks if character \p C is a valid letter as classified by "C" locale. +inline bool isAlpha(char C) { + return ('a' <= C && C <= 'z') || ('A' <= C && C <= 'Z'); +} + +/// Checks whether character \p C is either a decimal digit or an uppercase or +/// lowercase letter as classified by "C" locale. +inline bool isAlnum(char C) { return isAlpha(C) || isDigit(C); } + +/// Checks whether character \p C is valid ASCII (high bit is zero). +inline bool isASCII(char C) { return static_cast<unsigned char>(C) <= 127; } + +/// Checks whether all characters in S are ASCII. +inline bool isASCII(llvm::StringRef S) { + for (char C : S) + if (LLVM_UNLIKELY(!isASCII(C))) + return false; + return true; +} + +/// Checks whether character \p C is printable. +/// +/// Locale-independent version of the C standard library isprint whose results +/// may differ on different platforms. +inline bool isPrint(char C) { + unsigned char UC = static_cast<unsigned char>(C); + return (0x20 <= UC) && (UC <= 0x7E); +} + +/// Returns the corresponding lowercase character if \p x is uppercase. +inline char toLower(char x) { + if (x >= 'A' && x <= 'Z') + return x - 'A' + 'a'; + return x; +} + +/// Returns the corresponding uppercase character if \p x is lowercase. +inline char toUpper(char x) { + if (x >= 'a' && x <= 'z') + return x - 'a' + 'A'; + return x; +} + +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 std::string(BufPtr, std::end(Buffer)); +} + +/// Convert buffer \p Input to its hexadecimal representation. +/// The returned string is double the size of \p Input. +inline std::string toHex(StringRef Input, bool LowerCase = false) { + static const char *const LUT = "0123456789ABCDEF"; + const uint8_t Offset = LowerCase ? 32 : 0; + size_t Length = Input.size(); + + 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] | Offset); + Output.push_back(LUT[c & 15] | Offset); + } + return Output; +} + +inline std::string toHex(ArrayRef<uint8_t> Input, bool LowerCase = false) { + return toHex(toStringRef(Input), LowerCase); +} + +inline uint8_t hexFromNibbles(char MSB, char LSB) { + unsigned U1 = hexDigitValue(MSB); + unsigned U2 = hexDigitValue(LSB); + assert(U1 != -1U && U2 != -1U); + + return static_cast<uint8_t>((U1 << 4) | U2); +} + +/// Convert hexadecimal string \p Input to its binary representation. +/// The return string is half the size of \p Input. +inline std::string fromHex(StringRef Input) { + if (Input.empty()) + return std::string(); + + std::string Output; + Output.reserve((Input.size() + 1) / 2); + if (Input.size() % 2 == 1) { + Output.push_back(hexFromNibbles('0', Input.front())); + Input = Input.drop_front(); + } + + assert(Input.size() % 2 == 0); + while (!Input.empty()) { + uint8_t Hex = hexFromNibbles(Input[0], Input[1]); + Output.push_back(Hex); + Input = Input.drop_front(2); + } + return Output; +} + +/// Convert the string \p S to an integer of the specified type using +/// the radix \p Base. If \p Base is 0, auto-detects the radix. +/// Returns true if the number was successfully converted, false otherwise. +template <typename N> bool to_integer(StringRef S, N &Num, unsigned Base = 0) { + return !S.getAsInteger(Base, Num); +} + +namespace detail { +template <typename N> +inline bool to_float(const Twine &T, N &Num, N (*StrTo)(const char *, char **)) { + SmallString<32> Storage; + StringRef S = T.toNullTerminatedStringRef(Storage); + char *End; + N Temp = StrTo(S.data(), &End); + if (*End != '\0') + return false; + Num = Temp; + return true; +} +} + +inline bool to_float(const Twine &T, float &Num) { + return detail::to_float(T, Num, strtof); +} + +inline bool to_float(const Twine &T, double &Num) { + return detail::to_float(T, Num, strtod); +} + +inline bool to_float(const Twine &T, long double &Num) { + return detail::to_float(T, Num, strtold); +} + +inline std::string utostr(uint64_t X, bool isNeg = false) { + char Buffer[21]; + char *BufPtr = std::end(Buffer); + + if (X == 0) *--BufPtr = '0'; // Handle special case... + + while (X) { + *--BufPtr = '0' + char(X % 10); + X /= 10; + } + + if (isNeg) *--BufPtr = '-'; // Add negative sign... + return std::string(BufPtr, std::end(Buffer)); +} + +inline std::string itostr(int64_t X) { + if (X < 0) + return utostr(static_cast<uint64_t>(-X), true); + else + return utostr(static_cast<uint64_t>(X)); +} + +/// StrInStrNoCase - Portable version of strcasestr. Locates the first +/// occurrence of string 's1' in string 's2', ignoring case. Returns +/// the offset of s2 in s1 or npos if s2 cannot be found. +StringRef::size_type StrInStrNoCase(StringRef s1, StringRef s2); + +/// getToken - This function extracts one token from source, ignoring any +/// leading characters that appear in the Delimiters string, and ending the +/// token at any of the characters that appear in the Delimiters string. If +/// there are no tokens in the source string, an empty string is returned. +/// The function returns a pair containing the extracted token and the +/// remaining tail string. +std::pair<StringRef, StringRef> getToken(StringRef Source, + StringRef Delimiters = " \t\n\v\f\r"); + +/// SplitString - Split up the specified string according to the specified +/// delimiters, appending the result fragments to the output list. +void SplitString(StringRef Source, + SmallVectorImpl<StringRef> &OutFragments, + StringRef Delimiters = " \t\n\v\f\r"); + +/// Returns the English suffix for an ordinal integer (-st, -nd, -rd, -th). +inline StringRef getOrdinalSuffix(unsigned Val) { + // It is critically important that we do this perfectly for + // user-written sequences with over 100 elements. + switch (Val % 100) { + case 11: + case 12: + case 13: + return "th"; + default: + switch (Val % 10) { + case 1: return "st"; + case 2: return "nd"; + case 3: return "rd"; + default: return "th"; + } + } +} + +/// Print each character of the specified string, escaping it if it is not +/// printable or if it is an escape char. +void printEscapedString(StringRef Name, raw_ostream &Out); + +/// Print each character of the specified string, escaping HTML special +/// characters. +void printHTMLEscaped(StringRef String, raw_ostream &Out); + +/// printLowerCase - Print each character as lowercase if it is uppercase. +void printLowerCase(StringRef String, raw_ostream &Out); + +namespace detail { + +template <typename IteratorT> +inline std::string join_impl(IteratorT Begin, IteratorT End, + StringRef Separator, std::input_iterator_tag) { + std::string S; + if (Begin == End) + return S; + + S += (*Begin); + while (++Begin != End) { + S += Separator; + S += (*Begin); + } + return S; +} + +template <typename IteratorT> +inline std::string join_impl(IteratorT Begin, IteratorT End, + StringRef Separator, std::forward_iterator_tag) { + std::string S; + if (Begin == End) + return S; + + size_t Len = (std::distance(Begin, End) - 1) * Separator.size(); + for (IteratorT I = Begin; I != End; ++I) + Len += (*Begin).size(); + S.reserve(Len); + S += (*Begin); + while (++Begin != End) { + S += Separator; + S += (*Begin); + } + return S; +} + +template <typename Sep> +inline void join_items_impl(std::string &Result, Sep Separator) {} + +template <typename Sep, typename Arg> +inline void join_items_impl(std::string &Result, Sep Separator, + const Arg &Item) { + Result += Item; +} + +template <typename Sep, typename Arg1, typename... Args> +inline void join_items_impl(std::string &Result, Sep Separator, const Arg1 &A1, + Args &&... Items) { + Result += A1; + Result += Separator; + join_items_impl(Result, Separator, std::forward<Args>(Items)...); +} + +inline size_t join_one_item_size(char) { return 1; } +inline size_t join_one_item_size(const char *S) { return S ? ::strlen(S) : 0; } + +template <typename T> inline size_t join_one_item_size(const T &Str) { + return Str.size(); +} + +inline size_t join_items_size() { return 0; } + +template <typename A1> inline size_t join_items_size(const A1 &A) { + return join_one_item_size(A); +} +template <typename A1, typename... Args> +inline size_t join_items_size(const A1 &A, Args &&... Items) { + return join_one_item_size(A) + join_items_size(std::forward<Args>(Items)...); +} + +} // end namespace detail + +/// Joins the strings in the range [Begin, End), adding Separator between +/// the elements. +template <typename IteratorT> +inline std::string join(IteratorT Begin, IteratorT End, StringRef Separator) { + using tag = typename std::iterator_traits<IteratorT>::iterator_category; + return detail::join_impl(Begin, End, Separator, tag()); +} + +/// Joins the strings in the range [R.begin(), R.end()), adding Separator +/// between the elements. +template <typename Range> +inline std::string join(Range &&R, StringRef Separator) { + return join(R.begin(), R.end(), Separator); +} + +/// Joins the strings in the parameter pack \p Items, adding \p Separator +/// between the elements. All arguments must be implicitly convertible to +/// std::string, or there should be an overload of std::string::operator+=() +/// that accepts the argument explicitly. +template <typename Sep, typename... Args> +inline std::string join_items(Sep Separator, Args &&... Items) { + std::string Result; + if (sizeof...(Items) == 0) + return Result; + + size_t NS = detail::join_one_item_size(Separator); + size_t NI = detail::join_items_size(std::forward<Args>(Items)...); + Result.reserve(NI + (sizeof...(Items) - 1) * NS + 1); + detail::join_items_impl(Result, Separator, std::forward<Args>(Items)...); + return Result; +} + +} // end namespace llvm + +#endif // LLVM_ADT_STRINGEXTRAS_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/StringMap.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/StringMap.h new file mode 100644 index 0000000..108185b --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/StringMap.h
@@ -0,0 +1,593 @@ +//===- StringMap.h - String Hash table map interface ------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the StringMap class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STRINGMAP_H +#define LLVM_ADT_STRINGMAP_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/PointerLikeTypeTraits.h" +#include "llvm/Support/ErrorHandling.h" +#include <algorithm> +#include <cassert> +#include <cstdint> +#include <cstdlib> +#include <cstring> +#include <initializer_list> +#include <iterator> +#include <utility> + +namespace llvm { + +template<typename ValueTy> class StringMapConstIterator; +template<typename ValueTy> class StringMapIterator; +template<typename ValueTy> class StringMapKeyIterator; + +/// StringMapEntryBase - Shared base class of StringMapEntry instances. +class StringMapEntryBase { + size_t StrLen; + +public: + explicit StringMapEntryBase(size_t Len) : StrLen(Len) {} + + size_t getKeyLength() const { return StrLen; } +}; + +/// StringMapImpl - This is the base class of StringMap that is shared among +/// all of its instantiations. +class StringMapImpl { +protected: + // Array of NumBuckets pointers to entries, null pointers are holes. + // TheTable[NumBuckets] contains a sentinel value for easy iteration. Followed + // by an array of the actual hash values as unsigned integers. + StringMapEntryBase **TheTable = nullptr; + unsigned NumBuckets = 0; + unsigned NumItems = 0; + unsigned NumTombstones = 0; + unsigned ItemSize; + +protected: + explicit StringMapImpl(unsigned itemSize) + : ItemSize(itemSize) {} + StringMapImpl(StringMapImpl &&RHS) + : TheTable(RHS.TheTable), NumBuckets(RHS.NumBuckets), + NumItems(RHS.NumItems), NumTombstones(RHS.NumTombstones), + ItemSize(RHS.ItemSize) { + RHS.TheTable = nullptr; + RHS.NumBuckets = 0; + RHS.NumItems = 0; + RHS.NumTombstones = 0; + } + + StringMapImpl(unsigned InitSize, unsigned ItemSize); + unsigned RehashTable(unsigned BucketNo = 0); + + /// LookupBucketFor - Look up the bucket that the specified string should end + /// up in. If it already exists as a key in the map, the Item pointer for the + /// specified bucket will be non-null. Otherwise, it will be null. In either + /// case, the FullHashValue field of the bucket will be set to the hash value + /// of the string. + unsigned LookupBucketFor(StringRef Key); + + /// FindKey - Look up the bucket that contains the specified key. If it exists + /// in the map, return the bucket number of the key. Otherwise return -1. + /// This does not modify the map. + int FindKey(StringRef Key) const; + + /// RemoveKey - Remove the specified StringMapEntry from the table, but do not + /// delete it. This aborts if the value isn't in the table. + void RemoveKey(StringMapEntryBase *V); + + /// RemoveKey - Remove the StringMapEntry for the specified key from the + /// table, returning it. If the key is not in the table, this returns null. + StringMapEntryBase *RemoveKey(StringRef Key); + + /// Allocate the table with the specified number of buckets and otherwise + /// setup the map as empty. + void init(unsigned Size); + +public: + static StringMapEntryBase *getTombstoneVal() { + uintptr_t Val = static_cast<uintptr_t>(-1); + Val <<= PointerLikeTypeTraits<StringMapEntryBase *>::NumLowBitsAvailable; + return reinterpret_cast<StringMapEntryBase *>(Val); + } + + unsigned getNumBuckets() const { return NumBuckets; } + unsigned getNumItems() const { return NumItems; } + + bool empty() const { return NumItems == 0; } + unsigned size() const { return NumItems; } + + void swap(StringMapImpl &Other) { + std::swap(TheTable, Other.TheTable); + std::swap(NumBuckets, Other.NumBuckets); + std::swap(NumItems, Other.NumItems); + std::swap(NumTombstones, Other.NumTombstones); + } +}; + +/// StringMapEntryStorage - Holds the value in a StringMapEntry. +/// +/// Factored out into a separate base class to make it easier to specialize. +/// This is primarily intended to support StringSet, which doesn't need a value +/// stored at all. +template<typename ValueTy> +class StringMapEntryStorage : public StringMapEntryBase { +public: + ValueTy second; + + explicit StringMapEntryStorage(size_t strLen) + : StringMapEntryBase(strLen), second() {} + template <typename... InitTy> + StringMapEntryStorage(size_t strLen, InitTy &&... InitVals) + : StringMapEntryBase(strLen), second(std::forward<InitTy>(InitVals)...) {} + StringMapEntryStorage(StringMapEntryStorage &E) = delete; + + const ValueTy &getValue() const { return second; } + ValueTy &getValue() { return second; } + + void setValue(const ValueTy &V) { second = V; } +}; + +template<> +class StringMapEntryStorage<NoneType> : public StringMapEntryBase { +public: + explicit StringMapEntryStorage(size_t strLen, NoneType none = None) + : StringMapEntryBase(strLen) {} + StringMapEntryStorage(StringMapEntryStorage &E) = delete; + + NoneType getValue() const { return None; } +}; + +/// StringMapEntry - This is used to represent one value that is inserted into +/// a StringMap. It contains the Value itself and the key: the string length +/// and data. +template<typename ValueTy> +class StringMapEntry final : public StringMapEntryStorage<ValueTy> { +public: + using StringMapEntryStorage<ValueTy>::StringMapEntryStorage; + + StringRef getKey() const { + return StringRef(getKeyData(), this->getKeyLength()); + } + + /// getKeyData - Return the start of the string data that is the key for this + /// value. The string data is always stored immediately after the + /// StringMapEntry object. + const char *getKeyData() const {return reinterpret_cast<const char*>(this+1);} + + StringRef first() const { + return StringRef(getKeyData(), this->getKeyLength()); + } + + /// 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, + InitTy &&... InitVals) { + size_t KeyLength = Key.size(); + + // Allocate a new item with space for the string at the end and a null + // terminator. + size_t AllocSize = sizeof(StringMapEntry) + KeyLength + 1; + size_t Alignment = alignof(StringMapEntry); + + StringMapEntry *NewItem = + static_cast<StringMapEntry*>(Allocator.Allocate(AllocSize,Alignment)); + assert(NewItem && "Unhandled out-of-memory"); + + // Construct the value. + new (NewItem) StringMapEntry(KeyLength, std::forward<InitTy>(InitVals)...); + + // Copy the string information. + char *StrBuffer = const_cast<char*>(NewItem->getKeyData()); + if (KeyLength > 0) + memcpy(StrBuffer, Key.data(), KeyLength); + StrBuffer[KeyLength] = 0; // Null terminate for convenience of clients. + return NewItem; + } + + /// Create - Create a StringMapEntry with normal malloc/free. + template <typename... InitType> + static StringMapEntry *Create(StringRef Key, InitType &&... InitVal) { + MallocAllocator A; + return Create(Key, A, std::forward<InitType>(InitVal)...); + } + + static StringMapEntry *Create(StringRef Key) { + return Create(Key, ValueTy()); + } + + /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded + /// into a StringMapEntry, return the StringMapEntry itself. + static StringMapEntry &GetStringMapEntryFromKeyData(const char *KeyData) { + char *Ptr = const_cast<char*>(KeyData) - sizeof(StringMapEntry<ValueTy>); + return *reinterpret_cast<StringMapEntry*>(Ptr); + } + + /// Destroy - Destroy this StringMapEntry, releasing memory back to the + /// specified allocator. + template<typename AllocatorTy> + void Destroy(AllocatorTy &Allocator) { + // Free memory referenced by the item. + size_t AllocSize = sizeof(StringMapEntry) + this->getKeyLength() + 1; + this->~StringMapEntry(); + Allocator.Deallocate(static_cast<void *>(this), AllocSize); + } + + /// Destroy this object, releasing memory back to the malloc allocator. + void Destroy() { + MallocAllocator A; + Destroy(A); + } +}; + +/// StringMap - This is an unconventional map that is specialized for handling +/// keys that are "strings", which are basically ranges of bytes. This does some +/// funky memory allocation and hashing things to make it extremely efficient, +/// storing the string data *after* the value in the map. +template<typename ValueTy, typename AllocatorTy = MallocAllocator> +class StringMap : public StringMapImpl { + AllocatorTy Allocator; + +public: + using MapEntryTy = StringMapEntry<ValueTy>; + + StringMap() : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) {} + + explicit StringMap(unsigned InitialSize) + : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))) {} + + explicit StringMap(AllocatorTy A) + : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))), Allocator(A) {} + + StringMap(unsigned InitialSize, AllocatorTy A) + : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))), + Allocator(A) {} + + StringMap(std::initializer_list<std::pair<StringRef, ValueTy>> List) + : StringMapImpl(List.size(), static_cast<unsigned>(sizeof(MapEntryTy))) { + for (const auto &P : List) { + insert(P); + } + } + + StringMap(StringMap &&RHS) + : StringMapImpl(std::move(RHS)), Allocator(std::move(RHS.Allocator)) {} + + 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. + } + + StringMap &operator=(StringMap RHS) { + StringMapImpl::swap(RHS); + std::swap(Allocator, RHS.Allocator); + return *this; + } + + ~StringMap() { + // Delete all the elements in the map, but don't reset the elements + // to default values. This is a copy of clear(), but avoids unnecessary + // work not required in the destructor. + if (!empty()) { + for (unsigned I = 0, E = NumBuckets; I != E; ++I) { + StringMapEntryBase *Bucket = TheTable[I]; + if (Bucket && Bucket != getTombstoneVal()) { + static_cast<MapEntryTy*>(Bucket)->Destroy(Allocator); + } + } + } + free(TheTable); + } + + AllocatorTy &getAllocator() { return Allocator; } + const AllocatorTy &getAllocator() const { return Allocator; } + + using key_type = const char*; + using mapped_type = ValueTy; + using value_type = StringMapEntry<ValueTy>; + using size_type = size_t; + + using const_iterator = StringMapConstIterator<ValueTy>; + using iterator = StringMapIterator<ValueTy>; + + iterator begin() { + return iterator(TheTable, NumBuckets == 0); + } + iterator end() { + return iterator(TheTable+NumBuckets, true); + } + const_iterator begin() const { + return const_iterator(TheTable, NumBuckets == 0); + } + const_iterator end() const { + return const_iterator(TheTable+NumBuckets, true); + } + + iterator_range<StringMapKeyIterator<ValueTy>> keys() const { + return make_range(StringMapKeyIterator<ValueTy>(begin()), + StringMapKeyIterator<ValueTy>(end())); + } + + iterator find(StringRef Key) { + int Bucket = FindKey(Key); + if (Bucket == -1) return end(); + return iterator(TheTable+Bucket, true); + } + + const_iterator find(StringRef Key) const { + int Bucket = FindKey(Key); + if (Bucket == -1) return end(); + return const_iterator(TheTable+Bucket, true); + } + + /// lookup - Return the entry for the specified key, or a default + /// constructed value if no such entry exists. + ValueTy lookup(StringRef Key) const { + const_iterator it = find(Key); + if (it != end()) + return it->second; + 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 try_emplace(Key).first->second; } + + /// count - Return 1 if the element is in the map, 0 otherwise. + size_type count(StringRef Key) const { + return find(Key) == end() ? 0 : 1; + } + + template <typename InputTy> + size_type count(const StringMapEntry<InputTy> &MapEntry) const { + return count(MapEntry.getKey()); + } + + /// insert - Insert the specified key/value pair into the map. If the key + /// already exists in the map, return false and ignore the request, otherwise + /// insert it and return true. + bool insert(MapEntryTy *KeyValue) { + unsigned BucketNo = LookupBucketFor(KeyValue->getKey()); + StringMapEntryBase *&Bucket = TheTable[BucketNo]; + if (Bucket && Bucket != getTombstoneVal()) + return false; // Already exists in map. + + if (Bucket == getTombstoneVal()) + --NumTombstones; + Bucket = KeyValue; + ++NumItems; + assert(NumItems + NumTombstones <= NumBuckets); + + RehashTable(); + return true; + } + + /// insert - Inserts the specified key/value pair into the map if the key + /// isn't already in the map. The bool component of the returned pair is true + /// if and only if the insertion takes place, and the iterator component of + /// the pair points to the element with key equivalent to the key of the pair. + std::pair<iterator, bool> insert(std::pair<StringRef, ValueTy> KV) { + return try_emplace(KV.first, std::move(KV.second)); + } + + /// Inserts an element or assigns to the current element if the key already + /// exists. The return type is the same as try_emplace. + template <typename V> + std::pair<iterator, bool> insert_or_assign(StringRef Key, V &&Val) { + auto Ret = try_emplace(Key, std::forward<V>(Val)); + if (!Ret.second) + Ret.first->second = std::forward<V>(Val); + return Ret; + } + + /// 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> try_emplace(StringRef Key, ArgsTy &&... Args) { + unsigned BucketNo = LookupBucketFor(Key); + StringMapEntryBase *&Bucket = TheTable[BucketNo]; + if (Bucket && Bucket != getTombstoneVal()) + return std::make_pair(iterator(TheTable + BucketNo, false), + false); // Already exists in map. + + if (Bucket == getTombstoneVal()) + --NumTombstones; + Bucket = MapEntryTy::Create(Key, Allocator, std::forward<ArgsTy>(Args)...); + ++NumItems; + assert(NumItems + NumTombstones <= NumBuckets); + + BucketNo = RehashTable(BucketNo); + return std::make_pair(iterator(TheTable + BucketNo, false), true); + } + + // clear - Empties out the StringMap + void clear() { + if (empty()) return; + + // Zap all values, resetting the keys back to non-present (not tombstone), + // which is safe because we're removing all elements. + for (unsigned I = 0, E = NumBuckets; I != E; ++I) { + StringMapEntryBase *&Bucket = TheTable[I]; + if (Bucket && Bucket != getTombstoneVal()) { + static_cast<MapEntryTy*>(Bucket)->Destroy(Allocator); + } + Bucket = nullptr; + } + + NumItems = 0; + NumTombstones = 0; + } + + /// remove - Remove the specified key/value pair from the map, but do not + /// erase it. This aborts if the key is not in the map. + void remove(MapEntryTy *KeyValue) { + RemoveKey(KeyValue); + } + + void erase(iterator I) { + MapEntryTy &V = *I; + remove(&V); + V.Destroy(Allocator); + } + + bool erase(StringRef Key) { + iterator I = find(Key); + if (I == end()) return false; + erase(I); + return true; + } +}; + +template <typename DerivedTy, typename ValueTy> +class StringMapIterBase + : public iterator_facade_base<DerivedTy, std::forward_iterator_tag, + ValueTy> { +protected: + StringMapEntryBase **Ptr = nullptr; + +public: + StringMapIterBase() = default; + + explicit StringMapIterBase(StringMapEntryBase **Bucket, + bool NoAdvance = false) + : Ptr(Bucket) { + if (!NoAdvance) AdvancePastEmptyBuckets(); + } + + DerivedTy &operator=(const DerivedTy &Other) { + Ptr = Other.Ptr; + return static_cast<DerivedTy &>(*this); + } + + bool operator==(const DerivedTy &RHS) const { return Ptr == RHS.Ptr; } + + DerivedTy &operator++() { // Preincrement + ++Ptr; + AdvancePastEmptyBuckets(); + return static_cast<DerivedTy &>(*this); + } + + DerivedTy operator++(int) { // Post-increment + DerivedTy Tmp(Ptr); + ++*this; + return Tmp; + } + +private: + void AdvancePastEmptyBuckets() { + while (*Ptr == nullptr || *Ptr == StringMapImpl::getTombstoneVal()) + ++Ptr; + } +}; + +template <typename ValueTy> +class StringMapConstIterator + : public StringMapIterBase<StringMapConstIterator<ValueTy>, + const StringMapEntry<ValueTy>> { + using base = StringMapIterBase<StringMapConstIterator<ValueTy>, + const StringMapEntry<ValueTy>>; + +public: + StringMapConstIterator() = default; + explicit StringMapConstIterator(StringMapEntryBase **Bucket, + bool NoAdvance = false) + : base(Bucket, NoAdvance) {} + + const StringMapEntry<ValueTy> &operator*() const { + return *static_cast<const StringMapEntry<ValueTy> *>(*this->Ptr); + } +}; + +template <typename ValueTy> +class StringMapIterator : public StringMapIterBase<StringMapIterator<ValueTy>, + StringMapEntry<ValueTy>> { + using base = + StringMapIterBase<StringMapIterator<ValueTy>, StringMapEntry<ValueTy>>; + +public: + StringMapIterator() = default; + explicit StringMapIterator(StringMapEntryBase **Bucket, + bool NoAdvance = false) + : base(Bucket, NoAdvance) {} + + StringMapEntry<ValueTy> &operator*() const { + return *static_cast<StringMapEntry<ValueTy> *>(*this->Ptr); + } + + operator StringMapConstIterator<ValueTy>() const { + return StringMapConstIterator<ValueTy>(this->Ptr, true); + } +}; + +template <typename ValueTy> +class StringMapKeyIterator + : public iterator_adaptor_base<StringMapKeyIterator<ValueTy>, + StringMapConstIterator<ValueTy>, + std::forward_iterator_tag, StringRef> { + using base = iterator_adaptor_base<StringMapKeyIterator<ValueTy>, + StringMapConstIterator<ValueTy>, + std::forward_iterator_tag, StringRef>; + +public: + StringMapKeyIterator() = default; + explicit StringMapKeyIterator(StringMapConstIterator<ValueTy> Iter) + : base(std::move(Iter)) {} + + StringRef &operator*() { + Key = this->wrapped()->getKey(); + return Key; + } + +private: + StringRef Key; +}; + +} // end namespace llvm + +#endif // LLVM_ADT_STRINGMAP_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/StringRef.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/StringRef.h new file mode 100644 index 0000000..f06d187 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/StringRef.h
@@ -0,0 +1,922 @@ +//===- StringRef.h - Constant String Reference Wrapper ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STRINGREF_H +#define LLVM_ADT_STRINGREF_H + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/Compiler.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstring> +#include <limits> +#include <string> +#include <type_traits> +#include <utility> + +// Declare the __builtin_strlen intrinsic for MSVC so it can be used in +// constexpr context. +#if defined(_MSC_VER) +extern "C" size_t __builtin_strlen(const char *); +#endif + +namespace llvm { + + class APInt; + class hash_code; + template <typename T> class SmallVectorImpl; + class StringRef; + + /// Helper functions for StringRef::getAsInteger. + bool getAsUnsignedInteger(StringRef Str, unsigned Radix, + unsigned long long &Result); + + bool getAsSignedInteger(StringRef Str, unsigned Radix, long long &Result); + + bool consumeUnsignedInteger(StringRef &Str, unsigned Radix, + unsigned long long &Result); + bool consumeSignedInteger(StringRef &Str, unsigned Radix, long long &Result); + + /// StringRef - Represent a constant reference to a string, i.e. a character + /// array and a length, which need not be null terminated. + /// + /// This class does not own the string data, it is expected to be used in + /// situations where the character data resides in some other buffer, whose + /// lifetime extends past that of the StringRef. For this reason, it is not in + /// general safe to store a StringRef. + class StringRef { + public: + static const size_t npos = ~size_t(0); + + using iterator = const char *; + using const_iterator = const char *; + using size_type = size_t; + + private: + /// The start of the string, in an external buffer. + const char *Data = nullptr; + + /// The length of the string. + size_t Length = 0; + + // Workaround memcmp issue with null pointers (undefined behavior) + // by providing a specialized version + static int compareMemory(const char *Lhs, const char *Rhs, size_t Length) { + if (Length == 0) { return 0; } + return ::memcmp(Lhs,Rhs,Length); + } + + // Constexpr version of std::strlen. + static constexpr size_t strLen(const char *Str) { +#if __cplusplus > 201402L + return std::char_traits<char>::length(Str); +#elif __has_builtin(__builtin_strlen) || defined(__GNUC__) || \ + (defined(_MSC_VER) && _MSC_VER >= 1916) + return __builtin_strlen(Str); +#else + const char *Begin = Str; + while (*Str != '\0') + ++Str; + return Str - Begin; +#endif + } + + public: + /// @name Constructors + /// @{ + + /// Construct an empty string ref. + /*implicit*/ StringRef() = default; + + /// Disable conversion from nullptr. This prevents things like + /// if (S == nullptr) + StringRef(std::nullptr_t) = delete; + + /// Construct a string ref from a cstring. + /*implicit*/ constexpr StringRef(const char *Str) + : Data(Str), Length(Str ? strLen(Str) : 0) {} + + /// Construct a string ref from a pointer and length. + /*implicit*/ constexpr StringRef(const char *data, size_t length) + : Data(data), Length(length) {} + + /// Construct a string ref from an std::string. + /*implicit*/ StringRef(const std::string &Str) + : Data(Str.data()), Length(Str.length()) {} + + static StringRef withNullAsEmpty(const char *data) { + return StringRef(data ? data : ""); + } + + /// @} + /// @name Iterators + /// @{ + + iterator begin() const { return Data; } + + iterator end() const { return Data + Length; } + + const unsigned char *bytes_begin() const { + return reinterpret_cast<const unsigned char *>(begin()); + } + 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 + /// @{ + + /// data - Get a pointer to the start of the string (which may not be null + /// terminated). + LLVM_NODISCARD + const char *data() const { return Data; } + + /// empty - Check if the string is empty. + LLVM_NODISCARD + bool empty() const { return Length == 0; } + + /// size - Get the string size. + LLVM_NODISCARD + size_t size() const { return Length; } + + /// front - Get the first character in the string. + LLVM_NODISCARD + char front() const { + assert(!empty()); + return Data[0]; + } + + /// back - Get the last character in the string. + LLVM_NODISCARD + char back() const { + assert(!empty()); + return Data[Length-1]; + } + + // copy - Allocate copy in Allocator and return StringRef to it. + template <typename Allocator> + LLVM_NODISCARD 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); + } + + /// equals - Check for string equality, this is more efficient than + /// compare() when the relative ordering of inequal strings isn't needed. + LLVM_NODISCARD + bool equals(StringRef RHS) const { + return (Length == RHS.Length && + compareMemory(Data, RHS.Data, RHS.Length) == 0); + } + + /// equals_lower - Check for string equality, ignoring case. + LLVM_NODISCARD + bool equals_lower(StringRef RHS) const { + return Length == RHS.Length && compare_lower(RHS) == 0; + } + + /// compare - Compare two strings; the result is -1, 0, or 1 if this string + /// is lexicographically less than, equal to, or greater than the \p RHS. + LLVM_NODISCARD + int compare(StringRef RHS) const { + // Check the prefix for a mismatch. + if (int Res = compareMemory(Data, RHS.Data, std::min(Length, RHS.Length))) + return Res < 0 ? -1 : 1; + + // Otherwise the prefixes match, so we only need to check the lengths. + if (Length == RHS.Length) + return 0; + return Length < RHS.Length ? -1 : 1; + } + + /// compare_lower - Compare two strings, ignoring case. + LLVM_NODISCARD + int compare_lower(StringRef RHS) const; + + /// compare_numeric - Compare two strings, treating sequences of digits as + /// numbers. + LLVM_NODISCARD + int compare_numeric(StringRef RHS) const; + + /// Determine the edit distance between this string and another + /// string. + /// + /// \param Other the string to compare this string against. + /// + /// \param AllowReplacements whether to allow character + /// replacements (change one character into another) as a single + /// operation, rather than as two operations (an insertion and a + /// removal). + /// + /// \param MaxEditDistance If non-zero, the maximum edit distance that + /// this routine is allowed to compute. If the edit distance will exceed + /// that maximum, returns \c MaxEditDistance+1. + /// + /// \returns the minimum number of character insertions, removals, + /// or (if \p AllowReplacements is \c true) replacements needed to + /// transform one of the given strings into the other. If zero, + /// the strings are identical. + LLVM_NODISCARD + unsigned edit_distance(StringRef Other, bool AllowReplacements = true, + unsigned MaxEditDistance = 0) const; + + /// str - Get the contents as an std::string. + LLVM_NODISCARD + std::string str() const { + if (!Data) return std::string(); + return std::string(Data, Length); + } + + /// @} + /// @name Operator Overloads + /// @{ + + LLVM_NODISCARD + char operator[](size_t Index) const { + assert(Index < Length && "Invalid index!"); + return Data[Index]; + } + + /// Disallow accidental assignment from a temporary std::string. + /// + /// The declaration here is extra complicated so that `stringRef = {}` + /// and `stringRef = "abc"` continue to select the move assignment operator. + template <typename T> + typename std::enable_if<std::is_same<T, std::string>::value, + StringRef>::type & + operator=(T &&Str) = delete; + + /// @} + /// @name Type Conversions + /// @{ + + operator std::string() const { + return str(); + } + + /// @} + /// @name String Predicates + /// @{ + + /// Check if this string starts with the given \p Prefix. + LLVM_NODISCARD + bool startswith(StringRef Prefix) const { + return Length >= Prefix.Length && + compareMemory(Data, Prefix.Data, Prefix.Length) == 0; + } + + /// Check if this string starts with the given \p Prefix, ignoring case. + LLVM_NODISCARD + bool startswith_lower(StringRef Prefix) const; + + /// Check if this string ends with the given \p Suffix. + LLVM_NODISCARD + bool endswith(StringRef Suffix) const { + return Length >= Suffix.Length && + compareMemory(end() - Suffix.Length, Suffix.Data, Suffix.Length) == 0; + } + + /// Check if this string ends with the given \p Suffix, ignoring case. + LLVM_NODISCARD + bool endswith_lower(StringRef Suffix) const; + + /// @} + /// @name String Searching + /// @{ + + /// Search for the first character \p C in the string. + /// + /// \returns The index of the first occurrence of \p C, or npos if not + /// found. + LLVM_NODISCARD + size_t find(char C, size_t From = 0) const { + size_t FindBegin = std::min(From, Length); + if (FindBegin < Length) { // Avoid calling memchr with nullptr. + // Just forward to memchr, which is faster than a hand-rolled loop. + if (const void *P = ::memchr(Data + FindBegin, C, Length - FindBegin)) + return static_cast<const char *>(P) - Data; + } + return npos; + } + + /// Search for the first character \p C in the string, ignoring case. + /// + /// \returns The index of the first occurrence of \p C, or npos if not + /// found. + LLVM_NODISCARD + size_t find_lower(char C, size_t From = 0) const; + + /// Search for the first character satisfying the predicate \p F + /// + /// \returns The index of the first character satisfying \p F starting from + /// \p From, or npos if not found. + LLVM_NODISCARD + size_t find_if(function_ref<bool(char)> F, size_t From = 0) const { + StringRef S = drop_front(From); + while (!S.empty()) { + if (F(S.front())) + return size() - S.size(); + S = S.drop_front(); + } + return npos; + } + + /// Search for the first character not satisfying the predicate \p F + /// + /// \returns The index of the first character not satisfying \p F starting + /// from \p From, or npos if not found. + LLVM_NODISCARD + size_t find_if_not(function_ref<bool(char)> F, size_t From = 0) const { + return find_if([F](char c) { return !F(c); }, From); + } + + /// Search for the first string \p Str in the string. + /// + /// \returns The index of the first occurrence of \p Str, or npos if not + /// found. + LLVM_NODISCARD + size_t find(StringRef Str, size_t From = 0) const; + + /// Search for the first string \p Str in the string, ignoring case. + /// + /// \returns The index of the first occurrence of \p Str, or npos if not + /// found. + LLVM_NODISCARD + size_t find_lower(StringRef Str, size_t From = 0) const; + + /// Search for the last character \p C in the string. + /// + /// \returns The index of the last occurrence of \p C, or npos if not + /// found. + LLVM_NODISCARD + size_t rfind(char C, size_t From = npos) const { + From = std::min(From, Length); + size_t i = From; + while (i != 0) { + --i; + if (Data[i] == C) + return i; + } + return npos; + } + + /// Search for the last character \p C in the string, ignoring case. + /// + /// \returns The index of the last occurrence of \p C, or npos if not + /// found. + LLVM_NODISCARD + size_t rfind_lower(char C, size_t From = npos) const; + + /// Search for the last string \p Str in the string. + /// + /// \returns The index of the last occurrence of \p Str, or npos if not + /// found. + LLVM_NODISCARD + size_t rfind(StringRef Str) const; + + /// Search for the last string \p Str in the string, ignoring case. + /// + /// \returns The index of the last occurrence of \p Str, or npos if not + /// found. + LLVM_NODISCARD + size_t rfind_lower(StringRef Str) const; + + /// Find the first character in the string that is \p C, or npos if not + /// found. Same as find. + LLVM_NODISCARD + size_t find_first_of(char C, size_t From = 0) const { + return find(C, From); + } + + /// Find the first character in the string that is in \p Chars, or npos if + /// not found. + /// + /// Complexity: O(size() + Chars.size()) + LLVM_NODISCARD + size_t find_first_of(StringRef Chars, size_t From = 0) const; + + /// Find the first character in the string that is not \p C or npos if not + /// found. + LLVM_NODISCARD + size_t find_first_not_of(char C, size_t From = 0) const; + + /// Find the first character in the string that is not in the string + /// \p Chars, or npos if not found. + /// + /// Complexity: O(size() + Chars.size()) + LLVM_NODISCARD + size_t find_first_not_of(StringRef Chars, size_t From = 0) const; + + /// Find the last character in the string that is \p C, or npos if not + /// found. + LLVM_NODISCARD + size_t find_last_of(char C, size_t From = npos) const { + return rfind(C, From); + } + + /// Find the last character in the string that is in \p C, or npos if not + /// found. + /// + /// Complexity: O(size() + Chars.size()) + LLVM_NODISCARD + size_t find_last_of(StringRef Chars, size_t From = npos) const; + + /// Find the last character in the string that is not \p C, or npos if not + /// found. + LLVM_NODISCARD + size_t find_last_not_of(char C, size_t From = npos) const; + + /// Find the last character in the string that is not in \p Chars, or + /// npos if not found. + /// + /// Complexity: O(size() + Chars.size()) + LLVM_NODISCARD + size_t find_last_not_of(StringRef Chars, size_t From = npos) const; + + /// Return true if the given string is a substring of *this, and false + /// otherwise. + LLVM_NODISCARD + bool contains(StringRef Other) const { return find(Other) != npos; } + + /// Return true if the given character is contained in *this, and false + /// otherwise. + LLVM_NODISCARD + bool contains(char C) const { return find_first_of(C) != npos; } + + /// Return true if the given string is a substring of *this, and false + /// otherwise. + LLVM_NODISCARD + bool contains_lower(StringRef Other) const { + return find_lower(Other) != npos; + } + + /// Return true if the given character is contained in *this, and false + /// otherwise. + LLVM_NODISCARD + bool contains_lower(char C) const { return find_lower(C) != npos; } + + /// @} + /// @name Helpful Algorithms + /// @{ + + /// Return the number of occurrences of \p C in the string. + LLVM_NODISCARD + size_t count(char C) const { + size_t Count = 0; + for (size_t i = 0, e = Length; i != e; ++i) + if (Data[i] == C) + ++Count; + return Count; + } + + /// Return the number of non-overlapped occurrences of \p Str in + /// the string. + size_t count(StringRef Str) const; + + /// Parse the current string as an integer of the specified radix. If + /// \p Radix is specified as zero, this does radix autosensing using + /// extended C rules: 0 is octal, 0x is hex, 0b is binary. + /// + /// If the string is invalid or if only a subset of the string is valid, + /// this returns true to signify the error. The string is considered + /// erroneous if empty or if it overflows T. + template <typename T> + typename std::enable_if<std::numeric_limits<T>::is_signed, bool>::type + getAsInteger(unsigned Radix, T &Result) const { + long long LLVal; + if (getAsSignedInteger(*this, Radix, LLVal) || + static_cast<T>(LLVal) != LLVal) + return true; + Result = LLVal; + return false; + } + + template <typename T> + typename std::enable_if<!std::numeric_limits<T>::is_signed, bool>::type + getAsInteger(unsigned Radix, T &Result) const { + unsigned long long ULLVal; + // The additional cast to unsigned long long is required to avoid the + // Visual C++ warning C4805: '!=' : unsafe mix of type 'bool' and type + // 'unsigned __int64' when instantiating getAsInteger with T = bool. + if (getAsUnsignedInteger(*this, Radix, ULLVal) || + static_cast<unsigned long long>(static_cast<T>(ULLVal)) != ULLVal) + return true; + Result = ULLVal; + return false; + } + + /// Parse the current string as an integer of the specified radix. If + /// \p Radix is specified as zero, this does radix autosensing using + /// extended C rules: 0 is octal, 0x is hex, 0b is binary. + /// + /// If the string does not begin with a number of the specified radix, + /// this returns true to signify the error. The string is considered + /// erroneous if empty or if it overflows T. + /// The portion of the string representing the discovered numeric value + /// is removed from the beginning of the string. + template <typename T> + typename std::enable_if<std::numeric_limits<T>::is_signed, bool>::type + consumeInteger(unsigned Radix, T &Result) { + long long LLVal; + if (consumeSignedInteger(*this, Radix, LLVal) || + static_cast<long long>(static_cast<T>(LLVal)) != LLVal) + return true; + Result = LLVal; + return false; + } + + template <typename T> + typename std::enable_if<!std::numeric_limits<T>::is_signed, bool>::type + consumeInteger(unsigned Radix, T &Result) { + unsigned long long ULLVal; + if (consumeUnsignedInteger(*this, Radix, ULLVal) || + static_cast<unsigned long long>(static_cast<T>(ULLVal)) != ULLVal) + return true; + Result = ULLVal; + return false; + } + + /// Parse the current string as an integer of the specified \p Radix, or of + /// an autosensed radix if the \p Radix given is 0. The current value in + /// \p Result is discarded, and the storage is changed to be wide enough to + /// store the parsed integer. + /// + /// \returns true if the string does not solely consist of a valid + /// non-empty number in the appropriate base. + /// + /// APInt::fromString is superficially similar but assumes the + /// string is well-formed in the given radix. + bool getAsInteger(unsigned Radix, APInt &Result) const; + + /// Parse the current string as an IEEE double-precision floating + /// point value. The string must be a well-formed double. + /// + /// If \p AllowInexact is false, the function will fail if the string + /// cannot be represented exactly. Otherwise, the function only fails + /// in case of an overflow or underflow, or an invalid floating point + /// representation. + bool getAsDouble(double &Result, bool AllowInexact = true) const; + + /// @} + /// @name String Operations + /// @{ + + // Convert the given ASCII string to lowercase. + LLVM_NODISCARD + std::string lower() const; + + /// Convert the given ASCII string to uppercase. + LLVM_NODISCARD + std::string upper() const; + + /// @} + /// @name Substring Operations + /// @{ + + /// Return a reference to the substring from [Start, Start + N). + /// + /// \param Start The index of the starting character in the substring; if + /// the index is npos or greater than the length of the string then the + /// empty substring will be returned. + /// + /// \param N The number of characters to included in the substring. If N + /// exceeds the number of characters remaining in the string, the string + /// suffix (starting with \p Start) will be returned. + LLVM_NODISCARD + StringRef substr(size_t Start, size_t N = npos) const { + Start = std::min(Start, Length); + return StringRef(Data + Start, std::min(N, Length - Start)); + } + + /// Return a StringRef equal to 'this' but with only the first \p N + /// elements remaining. If \p N is greater than the length of the + /// string, the entire string is returned. + LLVM_NODISCARD + StringRef take_front(size_t N = 1) const { + if (N >= size()) + return *this; + return drop_back(size() - N); + } + + /// Return a StringRef equal to 'this' but with only the last \p N + /// elements remaining. If \p N is greater than the length of the + /// string, the entire string is returned. + LLVM_NODISCARD + StringRef take_back(size_t N = 1) const { + if (N >= size()) + return *this; + return drop_front(size() - N); + } + + /// Return the longest prefix of 'this' such that every character + /// in the prefix satisfies the given predicate. + LLVM_NODISCARD + StringRef take_while(function_ref<bool(char)> F) const { + return substr(0, find_if_not(F)); + } + + /// Return the longest prefix of 'this' such that no character in + /// the prefix satisfies the given predicate. + LLVM_NODISCARD + StringRef take_until(function_ref<bool(char)> F) const { + return substr(0, find_if(F)); + } + + /// Return a StringRef equal to 'this' but with the first \p N elements + /// dropped. + LLVM_NODISCARD + StringRef drop_front(size_t N = 1) const { + assert(size() >= N && "Dropping more elements than exist"); + return substr(N); + } + + /// Return a StringRef equal to 'this' but with the last \p N elements + /// dropped. + LLVM_NODISCARD + StringRef drop_back(size_t N = 1) const { + assert(size() >= N && "Dropping more elements than exist"); + return substr(0, size()-N); + } + + /// Return a StringRef equal to 'this', but with all characters satisfying + /// the given predicate dropped from the beginning of the string. + LLVM_NODISCARD + StringRef drop_while(function_ref<bool(char)> F) const { + return substr(find_if_not(F)); + } + + /// Return a StringRef equal to 'this', but with all characters not + /// satisfying the given predicate dropped from the beginning of the string. + LLVM_NODISCARD + StringRef drop_until(function_ref<bool(char)> F) const { + return substr(find_if(F)); + } + + /// Returns true if this StringRef has the given prefix and removes that + /// prefix. + bool consume_front(StringRef Prefix) { + if (!startswith(Prefix)) + return false; + + *this = drop_front(Prefix.size()); + return true; + } + + /// Returns true if this StringRef has the given suffix and removes that + /// suffix. + bool consume_back(StringRef Suffix) { + if (!endswith(Suffix)) + return false; + + *this = drop_back(Suffix.size()); + return true; + } + + /// Return a reference to the substring from [Start, End). + /// + /// \param Start The index of the starting character in the substring; if + /// the index is npos or greater than the length of the string then the + /// empty substring will be returned. + /// + /// \param End The index following the last character to include in the + /// 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_NODISCARD + StringRef slice(size_t Start, size_t End) const { + Start = std::min(Start, Length); + End = std::min(std::max(Start, End), Length); + return StringRef(Data + Start, End - Start); + } + + /// Split into two substrings around the first occurrence of a separator + /// character. + /// + /// If \p Separator is in the string, then the result is a pair (LHS, RHS) + /// such that (*this == LHS + Separator + RHS) is true and RHS is + /// maximal. If \p Separator is not in the string, then the result is a + /// pair (LHS, RHS) where (*this == LHS) and (RHS == ""). + /// + /// \param Separator The character to split on. + /// \returns The split substrings. + LLVM_NODISCARD + std::pair<StringRef, StringRef> split(char Separator) const { + return split(StringRef(&Separator, 1)); + } + + /// Split into two substrings around the first occurrence of a separator + /// string. + /// + /// If \p Separator is in the string, then the result is a pair (LHS, RHS) + /// such that (*this == LHS + Separator + RHS) is true and RHS is + /// maximal. If \p Separator is not in the string, then the result is a + /// pair (LHS, RHS) where (*this == LHS) and (RHS == ""). + /// + /// \param Separator - The string to split on. + /// \return - The split substrings. + LLVM_NODISCARD + std::pair<StringRef, StringRef> split(StringRef Separator) const { + size_t Idx = find(Separator); + if (Idx == npos) + return std::make_pair(*this, StringRef()); + return std::make_pair(slice(0, Idx), slice(Idx + Separator.size(), npos)); + } + + /// Split into two substrings around the last occurrence of a separator + /// string. + /// + /// If \p Separator is in the string, then the result is a pair (LHS, RHS) + /// such that (*this == LHS + Separator + RHS) is true and RHS is + /// minimal. If \p Separator is not in the string, then the result is a + /// pair (LHS, RHS) where (*this == LHS) and (RHS == ""). + /// + /// \param Separator - The string to split on. + /// \return - The split substrings. + LLVM_NODISCARD + std::pair<StringRef, StringRef> rsplit(StringRef Separator) const { + size_t Idx = rfind(Separator); + if (Idx == npos) + return std::make_pair(*this, StringRef()); + return std::make_pair(slice(0, Idx), slice(Idx + Separator.size(), npos)); + } + + /// Split into substrings around the occurrences of a separator string. + /// + /// Each substring is stored in \p A. If \p MaxSplit is >= 0, at most + /// \p MaxSplit splits are done and consequently <= \p MaxSplit + 1 + /// elements are added to A. + /// If \p KeepEmpty is false, empty strings are not added to \p A. They + /// still count when considering \p MaxSplit + /// An useful invariant is that + /// Separator.join(A) == *this if MaxSplit == -1 and KeepEmpty == true + /// + /// \param A - Where to put the substrings. + /// \param Separator - The string to split on. + /// \param MaxSplit - The maximum number of times the string is split. + /// \param KeepEmpty - True if empty substring should be added. + void split(SmallVectorImpl<StringRef> &A, + StringRef Separator, int MaxSplit = -1, + bool KeepEmpty = true) const; + + /// Split into substrings around the occurrences of a separator character. + /// + /// Each substring is stored in \p A. If \p MaxSplit is >= 0, at most + /// \p MaxSplit splits are done and consequently <= \p MaxSplit + 1 + /// elements are added to A. + /// If \p KeepEmpty is false, empty strings are not added to \p A. They + /// still count when considering \p MaxSplit + /// An useful invariant is that + /// Separator.join(A) == *this if MaxSplit == -1 and KeepEmpty == true + /// + /// \param A - Where to put the substrings. + /// \param Separator - The string to split on. + /// \param MaxSplit - The maximum number of times the string is split. + /// \param KeepEmpty - True if empty substring should be added. + void split(SmallVectorImpl<StringRef> &A, char Separator, int MaxSplit = -1, + bool KeepEmpty = true) const; + + /// Split into two substrings around the last occurrence of a separator + /// character. + /// + /// If \p Separator is in the string, then the result is a pair (LHS, RHS) + /// such that (*this == LHS + Separator + RHS) is true and RHS is + /// minimal. If \p Separator is not in the string, then the result is a + /// pair (LHS, RHS) where (*this == LHS) and (RHS == ""). + /// + /// \param Separator - The character to split on. + /// \return - The split substrings. + LLVM_NODISCARD + std::pair<StringRef, StringRef> rsplit(char Separator) const { + return rsplit(StringRef(&Separator, 1)); + } + + /// Return string with consecutive \p Char characters starting from the + /// the left removed. + LLVM_NODISCARD + 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. + LLVM_NODISCARD + 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. + LLVM_NODISCARD + 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. + LLVM_NODISCARD + 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. + LLVM_NODISCARD + 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. + LLVM_NODISCARD + StringRef trim(StringRef Chars = " \t\n\v\f\r") const { + return ltrim(Chars).rtrim(Chars); + } + + /// @} + }; + + /// A wrapper around a string literal that serves as a proxy for constructing + /// global tables of StringRefs with the length computed at compile time. + /// In order to avoid the invocation of a global constructor, StringLiteral + /// should *only* be used in a constexpr context, as such: + /// + /// constexpr StringLiteral S("test"); + /// + class StringLiteral : public StringRef { + private: + constexpr StringLiteral(const char *Str, size_t N) : StringRef(Str, N) { + } + + public: + template <size_t N> + constexpr StringLiteral(const char (&Str)[N]) +#if defined(__clang__) && __has_attribute(enable_if) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wgcc-compat" + __attribute((enable_if(__builtin_strlen(Str) == N - 1, + "invalid string literal"))) +#pragma clang diagnostic pop +#endif + : StringRef(Str, N - 1) { + } + + // Explicit construction for strings like "foo\0bar". + template <size_t N> + static constexpr StringLiteral withInnerNUL(const char (&Str)[N]) { + return StringLiteral(Str, N - 1); + } + }; + + /// @name StringRef Comparison Operators + /// @{ + + inline bool operator==(StringRef LHS, StringRef RHS) { + return LHS.equals(RHS); + } + + inline bool operator!=(StringRef LHS, StringRef RHS) { return !(LHS == RHS); } + + inline bool operator<(StringRef LHS, StringRef RHS) { + return LHS.compare(RHS) == -1; + } + + inline bool operator<=(StringRef LHS, StringRef RHS) { + return LHS.compare(RHS) != 1; + } + + inline bool operator>(StringRef LHS, StringRef RHS) { + return LHS.compare(RHS) == 1; + } + + inline bool operator>=(StringRef LHS, StringRef RHS) { + return LHS.compare(RHS) != -1; + } + + inline std::string &operator+=(std::string &buffer, StringRef string) { + return buffer.append(string.data(), string.size()); + } + + /// @} + + /// Compute a hash_code for a StringRef. + LLVM_NODISCARD + hash_code hash_value(StringRef S); + +} // end namespace llvm + +#endif // LLVM_ADT_STRINGREF_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/StringSet.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/StringSet.h new file mode 100644 index 0000000..60be09d --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/StringSet.h
@@ -0,0 +1,58 @@ +//===- StringSet.h - The LLVM Compiler Driver -------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// StringSet - A set-like wrapper for the StringMap. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STRINGSET_H +#define LLVM_ADT_STRINGSET_H + +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Allocator.h" +#include <cassert> +#include <initializer_list> +#include <utility> + +namespace llvm { + + /// StringSet - A wrapper for StringMap that provides set-like functionality. + template <class AllocatorTy = MallocAllocator> + class StringSet : public StringMap<NoneType, AllocatorTy> { + using base = StringMap<NoneType, AllocatorTy>; + + public: + StringSet() = default; + StringSet(std::initializer_list<StringRef> S) { + for (StringRef X : S) + insert(X); + } + explicit StringSet(AllocatorTy A) : base(A) {} + + std::pair<typename base::iterator, bool> insert(StringRef Key) { + assert(!Key.empty()); + return base::insert(std::make_pair(Key, None)); + } + + template <typename InputIt> + void insert(const InputIt &Begin, const InputIt &End) { + for (auto It = Begin; It != End; ++It) + base::insert(std::make_pair(*It, None)); + } + + template <typename ValueTy> + std::pair<typename base::iterator, bool> + insert(const StringMapEntry<ValueTy> &MapEntry) { + return insert(MapEntry.getKey()); + } + }; + +} // end namespace llvm + +#endif // LLVM_ADT_STRINGSET_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/StringSwitch.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/StringSwitch.h new file mode 100644 index 0000000..fea911f --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/StringSwitch.h
@@ -0,0 +1,196 @@ +//===--- StringSwitch.h - Switch-on-literal-string Construct --------------===/ +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +//===----------------------------------------------------------------------===/ +// +// This file implements the StringSwitch template, which mimics a switch() +// statement whose cases are string literals. +// +//===----------------------------------------------------------------------===/ +#ifndef LLVM_ADT_STRINGSWITCH_H +#define LLVM_ADT_STRINGSWITCH_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Compiler.h" +#include <cassert> +#include <cstring> + +namespace llvm { + +/// A switch()-like statement whose cases are string literals. +/// +/// The StringSwitch class is a simple form of a switch() statement that +/// determines whether the given string matches one of the given string +/// literals. The template type parameter \p T is the type of the value that +/// will be returned from the string-switch expression. For example, +/// the following code switches on the name of a color in \c argv[i]: +/// +/// \code +/// Color color = StringSwitch<Color>(argv[i]) +/// .Case("red", Red) +/// .Case("orange", Orange) +/// .Case("yellow", Yellow) +/// .Case("green", Green) +/// .Case("blue", Blue) +/// .Case("indigo", Indigo) +/// .Cases("violet", "purple", Violet) +/// .Default(UnknownColor); +/// \endcode +template<typename T, typename R = T> +class StringSwitch { + /// The string we are matching. + const StringRef Str; + + /// The pointer to the result of this switch statement, once known, + /// null before that. + Optional<T> Result; + +public: + explicit StringSwitch(StringRef S) + : Str(S), Result() { } + + // StringSwitch is not copyable. + StringSwitch(const StringSwitch &) = delete; + + // StringSwitch is not assignable due to 'Str' being 'const'. + void operator=(const StringSwitch &) = delete; + void operator=(StringSwitch &&other) = delete; + + StringSwitch(StringSwitch &&other) + : Str(other.Str), Result(std::move(other.Result)) { } + + ~StringSwitch() = default; + + // Case-sensitive case matchers + StringSwitch &Case(StringLiteral S, T Value) { + if (!Result && Str == S) { + Result = std::move(Value); + } + return *this; + } + + StringSwitch& EndsWith(StringLiteral S, T Value) { + if (!Result && Str.endswith(S)) { + Result = std::move(Value); + } + return *this; + } + + StringSwitch& StartsWith(StringLiteral S, T Value) { + if (!Result && Str.startswith(S)) { + Result = std::move(Value); + } + return *this; + } + + StringSwitch &Cases(StringLiteral S0, StringLiteral S1, T Value) { + return Case(S0, Value).Case(S1, Value); + } + + StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, + T Value) { + return Case(S0, Value).Cases(S1, S2, Value); + } + + StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, + StringLiteral S3, T Value) { + return Case(S0, Value).Cases(S1, S2, S3, Value); + } + + StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, + StringLiteral S3, StringLiteral S4, T Value) { + return Case(S0, Value).Cases(S1, S2, S3, S4, Value); + } + + StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, + StringLiteral S3, StringLiteral S4, StringLiteral S5, + T Value) { + return Case(S0, Value).Cases(S1, S2, S3, S4, S5, Value); + } + + StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, + StringLiteral S3, StringLiteral S4, StringLiteral S5, + StringLiteral S6, T Value) { + return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, Value); + } + + StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, + StringLiteral S3, StringLiteral S4, StringLiteral S5, + StringLiteral S6, StringLiteral S7, T Value) { + return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, Value); + } + + StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, + StringLiteral S3, StringLiteral S4, StringLiteral S5, + StringLiteral S6, StringLiteral S7, StringLiteral S8, + T Value) { + return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, S8, Value); + } + + StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, + StringLiteral S3, StringLiteral S4, StringLiteral S5, + StringLiteral S6, StringLiteral S7, StringLiteral S8, + StringLiteral S9, T Value) { + return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, S8, S9, Value); + } + + // Case-insensitive case matchers. + StringSwitch &CaseLower(StringLiteral S, T Value) { + if (!Result && Str.equals_lower(S)) + Result = std::move(Value); + + return *this; + } + + StringSwitch &EndsWithLower(StringLiteral S, T Value) { + if (!Result && Str.endswith_lower(S)) + Result = Value; + + return *this; + } + + StringSwitch &StartsWithLower(StringLiteral S, T Value) { + if (!Result && Str.startswith_lower(S)) + Result = std::move(Value); + + return *this; + } + + StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, T Value) { + return CaseLower(S0, Value).CaseLower(S1, Value); + } + + StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2, + T Value) { + return CaseLower(S0, Value).CasesLower(S1, S2, Value); + } + + StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2, + StringLiteral S3, T Value) { + return CaseLower(S0, Value).CasesLower(S1, S2, S3, Value); + } + + StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2, + StringLiteral S3, StringLiteral S4, T Value) { + return CaseLower(S0, Value).CasesLower(S1, S2, S3, S4, Value); + } + + LLVM_NODISCARD + R Default(T Value) { + if (Result) + return std::move(*Result); + return Value; + } + + LLVM_NODISCARD + operator R() { + assert(Result && "Fell off the end of a string-switch"); + return std::move(*Result); + } +}; + +} // end namespace llvm + +#endif // LLVM_ADT_STRINGSWITCH_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/TinyPtrVector.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/TinyPtrVector.h new file mode 100644 index 0000000..6b76d35 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/TinyPtrVector.h
@@ -0,0 +1,358 @@ +//===- llvm/ADT/TinyPtrVector.h - 'Normally tiny' vectors -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_TINYPTRVECTOR_H +#define LLVM_ADT_TINYPTRVECTOR_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/SmallVector.h" +#include <cassert> +#include <cstddef> +#include <iterator> +#include <type_traits> + +namespace llvm { + +/// TinyPtrVector - This class is specialized for cases where there are +/// normally 0 or 1 element in a vector, but is general enough to go beyond that +/// when required. +/// +/// NOTE: This container doesn't allow you to store a null pointer into it. +/// +template <typename EltTy> +class TinyPtrVector { +public: + using VecTy = SmallVector<EltTy, 4>; + using value_type = typename VecTy::value_type; + // EltTy must be the first pointer type so that is<EltTy> is true for the + // default-constructed PtrUnion. This allows an empty TinyPtrVector to + // naturally vend a begin/end iterator of type EltTy* without an additional + // check for the empty state. + using PtrUnion = PointerUnion<EltTy, VecTy *>; + +private: + PtrUnion Val; + +public: + TinyPtrVector() = default; + + ~TinyPtrVector() { + if (VecTy *V = Val.template dyn_cast<VecTy*>()) + delete V; + } + + TinyPtrVector(const TinyPtrVector &RHS) : Val(RHS.Val) { + if (VecTy *V = Val.template dyn_cast<VecTy*>()) + Val = new VecTy(*V); + } + + TinyPtrVector &operator=(const TinyPtrVector &RHS) { + if (this == &RHS) + return *this; + if (RHS.empty()) { + this->clear(); + return *this; + } + + // Try to squeeze into the single slot. If it won't fit, allocate a copied + // vector. + if (Val.template is<EltTy>()) { + if (RHS.size() == 1) + Val = RHS.front(); + else + Val = new VecTy(*RHS.Val.template get<VecTy*>()); + return *this; + } + + // If we have a full vector allocated, try to re-use it. + if (RHS.Val.template is<EltTy>()) { + Val.template get<VecTy*>()->clear(); + Val.template get<VecTy*>()->push_back(RHS.front()); + } else { + *Val.template get<VecTy*>() = *RHS.Val.template get<VecTy*>(); + } + return *this; + } + + TinyPtrVector(TinyPtrVector &&RHS) : Val(RHS.Val) { + RHS.Val = (EltTy)nullptr; + } + + TinyPtrVector &operator=(TinyPtrVector &&RHS) { + if (this == &RHS) + return *this; + if (RHS.empty()) { + this->clear(); + return *this; + } + + // If this vector has been allocated on the heap, re-use it if cheap. If it + // would require more copying, just delete it and we'll steal the other + // side. + if (VecTy *V = Val.template dyn_cast<VecTy*>()) { + if (RHS.Val.template is<EltTy>()) { + V->clear(); + V->push_back(RHS.front()); + RHS.Val = EltTy(); + return *this; + } + delete V; + } + + Val = RHS.Val; + RHS.Val = EltTy(); + return *this; + } + + TinyPtrVector(std::initializer_list<EltTy> IL) + : Val(IL.size() == 0 + ? PtrUnion() + : IL.size() == 1 ? PtrUnion(*IL.begin()) + : PtrUnion(new VecTy(IL.begin(), IL.end()))) {} + + /// Constructor from an ArrayRef. + /// + /// This also is a constructor for individual array elements due to the single + /// element constructor for ArrayRef. + explicit TinyPtrVector(ArrayRef<EltTy> Elts) + : 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 { + if (Val.isNull()) + return None; + if (Val.template is<EltTy>()) + return *Val.getAddrOfPtr1(); + return *Val.template get<VecTy*>(); + } + + // implicit conversion operator to MutableArrayRef. + operator MutableArrayRef<EltTy>() { + if (Val.isNull()) + return None; + if (Val.template is<EltTy>()) + return *Val.getAddrOfPtr1(); + 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. + if (Val.isNull()) return true; + if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) + return Vec->empty(); + return false; + } + + unsigned size() const { + if (empty()) + return 0; + if (Val.template is<EltTy>()) + return 1; + return Val.template get<VecTy*>()->size(); + } + + using iterator = EltTy *; + using const_iterator = const EltTy *; + using reverse_iterator = std::reverse_iterator<iterator>; + using const_reverse_iterator = std::reverse_iterator<const_iterator>; + + iterator begin() { + if (Val.template is<EltTy>()) + return Val.getAddrOfPtr1(); + + return Val.template get<VecTy *>()->begin(); + } + + iterator end() { + if (Val.template is<EltTy>()) + return begin() + (Val.isNull() ? 0 : 1); + + return Val.template get<VecTy *>()->end(); + } + + const_iterator begin() const { + return (const_iterator)const_cast<TinyPtrVector*>(this)->begin(); + } + + const_iterator end() const { + 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 (Val.template is<EltTy>()) { + assert(i == 0 && "tinyvector index out of range"); + return Val.template get<EltTy>(); + } + + assert(i < Val.template get<VecTy*>()->size() && + "tinyvector index out of range"); + return (*Val.template get<VecTy*>())[i]; + } + + EltTy front() const { + assert(!empty() && "vector empty"); + if (Val.template is<EltTy>()) + return Val.template get<EltTy>(); + return Val.template get<VecTy*>()->front(); + } + + EltTy back() const { + assert(!empty() && "vector empty"); + if (Val.template is<EltTy>()) + return Val.template get<EltTy>(); + return Val.template get<VecTy*>()->back(); + } + + void push_back(EltTy NewVal) { + // If we have nothing, add something. + if (Val.isNull()) { + Val = NewVal; + assert(!Val.isNull() && "Can't add a null value"); + return; + } + + // If we have a single value, convert to a vector. + if (Val.template is<EltTy>()) { + EltTy V = Val.template get<EltTy>(); + Val = new VecTy(); + Val.template get<VecTy*>()->push_back(V); + } + + // Add the new value, we know we have a vector. + Val.template get<VecTy*>()->push_back(NewVal); + } + + void pop_back() { + // If we have a single value, convert to empty. + if (Val.template is<EltTy>()) + Val = (EltTy)nullptr; + else if (VecTy *Vec = Val.template get<VecTy*>()) + Vec->pop_back(); + } + + void clear() { + // If we have a single value, convert to empty. + if (Val.template is<EltTy>()) { + Val = EltTy(); + } else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) { + // If we have a vector form, just clear it. + Vec->clear(); + } + // Otherwise, we're already empty. + } + + iterator erase(iterator I) { + assert(I >= begin() && "Iterator to erase is out of bounds."); + assert(I < end() && "Erasing at past-the-end iterator."); + + // If we have a single value, convert to empty. + if (Val.template is<EltTy>()) { + if (I == begin()) + Val = EltTy(); + } else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) { + // multiple items in a vector; just do the erase, there is no + // benefit to collapsing back to a pointer + return Vec->erase(I); + } + return end(); + } + + iterator erase(iterator S, iterator E) { + assert(S >= begin() && "Range to erase is out of bounds."); + assert(S <= E && "Trying to erase invalid range."); + assert(E <= end() && "Trying to erase past the end."); + + if (Val.template is<EltTy>()) { + if (S == begin() && S != E) + Val = EltTy(); + } else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) { + return Vec->erase(S, E); + } + return end(); + } + + iterator insert(iterator I, const EltTy &Elt) { + assert(I >= this->begin() && "Insertion iterator is out of bounds."); + assert(I <= this->end() && "Inserting past the end of the vector."); + if (I == end()) { + push_back(Elt); + return std::prev(end()); + } + assert(!Val.isNull() && "Null value with non-end insert iterator."); + if (Val.template is<EltTy>()) { + EltTy V = Val.template get<EltTy>(); + assert(I == begin()); + Val = Elt; + push_back(V); + return begin(); + } + + return Val.template get<VecTy*>()->insert(I, Elt); + } + + template<typename ItTy> + iterator insert(iterator I, ItTy From, ItTy To) { + assert(I >= this->begin() && "Insertion iterator is out of bounds."); + assert(I <= this->end() && "Inserting past the end of the vector."); + if (From == To) + return I; + + // If we have a single value, convert to a vector. + ptrdiff_t Offset = I - begin(); + if (Val.isNull()) { + if (std::next(From) == To) { + Val = *From; + return begin(); + } + + Val = new VecTy(); + } else if (Val.template is<EltTy>()) { + EltTy V = Val.template get<EltTy>(); + Val = new VecTy(); + Val.template get<VecTy*>()->push_back(V); + } + return Val.template get<VecTy*>()->insert(begin() + Offset, From, To); + } +}; + +} // end namespace llvm + +#endif // LLVM_ADT_TINYPTRVECTOR_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/Triple.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/Triple.h new file mode 100644 index 0000000..76a754d --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/Triple.h
@@ -0,0 +1,892 @@ +//===-- llvm/ADT/Triple.h - Target triple helper class ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_TRIPLE_H +#define LLVM_ADT_TRIPLE_H + +#include "llvm/ADT/Twine.h" + +// Some system headers or GCC predefined macros conflict with identifiers in +// this file. Undefine them here. +#undef NetBSD +#undef mips +#undef sparc + +namespace llvm { + +/// Triple - Helper class for working with autoconf configuration names. For +/// historical reasons, we also call these 'triples' (they used to contain +/// exactly three fields). +/// +/// Configuration names are strings in the canonical form: +/// ARCHITECTURE-VENDOR-OPERATING_SYSTEM +/// or +/// ARCHITECTURE-VENDOR-OPERATING_SYSTEM-ENVIRONMENT +/// +/// This class is used for clients which want to support arbitrary +/// configuration names, but also want to implement certain special +/// behavior for particular configurations. This class isolates the mapping +/// from the components of the configuration name to well known IDs. +/// +/// At its core the Triple class is designed to be a wrapper for a triple +/// string; the constructor does not change or normalize the triple string. +/// Clients that need to handle the non-canonical triples that users often +/// specify should use the normalize method. +/// +/// See autoconf/config.guess for a glimpse into what configuration names +/// look like in practice. +class Triple { +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 + aarch64_32, // AArch64 (little endian) ILP32: aarch64_32 + arc, // ARC: Synopsys ARC + 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, mipsr6 + mipsel, // MIPSEL: mipsel, mipsallegrexe, mipsr6el + mips64, // MIPS64: mips64, mips64r6, mipsn32, mipsn32r6 + mips64el, // MIPS64EL: mips64el, mips64r6el, mipsn32el, mipsn32r6el + msp430, // MSP430: msp430 + ppc, // PPC: powerpc + ppc64, // PPC64: powerpc64, ppu + ppc64le, // PPC64LE: powerpc64le + r600, // R600: AMD GPUs HD2XXX - HD6XXX + amdgcn, // AMDGCN: AMD GCN GPUs + riscv32, // RISC-V (32-bit): riscv32 + riscv64, // RISC-V (64-bit): riscv64 + 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 + tcele, // TCE little endian (http://tce.cs.tut.fi/): tcele + 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 + ve, // NEC SX-Aurora Vector Engine + LastArchType = ve + }; + enum SubArchType { + NoSubArch, + + ARMSubArch_v8_5a, + ARMSubArch_v8_4a, + ARMSubArch_v8_3a, + ARMSubArch_v8_2a, + ARMSubArch_v8_1a, + ARMSubArch_v8, + ARMSubArch_v8r, + ARMSubArch_v8m_baseline, + ARMSubArch_v8m_mainline, + ARMSubArch_v8_1m_mainline, + ARMSubArch_v7, + ARMSubArch_v7em, + ARMSubArch_v7m, + ARMSubArch_v7s, + ARMSubArch_v7k, + ARMSubArch_v7ve, + ARMSubArch_v6, + ARMSubArch_v6m, + ARMSubArch_v6k, + ARMSubArch_v6t2, + ARMSubArch_v5, + ARMSubArch_v5te, + ARMSubArch_v4t, + + KalimbaSubArch_v3, + KalimbaSubArch_v4, + KalimbaSubArch_v5, + + MipsSubArch_r6, + + PPCSubArch_spe + }; + enum VendorType { + UnknownVendor, + + Apple, + PC, + SCEI, + BGP, + BGQ, + Freescale, + IBM, + ImaginationTechnologies, + MipsTechnologies, + NVIDIA, + CSR, + Myriad, + AMD, + Mesa, + SUSE, + OpenEmbedded, + LastVendorType = OpenEmbedded + }; + enum OSType { + UnknownOS, + + Ananas, + CloudABI, + Darwin, + DragonFly, + FreeBSD, + Fuchsia, + IOS, + KFreeBSD, + Linux, + Lv2, // PS3 + MacOSX, + NetBSD, + OpenBSD, + Solaris, + Win32, + Haiku, + Minix, + RTEMS, + NaCl, // Native Client + CNK, // BG/P Compute-Node Kernel + AIX, + CUDA, // NVIDIA CUDA + NVCL, // NVIDIA OpenCL + AMDHSA, // AMD HSA Runtime + PS4, + ELFIAMCU, + TvOS, // Apple tvOS + WatchOS, // Apple watchOS + Mesa3D, + Contiki, + AMDPAL, // AMD PAL Runtime + HermitCore, // HermitCore Unikernel/Multikernel + Hurd, // GNU/Hurd + WASI, // Experimental WebAssembly OS + Emscripten, + LastOSType = Emscripten + }; + enum EnvironmentType { + UnknownEnvironment, + + GNU, + GNUABIN32, + GNUABI64, + GNUEABI, + GNUEABIHF, + GNUX32, + CODE16, + EABI, + EABIHF, + Android, + Musl, + MuslEABI, + MuslEABIHF, + + MSVC, + Itanium, + Cygnus, + CoreCLR, + Simulator, // Simulator variants of other systems, e.g., Apple's iOS + MacABI, // Mac Catalyst variant of Apple's iOS deployment target. + LastEnvironmentType = MacABI + }; + enum ObjectFormatType { + UnknownObjectFormat, + + COFF, + ELF, + MachO, + Wasm, + XCOFF, + }; + +private: + std::string Data; + + /// The parsed arch type. + ArchType Arch; + + /// The parsed subarchitecture type. + SubArchType SubArch; + + /// The parsed vendor type. + VendorType Vendor; + + /// The parsed OS type. + OSType OS; + + /// The parsed Environment type. + EnvironmentType Environment; + + /// The object format type. + ObjectFormatType ObjectFormat; + +public: + /// @name Constructors + /// @{ + + /// Default constructor is the same as an empty string and leaves all + /// triple fields unknown. + Triple() + : Data(), Arch(), SubArch(), Vendor(), OS(), Environment(), + ObjectFormat() {} + + explicit Triple(const Twine &Str); + Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr); + Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr, + const Twine &EnvironmentStr); + + bool operator==(const Triple &Other) const { + return Arch == Other.Arch && SubArch == Other.SubArch && + Vendor == Other.Vendor && OS == Other.OS && + Environment == Other.Environment && + ObjectFormat == Other.ObjectFormat; + } + + bool operator!=(const Triple &Other) const { + return !(*this == Other); + } + + /// @} + /// @name Normalization + /// @{ + + /// normalize - Turn an arbitrary machine specification into the canonical + /// triple form (or something sensible that the Triple class understands if + /// nothing better can reasonably be done). In particular, it handles the + /// common case in which otherwise valid components are in the wrong order. + static std::string normalize(StringRef Str); + + /// Return the normalized form of this triple's string. + std::string normalize() const { return normalize(Data); } + + /// @} + /// @name Typed Component Access + /// @{ + + /// getArch - Get the parsed architecture type of this triple. + ArchType getArch() const { return Arch; } + + /// getSubArch - get the parsed subarchitecture type for this triple. + SubArchType getSubArch() const { return SubArch; } + + /// getVendor - Get the parsed vendor type of this triple. + VendorType getVendor() const { return Vendor; } + + /// getOS - Get the parsed operating system type of this triple. + OSType getOS() const { return OS; } + + /// hasEnvironment - Does this triple have the optional environment + /// (fourth) component? + bool hasEnvironment() const { + return getEnvironmentName() != ""; + } + + /// getEnvironment - Get the parsed environment type of this triple. + EnvironmentType getEnvironment() const { return Environment; } + + /// Parse the version number from the OS name component of the + /// triple, if present. + /// + /// For example, "fooos1.2.3" would return (1, 2, 3). + /// + /// If an entry is not defined, it will be returned as 0. + void getEnvironmentVersion(unsigned &Major, unsigned &Minor, + unsigned &Micro) const; + + /// getFormat - Get the object format for this triple. + ObjectFormatType getObjectFormat() const { return ObjectFormat; } + + /// getOSVersion - Parse the version number from the OS name component of the + /// triple, if present. + /// + /// For example, "fooos1.2.3" would return (1, 2, 3). + /// + /// If an entry is not defined, it will be returned as 0. + void getOSVersion(unsigned &Major, unsigned &Minor, unsigned &Micro) const; + + /// getOSMajorVersion - Return just the major version number, this is + /// specialized because it is a common query. + unsigned getOSMajorVersion() const { + unsigned Maj, Min, Micro; + getOSVersion(Maj, Min, Micro); + return Maj; + } + + /// getMacOSXVersion - Parse the version number as with getOSVersion and then + /// translate generic "darwin" versions to the corresponding OS X versions. + /// This may also be called with IOS triples but the OS X version number is + /// just set to a constant 10.4.0 in that case. Returns true if successful. + bool getMacOSXVersion(unsigned &Major, unsigned &Minor, + unsigned &Micro) const; + + /// getiOSVersion - Parse the version number as with getOSVersion. This should + /// only be called with IOS or generic triples. + void getiOSVersion(unsigned &Major, unsigned &Minor, + unsigned &Micro) const; + + /// getWatchOSVersion - Parse the version number as with getOSVersion. This + /// should only be called with WatchOS or generic triples. + void getWatchOSVersion(unsigned &Major, unsigned &Minor, + unsigned &Micro) const; + + /// @} + /// @name Direct Component Access + /// @{ + + const std::string &str() const { return Data; } + + const std::string &getTriple() const { return Data; } + + /// getArchName - Get the architecture (first) component of the + /// triple. + StringRef getArchName() const; + + /// getVendorName - Get the vendor (second) component of the triple. + StringRef getVendorName() const; + + /// getOSName - Get the operating system (third) component of the + /// triple. + StringRef getOSName() const; + + /// getEnvironmentName - Get the optional environment (fourth) + /// component of the triple, or "" if empty. + StringRef getEnvironmentName() const; + + /// getOSAndEnvironmentName - Get the operating system and optional + /// environment components as a single string (separated by a '-' + /// if the environment component is present). + StringRef getOSAndEnvironmentName() const; + + /// @} + /// @name Convenience Predicates + /// @{ + + /// Test whether the architecture is 64-bit + /// + /// Note that this tests for 64-bit pointer width, and nothing else. Note + /// that we intentionally expose only three predicates, 64-bit, 32-bit, and + /// 16-bit. The inner details of pointer width for particular architectures + /// is not summed up in the triple, and so only a coarse grained predicate + /// system is provided. + bool isArch64Bit() const; + + /// Test whether the architecture is 32-bit + /// + /// Note that this tests for 32-bit pointer width, and nothing else. + bool isArch32Bit() const; + + /// Test whether the architecture is 16-bit + /// + /// Note that this tests for 16-bit pointer width, and nothing else. + bool isArch16Bit() const; + + /// isOSVersionLT - Helper function for doing comparisons against version + /// numbers included in the target triple. + bool isOSVersionLT(unsigned Major, unsigned Minor = 0, + unsigned Micro = 0) const { + unsigned LHS[3]; + getOSVersion(LHS[0], LHS[1], LHS[2]); + + if (LHS[0] != Major) + return LHS[0] < Major; + if (LHS[1] != Minor) + return LHS[1] < Minor; + if (LHS[2] != Micro) + return LHS[2] < Micro; + + return false; + } + + bool isOSVersionLT(const Triple &Other) const { + unsigned RHS[3]; + Other.getOSVersion(RHS[0], RHS[1], RHS[2]); + return isOSVersionLT(RHS[0], RHS[1], RHS[2]); + } + + /// isMacOSXVersionLT - Comparison function for checking OS X version + /// compatibility, which handles supporting skewed version numbering schemes + /// used by the "darwin" triples. + 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. + if (getOS() == Triple::MacOSX) + return isOSVersionLT(Major, Minor, Micro); + + // Otherwise, compare to the "Darwin" number. + assert(Major == 10 && "Unexpected major version"); + return isOSVersionLT(Minor + 4, Micro, 0); + } + + /// isMacOSX - Is this a Mac OS X triple. For legacy reasons, we support both + /// "darwin" and "osx" as OS X triples. + bool isMacOSX() const { + return getOS() == Triple::Darwin || getOS() == Triple::MacOSX; + } + + /// Is this an iOS triple. + /// Note: This identifies tvOS as a variant of iOS. If that ever + /// changes, i.e., if the two operating systems diverge or their version + /// numbers get out of sync, that will need to be changed. + /// watchOS has completely different version numbers so it is not included. + bool isiOS() const { + return getOS() == Triple::IOS || isTvOS(); + } + + /// Is this an Apple tvOS triple. + bool isTvOS() const { + return getOS() == Triple::TvOS; + } + + /// Is this an Apple watchOS triple. + bool isWatchOS() const { + return getOS() == Triple::WatchOS; + } + + bool isWatchABI() const { + return getSubArch() == Triple::ARMSubArch_v7k; + } + + /// isOSDarwin - Is this a "Darwin" OS (macOS, iOS, tvOS or watchOS). + bool isOSDarwin() const { + return isMacOSX() || isiOS() || isWatchOS(); + } + + bool isSimulatorEnvironment() const { + return getEnvironment() == Triple::Simulator; + } + + bool isMacCatalystEnvironment() const { + return getEnvironment() == Triple::MacABI; + } + + bool isOSNetBSD() const { + return getOS() == Triple::NetBSD; + } + + bool isOSOpenBSD() const { + return getOS() == Triple::OpenBSD; + } + + bool isOSFreeBSD() const { + return getOS() == Triple::FreeBSD; + } + + bool isOSFuchsia() const { + return getOS() == Triple::Fuchsia; + } + + bool isOSDragonFly() const { return getOS() == Triple::DragonFly; } + + bool isOSSolaris() const { + return getOS() == Triple::Solaris; + } + + bool isOSIAMCU() const { + return getOS() == Triple::ELFIAMCU; + } + + bool isOSUnknown() const { return getOS() == Triple::UnknownOS; } + + bool isGNUEnvironment() const { + EnvironmentType Env = getEnvironment(); + return Env == Triple::GNU || Env == Triple::GNUABIN32 || + Env == Triple::GNUABI64 || Env == Triple::GNUEABI || + Env == Triple::GNUEABIHF || Env == Triple::GNUX32; + } + + bool isOSContiki() const { + return getOS() == Triple::Contiki; + } + + /// Tests whether the OS is Haiku. + bool isOSHaiku() const { + return getOS() == Triple::Haiku; + } + + /// Tests whether the OS is Windows. + bool isOSWindows() const { + return getOS() == Triple::Win32; + } + + /// Checks if the environment is MSVC. + bool isKnownWindowsMSVCEnvironment() const { + return isOSWindows() && getEnvironment() == Triple::MSVC; + } + + /// Checks if the environment could be MSVC. + bool isWindowsMSVCEnvironment() const { + return isKnownWindowsMSVCEnvironment() || + (isOSWindows() && getEnvironment() == Triple::UnknownEnvironment); + } + + bool isWindowsCoreCLREnvironment() const { + return isOSWindows() && getEnvironment() == Triple::CoreCLR; + } + + bool isWindowsItaniumEnvironment() const { + return isOSWindows() && getEnvironment() == Triple::Itanium; + } + + bool isWindowsCygwinEnvironment() const { + return isOSWindows() && getEnvironment() == Triple::Cygnus; + } + + bool isWindowsGNUEnvironment() const { + return isOSWindows() && getEnvironment() == Triple::GNU; + } + + /// Tests for either Cygwin or MinGW OS + bool isOSCygMing() const { + return isWindowsCygwinEnvironment() || isWindowsGNUEnvironment(); + } + + /// Is this a "Windows" OS targeting a "MSVCRT.dll" environment. + bool isOSMSVCRT() const { + return isWindowsMSVCEnvironment() || isWindowsGNUEnvironment() || + isWindowsItaniumEnvironment(); + } + + /// Tests whether the OS is NaCl (Native Client) + bool isOSNaCl() const { + return getOS() == Triple::NaCl; + } + + /// Tests whether the OS is Linux. + bool isOSLinux() const { + return getOS() == Triple::Linux; + } + + /// Tests whether the OS is kFreeBSD. + bool isOSKFreeBSD() const { + return getOS() == Triple::KFreeBSD; + } + + /// Tests whether the OS is Hurd. + bool isOSHurd() const { + return getOS() == Triple::Hurd; + } + + /// Tests whether the OS is WASI. + bool isOSWASI() const { + return getOS() == Triple::WASI; + } + + /// Tests whether the OS is Emscripten. + bool isOSEmscripten() const { + return getOS() == Triple::Emscripten; + } + + /// Tests whether the OS uses glibc. + bool isOSGlibc() const { + return (getOS() == Triple::Linux || getOS() == Triple::KFreeBSD || + getOS() == Triple::Hurd) && + !isAndroid(); + } + + /// Tests whether the OS is AIX. + bool isOSAIX() const { + return getOS() == Triple::AIX; + } + + /// Tests whether the OS uses the ELF binary format. + bool isOSBinFormatELF() const { + return getObjectFormat() == Triple::ELF; + } + + /// Tests whether the OS uses the COFF binary format. + bool isOSBinFormatCOFF() const { + return getObjectFormat() == Triple::COFF; + } + + /// Tests whether the environment is MachO. + bool isOSBinFormatMachO() const { + return getObjectFormat() == Triple::MachO; + } + + /// Tests whether the OS uses the Wasm binary format. + bool isOSBinFormatWasm() const { + return getObjectFormat() == Triple::Wasm; + } + + /// Tests whether the OS uses the XCOFF binary format. + bool isOSBinFormatXCOFF() const { + return getObjectFormat() == Triple::XCOFF; + } + + /// Tests whether the target is the PS4 CPU + bool isPS4CPU() const { + return getArch() == Triple::x86_64 && + getVendor() == Triple::SCEI && + getOS() == Triple::PS4; + } + + /// Tests whether the target is the PS4 platform + bool isPS4() const { + return getVendor() == Triple::SCEI && + getOS() == Triple::PS4; + } + + /// Tests whether the target is Android + bool isAndroid() const { return getEnvironment() == Triple::Android; } + + bool isAndroidVersionLT(unsigned Major) const { + assert(isAndroid() && "Not an Android triple!"); + + unsigned Env[3]; + getEnvironmentVersion(Env[0], Env[1], Env[2]); + + // 64-bit targets did not exist before API level 21 (Lollipop). + if (isArch64Bit() && Env[0] < 21) + Env[0] = 21; + + return Env[0] < Major; + } + + /// 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 SPIR (32- or 64-bit). + bool isSPIR() const { + return getArch() == Triple::spir || getArch() == Triple::spir64; + } + + /// Tests whether the target is NVPTX (32- or 64-bit). + bool isNVPTX() const { + return getArch() == Triple::nvptx || getArch() == Triple::nvptx64; + } + + /// Tests whether the target is Thumb (little and big endian). + bool isThumb() const { + return getArch() == Triple::thumb || getArch() == Triple::thumbeb; + } + + /// Tests whether the target is ARM (little and big endian). + bool isARM() const { + return getArch() == Triple::arm || getArch() == Triple::armeb; + } + + /// Tests whether the target is AArch64 (little and big endian). + bool isAArch64() const { + return getArch() == Triple::aarch64 || getArch() == Triple::aarch64_be; + } + + /// Tests whether the target is MIPS 32-bit (little and big endian). + bool isMIPS32() const { + return getArch() == Triple::mips || getArch() == Triple::mipsel; + } + + /// Tests whether the target is MIPS 64-bit (little and big endian). + bool isMIPS64() const { + return getArch() == Triple::mips64 || getArch() == Triple::mips64el; + } + + /// Tests whether the target is MIPS (little and big endian, 32- or 64-bit). + bool isMIPS() const { + return isMIPS32() || isMIPS64(); + } + + /// Tests whether the target is 64-bit PowerPC (little and big endian). + bool isPPC64() const { + return getArch() == Triple::ppc64 || getArch() == Triple::ppc64le; + } + + /// Tests whether the target is RISC-V (32- and 64-bit). + bool isRISCV() const { + return getArch() == Triple::riscv32 || getArch() == Triple::riscv64; + } + + /// Tests whether the target is x86 (32- or 64-bit). + bool isX86() const { + return getArch() == Triple::x86 || getArch() == Triple::x86_64; + } + + /// Tests whether the target is VE + bool isVE() const { + return getArch() == Triple::ve; + } + + /// Tests whether the target supports comdat + bool supportsCOMDAT() const { + return !isOSBinFormatMachO(); + } + + /// Tests whether the target uses emulated TLS as default. + bool hasDefaultEmulatedTLS() const { + return isAndroid() || isOSOpenBSD() || isWindowsCygwinEnvironment(); + } + + /// @} + /// @name Mutators + /// @{ + + /// setArch - Set the architecture (first) component of the triple + /// to a known type. + void setArch(ArchType Kind); + + /// setVendor - Set the vendor (second) component of the triple to a + /// known type. + void setVendor(VendorType Kind); + + /// setOS - Set the operating system (third) component of the triple + /// to a known type. + void setOS(OSType Kind); + + /// setEnvironment - Set the environment (fourth) component of the triple + /// to a known type. + void setEnvironment(EnvironmentType Kind); + + /// setObjectFormat - Set the object file format + void setObjectFormat(ObjectFormatType Kind); + + /// setTriple - Set all components to the new triple \p Str. + void setTriple(const Twine &Str); + + /// setArchName - Set the architecture (first) component of the + /// triple by name. + void setArchName(StringRef Str); + + /// setVendorName - Set the vendor (second) component of the triple + /// by name. + void setVendorName(StringRef Str); + + /// setOSName - Set the operating system (third) component of the + /// triple by name. + void setOSName(StringRef Str); + + /// setEnvironmentName - Set the optional environment (fourth) + /// component of the triple by name. + void setEnvironmentName(StringRef Str); + + /// setOSAndEnvironmentName - Set the operating system and optional + /// environment components with a single string. + void setOSAndEnvironmentName(StringRef Str); + + /// @} + /// @name Helpers to build variants of a particular triple. + /// @{ + + /// Form a triple with a 32-bit variant of the current architecture. + /// + /// This can be used to move across "families" of architectures where useful. + /// + /// \returns A new triple with a 32-bit architecture or an unknown + /// architecture if no such variant can be found. + llvm::Triple get32BitArchVariant() const; + + /// Form a triple with a 64-bit variant of the current architecture. + /// + /// This can be used to move across "families" of architectures where useful. + /// + /// \returns A new triple with a 64-bit architecture or an unknown + /// architecture if no such variant can be found. + llvm::Triple get64BitArchVariant() const; + + /// Form a triple with a big endian variant of the current architecture. + /// + /// This can be used to move across "families" of architectures where useful. + /// + /// \returns A new triple with a big endian architecture or an unknown + /// architecture if no such variant can be found. + llvm::Triple getBigEndianArchVariant() const; + + /// Form a triple with a little endian variant of the current architecture. + /// + /// This can be used to move across "families" of architectures where useful. + /// + /// \returns A new triple with a little endian architecture or an unknown + /// architecture if no such variant can be found. + llvm::Triple getLittleEndianArchVariant() const; + + /// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting. + /// + /// \param Arch the architecture name (e.g., "armv7s"). If it is an empty + /// string then the triple's arch name is used. + 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; + + /// Test whether target triples are compatible. + bool isCompatibleWith(const Triple &Other) const; + + /// Merge target triples. + std::string merge(const Triple &Other) const; + + /// @} + /// @name Static helpers for IDs. + /// @{ + + /// getArchTypeName - Get the canonical name for the \p Kind architecture. + static StringRef getArchTypeName(ArchType Kind); + + /// getArchTypePrefix - Get the "prefix" canonical name for the \p Kind + /// architecture. This is the prefix used by the architecture specific + /// builtins, and is suitable for passing to \see + /// Intrinsic::getIntrinsicForGCCBuiltin(). + /// + /// \return - The architecture prefix, or 0 if none is defined. + static StringRef getArchTypePrefix(ArchType Kind); + + /// getVendorTypeName - Get the canonical name for the \p Kind vendor. + static StringRef getVendorTypeName(VendorType Kind); + + /// getOSTypeName - Get the canonical name for the \p Kind operating system. + static StringRef getOSTypeName(OSType Kind); + + /// getEnvironmentTypeName - Get the canonical name for the \p Kind + /// environment. + static StringRef getEnvironmentTypeName(EnvironmentType Kind); + + /// @} + /// @name Static helpers for converting alternate architecture names. + /// @{ + + /// getArchTypeForLLVMName - The canonical type for the given LLVM + /// architecture name (e.g., "x86"). + static ArchType getArchTypeForLLVMName(StringRef Str); + + /// @} +}; + +} // End llvm namespace + + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/Twine.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/Twine.h new file mode 100644 index 0000000..2dc7486 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/Twine.h
@@ -0,0 +1,544 @@ +//===- Twine.h - Fast Temporary String Concatenation ------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_TWINE_H +#define LLVM_ADT_TWINE_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/ErrorHandling.h" +#include <cassert> +#include <cstdint> +#include <string> + +namespace llvm { + + class formatv_object_base; + class raw_ostream; + + /// Twine - A lightweight data structure for efficiently representing the + /// concatenation of temporary values as strings. + /// + /// A Twine is a kind of rope, it represents a concatenated string using a + /// binary-tree, where the string is the preorder of the nodes. Since the + /// Twine can be efficiently rendered into a buffer when its result is used, + /// it avoids the cost of generating temporary values for intermediate string + /// results -- particularly in cases when the Twine result is never + /// required. By explicitly tracking the type of leaf nodes, we can also avoid + /// the creation of temporary strings for conversions operations (such as + /// appending an integer to a string). + /// + /// A Twine is not intended for use directly and should not be stored, its + /// implementation relies on the ability to store pointers to temporary stack + /// objects which may be deallocated at the end of a statement. Twines should + /// only be used accepted as const references in arguments, when an API wishes + /// to accept possibly-concatenated strings. + /// + /// Twines support a special 'null' value, which always concatenates to form + /// itself, and renders as an empty string. This can be returned from APIs to + /// effectively nullify any concatenations performed on the result. + /// + /// \b Implementation + /// + /// Given the nature of a Twine, it is not possible for the Twine's + /// concatenation method to construct interior nodes; the result must be + /// represented inside the returned value. For this reason a Twine object + /// actually holds two values, the left- and right-hand sides of a + /// concatenation. We also have nullary Twine objects, which are effectively + /// sentinel values that represent empty strings. + /// + /// Thus, a Twine can effectively have zero, one, or two children. The \see + /// isNullary(), \see isUnary(), and \see isBinary() predicates exist for + /// testing the number of children. + /// + /// We maintain a number of invariants on Twine objects (FIXME: Why): + /// - Nullary twines are always represented with their Kind on the left-hand + /// side, and the Empty kind on the right-hand side. + /// - Unary twines are always represented with the value on the left-hand + /// side, and the Empty kind on the right-hand side. + /// - If a Twine has another Twine as a child, that child should always be + /// binary (otherwise it could have been folded into the parent). + /// + /// These invariants are check by \see isValid(). + /// + /// \b Efficiency Considerations + /// + /// The Twine is designed to yield efficient and small code for common + /// situations. For this reason, the concat() method is inlined so that + /// concatenations of leaf nodes can be optimized into stores directly into a + /// single stack allocated object. + /// + /// In practice, not all compilers can be trusted to optimize concat() fully, + /// so we provide two additional methods (and accompanying operator+ + /// overloads) to guarantee that particularly important cases (cstring plus + /// StringRef) codegen as desired. + class Twine { + /// NodeKind - Represent the type of an argument. + enum NodeKind : unsigned char { + /// An empty string; the result of concatenating anything with it is also + /// empty. + NullKind, + + /// The empty string. + EmptyKind, + + /// A pointer to a Twine instance. + TwineKind, + + /// A pointer to a C string instance. + CStringKind, + + /// A pointer to an std::string instance. + StdStringKind, + + /// A pointer to a StringRef instance. + StringRefKind, + + /// A pointer to a SmallString instance. + SmallStringKind, + + /// A pointer to a formatv_object_base instance. + FormatvObjectKind, + + /// A char value, to render as a character. + CharKind, + + /// An unsigned int value, to render as an unsigned decimal integer. + DecUIKind, + + /// An int value, to render as a signed decimal integer. + DecIKind, + + /// A pointer to an unsigned long value, to render as an unsigned decimal + /// integer. + DecULKind, + + /// A pointer to a long value, to render as a signed decimal integer. + DecLKind, + + /// A pointer to an unsigned long long value, to render as an unsigned + /// decimal integer. + DecULLKind, + + /// A pointer to a long long value, to render as a signed decimal integer. + DecLLKind, + + /// A pointer to a uint64_t value, to render as an unsigned hexadecimal + /// integer. + UHexKind + }; + + union Child + { + const Twine *twine; + const char *cString; + const std::string *stdString; + const StringRef *stringRef; + const SmallVectorImpl<char> *smallString; + const formatv_object_base *formatvObject; + char character; + unsigned int decUI; + int decI; + const unsigned long *decUL; + const long *decL; + const unsigned long long *decULL; + const long long *decLL; + const uint64_t *uHex; + }; + + /// LHS - The prefix in the concatenation, which may be uninitialized for + /// Null or Empty kinds. + Child LHS = {0}; + + /// RHS - The suffix in the concatenation, which may be uninitialized for + /// Null or Empty kinds. + Child RHS = {0}; + + /// LHSKind - The NodeKind of the left hand side, \see getLHSKind(). + NodeKind LHSKind = EmptyKind; + + /// RHSKind - The NodeKind of the right hand side, \see getRHSKind(). + NodeKind RHSKind = EmptyKind; + + /// Construct a nullary twine; the kind must be NullKind or EmptyKind. + explicit Twine(NodeKind Kind) : LHSKind(Kind) { + assert(isNullary() && "Invalid kind!"); + } + + /// Construct a binary twine. + explicit Twine(const Twine &LHS, const Twine &RHS) + : LHSKind(TwineKind), RHSKind(TwineKind) { + this->LHS.twine = &LHS; + this->RHS.twine = &RHS; + assert(isValid() && "Invalid twine!"); + } + + /// Construct a twine from explicit values. + explicit Twine(Child LHS, NodeKind LHSKind, Child RHS, NodeKind RHSKind) + : LHS(LHS), RHS(RHS), LHSKind(LHSKind), RHSKind(RHSKind) { + assert(isValid() && "Invalid twine!"); + } + + /// Check for the null twine. + bool isNull() const { + return getLHSKind() == NullKind; + } + + /// Check for the empty twine. + bool isEmpty() const { + return getLHSKind() == EmptyKind; + } + + /// Check if this is a nullary twine (null or empty). + bool isNullary() const { + return isNull() || isEmpty(); + } + + /// Check if this is a unary twine. + bool isUnary() const { + return getRHSKind() == EmptyKind && !isNullary(); + } + + /// Check if this is a binary twine. + bool isBinary() const { + return getLHSKind() != NullKind && getRHSKind() != EmptyKind; + } + + /// Check if this is a valid twine (satisfying the invariants on + /// order and number of arguments). + bool isValid() const { + // Nullary twines always have Empty on the RHS. + if (isNullary() && getRHSKind() != EmptyKind) + return false; + + // Null should never appear on the RHS. + if (getRHSKind() == NullKind) + return false; + + // The RHS cannot be non-empty if the LHS is empty. + if (getRHSKind() != EmptyKind && getLHSKind() == EmptyKind) + return false; + + // A twine child should always be binary. + if (getLHSKind() == TwineKind && + !LHS.twine->isBinary()) + return false; + if (getRHSKind() == TwineKind && + !RHS.twine->isBinary()) + return false; + + return true; + } + + /// Get the NodeKind of the left-hand side. + NodeKind getLHSKind() const { return LHSKind; } + + /// Get the NodeKind of the right-hand side. + NodeKind getRHSKind() const { return RHSKind; } + + /// Print one child from a twine. + void printOneChild(raw_ostream &OS, Child Ptr, NodeKind Kind) const; + + /// Print the representation of one child from a twine. + void printOneChildRepr(raw_ostream &OS, Child Ptr, + NodeKind Kind) const; + + public: + /// @name Constructors + /// @{ + + /// Construct from an empty string. + /*implicit*/ Twine() { + assert(isValid() && "Invalid twine!"); + } + + Twine(const Twine &) = default; + + /// Construct from a C string. + /// + /// We take care here to optimize "" into the empty twine -- this will be + /// optimized out for string constants. This allows Twine arguments have + /// default "" values, without introducing unnecessary string constants. + /*implicit*/ Twine(const char *Str) { + if (Str[0] != '\0') { + LHS.cString = Str; + LHSKind = CStringKind; + } else + LHSKind = EmptyKind; + + assert(isValid() && "Invalid twine!"); + } + /// Delete the implicit conversion from nullptr as Twine(const char *) + /// cannot take nullptr. + /*implicit*/ Twine(std::nullptr_t) = delete; + + /// Construct from an std::string. + /*implicit*/ Twine(const std::string &Str) : LHSKind(StdStringKind) { + LHS.stdString = &Str; + assert(isValid() && "Invalid twine!"); + } + + /// Construct from a StringRef. + /*implicit*/ Twine(const StringRef &Str) : LHSKind(StringRefKind) { + LHS.stringRef = &Str; + assert(isValid() && "Invalid twine!"); + } + + /// Construct from a SmallString. + /*implicit*/ Twine(const SmallVectorImpl<char> &Str) + : LHSKind(SmallStringKind) { + LHS.smallString = &Str; + assert(isValid() && "Invalid twine!"); + } + + /// Construct from a formatv_object_base. + /*implicit*/ Twine(const formatv_object_base &Fmt) + : LHSKind(FormatvObjectKind) { + LHS.formatvObject = &Fmt; + assert(isValid() && "Invalid twine!"); + } + + /// Construct from a char. + explicit Twine(char Val) : LHSKind(CharKind) { + LHS.character = Val; + } + + /// Construct from a signed char. + explicit Twine(signed char Val) : LHSKind(CharKind) { + LHS.character = static_cast<char>(Val); + } + + /// Construct from an unsigned char. + explicit Twine(unsigned char Val) : LHSKind(CharKind) { + LHS.character = static_cast<char>(Val); + } + + /// Construct a twine to print \p Val as an unsigned decimal integer. + explicit Twine(unsigned Val) : LHSKind(DecUIKind) { + LHS.decUI = Val; + } + + /// Construct a twine to print \p Val as a signed decimal integer. + explicit Twine(int Val) : LHSKind(DecIKind) { + LHS.decI = Val; + } + + /// Construct a twine to print \p Val as an unsigned decimal integer. + explicit Twine(const unsigned long &Val) : LHSKind(DecULKind) { + LHS.decUL = &Val; + } + + /// Construct a twine to print \p Val as a signed decimal integer. + explicit Twine(const long &Val) : LHSKind(DecLKind) { + LHS.decL = &Val; + } + + /// Construct a twine to print \p Val as an unsigned decimal integer. + explicit Twine(const unsigned long long &Val) : LHSKind(DecULLKind) { + LHS.decULL = &Val; + } + + /// Construct a twine to print \p Val as a signed decimal integer. + explicit Twine(const long long &Val) : LHSKind(DecLLKind) { + LHS.decLL = &Val; + } + + // FIXME: Unfortunately, to make sure this is as efficient as possible we + // need extra binary constructors from particular types. We can't rely on + // the compiler to be smart enough to fold operator+()/concat() down to the + // right thing. Yet. + + /// Construct as the concatenation of a C string and a StringRef. + /*implicit*/ Twine(const char *LHS, const StringRef &RHS) + : LHSKind(CStringKind), RHSKind(StringRefKind) { + this->LHS.cString = LHS; + this->RHS.stringRef = &RHS; + assert(isValid() && "Invalid twine!"); + } + + /// Construct as the concatenation of a StringRef and a C string. + /*implicit*/ Twine(const StringRef &LHS, const char *RHS) + : LHSKind(StringRefKind), RHSKind(CStringKind) { + this->LHS.stringRef = &LHS; + this->RHS.cString = RHS; + assert(isValid() && "Invalid twine!"); + } + + /// Since the intended use of twines is as temporary objects, assignments + /// when concatenating might cause undefined behavior or stack corruptions + Twine &operator=(const Twine &) = delete; + + /// Create a 'null' string, which is an empty string that always + /// concatenates to form another empty string. + static Twine createNull() { + return Twine(NullKind); + } + + /// @} + /// @name Numeric Conversions + /// @{ + + // Construct a twine to print \p Val as an unsigned hexadecimal integer. + static Twine utohexstr(const uint64_t &Val) { + Child LHS, RHS; + LHS.uHex = &Val; + RHS.twine = nullptr; + return Twine(LHS, UHexKind, RHS, EmptyKind); + } + + /// @} + /// @name Predicate Operations + /// @{ + + /// Check if this twine is trivially empty; a false return value does not + /// necessarily mean the twine is empty. + bool isTriviallyEmpty() const { + return isNullary(); + } + + /// Return true if this twine can be dynamically accessed as a single + /// StringRef value with getSingleStringRef(). + bool isSingleStringRef() const { + if (getRHSKind() != EmptyKind) return false; + + switch (getLHSKind()) { + case EmptyKind: + case CStringKind: + case StdStringKind: + case StringRefKind: + case SmallStringKind: + return true; + default: + return false; + } + } + + /// @} + /// @name String Operations + /// @{ + + Twine concat(const Twine &Suffix) const; + + /// @} + /// @name Output & Conversion. + /// @{ + + /// Return the twine contents as a std::string. + std::string str() const; + + /// Append the concatenated string into the given SmallString or SmallVector. + void toVector(SmallVectorImpl<char> &Out) const; + + /// This returns the twine as a single StringRef. This method is only valid + /// if isSingleStringRef() is true. + StringRef getSingleStringRef() const { + assert(isSingleStringRef() &&"This cannot be had as a single stringref!"); + switch (getLHSKind()) { + default: llvm_unreachable("Out of sync with isSingleStringRef"); + case EmptyKind: return StringRef(); + case CStringKind: return StringRef(LHS.cString); + case StdStringKind: return StringRef(*LHS.stdString); + case StringRefKind: return *LHS.stringRef; + case SmallStringKind: + return StringRef(LHS.smallString->data(), LHS.smallString->size()); + } + } + + /// This returns the twine as a single StringRef if it can be + /// represented as such. Otherwise the twine is written into the given + /// SmallVector and a StringRef to the SmallVector's data is returned. + StringRef toStringRef(SmallVectorImpl<char> &Out) const { + if (isSingleStringRef()) + return getSingleStringRef(); + toVector(Out); + return StringRef(Out.data(), Out.size()); + } + + /// This returns the twine as a single null terminated StringRef if it + /// can be represented as such. Otherwise the twine is written into the + /// given SmallVector and a StringRef to the SmallVector's data is returned. + /// + /// The returned StringRef's size does not include the null terminator. + StringRef toNullTerminatedStringRef(SmallVectorImpl<char> &Out) const; + + /// Write the concatenated string represented by this twine to the + /// stream \p OS. + void print(raw_ostream &OS) const; + + /// Dump the concatenated string represented by this twine to stderr. + void dump() const; + + /// Write the representation of this twine to the stream \p OS. + void printRepr(raw_ostream &OS) const; + + /// Dump the representation of this twine to stderr. + void dumpRepr() const; + + /// @} + }; + + /// @name Twine Inline Implementations + /// @{ + + inline Twine Twine::concat(const Twine &Suffix) const { + // Concatenation with null is null. + if (isNull() || Suffix.isNull()) + return Twine(NullKind); + + // Concatenation with empty yields the other side. + if (isEmpty()) + return Suffix; + if (Suffix.isEmpty()) + return *this; + + // Otherwise we need to create a new node, taking care to fold in unary + // twines. + Child NewLHS, NewRHS; + NewLHS.twine = this; + NewRHS.twine = &Suffix; + NodeKind NewLHSKind = TwineKind, NewRHSKind = TwineKind; + if (isUnary()) { + NewLHS = LHS; + NewLHSKind = getLHSKind(); + } + if (Suffix.isUnary()) { + NewRHS = Suffix.LHS; + NewRHSKind = Suffix.getLHSKind(); + } + + return Twine(NewLHS, NewLHSKind, NewRHS, NewRHSKind); + } + + inline Twine operator+(const Twine &LHS, const Twine &RHS) { + return LHS.concat(RHS); + } + + /// Additional overload to guarantee simplified codegen; this is equivalent to + /// concat(). + + inline Twine operator+(const char *LHS, const StringRef &RHS) { + return Twine(LHS, RHS); + } + + /// Additional overload to guarantee simplified codegen; this is equivalent to + /// concat(). + + inline Twine operator+(const StringRef &LHS, const char *RHS) { + return Twine(LHS, RHS); + } + + inline raw_ostream &operator<<(raw_ostream &OS, const Twine &RHS) { + RHS.print(OS); + return OS; + } + + /// @} + +} // end namespace llvm + +#endif // LLVM_ADT_TWINE_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/UniqueVector.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/UniqueVector.h new file mode 100644 index 0000000..bfea988 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/UniqueVector.h
@@ -0,0 +1,101 @@ +//===- llvm/ADT/UniqueVector.h ----------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_UNIQUEVECTOR_H +#define LLVM_ADT_UNIQUEVECTOR_H + +#include <cassert> +#include <cstddef> +#include <map> +#include <vector> + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// UniqueVector - This class produces a sequential ID number (base 1) for each +/// unique entry that is added. T is the type of entries in the vector. This +/// class should have an implementation of operator== and of operator<. +/// Entries can be fetched using operator[] with the entry ID. +template<class T> class UniqueVector { +public: + using VectorType = typename std::vector<T>; + using iterator = typename VectorType::iterator; + using const_iterator = typename VectorType::const_iterator; + +private: + // Map - Used to handle the correspondence of entry to ID. + std::map<T, unsigned> Map; + + // Vector - ID ordered vector of entries. Entries can be indexed by ID - 1. + VectorType Vector; + +public: + /// insert - Append entry to the vector if it doesn't already exist. Returns + /// the entry's index + 1 to be used as a unique ID. + unsigned insert(const T &Entry) { + // Check if the entry is already in the map. + unsigned &Val = Map[Entry]; + + // See if entry exists, if so return prior ID. + if (Val) return Val; + + // Compute ID for entry. + Val = static_cast<unsigned>(Vector.size()) + 1; + + // Insert in vector. + Vector.push_back(Entry); + return Val; + } + + /// idFor - return the ID for an existing entry. Returns 0 if the entry is + /// not found. + unsigned idFor(const T &Entry) const { + // Search for entry in the map. + typename std::map<T, unsigned>::const_iterator MI = Map.find(Entry); + + // See if entry exists, if so return ID. + if (MI != Map.end()) return MI->second; + + // No luck. + return 0; + } + + /// operator[] - Returns a reference to the entry with the specified ID. + const T &operator[](unsigned ID) const { + assert(ID-1 < size() && "ID is 0 or out of range!"); + return Vector[ID - 1]; + } + + /// Return an iterator to the start of the vector. + iterator begin() { return Vector.begin(); } + + /// Return an iterator to the start of the vector. + const_iterator begin() const { return Vector.begin(); } + + /// Return an iterator to the end of the vector. + iterator end() { return Vector.end(); } + + /// Return an iterator to the end of the vector. + const_iterator end() const { return Vector.end(); } + + /// size - Returns the number of entries in the vector. + size_t size() const { return Vector.size(); } + + /// empty - Returns true if the vector is empty. + bool empty() const { return Vector.empty(); } + + /// reset - Clears all the entries. + void reset() { + Map.clear(); + Vector.resize(0, 0); + } +}; + +} // end namespace llvm + +#endif // LLVM_ADT_UNIQUEVECTOR_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/bit.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/bit.h new file mode 100644 index 0000000..a790d5e --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/bit.h
@@ -0,0 +1,58 @@ +//===-- llvm/ADT/bit.h - C++20 <bit> ----------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the C++20 <bit> header. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_BIT_H +#define LLVM_ADT_BIT_H + +#include "llvm/Support/Compiler.h" +#include <cstring> +#include <type_traits> + +namespace llvm { + +// This implementation of bit_cast is different from the C++17 one in two ways: +// - It isn't constexpr because that requires compiler support. +// - It requires trivially-constructible To, to avoid UB in the implementation. +template <typename To, typename From + , typename = typename std::enable_if<sizeof(To) == sizeof(From)>::type +#if (__has_feature(is_trivially_constructible) && defined(_LIBCPP_VERSION)) || \ + (defined(__GNUC__) && __GNUC__ >= 5) + , typename = typename std::is_trivially_constructible<To>::type +#elif __has_feature(is_trivially_constructible) + , typename = typename std::enable_if<__is_trivially_constructible(To)>::type +#else + // See comment below. +#endif +#if (__has_feature(is_trivially_copyable) && defined(_LIBCPP_VERSION)) || \ + (defined(__GNUC__) && __GNUC__ >= 5) + , typename = typename std::enable_if<std::is_trivially_copyable<To>::value>::type + , typename = typename std::enable_if<std::is_trivially_copyable<From>::value>::type +#elif __has_feature(is_trivially_copyable) + , typename = typename std::enable_if<__is_trivially_copyable(To)>::type + , typename = typename std::enable_if<__is_trivially_copyable(From)>::type +#else +// This case is GCC 4.x. clang with libc++ or libstdc++ never get here. Unlike +// llvm/Support/type_traits.h's is_trivially_copyable we don't want to +// provide a good-enough answer here: developers in that configuration will hit +// compilation failures on the bots instead of locally. That's acceptable +// because it's very few developers, and only until we move past C++11. +#endif +> +inline To bit_cast(const From &from) noexcept { + To to; + std::memcpy(&to, &from, sizeof(To)); + return to; +} + +} // namespace llvm + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/edit_distance.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/edit_distance.h new file mode 100644 index 0000000..4f51340 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/edit_distance.h
@@ -0,0 +1,102 @@ +//===-- llvm/ADT/edit_distance.h - Array edit distance function --- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines a Levenshtein distance function that works for any two +// sequences, with each element of each sequence being analogous to a character +// in a string. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_EDIT_DISTANCE_H +#define LLVM_ADT_EDIT_DISTANCE_H + +#include "llvm/ADT/ArrayRef.h" +#include <algorithm> +#include <memory> + +namespace llvm { + +/// Determine the edit distance between two sequences. +/// +/// \param FromArray the first sequence to compare. +/// +/// \param ToArray the second sequence to compare. +/// +/// \param AllowReplacements whether to allow element replacements (change one +/// element into another) as a single operation, rather than as two operations +/// (an insertion and a removal). +/// +/// \param MaxEditDistance If non-zero, the maximum edit distance that this +/// routine is allowed to compute. If the edit distance will exceed that +/// maximum, returns \c MaxEditDistance+1. +/// +/// \returns the minimum number of element insertions, removals, or (if +/// \p AllowReplacements is \c true) replacements needed to transform one of +/// the given sequences into the other. If zero, the sequences are identical. +template<typename T> +unsigned ComputeEditDistance(ArrayRef<T> FromArray, ArrayRef<T> ToArray, + bool AllowReplacements = true, + unsigned MaxEditDistance = 0) { + // The algorithm implemented below is the "classic" + // dynamic-programming algorithm for computing the Levenshtein + // distance, which is described here: + // + // http://en.wikipedia.org/wiki/Levenshtein_distance + // + // Although the algorithm is typically described using an m x n + // array, only one row plus one element are used at a time, so this + // implementation just keeps one vector for the row. To update one entry, + // only the entries to the left, top, and top-left are needed. The left + // entry is in Row[x-1], the top entry is what's in Row[x] from the last + // iteration, and the top-left entry is stored in Previous. + typename ArrayRef<T>::size_type m = FromArray.size(); + typename ArrayRef<T>::size_type n = ToArray.size(); + + const unsigned SmallBufferSize = 64; + unsigned SmallBuffer[SmallBufferSize]; + std::unique_ptr<unsigned[]> Allocated; + unsigned *Row = SmallBuffer; + if (n + 1 > SmallBufferSize) { + Row = new unsigned[n + 1]; + Allocated.reset(Row); + } + + for (unsigned i = 1; i <= n; ++i) + Row[i] = i; + + for (typename ArrayRef<T>::size_type y = 1; y <= m; ++y) { + Row[0] = y; + unsigned BestThisRow = Row[0]; + + unsigned Previous = y - 1; + for (typename ArrayRef<T>::size_type x = 1; x <= n; ++x) { + int OldRow = Row[x]; + if (AllowReplacements) { + Row[x] = std::min( + Previous + (FromArray[y-1] == ToArray[x-1] ? 0u : 1u), + std::min(Row[x-1], Row[x])+1); + } + else { + if (FromArray[y-1] == ToArray[x-1]) Row[x] = Previous; + else Row[x] = std::min(Row[x-1], Row[x]) + 1; + } + Previous = OldRow; + BestThisRow = std::min(BestThisRow, Row[x]); + } + + if (MaxEditDistance && BestThisRow > MaxEditDistance) + return MaxEditDistance + 1; + } + + unsigned Result = Row[n]; + return Result; +} + +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/fallible_iterator.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/fallible_iterator.h new file mode 100644 index 0000000..6501ad2 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/fallible_iterator.h
@@ -0,0 +1,243 @@ +//===--- fallible_iterator.h - Wrapper for fallible iterators ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_FALLIBLE_ITERATOR_H +#define LLVM_ADT_FALLIBLE_ITERATOR_H + +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/Error.h" + +#include <type_traits> + +namespace llvm { + +/// A wrapper class for fallible iterators. +/// +/// The fallible_iterator template wraps an underlying iterator-like class +/// whose increment and decrement operations are replaced with fallible versions +/// like: +/// +/// @code{.cpp} +/// Error inc(); +/// Error dec(); +/// @endcode +/// +/// It produces an interface that is (mostly) compatible with a traditional +/// c++ iterator, including ++ and -- operators that do not fail. +/// +/// Instances of the wrapper are constructed with an instance of the +/// underlying iterator and (for non-end iterators) a reference to an Error +/// instance. If the underlying increment/decrement operations fail, the Error +/// is returned via this reference, and the resulting iterator value set to an +/// end-of-range sentinel value. This enables the following loop idiom: +/// +/// @code{.cpp} +/// class Archive { // E.g. Potentially malformed on-disk archive +/// public: +/// fallible_iterator<ArchiveChildItr> children_begin(Error &Err); +/// fallible_iterator<ArchiveChildItr> children_end(); +/// iterator_range<fallible_iterator<ArchiveChildItr>> +/// children(Error &Err) { +/// return make_range(children_begin(Err), children_end()); +/// //... +/// }; +/// +/// void walk(Archive &A) { +/// Error Err = Error::success(); +/// for (auto &C : A.children(Err)) { +/// // Loop body only entered when increment succeeds. +/// } +/// if (Err) { +/// // handle error. +/// } +/// } +/// @endcode +/// +/// The wrapper marks the referenced Error as unchecked after each increment +/// and/or decrement operation, and clears the unchecked flag when a non-end +/// value is compared against end (since, by the increment invariant, not being +/// an end value proves that there was no error, and is equivalent to checking +/// that the Error is success). This allows early exits from the loop body +/// without requiring redundant error checks. +template <typename Underlying> class fallible_iterator { +private: + template <typename T> + using enable_if_struct_deref_supported = std::enable_if< + !std::is_void<decltype(std::declval<T>().operator->())>::value, + decltype(std::declval<T>().operator->())>; + +public: + /// Construct a fallible iterator that *cannot* be used as an end-of-range + /// value. + /// + /// A value created by this method can be dereferenced, incremented, + /// decremented and compared, providing the underlying type supports it. + /// + /// The error that is passed in will be initially marked as checked, so if the + /// iterator is not used at all the Error need not be checked. + static fallible_iterator itr(Underlying I, Error &Err) { + (void)!!Err; + return fallible_iterator(std::move(I), &Err); + } + + /// Construct a fallible iteratro that can be used as an end-of-range value. + /// + /// A value created by this method can be dereferenced (if the underlying + /// value points at a valid value) and compared, but not incremented or + /// decremented. + static fallible_iterator end(Underlying I) { + return fallible_iterator(std::move(I), nullptr); + } + + /// Forward dereference to the underlying iterator. + auto operator*() -> decltype(*std::declval<Underlying>()) { return *I; } + + /// Forward const dereference to the underlying iterator. + auto operator*() const -> decltype(*std::declval<const Underlying>()) { + return *I; + } + + /// Forward structure dereference to the underlying iterator (if the + /// underlying iterator supports it). + template <typename T = Underlying> + typename enable_if_struct_deref_supported<T>::type operator->() { + return I.operator->(); + } + + /// Forward const structure dereference to the underlying iterator (if the + /// underlying iterator supports it). + template <typename T = Underlying> + typename enable_if_struct_deref_supported<const T>::type operator->() const { + return I.operator->(); + } + + /// Increment the fallible iterator. + /// + /// If the underlying 'inc' operation fails, this will set the Error value + /// and update this iterator value to point to end-of-range. + /// + /// The Error value is marked as needing checking, regardless of whether the + /// 'inc' operation succeeds or fails. + fallible_iterator &operator++() { + assert(getErrPtr() && "Cannot increment end iterator"); + if (auto Err = I.inc()) + handleError(std::move(Err)); + else + resetCheckedFlag(); + return *this; + } + + /// Decrement the fallible iterator. + /// + /// If the underlying 'dec' operation fails, this will set the Error value + /// and update this iterator value to point to end-of-range. + /// + /// The Error value is marked as needing checking, regardless of whether the + /// 'dec' operation succeeds or fails. + fallible_iterator &operator--() { + assert(getErrPtr() && "Cannot decrement end iterator"); + if (auto Err = I.dec()) + handleError(std::move(Err)); + else + resetCheckedFlag(); + return *this; + } + + /// Compare fallible iterators for equality. + /// + /// Returns true if both LHS and RHS are end-of-range values, or if both are + /// non-end-of-range values whose underlying iterator values compare equal. + /// + /// If this is a comparison between an end-of-range iterator and a + /// non-end-of-range iterator, then the Error (referenced by the + /// non-end-of-range value) is marked as checked: Since all + /// increment/decrement operations result in an end-of-range value, comparing + /// false against end-of-range is equivalent to checking that the Error value + /// is success. This flag management enables early returns from loop bodies + /// without redundant Error checks. + friend bool operator==(const fallible_iterator &LHS, + const fallible_iterator &RHS) { + // If both iterators are in the end state they compare + // equal, regardless of whether either is valid. + if (LHS.isEnd() && RHS.isEnd()) + return true; + + assert(LHS.isValid() && RHS.isValid() && + "Invalid iterators can only be compared against end"); + + bool Equal = LHS.I == RHS.I; + + // If the iterators differ and this is a comparison against end then mark + // the Error as checked. + if (!Equal) { + if (LHS.isEnd()) + (void)!!*RHS.getErrPtr(); + else + (void)!!*LHS.getErrPtr(); + } + + return Equal; + } + + /// Compare fallible iterators for inequality. + /// + /// See notes for operator==. + friend bool operator!=(const fallible_iterator &LHS, + const fallible_iterator &RHS) { + return !(LHS == RHS); + } + +private: + fallible_iterator(Underlying I, Error *Err) + : I(std::move(I)), ErrState(Err, false) {} + + Error *getErrPtr() const { return ErrState.getPointer(); } + + bool isEnd() const { return getErrPtr() == nullptr; } + + bool isValid() const { return !ErrState.getInt(); } + + void handleError(Error Err) { + *getErrPtr() = std::move(Err); + ErrState.setPointer(nullptr); + ErrState.setInt(true); + } + + void resetCheckedFlag() { + *getErrPtr() = Error::success(); + } + + Underlying I; + mutable PointerIntPair<Error *, 1> ErrState; +}; + +/// Convenience wrapper to make a fallible_iterator value from an instance +/// of an underlying iterator and an Error reference. +template <typename Underlying> +fallible_iterator<Underlying> make_fallible_itr(Underlying I, Error &Err) { + return fallible_iterator<Underlying>::itr(std::move(I), Err); +} + +/// Convenience wrapper to make a fallible_iterator end value from an instance +/// of an underlying iterator. +template <typename Underlying> +fallible_iterator<Underlying> make_fallible_end(Underlying E) { + return fallible_iterator<Underlying>::end(std::move(E)); +} + +template <typename Underlying> +iterator_range<fallible_iterator<Underlying>> +make_fallible_range(Underlying I, Underlying E, Error &Err) { + return make_range(make_fallible_itr(std::move(I), Err), + make_fallible_end(std::move(E))); +} + +} // end namespace llvm + +#endif // LLVM_ADT_FALLIBLE_ITERATOR_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/ilist.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/ilist.h new file mode 100644 index 0000000..06c7abf --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/ilist.h
@@ -0,0 +1,419 @@ +//==-- llvm/ADT/ilist.h - Intrusive Linked List Template ---------*- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines classes to implement an intrusive doubly linked list class +// (i.e. each node of the list must contain a next and previous field for the +// list. +// +// The ilist class itself should be a plug in replacement for list. This list +// replacement does not provide a constant time size() method, so be careful to +// use empty() when you really want to know if it's empty. +// +// The ilist class is implemented as a circular list. The list itself contains +// a sentinel node, whose Next points at begin() and whose Prev points at +// rbegin(). The sentinel node itself serves as end() and rend(). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ILIST_H +#define LLVM_ADT_ILIST_H + +#include "llvm/ADT/simple_ilist.h" +#include <cassert> +#include <cstddef> +#include <iterator> + +namespace llvm { + +/// Use delete by default for iplist and ilist. +/// +/// Specialize this to get different behaviour for ownership-related API. (If +/// you really want ownership semantics, consider using std::list or building +/// something like \a BumpPtrList.) +/// +/// \see ilist_noalloc_traits +template <typename NodeTy> struct ilist_alloc_traits { + static void deleteNode(NodeTy *V) { delete V; } +}; + +/// Custom traits to do nothing on deletion. +/// +/// Specialize ilist_alloc_traits to inherit from this to disable the +/// non-intrusive deletion in iplist (which implies ownership). +/// +/// If you want purely intrusive semantics with no callbacks, consider using \a +/// simple_ilist instead. +/// +/// \code +/// template <> +/// struct ilist_alloc_traits<MyType> : ilist_noalloc_traits<MyType> {}; +/// \endcode +template <typename NodeTy> struct ilist_noalloc_traits { + static void deleteNode(NodeTy *V) {} +}; + +/// Callbacks do nothing by default in iplist and ilist. +/// +/// Specialize this for to use callbacks for when nodes change their list +/// membership. +template <typename NodeTy> struct ilist_callback_traits { + void addNodeToList(NodeTy *) {} + void removeNodeFromList(NodeTy *) {} + + /// Callback before transferring nodes to this list. The nodes may already be + /// in this same list. + template <class Iterator> + void transferNodesFromList(ilist_callback_traits &OldList, Iterator /*first*/, + Iterator /*last*/) { + (void)OldList; + } +}; + +/// A fragment for template traits for intrusive list that provides default +/// node related operations. +/// +/// TODO: Remove this layer of indirection. It's not necessary. +template <typename NodeTy> +struct ilist_node_traits : ilist_alloc_traits<NodeTy>, + ilist_callback_traits<NodeTy> {}; + +/// Template traits for intrusive list. +/// +/// Customize callbacks and allocation semantics. +template <typename NodeTy> +struct ilist_traits : public ilist_node_traits<NodeTy> {}; + +/// Const traits should never be instantiated. +template <typename Ty> struct ilist_traits<const Ty> {}; + +namespace ilist_detail { + +template <class T> T &make(); + +/// Type trait to check for a traits class that has a getNext member (as a +/// canary for any of the ilist_nextprev_traits API). +template <class TraitsT, class NodeT> struct HasGetNext { + typedef char Yes[1]; + typedef char No[2]; + template <size_t N> struct SFINAE {}; + + template <class U> + static Yes &test(U *I, decltype(I->getNext(&make<NodeT>())) * = 0); + template <class> static No &test(...); + +public: + static const bool value = sizeof(test<TraitsT>(nullptr)) == sizeof(Yes); +}; + +/// Type trait to check for a traits class that has a createSentinel member (as +/// a canary for any of the ilist_sentinel_traits API). +template <class TraitsT> struct HasCreateSentinel { + typedef char Yes[1]; + typedef char No[2]; + + template <class U> + static Yes &test(U *I, decltype(I->createSentinel()) * = 0); + template <class> static No &test(...); + +public: + static const bool value = sizeof(test<TraitsT>(nullptr)) == sizeof(Yes); +}; + +/// Type trait to check for a traits class that has a createNode member. +/// Allocation should be managed in a wrapper class, instead of in +/// ilist_traits. +template <class TraitsT, class NodeT> struct HasCreateNode { + typedef char Yes[1]; + typedef char No[2]; + template <size_t N> struct SFINAE {}; + + template <class U> + static Yes &test(U *I, decltype(I->createNode(make<NodeT>())) * = 0); + template <class> static No &test(...); + +public: + static const bool value = sizeof(test<TraitsT>(nullptr)) == sizeof(Yes); +}; + +template <class TraitsT, class NodeT> struct HasObsoleteCustomization { + static const bool value = HasGetNext<TraitsT, NodeT>::value || + HasCreateSentinel<TraitsT>::value || + HasCreateNode<TraitsT, NodeT>::value; +}; + +} // end namespace ilist_detail + +//===----------------------------------------------------------------------===// +// +/// A wrapper around an intrusive list with callbacks and non-intrusive +/// ownership. +/// +/// This wraps a purely intrusive list (like simple_ilist) with a configurable +/// traits class. The traits can implement callbacks and customize the +/// ownership semantics. +/// +/// This is a subset of ilist functionality that can safely be used on nodes of +/// polymorphic types, i.e. a heterogeneous list with a common base class that +/// holds the next/prev pointers. The only state of the list itself is an +/// ilist_sentinel, which holds pointers to the first and last nodes in the +/// list. +template <class IntrusiveListT, class TraitsT> +class iplist_impl : public TraitsT, IntrusiveListT { + typedef IntrusiveListT base_list_type; + +public: + typedef typename base_list_type::pointer pointer; + typedef typename base_list_type::const_pointer const_pointer; + typedef typename base_list_type::reference reference; + typedef typename base_list_type::const_reference const_reference; + typedef typename base_list_type::value_type value_type; + typedef typename base_list_type::size_type size_type; + typedef typename base_list_type::difference_type difference_type; + typedef typename base_list_type::iterator iterator; + typedef typename base_list_type::const_iterator const_iterator; + typedef typename base_list_type::reverse_iterator reverse_iterator; + typedef + typename base_list_type::const_reverse_iterator const_reverse_iterator; + +private: + // TODO: Drop this assertion and the transitive type traits anytime after + // v4.0 is branched (i.e,. keep them for one release to help out-of-tree code + // update). + static_assert( + !ilist_detail::HasObsoleteCustomization<TraitsT, value_type>::value, + "ilist customization points have changed!"); + + static bool op_less(const_reference L, const_reference R) { return L < R; } + static bool op_equal(const_reference L, const_reference R) { return L == R; } + +public: + iplist_impl() = default; + + iplist_impl(const iplist_impl &) = delete; + iplist_impl &operator=(const iplist_impl &) = delete; + + iplist_impl(iplist_impl &&X) + : TraitsT(std::move(X)), IntrusiveListT(std::move(X)) {} + iplist_impl &operator=(iplist_impl &&X) { + *static_cast<TraitsT *>(this) = std::move(X); + *static_cast<IntrusiveListT *>(this) = std::move(X); + return *this; + } + + ~iplist_impl() { clear(); } + + // Miscellaneous inspection routines. + size_type max_size() const { return size_type(-1); } + + using base_list_type::begin; + using base_list_type::end; + using base_list_type::rbegin; + using base_list_type::rend; + using base_list_type::empty; + using base_list_type::front; + using base_list_type::back; + + void swap(iplist_impl &RHS) { + assert(0 && "Swap does not use list traits callback correctly yet!"); + base_list_type::swap(RHS); + } + + iterator insert(iterator where, pointer New) { + this->addNodeToList(New); // Notify traits that we added a node... + return base_list_type::insert(where, *New); + } + + iterator insert(iterator where, const_reference New) { + return this->insert(where, new value_type(New)); + } + + iterator insertAfter(iterator where, pointer New) { + if (empty()) + return insert(begin(), New); + else + return insert(++where, New); + } + + /// Clone another list. + template <class Cloner> void cloneFrom(const iplist_impl &L2, Cloner clone) { + clear(); + for (const_reference V : L2) + push_back(clone(V)); + } + + pointer remove(iterator &IT) { + pointer Node = &*IT++; + this->removeNodeFromList(Node); // Notify traits that we removed a node... + base_list_type::remove(*Node); + return Node; + } + + pointer remove(const iterator &IT) { + iterator MutIt = IT; + return remove(MutIt); + } + + pointer remove(pointer IT) { return remove(iterator(IT)); } + pointer remove(reference IT) { return remove(iterator(IT)); } + + // erase - remove a node from the controlled sequence... and delete it. + iterator erase(iterator where) { + this->deleteNode(remove(where)); + return where; + } + + iterator erase(pointer IT) { return erase(iterator(IT)); } + iterator erase(reference IT) { return erase(iterator(IT)); } + + /// Remove all nodes from the list like clear(), but do not call + /// removeNodeFromList() or deleteNode(). + /// + /// This should only be used immediately before freeing nodes in bulk to + /// avoid traversing the list and bringing all the nodes into cache. + void clearAndLeakNodesUnsafely() { base_list_type::clear(); } + +private: + // transfer - The heart of the splice function. Move linked list nodes from + // [first, last) into position. + // + void transfer(iterator position, iplist_impl &L2, iterator first, iterator last) { + if (position == last) + return; + + // Notify traits we moved the nodes... + this->transferNodesFromList(L2, first, last); + + base_list_type::splice(position, L2, first, last); + } + +public: + //===----------------------------------------------------------------------=== + // Functionality derived from other functions defined above... + // + + using base_list_type::size; + + iterator erase(iterator first, iterator last) { + while (first != last) + first = erase(first); + return last; + } + + void clear() { erase(begin(), end()); } + + // Front and back inserters... + void push_front(pointer val) { insert(begin(), val); } + void push_back(pointer val) { insert(end(), val); } + void pop_front() { + assert(!empty() && "pop_front() on empty list!"); + erase(begin()); + } + void pop_back() { + assert(!empty() && "pop_back() on empty list!"); + iterator t = end(); erase(--t); + } + + // Special forms of insert... + template<class InIt> void insert(iterator where, InIt first, InIt last) { + for (; first != last; ++first) insert(where, *first); + } + + // Splice members - defined in terms of transfer... + void splice(iterator where, iplist_impl &L2) { + if (!L2.empty()) + transfer(where, L2, L2.begin(), L2.end()); + } + void splice(iterator where, iplist_impl &L2, iterator first) { + iterator last = first; ++last; + if (where == first || where == last) return; // No change + transfer(where, L2, first, last); + } + void splice(iterator where, iplist_impl &L2, iterator first, iterator last) { + if (first != last) transfer(where, L2, first, last); + } + void splice(iterator where, iplist_impl &L2, reference N) { + splice(where, L2, iterator(N)); + } + void splice(iterator where, iplist_impl &L2, pointer N) { + splice(where, L2, iterator(N)); + } + + template <class Compare> + void merge(iplist_impl &Right, Compare comp) { + if (this == &Right) + return; + this->transferNodesFromList(Right, Right.begin(), Right.end()); + base_list_type::merge(Right, comp); + } + void merge(iplist_impl &Right) { return merge(Right, op_less); } + + using base_list_type::sort; + + /// Get the previous node, or \c nullptr for the list head. + pointer getPrevNode(reference N) const { + auto I = N.getIterator(); + if (I == begin()) + return nullptr; + return &*std::prev(I); + } + /// Get the previous node, or \c nullptr for the list head. + const_pointer getPrevNode(const_reference N) const { + return getPrevNode(const_cast<reference >(N)); + } + + /// Get the next node, or \c nullptr for the list tail. + pointer getNextNode(reference N) const { + auto Next = std::next(N.getIterator()); + if (Next == end()) + return nullptr; + return &*Next; + } + /// Get the next node, or \c nullptr for the list tail. + const_pointer getNextNode(const_reference N) const { + return getNextNode(const_cast<reference >(N)); + } +}; + +/// An intrusive list with ownership and callbacks specified/controlled by +/// ilist_traits, only with API safe for polymorphic types. +/// +/// The \p Options parameters are the same as those for \a simple_ilist. See +/// there for a description of what's available. +template <class T, class... Options> +class iplist + : public iplist_impl<simple_ilist<T, Options...>, ilist_traits<T>> { + using iplist_impl_type = typename iplist::iplist_impl; + +public: + iplist() = default; + + iplist(const iplist &X) = delete; + iplist &operator=(const iplist &X) = delete; + + iplist(iplist &&X) : iplist_impl_type(std::move(X)) {} + iplist &operator=(iplist &&X) { + *static_cast<iplist_impl_type *>(this) = std::move(X); + return *this; + } +}; + +template <class T, class... Options> using ilist = iplist<T, Options...>; + +} // end namespace llvm + +namespace std { + + // Ensure that swap uses the fast list swap... + template<class Ty> + void swap(llvm::iplist<Ty> &Left, llvm::iplist<Ty> &Right) { + Left.swap(Right); + } + +} // end namespace std + +#endif // LLVM_ADT_ILIST_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/ilist_base.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/ilist_base.h new file mode 100644 index 0000000..b8c098b --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/ilist_base.h
@@ -0,0 +1,92 @@ +//===- llvm/ADT/ilist_base.h - Intrusive List Base --------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ILIST_BASE_H +#define LLVM_ADT_ILIST_BASE_H + +#include "llvm/ADT/ilist_node_base.h" +#include <cassert> + +namespace llvm { + +/// Implementations of list algorithms using ilist_node_base. +template <bool EnableSentinelTracking> class ilist_base { +public: + using node_base_type = ilist_node_base<EnableSentinelTracking>; + + static void insertBeforeImpl(node_base_type &Next, node_base_type &N) { + node_base_type &Prev = *Next.getPrev(); + N.setNext(&Next); + N.setPrev(&Prev); + Prev.setNext(&N); + Next.setPrev(&N); + } + + static void removeImpl(node_base_type &N) { + node_base_type *Prev = N.getPrev(); + node_base_type *Next = N.getNext(); + Next->setPrev(Prev); + Prev->setNext(Next); + + // Not strictly necessary, but helps catch a class of bugs. + N.setPrev(nullptr); + N.setNext(nullptr); + } + + static void removeRangeImpl(node_base_type &First, node_base_type &Last) { + node_base_type *Prev = First.getPrev(); + node_base_type *Final = Last.getPrev(); + Last.setPrev(Prev); + Prev->setNext(&Last); + + // Not strictly necessary, but helps catch a class of bugs. + First.setPrev(nullptr); + Final->setNext(nullptr); + } + + static void transferBeforeImpl(node_base_type &Next, node_base_type &First, + node_base_type &Last) { + if (&Next == &Last || &First == &Last) + return; + + // Position cannot be contained in the range to be transferred. + assert(&Next != &First && + // Check for the most common mistake. + "Insertion point can't be one of the transferred nodes"); + + node_base_type &Final = *Last.getPrev(); + + // Detach from old list/position. + First.getPrev()->setNext(&Last); + Last.setPrev(First.getPrev()); + + // Splice [First, Final] into its new list/position. + node_base_type &Prev = *Next.getPrev(); + Final.setNext(&Next); + First.setPrev(&Prev); + Prev.setNext(&First); + Next.setPrev(&Final); + } + + template <class T> static void insertBefore(T &Next, T &N) { + insertBeforeImpl(Next, N); + } + + template <class T> static void remove(T &N) { removeImpl(N); } + template <class T> static void removeRange(T &First, T &Last) { + removeRangeImpl(First, Last); + } + + template <class T> static void transferBefore(T &Next, T &First, T &Last) { + transferBeforeImpl(Next, First, Last); + } +}; + +} // end namespace llvm + +#endif // LLVM_ADT_ILIST_BASE_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/ilist_iterator.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/ilist_iterator.h new file mode 100644 index 0000000..cbe5cef --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/ilist_iterator.h
@@ -0,0 +1,198 @@ +//===- llvm/ADT/ilist_iterator.h - Intrusive List Iterator ------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ILIST_ITERATOR_H +#define LLVM_ADT_ILIST_ITERATOR_H + +#include "llvm/ADT/ilist_node.h" +#include <cassert> +#include <cstddef> +#include <iterator> +#include <type_traits> + +namespace llvm { + +namespace ilist_detail { + +/// Find const-correct node types. +template <class OptionsT, bool IsConst> struct IteratorTraits; +template <class OptionsT> struct IteratorTraits<OptionsT, false> { + using value_type = typename OptionsT::value_type; + using pointer = typename OptionsT::pointer; + using reference = typename OptionsT::reference; + using node_pointer = ilist_node_impl<OptionsT> *; + using node_reference = ilist_node_impl<OptionsT> &; +}; +template <class OptionsT> struct IteratorTraits<OptionsT, true> { + using value_type = const typename OptionsT::value_type; + using pointer = typename OptionsT::const_pointer; + using reference = typename OptionsT::const_reference; + using node_pointer = const ilist_node_impl<OptionsT> *; + using node_reference = const ilist_node_impl<OptionsT> &; +}; + +template <bool IsReverse> struct IteratorHelper; +template <> struct IteratorHelper<false> : ilist_detail::NodeAccess { + using Access = ilist_detail::NodeAccess; + + template <class T> static void increment(T *&I) { I = Access::getNext(*I); } + template <class T> static void decrement(T *&I) { I = Access::getPrev(*I); } +}; +template <> struct IteratorHelper<true> : ilist_detail::NodeAccess { + using Access = ilist_detail::NodeAccess; + + template <class T> static void increment(T *&I) { I = Access::getPrev(*I); } + template <class T> static void decrement(T *&I) { I = Access::getNext(*I); } +}; + +} // end namespace ilist_detail + +/// Iterator for intrusive lists based on ilist_node. +template <class OptionsT, bool IsReverse, bool IsConst> +class ilist_iterator : ilist_detail::SpecificNodeAccess<OptionsT> { + friend ilist_iterator<OptionsT, IsReverse, !IsConst>; + friend ilist_iterator<OptionsT, !IsReverse, IsConst>; + friend ilist_iterator<OptionsT, !IsReverse, !IsConst>; + + using Traits = ilist_detail::IteratorTraits<OptionsT, IsConst>; + using Access = ilist_detail::SpecificNodeAccess<OptionsT>; + +public: + using value_type = typename Traits::value_type; + using pointer = typename Traits::pointer; + using reference = typename Traits::reference; + using difference_type = ptrdiff_t; + using iterator_category = std::bidirectional_iterator_tag; + using const_pointer = typename OptionsT::const_pointer; + using const_reference = typename OptionsT::const_reference; + +private: + using node_pointer = typename Traits::node_pointer; + using node_reference = typename Traits::node_reference; + + node_pointer NodePtr = nullptr; + +public: + /// Create from an ilist_node. + explicit ilist_iterator(node_reference N) : NodePtr(&N) {} + + explicit ilist_iterator(pointer NP) : NodePtr(Access::getNodePtr(NP)) {} + explicit ilist_iterator(reference NR) : NodePtr(Access::getNodePtr(&NR)) {} + ilist_iterator() = default; + + // This is templated so that we can allow constructing a const iterator from + // a nonconst iterator... + template <bool RHSIsConst> + ilist_iterator( + const ilist_iterator<OptionsT, IsReverse, RHSIsConst> &RHS, + typename std::enable_if<IsConst || !RHSIsConst, void *>::type = nullptr) + : NodePtr(RHS.NodePtr) {} + + // This is templated so that we can allow assigning to a const iterator from + // a nonconst iterator... + template <bool RHSIsConst> + typename std::enable_if<IsConst || !RHSIsConst, ilist_iterator &>::type + operator=(const ilist_iterator<OptionsT, IsReverse, RHSIsConst> &RHS) { + NodePtr = RHS.NodePtr; + return *this; + } + + /// Explicit conversion between forward/reverse iterators. + /// + /// Translate between forward and reverse iterators without changing range + /// boundaries. The resulting iterator will dereference (and have a handle) + /// to the previous node, which is somewhat unexpected; but converting the + /// two endpoints in a range will give the same range in reverse. + /// + /// This matches std::reverse_iterator conversions. + explicit ilist_iterator( + const ilist_iterator<OptionsT, !IsReverse, IsConst> &RHS) + : ilist_iterator(++RHS.getReverse()) {} + + /// Get a reverse iterator to the same node. + /// + /// Gives a reverse iterator that will dereference (and have a handle) to the + /// same node. Converting the endpoint iterators in a range will give a + /// different range; for range operations, use the explicit conversions. + ilist_iterator<OptionsT, !IsReverse, IsConst> getReverse() const { + if (NodePtr) + return ilist_iterator<OptionsT, !IsReverse, IsConst>(*NodePtr); + return ilist_iterator<OptionsT, !IsReverse, IsConst>(); + } + + /// Const-cast. + ilist_iterator<OptionsT, IsReverse, false> getNonConst() const { + if (NodePtr) + return ilist_iterator<OptionsT, IsReverse, false>( + const_cast<typename ilist_iterator<OptionsT, IsReverse, + false>::node_reference>(*NodePtr)); + return ilist_iterator<OptionsT, IsReverse, false>(); + } + + // Accessors... + reference operator*() const { + assert(!NodePtr->isKnownSentinel()); + return *Access::getValuePtr(NodePtr); + } + pointer operator->() const { return &operator*(); } + + // Comparison operators + friend bool operator==(const ilist_iterator &LHS, const ilist_iterator &RHS) { + return LHS.NodePtr == RHS.NodePtr; + } + friend bool operator!=(const ilist_iterator &LHS, const ilist_iterator &RHS) { + return LHS.NodePtr != RHS.NodePtr; + } + + // Increment and decrement operators... + ilist_iterator &operator--() { + NodePtr = IsReverse ? NodePtr->getNext() : NodePtr->getPrev(); + return *this; + } + ilist_iterator &operator++() { + NodePtr = IsReverse ? NodePtr->getPrev() : NodePtr->getNext(); + return *this; + } + ilist_iterator operator--(int) { + ilist_iterator tmp = *this; + --*this; + return tmp; + } + ilist_iterator operator++(int) { + ilist_iterator tmp = *this; + ++*this; + return tmp; + } + + /// Get the underlying ilist_node. + node_pointer getNodePtr() const { return static_cast<node_pointer>(NodePtr); } + + /// Check for end. Only valid if ilist_sentinel_tracking<true>. + bool isEnd() const { return NodePtr ? NodePtr->isSentinel() : false; } +}; + +template <typename From> struct simplify_type; + +/// Allow ilist_iterators to convert into pointers to a node automatically when +/// used by the dyn_cast, cast, isa mechanisms... +/// +/// FIXME: remove this, since there is no implicit conversion to NodeTy. +template <class OptionsT, bool IsConst> +struct simplify_type<ilist_iterator<OptionsT, false, IsConst>> { + using iterator = ilist_iterator<OptionsT, false, IsConst>; + using SimpleType = typename iterator::pointer; + + static SimpleType getSimplifiedValue(const iterator &Node) { return &*Node; } +}; +template <class OptionsT, bool IsConst> +struct simplify_type<const ilist_iterator<OptionsT, false, IsConst>> + : simplify_type<ilist_iterator<OptionsT, false, IsConst>> {}; + +} // end namespace llvm + +#endif // LLVM_ADT_ILIST_ITERATOR_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/ilist_node.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/ilist_node.h new file mode 100644 index 0000000..e040d96 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/ilist_node.h
@@ -0,0 +1,305 @@ +//===- llvm/ADT/ilist_node.h - Intrusive Linked List Helper -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the ilist_node class template, which is a convenient +// base class for creating classes that can be used with ilists. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ILIST_NODE_H +#define LLVM_ADT_ILIST_NODE_H + +#include "llvm/ADT/ilist_node_base.h" +#include "llvm/ADT/ilist_node_options.h" + +namespace llvm { + +namespace ilist_detail { + +struct NodeAccess; + +} // end namespace ilist_detail + +template <class OptionsT, bool IsReverse, bool IsConst> class ilist_iterator; +template <class OptionsT> class ilist_sentinel; + +/// Implementation for an ilist node. +/// +/// Templated on an appropriate \a ilist_detail::node_options, usually computed +/// by \a ilist_detail::compute_node_options. +/// +/// This is a wrapper around \a ilist_node_base whose main purpose is to +/// provide type safety: you can't insert nodes of \a ilist_node_impl into the +/// wrong \a simple_ilist or \a iplist. +template <class OptionsT> class ilist_node_impl : OptionsT::node_base_type { + using value_type = typename OptionsT::value_type; + using node_base_type = typename OptionsT::node_base_type; + using list_base_type = typename OptionsT::list_base_type; + + friend typename OptionsT::list_base_type; + friend struct ilist_detail::NodeAccess; + friend class ilist_sentinel<OptionsT>; + friend class ilist_iterator<OptionsT, false, false>; + friend class ilist_iterator<OptionsT, false, true>; + friend class ilist_iterator<OptionsT, true, false>; + friend class ilist_iterator<OptionsT, true, true>; + +protected: + using self_iterator = ilist_iterator<OptionsT, false, false>; + using const_self_iterator = ilist_iterator<OptionsT, false, true>; + using reverse_self_iterator = ilist_iterator<OptionsT, true, false>; + using const_reverse_self_iterator = ilist_iterator<OptionsT, true, true>; + + ilist_node_impl() = default; + +private: + ilist_node_impl *getPrev() { + return static_cast<ilist_node_impl *>(node_base_type::getPrev()); + } + + ilist_node_impl *getNext() { + return static_cast<ilist_node_impl *>(node_base_type::getNext()); + } + + const ilist_node_impl *getPrev() const { + return static_cast<ilist_node_impl *>(node_base_type::getPrev()); + } + + const ilist_node_impl *getNext() const { + return static_cast<ilist_node_impl *>(node_base_type::getNext()); + } + + void setPrev(ilist_node_impl *N) { node_base_type::setPrev(N); } + void setNext(ilist_node_impl *N) { node_base_type::setNext(N); } + +public: + self_iterator getIterator() { return self_iterator(*this); } + const_self_iterator getIterator() const { return const_self_iterator(*this); } + + reverse_self_iterator getReverseIterator() { + return reverse_self_iterator(*this); + } + + const_reverse_self_iterator getReverseIterator() const { + return const_reverse_self_iterator(*this); + } + + // Under-approximation, but always available for assertions. + using node_base_type::isKnownSentinel; + + /// Check whether this is the sentinel node. + /// + /// This requires sentinel tracking to be explicitly enabled. Use the + /// ilist_sentinel_tracking<true> option to get this API. + bool isSentinel() const { + static_assert(OptionsT::is_sentinel_tracking_explicit, + "Use ilist_sentinel_tracking<true> to enable isSentinel()"); + return node_base_type::isSentinel(); + } +}; + +/// An intrusive list node. +/// +/// A base class to enable membership in intrusive lists, including \a +/// simple_ilist, \a iplist, and \a ilist. The first template parameter is the +/// \a value_type for the list. +/// +/// An ilist node can be configured with compile-time options to change +/// behaviour and/or add API. +/// +/// By default, an \a ilist_node knows whether it is the list sentinel (an +/// instance of \a ilist_sentinel) if and only if +/// LLVM_ENABLE_ABI_BREAKING_CHECKS. The function \a isKnownSentinel() always +/// returns \c false tracking is off. Sentinel tracking steals a bit from the +/// "prev" link, which adds a mask operation when decrementing an iterator, but +/// enables bug-finding assertions in \a ilist_iterator. +/// +/// To turn sentinel tracking on all the time, pass in the +/// ilist_sentinel_tracking<true> template parameter. This also enables the \a +/// isSentinel() function. The same option must be passed to the intrusive +/// list. (ilist_sentinel_tracking<false> turns sentinel tracking off all the +/// time.) +/// +/// A type can inherit from ilist_node multiple times by passing in different +/// \a ilist_tag options. This allows a single instance to be inserted into +/// multiple lists simultaneously, where each list is given the same tag. +/// +/// \example +/// struct A {}; +/// struct B {}; +/// struct N : ilist_node<N, ilist_tag<A>>, ilist_node<N, ilist_tag<B>> {}; +/// +/// void foo() { +/// simple_ilist<N, ilist_tag<A>> ListA; +/// simple_ilist<N, ilist_tag<B>> ListB; +/// N N1; +/// ListA.push_back(N1); +/// ListB.push_back(N1); +/// } +/// \endexample +/// +/// See \a is_valid_option for steps on adding a new option. +template <class T, class... Options> +class ilist_node + : public ilist_node_impl< + typename ilist_detail::compute_node_options<T, Options...>::type> { + static_assert(ilist_detail::check_options<Options...>::value, + "Unrecognized node option!"); +}; + +namespace ilist_detail { + +/// An access class for ilist_node private API. +/// +/// This gives access to the private parts of ilist nodes. Nodes for an ilist +/// should friend this class if they inherit privately from ilist_node. +/// +/// Using this class outside of the ilist implementation is unsupported. +struct NodeAccess { +protected: + template <class OptionsT> + static ilist_node_impl<OptionsT> *getNodePtr(typename OptionsT::pointer N) { + return N; + } + + template <class OptionsT> + static const ilist_node_impl<OptionsT> * + getNodePtr(typename OptionsT::const_pointer N) { + return N; + } + + template <class OptionsT> + static typename OptionsT::pointer getValuePtr(ilist_node_impl<OptionsT> *N) { + return static_cast<typename OptionsT::pointer>(N); + } + + template <class OptionsT> + static typename OptionsT::const_pointer + getValuePtr(const ilist_node_impl<OptionsT> *N) { + return static_cast<typename OptionsT::const_pointer>(N); + } + + template <class OptionsT> + static ilist_node_impl<OptionsT> *getPrev(ilist_node_impl<OptionsT> &N) { + return N.getPrev(); + } + + template <class OptionsT> + static ilist_node_impl<OptionsT> *getNext(ilist_node_impl<OptionsT> &N) { + return N.getNext(); + } + + template <class OptionsT> + static const ilist_node_impl<OptionsT> * + getPrev(const ilist_node_impl<OptionsT> &N) { + return N.getPrev(); + } + + template <class OptionsT> + static const ilist_node_impl<OptionsT> * + getNext(const ilist_node_impl<OptionsT> &N) { + return N.getNext(); + } +}; + +template <class OptionsT> struct SpecificNodeAccess : NodeAccess { +protected: + using pointer = typename OptionsT::pointer; + using const_pointer = typename OptionsT::const_pointer; + using node_type = ilist_node_impl<OptionsT>; + + static node_type *getNodePtr(pointer N) { + return NodeAccess::getNodePtr<OptionsT>(N); + } + + static const node_type *getNodePtr(const_pointer N) { + return NodeAccess::getNodePtr<OptionsT>(N); + } + + static pointer getValuePtr(node_type *N) { + return NodeAccess::getValuePtr<OptionsT>(N); + } + + static const_pointer getValuePtr(const node_type *N) { + return NodeAccess::getValuePtr<OptionsT>(N); + } +}; + +} // end namespace ilist_detail + +template <class OptionsT> +class ilist_sentinel : public ilist_node_impl<OptionsT> { +public: + ilist_sentinel() { + this->initializeSentinel(); + reset(); + } + + void reset() { + this->setPrev(this); + this->setNext(this); + } + + bool empty() const { return this == this->getPrev(); } +}; + +/// An ilist node that can access its parent list. +/// +/// Requires \c NodeTy to have \a getParent() to find the parent node, and the +/// \c ParentTy to have \a getSublistAccess() to get a reference to the list. +template <typename NodeTy, typename ParentTy, class... Options> +class ilist_node_with_parent : public ilist_node<NodeTy, Options...> { +protected: + ilist_node_with_parent() = default; + +private: + /// Forward to NodeTy::getParent(). + /// + /// Note: do not use the name "getParent()". We want a compile error + /// (instead of recursion) when the subclass fails to implement \a + /// getParent(). + const ParentTy *getNodeParent() const { + return static_cast<const NodeTy *>(this)->getParent(); + } + +public: + /// @name Adjacent Node Accessors + /// @{ + /// Get the previous node, or \c nullptr for the list head. + NodeTy *getPrevNode() { + // Should be separated to a reused function, but then we couldn't use auto + // (and would need the type of the list). + const auto &List = + getNodeParent()->*(ParentTy::getSublistAccess((NodeTy *)nullptr)); + return List.getPrevNode(*static_cast<NodeTy *>(this)); + } + + /// Get the previous node, or \c nullptr for the list head. + const NodeTy *getPrevNode() const { + return const_cast<ilist_node_with_parent *>(this)->getPrevNode(); + } + + /// Get the next node, or \c nullptr for the list tail. + NodeTy *getNextNode() { + // Should be separated to a reused function, but then we couldn't use auto + // (and would need the type of the list). + const auto &List = + getNodeParent()->*(ParentTy::getSublistAccess((NodeTy *)nullptr)); + return List.getNextNode(*static_cast<NodeTy *>(this)); + } + + /// Get the next node, or \c nullptr for the list tail. + const NodeTy *getNextNode() const { + return const_cast<ilist_node_with_parent *>(this)->getNextNode(); + } + /// @} +}; + +} // end namespace llvm + +#endif // LLVM_ADT_ILIST_NODE_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/ilist_node_base.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/ilist_node_base.h new file mode 100644 index 0000000..f6c518e --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/ilist_node_base.h
@@ -0,0 +1,52 @@ +//===- llvm/ADT/ilist_node_base.h - Intrusive List Node Base -----*- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ILIST_NODE_BASE_H +#define LLVM_ADT_ILIST_NODE_BASE_H + +#include "llvm/ADT/PointerIntPair.h" + +namespace llvm { + +/// Base class for ilist nodes. +/// +/// Optionally tracks whether this node is the sentinel. +template <bool EnableSentinelTracking> class ilist_node_base; + +template <> class ilist_node_base<false> { + ilist_node_base *Prev = nullptr; + ilist_node_base *Next = nullptr; + +public: + void setPrev(ilist_node_base *Prev) { this->Prev = Prev; } + void setNext(ilist_node_base *Next) { this->Next = Next; } + ilist_node_base *getPrev() const { return Prev; } + ilist_node_base *getNext() const { return Next; } + + bool isKnownSentinel() const { return false; } + void initializeSentinel() {} +}; + +template <> class ilist_node_base<true> { + PointerIntPair<ilist_node_base *, 1> PrevAndSentinel; + ilist_node_base *Next = nullptr; + +public: + void setPrev(ilist_node_base *Prev) { PrevAndSentinel.setPointer(Prev); } + void setNext(ilist_node_base *Next) { this->Next = Next; } + ilist_node_base *getPrev() const { return PrevAndSentinel.getPointer(); } + ilist_node_base *getNext() const { return Next; } + + bool isSentinel() const { return PrevAndSentinel.getInt(); } + bool isKnownSentinel() const { return isSentinel(); } + void initializeSentinel() { PrevAndSentinel.setInt(true); } +}; + +} // end namespace llvm + +#endif // LLVM_ADT_ILIST_NODE_BASE_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/ilist_node_options.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/ilist_node_options.h new file mode 100644 index 0000000..9b95cdb --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/ilist_node_options.h
@@ -0,0 +1,131 @@ +//===- llvm/ADT/ilist_node_options.h - ilist_node Options -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ILIST_NODE_OPTIONS_H +#define LLVM_ADT_ILIST_NODE_OPTIONS_H + +#include "llvm/Config/abi-breaking.h" + +#include <type_traits> + +namespace llvm { + +template <bool EnableSentinelTracking> class ilist_node_base; +template <bool EnableSentinelTracking> class ilist_base; + +/// Option to choose whether to track sentinels. +/// +/// This option affects the ABI for the nodes. When not specified explicitly, +/// the ABI depends on LLVM_ENABLE_ABI_BREAKING_CHECKS. Specify explicitly to +/// enable \a ilist_node::isSentinel(). +template <bool EnableSentinelTracking> struct ilist_sentinel_tracking {}; + +/// Option to specify a tag for the node type. +/// +/// This option allows a single value type to be inserted in multiple lists +/// simultaneously. See \a ilist_node for usage examples. +template <class Tag> struct ilist_tag {}; + +namespace ilist_detail { + +/// Helper trait for recording whether an option is specified explicitly. +template <bool IsExplicit> struct explicitness { + static const bool is_explicit = IsExplicit; +}; +typedef explicitness<true> is_explicit; +typedef explicitness<false> is_implicit; + +/// Check whether an option is valid. +/// +/// The steps for adding and enabling a new ilist option include: +/// \li define the option, ilist_foo<Bar>, above; +/// \li add new parameters for Bar to \a ilist_detail::node_options; +/// \li add an extraction meta-function, ilist_detail::extract_foo; +/// \li call extract_foo from \a ilist_detail::compute_node_options and pass it +/// into \a ilist_detail::node_options; and +/// \li specialize \c is_valid_option<ilist_foo<Bar>> to inherit from \c +/// std::true_type to get static assertions passing in \a simple_ilist and \a +/// ilist_node. +template <class Option> struct is_valid_option : std::false_type {}; + +/// Extract sentinel tracking option. +/// +/// Look through \p Options for the \a ilist_sentinel_tracking option, with the +/// default depending on LLVM_ENABLE_ABI_BREAKING_CHECKS. +template <class... Options> struct extract_sentinel_tracking; +template <bool EnableSentinelTracking, class... Options> +struct extract_sentinel_tracking< + ilist_sentinel_tracking<EnableSentinelTracking>, Options...> + : std::integral_constant<bool, EnableSentinelTracking>, is_explicit {}; +template <class Option1, class... Options> +struct extract_sentinel_tracking<Option1, Options...> + : extract_sentinel_tracking<Options...> {}; +#if LLVM_ENABLE_ABI_BREAKING_CHECKS +template <> struct extract_sentinel_tracking<> : std::true_type, is_implicit {}; +#else +template <> +struct extract_sentinel_tracking<> : std::false_type, is_implicit {}; +#endif +template <bool EnableSentinelTracking> +struct is_valid_option<ilist_sentinel_tracking<EnableSentinelTracking>> + : std::true_type {}; + +/// Extract custom tag option. +/// +/// Look through \p Options for the \a ilist_tag option, pulling out the +/// custom tag type, using void as a default. +template <class... Options> struct extract_tag; +template <class Tag, class... Options> +struct extract_tag<ilist_tag<Tag>, Options...> { + typedef Tag type; +}; +template <class Option1, class... Options> +struct extract_tag<Option1, Options...> : extract_tag<Options...> {}; +template <> struct extract_tag<> { typedef void type; }; +template <class Tag> struct is_valid_option<ilist_tag<Tag>> : std::true_type {}; + +/// Check whether options are valid. +/// +/// The conjunction of \a is_valid_option on each individual option. +template <class... Options> struct check_options; +template <> struct check_options<> : std::true_type {}; +template <class Option1, class... Options> +struct check_options<Option1, Options...> + : std::integral_constant<bool, is_valid_option<Option1>::value && + check_options<Options...>::value> {}; + +/// Traits for options for \a ilist_node. +/// +/// This is usually computed via \a compute_node_options. +template <class T, bool EnableSentinelTracking, bool IsSentinelTrackingExplicit, + class TagT> +struct node_options { + typedef T value_type; + typedef T *pointer; + typedef T &reference; + typedef const T *const_pointer; + typedef const T &const_reference; + + static const bool enable_sentinel_tracking = EnableSentinelTracking; + static const bool is_sentinel_tracking_explicit = IsSentinelTrackingExplicit; + typedef TagT tag; + typedef ilist_node_base<enable_sentinel_tracking> node_base_type; + typedef ilist_base<enable_sentinel_tracking> list_base_type; +}; + +template <class T, class... Options> struct compute_node_options { + typedef node_options<T, extract_sentinel_tracking<Options...>::value, + extract_sentinel_tracking<Options...>::is_explicit, + typename extract_tag<Options...>::type> + type; +}; + +} // end namespace ilist_detail +} // end namespace llvm + +#endif // LLVM_ADT_ILIST_NODE_OPTIONS_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/iterator.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/iterator.h new file mode 100644 index 0000000..8fd5c11 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/iterator.h
@@ -0,0 +1,371 @@ +//===- iterator.h - Utilities for using and defining iterators --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ITERATOR_H +#define LLVM_ADT_ITERATOR_H + +#include "llvm/ADT/iterator_range.h" +#include <algorithm> +#include <cstddef> +#include <iterator> +#include <type_traits> +#include <utility> + +namespace llvm { + +/// CRTP base class which implements the entire standard iterator facade +/// in terms of a minimal subset of the interface. +/// +/// Use this when it is reasonable to implement most of the iterator +/// functionality in terms of a core subset. If you need special behavior or +/// there are performance implications for this, you may want to override the +/// relevant members instead. +/// +/// Note, one abstraction that this does *not* provide is implementing +/// subtraction in terms of addition by negating the difference. Negation isn't +/// always information preserving, and I can see very reasonable iterator +/// designs where this doesn't work well. It doesn't really force much added +/// boilerplate anyways. +/// +/// Another abstraction that this doesn't provide is implementing increment in +/// terms of addition of one. These aren't equivalent for all iterator +/// categories, and respecting that adds a lot of complexity for little gain. +/// +/// Classes wishing to use `iterator_facade_base` should implement the following +/// methods: +/// +/// Forward Iterators: +/// (All of the following methods) +/// - DerivedT &operator=(const DerivedT &R); +/// - bool operator==(const DerivedT &R) const; +/// - const T &operator*() const; +/// - T &operator*(); +/// - DerivedT &operator++(); +/// +/// Bidirectional Iterators: +/// (All methods of forward iterators, plus the following) +/// - DerivedT &operator--(); +/// +/// Random-access Iterators: +/// (All methods of bidirectional iterators excluding the following) +/// - DerivedT &operator++(); +/// - DerivedT &operator--(); +/// (and plus the following) +/// - bool operator<(const DerivedT &RHS) const; +/// - DifferenceTypeT operator-(const DerivedT &R) const; +/// - DerivedT &operator+=(DifferenceTypeT N); +/// - DerivedT &operator-=(DifferenceTypeT N); +/// +template <typename DerivedT, typename IteratorCategoryT, typename T, + typename DifferenceTypeT = std::ptrdiff_t, typename PointerT = T *, + typename ReferenceT = T &> +class iterator_facade_base + : public std::iterator<IteratorCategoryT, T, DifferenceTypeT, PointerT, + ReferenceT> { +protected: + enum { + IsRandomAccess = std::is_base_of<std::random_access_iterator_tag, + IteratorCategoryT>::value, + IsBidirectional = std::is_base_of<std::bidirectional_iterator_tag, + IteratorCategoryT>::value, + }; + + /// 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(std::is_base_of<iterator_facade_base, DerivedT>::value, + "Must pass the derived type to this template!"); + static_assert( + IsRandomAccess, + "The '+' operator is only defined for random access iterators."); + DerivedT tmp = *static_cast<const DerivedT *>(this); + tmp += n; + return tmp; + } + friend DerivedT operator+(DifferenceTypeT n, const DerivedT &i) { + static_assert( + IsRandomAccess, + "The '+' operator is only defined for random access iterators."); + return i + n; + } + DerivedT operator-(DifferenceTypeT n) const { + static_assert( + IsRandomAccess, + "The '-' operator is only defined for random access iterators."); + DerivedT tmp = *static_cast<const DerivedT *>(this); + tmp -= n; + return tmp; + } + + DerivedT &operator++() { + static_assert(std::is_base_of<iterator_facade_base, DerivedT>::value, + "Must pass the derived type to this template!"); + return static_cast<DerivedT *>(this)->operator+=(1); + } + DerivedT operator++(int) { + DerivedT tmp = *static_cast<DerivedT *>(this); + ++*static_cast<DerivedT *>(this); + return tmp; + } + DerivedT &operator--() { + static_assert( + IsBidirectional, + "The decrement operator is only defined for bidirectional iterators."); + return static_cast<DerivedT *>(this)->operator-=(1); + } + DerivedT operator--(int) { + static_assert( + IsBidirectional, + "The decrement operator is only defined for bidirectional iterators."); + DerivedT tmp = *static_cast<DerivedT *>(this); + --*static_cast<DerivedT *>(this); + return tmp; + } + + bool operator!=(const DerivedT &RHS) const { + return !static_cast<const DerivedT *>(this)->operator==(RHS); + } + + bool operator>(const DerivedT &RHS) const { + static_assert( + IsRandomAccess, + "Relational operators are only defined for random access iterators."); + return !static_cast<const DerivedT *>(this)->operator<(RHS) && + !static_cast<const DerivedT *>(this)->operator==(RHS); + } + bool operator<=(const DerivedT &RHS) const { + static_assert( + IsRandomAccess, + "Relational operators are only defined for random access iterators."); + return !static_cast<const DerivedT *>(this)->operator>(RHS); + } + bool operator>=(const DerivedT &RHS) const { + static_assert( + IsRandomAccess, + "Relational operators are only defined for random access iterators."); + return !static_cast<const DerivedT *>(this)->operator<(RHS); + } + + PointerT operator->() { return &static_cast<DerivedT *>(this)->operator*(); } + PointerT operator->() const { + return &static_cast<const DerivedT *>(this)->operator*(); + } + ReferenceProxy operator[](DifferenceTypeT n) { + static_assert(IsRandomAccess, + "Subscripting is only defined for random access iterators."); + return ReferenceProxy(static_cast<DerivedT *>(this)->operator+(n)); + } + ReferenceProxy operator[](DifferenceTypeT n) const { + static_assert(IsRandomAccess, + "Subscripting is only defined for random access iterators."); + return ReferenceProxy(static_cast<const DerivedT *>(this)->operator+(n)); + } +}; + +/// CRTP base class for adapting an iterator to a different type. +/// +/// This class can be used through CRTP to adapt one iterator into another. +/// Typically this is done through providing in the derived class a custom \c +/// operator* implementation. Other methods can be overridden as well. +template < + typename DerivedT, typename WrappedIteratorT, + typename IteratorCategoryT = + typename std::iterator_traits<WrappedIteratorT>::iterator_category, + typename T = typename std::iterator_traits<WrappedIteratorT>::value_type, + typename DifferenceTypeT = + typename std::iterator_traits<WrappedIteratorT>::difference_type, + typename PointerT = typename std::conditional< + std::is_same<T, typename std::iterator_traits< + WrappedIteratorT>::value_type>::value, + typename std::iterator_traits<WrappedIteratorT>::pointer, T *>::type, + typename ReferenceT = typename std::conditional< + std::is_same<T, typename std::iterator_traits< + WrappedIteratorT>::value_type>::value, + typename std::iterator_traits<WrappedIteratorT>::reference, T &>::type> +class iterator_adaptor_base + : public iterator_facade_base<DerivedT, IteratorCategoryT, T, + DifferenceTypeT, PointerT, ReferenceT> { + using BaseT = typename iterator_adaptor_base::iterator_facade_base; + +protected: + WrappedIteratorT I; + + iterator_adaptor_base() = default; + + explicit iterator_adaptor_base(WrappedIteratorT u) : I(std::move(u)) { + static_assert(std::is_base_of<iterator_adaptor_base, DerivedT>::value, + "Must pass the derived type to this template!"); + } + + const WrappedIteratorT &wrapped() const { return I; } + +public: + using difference_type = DifferenceTypeT; + + DerivedT &operator+=(difference_type n) { + static_assert( + BaseT::IsRandomAccess, + "The '+=' operator is only defined for random access iterators."); + I += n; + return *static_cast<DerivedT *>(this); + } + DerivedT &operator-=(difference_type n) { + static_assert( + BaseT::IsRandomAccess, + "The '-=' operator is only defined for random access iterators."); + I -= n; + return *static_cast<DerivedT *>(this); + } + using BaseT::operator-; + difference_type operator-(const DerivedT &RHS) const { + static_assert( + BaseT::IsRandomAccess, + "The '-' operator is only defined for random access iterators."); + return I - RHS.I; + } + + // We have to explicitly provide ++ and -- rather than letting the facade + // forward to += because WrappedIteratorT might not support +=. + using BaseT::operator++; + DerivedT &operator++() { + ++I; + return *static_cast<DerivedT *>(this); + } + using BaseT::operator--; + DerivedT &operator--() { + static_assert( + BaseT::IsBidirectional, + "The decrement operator is only defined for bidirectional iterators."); + --I; + return *static_cast<DerivedT *>(this); + } + + bool operator==(const DerivedT &RHS) const { return I == RHS.I; } + bool operator<(const DerivedT &RHS) const { + static_assert( + BaseT::IsRandomAccess, + "Relational operators are only defined for random access iterators."); + return I < RHS.I; + } + + ReferenceT operator*() const { return *I; } +}; + +/// An iterator type that allows iterating over the pointees via some +/// other iterator. +/// +/// The typical usage of this is to expose a type that iterates over Ts, but +/// which is implemented with some iterator over T*s: +/// +/// \code +/// using iterator = pointee_iterator<SmallVectorImpl<T *>::iterator>; +/// \endcode +template <typename WrappedIteratorT, + typename T = typename std::remove_reference< + decltype(**std::declval<WrappedIteratorT>())>::type> +struct pointee_iterator + : iterator_adaptor_base< + pointee_iterator<WrappedIteratorT, T>, WrappedIteratorT, + typename std::iterator_traits<WrappedIteratorT>::iterator_category, + T> { + pointee_iterator() = default; + template <typename U> + pointee_iterator(U &&u) + : pointee_iterator::iterator_adaptor_base(std::forward<U &&>(u)) {} + + T &operator*() const { return **this->I; } +}; + +template <typename RangeT, typename WrappedIteratorT = + decltype(std::begin(std::declval<RangeT>()))> +iterator_range<pointee_iterator<WrappedIteratorT>> +make_pointee_range(RangeT &&Range) { + using PointeeIteratorT = pointee_iterator<WrappedIteratorT>; + return make_range(PointeeIteratorT(std::begin(std::forward<RangeT>(Range))), + PointeeIteratorT(std::end(std::forward<RangeT>(Range)))); +} + +template <typename WrappedIteratorT, + typename T = decltype(&*std::declval<WrappedIteratorT>())> +class pointer_iterator + : public iterator_adaptor_base< + pointer_iterator<WrappedIteratorT, T>, WrappedIteratorT, + typename std::iterator_traits<WrappedIteratorT>::iterator_category, + T> { + mutable T Ptr; + +public: + pointer_iterator() = default; + + explicit pointer_iterator(WrappedIteratorT u) + : pointer_iterator::iterator_adaptor_base(std::move(u)) {} + + T &operator*() { return Ptr = &*this->I; } + const T &operator*() const { return Ptr = &*this->I; } +}; + +template <typename RangeT, typename WrappedIteratorT = + decltype(std::begin(std::declval<RangeT>()))> +iterator_range<pointer_iterator<WrappedIteratorT>> +make_pointer_range(RangeT &&Range) { + using PointerIteratorT = pointer_iterator<WrappedIteratorT>; + return make_range(PointerIteratorT(std::begin(std::forward<RangeT>(Range))), + PointerIteratorT(std::end(std::forward<RangeT>(Range)))); +} + +template <typename WrappedIteratorT, + typename T1 = typename std::remove_reference<decltype(**std::declval<WrappedIteratorT>())>::type, + typename T2 = typename std::add_pointer<T1>::type> +using raw_pointer_iterator = pointer_iterator<pointee_iterator<WrappedIteratorT, T1>, T2>; + +// Wrapper iterator over iterator ItType, adding DataRef to the type of ItType, +// to create NodeRef = std::pair<InnerTypeOfItType, DataRef>. +template <typename ItType, typename NodeRef, typename DataRef> +class WrappedPairNodeDataIterator + : public iterator_adaptor_base< + WrappedPairNodeDataIterator<ItType, NodeRef, DataRef>, ItType, + typename std::iterator_traits<ItType>::iterator_category, NodeRef, + std::ptrdiff_t, NodeRef *, NodeRef &> { + using BaseT = iterator_adaptor_base< + WrappedPairNodeDataIterator, ItType, + typename std::iterator_traits<ItType>::iterator_category, NodeRef, + std::ptrdiff_t, NodeRef *, NodeRef &>; + + const DataRef DR; + mutable NodeRef NR; + +public: + WrappedPairNodeDataIterator(ItType Begin, const DataRef DR) + : BaseT(Begin), DR(DR) { + NR.first = DR; + } + + NodeRef &operator*() const { + NR.second = *this->I; + return NR; + } +}; + +} // end namespace llvm + +#endif // LLVM_ADT_ITERATOR_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/iterator_range.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/iterator_range.h new file mode 100644 index 0000000..f038f6b --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/iterator_range.h
@@ -0,0 +1,64 @@ +//===- iterator_range.h - A range adaptor for iterators ---------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// \file +/// This provides a very simple, boring adaptor for a begin and end iterator +/// into a range type. This should be used to build range views that work well +/// with range based for loops and range based constructors. +/// +/// Note that code here follows more standards-based coding conventions as it +/// is mirroring proposed interfaces for standardization. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ITERATOR_RANGE_H +#define LLVM_ADT_ITERATOR_RANGE_H + +#include <iterator> +#include <utility> + +namespace llvm { + +/// A range adaptor for a pair of iterators. +/// +/// This just wraps two iterators into a range-compatible interface. Nothing +/// fancy at all. +template <typename IteratorT> +class iterator_range { + IteratorT begin_iterator, end_iterator; + +public: + //TODO: Add SFINAE to test that the Container's iterators match the range's + // iterators. + template <typename Container> + iterator_range(Container &&c) + //TODO: Consider ADL/non-member begin/end calls. + : begin_iterator(c.begin()), end_iterator(c.end()) {} + iterator_range(IteratorT begin_iterator, IteratorT end_iterator) + : begin_iterator(std::move(begin_iterator)), + end_iterator(std::move(end_iterator)) {} + + IteratorT begin() const { return begin_iterator; } + IteratorT end() const { return end_iterator; } + bool empty() const { return begin_iterator == end_iterator; } +}; + +/// Convenience function for iterating over sub-ranges. +/// +/// This provides a bit of syntactic sugar to make using sub-ranges +/// in for loops a bit easier. Analogous to std::make_pair(). +template <class T> iterator_range<T> make_range(T x, T y) { + return iterator_range<T>(std::move(x), std::move(y)); +} + +template <typename T> iterator_range<T> make_range(std::pair<T, T> p) { + return iterator_range<T>(std::move(p.first), std::move(p.second)); +} + +} + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/ADT/simple_ilist.h b/third_party/llvm-10.0/llvm/include/llvm/ADT/simple_ilist.h new file mode 100644 index 0000000..9257b47 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/ADT/simple_ilist.h
@@ -0,0 +1,314 @@ +//===- llvm/ADT/simple_ilist.h - Simple Intrusive List ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SIMPLE_ILIST_H +#define LLVM_ADT_SIMPLE_ILIST_H + +#include "llvm/ADT/ilist_base.h" +#include "llvm/ADT/ilist_iterator.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/ADT/ilist_node_options.h" +#include "llvm/Support/Compiler.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <functional> +#include <iterator> +#include <utility> + +namespace llvm { + +/// A simple intrusive list implementation. +/// +/// This is a simple intrusive list for a \c T that inherits from \c +/// ilist_node<T>. The list never takes ownership of anything inserted in it. +/// +/// Unlike \a iplist<T> and \a ilist<T>, \a simple_ilist<T> never allocates or +/// deletes values, and has no callback traits. +/// +/// The API for adding nodes include \a push_front(), \a push_back(), and \a +/// insert(). These all take values by reference (not by pointer), except for +/// the range version of \a insert(). +/// +/// There are three sets of API for discarding nodes from the list: \a +/// remove(), which takes a reference to the node to remove, \a erase(), which +/// takes an iterator or iterator range and returns the next one, and \a +/// clear(), which empties out the container. All three are constant time +/// operations. None of these deletes any nodes; in particular, if there is a +/// single node in the list, then these have identical semantics: +/// \li \c L.remove(L.front()); +/// \li \c L.erase(L.begin()); +/// \li \c L.clear(); +/// +/// As a convenience for callers, there are parallel APIs that take a \c +/// Disposer (such as \c std::default_delete<T>): \a removeAndDispose(), \a +/// eraseAndDispose(), and \a clearAndDispose(). These have different names +/// because the extra semantic is otherwise non-obvious. They are equivalent +/// to calling \a std::for_each() on the range to be discarded. +/// +/// The currently available \p Options customize the nodes in the list. The +/// same options must be specified in the \a ilist_node instantation for +/// compatibility (although the order is irrelevant). +/// \li Use \a ilist_tag to designate which ilist_node for a given \p T this +/// list should use. This is useful if a type \p T is part of multiple, +/// independent lists simultaneously. +/// \li Use \a ilist_sentinel_tracking to always (or never) track whether a +/// node is a sentinel. Specifying \c true enables the \a +/// ilist_node::isSentinel() API. Unlike \a ilist_node::isKnownSentinel(), +/// which is only appropriate for assertions, \a ilist_node::isSentinel() is +/// appropriate for real logic. +/// +/// Here are examples of \p Options usage: +/// \li \c simple_ilist<T> gives the defaults. \li \c +/// simple_ilist<T,ilist_sentinel_tracking<true>> enables the \a +/// ilist_node::isSentinel() API. +/// \li \c simple_ilist<T,ilist_tag<A>,ilist_sentinel_tracking<false>> +/// specifies a tag of A and that tracking should be off (even when +/// LLVM_ENABLE_ABI_BREAKING_CHECKS are enabled). +/// \li \c simple_ilist<T,ilist_sentinel_tracking<false>,ilist_tag<A>> is +/// equivalent to the last. +/// +/// See \a is_valid_option for steps on adding a new option. +template <typename T, class... Options> +class simple_ilist + : ilist_detail::compute_node_options<T, Options...>::type::list_base_type, + ilist_detail::SpecificNodeAccess< + typename ilist_detail::compute_node_options<T, Options...>::type> { + static_assert(ilist_detail::check_options<Options...>::value, + "Unrecognized node option!"); + using OptionsT = + typename ilist_detail::compute_node_options<T, Options...>::type; + using list_base_type = typename OptionsT::list_base_type; + ilist_sentinel<OptionsT> Sentinel; + +public: + using value_type = typename OptionsT::value_type; + using pointer = typename OptionsT::pointer; + using reference = typename OptionsT::reference; + using const_pointer = typename OptionsT::const_pointer; + using const_reference = typename OptionsT::const_reference; + using iterator = ilist_iterator<OptionsT, false, false>; + using const_iterator = ilist_iterator<OptionsT, false, true>; + using reverse_iterator = ilist_iterator<OptionsT, true, false>; + using const_reverse_iterator = ilist_iterator<OptionsT, true, true>; + using size_type = size_t; + using difference_type = ptrdiff_t; + + simple_ilist() = default; + ~simple_ilist() = default; + + // No copy constructors. + simple_ilist(const simple_ilist &) = delete; + simple_ilist &operator=(const simple_ilist &) = delete; + + // Move constructors. + simple_ilist(simple_ilist &&X) { splice(end(), X); } + simple_ilist &operator=(simple_ilist &&X) { + clear(); + splice(end(), X); + return *this; + } + + iterator begin() { return ++iterator(Sentinel); } + const_iterator begin() const { return ++const_iterator(Sentinel); } + iterator end() { return iterator(Sentinel); } + const_iterator end() const { return const_iterator(Sentinel); } + reverse_iterator rbegin() { return ++reverse_iterator(Sentinel); } + const_reverse_iterator rbegin() const { + return ++const_reverse_iterator(Sentinel); + } + reverse_iterator rend() { return reverse_iterator(Sentinel); } + const_reverse_iterator rend() const { + return const_reverse_iterator(Sentinel); + } + + /// Check if the list is empty in constant time. + LLVM_NODISCARD bool empty() const { return Sentinel.empty(); } + + /// Calculate the size of the list in linear time. + LLVM_NODISCARD size_type size() const { + return std::distance(begin(), end()); + } + + reference front() { return *begin(); } + const_reference front() const { return *begin(); } + reference back() { return *rbegin(); } + const_reference back() const { return *rbegin(); } + + /// Insert a node at the front; never copies. + void push_front(reference Node) { insert(begin(), Node); } + + /// Insert a node at the back; never copies. + void push_back(reference Node) { insert(end(), Node); } + + /// Remove the node at the front; never deletes. + void pop_front() { erase(begin()); } + + /// Remove the node at the back; never deletes. + void pop_back() { erase(--end()); } + + /// Swap with another list in place using std::swap. + void swap(simple_ilist &X) { std::swap(*this, X); } + + /// Insert a node by reference; never copies. + iterator insert(iterator I, reference Node) { + list_base_type::insertBefore(*I.getNodePtr(), *this->getNodePtr(&Node)); + return iterator(&Node); + } + + /// Insert a range of nodes; never copies. + template <class Iterator> + void insert(iterator I, Iterator First, Iterator Last) { + for (; First != Last; ++First) + insert(I, *First); + } + + /// Clone another list. + template <class Cloner, class Disposer> + void cloneFrom(const simple_ilist &L2, Cloner clone, Disposer dispose) { + clearAndDispose(dispose); + for (const_reference V : L2) + push_back(*clone(V)); + } + + /// Remove a node by reference; never deletes. + /// + /// \see \a erase() for removing by iterator. + /// \see \a removeAndDispose() if the node should be deleted. + void remove(reference N) { list_base_type::remove(*this->getNodePtr(&N)); } + + /// Remove a node by reference and dispose of it. + template <class Disposer> + void removeAndDispose(reference N, Disposer dispose) { + remove(N); + dispose(&N); + } + + /// Remove a node by iterator; never deletes. + /// + /// \see \a remove() for removing by reference. + /// \see \a eraseAndDispose() it the node should be deleted. + iterator erase(iterator I) { + assert(I != end() && "Cannot remove end of list!"); + remove(*I++); + return I; + } + + /// Remove a range of nodes; never deletes. + /// + /// \see \a eraseAndDispose() if the nodes should be deleted. + iterator erase(iterator First, iterator Last) { + list_base_type::removeRange(*First.getNodePtr(), *Last.getNodePtr()); + return Last; + } + + /// Remove a node by iterator and dispose of it. + template <class Disposer> + iterator eraseAndDispose(iterator I, Disposer dispose) { + auto Next = std::next(I); + erase(I); + dispose(&*I); + return Next; + } + + /// Remove a range of nodes and dispose of them. + template <class Disposer> + iterator eraseAndDispose(iterator First, iterator Last, Disposer dispose) { + while (First != Last) + First = eraseAndDispose(First, dispose); + return Last; + } + + /// Clear the list; never deletes. + /// + /// \see \a clearAndDispose() if the nodes should be deleted. + void clear() { Sentinel.reset(); } + + /// Clear the list and dispose of the nodes. + template <class Disposer> void clearAndDispose(Disposer dispose) { + eraseAndDispose(begin(), end(), dispose); + } + + /// Splice in another list. + void splice(iterator I, simple_ilist &L2) { + splice(I, L2, L2.begin(), L2.end()); + } + + /// Splice in a node from another list. + void splice(iterator I, simple_ilist &L2, iterator Node) { + splice(I, L2, Node, std::next(Node)); + } + + /// Splice in a range of nodes from another list. + void splice(iterator I, simple_ilist &, iterator First, iterator Last) { + list_base_type::transferBefore(*I.getNodePtr(), *First.getNodePtr(), + *Last.getNodePtr()); + } + + /// Merge in another list. + /// + /// \pre \c this and \p RHS are sorted. + ///@{ + void merge(simple_ilist &RHS) { merge(RHS, std::less<T>()); } + template <class Compare> void merge(simple_ilist &RHS, Compare comp); + ///@} + + /// Sort the list. + ///@{ + void sort() { sort(std::less<T>()); } + template <class Compare> void sort(Compare comp); + ///@} +}; + +template <class T, class... Options> +template <class Compare> +void simple_ilist<T, Options...>::merge(simple_ilist &RHS, Compare comp) { + if (this == &RHS || RHS.empty()) + return; + iterator LI = begin(), LE = end(); + iterator RI = RHS.begin(), RE = RHS.end(); + while (LI != LE) { + if (comp(*RI, *LI)) { + // Transfer a run of at least size 1 from RHS to LHS. + iterator RunStart = RI++; + RI = std::find_if(RI, RE, [&](reference RV) { return !comp(RV, *LI); }); + splice(LI, RHS, RunStart, RI); + if (RI == RE) + return; + } + ++LI; + } + // Transfer the remaining RHS nodes once LHS is finished. + splice(LE, RHS, RI, RE); +} + +template <class T, class... Options> +template <class Compare> +void simple_ilist<T, Options...>::sort(Compare comp) { + // Vacuously sorted. + if (empty() || std::next(begin()) == end()) + return; + + // Split the list in the middle. + iterator Center = begin(), End = begin(); + while (End != end() && ++End != end()) { + ++Center; + ++End; + } + simple_ilist RHS; + RHS.splice(RHS.end(), *this, Center, end()); + + // Sort the sublists and merge back together. + sort(comp); + RHS.sort(comp); + merge(RHS, comp); +} + +} // end namespace llvm + +#endif // LLVM_ADT_SIMPLE_ILIST_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/AliasAnalysis.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/AliasAnalysis.h new file mode 100644 index 0000000..7c42a26 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/AliasAnalysis.h
@@ -0,0 +1,1218 @@ +//===- llvm/Analysis/AliasAnalysis.h - Alias Analysis Interface -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the generic AliasAnalysis interface, which is used as the +// common interface used by all clients of alias analysis information, and +// implemented by all alias analysis implementations. Mod/Ref information is +// also captured by this interface. +// +// Implementations of this interface must implement the various virtual methods, +// which automatically provides functionality for the entire suite of client +// APIs. +// +// This API identifies memory regions with the MemoryLocation class. The pointer +// component specifies the base memory address of the region. The Size specifies +// the maximum size (in address units) of the memory region, or +// MemoryLocation::UnknownSize if the size is not known. The TBAA tag +// identifies the "type" of the memory reference; see the +// TypeBasedAliasAnalysis class for details. +// +// Some non-obvious details include: +// - Pointers that point to two completely different objects in memory never +// alias, regardless of the value of the Size component. +// - NoAlias doesn't imply inequal pointers. The most obvious example of this +// is two pointers to constant memory. Even if they are equal, constant +// memory is never stored to, so there will never be any dependencies. +// In this and other situations, the pointers may be both NoAlias and +// MustAlias at the same time. The current API can only return one result, +// though this is rarely a problem in practice. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_ALIASANALYSIS_H +#define LLVM_ANALYSIS_ALIASANALYSIS_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Analysis/MemoryLocation.h" +#include "llvm/Analysis/TargetLibraryInfo.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Pass.h" +#include <cstdint> +#include <functional> +#include <memory> +#include <vector> + +namespace llvm { + +class AnalysisUsage; +class BasicAAResult; +class BasicBlock; +class DominatorTree; +class OrderedBasicBlock; +class Value; + +/// The possible results of an alias query. +/// +/// These results are always computed between two MemoryLocation objects as +/// a query to some alias analysis. +/// +/// Note that these are unscoped enumerations because we would like to support +/// implicitly testing a result for the existence of any possible aliasing with +/// a conversion to bool, but an "enum class" doesn't support this. The +/// canonical names from the literature are suffixed and unique anyways, and so +/// they serve as global constants in LLVM for these results. +/// +/// See docs/AliasAnalysis.html for more information on the specific meanings +/// of these values. +enum AliasResult : uint8_t { + /// The two locations do not alias at all. + /// + /// This value is arranged to convert to false, while all other values + /// convert to true. This allows a boolean context to convert the result to + /// a binary flag indicating whether there is the possibility of aliasing. + NoAlias = 0, + /// The two locations may or may not alias. This is the least precise result. + MayAlias, + /// The two locations alias, but only due to a partial overlap. + PartialAlias, + /// The two locations precisely alias each other. + MustAlias, +}; + +/// << operator for AliasResult. +raw_ostream &operator<<(raw_ostream &OS, AliasResult AR); + +/// Flags indicating whether a memory access modifies or references memory. +/// +/// This is no access at all, a modification, a reference, or both +/// a modification and a reference. These are specifically structured such that +/// they form a three bit matrix and bit-tests for 'mod' or 'ref' or 'must' +/// work with any of the possible values. +enum class ModRefInfo : uint8_t { + /// Must is provided for completeness, but no routines will return only + /// Must today. See definition of Must below. + Must = 0, + /// The access may reference the value stored in memory, + /// a mustAlias relation was found, and no mayAlias or partialAlias found. + MustRef = 1, + /// The access may modify the value stored in memory, + /// a mustAlias relation was found, and no mayAlias or partialAlias found. + MustMod = 2, + /// The access may reference, modify or both the value stored in memory, + /// a mustAlias relation was found, and no mayAlias or partialAlias found. + MustModRef = MustRef | MustMod, + /// The access neither references nor modifies the value stored in memory. + NoModRef = 4, + /// The access may reference the value stored in memory. + Ref = NoModRef | MustRef, + /// The access may modify the value stored in memory. + Mod = NoModRef | MustMod, + /// The access may reference and may modify the value stored in memory. + ModRef = Ref | Mod, + + /// About Must: + /// Must is set in a best effort manner. + /// We usually do not try our best to infer Must, instead it is merely + /// another piece of "free" information that is presented when available. + /// Must set means there was certainly a MustAlias found. For calls, + /// where multiple arguments are checked (argmemonly), this translates to + /// only MustAlias or NoAlias was found. + /// Must is not set for RAR accesses, even if the two locations must + /// alias. The reason is that two read accesses translate to an early return + /// of NoModRef. An additional alias check to set Must may be + /// expensive. Other cases may also not set Must(e.g. callCapturesBefore). + /// We refer to Must being *set* when the most significant bit is *cleared*. + /// Conversely we *clear* Must information by *setting* the Must bit to 1. +}; + +LLVM_NODISCARD inline bool isNoModRef(const ModRefInfo MRI) { + return (static_cast<int>(MRI) & static_cast<int>(ModRefInfo::MustModRef)) == + static_cast<int>(ModRefInfo::Must); +} +LLVM_NODISCARD inline bool isModOrRefSet(const ModRefInfo MRI) { + return static_cast<int>(MRI) & static_cast<int>(ModRefInfo::MustModRef); +} +LLVM_NODISCARD inline bool isModAndRefSet(const ModRefInfo MRI) { + return (static_cast<int>(MRI) & static_cast<int>(ModRefInfo::MustModRef)) == + static_cast<int>(ModRefInfo::MustModRef); +} +LLVM_NODISCARD inline bool isModSet(const ModRefInfo MRI) { + return static_cast<int>(MRI) & static_cast<int>(ModRefInfo::MustMod); +} +LLVM_NODISCARD inline bool isRefSet(const ModRefInfo MRI) { + return static_cast<int>(MRI) & static_cast<int>(ModRefInfo::MustRef); +} +LLVM_NODISCARD inline bool isMustSet(const ModRefInfo MRI) { + return !(static_cast<int>(MRI) & static_cast<int>(ModRefInfo::NoModRef)); +} + +LLVM_NODISCARD inline ModRefInfo setMod(const ModRefInfo MRI) { + return ModRefInfo(static_cast<int>(MRI) | + static_cast<int>(ModRefInfo::MustMod)); +} +LLVM_NODISCARD inline ModRefInfo setRef(const ModRefInfo MRI) { + return ModRefInfo(static_cast<int>(MRI) | + static_cast<int>(ModRefInfo::MustRef)); +} +LLVM_NODISCARD inline ModRefInfo setMust(const ModRefInfo MRI) { + return ModRefInfo(static_cast<int>(MRI) & + static_cast<int>(ModRefInfo::MustModRef)); +} +LLVM_NODISCARD inline ModRefInfo setModAndRef(const ModRefInfo MRI) { + return ModRefInfo(static_cast<int>(MRI) | + static_cast<int>(ModRefInfo::MustModRef)); +} +LLVM_NODISCARD inline ModRefInfo clearMod(const ModRefInfo MRI) { + return ModRefInfo(static_cast<int>(MRI) & static_cast<int>(ModRefInfo::Ref)); +} +LLVM_NODISCARD inline ModRefInfo clearRef(const ModRefInfo MRI) { + return ModRefInfo(static_cast<int>(MRI) & static_cast<int>(ModRefInfo::Mod)); +} +LLVM_NODISCARD inline ModRefInfo clearMust(const ModRefInfo MRI) { + return ModRefInfo(static_cast<int>(MRI) | + static_cast<int>(ModRefInfo::NoModRef)); +} +LLVM_NODISCARD inline ModRefInfo unionModRef(const ModRefInfo MRI1, + const ModRefInfo MRI2) { + return ModRefInfo(static_cast<int>(MRI1) | static_cast<int>(MRI2)); +} +LLVM_NODISCARD inline ModRefInfo intersectModRef(const ModRefInfo MRI1, + const ModRefInfo MRI2) { + return ModRefInfo(static_cast<int>(MRI1) & static_cast<int>(MRI2)); +} + +/// The locations at which a function might access memory. +/// +/// These are primarily used in conjunction with the \c AccessKind bits to +/// describe both the nature of access and the locations of access for a +/// function call. +enum FunctionModRefLocation { + /// Base case is no access to memory. + FMRL_Nowhere = 0, + /// Access to memory via argument pointers. + FMRL_ArgumentPointees = 8, + /// Memory that is inaccessible via LLVM IR. + FMRL_InaccessibleMem = 16, + /// Access to any memory. + FMRL_Anywhere = 32 | FMRL_InaccessibleMem | FMRL_ArgumentPointees +}; + +/// Summary of how a function affects memory in the program. +/// +/// Loads from constant globals are not considered memory accesses for this +/// interface. Also, functions may freely modify stack space local to their +/// invocation without having to report it through these interfaces. +enum FunctionModRefBehavior { + /// This function does not perform any non-local loads or stores to memory. + /// + /// This property corresponds to the GCC 'const' attribute. + /// This property corresponds to the LLVM IR 'readnone' attribute. + /// This property corresponds to the IntrNoMem LLVM intrinsic flag. + FMRB_DoesNotAccessMemory = + FMRL_Nowhere | static_cast<int>(ModRefInfo::NoModRef), + + /// The only memory references in this function (if it has any) are + /// non-volatile loads from objects pointed to by its pointer-typed + /// arguments, with arbitrary offsets. + /// + /// This property corresponds to the IntrReadArgMem LLVM intrinsic flag. + FMRB_OnlyReadsArgumentPointees = + FMRL_ArgumentPointees | static_cast<int>(ModRefInfo::Ref), + + /// The only memory references in this function (if it has any) are + /// non-volatile loads and stores from objects pointed to by its + /// pointer-typed arguments, with arbitrary offsets. + /// + /// This property corresponds to the IntrArgMemOnly LLVM intrinsic flag. + FMRB_OnlyAccessesArgumentPointees = + FMRL_ArgumentPointees | static_cast<int>(ModRefInfo::ModRef), + + /// The only memory references in this function (if it has any) are + /// references of memory that is otherwise inaccessible via LLVM IR. + /// + /// This property corresponds to the LLVM IR inaccessiblememonly attribute. + FMRB_OnlyAccessesInaccessibleMem = + FMRL_InaccessibleMem | static_cast<int>(ModRefInfo::ModRef), + + /// The function may perform non-volatile loads and stores of objects + /// pointed to by its pointer-typed arguments, with arbitrary offsets, and + /// it may also perform loads and stores of memory that is otherwise + /// inaccessible via LLVM IR. + /// + /// This property corresponds to the LLVM IR + /// inaccessiblemem_or_argmemonly attribute. + FMRB_OnlyAccessesInaccessibleOrArgMem = FMRL_InaccessibleMem | + FMRL_ArgumentPointees | + static_cast<int>(ModRefInfo::ModRef), + + /// This function does not perform any non-local stores or volatile loads, + /// but may read from any memory location. + /// + /// This property corresponds to the GCC 'pure' attribute. + /// This property corresponds to the LLVM IR 'readonly' attribute. + /// This property corresponds to the IntrReadMem LLVM intrinsic flag. + FMRB_OnlyReadsMemory = FMRL_Anywhere | static_cast<int>(ModRefInfo::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 | static_cast<int>(ModRefInfo::Mod), + + /// This indicates that the function could not be classified into one of the + /// behaviors above. + FMRB_UnknownModRefBehavior = + FMRL_Anywhere | static_cast<int>(ModRefInfo::ModRef) +}; + +// Wrapper method strips bits significant only in FunctionModRefBehavior, +// to obtain a valid ModRefInfo. The benefit of using the wrapper is that if +// ModRefInfo enum changes, the wrapper can be updated to & with the new enum +// entry with all bits set to 1. +LLVM_NODISCARD inline ModRefInfo +createModRefInfo(const FunctionModRefBehavior FMRB) { + return ModRefInfo(FMRB & static_cast<int>(ModRefInfo::ModRef)); +} + +/// This class stores info we want to provide to or retain within an alias +/// query. By default, the root query is stateless and starts with a freshly +/// constructed info object. Specific alias analyses can use this query info to +/// store per-query state that is important for recursive or nested queries to +/// avoid recomputing. To enable preserving this state across multiple queries +/// where safe (due to the IR not changing), use a `BatchAAResults` wrapper. +/// The information stored in an `AAQueryInfo` is currently limitted to the +/// caches used by BasicAA, but can further be extended to fit other AA needs. +class AAQueryInfo { +public: + using LocPair = std::pair<MemoryLocation, MemoryLocation>; + using AliasCacheT = SmallDenseMap<LocPair, AliasResult, 8>; + AliasCacheT AliasCache; + + using IsCapturedCacheT = SmallDenseMap<const Value *, bool, 8>; + IsCapturedCacheT IsCapturedCache; + + AAQueryInfo() : AliasCache(), IsCapturedCache() {} +}; + +class BatchAAResults; + +class AAResults { +public: + // Make these results default constructable and movable. We have to spell + // these out because MSVC won't synthesize them. + AAResults(const TargetLibraryInfo &TLI) : TLI(TLI) {} + AAResults(AAResults &&Arg); + ~AAResults(); + + /// Register a specific AA result. + template <typename AAResultT> void addAAResult(AAResultT &AAResult) { + // FIXME: We should use a much lighter weight system than the usual + // polymorphic pattern because we don't own AAResult. It should + // ideally involve two pointers and no separate allocation. + AAs.emplace_back(new Model<AAResultT>(AAResult, *this)); + } + + /// Register a function analysis ID that the results aggregation depends on. + /// + /// This is used in the new pass manager to implement the invalidation logic + /// where we must invalidate the results aggregation if any of our component + /// analyses become invalid. + void addAADependencyID(AnalysisKey *ID) { AADeps.push_back(ID); } + + /// Handle invalidation events in the new pass manager. + /// + /// The aggregation is invalidated if any of the underlying analyses is + /// invalidated. + bool invalidate(Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &Inv); + + //===--------------------------------------------------------------------===// + /// \name Alias Queries + /// @{ + + /// The main low level interface to the alias analysis implementation. + /// Returns an AliasResult indicating whether the two pointers are aliased to + /// each other. This is the interface that must be implemented by specific + /// alias analysis implementations. + AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB); + + /// A convenience wrapper around the primary \c alias interface. + AliasResult alias(const Value *V1, LocationSize V1Size, const Value *V2, + LocationSize V2Size) { + return alias(MemoryLocation(V1, V1Size), MemoryLocation(V2, V2Size)); + } + + /// A convenience wrapper around the primary \c alias interface. + AliasResult alias(const Value *V1, const Value *V2) { + return alias(V1, LocationSize::unknown(), V2, LocationSize::unknown()); + } + + /// A trivial helper function to check to see if the specified pointers are + /// no-alias. + bool isNoAlias(const MemoryLocation &LocA, const MemoryLocation &LocB) { + return alias(LocA, LocB) == NoAlias; + } + + /// A convenience wrapper around the \c isNoAlias helper interface. + bool isNoAlias(const Value *V1, LocationSize V1Size, const Value *V2, + LocationSize V2Size) { + return isNoAlias(MemoryLocation(V1, V1Size), MemoryLocation(V2, V2Size)); + } + + /// A convenience wrapper around the \c isNoAlias helper interface. + bool isNoAlias(const Value *V1, const Value *V2) { + return isNoAlias(MemoryLocation(V1), MemoryLocation(V2)); + } + + /// A trivial helper function to check to see if the specified pointers are + /// must-alias. + bool isMustAlias(const MemoryLocation &LocA, const MemoryLocation &LocB) { + return alias(LocA, LocB) == MustAlias; + } + + /// A convenience wrapper around the \c isMustAlias helper interface. + bool isMustAlias(const Value *V1, const Value *V2) { + return alias(V1, LocationSize::precise(1), V2, LocationSize::precise(1)) == + MustAlias; + } + + /// Checks whether the given location points to constant memory, or if + /// \p OrLocal is true whether it points to a local alloca. + bool pointsToConstantMemory(const MemoryLocation &Loc, bool OrLocal = false); + + /// A convenience wrapper around the primary \c pointsToConstantMemory + /// interface. + bool pointsToConstantMemory(const Value *P, bool OrLocal = false) { + return pointsToConstantMemory(MemoryLocation(P), OrLocal); + } + + /// @} + //===--------------------------------------------------------------------===// + /// \name Simple mod/ref information + /// @{ + + /// Get the ModRef info associated with a pointer argument of a call. The + /// result's bits are set to indicate the allowed aliasing ModRef kinds. Note + /// that these bits do not necessarily account for the overall behavior of + /// the function, but rather only provide additional per-argument + /// information. This never sets ModRefInfo::Must. + ModRefInfo getArgModRefInfo(const CallBase *Call, unsigned ArgIdx); + + /// Return the behavior of the given call site. + FunctionModRefBehavior getModRefBehavior(const CallBase *Call); + + /// Return the behavior when calling the given function. + FunctionModRefBehavior getModRefBehavior(const Function *F); + + /// Checks if the specified call is known to never read or write memory. + /// + /// Note that if the call only reads from known-constant memory, it is also + /// legal to return true. Also, calls that unwind the stack are legal for + /// this predicate. + /// + /// Many optimizations (such as CSE and LICM) can be performed on such calls + /// without worrying about aliasing properties, and many calls have this + /// property (e.g. calls to 'sin' and 'cos'). + /// + /// This property corresponds to the GCC 'const' attribute. + bool doesNotAccessMemory(const CallBase *Call) { + return getModRefBehavior(Call) == FMRB_DoesNotAccessMemory; + } + + /// Checks if the specified function is known to never read or write memory. + /// + /// Note that if the function only reads from known-constant memory, it is + /// also legal to return true. Also, function that unwind the stack are legal + /// for this predicate. + /// + /// Many optimizations (such as CSE and LICM) can be performed on such calls + /// to such functions without worrying about aliasing properties, and many + /// functions have this property (e.g. 'sin' and 'cos'). + /// + /// This property corresponds to the GCC 'const' attribute. + bool doesNotAccessMemory(const Function *F) { + return getModRefBehavior(F) == FMRB_DoesNotAccessMemory; + } + + /// Checks if the specified call is known to only read from non-volatile + /// memory (or not access memory at all). + /// + /// Calls that unwind the stack are legal for this predicate. + /// + /// This property allows many common optimizations to be performed in the + /// absence of interfering store instructions, such as CSE of strlen calls. + /// + /// This property corresponds to the GCC 'pure' attribute. + bool onlyReadsMemory(const CallBase *Call) { + return onlyReadsMemory(getModRefBehavior(Call)); + } + + /// Checks if the specified function is known to only read from non-volatile + /// memory (or not access memory at all). + /// + /// Functions that unwind the stack are legal for this predicate. + /// + /// This property allows many common optimizations to be performed in the + /// absence of interfering store instructions, such as CSE of strlen calls. + /// + /// This property corresponds to the GCC 'pure' attribute. + bool onlyReadsMemory(const Function *F) { + return onlyReadsMemory(getModRefBehavior(F)); + } + + /// Checks if functions with the specified behavior are known to only read + /// from non-volatile memory (or not access memory at all). + static bool onlyReadsMemory(FunctionModRefBehavior MRB) { + return !isModSet(createModRefInfo(MRB)); + } + + /// 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 !isRefSet(createModRefInfo(MRB)); + } + + /// 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). + static bool onlyAccessesArgPointees(FunctionModRefBehavior MRB) { + return !(MRB & FMRL_Anywhere & ~FMRL_ArgumentPointees); + } + + /// Checks if functions with the specified behavior are known to potentially + /// read or write from objects pointed to be their pointer-typed arguments + /// (with arbitrary offsets). + static bool doesAccessArgPointees(FunctionModRefBehavior MRB) { + return isModOrRefSet(createModRefInfo(MRB)) && + (MRB & FMRL_ArgumentPointees); + } + + /// Checks if functions with the specified behavior are known to read and + /// write at most from memory that is inaccessible from LLVM IR. + static bool onlyAccessesInaccessibleMem(FunctionModRefBehavior MRB) { + return !(MRB & FMRL_Anywhere & ~FMRL_InaccessibleMem); + } + + /// Checks if functions with the specified behavior are known to potentially + /// read or write from memory that is inaccessible from LLVM IR. + static bool doesAccessInaccessibleMem(FunctionModRefBehavior MRB) { + return isModOrRefSet(createModRefInfo(MRB)) && (MRB & FMRL_InaccessibleMem); + } + + /// Checks if functions with the specified behavior are known to read and + /// write at most from memory that is inaccessible from LLVM IR or objects + /// pointed to by their pointer-typed arguments (with arbitrary offsets). + static bool onlyAccessesInaccessibleOrArgMem(FunctionModRefBehavior MRB) { + return !(MRB & FMRL_Anywhere & + ~(FMRL_InaccessibleMem | FMRL_ArgumentPointees)); + } + + /// getModRefInfo (for call sites) - Return information about whether + /// a particular call site modifies or reads the specified memory location. + ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc); + + /// getModRefInfo (for call sites) - A convenience wrapper. + ModRefInfo getModRefInfo(const CallBase *Call, const Value *P, + LocationSize Size) { + return getModRefInfo(Call, MemoryLocation(P, Size)); + } + + /// getModRefInfo (for loads) - Return information about whether + /// a particular load modifies or reads the specified memory location. + ModRefInfo getModRefInfo(const LoadInst *L, const MemoryLocation &Loc); + + /// getModRefInfo (for loads) - A convenience wrapper. + ModRefInfo getModRefInfo(const LoadInst *L, const Value *P, + LocationSize Size) { + return getModRefInfo(L, MemoryLocation(P, Size)); + } + + /// getModRefInfo (for stores) - Return information about whether + /// a particular store modifies or reads the specified memory location. + ModRefInfo getModRefInfo(const StoreInst *S, const MemoryLocation &Loc); + + /// getModRefInfo (for stores) - A convenience wrapper. + ModRefInfo getModRefInfo(const StoreInst *S, const Value *P, + LocationSize Size) { + return getModRefInfo(S, MemoryLocation(P, Size)); + } + + /// getModRefInfo (for fences) - Return information about whether + /// a particular store modifies or reads the specified memory location. + ModRefInfo getModRefInfo(const FenceInst *S, const MemoryLocation &Loc); + + /// getModRefInfo (for fences) - A convenience wrapper. + ModRefInfo getModRefInfo(const FenceInst *S, const Value *P, + LocationSize Size) { + return getModRefInfo(S, MemoryLocation(P, Size)); + } + + /// getModRefInfo (for cmpxchges) - Return information about whether + /// a particular cmpxchg modifies or reads the specified memory location. + ModRefInfo getModRefInfo(const AtomicCmpXchgInst *CX, + const MemoryLocation &Loc); + + /// getModRefInfo (for cmpxchges) - A convenience wrapper. + ModRefInfo getModRefInfo(const AtomicCmpXchgInst *CX, const Value *P, + LocationSize Size) { + return getModRefInfo(CX, MemoryLocation(P, Size)); + } + + /// getModRefInfo (for atomicrmws) - Return information about whether + /// a particular atomicrmw modifies or reads the specified memory location. + ModRefInfo getModRefInfo(const AtomicRMWInst *RMW, const MemoryLocation &Loc); + + /// getModRefInfo (for atomicrmws) - A convenience wrapper. + ModRefInfo getModRefInfo(const AtomicRMWInst *RMW, const Value *P, + LocationSize Size) { + return getModRefInfo(RMW, MemoryLocation(P, Size)); + } + + /// getModRefInfo (for va_args) - Return information about whether + /// a particular va_arg modifies or reads the specified memory location. + ModRefInfo getModRefInfo(const VAArgInst *I, const MemoryLocation &Loc); + + /// getModRefInfo (for va_args) - A convenience wrapper. + ModRefInfo getModRefInfo(const VAArgInst *I, const Value *P, + LocationSize Size) { + return getModRefInfo(I, MemoryLocation(P, Size)); + } + + /// getModRefInfo (for catchpads) - Return information about whether + /// a particular catchpad modifies or reads the specified memory location. + ModRefInfo getModRefInfo(const CatchPadInst *I, const MemoryLocation &Loc); + + /// getModRefInfo (for catchpads) - A convenience wrapper. + ModRefInfo getModRefInfo(const CatchPadInst *I, const Value *P, + LocationSize Size) { + return getModRefInfo(I, MemoryLocation(P, Size)); + } + + /// getModRefInfo (for catchrets) - Return information about whether + /// a particular catchret modifies or reads the specified memory location. + ModRefInfo getModRefInfo(const CatchReturnInst *I, const MemoryLocation &Loc); + + /// getModRefInfo (for catchrets) - A convenience wrapper. + ModRefInfo getModRefInfo(const CatchReturnInst *I, const Value *P, + LocationSize Size) { + return getModRefInfo(I, MemoryLocation(P, Size)); + } + + /// Check whether or not an instruction may read or write the optionally + /// specified memory location. + /// + /// + /// An instruction that doesn't read or write memory may be trivially LICM'd + /// for example. + /// + /// For function calls, this delegates to the alias-analysis specific + /// call-site mod-ref behavior queries. Otherwise it delegates to the specific + /// helpers above. + ModRefInfo getModRefInfo(const Instruction *I, + const Optional<MemoryLocation> &OptLoc) { + AAQueryInfo AAQIP; + return getModRefInfo(I, OptLoc, AAQIP); + } + + /// A convenience wrapper for constructing the memory location. + ModRefInfo getModRefInfo(const Instruction *I, const Value *P, + LocationSize Size) { + return getModRefInfo(I, MemoryLocation(P, Size)); + } + + /// Return information about whether a call and an instruction may refer to + /// the same memory locations. + ModRefInfo getModRefInfo(Instruction *I, const CallBase *Call); + + /// Return information about whether two call sites may refer to the same set + /// of memory locations. See the AA documentation for details: + /// http://llvm.org/docs/AliasAnalysis.html#ModRefInfo + ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2); + + /// Return information about whether a particular call site modifies + /// or reads the specified memory location \p MemLoc before instruction \p I + /// in a BasicBlock. An ordered basic block \p OBB can be used to speed up + /// instruction ordering queries inside the BasicBlock containing \p I. + /// Early exits in callCapturesBefore may lead to ModRefInfo::Must not being + /// set. + ModRefInfo callCapturesBefore(const Instruction *I, + const MemoryLocation &MemLoc, DominatorTree *DT, + OrderedBasicBlock *OBB = nullptr); + + /// A convenience wrapper to synthesize a memory location. + ModRefInfo callCapturesBefore(const Instruction *I, const Value *P, + LocationSize Size, DominatorTree *DT, + OrderedBasicBlock *OBB = nullptr) { + return callCapturesBefore(I, MemoryLocation(P, Size), DT, OBB); + } + + /// @} + //===--------------------------------------------------------------------===// + /// \name Higher level methods for querying mod/ref information. + /// @{ + + /// Check if it is possible for execution of the specified basic block to + /// modify the location Loc. + bool canBasicBlockModify(const BasicBlock &BB, const MemoryLocation &Loc); + + /// A convenience wrapper synthesizing a memory location. + bool canBasicBlockModify(const BasicBlock &BB, const Value *P, + LocationSize Size) { + return canBasicBlockModify(BB, MemoryLocation(P, Size)); + } + + /// Check if it is possible for the execution of the specified instructions + /// to mod\ref (according to the mode) the location Loc. + /// + /// The instructions to consider are all of the instructions in the range of + /// [I1,I2] INCLUSIVE. I1 and I2 must be in the same basic block. + bool canInstructionRangeModRef(const Instruction &I1, const Instruction &I2, + const MemoryLocation &Loc, + const ModRefInfo Mode); + + /// A convenience wrapper synthesizing a memory location. + bool canInstructionRangeModRef(const Instruction &I1, const Instruction &I2, + const Value *Ptr, LocationSize Size, + const ModRefInfo Mode) { + return canInstructionRangeModRef(I1, I2, MemoryLocation(Ptr, Size), Mode); + } + +private: + AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB, + AAQueryInfo &AAQI); + bool pointsToConstantMemory(const MemoryLocation &Loc, AAQueryInfo &AAQI, + bool OrLocal = false); + ModRefInfo getModRefInfo(Instruction *I, const CallBase *Call2, + AAQueryInfo &AAQIP); + ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc, + AAQueryInfo &AAQI); + ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2, + AAQueryInfo &AAQI); + ModRefInfo getModRefInfo(const VAArgInst *V, const MemoryLocation &Loc, + AAQueryInfo &AAQI); + ModRefInfo getModRefInfo(const LoadInst *L, const MemoryLocation &Loc, + AAQueryInfo &AAQI); + ModRefInfo getModRefInfo(const StoreInst *S, const MemoryLocation &Loc, + AAQueryInfo &AAQI); + ModRefInfo getModRefInfo(const FenceInst *S, const MemoryLocation &Loc, + AAQueryInfo &AAQI); + ModRefInfo getModRefInfo(const AtomicCmpXchgInst *CX, + const MemoryLocation &Loc, AAQueryInfo &AAQI); + ModRefInfo getModRefInfo(const AtomicRMWInst *RMW, const MemoryLocation &Loc, + AAQueryInfo &AAQI); + ModRefInfo getModRefInfo(const CatchPadInst *I, const MemoryLocation &Loc, + AAQueryInfo &AAQI); + ModRefInfo getModRefInfo(const CatchReturnInst *I, const MemoryLocation &Loc, + AAQueryInfo &AAQI); + ModRefInfo getModRefInfo(const Instruction *I, + const Optional<MemoryLocation> &OptLoc, + AAQueryInfo &AAQIP) { + if (OptLoc == None) { + if (const auto *Call = dyn_cast<CallBase>(I)) { + return createModRefInfo(getModRefBehavior(Call)); + } + } + + const MemoryLocation &Loc = OptLoc.getValueOr(MemoryLocation()); + + switch (I->getOpcode()) { + case Instruction::VAArg: + return getModRefInfo((const VAArgInst *)I, Loc, AAQIP); + case Instruction::Load: + return getModRefInfo((const LoadInst *)I, Loc, AAQIP); + case Instruction::Store: + return getModRefInfo((const StoreInst *)I, Loc, AAQIP); + case Instruction::Fence: + return getModRefInfo((const FenceInst *)I, Loc, AAQIP); + case Instruction::AtomicCmpXchg: + return getModRefInfo((const AtomicCmpXchgInst *)I, Loc, AAQIP); + case Instruction::AtomicRMW: + return getModRefInfo((const AtomicRMWInst *)I, Loc, AAQIP); + case Instruction::Call: + return getModRefInfo((const CallInst *)I, Loc, AAQIP); + case Instruction::Invoke: + return getModRefInfo((const InvokeInst *)I, Loc, AAQIP); + case Instruction::CatchPad: + return getModRefInfo((const CatchPadInst *)I, Loc, AAQIP); + case Instruction::CatchRet: + return getModRefInfo((const CatchReturnInst *)I, Loc, AAQIP); + default: + return ModRefInfo::NoModRef; + } + } + + class Concept; + + template <typename T> class Model; + + template <typename T> friend class AAResultBase; + + const TargetLibraryInfo &TLI; + + std::vector<std::unique_ptr<Concept>> AAs; + + std::vector<AnalysisKey *> AADeps; + + friend class BatchAAResults; +}; + +/// This class is a wrapper over an AAResults, and it is intended to be used +/// only when there are no IR changes inbetween queries. BatchAAResults is +/// reusing the same `AAQueryInfo` to preserve the state across queries, +/// esentially making AA work in "batch mode". The internal state cannot be +/// cleared, so to go "out-of-batch-mode", the user must either use AAResults, +/// or create a new BatchAAResults. +class BatchAAResults { + AAResults &AA; + AAQueryInfo AAQI; + +public: + BatchAAResults(AAResults &AAR) : AA(AAR), AAQI() {} + AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB) { + return AA.alias(LocA, LocB, AAQI); + } + bool pointsToConstantMemory(const MemoryLocation &Loc, bool OrLocal = false) { + return AA.pointsToConstantMemory(Loc, AAQI, OrLocal); + } + ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc) { + return AA.getModRefInfo(Call, Loc, AAQI); + } + ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2) { + return AA.getModRefInfo(Call1, Call2, AAQI); + } + ModRefInfo getModRefInfo(const Instruction *I, + const Optional<MemoryLocation> &OptLoc) { + return AA.getModRefInfo(I, OptLoc, AAQI); + } + ModRefInfo getModRefInfo(Instruction *I, const CallBase *Call2) { + return AA.getModRefInfo(I, Call2, AAQI); + } + ModRefInfo getArgModRefInfo(const CallBase *Call, unsigned ArgIdx) { + return AA.getArgModRefInfo(Call, ArgIdx); + } + FunctionModRefBehavior getModRefBehavior(const CallBase *Call) { + return AA.getModRefBehavior(Call); + } +}; + +/// Temporary typedef for legacy code that uses a generic \c AliasAnalysis +/// pointer or reference. +using AliasAnalysis = AAResults; + +/// A private abstract base class describing the concept of an individual alias +/// analysis implementation. +/// +/// This interface is implemented by any \c Model instantiation. It is also the +/// interface which a type used to instantiate the model must provide. +/// +/// All of these methods model methods by the same name in the \c +/// AAResults class. Only differences and specifics to how the +/// implementations are called are documented here. +class AAResults::Concept { +public: + virtual ~Concept() = 0; + + /// An update API used internally by the AAResults to provide + /// a handle back to the top level aggregation. + virtual void setAAResults(AAResults *NewAAR) = 0; + + //===--------------------------------------------------------------------===// + /// \name Alias Queries + /// @{ + + /// The main low level interface to the alias analysis implementation. + /// Returns an AliasResult indicating whether the two pointers are aliased to + /// each other. This is the interface that must be implemented by specific + /// alias analysis implementations. + virtual AliasResult alias(const MemoryLocation &LocA, + const MemoryLocation &LocB, AAQueryInfo &AAQI) = 0; + + /// Checks whether the given location points to constant memory, or if + /// \p OrLocal is true whether it points to a local alloca. + virtual bool pointsToConstantMemory(const MemoryLocation &Loc, + AAQueryInfo &AAQI, bool OrLocal) = 0; + + /// @} + //===--------------------------------------------------------------------===// + /// \name Simple mod/ref information + /// @{ + + /// Get the ModRef info associated with a pointer argument of a callsite. The + /// result's bits are set to indicate the allowed aliasing ModRef kinds. Note + /// that these bits do not necessarily account for the overall behavior of + /// the function, but rather only provide additional per-argument + /// information. + virtual ModRefInfo getArgModRefInfo(const CallBase *Call, + unsigned ArgIdx) = 0; + + /// Return the behavior of the given call site. + virtual FunctionModRefBehavior getModRefBehavior(const CallBase *Call) = 0; + + /// Return the behavior when calling the given function. + virtual FunctionModRefBehavior getModRefBehavior(const Function *F) = 0; + + /// getModRefInfo (for call sites) - Return information about whether + /// a particular call site modifies or reads the specified memory location. + virtual ModRefInfo getModRefInfo(const CallBase *Call, + const MemoryLocation &Loc, + AAQueryInfo &AAQI) = 0; + + /// Return information about whether two call sites may refer to the same set + /// of memory locations. See the AA documentation for details: + /// http://llvm.org/docs/AliasAnalysis.html#ModRefInfo + virtual ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2, + AAQueryInfo &AAQI) = 0; + + /// @} +}; + +/// A private class template which derives from \c Concept and wraps some other +/// type. +/// +/// This models the concept by directly forwarding each interface point to the +/// wrapped type which must implement a compatible interface. This provides +/// a type erased binding. +template <typename AAResultT> class AAResults::Model final : public Concept { + AAResultT &Result; + +public: + explicit Model(AAResultT &Result, AAResults &AAR) : Result(Result) { + Result.setAAResults(&AAR); + } + ~Model() override = default; + + void setAAResults(AAResults *NewAAR) override { Result.setAAResults(NewAAR); } + + AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB, + AAQueryInfo &AAQI) override { + return Result.alias(LocA, LocB, AAQI); + } + + bool pointsToConstantMemory(const MemoryLocation &Loc, AAQueryInfo &AAQI, + bool OrLocal) override { + return Result.pointsToConstantMemory(Loc, AAQI, OrLocal); + } + + ModRefInfo getArgModRefInfo(const CallBase *Call, unsigned ArgIdx) override { + return Result.getArgModRefInfo(Call, ArgIdx); + } + + FunctionModRefBehavior getModRefBehavior(const CallBase *Call) override { + return Result.getModRefBehavior(Call); + } + + FunctionModRefBehavior getModRefBehavior(const Function *F) override { + return Result.getModRefBehavior(F); + } + + ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc, + AAQueryInfo &AAQI) override { + return Result.getModRefInfo(Call, Loc, AAQI); + } + + ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2, + AAQueryInfo &AAQI) override { + return Result.getModRefInfo(Call1, Call2, AAQI); + } +}; + +/// A CRTP-driven "mixin" base class to help implement the function alias +/// analysis results concept. +/// +/// Because of the nature of many alias analysis implementations, they often +/// only implement a subset of the interface. This base class will attempt to +/// implement the remaining portions of the interface in terms of simpler forms +/// of the interface where possible, and otherwise provide conservatively +/// correct fallback implementations. +/// +/// Implementors of an alias analysis should derive from this CRTP, and then +/// override specific methods that they wish to customize. There is no need to +/// use virtual anywhere, the CRTP base class does static dispatch to the +/// derived type passed into it. +template <typename DerivedT> class AAResultBase { + // Expose some parts of the interface only to the AAResults::Model + // for wrapping. Specifically, this allows the model to call our + // setAAResults method without exposing it as a fully public API. + friend class AAResults::Model<DerivedT>; + + /// A pointer to the AAResults object that this AAResult is + /// aggregated within. May be null if not aggregated. + AAResults *AAR = nullptr; + + /// Helper to dispatch calls back through the derived type. + DerivedT &derived() { return static_cast<DerivedT &>(*this); } + + /// A setter for the AAResults pointer, which is used to satisfy the + /// AAResults::Model contract. + void setAAResults(AAResults *NewAAR) { AAR = NewAAR; } + +protected: + /// This proxy class models a common pattern where we delegate to either the + /// top-level \c AAResults aggregation if one is registered, or to the + /// current result if none are registered. + class AAResultsProxy { + AAResults *AAR; + DerivedT &CurrentResult; + + public: + AAResultsProxy(AAResults *AAR, DerivedT &CurrentResult) + : AAR(AAR), CurrentResult(CurrentResult) {} + + AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB, + AAQueryInfo &AAQI) { + return AAR ? AAR->alias(LocA, LocB, AAQI) + : CurrentResult.alias(LocA, LocB, AAQI); + } + + bool pointsToConstantMemory(const MemoryLocation &Loc, AAQueryInfo &AAQI, + bool OrLocal) { + return AAR ? AAR->pointsToConstantMemory(Loc, AAQI, OrLocal) + : CurrentResult.pointsToConstantMemory(Loc, AAQI, OrLocal); + } + + ModRefInfo getArgModRefInfo(const CallBase *Call, unsigned ArgIdx) { + return AAR ? AAR->getArgModRefInfo(Call, ArgIdx) + : CurrentResult.getArgModRefInfo(Call, ArgIdx); + } + + FunctionModRefBehavior getModRefBehavior(const CallBase *Call) { + return AAR ? AAR->getModRefBehavior(Call) + : CurrentResult.getModRefBehavior(Call); + } + + FunctionModRefBehavior getModRefBehavior(const Function *F) { + return AAR ? AAR->getModRefBehavior(F) : CurrentResult.getModRefBehavior(F); + } + + ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc, + AAQueryInfo &AAQI) { + return AAR ? AAR->getModRefInfo(Call, Loc, AAQI) + : CurrentResult.getModRefInfo(Call, Loc, AAQI); + } + + ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2, + AAQueryInfo &AAQI) { + return AAR ? AAR->getModRefInfo(Call1, Call2, AAQI) + : CurrentResult.getModRefInfo(Call1, Call2, AAQI); + } + }; + + explicit AAResultBase() = default; + + // Provide all the copy and move constructors so that derived types aren't + // constrained. + 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: + AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB, + AAQueryInfo &AAQI) { + return MayAlias; + } + + bool pointsToConstantMemory(const MemoryLocation &Loc, AAQueryInfo &AAQI, + bool OrLocal) { + return false; + } + + ModRefInfo getArgModRefInfo(const CallBase *Call, unsigned ArgIdx) { + return ModRefInfo::ModRef; + } + + FunctionModRefBehavior getModRefBehavior(const CallBase *Call) { + return FMRB_UnknownModRefBehavior; + } + + FunctionModRefBehavior getModRefBehavior(const Function *F) { + return FMRB_UnknownModRefBehavior; + } + + ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc, + AAQueryInfo &AAQI) { + return ModRefInfo::ModRef; + } + + ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2, + AAQueryInfo &AAQI) { + return ModRefInfo::ModRef; + } +}; + +/// Return true if this pointer is returned by a noalias function. +bool isNoAliasCall(const Value *V); + +/// Return true if this is an argument with the noalias attribute. +bool isNoAliasArgument(const Value *V); + +/// 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 +/// NoAlias returns (e.g. calls to malloc) +/// +bool isIdentifiedObject(const Value *V); + +/// Return true if V is umabigously identified at the function-level. +/// Different IdentifiedFunctionLocals can't alias. +/// Further, an IdentifiedFunctionLocal can not alias with any function +/// arguments other than itself, which is not necessarily true for +/// IdentifiedObjects. +bool isIdentifiedFunctionLocal(const Value *V); + +/// A manager for alias analyses. +/// +/// This class can have analyses registered with it and when run, it will run +/// all of them and aggregate their results into single AA results interface +/// that dispatches across all of the alias analysis results available. +/// +/// Note that the order in which analyses are registered is very significant. +/// That is the order in which the results will be aggregated and queried. +/// +/// 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. +/// +/// The result of this analysis is only invalidated if one of the particular +/// aggregated AA results end up being invalidated. This removes the need to +/// explicitly preserve the results of `AAManager`. Note that analyses should no +/// longer be registered once the `AAManager` is run. +class AAManager : public AnalysisInfoMixin<AAManager> { +public: + using Result = AAResults; + + /// Register a specific AA result. + template <typename AnalysisT> void registerFunctionAnalysis() { + ResultGetters.push_back(&getFunctionAAResultImpl<AnalysisT>); + } + + /// Register a specific AA result. + template <typename AnalysisT> void registerModuleAnalysis() { + ResultGetters.push_back(&getModuleAAResultImpl<AnalysisT>); + } + + Result run(Function &F, FunctionAnalysisManager &AM) { + Result R(AM.getResult<TargetLibraryAnalysis>(F)); + for (auto &Getter : ResultGetters) + (*Getter)(F, AM, R); + return R; + } + +private: + friend AnalysisInfoMixin<AAManager>; + + static AnalysisKey Key; + + SmallVector<void (*)(Function &F, FunctionAnalysisManager &AM, + AAResults &AAResults), + 4> ResultGetters; + + template <typename AnalysisT> + static void getFunctionAAResultImpl(Function &F, + FunctionAnalysisManager &AM, + AAResults &AAResults) { + AAResults.addAAResult(AM.template getResult<AnalysisT>(F)); + AAResults.addAADependencyID(AnalysisT::ID()); + } + + template <typename AnalysisT> + static void getModuleAAResultImpl(Function &F, FunctionAnalysisManager &AM, + AAResults &AAResults) { + auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F); + auto &MAM = MAMProxy.getManager(); + if (auto *R = MAM.template getCachedResult<AnalysisT>(*F.getParent())) { + AAResults.addAAResult(*R); + MAMProxy + .template registerOuterAnalysisInvalidation<AnalysisT, AAManager>(); + } + } +}; + +/// A wrapper pass to provide the legacy pass manager access to a suitably +/// prepared AAResults object. +class AAResultsWrapperPass : public FunctionPass { + std::unique_ptr<AAResults> AAR; + +public: + static char ID; + + AAResultsWrapperPass(); + + AAResults &getAAResults() { return *AAR; } + const AAResults &getAAResults() const { return *AAR; } + + bool runOnFunction(Function &F) override; + + void getAnalysisUsage(AnalysisUsage &AU) const override; +}; + +/// A wrapper pass for external alias analyses. This just squirrels away the +/// callback used to run any analyses and register their results. +struct ExternalAAWrapperPass : ImmutablePass { + using CallbackT = std::function<void(Pass &, Function &, AAResults &)>; + + CallbackT CB; + + static char ID; + + ExternalAAWrapperPass(); + + explicit ExternalAAWrapperPass(CallbackT CB); + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + } +}; + +FunctionPass *createAAResultsWrapperPass(); + +/// A wrapper pass around a callback which can be used to populate the +/// AAResults in the AAResultsWrapperPass from an external AA. +/// +/// The callback provided here will be used each time we prepare an AAResults +/// object, and will receive a reference to the function wrapper pass, the +/// function, and the AAResults object to populate. This should be used when +/// setting up a custom pass pipeline to inject a hook into the AA results. +ImmutablePass *createExternalAAWrapperPass( + std::function<void(Pass &, Function &, AAResults &)> Callback); + +/// 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 namespace llvm + +#endif // LLVM_ANALYSIS_ALIASANALYSIS_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/AliasAnalysisEvaluator.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/AliasAnalysisEvaluator.h new file mode 100644 index 0000000..972ecea --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/AliasAnalysisEvaluator.h
@@ -0,0 +1,73 @@ +//===- AliasAnalysisEvaluator.h - Alias Analysis Accuracy Evaluator -------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// \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; + int64_t MustCount, MustRefCount, MustModCount, MustModRefCount; + +public: + AAEvaluator() + : FunctionCount(), NoAliasCount(), MayAliasCount(), PartialAliasCount(), + MustAliasCount(), NoModRefCount(), ModCount(), RefCount(), + ModRefCount(), MustCount(), MustRefCount(), MustModCount(), + MustModRefCount() {} + 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), MustCount(Arg.MustCount), + MustRefCount(Arg.MustRefCount), MustModCount(Arg.MustModCount), + MustModRefCount(Arg.MustModRefCount) { + Arg.FunctionCount = 0; + } + ~AAEvaluator(); + + /// Run the pass over the function. + PreservedAnalyses run(Function &F, FunctionAnalysisManager &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
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/AliasSetTracker.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/AliasSetTracker.h new file mode 100644 index 0000000..e94a758 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/AliasSetTracker.h
@@ -0,0 +1,467 @@ +//===- llvm/Analysis/AliasSetTracker.h - Build Alias Sets -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// 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 +// object refers to memory disjoint from the other sets. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_ALIASSETTRACKER_H +#define LLVM_ANALYSIS_ALIASSETTRACKER_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/ADT/ilist.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Metadata.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/Support/Casting.h" +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <iterator> +#include <vector> + +namespace llvm { + +class AliasSetTracker; +class BasicBlock; +class LoadInst; +class Loop; +class MemorySSA; +class AnyMemSetInst; +class AnyMemTransferInst; +class raw_ostream; +class StoreInst; +class VAArgInst; +class Value; + +class AliasSet : public ilist_node<AliasSet> { + friend class AliasSetTracker; + + class PointerRec { + Value *Val; // The pointer this record corresponds to. + PointerRec **PrevInList = nullptr; + PointerRec *NextInList = nullptr; + AliasSet *AS = nullptr; + LocationSize Size = LocationSize::mapEmpty(); + AAMDNodes AAInfo; + + // Whether the size for this record has been set at all. This makes no + // guarantees about the size being known. + bool isSizeSet() const { return Size != LocationSize::mapEmpty(); } + + public: + PointerRec(Value *V) + : Val(V), AAInfo(DenseMapInfo<AAMDNodes>::getEmptyKey()) {} + + Value *getValue() const { return Val; } + + PointerRec *getNext() const { return NextInList; } + bool hasAliasSet() const { return AS != nullptr; } + + PointerRec** setPrevInList(PointerRec **PIL) { + PrevInList = PIL; + return &NextInList; + } + + bool updateSizeAndAAInfo(LocationSize NewSize, const AAMDNodes &NewAAInfo) { + bool SizeChanged = false; + if (NewSize != Size) { + LocationSize OldSize = Size; + Size = isSizeSet() ? Size.unionWith(NewSize) : NewSize; + SizeChanged = OldSize != Size; + } + + if (AAInfo == DenseMapInfo<AAMDNodes>::getEmptyKey()) + // We don't have a AAInfo yet. Set it to NewAAInfo. + AAInfo = NewAAInfo; + else { + AAMDNodes Intersection(AAInfo.intersect(NewAAInfo)); + if (!Intersection.TBAA || !Intersection.Scope || + !Intersection.NoAlias) { + // NewAAInfo conflicts with AAInfo. + AAInfo = DenseMapInfo<AAMDNodes>::getTombstoneKey(); + SizeChanged = true; + } + AAInfo = Intersection; + } + return SizeChanged; + } + + LocationSize getSize() const { + assert(isSizeSet() && "Getting an unset size!"); + return Size; + } + + /// 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() || + AAInfo == DenseMapInfo<AAMDNodes>::getTombstoneKey()) + return AAMDNodes(); + return AAInfo; + } + + AliasSet *getAliasSet(AliasSetTracker &AST) { + assert(AS && "No AliasSet yet!"); + if (AS->Forward) { + AliasSet *OldAS = AS; + AS = OldAS->getForwardedTarget(AST); + AS->addRef(); + OldAS->dropRef(AST); + } + return AS; + } + + void setAliasSet(AliasSet *as) { + assert(!AS && "Already have an alias set!"); + AS = as; + } + + void eraseFromList() { + if (NextInList) NextInList->PrevInList = PrevInList; + *PrevInList = NextInList; + if (AS->PtrListEnd == &NextInList) { + AS->PtrListEnd = PrevInList; + assert(*AS->PtrListEnd == nullptr && "List not terminated right!"); + } + delete this; + } + }; + + // Doubly linked list of nodes. + PointerRec *PtrList = nullptr; + PointerRec **PtrListEnd; + // Forwarding pointer. + AliasSet *Forward = nullptr; + + /// All instructions without a specific address in this alias set. + /// In rare cases this vector can have a null'ed out WeakVH + /// instances (can happen if some other loop pass deletes an + /// instruction in this list). + std::vector<WeakVH> UnknownInsts; + + /// Number of nodes pointing to this AliasSet plus the number of AliasSets + /// forwarding to it. + unsigned RefCount : 27; + + // Signifies that this set should be considered to alias any pointer. + // Use when the tracker holding this set is saturated. + unsigned AliasAny : 1; + + /// The kinds of access this alias set models. + /// + /// We keep track of whether this alias set merely refers to the locations of + /// memory (and not any particular access), whether it modifies or references + /// the memory, or whether it does both. The lattice goes from "NoAccess" to + /// either RefAccess or ModAccess, then to ModRefAccess as necessary. + enum AccessLattice { + NoAccess = 0, + RefAccess = 1, + ModAccess = 2, + ModRefAccess = RefAccess | ModAccess + }; + unsigned Access : 2; + + /// The kind of alias relationship between pointers of the set. + /// + /// These represent conservatively correct alias results between any members + /// of the set. We represent these independently of the values of alias + /// results in order to pack it into a single bit. Lattice goes from + /// MustAlias to MayAlias. + enum AliasLattice { + SetMustAlias = 0, SetMayAlias = 1 + }; + unsigned Alias : 1; + + unsigned SetSize = 0; + + void addRef() { ++RefCount; } + + void dropRef(AliasSetTracker &AST) { + assert(RefCount >= 1 && "Invalid reference count detected!"); + if (--RefCount == 0) + removeFromTracker(AST); + } + + Instruction *getUnknownInst(unsigned i) const { + assert(i < UnknownInsts.size()); + return cast_or_null<Instruction>(UnknownInsts[i]); + } + +public: + AliasSet(const AliasSet &) = delete; + AliasSet &operator=(const AliasSet &) = delete; + + /// Accessors... + bool isRef() const { return Access & RefAccess; } + bool isMod() const { return Access & ModAccess; } + bool isMustAlias() const { return Alias == SetMustAlias; } + bool isMayAlias() const { return Alias == SetMayAlias; } + + /// Return true if this alias set should be ignored as part of the + /// AliasSetTracker object. + bool isForwardingAliasSet() const { return Forward; } + + /// Merge the specified alias set into this alias set. + void mergeSetIn(AliasSet &AS, AliasSetTracker &AST); + + // 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(); } + bool empty() const { return PtrList == nullptr; } + + // Unfortunately, ilist::size() is linear, so we have to add code to keep + // track of the list's exact size. + unsigned size() { return SetSize; } + + /// If this alias set is known to contain a single instruction and *only* a + /// single unique instruction, return it. Otherwise, return nullptr. + Instruction* getUniqueInstruction(); + + void print(raw_ostream &OS) const; + void dump() const; + + /// Define an iterator for alias sets... this is just a forward iterator. + class iterator : public std::iterator<std::forward_iterator_tag, + PointerRec, ptrdiff_t> { + PointerRec *CurNode; + + public: + explicit iterator(PointerRec *CN = nullptr) : CurNode(CN) {} + + bool operator==(const iterator& x) const { + return CurNode == x.CurNode; + } + bool operator!=(const iterator& x) const { return !operator==(x); } + + value_type &operator*() const { + assert(CurNode && "Dereferencing AliasSet.end()!"); + return *CurNode; + } + value_type *operator->() const { return &operator*(); } + + Value *getPointer() const { return CurNode->getValue(); } + LocationSize getSize() const { return CurNode->getSize(); } + AAMDNodes getAAInfo() const { return CurNode->getAAInfo(); } + + iterator& operator++() { // Preincrement + assert(CurNode && "Advancing past AliasSet.end()!"); + CurNode = CurNode->getNext(); + return *this; + } + iterator operator++(int) { // Postincrement + iterator tmp = *this; ++*this; return tmp; + } + }; + +private: + // Can only be created by AliasSetTracker. + AliasSet() + : PtrListEnd(&PtrList), RefCount(0), AliasAny(false), Access(NoAccess), + Alias(SetMustAlias) {} + + PointerRec *getSomePointer() const { + return PtrList; + } + + /// 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; + + AliasSet *Dest = Forward->getForwardedTarget(AST); + if (Dest != Forward) { + Dest->addRef(); + Forward->dropRef(AST); + Forward = Dest; + } + return Dest; + } + + void removeFromTracker(AliasSetTracker &AST); + + void addPointer(AliasSetTracker &AST, PointerRec &Entry, LocationSize Size, + const AAMDNodes &AAInfo, bool KnownMustAlias = false, + bool SkipSizeUpdate = false); + void addUnknownInst(Instruction *I, AliasAnalysis &AA); + + void removeUnknownInst(AliasSetTracker &AST, Instruction *I) { + bool WasEmpty = UnknownInsts.empty(); + for (size_t i = 0, e = UnknownInsts.size(); i != e; ++i) + if (UnknownInsts[i] == I) { + UnknownInsts[i] = UnknownInsts.back(); + UnknownInsts.pop_back(); + --i; --e; // Revisit the moved entry. + } + if (!WasEmpty && UnknownInsts.empty()) + dropRef(AST); + } + +public: + /// If the specified pointer "may" (or must) alias one of the members in the + /// set return the appropriate AliasResult. Otherwise return NoAlias. + AliasResult aliasesPointer(const Value *Ptr, LocationSize Size, + const AAMDNodes &AAInfo, AliasAnalysis &AA) const; + bool aliasesUnknownInst(const Instruction *Inst, AliasAnalysis &AA) const; +}; + +inline raw_ostream& operator<<(raw_ostream &OS, const AliasSet &AS) { + AS.print(OS); + return OS; +} + +class AliasSetTracker { + /// A CallbackVH to arrange for AliasSetTracker to be notified whenever a + /// Value is deleted. + class ASTCallbackVH final : public CallbackVH { + AliasSetTracker *AST; + + void deleted() override; + void allUsesReplacedWith(Value *) override; + + public: + ASTCallbackVH(Value *V, AliasSetTracker *AST = nullptr); + + ASTCallbackVH &operator=(Value *V); + }; + /// Traits to tell DenseMap that tell us how to compare and hash the value + /// handle. + struct ASTCallbackVHDenseMapInfo : public DenseMapInfo<Value *> {}; + + AliasAnalysis &AA; + MemorySSA *MSSA = nullptr; + Loop *L = nullptr; + ilist<AliasSet> AliasSets; + + using PointerMapType = DenseMap<ASTCallbackVH, AliasSet::PointerRec *, + ASTCallbackVHDenseMapInfo>; + + // Map from pointers to their node + PointerMapType PointerMap; + +public: + /// 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) {} + explicit AliasSetTracker(AliasAnalysis &aa, MemorySSA *mssa, Loop *l) + : AA(aa), MSSA(mssa), L(l) {} + ~AliasSetTracker() { clear(); } + + /// 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 + /// 3. If the instruction aliases multiple sets, merge the sets, and add + /// the instruction to the result. + /// + /// These methods return true if inserting the instruction resulted in the + /// addition of a new alias set (i.e., the pointer did not alias anything). + /// + void add(Value *Ptr, LocationSize Size, const AAMDNodes &AAInfo); // Add a loc + void add(LoadInst *LI); + void add(StoreInst *SI); + void add(VAArgInst *VAAI); + void add(AnyMemSetInst *MSI); + void add(AnyMemTransferInst *MTI); + void 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 + void addUnknown(Instruction *I); + void addAllInstructionsInLoopUsingMSSA(); + + void clear(); + + /// Return the alias sets that are active. + const ilist<AliasSet> &getAliasSets() const { return AliasSets; } + + /// Return the alias set which contains the specified memory location. If + /// the memory location aliases two or more existing alias sets, will have + /// the effect of merging those alias sets before the single resulting alias + /// set is returned. + AliasSet &getAliasSetFor(const MemoryLocation &MemLoc); + + /// Return the underlying alias analysis object used by this tracker. + AliasAnalysis &getAliasAnalysis() const { return AA; } + + /// 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); + + /// 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); + + using iterator = ilist<AliasSet>::iterator; + using const_iterator = ilist<AliasSet>::const_iterator; + + const_iterator begin() const { return AliasSets.begin(); } + const_iterator end() const { return AliasSets.end(); } + + iterator begin() { return AliasSets.begin(); } + iterator end() { return AliasSets.end(); } + + void print(raw_ostream &OS) const; + void dump() const; + +private: + friend class AliasSet; + + // The total number of pointers contained in all "may" alias sets. + unsigned TotalMayAliasSetSize = 0; + + // A non-null value signifies this AST is saturated. A saturated AST lumps + // all pointers into a single "May" set. + AliasSet *AliasAnyAS = nullptr; + + void removeAliasSet(AliasSet *AS); + + /// 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) + Entry = new AliasSet::PointerRec(V); + return *Entry; + } + + AliasSet &addPointer(MemoryLocation Loc, AliasSet::AccessLattice E); + AliasSet *mergeAliasSetsForPointer(const Value *Ptr, LocationSize Size, + const AAMDNodes &AAInfo, + bool &MustAliasAll); + + /// Merge all alias sets into a single set that is considered to alias any + /// pointer. + AliasSet &mergeAllAliasSets(); + + AliasSet *findAliasSetForUnknownInst(Instruction *Inst); +}; + +inline raw_ostream& operator<<(raw_ostream &OS, const AliasSetTracker &AST) { + AST.print(OS); + return OS; +} + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_ALIASSETTRACKER_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/AssumptionCache.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/AssumptionCache.h new file mode 100644 index 0000000..0efbd59 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/AssumptionCache.h
@@ -0,0 +1,239 @@ +//===- llvm/Analysis/AssumptionCache.h - Track @llvm.assume -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains a pass that keeps track of @llvm.assume intrinsics in +// the functions of a module (allowing assumptions within any function to be +// found cheaply by other parts of the optimizer). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_ASSUMPTIONCACHE_H +#define LLVM_ANALYSIS_ASSUMPTIONCACHE_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/IR/PassManager.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/Pass.h" +#include <memory> + +namespace llvm { + +class CallInst; +class Function; +class raw_ostream; +class Value; + +/// A cache of \@llvm.assume calls within a function. +/// +/// This cache provides fast lookup of assumptions within a function by caching +/// them and amortizing the cost of scanning for them across all queries. Passes +/// that create new assumptions are required to call registerAssumption() to +/// register any new \@llvm.assume calls that they create. Deletions of +/// \@llvm.assume calls do not require special handling. +class AssumptionCache { + /// The function for which this cache is handling assumptions. + /// + /// We track this to lazily populate our assumptions. + Function &F; + + /// Vector of weak value handles to calls of the \@llvm.assume + /// intrinsic. + SmallVector<WeakTrackingVH, 4> AssumeHandles; + + class AffectedValueCallbackVH final : public CallbackVH { + AssumptionCache *AC; + + void deleted() override; + void allUsesReplacedWith(Value *) override; + + public: + using DMI = DenseMapInfo<Value *>; + + AffectedValueCallbackVH(Value *V, AssumptionCache *AC = nullptr) + : CallbackVH(V), AC(AC) {} + }; + + friend AffectedValueCallbackVH; + + /// A map of values about which an assumption might be providing + /// information to the relevant set of assumptions. + using AffectedValuesMap = + DenseMap<AffectedValueCallbackVH, SmallVector<WeakTrackingVH, 1>, + AffectedValueCallbackVH::DMI>; + AffectedValuesMap AffectedValues; + + /// Get the vector of assumptions which affect a value from the cache. + SmallVector<WeakTrackingVH, 1> &getOrInsertAffectedValues(Value *V); + + /// Move affected values in the cache for OV to be affected values for NV. + void transferAffectedValuesInCache(Value *OV, Value *NV); + + /// Flag tracking whether we have scanned the function yet. + /// + /// We want to be as lazy about this as possible, and so we scan the function + /// at the last moment. + bool Scanned = false; + + /// Scan the function for assumptions and add them to the cache. + void scanFunction(); + +public: + /// Construct an AssumptionCache from a function by scanning all of + /// its instructions. + AssumptionCache(Function &F) : F(F) {} + + /// This cache is designed to be self-updating and so it should never be + /// invalidated. + bool invalidate(Function &, const PreservedAnalyses &, + FunctionAnalysisManager::Invalidator &) { + return false; + } + + /// Add an \@llvm.assume intrinsic to this function's cache. + /// + /// The call passed in must be an instruction within this function and must + /// not already be in the cache. + void registerAssumption(CallInst *CI); + + /// Remove an \@llvm.assume intrinsic from this function's cache if it has + /// been added to the cache earlier. + void unregisterAssumption(CallInst *CI); + + /// Update the cache of values being affected by this assumption (i.e. + /// the values about which this assumption provides information). + void updateAffectedValues(CallInst *CI); + + /// Clear the cache of \@llvm.assume intrinsics for a function. + /// + /// It will be re-scanned the next time it is requested. + void clear() { + AssumeHandles.clear(); + AffectedValues.clear(); + Scanned = false; + } + + /// Access the list of assumption handles currently tracked for this + /// function. + /// + /// Note that these produce weak handles that may be null. The caller must + /// handle that case. + /// FIXME: We should replace this with pointee_iterator<filter_iterator<...>> + /// when we can write that to filter out the null values. Then caller code + /// will become simpler. + MutableArrayRef<WeakTrackingVH> assumptions() { + if (!Scanned) + scanFunction(); + return AssumeHandles; + } + + /// Access the list of assumptions which affect this value. + MutableArrayRef<WeakTrackingVH> assumptionsFor(const Value *V) { + if (!Scanned) + scanFunction(); + + auto AVI = AffectedValues.find_as(const_cast<Value *>(V)); + if (AVI == AffectedValues.end()) + return MutableArrayRef<WeakTrackingVH>(); + + return AVI->second; + } +}; + +/// A function analysis which provides an \c AssumptionCache. +/// +/// This analysis is intended for use with the new pass manager and will vend +/// assumption caches for a given function. +class AssumptionAnalysis : public AnalysisInfoMixin<AssumptionAnalysis> { + friend AnalysisInfoMixin<AssumptionAnalysis>; + + static AnalysisKey Key; + +public: + using Result = AssumptionCache; + + AssumptionCache run(Function &F, FunctionAnalysisManager &) { + return AssumptionCache(F); + } +}; + +/// Printer pass for the \c AssumptionAnalysis results. +class AssumptionPrinterPass : public PassInfoMixin<AssumptionPrinterPass> { + raw_ostream &OS; + +public: + explicit AssumptionPrinterPass(raw_ostream &OS) : OS(OS) {} + + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + +/// An immutable pass that tracks lazily created \c AssumptionCache +/// objects. +/// +/// This is essentially a workaround for the legacy pass manager's weaknesses +/// which associates each assumption cache with Function and clears it if the +/// function is deleted. The nature of the AssumptionCache is that it is not +/// invalidated by any changes to the function body and so this is sufficient +/// to be conservatively correct. +class AssumptionCacheTracker : public ImmutablePass { + /// A callback value handle applied to function objects, which we use to + /// delete our cache of intrinsics for a function when it is deleted. + class FunctionCallbackVH final : public CallbackVH { + AssumptionCacheTracker *ACT; + + void deleted() override; + + public: + using DMI = DenseMapInfo<Value *>; + + FunctionCallbackVH(Value *V, AssumptionCacheTracker *ACT = nullptr) + : CallbackVH(V), ACT(ACT) {} + }; + + friend FunctionCallbackVH; + + using FunctionCallsMap = + DenseMap<FunctionCallbackVH, std::unique_ptr<AssumptionCache>, + FunctionCallbackVH::DMI>; + + FunctionCallsMap AssumptionCaches; + +public: + /// Get the cached assumptions for a function. + /// + /// If no assumptions are cached, this will scan the function. Otherwise, the + /// existing cache will be returned. + AssumptionCache &getAssumptionCache(Function &F); + + /// Return the cached assumptions for a function if it has already been + /// scanned. Otherwise return nullptr. + AssumptionCache *lookupAssumptionCache(Function &F); + + AssumptionCacheTracker(); + ~AssumptionCacheTracker() override; + + void releaseMemory() override { + verifyAnalysis(); + AssumptionCaches.shrink_and_clear(); + } + + void verifyAnalysis() const override; + + bool doFinalization(Module &) override { + verifyAnalysis(); + return false; + } + + static char ID; // Pass identification, replacement for typeid +}; + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_ASSUMPTIONCACHE_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/BasicAliasAnalysis.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/BasicAliasAnalysis.h new file mode 100644 index 0000000..22e8c4b --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/BasicAliasAnalysis.h
@@ -0,0 +1,277 @@ +//===- BasicAliasAnalysis.h - Stateless, local Alias Analysis ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// \file +/// This is the interface for LLVM's primary stateless and local alias analysis. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_BASICALIASANALYSIS_H +#define LLVM_ANALYSIS_BASICALIASANALYSIS_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/AssumptionCache.h" +#include "llvm/Analysis/MemoryLocation.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Pass.h" +#include <algorithm> +#include <cstdint> +#include <memory> +#include <utility> + +namespace llvm { + +struct AAMDNodes; +class APInt; +class AssumptionCache; +class BasicBlock; +class DataLayout; +class DominatorTree; +class Function; +class GEPOperator; +class LoopInfo; +class PHINode; +class SelectInst; +class TargetLibraryInfo; +class PhiValues; +class Value; + +/// This is the AA result object for the basic, local, and stateless alias +/// analysis. It implements the AA query interface in an entirely stateless +/// manner. As one consequence, it is never invalidated due to IR changes. +/// While it does retain some storage, that is used as an optimization and not +/// to preserve information from query to query. However it does retain handles +/// to various other analyses and must be recomputed when those analyses are. +class BasicAAResult : public AAResultBase<BasicAAResult> { + friend AAResultBase<BasicAAResult>; + + const DataLayout &DL; + const Function &F; + const TargetLibraryInfo &TLI; + AssumptionCache &AC; + DominatorTree *DT; + LoopInfo *LI; + PhiValues *PV; + +public: + BasicAAResult(const DataLayout &DL, const Function &F, + const TargetLibraryInfo &TLI, AssumptionCache &AC, + DominatorTree *DT = nullptr, LoopInfo *LI = nullptr, + PhiValues *PV = nullptr) + : AAResultBase(), DL(DL), F(F), TLI(TLI), AC(AC), DT(DT), LI(LI), PV(PV) + {} + + BasicAAResult(const BasicAAResult &Arg) + : AAResultBase(Arg), DL(Arg.DL), F(Arg.F), TLI(Arg.TLI), AC(Arg.AC), + DT(Arg.DT), LI(Arg.LI), PV(Arg.PV) {} + BasicAAResult(BasicAAResult &&Arg) + : AAResultBase(std::move(Arg)), DL(Arg.DL), F(Arg.F), TLI(Arg.TLI), + AC(Arg.AC), DT(Arg.DT), LI(Arg.LI), PV(Arg.PV) {} + + /// Handle invalidation events in the new pass manager. + bool invalidate(Function &Fn, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &Inv); + + AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB, + AAQueryInfo &AAQI); + + ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc, + AAQueryInfo &AAQI); + + ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2, + AAQueryInfo &AAQI); + + /// Chases pointers until we find a (constant global) or not. + bool pointsToConstantMemory(const MemoryLocation &Loc, AAQueryInfo &AAQI, + bool OrLocal); + + /// Get the location associated with a pointer argument of a callsite. + ModRefInfo getArgModRefInfo(const CallBase *Call, unsigned ArgIdx); + + /// Returns the behavior when calling the given call site. + FunctionModRefBehavior getModRefBehavior(const CallBase *Call); + + /// Returns the behavior when calling the given function. For use when the + /// call site is not known. + FunctionModRefBehavior getModRefBehavior(const Function *Fn); + +private: + // A linear transformation of a Value; this class represents ZExt(SExt(V, + // SExtBits), ZExtBits) * Scale + Offset. + struct VariableGEPIndex { + // An opaque Value - we can't decompose this further. + const Value *V; + + // We need to track what extensions we've done as we consider the same Value + // with different extensions as different variables in a GEP's linear + // expression; + // e.g.: if V == -1, then sext(x) != zext(x). + unsigned ZExtBits; + unsigned SExtBits; + + APInt Scale; + + bool operator==(const VariableGEPIndex &Other) const { + return V == Other.V && ZExtBits == Other.ZExtBits && + SExtBits == Other.SExtBits && Scale == Other.Scale; + } + + bool operator!=(const VariableGEPIndex &Other) const { + return !operator==(Other); + } + }; + + // 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 + APInt StructOffset; + // Total constant offset w.r.t the base from indexing through + // pointers/arrays/vectors + APInt OtherOffset; + // Scaled variable (non-constant) indices. + SmallVector<VariableGEPIndex, 4> VarIndices; + }; + + /// Tracks phi nodes we have visited. + /// + /// When interpret "Value" pointer equality as value equality we need to make + /// sure that the "Value" is not part of a cycle. Otherwise, two uses could + /// come from different "iterations" of a cycle and see different values for + /// the same "Value" pointer. + /// + /// The following example shows the problem: + /// %p = phi(%alloca1, %addr2) + /// %l = load %ptr + /// %addr1 = gep, %alloca2, 0, %l + /// %addr2 = gep %alloca2, 0, (%l + 1) + /// alias(%p, %addr1) -> MayAlias ! + /// store %l, ... + SmallPtrSet<const BasicBlock *, 8> VisitedPhiBBs; + + /// Tracks instructions visited by pointsToConstantMemory. + SmallPtrSet<const Value *, 16> Visited; + + static const Value * + GetLinearExpression(const Value *V, APInt &Scale, APInt &Offset, + unsigned &ZExtBits, unsigned &SExtBits, + const DataLayout &DL, unsigned Depth, AssumptionCache *AC, + DominatorTree *DT, bool &NSW, bool &NUW); + + 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, + LocationSize ObjectAccessSize); + + /// A Heuristic for aliasGEP that searches for a constant offset + /// between the variables. + /// + /// GetLinearExpression has some limitations, as generally zext(%x + 1) + /// != zext(%x) + zext(1) if the arithmetic overflows. GetLinearExpression + /// will therefore conservatively refuse to decompose these expressions. + /// However, we know that, for all %x, zext(%x) != zext(%x + 1), even if + /// the addition overflows. + bool + constantOffsetHeuristic(const SmallVectorImpl<VariableGEPIndex> &VarIndices, + LocationSize V1Size, LocationSize V2Size, + APInt BaseOffset, AssumptionCache *AC, + DominatorTree *DT); + + bool isValueEqualInPotentialCycles(const Value *V1, const Value *V2); + + void GetIndexDifference(SmallVectorImpl<VariableGEPIndex> &Dest, + const SmallVectorImpl<VariableGEPIndex> &Src); + + AliasResult aliasGEP(const GEPOperator *V1, LocationSize V1Size, + const AAMDNodes &V1AAInfo, const Value *V2, + LocationSize V2Size, const AAMDNodes &V2AAInfo, + const Value *UnderlyingV1, const Value *UnderlyingV2, + AAQueryInfo &AAQI); + + AliasResult aliasPHI(const PHINode *PN, LocationSize PNSize, + const AAMDNodes &PNAAInfo, const Value *V2, + LocationSize V2Size, const AAMDNodes &V2AAInfo, + const Value *UnderV2, AAQueryInfo &AAQI); + + AliasResult aliasSelect(const SelectInst *SI, LocationSize SISize, + const AAMDNodes &SIAAInfo, const Value *V2, + LocationSize V2Size, const AAMDNodes &V2AAInfo, + const Value *UnderV2, AAQueryInfo &AAQI); + + AliasResult aliasCheck(const Value *V1, LocationSize V1Size, + AAMDNodes V1AATag, const Value *V2, + LocationSize V2Size, AAMDNodes V2AATag, + AAQueryInfo &AAQI, const Value *O1 = nullptr, + const Value *O2 = nullptr); +}; + +/// Analysis pass providing a never-invalidated alias analysis result. +class BasicAA : public AnalysisInfoMixin<BasicAA> { + friend AnalysisInfoMixin<BasicAA>; + + static AnalysisKey Key; + +public: + using Result = BasicAAResult; + + BasicAAResult run(Function &F, FunctionAnalysisManager &AM); +}; + +/// Legacy wrapper pass to provide the BasicAAResult object. +class BasicAAWrapperPass : public FunctionPass { + std::unique_ptr<BasicAAResult> Result; + + virtual void anchor(); + +public: + static char ID; + + BasicAAWrapperPass(); + + BasicAAResult &getResult() { return *Result; } + const BasicAAResult &getResult() const { return *Result; } + + bool runOnFunction(Function &F) override; + void getAnalysisUsage(AnalysisUsage &AU) const override; +}; + +FunctionPass *createBasicAAWrapperPass(); + +/// A helper for the legacy pass manager to create a \c BasicAAResult object +/// populated to the best of our ability for a particular function when inside +/// of a \c ModulePass or a \c CallGraphSCCPass. +BasicAAResult createLegacyPMBasicAAResult(Pass &P, Function &F); + +/// This class is a functor to be used in legacy module or SCC passes for +/// computing AA results for a function. We store the results in fields so that +/// they live long enough to be queried, but we re-use them each time. +class LegacyAARGetter { + Pass &P; + Optional<BasicAAResult> BAR; + Optional<AAResults> AAR; + +public: + LegacyAARGetter(Pass &P) : P(P) {} + AAResults &operator()(Function &F) { + BAR.emplace(createLegacyPMBasicAAResult(P, F)); + AAR.emplace(createLegacyPMAAResults(P, F, *BAR)); + return *AAR; + } +}; + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_BASICALIASANALYSIS_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/BlockFrequencyInfo.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/BlockFrequencyInfo.h new file mode 100644 index 0000000..8bcfd7f --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/BlockFrequencyInfo.h
@@ -0,0 +1,156 @@ +//===- BlockFrequencyInfo.h - Block Frequency Analysis ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Loops should be simplified before this analysis. +// +//===----------------------------------------------------------------------===// + +#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 <cstdint> +#include <memory> + +namespace llvm { + +class BasicBlock; +class BranchProbabilityInfo; +class Function; +class LoopInfo; +class Module; +class raw_ostream; +template <class BlockT> class BlockFrequencyInfoImpl; + +enum PGOViewCountsType { PGOVCT_None, PGOVCT_Graph, PGOVCT_Text }; + +/// BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to +/// estimate IR basic block frequencies. +class BlockFrequencyInfo { + using ImplType = BlockFrequencyInfoImpl<BasicBlock>; + + std::unique_ptr<ImplType> BFI; + +public: + BlockFrequencyInfo(); + BlockFrequencyInfo(const Function &F, const BranchProbabilityInfo &BPI, + const LoopInfo &LI); + BlockFrequencyInfo(const BlockFrequencyInfo &) = delete; + BlockFrequencyInfo &operator=(const BlockFrequencyInfo &) = delete; + BlockFrequencyInfo(BlockFrequencyInfo &&Arg); + BlockFrequencyInfo &operator=(BlockFrequencyInfo &&RHS); + ~BlockFrequencyInfo(); + + /// Handle invalidation explicitly. + bool invalidate(Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &); + + const Function *getFunction() const; + const BranchProbabilityInfo *getBPI() const; + void view(StringRef = "BlockFrequencyDAGs") const; + + /// getblockFreq - Return block frequency. Return 0 if we don't have the + /// information. Please note that initial frequency is equal to ENTRY_FREQ. It + /// means that we should not rely on the value itself, but only on the + /// comparison to the other block frequencies. We do this to avoid using of + /// floating points. + BlockFrequency getBlockFreq(const BasicBlock *BB) const; + + /// 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, + bool AllowSynthetic = false) const; + + /// Returns the estimated profile count of \p Freq. + /// This uses the frequency \p Freq and multiplies it by + /// the enclosing function's count (if available) and returns the value. + Optional<uint64_t> getProfileCountFromFreq(uint64_t Freq) const; + + /// Returns true if \p BB is an irreducible loop header + /// block. Otherwise false. + bool isIrrLoopHeader(const BasicBlock *BB); + + // Set the frequency of the given basic block. + void setBlockFreq(const BasicBlock *BB, uint64_t Freq); + + /// Set the frequency of \p ReferenceBB to \p Freq and scale the frequencies + /// of the blocks in \p BlocksToScale such that their frequencies relative + /// to \p ReferenceBB remain unchanged. + void setBlockFreqAndScale(const BasicBlock *ReferenceBB, uint64_t Freq, + SmallPtrSetImpl<BasicBlock *> &BlocksToScale); + + /// calculate - compute block frequency info for the given function. + void calculate(const Function &F, const BranchProbabilityInfo &BPI, + const LoopInfo &LI); + + // Print the block frequency Freq to OS using the current functions entry + // frequency to convert freq into a relative decimal form. + raw_ostream &printBlockFreq(raw_ostream &OS, const BlockFrequency Freq) const; + + // Convenience method that attempts to look up the frequency associated with + // BB and print it to OS. + raw_ostream &printBlockFreq(raw_ostream &OS, const BasicBlock *BB) const; + + uint64_t getEntryFreq() const; + void releaseMemory(); + void print(raw_ostream &OS) const; +}; + +/// Analysis pass which computes \c BlockFrequencyInfo. +class BlockFrequencyAnalysis + : public AnalysisInfoMixin<BlockFrequencyAnalysis> { + friend AnalysisInfoMixin<BlockFrequencyAnalysis>; + + static AnalysisKey Key; + +public: + /// Provide the result type for this analysis pass. + using Result = BlockFrequencyInfo; + + /// Run the analysis pass over a function and produce BFI. + Result run(Function &F, FunctionAnalysisManager &AM); +}; + +/// 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, FunctionAnalysisManager &AM); +}; + +/// Legacy analysis pass which computes \c BlockFrequencyInfo. +class BlockFrequencyInfoWrapperPass : public FunctionPass { + BlockFrequencyInfo BFI; + +public: + static char ID; + + BlockFrequencyInfoWrapperPass(); + ~BlockFrequencyInfoWrapperPass() override; + + BlockFrequencyInfo &getBFI() { return BFI; } + const BlockFrequencyInfo &getBFI() const { return BFI; } + + void getAnalysisUsage(AnalysisUsage &AU) const override; + + bool runOnFunction(Function &F) override; + void releaseMemory() override; + void print(raw_ostream &OS, const Module *M) const override; +}; + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_BLOCKFREQUENCYINFO_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h new file mode 100644 index 0000000..bfe4fb1 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h
@@ -0,0 +1,1477 @@ +//==- BlockFrequencyInfoImpl.h - Block Frequency Implementation --*- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Shared implementation of BlockFrequency for IR and Machine Instructions. +// See the documentation below for BlockFrequencyInfoImpl for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_BLOCKFREQUENCYINFOIMPL_H +#define LLVM_ANALYSIS_BLOCKFREQUENCYINFOIMPL_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SparseBitVector.h" +#include "llvm/ADT/Twine.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/ErrorHandling.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/ScaledNumber.h" +#include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <deque> +#include <iterator> +#include <limits> +#include <list> +#include <string> +#include <utility> +#include <vector> + +#define DEBUG_TYPE "block-freq" + +namespace llvm { + +class BranchProbabilityInfo; +class Function; +class Loop; +class LoopInfo; +class MachineBasicBlock; +class MachineBranchProbabilityInfo; +class MachineFunction; +class MachineLoop; +class MachineLoopInfo; + +namespace bfi_detail { + +struct IrreducibleGraph; + +// This is part of a workaround for a GCC 4.7 crash on lambdas. +template <class BT> struct BlockEdgesAdder; + +/// Mass of a block. +/// +/// This class implements a sort of fixed-point fraction always between 0.0 and +/// 1.0. getMass() == std::numeric_limits<uint64_t>::max() indicates a value of +/// 1.0. +/// +/// Masses can be added and subtracted. Simple saturation arithmetic is used, +/// so arithmetic operations never overflow or underflow. +/// +/// Masses can be multiplied. Multiplication treats full mass as 1.0 and uses +/// an inexpensive floating-point algorithm that's off-by-one (almost, but not +/// quite, maximum precision). +/// +/// Masses can be scaled by \a BranchProbability at maximum precision. +class BlockMass { + uint64_t Mass = 0; + +public: + BlockMass() = default; + explicit BlockMass(uint64_t Mass) : Mass(Mass) {} + + static BlockMass getEmpty() { return BlockMass(); } + + static BlockMass getFull() { + return BlockMass(std::numeric_limits<uint64_t>::max()); + } + + uint64_t getMass() const { return Mass; } + + bool isFull() const { return Mass == std::numeric_limits<uint64_t>::max(); } + bool isEmpty() const { return !Mass; } + + bool operator!() const { return isEmpty(); } + + /// Add another mass. + /// + /// Adds another mass, saturating at \a isFull() rather than overflowing. + BlockMass &operator+=(BlockMass X) { + uint64_t Sum = Mass + X.Mass; + Mass = Sum < Mass ? std::numeric_limits<uint64_t>::max() : Sum; + return *this; + } + + /// Subtract another mass. + /// + /// Subtracts another mass, saturating at \a isEmpty() rather than + /// undeflowing. + BlockMass &operator-=(BlockMass X) { + uint64_t Diff = Mass - X.Mass; + Mass = Diff > Mass ? 0 : Diff; + return *this; + } + + BlockMass &operator*=(BranchProbability P) { + Mass = P.scale(Mass); + return *this; + } + + bool operator==(BlockMass X) const { return Mass == X.Mass; } + bool operator!=(BlockMass X) const { return Mass != X.Mass; } + bool operator<=(BlockMass X) const { return Mass <= X.Mass; } + bool operator>=(BlockMass X) const { return Mass >= X.Mass; } + bool operator<(BlockMass X) const { return Mass < X.Mass; } + bool operator>(BlockMass X) const { return Mass > X.Mass; } + + /// Convert to scaled number. + /// + /// Convert to \a ScaledNumber. \a isFull() gives 1.0, while \a isEmpty() + /// gives slightly above 0.0. + ScaledNumber<uint64_t> toScaled() const; + + void dump() const; + raw_ostream &print(raw_ostream &OS) const; +}; + +inline BlockMass operator+(BlockMass L, BlockMass R) { + return BlockMass(L) += R; +} +inline BlockMass operator-(BlockMass L, BlockMass R) { + return BlockMass(L) -= R; +} +inline BlockMass operator*(BlockMass L, BranchProbability R) { + return BlockMass(L) *= R; +} +inline BlockMass operator*(BranchProbability L, BlockMass R) { + return BlockMass(R) *= L; +} + +inline raw_ostream &operator<<(raw_ostream &OS, BlockMass X) { + return X.print(OS); +} + +} // end namespace bfi_detail + +/// Base class for BlockFrequencyInfoImpl +/// +/// BlockFrequencyInfoImplBase has supporting data structures and some +/// algorithms for BlockFrequencyInfoImplBase. Only algorithms that depend on +/// the block type (or that call such algorithms) are skipped here. +/// +/// Nevertheless, the majority of the overall algorithm documention lives with +/// BlockFrequencyInfoImpl. See there for details. +class BlockFrequencyInfoImplBase { +public: + using Scaled64 = ScaledNumber<uint64_t>; + using BlockMass = bfi_detail::BlockMass; + + /// Representative of a block. + /// + /// This is a simple wrapper around an index into the reverse-post-order + /// traversal of the blocks. + /// + /// Unlike a block pointer, its order has meaning (location in the + /// topological sort) and it's class is the same regardless of block type. + struct BlockNode { + using IndexType = uint32_t; + + IndexType Index; + + BlockNode() : Index(std::numeric_limits<uint32_t>::max()) {} + BlockNode(IndexType Index) : Index(Index) {} + + bool operator==(const BlockNode &X) const { return Index == X.Index; } + bool operator!=(const BlockNode &X) const { return Index != X.Index; } + bool operator<=(const BlockNode &X) const { return Index <= X.Index; } + bool operator>=(const BlockNode &X) const { return Index >= X.Index; } + bool operator<(const BlockNode &X) const { return Index < X.Index; } + bool operator>(const BlockNode &X) const { return Index > X.Index; } + + bool isValid() const { return Index <= getMaxIndex(); } + + static size_t getMaxIndex() { + return std::numeric_limits<uint32_t>::max() - 1; + } + }; + + /// Stats about a block itself. + struct FrequencyData { + Scaled64 Scaled; + uint64_t Integer; + }; + + /// Data about a loop. + /// + /// Contains the data necessary to represent a loop as a pseudo-node once it's + /// packaged. + struct LoopData { + using ExitMap = SmallVector<std::pair<BlockNode, BlockMass>, 4>; + using NodeList = SmallVector<BlockNode, 4>; + using HeaderMassList = SmallVector<BlockMass, 1>; + + LoopData *Parent; ///< The parent loop. + bool IsPackaged = false; ///< Whether this has been packaged. + uint32_t NumHeaders = 1; ///< Number of headers. + ExitMap Exits; ///< Successor edges (and weights). + NodeList Nodes; ///< Header and the members of the loop. + HeaderMassList BackedgeMass; ///< Mass returned to each loop header. + BlockMass Mass; + Scaled64 Scale; + + LoopData(LoopData *Parent, const BlockNode &Header) + : Parent(Parent), Nodes(1, Header), BackedgeMass(1) {} + + template <class It1, class It2> + LoopData(LoopData *Parent, It1 FirstHeader, It1 LastHeader, It2 FirstOther, + It2 LastOther) + : Parent(Parent), Nodes(FirstHeader, LastHeader) { + NumHeaders = Nodes.size(); + Nodes.insert(Nodes.end(), FirstOther, LastOther); + BackedgeMass.resize(NumHeaders); + } + + bool isHeader(const BlockNode &Node) const { + if (isIrreducible()) + return std::binary_search(Nodes.begin(), Nodes.begin() + NumHeaders, + Node); + return Node == Nodes[0]; + } + + BlockNode getHeader() const { return Nodes[0]; } + bool isIrreducible() const { return NumHeaders > 1; } + + HeaderMassList::difference_type getHeaderIndex(const BlockNode &B) { + assert(isHeader(B) && "this is only valid on loop header blocks"); + if (isIrreducible()) + return std::lower_bound(Nodes.begin(), Nodes.begin() + NumHeaders, B) - + Nodes.begin(); + return 0; + } + + NodeList::const_iterator members_begin() const { + return Nodes.begin() + NumHeaders; + } + + NodeList::const_iterator members_end() const { return Nodes.end(); } + iterator_range<NodeList::const_iterator> members() const { + return make_range(members_begin(), members_end()); + } + }; + + /// Index of loop information. + struct WorkingData { + BlockNode Node; ///< This node. + LoopData *Loop = nullptr; ///< The loop this block is inside. + BlockMass Mass; ///< Mass distribution from the entry block. + + WorkingData(const BlockNode &Node) : Node(Node) {} + + bool isLoopHeader() const { return Loop && Loop->isHeader(Node); } + + bool isDoubleLoopHeader() const { + return isLoopHeader() && Loop->Parent && Loop->Parent->isIrreducible() && + Loop->Parent->isHeader(Node); + } + + LoopData *getContainingLoop() const { + if (!isLoopHeader()) + return Loop; + if (!isDoubleLoopHeader()) + return Loop->Parent; + return Loop->Parent->Parent; + } + + /// Resolve a node to its representative. + /// + /// Get the node currently representing Node, which could be a containing + /// loop. + /// + /// This function should only be called when distributing mass. As long as + /// there are no irreducible edges to Node, then it will have complexity + /// O(1) in this context. + /// + /// In general, the complexity is O(L), where L is the number of loop + /// headers Node has been packaged into. Since this method is called in + /// the context of distributing mass, L will be the number of loop headers + /// an early exit edge jumps out of. + BlockNode getResolvedNode() const { + auto L = getPackagedLoop(); + return L ? L->getHeader() : Node; + } + + LoopData *getPackagedLoop() const { + if (!Loop || !Loop->IsPackaged) + return nullptr; + auto L = Loop; + while (L->Parent && L->Parent->IsPackaged) + L = L->Parent; + return L; + } + + /// Get the appropriate mass for a node. + /// + /// Get appropriate mass for Node. If Node is a loop-header (whose loop + /// has been packaged), returns the mass of its pseudo-node. If it's a + /// node inside a packaged loop, it returns the loop's mass. + BlockMass &getMass() { + if (!isAPackage()) + return Mass; + if (!isADoublePackage()) + return Loop->Mass; + return Loop->Parent->Mass; + } + + /// Has ContainingLoop been packaged up? + bool isPackaged() const { return getResolvedNode() != Node; } + + /// Has Loop been packaged up? + bool isAPackage() const { return isLoopHeader() && Loop->IsPackaged; } + + /// Has Loop been packaged up twice? + bool isADoublePackage() const { + return isDoubleLoopHeader() && Loop->Parent->IsPackaged; + } + }; + + /// Unscaled probability weight. + /// + /// Probability weight for an edge in the graph (including the + /// successor/target node). + /// + /// All edges in the original function are 32-bit. However, exit edges from + /// loop packages are taken from 64-bit exit masses, so we need 64-bits of + /// space in general. + /// + /// In addition to the raw weight amount, Weight stores the type of the edge + /// in the current context (i.e., the context of the loop being processed). + /// Is this a local edge within the loop, an exit from the loop, or a + /// backedge to the loop header? + struct Weight { + enum DistType { Local, Exit, Backedge }; + DistType Type = Local; + BlockNode TargetNode; + uint64_t Amount = 0; + + Weight() = default; + Weight(DistType Type, BlockNode TargetNode, uint64_t Amount) + : Type(Type), TargetNode(TargetNode), Amount(Amount) {} + }; + + /// Distribution of unscaled probability weight. + /// + /// Distribution of unscaled probability weight to a set of successors. + /// + /// This class collates the successor edge weights for later processing. + /// + /// \a DidOverflow indicates whether \a Total did overflow while adding to + /// the distribution. It should never overflow twice. + struct Distribution { + using WeightList = SmallVector<Weight, 4>; + + WeightList Weights; ///< Individual successor weights. + uint64_t Total = 0; ///< Sum of all weights. + bool DidOverflow = false; ///< Whether \a Total did overflow. + + Distribution() = default; + + void addLocal(const BlockNode &Node, uint64_t Amount) { + add(Node, Amount, Weight::Local); + } + + void addExit(const BlockNode &Node, uint64_t Amount) { + add(Node, Amount, Weight::Exit); + } + + void addBackedge(const BlockNode &Node, uint64_t Amount) { + add(Node, Amount, Weight::Backedge); + } + + /// Normalize the distribution. + /// + /// Combines multiple edges to the same \a Weight::TargetNode and scales + /// down so that \a Total fits into 32-bits. + /// + /// This is linear in the size of \a Weights. For the vast majority of + /// cases, adjacent edge weights are combined by sorting WeightList and + /// combining adjacent weights. However, for very large edge lists an + /// auxiliary hash table is used. + void normalize(); + + private: + void add(const BlockNode &Node, uint64_t Amount, Weight::DistType Type); + }; + + /// Data about each block. This is used downstream. + std::vector<FrequencyData> Freqs; + + /// Whether each block is an irreducible loop header. + /// This is used downstream. + SparseBitVector<> IsIrrLoopHeader; + + /// Loop data: see initializeLoops(). + std::vector<WorkingData> Working; + + /// Indexed information about loops. + std::list<LoopData> Loops; + + /// Virtual destructor. + /// + /// Need a virtual destructor to mask the compiler warning about + /// getBlockName(). + virtual ~BlockFrequencyInfoImplBase() = default; + + /// Add all edges out of a packaged loop to the distribution. + /// + /// Adds all edges from LocalLoopHead to Dist. Calls addToDist() to add each + /// successor edge. + /// + /// \return \c true unless there's an irreducible backedge. + bool addLoopSuccessorsToDist(const LoopData *OuterLoop, LoopData &Loop, + Distribution &Dist); + + /// Add an edge to the distribution. + /// + /// Adds an edge to Succ to Dist. If \c LoopHead.isValid(), then whether the + /// edge is local/exit/backedge is in the context of LoopHead. Otherwise, + /// every edge should be a local edge (since all the loops are packaged up). + /// + /// \return \c true unless aborted due to an irreducible backedge. + bool addToDist(Distribution &Dist, const LoopData *OuterLoop, + const BlockNode &Pred, const BlockNode &Succ, uint64_t Weight); + + LoopData &getLoopPackage(const BlockNode &Head) { + assert(Head.Index < Working.size()); + assert(Working[Head.Index].isLoopHeader()); + return *Working[Head.Index].Loop; + } + + /// Analyze irreducible SCCs. + /// + /// Separate irreducible SCCs from \c G, which is an explict graph of \c + /// OuterLoop (or the top-level function, if \c OuterLoop is \c nullptr). + /// Insert them into \a Loops before \c Insert. + /// + /// \return the \c LoopData nodes representing the irreducible SCCs. + iterator_range<std::list<LoopData>::iterator> + analyzeIrreducible(const bfi_detail::IrreducibleGraph &G, LoopData *OuterLoop, + std::list<LoopData>::iterator Insert); + + /// Update a loop after packaging irreducible SCCs inside of it. + /// + /// Update \c OuterLoop. Before finding irreducible control flow, it was + /// partway through \a computeMassInLoop(), so \a LoopData::Exits and \a + /// LoopData::BackedgeMass need to be reset. Also, nodes that were packaged + /// up need to be removed from \a OuterLoop::Nodes. + void updateLoopWithIrreducible(LoopData &OuterLoop); + + /// Distribute mass according to a distribution. + /// + /// Distributes the mass in Source according to Dist. If LoopHead.isValid(), + /// backedges and exits are stored in its entry in Loops. + /// + /// Mass is distributed in parallel from two copies of the source mass. + void distributeMass(const BlockNode &Source, LoopData *OuterLoop, + Distribution &Dist); + + /// Compute the loop scale for a loop. + void computeLoopScale(LoopData &Loop); + + /// Adjust the mass of all headers in an irreducible loop. + /// + /// Initially, irreducible loops are assumed to distribute their mass + /// equally among its headers. This can lead to wrong frequency estimates + /// since some headers may be executed more frequently than others. + /// + /// This adjusts header mass distribution so it matches the weights of + /// the backedges going into each of the loop headers. + void adjustLoopHeaderMass(LoopData &Loop); + + void distributeIrrLoopHeaderMass(Distribution &Dist); + + /// Package up a loop. + void packageLoop(LoopData &Loop); + + /// Unwrap loops. + void unwrapLoops(); + + /// Finalize frequency metrics. + /// + /// Calculates final frequencies and cleans up no-longer-needed data + /// structures. + void finalizeMetrics(); + + /// Clear all memory. + void clear(); + + virtual std::string getBlockName(const BlockNode &Node) const; + std::string getLoopName(const LoopData &Loop) const; + + virtual raw_ostream &print(raw_ostream &OS) const { return OS; } + void dump() const { print(dbgs()); } + + Scaled64 getFloatingBlockFreq(const BlockNode &Node) const; + + BlockFrequency getBlockFreq(const BlockNode &Node) const; + Optional<uint64_t> getBlockProfileCount(const Function &F, + const BlockNode &Node, + bool AllowSynthetic = false) const; + Optional<uint64_t> getProfileCountFromFreq(const Function &F, + uint64_t Freq, + bool AllowSynthetic = false) const; + bool isIrrLoopHeader(const BlockNode &Node); + + void setBlockFreq(const BlockNode &Node, uint64_t Freq); + + raw_ostream &printBlockFreq(raw_ostream &OS, const BlockNode &Node) const; + raw_ostream &printBlockFreq(raw_ostream &OS, + const BlockFrequency &Freq) const; + + uint64_t getEntryFreq() const { + assert(!Freqs.empty()); + return Freqs[0].Integer; + } +}; + +namespace bfi_detail { + +template <class BlockT> struct TypeMap {}; +template <> struct TypeMap<BasicBlock> { + using BlockT = BasicBlock; + using FunctionT = Function; + using BranchProbabilityInfoT = BranchProbabilityInfo; + using LoopT = Loop; + using LoopInfoT = LoopInfo; +}; +template <> struct TypeMap<MachineBasicBlock> { + using BlockT = MachineBasicBlock; + using FunctionT = MachineFunction; + using BranchProbabilityInfoT = MachineBranchProbabilityInfo; + using LoopT = MachineLoop; + using LoopInfoT = MachineLoopInfo; +}; + +/// Get the name of a MachineBasicBlock. +/// +/// Get the name of a MachineBasicBlock. It's templated so that including from +/// CodeGen is unnecessary (that would be a layering issue). +/// +/// This is used mainly for debug output. The name is similar to +/// MachineBasicBlock::getFullName(), but skips the name of the function. +template <class BlockT> std::string getBlockName(const BlockT *BB) { + assert(BB && "Unexpected nullptr"); + auto MachineName = "BB" + Twine(BB->getNumber()); + if (BB->getBasicBlock()) + return (MachineName + "[" + BB->getName() + "]").str(); + return MachineName.str(); +} +/// Get the name of a BasicBlock. +template <> inline std::string getBlockName(const BasicBlock *BB) { + assert(BB && "Unexpected nullptr"); + return BB->getName().str(); +} + +/// Graph of irreducible control flow. +/// +/// This graph is used for determining the SCCs in a loop (or top-level +/// function) that has irreducible control flow. +/// +/// During the block frequency algorithm, the local graphs are defined in a +/// light-weight way, deferring to the \a BasicBlock or \a MachineBasicBlock +/// graphs for most edges, but getting others from \a LoopData::ExitMap. The +/// latter only has successor information. +/// +/// \a IrreducibleGraph makes this graph explicit. It's in a form that can use +/// \a GraphTraits (so that \a analyzeIrreducible() can use \a scc_iterator), +/// and it explicitly lists predecessors and successors. The initialization +/// that relies on \c MachineBasicBlock is defined in the header. +struct IrreducibleGraph { + using BFIBase = BlockFrequencyInfoImplBase; + + BFIBase &BFI; + + using BlockNode = BFIBase::BlockNode; + struct IrrNode { + BlockNode Node; + unsigned NumIn = 0; + std::deque<const IrrNode *> Edges; + + IrrNode(const BlockNode &Node) : Node(Node) {} + + using iterator = std::deque<const IrrNode *>::const_iterator; + + iterator pred_begin() const { return Edges.begin(); } + iterator succ_begin() const { return Edges.begin() + NumIn; } + iterator pred_end() const { return succ_begin(); } + iterator succ_end() const { return Edges.end(); } + }; + BlockNode Start; + const IrrNode *StartIrr = nullptr; + std::vector<IrrNode> Nodes; + SmallDenseMap<uint32_t, IrrNode *, 4> Lookup; + + /// Construct an explicit graph containing irreducible control flow. + /// + /// Construct an explicit graph of the control flow in \c OuterLoop (or the + /// top-level function, if \c OuterLoop is \c nullptr). Uses \c + /// addBlockEdges to add block successors that have not been packaged into + /// loops. + /// + /// \a BlockFrequencyInfoImpl::computeIrreducibleMass() is the only expected + /// user of this. + template <class BlockEdgesAdder> + IrreducibleGraph(BFIBase &BFI, const BFIBase::LoopData *OuterLoop, + BlockEdgesAdder addBlockEdges) : BFI(BFI) { + initialize(OuterLoop, addBlockEdges); + } + + template <class BlockEdgesAdder> + void initialize(const BFIBase::LoopData *OuterLoop, + BlockEdgesAdder addBlockEdges); + void addNodesInLoop(const BFIBase::LoopData &OuterLoop); + void addNodesInFunction(); + + void addNode(const BlockNode &Node) { + Nodes.emplace_back(Node); + BFI.Working[Node.Index].getMass() = BlockMass::getEmpty(); + } + + void indexNodes(); + template <class BlockEdgesAdder> + void addEdges(const BlockNode &Node, const BFIBase::LoopData *OuterLoop, + BlockEdgesAdder addBlockEdges); + void addEdge(IrrNode &Irr, const BlockNode &Succ, + const BFIBase::LoopData *OuterLoop); +}; + +template <class BlockEdgesAdder> +void IrreducibleGraph::initialize(const BFIBase::LoopData *OuterLoop, + BlockEdgesAdder addBlockEdges) { + if (OuterLoop) { + addNodesInLoop(*OuterLoop); + for (auto N : OuterLoop->Nodes) + addEdges(N, OuterLoop, addBlockEdges); + } else { + addNodesInFunction(); + for (uint32_t Index = 0; Index < BFI.Working.size(); ++Index) + addEdges(Index, OuterLoop, addBlockEdges); + } + StartIrr = Lookup[Start.Index]; +} + +template <class BlockEdgesAdder> +void IrreducibleGraph::addEdges(const BlockNode &Node, + const BFIBase::LoopData *OuterLoop, + BlockEdgesAdder addBlockEdges) { + auto L = Lookup.find(Node.Index); + if (L == Lookup.end()) + return; + IrrNode &Irr = *L->second; + const auto &Working = BFI.Working[Node.Index]; + + if (Working.isAPackage()) + for (const auto &I : Working.Loop->Exits) + addEdge(Irr, I.first, OuterLoop); + else + addBlockEdges(*this, Irr, OuterLoop); +} + +} // end namespace bfi_detail + +/// Shared implementation for block frequency analysis. +/// +/// This is a shared implementation of BlockFrequencyInfo and +/// MachineBlockFrequencyInfo, and calculates the relative frequencies of +/// blocks. +/// +/// LoopInfo defines a loop as a "non-trivial" SCC dominated by a single block, +/// which is called the header. A given loop, L, can have sub-loops, which are +/// loops within the subgraph of L that exclude its header. (A "trivial" SCC +/// consists of a single block that does not have a self-edge.) +/// +/// In addition to loops, this algorithm has limited support for irreducible +/// SCCs, which are SCCs with multiple entry blocks. Irreducible SCCs are +/// discovered on they fly, and modelled as loops with multiple headers. +/// +/// The headers of irreducible sub-SCCs consist of its entry blocks and all +/// nodes that are targets of a backedge within it (excluding backedges within +/// true sub-loops). Block frequency calculations act as if a block is +/// inserted that intercepts all the edges to the headers. All backedges and +/// entries point to this block. Its successors are the headers, which split +/// the frequency evenly. +/// +/// This algorithm leverages BlockMass and ScaledNumber to maintain precision, +/// separates mass distribution from loop scaling, and dithers to eliminate +/// probability mass loss. +/// +/// The implementation is split between BlockFrequencyInfoImpl, which knows the +/// type of graph being modelled (BasicBlock vs. MachineBasicBlock), and +/// BlockFrequencyInfoImplBase, which doesn't. The base class uses \a +/// BlockNode, a wrapper around a uint32_t. BlockNode is numbered from 0 in +/// reverse-post order. This gives two advantages: it's easy to compare the +/// relative ordering of two nodes, and maps keyed on BlockT can be represented +/// by vectors. +/// +/// This algorithm is O(V+E), unless there is irreducible control flow, in +/// which case it's O(V*E) in the worst case. +/// +/// These are the main stages: +/// +/// 0. Reverse post-order traversal (\a initializeRPOT()). +/// +/// Run a single post-order traversal and save it (in reverse) in RPOT. +/// All other stages make use of this ordering. Save a lookup from BlockT +/// to BlockNode (the index into RPOT) in Nodes. +/// +/// 1. Loop initialization (\a initializeLoops()). +/// +/// Translate LoopInfo/MachineLoopInfo into a form suitable for the rest of +/// the algorithm. In particular, store the immediate members of each loop +/// in reverse post-order. +/// +/// 2. Calculate mass and scale in loops (\a computeMassInLoops()). +/// +/// For each loop (bottom-up), distribute mass through the DAG resulting +/// from ignoring backedges and treating sub-loops as a single pseudo-node. +/// Track the backedge mass distributed to the loop header, and use it to +/// calculate the loop scale (number of loop iterations). Immediate +/// members that represent sub-loops will already have been visited and +/// packaged into a pseudo-node. +/// +/// Distributing mass in a loop is a reverse-post-order traversal through +/// the loop. Start by assigning full mass to the Loop header. For each +/// node in the loop: +/// +/// - Fetch and categorize the weight distribution for its successors. +/// If this is a packaged-subloop, the weight distribution is stored +/// in \a LoopData::Exits. Otherwise, fetch it from +/// BranchProbabilityInfo. +/// +/// - Each successor is categorized as \a Weight::Local, a local edge +/// within the current loop, \a Weight::Backedge, a backedge to the +/// loop header, or \a Weight::Exit, any successor outside the loop. +/// The weight, the successor, and its category are stored in \a +/// Distribution. There can be multiple edges to each successor. +/// +/// - If there's a backedge to a non-header, there's an irreducible SCC. +/// The usual flow is temporarily aborted. \a +/// computeIrreducibleMass() finds the irreducible SCCs within the +/// loop, packages them up, and restarts the flow. +/// +/// - Normalize the distribution: scale weights down so that their sum +/// is 32-bits, and coalesce multiple edges to the same node. +/// +/// - Distribute the mass accordingly, dithering to minimize mass loss, +/// as described in \a distributeMass(). +/// +/// In the case of irreducible loops, instead of a single loop header, +/// there will be several. The computation of backedge masses is similar +/// but instead of having a single backedge mass, there will be one +/// backedge per loop header. In these cases, each backedge will carry +/// a mass proportional to the edge weights along the corresponding +/// path. +/// +/// At the end of propagation, the full mass assigned to the loop will be +/// distributed among the loop headers proportionally according to the +/// mass flowing through their backedges. +/// +/// Finally, calculate the loop scale from the accumulated backedge mass. +/// +/// 3. Distribute mass in the function (\a computeMassInFunction()). +/// +/// Finally, distribute mass through the DAG resulting from packaging all +/// loops in the function. This uses the same algorithm as distributing +/// mass in a loop, except that there are no exit or backedge edges. +/// +/// 4. Unpackage loops (\a unwrapLoops()). +/// +/// Initialize each block's frequency to a floating point representation of +/// its mass. +/// +/// Visit loops top-down, scaling the frequencies of its immediate members +/// by the loop's pseudo-node's frequency. +/// +/// 5. Convert frequencies to a 64-bit range (\a finalizeMetrics()). +/// +/// Using the min and max frequencies as a guide, translate floating point +/// frequencies to an appropriate range in uint64_t. +/// +/// It has some known flaws. +/// +/// - The model of irreducible control flow is a rough approximation. +/// +/// Modelling irreducible control flow exactly involves setting up and +/// solving a group of infinite geometric series. Such precision is +/// unlikely to be worthwhile, since most of our algorithms give up on +/// irreducible control flow anyway. +/// +/// Nevertheless, we might find that we need to get closer. Here's a sort +/// of TODO list for the model with diminishing returns, to be completed as +/// necessary. +/// +/// - The headers for the \a LoopData representing an irreducible SCC +/// include non-entry blocks. When these extra blocks exist, they +/// indicate a self-contained irreducible sub-SCC. We could treat them +/// as sub-loops, rather than arbitrarily shoving the problematic +/// blocks into the headers of the main irreducible SCC. +/// +/// - Entry frequencies are assumed to be evenly split between the +/// headers of a given irreducible SCC, which is the only option if we +/// need to compute mass in the SCC before its parent loop. Instead, +/// we could partially compute mass in the parent loop, and stop when +/// we get to the SCC. Here, we have the correct ratio of entry +/// masses, which we can use to adjust their relative frequencies. +/// Compute mass in the SCC, and then continue propagation in the +/// parent. +/// +/// - We can propagate mass iteratively through the SCC, for some fixed +/// number of iterations. Each iteration starts by assigning the entry +/// blocks their backedge mass from the prior iteration. The final +/// mass for each block (and each exit, and the total backedge mass +/// used for computing loop scale) is the sum of all iterations. +/// (Running this until fixed point would "solve" the geometric +/// series by simulation.) +template <class BT> class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase { + // This is part of a workaround for a GCC 4.7 crash on lambdas. + friend struct bfi_detail::BlockEdgesAdder<BT>; + + using BlockT = typename bfi_detail::TypeMap<BT>::BlockT; + using FunctionT = typename bfi_detail::TypeMap<BT>::FunctionT; + using BranchProbabilityInfoT = + typename bfi_detail::TypeMap<BT>::BranchProbabilityInfoT; + using LoopT = typename bfi_detail::TypeMap<BT>::LoopT; + using LoopInfoT = typename bfi_detail::TypeMap<BT>::LoopInfoT; + using Successor = GraphTraits<const BlockT *>; + using Predecessor = GraphTraits<Inverse<const BlockT *>>; + + const BranchProbabilityInfoT *BPI = nullptr; + const LoopInfoT *LI = nullptr; + const FunctionT *F = nullptr; + + // All blocks in reverse postorder. + std::vector<const BlockT *> RPOT; + DenseMap<const BlockT *, BlockNode> Nodes; + + using rpot_iterator = typename std::vector<const BlockT *>::const_iterator; + + rpot_iterator rpot_begin() const { return RPOT.begin(); } + rpot_iterator rpot_end() const { return RPOT.end(); } + + size_t getIndex(const rpot_iterator &I) const { return I - rpot_begin(); } + + BlockNode getNode(const rpot_iterator &I) const { + return BlockNode(getIndex(I)); + } + BlockNode getNode(const BlockT *BB) const { return Nodes.lookup(BB); } + + const BlockT *getBlock(const BlockNode &Node) const { + assert(Node.Index < RPOT.size()); + return RPOT[Node.Index]; + } + + /// Run (and save) a post-order traversal. + /// + /// Saves a reverse post-order traversal of all the nodes in \a F. + void initializeRPOT(); + + /// Initialize loop data. + /// + /// Build up \a Loops using \a LoopInfo. \a LoopInfo gives us a mapping from + /// each block to the deepest loop it's in, but we need the inverse. For each + /// loop, we store in reverse post-order its "immediate" members, defined as + /// the header, the headers of immediate sub-loops, and all other blocks in + /// the loop that are not in sub-loops. + void initializeLoops(); + + /// Propagate to a block's successors. + /// + /// In the context of distributing mass through \c OuterLoop, divide the mass + /// currently assigned to \c Node between its successors. + /// + /// \return \c true unless there's an irreducible backedge. + bool propagateMassToSuccessors(LoopData *OuterLoop, const BlockNode &Node); + + /// Compute mass in a particular loop. + /// + /// Assign mass to \c Loop's header, and then for each block in \c Loop in + /// reverse post-order, distribute mass to its successors. Only visits nodes + /// that have not been packaged into sub-loops. + /// + /// \pre \a computeMassInLoop() has been called for each subloop of \c Loop. + /// \return \c true unless there's an irreducible backedge. + bool computeMassInLoop(LoopData &Loop); + + /// Try to compute mass in the top-level function. + /// + /// Assign mass to the entry block, and then for each block in reverse + /// post-order, distribute mass to its successors. Skips nodes that have + /// been packaged into loops. + /// + /// \pre \a computeMassInLoops() has been called. + /// \return \c true unless there's an irreducible backedge. + bool tryToComputeMassInFunction(); + + /// Compute mass in (and package up) irreducible SCCs. + /// + /// Find the irreducible SCCs in \c OuterLoop, add them to \a Loops (in front + /// of \c Insert), and call \a computeMassInLoop() on each of them. + /// + /// If \c OuterLoop is \c nullptr, it refers to the top-level function. + /// + /// \pre \a computeMassInLoop() has been called for each subloop of \c + /// OuterLoop. + /// \pre \c Insert points at the last loop successfully processed by \a + /// computeMassInLoop(). + /// \pre \c OuterLoop has irreducible SCCs. + void computeIrreducibleMass(LoopData *OuterLoop, + std::list<LoopData>::iterator Insert); + + /// Compute mass in all loops. + /// + /// For each loop bottom-up, call \a computeMassInLoop(). + /// + /// \a computeMassInLoop() aborts (and returns \c false) on loops that + /// contain a irreducible sub-SCCs. Use \a computeIrreducibleMass() and then + /// re-enter \a computeMassInLoop(). + /// + /// \post \a computeMassInLoop() has returned \c true for every loop. + void computeMassInLoops(); + + /// Compute mass in the top-level function. + /// + /// Uses \a tryToComputeMassInFunction() and \a computeIrreducibleMass() to + /// compute mass in the top-level function. + /// + /// \post \a tryToComputeMassInFunction() has returned \c true. + void computeMassInFunction(); + + std::string getBlockName(const BlockNode &Node) const override { + return bfi_detail::getBlockName(getBlock(Node)); + } + +public: + BlockFrequencyInfoImpl() = default; + + const FunctionT *getFunction() const { return F; } + + void calculate(const FunctionT &F, const BranchProbabilityInfoT &BPI, + const LoopInfoT &LI); + + using BlockFrequencyInfoImplBase::getEntryFreq; + + BlockFrequency getBlockFreq(const BlockT *BB) const { + return BlockFrequencyInfoImplBase::getBlockFreq(getNode(BB)); + } + + Optional<uint64_t> getBlockProfileCount(const Function &F, + const BlockT *BB, + bool AllowSynthetic = false) const { + return BlockFrequencyInfoImplBase::getBlockProfileCount(F, getNode(BB), + AllowSynthetic); + } + + Optional<uint64_t> getProfileCountFromFreq(const Function &F, + uint64_t Freq, + bool AllowSynthetic = false) const { + return BlockFrequencyInfoImplBase::getProfileCountFromFreq(F, Freq, + AllowSynthetic); + } + + bool isIrrLoopHeader(const BlockT *BB) { + return BlockFrequencyInfoImplBase::isIrrLoopHeader(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; } + + /// Print the frequencies for the current function. + /// + /// Prints the frequencies for the blocks in the current function. + /// + /// Blocks are printed in the natural iteration order of the function, rather + /// than reverse post-order. This provides two advantages: writing -analyze + /// tests is easier (since blocks come out in source order), and even + /// unreachable blocks are printed. + /// + /// \a BlockFrequencyInfoImplBase::print() only knows reverse post-order, so + /// we need to override it here. + raw_ostream &print(raw_ostream &OS) const override; + + using BlockFrequencyInfoImplBase::dump; + using BlockFrequencyInfoImplBase::printBlockFreq; + + raw_ostream &printBlockFreq(raw_ostream &OS, const BlockT *BB) const { + return BlockFrequencyInfoImplBase::printBlockFreq(OS, getNode(BB)); + } +}; + +template <class BT> +void BlockFrequencyInfoImpl<BT>::calculate(const FunctionT &F, + const BranchProbabilityInfoT &BPI, + const LoopInfoT &LI) { + // Save the parameters. + this->BPI = &BPI; + this->LI = &LI; + this->F = &F; + + // Clean up left-over data structures. + BlockFrequencyInfoImplBase::clear(); + RPOT.clear(); + Nodes.clear(); + + // Initialize. + LLVM_DEBUG(dbgs() << "\nblock-frequency: " << F.getName() + << "\n=================" + << std::string(F.getName().size(), '=') << "\n"); + initializeRPOT(); + initializeLoops(); + + // Visit loops in post-order to find the local mass distribution, and then do + // the full function. + computeMassInLoops(); + computeMassInFunction(); + unwrapLoops(); + finalizeMetrics(); +} + +template <class BT> +void BlockFrequencyInfoImpl<BT>::setBlockFreq(const BlockT *BB, uint64_t Freq) { + if (Nodes.count(BB)) + BlockFrequencyInfoImplBase::setBlockFreq(getNode(BB), Freq); + else { + // If BB is a newly added block after BFI is done, we need to create a new + // BlockNode for it assigned with a new index. The index can be determined + // by the size of Freqs. + BlockNode NewNode(Freqs.size()); + Nodes[BB] = NewNode; + Freqs.emplace_back(); + BlockFrequencyInfoImplBase::setBlockFreq(NewNode, Freq); + } +} + +template <class BT> void BlockFrequencyInfoImpl<BT>::initializeRPOT() { + const BlockT *Entry = &F->front(); + RPOT.reserve(F->size()); + std::copy(po_begin(Entry), po_end(Entry), std::back_inserter(RPOT)); + std::reverse(RPOT.begin(), RPOT.end()); + + assert(RPOT.size() - 1 <= BlockNode::getMaxIndex() && + "More nodes in function than Block Frequency Info supports"); + + LLVM_DEBUG(dbgs() << "reverse-post-order-traversal\n"); + for (rpot_iterator I = rpot_begin(), E = rpot_end(); I != E; ++I) { + BlockNode Node = getNode(I); + LLVM_DEBUG(dbgs() << " - " << getIndex(I) << ": " << getBlockName(Node) + << "\n"); + Nodes[*I] = Node; + } + + Working.reserve(RPOT.size()); + for (size_t Index = 0; Index < RPOT.size(); ++Index) + Working.emplace_back(Index); + Freqs.resize(RPOT.size()); +} + +template <class BT> void BlockFrequencyInfoImpl<BT>::initializeLoops() { + LLVM_DEBUG(dbgs() << "loop-detection\n"); + if (LI->empty()) + return; + + // Visit loops top down and assign them an index. + std::deque<std::pair<const LoopT *, LoopData *>> Q; + for (const LoopT *L : *LI) + Q.emplace_back(L, nullptr); + while (!Q.empty()) { + const LoopT *Loop = Q.front().first; + LoopData *Parent = Q.front().second; + Q.pop_front(); + + BlockNode Header = getNode(Loop->getHeader()); + assert(Header.isValid()); + + Loops.emplace_back(Parent, Header); + Working[Header.Index].Loop = &Loops.back(); + LLVM_DEBUG(dbgs() << " - loop = " << getBlockName(Header) << "\n"); + + for (const LoopT *L : *Loop) + Q.emplace_back(L, &Loops.back()); + } + + // Visit nodes in reverse post-order and add them to their deepest containing + // loop. + for (size_t Index = 0; Index < RPOT.size(); ++Index) { + // Loop headers have already been mostly mapped. + if (Working[Index].isLoopHeader()) { + LoopData *ContainingLoop = Working[Index].getContainingLoop(); + if (ContainingLoop) + ContainingLoop->Nodes.push_back(Index); + continue; + } + + const LoopT *Loop = LI->getLoopFor(RPOT[Index]); + if (!Loop) + continue; + + // Add this node to its containing loop's member list. + BlockNode Header = getNode(Loop->getHeader()); + assert(Header.isValid()); + const auto &HeaderData = Working[Header.Index]; + assert(HeaderData.isLoopHeader()); + + Working[Index].Loop = HeaderData.Loop; + HeaderData.Loop->Nodes.push_back(Index); + LLVM_DEBUG(dbgs() << " - loop = " << getBlockName(Header) + << ": member = " << getBlockName(Index) << "\n"); + } +} + +template <class BT> void BlockFrequencyInfoImpl<BT>::computeMassInLoops() { + // Visit loops with the deepest first, and the top-level loops last. + for (auto L = Loops.rbegin(), E = Loops.rend(); L != E; ++L) { + if (computeMassInLoop(*L)) + continue; + auto Next = std::next(L); + computeIrreducibleMass(&*L, L.base()); + L = std::prev(Next); + if (computeMassInLoop(*L)) + continue; + llvm_unreachable("unhandled irreducible control flow"); + } +} + +template <class BT> +bool BlockFrequencyInfoImpl<BT>::computeMassInLoop(LoopData &Loop) { + // Compute mass in loop. + LLVM_DEBUG(dbgs() << "compute-mass-in-loop: " << getLoopName(Loop) << "\n"); + + if (Loop.isIrreducible()) { + LLVM_DEBUG(dbgs() << "isIrreducible = true\n"); + Distribution Dist; + unsigned NumHeadersWithWeight = 0; + Optional<uint64_t> MinHeaderWeight; + DenseSet<uint32_t> HeadersWithoutWeight; + HeadersWithoutWeight.reserve(Loop.NumHeaders); + for (uint32_t H = 0; H < Loop.NumHeaders; ++H) { + auto &HeaderNode = Loop.Nodes[H]; + const BlockT *Block = getBlock(HeaderNode); + IsIrrLoopHeader.set(Loop.Nodes[H].Index); + Optional<uint64_t> HeaderWeight = Block->getIrrLoopHeaderWeight(); + if (!HeaderWeight) { + LLVM_DEBUG(dbgs() << "Missing irr loop header metadata on " + << getBlockName(HeaderNode) << "\n"); + HeadersWithoutWeight.insert(H); + continue; + } + LLVM_DEBUG(dbgs() << getBlockName(HeaderNode) + << " has irr loop header weight " + << HeaderWeight.getValue() << "\n"); + NumHeadersWithWeight++; + uint64_t HeaderWeightValue = HeaderWeight.getValue(); + if (!MinHeaderWeight || HeaderWeightValue < MinHeaderWeight) + MinHeaderWeight = HeaderWeightValue; + if (HeaderWeightValue) { + Dist.addLocal(HeaderNode, HeaderWeightValue); + } + } + // As a heuristic, if some headers don't have a weight, give them the + // minimium weight seen (not to disrupt the existing trends too much by + // using a weight that's in the general range of the other headers' weights, + // and the minimum seems to perform better than the average.) + // FIXME: better update in the passes that drop the header weight. + // If no headers have a weight, give them even weight (use weight 1). + if (!MinHeaderWeight) + MinHeaderWeight = 1; + for (uint32_t H : HeadersWithoutWeight) { + auto &HeaderNode = Loop.Nodes[H]; + assert(!getBlock(HeaderNode)->getIrrLoopHeaderWeight() && + "Shouldn't have a weight metadata"); + uint64_t MinWeight = MinHeaderWeight.getValue(); + LLVM_DEBUG(dbgs() << "Giving weight " << MinWeight << " to " + << getBlockName(HeaderNode) << "\n"); + if (MinWeight) + Dist.addLocal(HeaderNode, MinWeight); + } + distributeIrrLoopHeaderMass(Dist); + for (const BlockNode &M : Loop.Nodes) + if (!propagateMassToSuccessors(&Loop, M)) + llvm_unreachable("unhandled irreducible control flow"); + if (NumHeadersWithWeight == 0) + // No headers have a metadata. Adjust header mass. + adjustLoopHeaderMass(Loop); + } else { + Working[Loop.getHeader().Index].getMass() = BlockMass::getFull(); + if (!propagateMassToSuccessors(&Loop, Loop.getHeader())) + llvm_unreachable("irreducible control flow to loop header!?"); + for (const BlockNode &M : Loop.members()) + if (!propagateMassToSuccessors(&Loop, M)) + // Irreducible backedge. + return false; + } + + computeLoopScale(Loop); + packageLoop(Loop); + return true; +} + +template <class BT> +bool BlockFrequencyInfoImpl<BT>::tryToComputeMassInFunction() { + // Compute mass in function. + LLVM_DEBUG(dbgs() << "compute-mass-in-function\n"); + assert(!Working.empty() && "no blocks in function"); + assert(!Working[0].isLoopHeader() && "entry block is a loop header"); + + Working[0].getMass() = BlockMass::getFull(); + for (rpot_iterator I = rpot_begin(), IE = rpot_end(); I != IE; ++I) { + // Check for nodes that have been packaged. + BlockNode Node = getNode(I); + if (Working[Node.Index].isPackaged()) + continue; + + if (!propagateMassToSuccessors(nullptr, Node)) + return false; + } + return true; +} + +template <class BT> void BlockFrequencyInfoImpl<BT>::computeMassInFunction() { + if (tryToComputeMassInFunction()) + return; + computeIrreducibleMass(nullptr, Loops.begin()); + if (tryToComputeMassInFunction()) + return; + llvm_unreachable("unhandled irreducible control flow"); +} + +/// \note This should be a lambda, but that crashes GCC 4.7. +namespace bfi_detail { + +template <class BT> struct BlockEdgesAdder { + using BlockT = BT; + using LoopData = BlockFrequencyInfoImplBase::LoopData; + using Successor = GraphTraits<const BlockT *>; + + const BlockFrequencyInfoImpl<BT> &BFI; + + explicit BlockEdgesAdder(const BlockFrequencyInfoImpl<BT> &BFI) + : BFI(BFI) {} + + void operator()(IrreducibleGraph &G, IrreducibleGraph::IrrNode &Irr, + const LoopData *OuterLoop) { + const BlockT *BB = BFI.RPOT[Irr.Node.Index]; + for (const auto Succ : children<const BlockT *>(BB)) + G.addEdge(Irr, BFI.getNode(Succ), OuterLoop); + } +}; + +} // end namespace bfi_detail + +template <class BT> +void BlockFrequencyInfoImpl<BT>::computeIrreducibleMass( + LoopData *OuterLoop, std::list<LoopData>::iterator Insert) { + LLVM_DEBUG(dbgs() << "analyze-irreducible-in-"; + if (OuterLoop) dbgs() + << "loop: " << getLoopName(*OuterLoop) << "\n"; + else dbgs() << "function\n"); + + using namespace bfi_detail; + + // Ideally, addBlockEdges() would be declared here as a lambda, but that + // crashes GCC 4.7. + BlockEdgesAdder<BT> addBlockEdges(*this); + IrreducibleGraph G(*this, OuterLoop, addBlockEdges); + + for (auto &L : analyzeIrreducible(G, OuterLoop, Insert)) + computeMassInLoop(L); + + if (!OuterLoop) + return; + updateLoopWithIrreducible(*OuterLoop); +} + +// A helper function that converts a branch probability into weight. +inline uint32_t getWeightFromBranchProb(const BranchProbability Prob) { + return Prob.getNumerator(); +} + +template <class BT> +bool +BlockFrequencyInfoImpl<BT>::propagateMassToSuccessors(LoopData *OuterLoop, + const BlockNode &Node) { + LLVM_DEBUG(dbgs() << " - node: " << getBlockName(Node) << "\n"); + // Calculate probability for successors. + Distribution Dist; + if (auto *Loop = Working[Node.Index].getPackagedLoop()) { + assert(Loop != OuterLoop && "Cannot propagate mass in a packaged loop"); + if (!addLoopSuccessorsToDist(OuterLoop, *Loop, Dist)) + // Irreducible backedge. + return false; + } else { + const BlockT *BB = getBlock(Node); + for (auto SI = GraphTraits<const BlockT *>::child_begin(BB), + SE = GraphTraits<const BlockT *>::child_end(BB); + SI != SE; ++SI) + if (!addToDist( + Dist, OuterLoop, Node, getNode(*SI), + getWeightFromBranchProb(BPI->getEdgeProbability(BB, SI)))) + // Irreducible backedge. + return false; + } + + // Distribute mass to successors, saving exit and backedge data in the + // loop header. + distributeMass(Node, OuterLoop, Dist); + return true; +} + +template <class BT> +raw_ostream &BlockFrequencyInfoImpl<BT>::print(raw_ostream &OS) const { + if (!F) + return OS; + OS << "block-frequency-info: " << F->getName() << "\n"; + for (const BlockT &BB : *F) { + OS << " - " << bfi_detail::getBlockName(&BB) << ": float = "; + getFloatingBlockFreq(&BB).print(OS, 5) + << ", int = " << getBlockFreq(&BB).getFrequency(); + if (Optional<uint64_t> ProfileCount = + BlockFrequencyInfoImplBase::getBlockProfileCount( + F->getFunction(), getNode(&BB))) + OS << ", count = " << ProfileCount.getValue(); + if (Optional<uint64_t> IrrLoopHeaderWeight = + BB.getIrrLoopHeaderWeight()) + OS << ", irr_loop_header_weight = " << IrrLoopHeaderWeight.getValue(); + OS << "\n"; + } + + // Add an extra newline for readability. + OS << "\n"; + 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 { + using GTraits = GraphTraits<BlockFrequencyInfoT *>; + using NodeRef = typename GTraits::NodeRef; + using EdgeIter = typename GTraits::ChildIteratorType; + using NodeIter = typename GTraits::nodes_iterator; + + uint64_t MaxFrequency = 0; + + explicit BFIDOTGraphTraitsBase(bool isSimple = false) + : DefaultDOTGraphTraits(isSimple) {} + + static std::string getGraphName(const BlockFrequencyInfoT *G) { + return G->getFunction()->getName(); + } + + std::string getNodeAttributes(NodeRef 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) { + NodeRef 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(NodeRef Node, const BlockFrequencyInfoT *Graph, + GVDAGType GType, int layout_order = -1) { + std::string Result; + raw_string_ostream OS(Result); + + if (layout_order != -1) + OS << Node->getName() << "[" << layout_order << "] : "; + else + OS << Node->getName() << " : "; + 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(NodeRef 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 + +#endif // LLVM_ANALYSIS_BLOCKFREQUENCYINFOIMPL_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/BranchProbabilityInfo.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/BranchProbabilityInfo.h new file mode 100644 index 0000000..41d6c23 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/BranchProbabilityInfo.h
@@ -0,0 +1,252 @@ +//===- BranchProbabilityInfo.h - Branch Probability Analysis ----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This pass is used to evaluate branch probabilties. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_BRANCHPROBABILITYINFO_H +#define LLVM_ANALYSIS_BRANCHPROBABILITYINFO_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/CFG.h" +#include "llvm/IR/PassManager.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/Pass.h" +#include "llvm/Support/BranchProbability.h" +#include "llvm/Support/Casting.h" +#include <algorithm> +#include <cassert> +#include <cstdint> +#include <utility> + +namespace llvm { + +class Function; +class LoopInfo; +class raw_ostream; +class PostDominatorTree; +class TargetLibraryInfo; +class Value; + +/// Analysis providing branch probability information. +/// +/// This is a function analysis which provides information on the relative +/// probabilities of each "edge" in the function's CFG where such an edge is +/// defined by a pair (PredBlock and an index in the successors). The +/// probability of an edge from one block is always relative to the +/// probabilities of other edges from the block. The probabilites of all edges +/// from a block sum to exactly one (100%). +/// We use a pair (PredBlock and an index in the successors) to uniquely +/// identify an edge, since we can have multiple edges from Src to Dst. +/// As an example, we can have a switch which jumps to Dst with value 0 and +/// value 10. +class BranchProbabilityInfo { +public: + BranchProbabilityInfo() = default; + + BranchProbabilityInfo(const Function &F, const LoopInfo &LI, + const TargetLibraryInfo *TLI = nullptr) { + calculate(F, LI, TLI); + } + + BranchProbabilityInfo(BranchProbabilityInfo &&Arg) + : Probs(std::move(Arg.Probs)), LastF(Arg.LastF), + PostDominatedByUnreachable(std::move(Arg.PostDominatedByUnreachable)), + PostDominatedByColdCall(std::move(Arg.PostDominatedByColdCall)) {} + + BranchProbabilityInfo(const BranchProbabilityInfo &) = delete; + BranchProbabilityInfo &operator=(const BranchProbabilityInfo &) = delete; + + BranchProbabilityInfo &operator=(BranchProbabilityInfo &&RHS) { + releaseMemory(); + Probs = std::move(RHS.Probs); + PostDominatedByColdCall = std::move(RHS.PostDominatedByColdCall); + PostDominatedByUnreachable = std::move(RHS.PostDominatedByUnreachable); + return *this; + } + + void releaseMemory(); + + void print(raw_ostream &OS) const; + + /// Get an edge's probability, relative to other out-edges of the Src. + /// + /// This routine provides access to the fractional probability between zero + /// (0%) and one (100%) of this edge executing, relative to other edges + /// leaving the 'Src' block. The returned probability is never zero, and can + /// only be one if the source block has only one successor. + BranchProbability getEdgeProbability(const BasicBlock *Src, + unsigned IndexInSuccessors) const; + + /// Get the probability of going from Src to Dst. + /// + /// It returns the sum of all probabilities for edges from Src to Dst. + BranchProbability getEdgeProbability(const BasicBlock *Src, + const BasicBlock *Dst) const; + + BranchProbability getEdgeProbability(const BasicBlock *Src, + succ_const_iterator Dst) const; + + /// Test if an edge is hot relative to other out-edges of the Src. + /// + /// Check whether this edge out of the source block is 'hot'. We define hot + /// as having a relative probability >= 80%. + bool isEdgeHot(const BasicBlock *Src, const BasicBlock *Dst) const; + + /// Retrieve the hot successor of a block if one exists. + /// + /// Given a basic block, look through its successors and if one exists for + /// which \see isEdgeHot would return true, return that successor block. + const BasicBlock *getHotSucc(const BasicBlock *BB) const; + + /// Print an edge's probability. + /// + /// Retrieves an edge's probability similarly to \see getEdgeProbability, but + /// then prints that probability to the provided stream. That stream is then + /// returned. + raw_ostream &printEdgeProbability(raw_ostream &OS, const BasicBlock *Src, + const BasicBlock *Dst) const; + + /// Set the raw edge probability for the given edge. + /// + /// This allows a pass to explicitly set the edge probability for an edge. It + /// can be used when updating the CFG to update and preserve the branch + /// probability information. Read the implementation of how these edge + /// probabilities are calculated carefully before using! + void setEdgeProbability(const BasicBlock *Src, unsigned IndexInSuccessors, + BranchProbability Prob); + + static BranchProbability getBranchProbStackProtector(bool IsLikely) { + static const BranchProbability LikelyProb((1u << 20) - 1, 1u << 20); + return IsLikely ? LikelyProb : LikelyProb.getCompl(); + } + + void calculate(const Function &F, const LoopInfo &LI, + const TargetLibraryInfo *TLI = nullptr); + + /// Forget analysis results for the given basic block. + void eraseBlock(const BasicBlock *BB); + + // Use to track SCCs for handling irreducible loops. + using SccMap = DenseMap<const BasicBlock *, int>; + using SccHeaderMap = DenseMap<const BasicBlock *, bool>; + using SccHeaderMaps = std::vector<SccHeaderMap>; + struct SccInfo { + SccMap SccNums; + SccHeaderMaps SccHeaders; + }; + +private: + // 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. + using Edge = std::pair<const BasicBlock *, unsigned>; + + // Default weight value. Used when we don't have information about the edge. + // TODO: DEFAULT_WEIGHT makes sense during static predication, when none of + // the successors have a weight yet. But it doesn't make sense when providing + // weight to an edge that may have siblings with non-zero weights. This can + // be handled various ways, but it's probably fine for an edge with unknown + // weight to just "inherit" the non-zero weight of an adjacent successor. + static const uint32_t DEFAULT_WEIGHT = 16; + + DenseMap<Edge, BranchProbability> Probs; + + /// Track the last function we run over for printing. + const Function *LastF = nullptr; + + /// Track the set of blocks directly succeeded by a returning block. + SmallPtrSet<const BasicBlock *, 16> PostDominatedByUnreachable; + + /// Track the set of blocks that always lead to a cold call. + SmallPtrSet<const BasicBlock *, 16> PostDominatedByColdCall; + + void computePostDominatedByUnreachable(const Function &F, + PostDominatorTree *PDT); + void computePostDominatedByColdCall(const Function &F, + PostDominatorTree *PDT); + 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, + SccInfo &SccI); + bool calcZeroHeuristics(const BasicBlock *BB, const TargetLibraryInfo *TLI); + bool calcFloatingPointHeuristics(const BasicBlock *BB); + bool calcInvokeHeuristics(const BasicBlock *BB); +}; + +/// Analysis pass which computes \c BranchProbabilityInfo. +class BranchProbabilityAnalysis + : public AnalysisInfoMixin<BranchProbabilityAnalysis> { + friend AnalysisInfoMixin<BranchProbabilityAnalysis>; + + static AnalysisKey Key; + +public: + /// Provide the result type for this analysis pass. + using Result = BranchProbabilityInfo; + + /// Run the analysis pass over a function and produce BPI. + BranchProbabilityInfo run(Function &F, FunctionAnalysisManager &AM); +}; + +/// 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, FunctionAnalysisManager &AM); +}; + +/// Legacy analysis pass which computes \c BranchProbabilityInfo. +class BranchProbabilityInfoWrapperPass : public FunctionPass { + BranchProbabilityInfo BPI; + +public: + static char ID; + + BranchProbabilityInfoWrapperPass(); + + BranchProbabilityInfo &getBPI() { return BPI; } + const BranchProbabilityInfo &getBPI() const { return BPI; } + + void getAnalysisUsage(AnalysisUsage &AU) const override; + bool runOnFunction(Function &F) override; + void releaseMemory() override; + void print(raw_ostream &OS, const Module *M = nullptr) const override; +}; + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_BRANCHPROBABILITYINFO_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/CFG.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/CFG.h new file mode 100644 index 0000000..68f137b --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/CFG.h
@@ -0,0 +1,176 @@ +//===-- Analysis/CFG.h - BasicBlock Analyses --------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This family of functions performs analyses on basic blocks, and instructions +// contained within basic blocks. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CFG_H +#define LLVM_ANALYSIS_CFG_H + +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/CFG.h" + +namespace llvm { + +class BasicBlock; +class DominatorTree; +class Function; +class Instruction; +class LoopInfo; + +/// Analyze the specified function to find all of the loop backedges in the +/// function and return them. This is a relatively cheap (compared to +/// computing dominators and loop info) analysis. +/// +/// The output is added to Result, as pairs of <from,to> edge info. +void FindFunctionBackedges( + const Function &F, + SmallVectorImpl<std::pair<const BasicBlock *, const BasicBlock *> > & + Result); + +/// Search for the specified successor of basic block BB and return its position +/// in the terminator instruction's list of successors. It is an error to call +/// this with a block that is not a successor. +unsigned GetSuccessorNumber(const BasicBlock *BB, const BasicBlock *Succ); + +/// Return true if the specified edge is a critical edge. Critical edges are +/// edges from a block with multiple successors to a block with multiple +/// predecessors. +/// +bool isCriticalEdge(const Instruction *TI, unsigned SuccNum, + bool AllowIdenticalEdges = false); +bool isCriticalEdge(const Instruction *TI, const BasicBlock *Succ, + bool AllowIdenticalEdges = false); + +/// Determine whether instruction 'To' is reachable from 'From', without passing +/// through any blocks in ExclusionSet, returning true if uncertain. +/// +/// Determine whether there is a path from From to To within a single function. +/// Returns false only if we can prove that once 'From' has been executed then +/// 'To' can not be executed. Conservatively returns true. +/// +/// This function is linear with respect to the number of blocks in the CFG, +/// walking down successors from From to reach To, with a fixed threshold. +/// Using DT or LI allows us to answer more quickly. LI reduces the cost of +/// an entire loop of any number of blocks to be the same as the cost of a +/// single block. DT reduces the cost by allowing the search to terminate when +/// we find a block that dominates the block containing 'To'. DT is most useful +/// on branchy code but not loops, and LI is most useful on code with loops but +/// does not help on branchy code outside loops. +bool isPotentiallyReachable( + const Instruction *From, const Instruction *To, + const SmallPtrSetImpl<BasicBlock *> *ExclusionSet = nullptr, + const DominatorTree *DT = nullptr, const LoopInfo *LI = nullptr); + +/// Determine whether block 'To' is reachable from 'From', returning +/// true if uncertain. +/// +/// Determine whether there is a path from From to To within a single function. +/// Returns false only if we can prove that once 'From' has been reached then +/// 'To' can not be executed. Conservatively returns true. +bool isPotentiallyReachable(const BasicBlock *From, const BasicBlock *To, + const DominatorTree *DT = nullptr, + const LoopInfo *LI = nullptr); + +/// Determine whether there is at least one path from a block in +/// 'Worklist' to 'StopBB', returning true if uncertain. +/// +/// Determine whether there is a path from at least one block in Worklist to +/// StopBB within a single function. Returns false only if we can prove that +/// once any block in 'Worklist' has been reached then 'StopBB' can not be +/// executed. Conservatively returns true. +bool isPotentiallyReachableFromMany(SmallVectorImpl<BasicBlock *> &Worklist, + BasicBlock *StopBB, + const DominatorTree *DT = nullptr, + const LoopInfo *LI = nullptr); + +/// Determine whether there is at least one path from a block in +/// 'Worklist' to 'StopBB' without passing through any blocks in +/// 'ExclusionSet', returning true if uncertain. +/// +/// Determine whether there is a path from at least one block in Worklist to +/// StopBB within a single function without passing through any of the blocks +/// in 'ExclusionSet'. Returns false only if we can prove that once any block +/// in 'Worklist' has been reached then 'StopBB' can not be executed. +/// Conservatively returns true. +bool isPotentiallyReachableFromMany( + SmallVectorImpl<BasicBlock *> &Worklist, BasicBlock *StopBB, + const SmallPtrSetImpl<BasicBlock *> *ExclusionSet, + const DominatorTree *DT = nullptr, const LoopInfo *LI = nullptr); + +/// Return true if the control flow in \p RPOTraversal is irreducible. +/// +/// This is a generic implementation to detect CFG irreducibility based on loop +/// info analysis. It can be used for any kind of CFG (Loop, MachineLoop, +/// Function, MachineFunction, etc.) by providing an RPO traversal (\p +/// RPOTraversal) and the loop info analysis (\p LI) of the CFG. This utility +/// function is only recommended when loop info analysis is available. If loop +/// info analysis isn't available, please, don't compute it explicitly for this +/// purpose. There are more efficient ways to detect CFG irreducibility that +/// don't require recomputing loop info analysis (e.g., T1/T2 or Tarjan's +/// algorithm). +/// +/// Requirements: +/// 1) GraphTraits must be implemented for NodeT type. It is used to access +/// NodeT successors. +// 2) \p RPOTraversal must be a valid reverse post-order traversal of the +/// target CFG with begin()/end() iterator interfaces. +/// 3) \p LI must be a valid LoopInfoBase that contains up-to-date loop +/// analysis information of the CFG. +/// +/// This algorithm uses the information about reducible loop back-edges already +/// computed in \p LI. When a back-edge is found during the RPO traversal, the +/// algorithm checks whether the back-edge is one of the reducible back-edges in +/// loop info. If it isn't, the CFG is irreducible. For example, for the CFG +/// below (canonical irreducible graph) loop info won't contain any loop, so the +/// algorithm will return that the CFG is irreducible when checking the B <- +/// -> C back-edge. +/// +/// (A->B, A->C, B->C, C->B, C->D) +/// A +/// / \ +/// B<- ->C +/// | +/// D +/// +template <class NodeT, class RPOTraversalT, class LoopInfoT, + class GT = GraphTraits<NodeT>> +bool containsIrreducibleCFG(RPOTraversalT &RPOTraversal, const LoopInfoT &LI) { + /// Check whether the edge (\p Src, \p Dst) is a reducible loop backedge + /// according to LI. I.e., check if there exists a loop that contains Src and + /// where Dst is the loop header. + auto isProperBackedge = [&](NodeT Src, NodeT Dst) { + for (const auto *Lp = LI.getLoopFor(Src); Lp; Lp = Lp->getParentLoop()) { + if (Lp->getHeader() == Dst) + return true; + } + return false; + }; + + SmallPtrSet<NodeT, 32> Visited; + for (NodeT Node : RPOTraversal) { + Visited.insert(Node); + for (NodeT Succ : make_range(GT::child_begin(Node), GT::child_end(Node))) { + // Succ hasn't been visited yet + if (!Visited.count(Succ)) + continue; + // We already visited Succ, thus Node->Succ must be a backedge. Check that + // the head matches what we have in the loop information. Otherwise, we + // have an irreducible graph. + if (!isProperBackedge(Node, Succ)) + return true; + } + } + + return false; +} +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/CFGPrinter.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/CFGPrinter.h new file mode 100644 index 0000000..aaefc11 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/CFGPrinter.h
@@ -0,0 +1,185 @@ +//===-- CFGPrinter.h - CFG printer external interface -----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines a 'dot-cfg' analysis pass, which emits the +// cfg.<fnname>.dot file for each function in the program, with a graph of the +// CFG for that function. +// +// This file defines external functions that can be called to explicitly +// instantiate the CFG printer. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CFGPRINTER_H +#define LLVM_ANALYSIS_CFGPRINTER_H + +#include "llvm/IR/CFG.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Support/GraphWriter.h" + +namespace llvm { +class CFGViewerPass + : public PassInfoMixin<CFGViewerPass> { +public: + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + +class CFGOnlyViewerPass + : public PassInfoMixin<CFGOnlyViewerPass> { +public: + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + +class CFGPrinterPass + : public PassInfoMixin<CFGPrinterPass> { +public: + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + +class CFGOnlyPrinterPass + : public PassInfoMixin<CFGOnlyPrinterPass> { +public: + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + +template<> +struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits { + + DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {} + + static std::string getGraphName(const Function *F) { + return "CFG for '" + F->getName().str() + "' function"; + } + + static std::string getSimpleNodeLabel(const BasicBlock *Node, + const Function *) { + if (!Node->getName().empty()) + return Node->getName().str(); + + std::string Str; + raw_string_ostream OS(Str); + + Node->printAsOperand(OS, false); + return OS.str(); + } + + static std::string getCompleteNodeLabel(const BasicBlock *Node, + const Function *) { + enum { MaxColumns = 80 }; + std::string Str; + raw_string_ostream OS(Str); + + if (Node->getName().empty()) { + Node->printAsOperand(OS, false); + OS << ":"; + } + + OS << *Node; + std::string OutStr = OS.str(); + if (OutStr[0] == '\n') OutStr.erase(OutStr.begin()); + + // Process string output to make it nicer... + unsigned ColNum = 0; + unsigned LastSpace = 0; + for (unsigned i = 0; i != OutStr.length(); ++i) { + if (OutStr[i] == '\n') { // Left justify + OutStr[i] = '\\'; + OutStr.insert(OutStr.begin()+i+1, 'l'); + ColNum = 0; + LastSpace = 0; + } else if (OutStr[i] == ';') { // Delete comments! + unsigned Idx = OutStr.find('\n', i+1); // Find end of line + OutStr.erase(OutStr.begin()+i, OutStr.begin()+Idx); + --i; + } else if (ColNum == MaxColumns) { // Wrap lines. + // Wrap very long names even though we can't find a space. + if (!LastSpace) + LastSpace = i; + OutStr.insert(LastSpace, "\\l..."); + ColNum = i - LastSpace; + LastSpace = 0; + i += 3; // The loop will advance 'i' again. + } + else + ++ColNum; + if (OutStr[i] == ' ') + LastSpace = i; + } + return OutStr; + } + + std::string getNodeLabel(const BasicBlock *Node, + const Function *Graph) { + if (isSimple()) + return getSimpleNodeLabel(Node, Graph); + else + return getCompleteNodeLabel(Node, Graph); + } + + static std::string getEdgeSourceLabel(const BasicBlock *Node, + succ_const_iterator I) { + // Label source of conditional branches with "T" or "F" + if (const BranchInst *BI = dyn_cast<BranchInst>(Node->getTerminator())) + if (BI->isConditional()) + return (I == succ_begin(Node)) ? "T" : "F"; + + // Label source of switch edges with the associated value. + if (const SwitchInst *SI = dyn_cast<SwitchInst>(Node->getTerminator())) { + unsigned SuccNo = I.getSuccessorIndex(); + + if (SuccNo == 0) return "def"; + + std::string Str; + raw_string_ostream OS(Str); + auto Case = *SwitchInst::ConstCaseIt::fromSuccessorIndex(SI, SuccNo); + OS << Case.getCaseValue()->getValue(); + return OS.str(); + } + return ""; + } + + /// Display the raw branch weights from PGO. + std::string getEdgeAttributes(const BasicBlock *Node, succ_const_iterator I, + const Function *F) { + const Instruction *TI = Node->getTerminator(); + if (TI->getNumSuccessors() == 1) + return ""; + + MDNode *WeightsNode = TI->getMetadata(LLVMContext::MD_prof); + if (!WeightsNode) + return ""; + + MDString *MDName = cast<MDString>(WeightsNode->getOperand(0)); + if (MDName->getString() != "branch_weights") + return ""; + + unsigned OpNo = I.getSuccessorIndex() + 1; + if (OpNo >= WeightsNode->getNumOperands()) + return ""; + ConstantInt *Weight = + mdconst::dyn_extract<ConstantInt>(WeightsNode->getOperand(OpNo)); + if (!Weight) + return ""; + + // Prepend a 'W' to indicate that this is a weight rather than the actual + // profile count (due to scaling). + return ("label=\"W:" + Twine(Weight->getZExtValue()) + "\"").str(); + } +}; +} // End llvm namespace + +namespace llvm { + class FunctionPass; + FunctionPass *createCFGPrinterLegacyPassPass (); + FunctionPass *createCFGOnlyPrinterLegacyPassPass (); +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/CFLAliasAnalysisUtils.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/CFLAliasAnalysisUtils.h new file mode 100644 index 0000000..02f999a --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/CFLAliasAnalysisUtils.h
@@ -0,0 +1,57 @@ +//=- CFLAliasAnalysisUtils.h - Utilities for CFL Alias Analysis ----*- C++-*-=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// \file +// These are the utilities/helpers used by the CFL Alias Analyses available in +// tree, i.e. Steensgaard's and Andersens'. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CFLALIASANALYSISUTILS_H +#define LLVM_ANALYSIS_CFLALIASANALYSISUTILS_H + +#include "llvm/IR/Function.h" +#include "llvm/IR/ValueHandle.h" + +namespace llvm { +namespace cflaa { + +template <typename AAResult> struct FunctionHandle final : public CallbackVH { + FunctionHandle(Function *Fn, AAResult *Result) + : CallbackVH(Fn), Result(Result) { + assert(Fn != nullptr); + assert(Result != nullptr); + } + + void deleted() override { removeSelfFromCache(); } + void allUsesReplacedWith(Value *) override { removeSelfFromCache(); } + +private: + AAResult *Result; + + void removeSelfFromCache() { + assert(Result != nullptr); + auto *Val = getValPtr(); + Result->evict(cast<Function>(Val)); + setValPtr(nullptr); + } +}; + +static inline const Function *parentFunctionOfValue(const Value *Val) { + if (auto *Inst = dyn_cast<Instruction>(Val)) { + auto *Bb = Inst->getParent(); + return Bb->getParent(); + } + + if (auto *Arg = dyn_cast<Argument>(Val)) + return Arg->getParent(); + return nullptr; +} // namespace cflaa +} // namespace llvm +} + +#endif // LLVM_ANALYSIS_CFLALIASANALYSISUTILS_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/CFLAndersAliasAnalysis.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/CFLAndersAliasAnalysis.h new file mode 100644 index 0000000..5f5e52a --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/CFLAndersAliasAnalysis.h
@@ -0,0 +1,127 @@ +//==- CFLAndersAliasAnalysis.h - Unification-based Alias Analysis -*- C++-*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// \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/Analysis/CFLAliasAnalysisUtils.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Pass.h" +#include <forward_list> +#include <memory> + +namespace llvm { + +class Function; +class MemoryLocation; +class TargetLibraryInfo; + +namespace cflaa { + +struct AliasSummary; + +} // end namespace cflaa + +class CFLAndersAAResult : public AAResultBase<CFLAndersAAResult> { + friend AAResultBase<CFLAndersAAResult>; + + class FunctionInfo; + +public: + explicit CFLAndersAAResult( + std::function<const TargetLibraryInfo &(Function &F)> GetTLI); + CFLAndersAAResult(CFLAndersAAResult &&RHS); + ~CFLAndersAAResult(); + + /// Handle invalidation events from the new pass manager. + /// By definition, this result is stateless and so remains valid. + bool invalidate(Function &, const PreservedAnalyses &, + FunctionAnalysisManager::Invalidator &) { + return false; + } + + /// Evict the given function from cache + void evict(const Function *Fn); + + /// 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 &, + AAQueryInfo &); + +private: + /// Ensures that the given function is available in the cache. + /// Returns the appropriate entry from the cache. + const Optional<FunctionInfo> &ensureCached(const Function &); + + /// Inserts the given Function into the cache. + void scan(const Function &); + + /// Build summary for a given function + FunctionInfo buildInfoFrom(const Function &); + + std::function<const TargetLibraryInfo &(Function &F)> GetTLI; + + /// 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<cflaa::FunctionHandle<CFLAndersAAResult>> 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 AnalysisKey Key; + +public: + using Result = CFLAndersAAResult; + + CFLAndersAAResult run(Function &F, FunctionAnalysisManager &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(); + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_CFLANDERSALIASANALYSIS_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/CFLSteensAliasAnalysis.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/CFLSteensAliasAnalysis.h new file mode 100644 index 0000000..1353216 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/CFLSteensAliasAnalysis.h
@@ -0,0 +1,144 @@ +//==- CFLSteensAliasAnalysis.h - Unification-based Alias Analysis -*- C++-*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// \file +/// This is the interface for LLVM's unification-based alias analysis +/// implemented with CFL graph reachability. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CFLSTEENSALIASANALYSIS_H +#define LLVM_ANALYSIS_CFLSTEENSALIASANALYSIS_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Optional.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/CFLAliasAnalysisUtils.h" +#include "llvm/Analysis/MemoryLocation.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Pass.h" +#include "llvm/Support/Casting.h" +#include <forward_list> +#include <memory> + +namespace llvm { + +class Function; +class TargetLibraryInfo; + +namespace cflaa { + +struct AliasSummary; + +} // end namespace cflaa + +class CFLSteensAAResult : public AAResultBase<CFLSteensAAResult> { + friend AAResultBase<CFLSteensAAResult>; + + class FunctionInfo; + +public: + explicit CFLSteensAAResult( + std::function<const TargetLibraryInfo &(Function &)> GetTLI); + CFLSteensAAResult(CFLSteensAAResult &&Arg); + ~CFLSteensAAResult(); + + /// Handle invalidation events from the new pass manager. + /// + /// By definition, this result is stateless and so remains valid. + bool invalidate(Function &, const PreservedAnalyses &, + FunctionAnalysisManager::Invalidator &) { + return false; + } + + /// Inserts the given Function into the cache. + void scan(Function *Fn); + + void evict(Function *Fn); + + /// Ensures that the given function is available in the cache. + /// Returns the appropriate entry from the cache. + const Optional<FunctionInfo> &ensureCached(Function *Fn); + + /// 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, + AAQueryInfo &AAQI) { + if (LocA.Ptr == LocB.Ptr) + return MustAlias; + + // Comparisons between global variables and other constants should be + // handled by BasicAA. + // 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, AAQI); + + AliasResult QueryResult = query(LocA, LocB); + if (QueryResult == MayAlias) + return AAResultBase::alias(LocA, LocB, AAQI); + + return QueryResult; + } + +private: + std::function<const TargetLibraryInfo &(Function &)> GetTLI; + + /// 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<Function *, Optional<FunctionInfo>> Cache; + std::forward_list<cflaa::FunctionHandle<CFLSteensAAResult>> Handles; + + FunctionInfo buildSetsFrom(Function *F); +}; + +/// 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 of sets. +class CFLSteensAA : public AnalysisInfoMixin<CFLSteensAA> { + friend AnalysisInfoMixin<CFLSteensAA>; + + static AnalysisKey Key; + +public: + using Result = CFLSteensAAResult; + + CFLSteensAAResult run(Function &F, FunctionAnalysisManager &AM); +}; + +/// Legacy wrapper pass to provide the CFLSteensAAResult object. +class CFLSteensAAWrapperPass : public ImmutablePass { + std::unique_ptr<CFLSteensAAResult> Result; + +public: + static char ID; + + CFLSteensAAWrapperPass(); + + CFLSteensAAResult &getResult() { return *Result; } + const CFLSteensAAResult &getResult() const { return *Result; } + + void initializePass() override; + void getAnalysisUsage(AnalysisUsage &AU) const override; +}; + +// createCFLSteensAAWrapperPass - This pass implements a set-based approach to +// alias analysis. +ImmutablePass *createCFLSteensAAWrapperPass(); + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_CFLSTEENSALIASANALYSIS_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/CGSCCPassManager.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/CGSCCPassManager.h new file mode 100644 index 0000000..933f221 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/CGSCCPassManager.h
@@ -0,0 +1,940 @@ +//===- CGSCCPassManager.h - Call graph pass management ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This header provides classes for managing passes over SCCs of the call +/// graph. These passes form an important component of LLVM's interprocedural +/// optimizations. Because they operate on the SCCs of the call graph, and they +/// traverse the graph in post-order, they can effectively do pair-wise +/// interprocedural optimizations for all call edges in the program while +/// incrementally refining it and improving the context of these pair-wise +/// optimizations. 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. +/// +/// A secondary more general goal is to be able to isolate optimization on +/// unrelated parts of the IR module. This is useful to ensure our +/// optimizations are principled and don't miss oportunities where refinement +/// of one part of the module influence transformations in another part of the +/// module. But this is also useful if we want to parallelize the optimizations +/// across common large module graph shapes which tend to be very wide and have +/// large regions of unrelated cliques. +/// +/// To satisfy these goals, we use the LazyCallGraph which provides two graphs +/// nested inside each other (and built lazily from the bottom-up): the call +/// graph proper, and a reference graph. The reference graph is super set of +/// the call graph and is a conservative approximation of what could through +/// scalar or CGSCC transforms *become* the call graph. Using this allows us to +/// ensure we optimize functions prior to them being introduced into the call +/// graph by devirtualization or other technique, and thus ensures that +/// subsequent pair-wise interprocedural optimizations observe the optimized +/// form of these functions. The (potentially transitive) reference +/// reachability used by the reference graph is a conservative approximation +/// that still allows us to have independent regions of the graph. +/// +/// FIXME: There is one major drawback of the reference graph: in its naive +/// form it is quadratic because it contains a distinct edge for each +/// (potentially indirect) reference, even if are all through some common +/// global table of function pointers. This can be fixed in a number of ways +/// that essentially preserve enough of the normalization. While it isn't +/// expected to completely preclude the usability of this, it will need to be +/// addressed. +/// +/// +/// All of these issues are made substantially more complex in the face of +/// mutations to the call graph while optimization passes are being run. When +/// mutations to the call graph occur we want to achieve two different things: +/// +/// - We need to update the call graph in-flight and invalidate analyses +/// cached on entities in the graph. Because of the cache-based analysis +/// design of the pass manager, it is essential to have stable identities for +/// the elements of the IR that passes traverse, and to invalidate any +/// analyses cached on these elements as the mutations take place. +/// +/// - We want to preserve the incremental and post-order traversal of the +/// graph even as it is refined and mutated. This means we want optimization +/// to observe the most refined form of the call graph and to do so in +/// post-order. +/// +/// To address this, the CGSCC manager uses both worklists that can be expanded +/// by passes which transform the IR, and provides invalidation tests to skip +/// entries that become dead. This extra data is provided to every SCC pass so +/// that it can carefully update the manager's traversal as the call graph +/// mutates. +/// +/// We also provide support for running function passes within the CGSCC walk, +/// and there we provide automatic update of the call graph including of the +/// pass manager to reflect call graph changes that fall out naturally as part +/// of scalar transformations. +/// +/// The patterns used to ensure the goals of post-order visitation of the fully +/// refined graph: +/// +/// 1) Sink toward the "bottom" as the graph is refined. This means that any +/// iteration continues in some valid post-order sequence after the mutation +/// has altered the structure. +/// +/// 2) Enqueue in post-order, including the current entity. If the current +/// entity's shape changes, it and everything after it in post-order needs +/// to be visited to observe that shape. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CGSCCPASSMANAGER_H +#define LLVM_ANALYSIS_CGSCCPASSMANAGER_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/PriorityWorklist.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Analysis/LazyCallGraph.h" +#include "llvm/IR/CallSite.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/InstIterator.h" +#include "llvm/IR/PassManager.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cassert> +#include <utility> + +namespace llvm { + +struct CGSCCUpdateResult; +class Module; + +// Allow debug logging in this inline function. +#define DEBUG_TYPE "cgscc" + +/// Extern template declaration for the analysis set for this IR unit. +extern template class AllAnalysesOn<LazyCallGraph::SCC>; + +extern template class AnalysisManager<LazyCallGraph::SCC, LazyCallGraph &>; + +/// The CGSCC analysis manager. +/// +/// See the documentation for the AnalysisManager template for detail +/// documentation. This type 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. +using CGSCCAnalysisManager = + AnalysisManager<LazyCallGraph::SCC, LazyCallGraph &>; + +// Explicit specialization and instantiation declarations for the pass manager. +// See the comments on the definition of the specialization for details on how +// it differs from the primary template. +template <> +PreservedAnalyses +PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &, + CGSCCUpdateResult &>::run(LazyCallGraph::SCC &InitialC, + CGSCCAnalysisManager &AM, + LazyCallGraph &G, CGSCCUpdateResult &UR); +extern template class PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager, + LazyCallGraph &, CGSCCUpdateResult &>; + +/// The CGSCC pass manager. +/// +/// See the documentation for the PassManager template for details. It runs +/// a sequence of SCC passes over each SCC that the manager is run over. This +/// type serves as a convenient way to refer to this construct. +using CGSCCPassManager = + PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &, + CGSCCUpdateResult &>; + +/// An explicit specialization of the require analysis template pass. +template <typename AnalysisT> +struct RequireAnalysisPass<AnalysisT, LazyCallGraph::SCC, CGSCCAnalysisManager, + LazyCallGraph &, CGSCCUpdateResult &> + : PassInfoMixin<RequireAnalysisPass<AnalysisT, LazyCallGraph::SCC, + CGSCCAnalysisManager, LazyCallGraph &, + CGSCCUpdateResult &>> { + PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, + LazyCallGraph &CG, CGSCCUpdateResult &) { + (void)AM.template getResult<AnalysisT>(C, CG); + return PreservedAnalyses::all(); + } +}; + +/// A proxy from a \c CGSCCAnalysisManager to a \c Module. +using CGSCCAnalysisManagerModuleProxy = + InnerAnalysisManagerProxy<CGSCCAnalysisManager, Module>; + +/// We need a specialized result for the \c CGSCCAnalysisManagerModuleProxy so +/// it can have access to the call graph in order to walk all the SCCs when +/// invalidating things. +template <> class CGSCCAnalysisManagerModuleProxy::Result { +public: + explicit Result(CGSCCAnalysisManager &InnerAM, LazyCallGraph &G) + : InnerAM(&InnerAM), G(&G) {} + + /// Accessor for the analysis manager. + CGSCCAnalysisManager &getManager() { return *InnerAM; } + + /// Handler for invalidation of the Module. + /// + /// If the proxy analysis itself is preserved, then we assume that the set of + /// SCCs in the Module hasn't changed. Thus any pointers to SCCs in the + /// CGSCCAnalysisManager are still valid, and we don't need to call \c clear + /// on the 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, + ModuleAnalysisManager::Invalidator &Inv); + +private: + CGSCCAnalysisManager *InnerAM; + LazyCallGraph *G; +}; + +/// Provide a specialized run method for the \c CGSCCAnalysisManagerModuleProxy +/// so it can pass the lazy call graph to the result. +template <> +CGSCCAnalysisManagerModuleProxy::Result +CGSCCAnalysisManagerModuleProxy::run(Module &M, ModuleAnalysisManager &AM); + +// Ensure the \c CGSCCAnalysisManagerModuleProxy is provided as an extern +// template. +extern template class InnerAnalysisManagerProxy<CGSCCAnalysisManager, Module>; + +extern template class OuterAnalysisManagerProxy< + ModuleAnalysisManager, LazyCallGraph::SCC, LazyCallGraph &>; + +/// A proxy from a \c ModuleAnalysisManager to an \c SCC. +using ModuleAnalysisManagerCGSCCProxy = + OuterAnalysisManagerProxy<ModuleAnalysisManager, LazyCallGraph::SCC, + LazyCallGraph &>; + +/// Support structure for SCC passes to communicate updates the call graph back +/// to the CGSCC pass manager infrsatructure. +/// +/// The CGSCC pass manager runs SCC passes which are allowed to update the call +/// graph and SCC structures. This means the structure the pass manager works +/// on is mutating underneath it. In order to support that, there needs to be +/// careful communication about the precise nature and ramifications of these +/// updates to the pass management infrastructure. +/// +/// All SCC passes will have to accept a reference to the management layer's +/// update result struct and use it to reflect the results of any CG updates +/// performed. +/// +/// Passes which do not change the call graph structure in any way can just +/// ignore this argument to their run method. +struct CGSCCUpdateResult { + /// Worklist of the RefSCCs queued for processing. + /// + /// When a pass refines the graph and creates new RefSCCs or causes them to + /// have a different shape or set of component SCCs it should add the RefSCCs + /// to this worklist so that we visit them in the refined form. + /// + /// This worklist is in reverse post-order, as we pop off the back in order + /// to observe RefSCCs in post-order. When adding RefSCCs, clients should add + /// them in reverse post-order. + SmallPriorityWorklist<LazyCallGraph::RefSCC *, 1> &RCWorklist; + + /// Worklist of the SCCs queued for processing. + /// + /// When a pass refines the graph and creates new SCCs or causes them to have + /// a different shape or set of component functions it should add the SCCs to + /// this worklist so that we visit them in the refined form. + /// + /// Note that if the SCCs are part of a RefSCC that is added to the \c + /// RCWorklist, they don't need to be added here as visiting the RefSCC will + /// be sufficient to re-visit the SCCs within it. + /// + /// This worklist is in reverse post-order, as we pop off the back in order + /// to observe SCCs in post-order. When adding SCCs, clients should add them + /// in reverse post-order. + SmallPriorityWorklist<LazyCallGraph::SCC *, 1> &CWorklist; + + /// The set of invalidated RefSCCs which should be skipped if they are found + /// in \c RCWorklist. + /// + /// This is used to quickly prune out RefSCCs when they get deleted and + /// happen to already be on the worklist. We use this primarily to avoid + /// scanning the list and removing entries from it. + SmallPtrSetImpl<LazyCallGraph::RefSCC *> &InvalidatedRefSCCs; + + /// The set of invalidated SCCs which should be skipped if they are found + /// in \c CWorklist. + /// + /// This is used to quickly prune out SCCs when they get deleted and happen + /// to already be on the worklist. We use this primarily to avoid scanning + /// the list and removing entries from it. + SmallPtrSetImpl<LazyCallGraph::SCC *> &InvalidatedSCCs; + + /// If non-null, the updated current \c RefSCC being processed. + /// + /// This is set when a graph refinement takes place an the "current" point in + /// the graph moves "down" or earlier in the post-order walk. This will often + /// cause the "current" RefSCC to be a newly created RefSCC object and the + /// old one to be added to the above worklist. When that happens, this + /// pointer is non-null and can be used to continue processing the "top" of + /// the post-order walk. + LazyCallGraph::RefSCC *UpdatedRC; + + /// If non-null, the updated current \c SCC being processed. + /// + /// This is set when a graph refinement takes place an the "current" point in + /// the graph moves "down" or earlier in the post-order walk. This will often + /// cause the "current" SCC to be a newly created SCC object and the old one + /// to be added to the above worklist. When that happens, this pointer is + /// non-null and can be used to continue processing the "top" of the + /// post-order walk. + LazyCallGraph::SCC *UpdatedC; + + /// Preserved analyses across SCCs. + /// + /// We specifically want to allow CGSCC passes to mutate ancestor IR + /// (changing both the CG structure and the function IR itself). However, + /// this means we need to take special care to correctly mark what analyses + /// are preserved *across* SCCs. We have to track this out-of-band here + /// because within the main `PassManeger` infrastructure we need to mark + /// everything within an SCC as preserved in order to avoid repeatedly + /// invalidating the same analyses as we unnest pass managers and adaptors. + /// So we track the cross-SCC version of the preserved analyses here from any + /// code that does direct invalidation of SCC analyses, and then use it + /// whenever we move forward in the post-order walk of SCCs before running + /// passes over the new SCC. + PreservedAnalyses CrossSCCPA; + + /// A hacky area where the inliner can retain history about inlining + /// decisions that mutated the call graph's SCC structure in order to avoid + /// infinite inlining. See the comments in the inliner's CG update logic. + /// + /// FIXME: Keeping this here seems like a big layering issue, we should look + /// for a better technique. + SmallDenseSet<std::pair<LazyCallGraph::Node *, LazyCallGraph::SCC *>, 4> + &InlinedInternalEdges; +}; + +/// The core module pass which does a post-order walk of the SCCs and +/// runs a CGSCC pass over each one. +/// +/// Designed to allow composition of a CGSCCPass(Manager) and +/// a ModulePassManager. Note that this pass must be run with a module analysis +/// manager as it uses the LazyCallGraph analysis. It will also run the +/// \c CGSCCAnalysisManagerModuleProxy analysis prior to running the CGSCC +/// pass over the module to enable a \c FunctionAnalysisManager to be used +/// within this run safely. +template <typename CGSCCPassT> +class ModuleToPostOrderCGSCCPassAdaptor + : public PassInfoMixin<ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>> { +public: + explicit ModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass) + : Pass(std::move(Pass)) {} + + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + ModuleToPostOrderCGSCCPassAdaptor( + const ModuleToPostOrderCGSCCPassAdaptor &Arg) + : Pass(Arg.Pass) {} + + ModuleToPostOrderCGSCCPassAdaptor(ModuleToPostOrderCGSCCPassAdaptor &&Arg) + : Pass(std::move(Arg.Pass)) {} + + friend void swap(ModuleToPostOrderCGSCCPassAdaptor &LHS, + ModuleToPostOrderCGSCCPassAdaptor &RHS) { + std::swap(LHS.Pass, RHS.Pass); + } + + ModuleToPostOrderCGSCCPassAdaptor & + operator=(ModuleToPostOrderCGSCCPassAdaptor RHS) { + swap(*this, RHS); + return *this; + } + + /// Runs the CGSCC pass across every SCC in the module. + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); + +private: + CGSCCPassT Pass; +}; + +/// 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)); +} + +/// A proxy from a \c FunctionAnalysisManager to an \c SCC. +/// +/// When a module pass runs and triggers invalidation, both the CGSCC and +/// Function analysis manager proxies on the module get an invalidation event. +/// We don't want to fully duplicate responsibility for most of the +/// invalidation logic. Instead, this layer is only responsible for SCC-local +/// invalidation events. We work with the module's FunctionAnalysisManager to +/// invalidate function analyses. +class FunctionAnalysisManagerCGSCCProxy + : public AnalysisInfoMixin<FunctionAnalysisManagerCGSCCProxy> { +public: + class Result { + public: + explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {} + + /// Accessor for the analysis manager. + FunctionAnalysisManager &getManager() { return *FAM; } + + bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA, + CGSCCAnalysisManager::Invalidator &Inv); + + private: + FunctionAnalysisManager *FAM; + }; + + /// Computes the \c FunctionAnalysisManager and stores it in the result proxy. + Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &); + +private: + friend AnalysisInfoMixin<FunctionAnalysisManagerCGSCCProxy>; + + static AnalysisKey Key; +}; + +extern template class OuterAnalysisManagerProxy<CGSCCAnalysisManager, Function>; + +/// A proxy from a \c CGSCCAnalysisManager to a \c Function. +using CGSCCAnalysisManagerFunctionProxy = + OuterAnalysisManagerProxy<CGSCCAnalysisManager, Function>; + +/// Helper to update the call graph after running a function pass. +/// +/// Function passes can only mutate the call graph in specific ways. This +/// routine provides a helper that updates the call graph in those ways +/// including returning whether any changes were made and populating a CG +/// update result struct for the overall CGSCC walk. +LazyCallGraph::SCC &updateCGAndAnalysisManagerForFunctionPass( + LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N, + CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR); + +/// Adaptor that maps from a SCC to its functions. +/// +/// Designed to allow composition of a FunctionPass(Manager) and +/// a CGSCCPassManager. Note that if this pass is constructed with a pointer +/// to a \c CGSCCAnalysisManager it will run the +/// \c FunctionAnalysisManagerCGSCCProxy analysis prior to running the function +/// pass over the SCC to enable a \c FunctionAnalysisManager to be used +/// within this run safely. +template <typename FunctionPassT> +class CGSCCToFunctionPassAdaptor + : public PassInfoMixin<CGSCCToFunctionPassAdaptor<FunctionPassT>> { +public: + explicit CGSCCToFunctionPassAdaptor(FunctionPassT Pass) + : Pass(std::move(Pass)) {} + + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + CGSCCToFunctionPassAdaptor(const CGSCCToFunctionPassAdaptor &Arg) + : Pass(Arg.Pass) {} + + CGSCCToFunctionPassAdaptor(CGSCCToFunctionPassAdaptor &&Arg) + : Pass(std::move(Arg.Pass)) {} + + friend void swap(CGSCCToFunctionPassAdaptor &LHS, + CGSCCToFunctionPassAdaptor &RHS) { + std::swap(LHS.Pass, RHS.Pass); + } + + CGSCCToFunctionPassAdaptor &operator=(CGSCCToFunctionPassAdaptor RHS) { + swap(*this, RHS); + return *this; + } + + /// Runs the function pass across every function in the module. + PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, + LazyCallGraph &CG, CGSCCUpdateResult &UR) { + // Setup the function analysis manager from its proxy. + FunctionAnalysisManager &FAM = + AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager(); + + SmallVector<LazyCallGraph::Node *, 4> Nodes; + for (LazyCallGraph::Node &N : C) + Nodes.push_back(&N); + + // The SCC may get split while we are optimizing functions due to deleting + // edges. If this happens, the current SCC can shift, so keep track of + // a pointer we can overwrite. + LazyCallGraph::SCC *CurrentC = &C; + + LLVM_DEBUG(dbgs() << "Running function passes across an SCC: " << C + << "\n"); + + PreservedAnalyses PA = PreservedAnalyses::all(); + for (LazyCallGraph::Node *N : Nodes) { + // Skip nodes from other SCCs. These may have been split out during + // processing. We'll eventually visit those SCCs and pick up the nodes + // there. + if (CG.lookupSCC(*N) != CurrentC) + continue; + + Function &F = N->getFunction(); + + PassInstrumentation PI = FAM.getResult<PassInstrumentationAnalysis>(F); + if (!PI.runBeforePass<Function>(Pass, F)) + continue; + + PreservedAnalyses PassPA = Pass.run(F, FAM); + + PI.runAfterPass<Function>(Pass, F); + + // 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. + FAM.invalidate(F, 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)); + + // If the call graph hasn't been preserved, update it based on this + // function pass. This may also update the current SCC to point to + // a smaller, more refined SCC. + auto PAC = PA.getChecker<LazyCallGraphAnalysis>(); + if (!PAC.preserved() && !PAC.preservedSet<AllAnalysesOn<Module>>()) { + CurrentC = &updateCGAndAnalysisManagerForFunctionPass(CG, *CurrentC, *N, + AM, UR); + assert( + CG.lookupSCC(*N) == CurrentC && + "Current SCC not updated to the SCC containing the current node!"); + } + } + + // By definition we preserve the proxy. And we preserve all analyses on + // Functions. This precludes *any* invalidation of function analyses by the + // proxy, but that's OK because we've taken care to invalidate analyses in + // the function analysis manager incrementally above. + PA.preserveSet<AllAnalysesOn<Function>>(); + PA.preserve<FunctionAnalysisManagerCGSCCProxy>(); + + // We've also ensured that we updated the call graph along the way. + PA.preserve<LazyCallGraphAnalysis>(); + + return PA; + } + +private: + FunctionPassT Pass; +}; + +/// 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)); +} + +/// A helper that repeats an SCC pass each time an indirect call is refined to +/// a direct call by that pass. +/// +/// While the CGSCC pass manager works to re-visit SCCs and RefSCCs as they +/// change shape, we may also want to repeat an SCC pass if it simply refines +/// an indirect call to a direct call, even if doing so does not alter the +/// shape of the graph. Note that this only pertains to direct calls to +/// functions where IPO across the SCC may be able to compute more precise +/// results. For intrinsics, we assume scalar optimizations already can fully +/// reason about them. +/// +/// This repetition has the potential to be very large however, as each one +/// might refine a single call site. As a consequence, in practice we use an +/// upper bound on the number of repetitions to limit things. +template <typename PassT> +class DevirtSCCRepeatedPass + : public PassInfoMixin<DevirtSCCRepeatedPass<PassT>> { +public: + explicit DevirtSCCRepeatedPass(PassT Pass, int MaxIterations) + : Pass(std::move(Pass)), MaxIterations(MaxIterations) {} + + /// Runs the wrapped pass up to \c MaxIterations on the SCC, iterating + /// whenever an indirect call is refined. + PreservedAnalyses run(LazyCallGraph::SCC &InitialC, CGSCCAnalysisManager &AM, + LazyCallGraph &CG, CGSCCUpdateResult &UR) { + PreservedAnalyses PA = PreservedAnalyses::all(); + PassInstrumentation PI = + AM.getResult<PassInstrumentationAnalysis>(InitialC, CG); + + // The SCC may be refined while we are running passes over it, so set up + // a pointer that we can update. + LazyCallGraph::SCC *C = &InitialC; + + // Collect value handles for all of the indirect call sites. + SmallVector<WeakTrackingVH, 8> CallHandles; + + // Struct to track the counts of direct and indirect calls in each function + // of the SCC. + struct CallCount { + int Direct; + int Indirect; + }; + + // Put value handles on all of the indirect calls and return the number of + // direct calls for each function in the SCC. + auto ScanSCC = [](LazyCallGraph::SCC &C, + SmallVectorImpl<WeakTrackingVH> &CallHandles) { + assert(CallHandles.empty() && "Must start with a clear set of handles."); + + SmallDenseMap<Function *, CallCount> CallCounts; + CallCount CountLocal = {0, 0}; + for (LazyCallGraph::Node &N : C) { + CallCount &Count = + CallCounts.insert(std::make_pair(&N.getFunction(), CountLocal)) + .first->second; + for (Instruction &I : instructions(N.getFunction())) + if (auto CS = CallSite(&I)) { + if (CS.getCalledFunction()) { + ++Count.Direct; + } else { + ++Count.Indirect; + CallHandles.push_back(WeakTrackingVH(&I)); + } + } + } + + return CallCounts; + }; + + // Populate the initial call handles and get the initial call counts. + auto CallCounts = ScanSCC(*C, CallHandles); + + for (int Iteration = 0;; ++Iteration) { + + if (!PI.runBeforePass<LazyCallGraph::SCC>(Pass, *C)) + continue; + + PreservedAnalyses PassPA = Pass.run(*C, AM, CG, UR); + + if (UR.InvalidatedSCCs.count(C)) + PI.runAfterPassInvalidated<LazyCallGraph::SCC>(Pass); + else + PI.runAfterPass<LazyCallGraph::SCC>(Pass, *C); + + // If the SCC structure has changed, bail immediately and let the outer + // CGSCC layer handle any iteration to reflect the refined structure. + if (UR.UpdatedC && UR.UpdatedC != C) { + PA.intersect(std::move(PassPA)); + break; + } + + // Check that we didn't miss any update scenario. + assert(!UR.InvalidatedSCCs.count(C) && "Processing an invalid SCC!"); + assert(C->begin() != C->end() && "Cannot have an empty SCC!"); + + // Check whether any of the handles were devirtualized. + auto IsDevirtualizedHandle = [&](WeakTrackingVH &CallH) { + if (!CallH) + return false; + auto CS = CallSite(CallH); + if (!CS) + return false; + + // If the call is still indirect, leave it alone. + Function *F = CS.getCalledFunction(); + if (!F) + return false; + + LLVM_DEBUG(dbgs() << "Found devirtualized call from " + << CS.getParent()->getParent()->getName() << " to " + << F->getName() << "\n"); + + // We now have a direct call where previously we had an indirect call, + // so iterate to process this devirtualization site. + return true; + }; + bool Devirt = llvm::any_of(CallHandles, IsDevirtualizedHandle); + + // Rescan to build up a new set of handles and count how many direct + // calls remain. If we decide to iterate, this also sets up the input to + // the next iteration. + CallHandles.clear(); + auto NewCallCounts = ScanSCC(*C, CallHandles); + + // If we haven't found an explicit devirtualization already see if we + // have decreased the number of indirect calls and increased the number + // of direct calls for any function in the SCC. This can be fooled by all + // manner of transformations such as DCE and other things, but seems to + // work well in practice. + if (!Devirt) + // Iterate over the keys in NewCallCounts, if Function also exists in + // CallCounts, make the check below. + for (auto &Pair : NewCallCounts) { + auto &CallCountNew = Pair.second; + auto CountIt = CallCounts.find(Pair.first); + if (CountIt != CallCounts.end()) { + const auto &CallCountOld = CountIt->second; + if (CallCountOld.Indirect > CallCountNew.Indirect && + CallCountOld.Direct < CallCountNew.Direct) { + Devirt = true; + break; + } + } + } + + if (!Devirt) { + PA.intersect(std::move(PassPA)); + break; + } + + // Otherwise, if we've already hit our max, we're done. + if (Iteration >= MaxIterations) { + LLVM_DEBUG( + dbgs() << "Found another devirtualization after hitting the max " + "number of repetitions (" + << MaxIterations << ") on SCC: " << *C << "\n"); + PA.intersect(std::move(PassPA)); + break; + } + + LLVM_DEBUG( + dbgs() + << "Repeating an SCC pass after finding a devirtualization in: " << *C + << "\n"); + + // Move over the new call counts in preparation for iterating. + CallCounts = std::move(NewCallCounts); + + // Update the analysis manager with each run and intersect the total set + // of preserved analyses so we're ready to iterate. + AM.invalidate(*C, PassPA); + PA.intersect(std::move(PassPA)); + } + + // Note that we don't add any preserved entries here unlike a more normal + // "pass manager" because we only handle invalidation *between* iterations, + // not after the last iteration. + return PA; + } + +private: + PassT Pass; + int MaxIterations; +}; + +/// A function to deduce a function pass type and wrap it in the +/// templated adaptor. +template <typename PassT> +DevirtSCCRepeatedPass<PassT> createDevirtSCCRepeatedPass(PassT Pass, + int MaxIterations) { + return DevirtSCCRepeatedPass<PassT>(std::move(Pass), MaxIterations); +} + +// Out-of-line implementation details for templates below this point. + +template <typename CGSCCPassT> +PreservedAnalyses +ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>::run(Module &M, + ModuleAnalysisManager &AM) { + // Setup the CGSCC analysis manager from its proxy. + CGSCCAnalysisManager &CGAM = + AM.getResult<CGSCCAnalysisManagerModuleProxy>(M).getManager(); + + // Get the call graph for this module. + LazyCallGraph &CG = AM.getResult<LazyCallGraphAnalysis>(M); + + // We keep worklists to allow us to push more work onto the pass manager as + // the passes are run. + SmallPriorityWorklist<LazyCallGraph::RefSCC *, 1> RCWorklist; + SmallPriorityWorklist<LazyCallGraph::SCC *, 1> CWorklist; + + // Keep sets for invalidated SCCs and RefSCCs that should be skipped when + // iterating off the worklists. + SmallPtrSet<LazyCallGraph::RefSCC *, 4> InvalidRefSCCSet; + SmallPtrSet<LazyCallGraph::SCC *, 4> InvalidSCCSet; + + SmallDenseSet<std::pair<LazyCallGraph::Node *, LazyCallGraph::SCC *>, 4> + InlinedInternalEdges; + + CGSCCUpdateResult UR = { + RCWorklist, CWorklist, InvalidRefSCCSet, InvalidSCCSet, + nullptr, nullptr, PreservedAnalyses::all(), InlinedInternalEdges}; + + // Request PassInstrumentation from analysis manager, will use it to run + // instrumenting callbacks for the passes later. + PassInstrumentation PI = AM.getResult<PassInstrumentationAnalysis>(M); + + PreservedAnalyses PA = PreservedAnalyses::all(); + CG.buildRefSCCs(); + for (auto RCI = CG.postorder_ref_scc_begin(), + RCE = CG.postorder_ref_scc_end(); + RCI != RCE;) { + assert(RCWorklist.empty() && + "Should always start with an empty RefSCC worklist"); + // The postorder_ref_sccs range we are walking is lazily constructed, so + // we only push the first one onto the worklist. The worklist allows us + // to capture *new* RefSCCs created during transformations. + // + // We really want to form RefSCCs lazily because that makes them cheaper + // to update as the program is simplified and allows us to have greater + // cache locality as forming a RefSCC touches all the parts of all the + // functions within that RefSCC. + // + // We also eagerly increment the iterator to the next position because + // the CGSCC passes below may delete the current RefSCC. + RCWorklist.insert(&*RCI++); + + do { + LazyCallGraph::RefSCC *RC = RCWorklist.pop_back_val(); + if (InvalidRefSCCSet.count(RC)) { + LLVM_DEBUG(dbgs() << "Skipping an invalid RefSCC...\n"); + continue; + } + + assert(CWorklist.empty() && + "Should always start with an empty SCC worklist"); + + LLVM_DEBUG(dbgs() << "Running an SCC pass across the RefSCC: " << *RC + << "\n"); + + // Push the initial SCCs in reverse post-order as we'll pop off the + // back and so see this in post-order. + for (LazyCallGraph::SCC &C : llvm::reverse(*RC)) + CWorklist.insert(&C); + + do { + LazyCallGraph::SCC *C = CWorklist.pop_back_val(); + // Due to call graph mutations, we may have invalid SCCs or SCCs from + // other RefSCCs in the worklist. The invalid ones are dead and the + // other RefSCCs should be queued above, so we just need to skip both + // scenarios here. + if (InvalidSCCSet.count(C)) { + LLVM_DEBUG(dbgs() << "Skipping an invalid SCC...\n"); + continue; + } + if (&C->getOuterRefSCC() != RC) { + LLVM_DEBUG(dbgs() << "Skipping an SCC that is now part of some other " + "RefSCC...\n"); + continue; + } + + // Ensure we can proxy analysis updates from from the CGSCC analysis + // manager into the Function analysis manager by getting a proxy here. + // FIXME: This seems like a bit of a hack. We should find a cleaner + // or more costructive way to ensure this happens. + (void)CGAM.getResult<FunctionAnalysisManagerCGSCCProxy>(*C, CG); + + // Each time we visit a new SCC pulled off the worklist, + // a transformation of a child SCC may have also modified this parent + // and invalidated analyses. So we invalidate using the update record's + // cross-SCC preserved set. This preserved set is intersected by any + // CGSCC pass that handles invalidation (primarily pass managers) prior + // to marking its SCC as preserved. That lets us track everything that + // might need invalidation across SCCs without excessive invalidations + // on a single SCC. + // + // This essentially allows SCC passes to freely invalidate analyses + // of any ancestor SCC. If this becomes detrimental to successfully + // caching analyses, we could force each SCC pass to manually + // invalidate the analyses for any SCCs other than themselves which + // are mutated. However, that seems to lose the robustness of the + // pass-manager driven invalidation scheme. + // + // FIXME: This is redundant in one case -- the top of the worklist may + // *also* be the same SCC we just ran over (and invalidated for). In + // that case, we'll end up doing a redundant invalidation here as + // a consequence. + CGAM.invalidate(*C, UR.CrossSCCPA); + + do { + // Check that we didn't miss any update scenario. + assert(!InvalidSCCSet.count(C) && "Processing an invalid SCC!"); + assert(C->begin() != C->end() && "Cannot have an empty SCC!"); + assert(&C->getOuterRefSCC() == RC && + "Processing an SCC in a different RefSCC!"); + + UR.UpdatedRC = nullptr; + UR.UpdatedC = nullptr; + + // Check the PassInstrumentation's BeforePass callbacks before + // running the pass, skip its execution completely if asked to + // (callback returns false). + if (!PI.runBeforePass<LazyCallGraph::SCC>(Pass, *C)) + continue; + + PreservedAnalyses PassPA = Pass.run(*C, CGAM, CG, UR); + + if (UR.InvalidatedSCCs.count(C)) + PI.runAfterPassInvalidated<LazyCallGraph::SCC>(Pass); + else + PI.runAfterPass<LazyCallGraph::SCC>(Pass, *C); + + // Update the SCC and RefSCC if necessary. + C = UR.UpdatedC ? UR.UpdatedC : C; + RC = UR.UpdatedRC ? UR.UpdatedRC : RC; + + // If the CGSCC pass wasn't able to provide a valid updated SCC, + // the current SCC may simply need to be skipped if invalid. + if (UR.InvalidatedSCCs.count(C)) { + LLVM_DEBUG(dbgs() << "Skipping invalidated root or island SCC!\n"); + break; + } + // Check that we didn't miss any update scenario. + assert(C->begin() != C->end() && "Cannot have an empty SCC!"); + + // We handle invalidating the CGSCC analysis manager's information + // for the (potentially updated) SCC here. Note that any other SCCs + // whose structure has changed should have been invalidated by + // whatever was updating the call graph. This SCC gets invalidated + // late as it contains the nodes that were actively being + // processed. + CGAM.invalidate(*C, PassPA); + + // Then intersect the preserved set so that invalidation of module + // analyses will eventually occur when the module pass completes. + // Also intersect with the cross-SCC preserved set to capture any + // cross-SCC invalidation. + UR.CrossSCCPA.intersect(PassPA); + PA.intersect(std::move(PassPA)); + + // The pass may have restructured the call graph and refined the + // current SCC and/or RefSCC. We need to update our current SCC and + // RefSCC pointers to follow these. Also, when the current SCC is + // refined, re-run the SCC pass over the newly refined SCC in order + // to observe the most precise SCC model available. This inherently + // cannot cycle excessively as it only happens when we split SCCs + // apart, at most converging on a DAG of single nodes. + // FIXME: If we ever start having RefSCC passes, we'll want to + // iterate there too. + if (UR.UpdatedC) + LLVM_DEBUG(dbgs() + << "Re-running SCC passes after a refinement of the " + "current SCC: " + << *UR.UpdatedC << "\n"); + + // Note that both `C` and `RC` may at this point refer to deleted, + // invalid SCC and RefSCCs respectively. But we will short circuit + // the processing when we check them in the loop above. + } while (UR.UpdatedC); + } while (!CWorklist.empty()); + + // We only need to keep internal inlined edge information within + // a RefSCC, clear it to save on space and let the next time we visit + // any of these functions have a fresh start. + InlinedInternalEdges.clear(); + } while (!RCWorklist.empty()); + } + + // By definition we preserve the call garph, all SCC analyses, and the + // analysis proxies by handling them above and in any nested pass managers. + PA.preserveSet<AllAnalysesOn<LazyCallGraph::SCC>>(); + PA.preserve<LazyCallGraphAnalysis>(); + PA.preserve<CGSCCAnalysisManagerModuleProxy>(); + PA.preserve<FunctionAnalysisManagerModuleProxy>(); + return PA; +} + +// Clear out the debug logging macro. +#undef DEBUG_TYPE + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_CGSCCPASSMANAGER_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/CallGraph.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/CallGraph.h new file mode 100644 index 0000000..7a10183 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/CallGraph.h
@@ -0,0 +1,509 @@ +//===- CallGraph.h - Build a Module's call graph ----------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This file provides interfaces used to build and manipulate a call graph, +/// which is a very useful tool for interprocedural optimization. +/// +/// Every function in a module is represented as a node in the call graph. The +/// callgraph node keeps track of which functions are called by the function +/// corresponding to the node. +/// +/// A call graph may contain nodes where the function that they correspond to +/// is null. These 'external' nodes are used to represent control flow that is +/// not represented (or analyzable) in the module. In particular, this +/// analysis builds one external node such that: +/// 1. All functions in the module without internal linkage will have edges +/// from this external node, indicating that they could be called by +/// functions outside of the module. +/// 2. All functions whose address is used for something more than a direct +/// call, for example being stored into a memory location will also have +/// an edge from this external node. Since they may be called by an +/// unknown caller later, they must be tracked as such. +/// +/// There is a second external node added for calls that leave this module. +/// Functions have a call edge to the external node iff: +/// 1. The function is external, reflecting the fact that they could call +/// anything without internal linkage or that has its address taken. +/// 2. The function contains an indirect function call. +/// +/// As an extension in the future, there may be multiple nodes with a null +/// function. These will be used when we can prove (through pointer analysis) +/// that an indirect call site can call only a specific set of functions. +/// +/// Because of these properties, the CallGraph captures a conservative superset +/// of all of the caller-callee relationships, which is useful for +/// transformations. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CALLGRAPH_H +#define LLVM_ANALYSIS_CALLGRAPH_H + +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/IR/PassManager.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/Pass.h" +#include <cassert> +#include <map> +#include <memory> +#include <utility> +#include <vector> + +namespace llvm { + +class CallGraphNode; +class Module; +class raw_ostream; + +/// The basic data container for the call graph of a \c Module of IR. +/// +/// This class exposes both the interface to the call graph for a module of IR. +/// +/// The core call graph itself can also be updated to reflect changes to the IR. +class CallGraph { + Module &M; + + using FunctionMapTy = + std::map<const Function *, std::unique_ptr<CallGraphNode>>; + + /// A map from \c Function* to \c CallGraphNode*. + FunctionMapTy FunctionMap; + + /// This node has edges to all external functions and those internal + /// functions that have their address taken. + CallGraphNode *ExternalCallingNode; + + /// This node has edges to it from all functions making indirect calls + /// or calling an external function. + std::unique_ptr<CallGraphNode> CallsExternalNode; + + /// Replace the function represented by this node by another. + /// + /// This does not rescan the body of the function, so it is suitable when + /// splicing the body of one function to another while also updating all + /// callers from the old function to the new. + void spliceFunction(const Function *From, const Function *To); + + /// Add a function to the call graph, and link the node to all of the + /// functions that it calls. + void addToCallGraph(Function *F); + +public: + explicit CallGraph(Module &M); + CallGraph(CallGraph &&Arg); + ~CallGraph(); + + void print(raw_ostream &OS) const; + void dump() const; + + using iterator = FunctionMapTy::iterator; + using const_iterator = FunctionMapTy::const_iterator; + + /// Returns the module the call graph corresponds to. + Module &getModule() const { return M; } + + inline iterator begin() { return FunctionMap.begin(); } + inline iterator end() { return FunctionMap.end(); } + inline const_iterator begin() const { return FunctionMap.begin(); } + inline const_iterator end() const { return FunctionMap.end(); } + + /// Returns the call graph node for the provided function. + inline const CallGraphNode *operator[](const Function *F) const { + const_iterator I = FunctionMap.find(F); + assert(I != FunctionMap.end() && "Function not in callgraph!"); + return I->second.get(); + } + + /// Returns the call graph node for the provided function. + inline CallGraphNode *operator[](const Function *F) { + const_iterator I = FunctionMap.find(F); + assert(I != FunctionMap.end() && "Function not in callgraph!"); + return I->second.get(); + } + + /// Returns the \c CallGraphNode which is used to represent + /// undetermined calls into the callgraph. + CallGraphNode *getExternalCallingNode() const { return ExternalCallingNode; } + + CallGraphNode *getCallsExternalNode() const { + return CallsExternalNode.get(); + } + + //===--------------------------------------------------------------------- + // Functions to keep a call graph up to date with a function that has been + // modified. + // + + /// Unlink the function from this module, returning it. + /// + /// Because this removes the function from the module, the call graph node is + /// destroyed. This is only valid if the function does not call any other + /// functions (ie, there are no edges in it's CGN). The easiest way to do + /// this is to dropAllReferences before calling this. + Function *removeFunctionFromModule(CallGraphNode *CGN); + + /// Similar to operator[], but this will insert a new CallGraphNode for + /// \c F if one does not already exist. + CallGraphNode *getOrInsertFunction(const Function *F); +}; + +/// A node in the call graph for a module. +/// +/// Typically represents a function in the call graph. There are also special +/// "null" nodes used to represent theoretical entries in the call graph. +class CallGraphNode { +public: + /// A pair of the calling instruction (a call or invoke) + /// and the call graph node being called. + using CallRecord = std::pair<WeakTrackingVH, CallGraphNode *>; + +public: + using CalledFunctionsVector = std::vector<CallRecord>; + + /// Creates a node for the specified function. + inline CallGraphNode(Function *F) : F(F) {} + + CallGraphNode(const CallGraphNode &) = delete; + CallGraphNode &operator=(const CallGraphNode &) = delete; + + ~CallGraphNode() { + assert(NumReferences == 0 && "Node deleted while references remain"); + } + + using iterator = std::vector<CallRecord>::iterator; + using const_iterator = std::vector<CallRecord>::const_iterator; + + /// Returns the function that this call graph node represents. + Function *getFunction() const { return F; } + + inline iterator begin() { return CalledFunctions.begin(); } + inline iterator end() { return CalledFunctions.end(); } + inline const_iterator begin() const { return CalledFunctions.begin(); } + inline const_iterator end() const { return CalledFunctions.end(); } + inline bool empty() const { return CalledFunctions.empty(); } + inline unsigned size() const { return (unsigned)CalledFunctions.size(); } + + /// Returns the number of other CallGraphNodes in this CallGraph that + /// reference this node in their callee list. + unsigned getNumReferences() const { return NumReferences; } + + /// Returns the i'th called function. + CallGraphNode *operator[](unsigned i) const { + assert(i < CalledFunctions.size() && "Invalid index"); + return CalledFunctions[i].second; + } + + /// Print out this call graph node. + void dump() const; + void print(raw_ostream &OS) const; + + //===--------------------------------------------------------------------- + // Methods to keep a call graph up to date with a function that has been + // modified + // + + /// Removes all edges from this CallGraphNode to any functions it + /// calls. + void removeAllCalledFunctions() { + while (!CalledFunctions.empty()) { + CalledFunctions.back().second->DropRef(); + CalledFunctions.pop_back(); + } + } + + /// Moves all the callee information from N to this node. + void stealCalledFunctionsFrom(CallGraphNode *N) { + assert(CalledFunctions.empty() && + "Cannot steal callsite information if I already have some"); + std::swap(CalledFunctions, N->CalledFunctions); + } + + /// Adds a function to the list of functions called by this one. + void addCalledFunction(CallBase *Call, CallGraphNode *M) { + assert(!Call || !Call->getCalledFunction() || + !Call->getCalledFunction()->isIntrinsic() || + !Intrinsic::isLeaf(Call->getCalledFunction()->getIntrinsicID())); + CalledFunctions.emplace_back(Call, M); + M->AddRef(); + } + + void removeCallEdge(iterator I) { + I->second->DropRef(); + *I = CalledFunctions.back(); + CalledFunctions.pop_back(); + } + + /// Removes the edge in the node for the specified call site. + /// + /// Note that this method takes linear time, so it should be used sparingly. + void removeCallEdgeFor(CallBase &Call); + + /// Removes all call edges from this node to the specified callee + /// function. + /// + /// This takes more time to execute than removeCallEdgeTo, so it should not + /// be used unless necessary. + void removeAnyCallEdgeTo(CallGraphNode *Callee); + + /// Removes one edge associated with a null callsite from this node to + /// the specified callee function. + void removeOneAbstractEdgeTo(CallGraphNode *Callee); + + /// Replaces the edge in the node for the specified call site with a + /// new one. + /// + /// Note that this method takes linear time, so it should be used sparingly. + void replaceCallEdge(CallBase &Call, CallBase &NewCall, + CallGraphNode *NewNode); + +private: + friend class CallGraph; + + Function *F; + + std::vector<CallRecord> CalledFunctions; + + /// The number of times that this CallGraphNode occurs in the + /// CalledFunctions array of this or other CallGraphNodes. + unsigned NumReferences = 0; + + void DropRef() { --NumReferences; } + void AddRef() { ++NumReferences; } + + /// A special function that should only be used by the CallGraph class. + void allReferencesDropped() { NumReferences = 0; } +}; + +/// An analysis pass to compute the \c CallGraph for a \c Module. +/// +/// This class implements the concept of an analysis pass used by the \c +/// ModuleAnalysisManager to run an analysis over a module and cache the +/// resulting data. +class CallGraphAnalysis : public AnalysisInfoMixin<CallGraphAnalysis> { + friend AnalysisInfoMixin<CallGraphAnalysis>; + + static AnalysisKey Key; + +public: + /// A formulaic type to inform clients of the result type. + using Result = CallGraph; + + /// Compute the \c CallGraph for the module \c M. + /// + /// The real work here is done in the \c CallGraph constructor. + CallGraph run(Module &M, ModuleAnalysisManager &) { return CallGraph(M); } +}; + +/// 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, ModuleAnalysisManager &AM); +}; + +/// The \c ModulePass which wraps up a \c CallGraph and the logic to +/// build it. +/// +/// This class exposes both the interface to the call graph container and the +/// module pass which runs over a module of IR and produces the call graph. The +/// call graph interface is entirelly a wrapper around a \c CallGraph object +/// which is stored internally for each module. +class CallGraphWrapperPass : public ModulePass { + std::unique_ptr<CallGraph> G; + +public: + static char ID; // Class identification, replacement for typeinfo + + CallGraphWrapperPass(); + ~CallGraphWrapperPass() override; + + /// The internal \c CallGraph around which the rest of this interface + /// is wrapped. + const CallGraph &getCallGraph() const { return *G; } + CallGraph &getCallGraph() { return *G; } + + using iterator = CallGraph::iterator; + using const_iterator = CallGraph::const_iterator; + + /// Returns the module the call graph corresponds to. + Module &getModule() const { return G->getModule(); } + + inline iterator begin() { return G->begin(); } + inline iterator end() { return G->end(); } + inline const_iterator begin() const { return G->begin(); } + inline const_iterator end() const { return G->end(); } + + /// Returns the call graph node for the provided function. + inline const CallGraphNode *operator[](const Function *F) const { + return (*G)[F]; + } + + /// Returns the call graph node for the provided function. + inline CallGraphNode *operator[](const Function *F) { return (*G)[F]; } + + /// Returns the \c CallGraphNode which is used to represent + /// undetermined calls into the callgraph. + CallGraphNode *getExternalCallingNode() const { + return G->getExternalCallingNode(); + } + + CallGraphNode *getCallsExternalNode() const { + return G->getCallsExternalNode(); + } + + //===--------------------------------------------------------------------- + // Functions to keep a call graph up to date with a function that has been + // modified. + // + + /// Unlink the function from this module, returning it. + /// + /// Because this removes the function from the module, the call graph node is + /// destroyed. This is only valid if the function does not call any other + /// functions (ie, there are no edges in it's CGN). The easiest way to do + /// this is to dropAllReferences before calling this. + Function *removeFunctionFromModule(CallGraphNode *CGN) { + return G->removeFunctionFromModule(CGN); + } + + /// Similar to operator[], but this will insert a new CallGraphNode for + /// \c F if one does not already exist. + CallGraphNode *getOrInsertFunction(const Function *F) { + return G->getOrInsertFunction(F); + } + + //===--------------------------------------------------------------------- + // Implementation of the ModulePass interface needed here. + // + + void getAnalysisUsage(AnalysisUsage &AU) const override; + bool runOnModule(Module &M) override; + void releaseMemory() override; + + void print(raw_ostream &o, const Module *) const override; + void dump() const; +}; + +//===----------------------------------------------------------------------===// +// GraphTraits specializations for call graphs so that they can be treated as +// graphs by the generic graph algorithms. +// + +// Provide graph traits for tranversing call graphs using standard graph +// traversals. +template <> struct GraphTraits<CallGraphNode *> { + using NodeRef = CallGraphNode *; + using CGNPairTy = CallGraphNode::CallRecord; + + static NodeRef getEntryNode(CallGraphNode *CGN) { return CGN; } + static CallGraphNode *CGNGetValue(CGNPairTy P) { return P.second; } + + using ChildIteratorType = + mapped_iterator<CallGraphNode::iterator, decltype(&CGNGetValue)>; + + static ChildIteratorType child_begin(NodeRef N) { + return ChildIteratorType(N->begin(), &CGNGetValue); + } + + static ChildIteratorType child_end(NodeRef N) { + return ChildIteratorType(N->end(), &CGNGetValue); + } +}; + +template <> struct GraphTraits<const CallGraphNode *> { + using NodeRef = const CallGraphNode *; + using CGNPairTy = CallGraphNode::CallRecord; + using EdgeRef = const CallGraphNode::CallRecord &; + + static NodeRef getEntryNode(const CallGraphNode *CGN) { return CGN; } + static const CallGraphNode *CGNGetValue(CGNPairTy P) { return P.second; } + + using ChildIteratorType = + mapped_iterator<CallGraphNode::const_iterator, decltype(&CGNGetValue)>; + using ChildEdgeIteratorType = CallGraphNode::const_iterator; + + static ChildIteratorType child_begin(NodeRef N) { + return ChildIteratorType(N->begin(), &CGNGetValue); + } + + static ChildIteratorType child_end(NodeRef N) { + return ChildIteratorType(N->end(), &CGNGetValue); + } + + static ChildEdgeIteratorType child_edge_begin(NodeRef N) { + return N->begin(); + } + static ChildEdgeIteratorType child_edge_end(NodeRef N) { return N->end(); } + + static NodeRef edge_dest(EdgeRef E) { return E.second; } +}; + +template <> +struct GraphTraits<CallGraph *> : public GraphTraits<CallGraphNode *> { + using PairTy = + std::pair<const Function *const, std::unique_ptr<CallGraphNode>>; + + static NodeRef getEntryNode(CallGraph *CGN) { + return CGN->getExternalCallingNode(); // Start at the external node! + } + + static CallGraphNode *CGGetValuePtr(const PairTy &P) { + return P.second.get(); + } + + // nodes_iterator/begin/end - Allow iteration over all nodes in the graph + using nodes_iterator = + mapped_iterator<CallGraph::iterator, decltype(&CGGetValuePtr)>; + + static nodes_iterator nodes_begin(CallGraph *CG) { + return nodes_iterator(CG->begin(), &CGGetValuePtr); + } + + static nodes_iterator nodes_end(CallGraph *CG) { + return nodes_iterator(CG->end(), &CGGetValuePtr); + } +}; + +template <> +struct GraphTraits<const CallGraph *> : public GraphTraits< + const CallGraphNode *> { + using PairTy = + std::pair<const Function *const, std::unique_ptr<CallGraphNode>>; + + static NodeRef getEntryNode(const CallGraph *CGN) { + return CGN->getExternalCallingNode(); // Start at the external node! + } + + static const CallGraphNode *CGGetValuePtr(const PairTy &P) { + return P.second.get(); + } + + // nodes_iterator/begin/end - Allow iteration over all nodes in the graph + using nodes_iterator = + mapped_iterator<CallGraph::const_iterator, decltype(&CGGetValuePtr)>; + + static nodes_iterator nodes_begin(const CallGraph *CG) { + return nodes_iterator(CG->begin(), &CGGetValuePtr); + } + + static nodes_iterator nodes_end(const CallGraph *CG) { + return nodes_iterator(CG->end(), &CGGetValuePtr); + } +}; + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_CALLGRAPH_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/CallGraphSCCPass.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/CallGraphSCCPass.h new file mode 100644 index 0000000..1b5b7e2 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/CallGraphSCCPass.h
@@ -0,0 +1,136 @@ +//===- CallGraphSCCPass.h - Pass that operates BU on call graph -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the CallGraphSCCPass class, which is used for passes which +// are implemented as bottom-up traversals on the call graph. Because there may +// be cycles in the call graph, passes of this type operate on the call-graph in +// SCC order: that is, they process function bottom-up, except for recursive +// functions, which they process all at once. +// +// These passes are inherently interprocedural, and are required to keep the +// call graph up-to-date if they do anything which could modify it. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CALLGRAPHSCCPASS_H +#define LLVM_ANALYSIS_CALLGRAPHSCCPASS_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Pass.h" +#include <vector> + +namespace llvm { + +class CallGraph; +class CallGraphNode; +class CallGraphSCC; +class PMStack; + +class CallGraphSCCPass : public Pass { +public: + explicit CallGraphSCCPass(char &pid) : Pass(PT_CallGraphSCC, pid) {} + + /// createPrinterPass - Get a pass that prints the Module + /// corresponding to a CallGraph. + Pass *createPrinterPass(raw_ostream &OS, + const std::string &Banner) const override; + + using llvm::Pass::doInitialization; + using llvm::Pass::doFinalization; + + /// doInitialization - This method is called before the SCC's of the program + /// has been processed, allowing the pass to do initialization as necessary. + virtual bool doInitialization(CallGraph &CG) { + return false; + } + + /// runOnSCC - This method should be implemented by the subclass to perform + /// whatever action is necessary for the specified SCC. Note that + /// non-recursive (or only self-recursive) functions will have an SCC size of + /// 1, where recursive portions of the call graph will have SCC size > 1. + /// + /// SCC passes that add or delete functions to the SCC are required to update + /// the SCC list, otherwise stale pointers may be dereferenced. + virtual bool runOnSCC(CallGraphSCC &SCC) = 0; + + /// doFinalization - This method is called after the SCC's of the program has + /// been processed, allowing the pass to do final cleanup as necessary. + virtual bool doFinalization(CallGraph &CG) { + return false; + } + + /// Assign pass manager to manager this pass + void assignPassManager(PMStack &PMS, PassManagerType PMT) override; + + /// Return what kind of Pass Manager can manage this pass. + PassManagerType getPotentialPassManagerType() const override { + return PMT_CallGraphPassManager; + } + + /// getAnalysisUsage - For this class, we declare that we require and preserve + /// the call graph. If the derived class implements this method, it should + /// always explicitly call the implementation here. + 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(CallGraph &cg, void *context) : CG(cg), Context(context) {} + + void initialize(ArrayRef<CallGraphNode *> NewNodes) { + Nodes.assign(NewNodes.begin(), NewNodes.end()); + } + + bool isSingular() const { return Nodes.size() == 1; } + unsigned size() const { return Nodes.size(); } + + /// ReplaceNode - This informs the SCC and the pass manager that the specified + /// Old node has been deleted, and New is to be used in its place. + void ReplaceNode(CallGraphNode *Old, CallGraphNode *New); + + using iterator = std::vector<CallGraphNode *>::const_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 namespace llvm + +#endif // LLVM_ANALYSIS_CALLGRAPHSCCPASS_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/CallPrinter.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/CallPrinter.h new file mode 100644 index 0000000..8d4159f --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/CallPrinter.h
@@ -0,0 +1,26 @@ +//===-- CallPrinter.h - Call graph printer external interface ----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines external functions that can be called to explicitly +// instantiate the call graph printer. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CALLPRINTER_H +#define LLVM_ANALYSIS_CALLPRINTER_H + +namespace llvm { + +class ModulePass; + +ModulePass *createCallGraphViewerPass(); +ModulePass *createCallGraphDOTPrinterPass(); + +} // end namespace llvm + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/CaptureTracking.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/CaptureTracking.h new file mode 100644 index 0000000..29921a5 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/CaptureTracking.h
@@ -0,0 +1,103 @@ +//===----- llvm/Analysis/CaptureTracking.h - Pointer capture ----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains routines that help determine which pointers are captured. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CAPTURETRACKING_H +#define LLVM_ANALYSIS_CAPTURETRACKING_H + +namespace llvm { + + class Value; + class Use; + class DataLayout; + class Instruction; + class DominatorTree; + class OrderedBasicBlock; + + /// The default value for MaxUsesToExplore argument. It's relatively small to + /// keep the cost of analysis reasonable for clients like BasicAliasAnalysis, + /// where the results can't be cached. + /// TODO: we should probably introduce a caching CaptureTracking analysis and + /// use it where possible. The caching version can use much higher limit or + /// don't have this cap at all. + unsigned constexpr DefaultMaxUsesToExplore = 20; + + /// PointerMayBeCaptured - Return true if this pointer value may be captured + /// by the enclosing function (which is required to exist). This routine can + /// be expensive, so consider caching the results. The boolean ReturnCaptures + /// specifies whether returning the value (or part of it) from the function + /// counts as capturing it or not. The boolean StoreCaptures specified + /// whether storing the value (or part of it) into memory anywhere + /// automatically counts as capturing it or not. + /// MaxUsesToExplore specifies how many uses should the analysis explore for + /// one value before giving up due too "too many uses". + bool PointerMayBeCaptured(const Value *V, + bool ReturnCaptures, + bool StoreCaptures, + unsigned MaxUsesToExplore = DefaultMaxUsesToExplore); + + /// PointerMayBeCapturedBefore - Return true if this pointer value may be + /// captured by the enclosing function (which is required to exist). If a + /// DominatorTree is provided, only captures which happen before the given + /// instruction are considered. This routine can be expensive, so consider + /// caching the results. The boolean ReturnCaptures specifies whether + /// returning the value (or part of it) from the function counts as capturing + /// it or not. The boolean StoreCaptures specified whether storing the value + /// (or part of it) into memory anywhere automatically counts as capturing it + /// or not. Captures by the provided instruction are considered if the + /// final parameter is true. An ordered basic block in \p OBB could be used + /// to speed up capture-tracker queries. + /// MaxUsesToExplore specifies how many uses should the analysis explore for + /// one value before giving up due too "too many uses". + bool PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures, + bool StoreCaptures, const Instruction *I, + const DominatorTree *DT, bool IncludeI = false, + OrderedBasicBlock *OBB = nullptr, + unsigned MaxUsesToExplore = DefaultMaxUsesToExplore); + + /// This callback is used in conjunction with PointerMayBeCaptured. In + /// addition to the interface here, you'll need to provide your own getters + /// to see whether anything was captured. + struct CaptureTracker { + virtual ~CaptureTracker(); + + /// tooManyUses - The depth of traversal has breached a limit. There may be + /// capturing instructions that will not be passed into captured(). + virtual void tooManyUses() = 0; + + /// shouldExplore - This is the use of a value derived from the pointer. + /// To prune the search (ie., assume that none of its users could possibly + /// capture) return false. To search it, return true. + /// + /// U->getUser() is always an Instruction. + virtual bool shouldExplore(const Use *U); + + /// captured - Information about the pointer was captured by the user of + /// use U. Return true to stop the traversal or false to continue looking + /// for more capturing instructions. + virtual bool captured(const Use *U) = 0; + + /// isDereferenceableOrNull - Overload to allow clients with additional + /// knowledge about pointer dereferenceability to provide it and thereby + /// avoid conservative responses when a pointer is compared to null. + virtual bool isDereferenceableOrNull(Value *O, const DataLayout &DL); + }; + + /// PointerMayBeCaptured - Visit the value and the values derived from it and + /// find values which appear to be capturing the pointer value. This feeds + /// results into and is controlled by the CaptureTracker object. + /// MaxUsesToExplore specifies how many uses should the analysis explore for + /// one value before giving up due too "too many uses". + void PointerMayBeCaptured(const Value *V, CaptureTracker *Tracker, + unsigned MaxUsesToExplore = DefaultMaxUsesToExplore); +} // end namespace llvm + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/CmpInstAnalysis.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/CmpInstAnalysis.h new file mode 100644 index 0000000..3d34cd1 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/CmpInstAnalysis.h
@@ -0,0 +1,70 @@ +//===-- CmpInstAnalysis.h - Utils to help fold compare insts ----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file holds routines to help analyse compare instructions +// and fold them into constants or other compare instructions +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CMPINSTANALYSIS_H +#define LLVM_ANALYSIS_CMPINSTANALYSIS_H + +#include "llvm/IR/InstrTypes.h" + +namespace llvm { + class ICmpInst; + class Value; + + /// Encode a icmp predicate into a three bit mask. These bits are carefully + /// arranged to allow folding of expressions such as: + /// + /// (A < B) | (A > B) --> (A != B) + /// + /// Note that this is only valid if the first and second predicates have the + /// same sign. It is illegal to do: (A u< B) | (A s> B) + /// + /// Three bits are used to represent the condition, as follows: + /// 0 A > B + /// 1 A == B + /// 2 A < B + /// + /// <=> Value Definition + /// 000 0 Always false + /// 001 1 A > B + /// 010 2 A == B + /// 011 3 A >= B + /// 100 4 A < B + /// 101 5 A != B + /// 110 6 A <= B + /// 111 7 Always true + /// + unsigned getICmpCode(const ICmpInst *ICI, bool InvertPred = false); + + /// This is the complement of getICmpCode. It turns a predicate code into + /// either a constant true or false or the predicate for a new ICmp. + /// The sign is passed in to determine which kind of predicate to use in the + /// new ICmp instruction. + /// Non-NULL return value will be a true or false constant. + /// NULL return means a new ICmp is needed. The predicate is output in Pred. + Constant *getPredForICmpCode(unsigned Code, bool Sign, Type *OpTy, + CmpInst::Predicate &Pred); + + /// Return true if both predicates match sign or if at least one of them is an + /// equality comparison (which is signless). + bool predicatesFoldable(CmpInst::Predicate P1, CmpInst::Predicate P2); + + /// Decompose an icmp into the form ((X & Mask) pred 0) if possible. The + /// returned predicate is either == or !=. Returns false if decomposition + /// fails. + bool decomposeBitTestICmp(Value *LHS, Value *RHS, CmpInst::Predicate &Pred, + Value *&X, APInt &Mask, + bool LookThroughTrunc = true); + +} // end namespace llvm + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/CodeMetrics.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/CodeMetrics.h new file mode 100644 index 0000000..1482b66 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/CodeMetrics.h
@@ -0,0 +1,95 @@ +//===- CodeMetrics.h - Code cost measurements -------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements various weight measurements for code, helping +// the Inliner and other passes decide whether to duplicate its contents. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CODEMETRICS_H +#define LLVM_ANALYSIS_CODEMETRICS_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" + +namespace llvm { +class AssumptionCache; +class BasicBlock; +class Loop; +class Function; +class Instruction; +class DataLayout; +class TargetTransformInfo; +class Value; + +/// Utility to calculate the size and a few similar metrics for a set +/// of basic blocks. +struct CodeMetrics { + /// True if this function contains a call to setjmp or other functions + /// with attribute "returns twice" without having the attribute itself. + bool exposesReturnsTwice = false; + + /// True if this function calls itself. + bool isRecursive = false; + + /// 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 = false; + + /// True if this function contains a call to a convergent function. + bool convergent = false; + + /// True if this function calls alloca (in the C sense). + bool usesDynamicAlloca = false; + + /// Number of instructions in the analyzed blocks. + unsigned NumInsts = false; + + /// Number of analyzed blocks. + unsigned NumBlocks = false; + + /// Keeps track of basic block code size estimates. + DenseMap<const BasicBlock *, unsigned> NumBBInsts; + + /// Keep track of the number of calls to 'big' functions. + unsigned NumCalls = false; + + /// 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 = 0; + + /// How many instructions produce vector values. + /// + /// The inliner is more aggressive with inlining vector kernels. + unsigned NumVectorInsts = 0; + + /// How many 'ret' instructions the blocks contain. + unsigned NumRets = 0; + + /// Add information about a block to the current state. + void analyzeBasicBlock(const BasicBlock *BB, const TargetTransformInfo &TTI, + const SmallPtrSetImpl<const Value*> &EphValues); + + /// Collect a loop's ephemeral values (those used only by an assume + /// or similar intrinsics in the loop). + static void collectEphemeralValues(const Loop *L, AssumptionCache *AC, + SmallPtrSetImpl<const Value *> &EphValues); + + /// Collect a functions's ephemeral values (those used only by an + /// assume or similar intrinsics in the function). + static void collectEphemeralValues(const Function *L, AssumptionCache *AC, + SmallPtrSetImpl<const Value *> &EphValues); +}; + +} + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/ConstantFolding.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/ConstantFolding.h new file mode 100644 index 0000000..2385b6f --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/ConstantFolding.h
@@ -0,0 +1,165 @@ +//===-- ConstantFolding.h - Fold instructions into constants ----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file declares routines for folding instructions into constants when all +// operands are constants, for example "sub i32 1, 0" -> "1". +// +// Also, to supplement the basic VMCore ConstantExpr simplifications, +// this file declares some additional folding routines that can make use of +// DataLayout information. These functions cannot go in VMCore due to library +// dependency issues. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CONSTANTFOLDING_H +#define LLVM_ANALYSIS_CONSTANTFOLDING_H + +namespace llvm { +class APInt; +template <typename T> class ArrayRef; +class CallBase; +class Constant; +class ConstantExpr; +class ConstantVector; +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); + +/// ConstantFoldConstant - Attempt to fold the constant using the +/// specified DataLayout. +/// If successful, the constant result is returned, if not, null is returned. +Constant *ConstantFoldConstant(const Constant *C, 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. +/// +Constant *ConstantFoldInstOperands(Instruction *I, 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); + +/// Attempt to constant fold a unary operation with the specified +/// operand. If it fails, it returns a constant expression of the specified +/// operands. +Constant *ConstantFoldUnaryOpOperand(unsigned Opcode, Constant *Op, + const DataLayout &DL); + +/// 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); + +/// Attempt to constant fold a select instruction with the specified +/// operands. The constant result is returned if successful; if not, null is +/// returned. +Constant *ConstantFoldSelectInstruction(Constant *Cond, Constant *V1, + Constant *V2); + +/// 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 +/// returned if successful; if not, null is returned. +Constant *ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val, + ArrayRef<unsigned> Idxs); + +/// Attempt to constant fold an extractvalue instruction with the +/// specified operands and indices. The constant result is returned if +/// successful; if not, null is returned. +Constant *ConstantFoldExtractValueInstruction(Constant *Agg, + ArrayRef<unsigned> Idxs); + +/// Attempt to constant fold an insertelement instruction with the +/// specified operands and indices. The constant result is returned if +/// successful; if not, null is returned. +Constant *ConstantFoldInsertElementInstruction(Constant *Val, + Constant *Elt, + Constant *Idx); + +/// Attempt to constant fold an extractelement instruction with the +/// specified operands and indices. The constant result is returned if +/// successful; if not, null is returned. +Constant *ConstantFoldExtractElementInstruction(Constant *Val, Constant *Idx); + +/// Attempt to constant fold a shufflevector instruction with the +/// specified operands and indices. The constant result is returned if +/// successful; if not, null is returned. +Constant *ConstantFoldShuffleVectorInstruction(Constant *V1, Constant *V2, + Constant *Mask); + +/// 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, Type *Ty, const DataLayout &DL); + +/// ConstantFoldLoadThroughGEPConstantExpr - Given a constant and a +/// getelementptr constantexpr, return the constant value being addressed by the +/// constant expression, or null if something is funny and we can't decide. +Constant *ConstantFoldLoadThroughGEPConstantExpr(Constant *C, ConstantExpr *CE); + +/// ConstantFoldLoadThroughGEPIndices - Given a constant and getelementptr +/// indices (with an *implied* zero pointer index that is not in the list), +/// 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); + +/// canConstantFoldCallTo - Return true if its even possible to fold a call to +/// the specified function. +bool canConstantFoldCallTo(const CallBase *Call, const Function *F); + +/// ConstantFoldCall - Attempt to constant fold a call to the specified function +/// with the specified arguments, returning null if unsuccessful. +Constant *ConstantFoldCall(const CallBase *Call, Function *F, + ArrayRef<Constant *> Operands, + const TargetLibraryInfo *TLI = nullptr); + +/// ConstantFoldLoadThroughBitcast - try to cast constant to destination type +/// returning null if unsuccessful. Can cast pointer to pointer or pointer to +/// integer and vice versa if their sizes are equal. +Constant *ConstantFoldLoadThroughBitcast(Constant *C, Type *DestTy, + const DataLayout &DL); + +/// Check whether the given call has no side-effects. +/// Specifically checks for math routimes which sometimes set errno. +bool isMathLibCallNoop(const CallBase *Call, const TargetLibraryInfo *TLI); +} + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/DDG.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/DDG.h new file mode 100644 index 0000000..22df60e --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/DDG.h
@@ -0,0 +1,515 @@ +//===- llvm/Analysis/DDG.h --------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the Data-Dependence Graph (DDG). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_DDG_H +#define LLVM_ANALYSIS_DDG_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DirectedGraph.h" +#include "llvm/Analysis/DependenceAnalysis.h" +#include "llvm/Analysis/DependenceGraphBuilder.h" +#include "llvm/Analysis/LoopAnalysisManager.h" +#include "llvm/IR/Instructions.h" + +namespace llvm { +class DDGNode; +class DDGEdge; +using DDGNodeBase = DGNode<DDGNode, DDGEdge>; +using DDGEdgeBase = DGEdge<DDGNode, DDGEdge>; +using DDGBase = DirectedGraph<DDGNode, DDGEdge>; +class LPMUpdater; + +/// Data Dependence Graph Node +/// The graph can represent the following types of nodes: +/// 1. Single instruction node containing just one instruction. +/// 2. Multiple instruction node where two or more instructions from +/// the same basic block are merged into one node. +/// 3. Pi-block node which is a group of other DDG nodes that are part of a +/// strongly-connected component of the graph. +/// A pi-block node contains more than one single or multiple instruction +/// nodes. The root node cannot be part of a pi-block. +/// 4. Root node is a special node that connects to all components such that +/// there is always a path from it to any node in the graph. +class DDGNode : public DDGNodeBase { +public: + using InstructionListType = SmallVectorImpl<Instruction *>; + + enum class NodeKind { + Unknown, + SingleInstruction, + MultiInstruction, + PiBlock, + Root, + }; + + DDGNode() = delete; + DDGNode(const NodeKind K) : DDGNodeBase(), Kind(K) {} + DDGNode(const DDGNode &N) : DDGNodeBase(N), Kind(N.Kind) {} + DDGNode(DDGNode &&N) : DDGNodeBase(std::move(N)), Kind(N.Kind) {} + virtual ~DDGNode() = 0; + + DDGNode &operator=(const DDGNode &N) { + DGNode::operator=(N); + Kind = N.Kind; + return *this; + } + + DDGNode &operator=(DDGNode &&N) { + DGNode::operator=(std::move(N)); + Kind = N.Kind; + return *this; + } + + /// Getter for the kind of this node. + NodeKind getKind() const { return Kind; } + + /// Collect a list of instructions, in \p IList, for which predicate \p Pred + /// evaluates to true when iterating over instructions of this node. Return + /// true if at least one instruction was collected, and false otherwise. + bool collectInstructions(llvm::function_ref<bool(Instruction *)> const &Pred, + InstructionListType &IList) const; + +protected: + /// Setter for the kind of this node. + void setKind(NodeKind K) { Kind = K; } + +private: + NodeKind Kind; +}; + +/// Subclass of DDGNode representing the root node of the graph. +/// There should only be one such node in a given graph. +class RootDDGNode : public DDGNode { +public: + RootDDGNode() : DDGNode(NodeKind::Root) {} + RootDDGNode(const RootDDGNode &N) = delete; + RootDDGNode(RootDDGNode &&N) : DDGNode(std::move(N)) {} + ~RootDDGNode() {} + + /// Define classof to be able to use isa<>, cast<>, dyn_cast<>, etc. + static bool classof(const DDGNode *N) { + return N->getKind() == NodeKind::Root; + } + static bool classof(const RootDDGNode *N) { return true; } +}; + +/// Subclass of DDGNode representing single or multi-instruction nodes. +class SimpleDDGNode : public DDGNode { +public: + SimpleDDGNode() = delete; + SimpleDDGNode(Instruction &I); + SimpleDDGNode(const SimpleDDGNode &N); + SimpleDDGNode(SimpleDDGNode &&N); + ~SimpleDDGNode(); + + SimpleDDGNode &operator=(const SimpleDDGNode &N) { + DDGNode::operator=(N); + InstList = N.InstList; + return *this; + } + + SimpleDDGNode &operator=(SimpleDDGNode &&N) { + DDGNode::operator=(std::move(N)); + InstList = std::move(N.InstList); + return *this; + } + + /// Get the list of instructions in this node. + const InstructionListType &getInstructions() const { + assert(!InstList.empty() && "Instruction List is empty."); + return InstList; + } + InstructionListType &getInstructions() { + return const_cast<InstructionListType &>( + static_cast<const SimpleDDGNode *>(this)->getInstructions()); + } + + /// Get the first/last instruction in the node. + Instruction *getFirstInstruction() const { return getInstructions().front(); } + Instruction *getLastInstruction() const { return getInstructions().back(); } + + /// Define classof to be able to use isa<>, cast<>, dyn_cast<>, etc. + static bool classof(const DDGNode *N) { + return N->getKind() == NodeKind::SingleInstruction || + N->getKind() == NodeKind::MultiInstruction; + } + static bool classof(const SimpleDDGNode *N) { return true; } + +private: + /// Append the list of instructions in \p Input to this node. + void appendInstructions(const InstructionListType &Input) { + setKind((InstList.size() == 0 && Input.size() == 1) + ? NodeKind::SingleInstruction + : NodeKind::MultiInstruction); + InstList.insert(InstList.end(), Input.begin(), Input.end()); + } + void appendInstructions(const SimpleDDGNode &Input) { + appendInstructions(Input.getInstructions()); + } + + /// List of instructions associated with a single or multi-instruction node. + SmallVector<Instruction *, 2> InstList; +}; + +/// Subclass of DDGNode representing a pi-block. A pi-block represents a group +/// of DDG nodes that are part of a strongly-connected component of the graph. +/// Replacing all the SCCs with pi-blocks results in an acyclic representation +/// of the DDG. For example if we have: +/// {a -> b}, {b -> c, d}, {c -> a} +/// the cycle a -> b -> c -> a is abstracted into a pi-block "p" as follows: +/// {p -> d} with "p" containing: {a -> b}, {b -> c}, {c -> a} +class PiBlockDDGNode : public DDGNode { +public: + using PiNodeList = SmallVector<DDGNode *, 4>; + + PiBlockDDGNode() = delete; + PiBlockDDGNode(const PiNodeList &List); + PiBlockDDGNode(const PiBlockDDGNode &N); + PiBlockDDGNode(PiBlockDDGNode &&N); + ~PiBlockDDGNode(); + + PiBlockDDGNode &operator=(const PiBlockDDGNode &N) { + DDGNode::operator=(N); + NodeList = N.NodeList; + return *this; + } + + PiBlockDDGNode &operator=(PiBlockDDGNode &&N) { + DDGNode::operator=(std::move(N)); + NodeList = std::move(N.NodeList); + return *this; + } + + /// Get the list of nodes in this pi-block. + const PiNodeList &getNodes() const { + assert(!NodeList.empty() && "Node list is empty."); + return NodeList; + } + PiNodeList &getNodes() { + return const_cast<PiNodeList &>( + static_cast<const PiBlockDDGNode *>(this)->getNodes()); + } + + /// Define classof to be able to use isa<>, cast<>, dyn_cast<>, etc. + static bool classof(const DDGNode *N) { + return N->getKind() == NodeKind::PiBlock; + } + +private: + /// List of nodes in this pi-block. + PiNodeList NodeList; +}; + +/// Data Dependency Graph Edge. +/// An edge in the DDG can represent a def-use relationship or +/// a memory dependence based on the result of DependenceAnalysis. +/// A rooted edge connects the root node to one of the components +/// of the graph. +class DDGEdge : public DDGEdgeBase { +public: + /// The kind of edge in the DDG + enum class EdgeKind { + Unknown, + RegisterDefUse, + MemoryDependence, + Rooted, + Last = Rooted // Must be equal to the largest enum value. + }; + + explicit DDGEdge(DDGNode &N) = delete; + DDGEdge(DDGNode &N, EdgeKind K) : DDGEdgeBase(N), Kind(K) {} + DDGEdge(const DDGEdge &E) : DDGEdgeBase(E), Kind(E.getKind()) {} + DDGEdge(DDGEdge &&E) : DDGEdgeBase(std::move(E)), Kind(E.Kind) {} + DDGEdge &operator=(const DDGEdge &E) { + DDGEdgeBase::operator=(E); + Kind = E.Kind; + return *this; + } + + DDGEdge &operator=(DDGEdge &&E) { + DDGEdgeBase::operator=(std::move(E)); + Kind = E.Kind; + return *this; + } + + /// Get the edge kind + EdgeKind getKind() const { return Kind; }; + + /// Return true if this is a def-use edge, and false otherwise. + bool isDefUse() const { return Kind == EdgeKind::RegisterDefUse; } + + /// Return true if this is a memory dependence edge, and false otherwise. + bool isMemoryDependence() const { return Kind == EdgeKind::MemoryDependence; } + + /// Return true if this is an edge stemming from the root node, and false + /// otherwise. + bool isRooted() const { return Kind == EdgeKind::Rooted; } + +private: + EdgeKind Kind; +}; + +/// Encapsulate some common data and functionality needed for different +/// variations of data dependence graphs. +template <typename NodeType> class DependenceGraphInfo { +public: + using DependenceList = SmallVector<std::unique_ptr<Dependence>, 1>; + + DependenceGraphInfo() = delete; + DependenceGraphInfo(const DependenceGraphInfo &G) = delete; + DependenceGraphInfo(const std::string &N, const DependenceInfo &DepInfo) + : Name(N), DI(DepInfo), Root(nullptr) {} + DependenceGraphInfo(DependenceGraphInfo &&G) + : Name(std::move(G.Name)), DI(std::move(G.DI)), Root(G.Root) {} + virtual ~DependenceGraphInfo() {} + + /// Return the label that is used to name this graph. + const StringRef getName() const { return Name; } + + /// Return the root node of the graph. + NodeType &getRoot() const { + assert(Root && "Root node is not available yet. Graph construction may " + "still be in progress\n"); + return *Root; + } + +protected: + // Name of the graph. + std::string Name; + + // Store a copy of DependenceInfo in the graph, so that individual memory + // dependencies don't need to be stored. Instead when the dependence is + // queried it is recomputed using @DI. + const DependenceInfo DI; + + // A special node in the graph that has an edge to every connected component of + // the graph, to ensure all nodes are reachable in a graph walk. + NodeType *Root = nullptr; +}; + +using DDGInfo = DependenceGraphInfo<DDGNode>; + +/// Data Dependency Graph +class DataDependenceGraph : public DDGBase, public DDGInfo { + friend AbstractDependenceGraphBuilder<DataDependenceGraph>; + friend class DDGBuilder; + +public: + using NodeType = DDGNode; + using EdgeType = DDGEdge; + + DataDependenceGraph() = delete; + DataDependenceGraph(const DataDependenceGraph &G) = delete; + DataDependenceGraph(DataDependenceGraph &&G) + : DDGBase(std::move(G)), DDGInfo(std::move(G)) {} + DataDependenceGraph(Function &F, DependenceInfo &DI); + DataDependenceGraph(Loop &L, LoopInfo &LI, DependenceInfo &DI); + ~DataDependenceGraph(); + + /// If node \p N belongs to a pi-block return a pointer to the pi-block, + /// otherwise return null. + const PiBlockDDGNode *getPiBlock(const NodeType &N) const; + +protected: + /// Add node \p N to the graph, if it's not added yet, and keep track of the + /// root node as well as pi-blocks and their members. Return true if node is + /// successfully added. + bool addNode(NodeType &N); + +private: + using PiBlockMapType = DenseMap<const NodeType *, const PiBlockDDGNode *>; + + /// Mapping from graph nodes to their containing pi-blocks. If a node is not + /// part of a pi-block, it will not appear in this map. + PiBlockMapType PiBlockMap; +}; + +/// Concrete implementation of a pure data dependence graph builder. This class +/// provides custom implementation for the pure-virtual functions used in the +/// generic dependence graph build algorithm. +/// +/// For information about time complexity of the build algorithm see the +/// comments near the declaration of AbstractDependenceGraphBuilder. +class DDGBuilder : public AbstractDependenceGraphBuilder<DataDependenceGraph> { +public: + DDGBuilder(DataDependenceGraph &G, DependenceInfo &D, + const BasicBlockListType &BBs) + : AbstractDependenceGraphBuilder(G, D, BBs) {} + DDGNode &createRootNode() final override { + auto *RN = new RootDDGNode(); + assert(RN && "Failed to allocate memory for DDG root node."); + Graph.addNode(*RN); + return *RN; + } + DDGNode &createFineGrainedNode(Instruction &I) final override { + auto *SN = new SimpleDDGNode(I); + assert(SN && "Failed to allocate memory for simple DDG node."); + Graph.addNode(*SN); + return *SN; + } + DDGNode &createPiBlock(const NodeListType &L) final override { + auto *Pi = new PiBlockDDGNode(L); + assert(Pi && "Failed to allocate memory for pi-block node."); + Graph.addNode(*Pi); + return *Pi; + } + DDGEdge &createDefUseEdge(DDGNode &Src, DDGNode &Tgt) final override { + auto *E = new DDGEdge(Tgt, DDGEdge::EdgeKind::RegisterDefUse); + assert(E && "Failed to allocate memory for edge"); + Graph.connect(Src, Tgt, *E); + return *E; + } + DDGEdge &createMemoryEdge(DDGNode &Src, DDGNode &Tgt) final override { + auto *E = new DDGEdge(Tgt, DDGEdge::EdgeKind::MemoryDependence); + assert(E && "Failed to allocate memory for edge"); + Graph.connect(Src, Tgt, *E); + return *E; + } + DDGEdge &createRootedEdge(DDGNode &Src, DDGNode &Tgt) final override { + auto *E = new DDGEdge(Tgt, DDGEdge::EdgeKind::Rooted); + assert(E && "Failed to allocate memory for edge"); + assert(isa<RootDDGNode>(Src) && "Expected root node"); + Graph.connect(Src, Tgt, *E); + return *E; + } + + const NodeListType &getNodesInPiBlock(const DDGNode &N) final override { + auto *PiNode = dyn_cast<const PiBlockDDGNode>(&N); + assert(PiNode && "Expected a pi-block node."); + return PiNode->getNodes(); + } + + bool shouldCreatePiBlocks() const final override; +}; + +raw_ostream &operator<<(raw_ostream &OS, const DDGNode &N); +raw_ostream &operator<<(raw_ostream &OS, const DDGNode::NodeKind K); +raw_ostream &operator<<(raw_ostream &OS, const DDGEdge &E); +raw_ostream &operator<<(raw_ostream &OS, const DDGEdge::EdgeKind K); +raw_ostream &operator<<(raw_ostream &OS, const DataDependenceGraph &G); + +//===--------------------------------------------------------------------===// +// DDG Analysis Passes +//===--------------------------------------------------------------------===// + +/// Analysis pass that builds the DDG for a loop. +class DDGAnalysis : public AnalysisInfoMixin<DDGAnalysis> { +public: + using Result = std::unique_ptr<DataDependenceGraph>; + Result run(Loop &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR); + +private: + friend AnalysisInfoMixin<DDGAnalysis>; + static AnalysisKey Key; +}; + +/// Textual printer pass for the DDG of a loop. +class DDGAnalysisPrinterPass : public PassInfoMixin<DDGAnalysisPrinterPass> { +public: + explicit DDGAnalysisPrinterPass(raw_ostream &OS) : OS(OS) {} + PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, + LoopStandardAnalysisResults &AR, LPMUpdater &U); + +private: + raw_ostream &OS; +}; + +//===--------------------------------------------------------------------===// +// GraphTraits specializations for the DDG +//===--------------------------------------------------------------------===// + +/// non-const versions of the grapth trait specializations for DDG +template <> struct GraphTraits<DDGNode *> { + using NodeRef = DDGNode *; + + static DDGNode *DDGGetTargetNode(DGEdge<DDGNode, DDGEdge> *P) { + return &P->getTargetNode(); + } + + // Provide a mapped iterator so that the GraphTrait-based implementations can + // find the target nodes without having to explicitly go through the edges. + using ChildIteratorType = + mapped_iterator<DDGNode::iterator, decltype(&DDGGetTargetNode)>; + using ChildEdgeIteratorType = DDGNode::iterator; + + static NodeRef getEntryNode(NodeRef N) { return N; } + static ChildIteratorType child_begin(NodeRef N) { + return ChildIteratorType(N->begin(), &DDGGetTargetNode); + } + static ChildIteratorType child_end(NodeRef N) { + return ChildIteratorType(N->end(), &DDGGetTargetNode); + } + + static ChildEdgeIteratorType child_edge_begin(NodeRef N) { + return N->begin(); + } + static ChildEdgeIteratorType child_edge_end(NodeRef N) { return N->end(); } +}; + +template <> +struct GraphTraits<DataDependenceGraph *> : public GraphTraits<DDGNode *> { + using nodes_iterator = DataDependenceGraph::iterator; + static NodeRef getEntryNode(DataDependenceGraph *DG) { + return &DG->getRoot(); + } + static nodes_iterator nodes_begin(DataDependenceGraph *DG) { + return DG->begin(); + } + static nodes_iterator nodes_end(DataDependenceGraph *DG) { return DG->end(); } +}; + +/// const versions of the grapth trait specializations for DDG +template <> struct GraphTraits<const DDGNode *> { + using NodeRef = const DDGNode *; + + static const DDGNode *DDGGetTargetNode(const DGEdge<DDGNode, DDGEdge> *P) { + return &P->getTargetNode(); + } + + // Provide a mapped iterator so that the GraphTrait-based implementations can + // find the target nodes without having to explicitly go through the edges. + using ChildIteratorType = + mapped_iterator<DDGNode::const_iterator, decltype(&DDGGetTargetNode)>; + using ChildEdgeIteratorType = DDGNode::const_iterator; + + static NodeRef getEntryNode(NodeRef N) { return N; } + static ChildIteratorType child_begin(NodeRef N) { + return ChildIteratorType(N->begin(), &DDGGetTargetNode); + } + static ChildIteratorType child_end(NodeRef N) { + return ChildIteratorType(N->end(), &DDGGetTargetNode); + } + + static ChildEdgeIteratorType child_edge_begin(NodeRef N) { + return N->begin(); + } + static ChildEdgeIteratorType child_edge_end(NodeRef N) { return N->end(); } +}; + +template <> +struct GraphTraits<const DataDependenceGraph *> + : public GraphTraits<const DDGNode *> { + using nodes_iterator = DataDependenceGraph::const_iterator; + static NodeRef getEntryNode(const DataDependenceGraph *DG) { + return &DG->getRoot(); + } + static nodes_iterator nodes_begin(const DataDependenceGraph *DG) { + return DG->begin(); + } + static nodes_iterator nodes_end(const DataDependenceGraph *DG) { + return DG->end(); + } +}; + +} // namespace llvm + +#endif // LLVM_ANALYSIS_DDG_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/DOTGraphTraitsPass.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/DOTGraphTraitsPass.h new file mode 100644 index 0000000..c9e8df5 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/DOTGraphTraitsPass.h
@@ -0,0 +1,188 @@ +//===-- DOTGraphTraitsPass.h - Print/View dotty graphs-----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Templates to create dotty viewer and printer passes for GraphTraits graphs. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_DOTGRAPHTRAITSPASS_H +#define LLVM_ANALYSIS_DOTGRAPHTRAITSPASS_H + +#include "llvm/Analysis/CFGPrinter.h" +#include "llvm/Pass.h" +#include "llvm/Support/FileSystem.h" + +namespace llvm { + +/// Default traits class for extracting a graph from an analysis pass. +/// +/// This assumes that 'GraphT' is 'AnalysisT *' and so just passes it through. +template <typename AnalysisT, typename GraphT = AnalysisT *> +struct DefaultAnalysisGraphTraits { + static GraphT getGraph(AnalysisT *A) { return A; } +}; + +template < + typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *, + typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT, GraphT> > +class DOTGraphTraitsViewer : public FunctionPass { +public: + DOTGraphTraitsViewer(StringRef GraphName, char &ID) + : FunctionPass(ID), Name(GraphName) {} + + /// Return true if this function should be processed. + /// + /// An implementation of this class my override this function to indicate that + /// only certain functions should be viewed. + /// + /// @param Analysis The current analysis result for this function. + virtual bool processFunction(Function &F, AnalysisT &Analysis) { + return true; + } + + bool runOnFunction(Function &F) override { + auto &Analysis = getAnalysis<AnalysisT>(); + + if (!processFunction(F, Analysis)) + return false; + + GraphT Graph = AnalysisGraphTraitsT::getGraph(&Analysis); + std::string GraphName = DOTGraphTraits<GraphT>::getGraphName(Graph); + std::string Title = GraphName + " for '" + F.getName().str() + "' function"; + + ViewGraph(Graph, Name, IsSimple, Title); + + return false; + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + AU.addRequired<AnalysisT>(); + } + +private: + std::string Name; +}; + +template < + typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *, + typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT, GraphT> > +class DOTGraphTraitsPrinter : public FunctionPass { +public: + DOTGraphTraitsPrinter(StringRef GraphName, char &ID) + : FunctionPass(ID), Name(GraphName) {} + + /// Return true if this function should be processed. + /// + /// An implementation of this class my override this function to indicate that + /// only certain functions should be printed. + /// + /// @param Analysis The current analysis result for this function. + virtual bool processFunction(Function &F, AnalysisT &Analysis) { + return true; + } + + bool runOnFunction(Function &F) override { + auto &Analysis = getAnalysis<AnalysisT>(); + + if (!processFunction(F, Analysis)) + return false; + + GraphT Graph = AnalysisGraphTraitsT::getGraph(&Analysis); + std::string Filename = Name + "." + F.getName().str() + ".dot"; + std::error_code EC; + + errs() << "Writing '" << Filename << "'..."; + + raw_fd_ostream File(Filename, EC, sys::fs::OF_Text); + std::string GraphName = DOTGraphTraits<GraphT>::getGraphName(Graph); + std::string Title = GraphName + " for '" + F.getName().str() + "' function"; + + if (!EC) + WriteGraph(File, Graph, IsSimple, Title); + else + errs() << " error opening file for writing!"; + errs() << "\n"; + + return false; + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + AU.addRequired<AnalysisT>(); + } + +private: + std::string Name; +}; + +template < + typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *, + typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT, GraphT> > +class DOTGraphTraitsModuleViewer : public ModulePass { +public: + DOTGraphTraitsModuleViewer(StringRef GraphName, char &ID) + : ModulePass(ID), Name(GraphName) {} + + bool runOnModule(Module &M) override { + GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>()); + std::string Title = DOTGraphTraits<GraphT>::getGraphName(Graph); + + ViewGraph(Graph, Name, IsSimple, Title); + + return false; + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + AU.addRequired<AnalysisT>(); + } + +private: + std::string Name; +}; + +template < + typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *, + typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT, GraphT> > +class DOTGraphTraitsModulePrinter : public ModulePass { +public: + DOTGraphTraitsModulePrinter(StringRef GraphName, char &ID) + : ModulePass(ID), Name(GraphName) {} + + bool runOnModule(Module &M) override { + GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>()); + std::string Filename = Name + ".dot"; + std::error_code EC; + + errs() << "Writing '" << Filename << "'..."; + + raw_fd_ostream File(Filename, EC, sys::fs::OF_Text); + std::string Title = DOTGraphTraits<GraphT>::getGraphName(Graph); + + if (!EC) + WriteGraph(File, Graph, IsSimple, Title); + else + errs() << " error opening file for writing!"; + errs() << "\n"; + + return false; + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + AU.addRequired<AnalysisT>(); + } + +private: + std::string Name; +}; + +} // end namespace llvm + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/DemandedBits.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/DemandedBits.h new file mode 100644 index 0000000..04db3eb --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/DemandedBits.h
@@ -0,0 +1,135 @@ +//===- llvm/Analysis/DemandedBits.h - Determine demanded bits ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This pass implements a demanded bits analysis. A demanded bit is one that +// contributes to a result; bits that are not demanded can be either zero or +// one without affecting control or data flow. For example in this sequence: +// +// %1 = add i32 %x, %y +// %2 = trunc i32 %1 to i16 +// +// Only the lowest 16 bits of %1 are demanded; the rest are removed by the +// trunc. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_DEMANDED_BITS_H +#define LLVM_ANALYSIS_DEMANDED_BITS_H + +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Pass.h" + +namespace llvm { + +class AssumptionCache; +class DominatorTree; +class Function; +class Instruction; +struct KnownBits; +class raw_ostream; + +class DemandedBits { +public: + DemandedBits(Function &F, AssumptionCache &AC, DominatorTree &DT) : + F(F), AC(AC), DT(DT) {} + + /// Return the bits demanded from instruction I. + /// + /// For vector instructions individual vector elements are not distinguished: + /// A bit is demanded if it is demanded for any of the vector elements. The + /// size of the return value corresponds to the type size in bits of the + /// scalar type. + /// + /// Instructions that do not have integer or vector of integer type are + /// accepted, but will always produce a mask with all bits set. + APInt getDemandedBits(Instruction *I); + + /// Return true if, during analysis, I could not be reached. + bool isInstructionDead(Instruction *I); + + /// Return whether this use is dead by means of not having any demanded bits. + bool isUseDead(Use *U); + + void print(raw_ostream &OS); + +private: + void performAnalysis(); + void determineLiveOperandBits(const Instruction *UserI, + const Value *Val, unsigned OperandNo, + const APInt &AOut, APInt &AB, + KnownBits &Known, KnownBits &Known2, bool &KnownBitsComputed); + + Function &F; + AssumptionCache &AC; + DominatorTree &DT; + + bool Analyzed = false; + + // The set of visited instructions (non-integer-typed only). + SmallPtrSet<Instruction*, 32> Visited; + DenseMap<Instruction *, APInt> AliveBits; + // Uses with no demanded bits. If the user also has no demanded bits, the use + // might not be stored explicitly in this map, to save memory during analysis. + SmallPtrSet<Use *, 16> DeadUses; +}; + +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 AnalysisKey Key; + +public: + /// Provide the result type for this analysis pass. + using Result = DemandedBits; + + /// Run the analysis pass over a function and produce demanded bits + /// information. + DemandedBits run(Function &F, FunctionAnalysisManager &AM); +}; + +/// Printer pass for DemandedBits +class DemandedBitsPrinterPass : public PassInfoMixin<DemandedBitsPrinterPass> { + raw_ostream &OS; + +public: + explicit DemandedBitsPrinterPass(raw_ostream &OS) : OS(OS) {} + + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + +/// Create a demanded bits analysis pass. +FunctionPass *createDemandedBitsWrapperPass(); + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_DEMANDED_BITS_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/DependenceAnalysis.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/DependenceAnalysis.h new file mode 100644 index 0000000..0c4002c --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/DependenceAnalysis.h
@@ -0,0 +1,981 @@ +//===-- llvm/Analysis/DependenceAnalysis.h -------------------- -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// DependenceAnalysis is an LLVM pass that analyses dependences between memory +// accesses. Currently, it is an implementation of the approach described in +// +// Practical Dependence Testing +// Goff, Kennedy, Tseng +// PLDI 1991 +// +// There's a single entry point that analyzes the dependence between a pair +// of memory references in a function, returning either NULL, for no dependence, +// or a more-or-less detailed description of the dependence between them. +// +// This pass exists to support the DependenceGraph pass. There are two separate +// passes because there's a useful separation of concerns. A dependence exists +// if two conditions are met: +// +// 1) Two instructions reference the same memory location, and +// 2) There is a flow of control leading from one instruction to the other. +// +// DependenceAnalysis attacks the first condition; DependenceGraph will attack +// the second (it's not yet ready). +// +// Please note that this is work in progress and the interface is subject to +// change. +// +// Plausible changes: +// Return a set of more precise dependences instead of just one dependence +// summarizing all. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_DEPENDENCEANALYSIS_H +#define LLVM_ANALYSIS_DEPENDENCEANALYSIS_H + +#include "llvm/ADT/SmallBitVector.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; + class SCEV; + class SCEVConstant; + class raw_ostream; + + /// Dependence - This class represents a dependence between two memory + /// memory references in a function. It contains minimal information and + /// is used in the very common situation where the compiler is unable to + /// determine anything beyond the existence of a dependence; that is, it + /// represents a confused dependence (see also FullDependence). In most + /// cases (for output, flow, and anti dependences), the dependence implies + /// an ordering, where the source must precede the destination; in contrast, + /// input dependences are unordered. + /// + /// When a dependence graph is built, each Dependence will be a member of + /// the set of predecessor edges for its destination instruction and a set + /// if successor edges for its source instruction. These sets are represented + /// as singly-linked lists, with the "next" fields stored in the dependence + /// itelf. + class Dependence { + protected: + Dependence(Dependence &&) = default; + Dependence &operator=(Dependence &&) = default; + + public: + Dependence(Instruction *Source, + Instruction *Destination) : + Src(Source), + Dst(Destination), + NextPredecessor(nullptr), + NextSuccessor(nullptr) {} + virtual ~Dependence() {} + + /// Dependence::DVEntry - Each level in the distance/direction vector + /// has a direction (or perhaps a union of several directions), and + /// perhaps a distance. + struct DVEntry { + enum { NONE = 0, + LT = 1, + EQ = 2, + LE = 3, + GT = 4, + NE = 5, + GE = 6, + ALL = 7 }; + unsigned char Direction : 3; // Init to ALL, then refine. + bool Scalar : 1; // Init to true. + bool PeelFirst : 1; // Peeling the first iteration will break dependence. + bool PeelLast : 1; // Peeling the last iteration will break the dependence. + bool Splitable : 1; // Splitting the loop will break dependence. + const SCEV *Distance; // NULL implies no distance available. + DVEntry() : Direction(ALL), Scalar(true), PeelFirst(false), + PeelLast(false), Splitable(false), Distance(nullptr) { } + }; + + /// getSrc - Returns the source instruction for this dependence. + /// + Instruction *getSrc() const { return Src; } + + /// getDst - Returns the destination instruction for this dependence. + /// + Instruction *getDst() const { return Dst; } + + /// isInput - Returns true if this is an input dependence. + /// + bool isInput() const; + + /// isOutput - Returns true if this is an output dependence. + /// + bool isOutput() const; + + /// isFlow - Returns true if this is a flow (aka true) dependence. + /// + bool isFlow() const; + + /// isAnti - Returns true if this is an anti dependence. + /// + bool isAnti() const; + + /// isOrdered - Returns true if dependence is Output, Flow, or Anti + /// + bool isOrdered() const { return isOutput() || isFlow() || isAnti(); } + + /// isUnordered - Returns true if dependence is Input + /// + bool isUnordered() const { return isInput(); } + + /// isLoopIndependent - Returns true if this is a loop-independent + /// dependence. + virtual bool isLoopIndependent() const { return true; } + + /// isConfused - Returns true if this dependence is confused + /// (the compiler understands nothing and makes worst-case + /// assumptions). + virtual bool isConfused() const { return true; } + + /// isConsistent - Returns true if this dependence is consistent + /// (occurs every time the source and destination are executed). + virtual bool isConsistent() const { return false; } + + /// getLevels - Returns the number of common loops surrounding the + /// source and destination of the dependence. + virtual unsigned getLevels() const { return 0; } + + /// getDirection - Returns the direction associated with a particular + /// level. + virtual unsigned getDirection(unsigned Level) const { return DVEntry::ALL; } + + /// getDistance - Returns the distance (or NULL) associated with a + /// particular level. + virtual const SCEV *getDistance(unsigned Level) const { return nullptr; } + + /// isPeelFirst - Returns true if peeling the first iteration from + /// this loop will break this dependence. + virtual bool isPeelFirst(unsigned Level) const { return false; } + + /// isPeelLast - Returns true if peeling the last iteration from + /// this loop will break this dependence. + virtual bool isPeelLast(unsigned Level) const { return false; } + + /// isSplitable - Returns true if splitting this loop will break + /// the dependence. + virtual bool isSplitable(unsigned Level) const { return false; } + + /// isScalar - Returns true if a particular level is scalar; that is, + /// if no subscript in the source or destination mention the induction + /// variable associated with the loop at this level. + virtual bool isScalar(unsigned Level) const; + + /// getNextPredecessor - Returns the value of the NextPredecessor + /// field. + const Dependence *getNextPredecessor() const { return NextPredecessor; } + + /// getNextSuccessor - Returns the value of the NextSuccessor + /// field. + const Dependence *getNextSuccessor() const { return NextSuccessor; } + + /// setNextPredecessor - Sets the value of the NextPredecessor + /// field. + void setNextPredecessor(const Dependence *pred) { NextPredecessor = pred; } + + /// setNextSuccessor - Sets the value of the NextSuccessor + /// field. + void setNextSuccessor(const Dependence *succ) { NextSuccessor = succ; } + + /// dump - For debugging purposes, dumps a dependence to OS. + /// + void dump(raw_ostream &OS) const; + + private: + Instruction *Src, *Dst; + const Dependence *NextPredecessor, *NextSuccessor; + friend class DependenceInfo; + }; + + /// FullDependence - This class represents a dependence between two memory + /// references in a function. It contains detailed information about the + /// dependence (direction vectors, etc.) and is used when the compiler is + /// able to accurately analyze the interaction of the references; that is, + /// it is not a confused dependence (see Dependence). In most cases + /// (for output, flow, and anti dependences), the dependence implies an + /// ordering, where the source must precede the destination; in contrast, + /// input dependences are unordered. + class FullDependence final : public Dependence { + public: + FullDependence(Instruction *Src, Instruction *Dst, bool LoopIndependent, + unsigned Levels); + + /// isLoopIndependent - Returns true if this is a loop-independent + /// dependence. + bool isLoopIndependent() const override { return LoopIndependent; } + + /// isConfused - Returns true if this dependence is confused + /// (the compiler understands nothing and makes worst-case + /// assumptions). + bool isConfused() const override { return false; } + + /// isConsistent - Returns true if this dependence is consistent + /// (occurs every time the source and destination are executed). + bool isConsistent() const override { return Consistent; } + + /// getLevels - Returns the number of common loops surrounding the + /// source and destination of the dependence. + unsigned getLevels() const override { return Levels; } + + /// getDirection - Returns the direction associated with a particular + /// level. + unsigned getDirection(unsigned Level) const override; + + /// getDistance - Returns the distance (or NULL) associated with a + /// particular level. + const SCEV *getDistance(unsigned Level) const override; + + /// isPeelFirst - Returns true if peeling the first iteration from + /// this loop will break this dependence. + bool isPeelFirst(unsigned Level) const override; + + /// isPeelLast - Returns true if peeling the last iteration from + /// this loop will break this dependence. + bool isPeelLast(unsigned Level) const override; + + /// isSplitable - Returns true if splitting the loop will break + /// the dependence. + bool isSplitable(unsigned Level) const override; + + /// isScalar - Returns true if a particular level is scalar; that is, + /// if no subscript in the source or destination mention the induction + /// variable associated with the loop at this level. + bool isScalar(unsigned Level) const override; + + private: + unsigned short Levels; + bool LoopIndependent; + bool Consistent; // Init to true, then refine. + std::unique_ptr<DVEntry[]> DV; + friend class DependenceInfo; + }; + + /// DependenceInfo - This class is the main dependence-analysis driver. + /// + class DependenceInfo { + public: + DependenceInfo(Function *F, AliasAnalysis *AA, ScalarEvolution *SE, + LoopInfo *LI) + : AA(AA), SE(SE), LI(LI), F(F) {} + + /// Handle transitive invalidation when the cached analysis results go away. + bool invalidate(Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &Inv); + + /// 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. + /// The flag PossiblyLoopIndependent should be set by the caller + /// if it appears that control flow can reach from Src to Dst + /// without traversing a loop back edge. + std::unique_ptr<Dependence> depends(Instruction *Src, + Instruction *Dst, + bool PossiblyLoopIndependent); + + /// getSplitIteration - Give a dependence that's splittable at some + /// particular level, return the iteration that should be used to split + /// the loop. + /// + /// Generally, the dependence analyzer will be used to build + /// a dependence graph for a function (basically a map from instructions + /// to dependences). Looking for cycles in the graph shows us loops + /// that cannot be trivially vectorized/parallelized. + /// + /// We can try to improve the situation by examining all the dependences + /// that make up the cycle, looking for ones we can break. + /// Sometimes, peeling the first or last iteration of a loop will break + /// dependences, and there are flags for those possibilities. + /// Sometimes, splitting a loop at some other iteration will do the trick, + /// and we've got a flag for that case. Rather than waste the space to + /// record the exact iteration (since we rarely know), we provide + /// a method that calculates the iteration. It's a drag that it must work + /// from scratch, but wonderful in that it's possible. + /// + /// Here's an example: + /// + /// for (i = 0; i < 10; i++) + /// A[i] = ... + /// ... = A[11 - i] + /// + /// There's a loop-carried flow dependence from the store to the load, + /// found by the weak-crossing SIV test. The dependence will have a flag, + /// indicating that the dependence can be broken by splitting the loop. + /// Calling getSplitIteration will return 5. + /// Splitting the loop breaks the dependence, like so: + /// + /// for (i = 0; i <= 5; i++) + /// A[i] = ... + /// ... = A[11 - i] + /// for (i = 6; i < 10; i++) + /// A[i] = ... + /// ... = A[11 - i] + /// + /// breaks the dependence and allows us to vectorize/parallelize + /// both loops. + const SCEV *getSplitIteration(const Dependence &Dep, unsigned Level); + + Function *getFunction() const { return F; } + + private: + AliasAnalysis *AA; + ScalarEvolution *SE; + LoopInfo *LI; + Function *F; + + /// Subscript - This private struct represents a pair of subscripts from + /// a pair of potentially multi-dimensional array references. We use a + /// vector of them to guide subscript partitioning. + struct Subscript { + const SCEV *Src; + const SCEV *Dst; + enum ClassificationKind { ZIV, SIV, RDIV, MIV, NonLinear } Classification; + SmallBitVector Loops; + SmallBitVector GroupLoops; + SmallBitVector Group; + }; + + struct CoefficientInfo { + const SCEV *Coeff; + const SCEV *PosPart; + const SCEV *NegPart; + const SCEV *Iterations; + }; + + struct BoundInfo { + const SCEV *Iterations; + const SCEV *Upper[8]; + const SCEV *Lower[8]; + unsigned char Direction; + unsigned char DirSet; + }; + + /// Constraint - This private class represents a constraint, as defined + /// in the paper + /// + /// Practical Dependence Testing + /// Goff, Kennedy, Tseng + /// PLDI 1991 + /// + /// There are 5 kinds of constraint, in a hierarchy. + /// 1) Any - indicates no constraint, any dependence is possible. + /// 2) Line - A line ax + by = c, where a, b, and c are parameters, + /// representing the dependence equation. + /// 3) Distance - The value d of the dependence distance; + /// 4) Point - A point <x, y> representing the dependence from + /// iteration x to iteration y. + /// 5) Empty - No dependence is possible. + class Constraint { + private: + enum ConstraintKind { Empty, Point, Distance, Line, Any } Kind; + ScalarEvolution *SE; + const SCEV *A; + const SCEV *B; + const SCEV *C; + const Loop *AssociatedLoop; + + public: + /// isEmpty - Return true if the constraint is of kind Empty. + bool isEmpty() const { return Kind == Empty; } + + /// isPoint - Return true if the constraint is of kind Point. + bool isPoint() const { return Kind == Point; } + + /// isDistance - Return true if the constraint is of kind Distance. + bool isDistance() const { return Kind == Distance; } + + /// isLine - Return true if the constraint is of kind Line. + /// Since Distance's can also be represented as Lines, we also return + /// true if the constraint is of kind Distance. + bool isLine() const { return Kind == Line || Kind == Distance; } + + /// isAny - Return true if the constraint is of kind Any; + bool isAny() const { return Kind == Any; } + + /// getX - If constraint is a point <X, Y>, returns X. + /// Otherwise assert. + const SCEV *getX() const; + + /// getY - If constraint is a point <X, Y>, returns Y. + /// Otherwise assert. + const SCEV *getY() const; + + /// getA - If constraint is a line AX + BY = C, returns A. + /// Otherwise assert. + const SCEV *getA() const; + + /// getB - If constraint is a line AX + BY = C, returns B. + /// Otherwise assert. + const SCEV *getB() const; + + /// getC - If constraint is a line AX + BY = C, returns C. + /// Otherwise assert. + const SCEV *getC() const; + + /// getD - If constraint is a distance, returns D. + /// Otherwise assert. + const SCEV *getD() const; + + /// getAssociatedLoop - Returns the loop associated with this constraint. + const Loop *getAssociatedLoop() const; + + /// setPoint - Change a constraint to Point. + void setPoint(const SCEV *X, const SCEV *Y, const Loop *CurrentLoop); + + /// setLine - Change a constraint to Line. + void setLine(const SCEV *A, const SCEV *B, + const SCEV *C, const Loop *CurrentLoop); + + /// setDistance - Change a constraint to Distance. + void setDistance(const SCEV *D, const Loop *CurrentLoop); + + /// setEmpty - Change a constraint to Empty. + void setEmpty(); + + /// setAny - Change a constraint to Any. + void setAny(ScalarEvolution *SE); + + /// dump - For debugging purposes. Dumps the constraint + /// out to OS. + void dump(raw_ostream &OS) const; + }; + + /// establishNestingLevels - Examines the loop nesting of the Src and Dst + /// instructions and establishes their shared loops. Sets the variables + /// CommonLevels, SrcLevels, and MaxLevels. + /// The source and destination instructions needn't be contained in the same + /// loop. The routine establishNestingLevels finds the level of most deeply + /// nested loop that contains them both, CommonLevels. An instruction that's + /// not contained in a loop is at level = 0. MaxLevels is equal to the level + /// of the source plus the level of the destination, minus CommonLevels. + /// This lets us allocate vectors MaxLevels in length, with room for every + /// distinct loop referenced in both the source and destination subscripts. + /// The variable SrcLevels is the nesting depth of the source instruction. + /// It's used to help calculate distinct loops referenced by the destination. + /// Here's the map from loops to levels: + /// 0 - unused + /// 1 - outermost common loop + /// ... - other common loops + /// CommonLevels - innermost common loop + /// ... - loops containing Src but not Dst + /// SrcLevels - innermost loop containing Src but not Dst + /// ... - loops containing Dst but not Src + /// MaxLevels - innermost loop containing Dst but not Src + /// Consider the follow code fragment: + /// for (a = ...) { + /// for (b = ...) { + /// for (c = ...) { + /// for (d = ...) { + /// A[] = ...; + /// } + /// } + /// for (e = ...) { + /// for (f = ...) { + /// for (g = ...) { + /// ... = A[]; + /// } + /// } + /// } + /// } + /// } + /// If we're looking at the possibility of a dependence between the store + /// to A (the Src) and the load from A (the Dst), we'll note that they + /// have 2 loops in common, so CommonLevels will equal 2 and the direction + /// vector for Result will have 2 entries. SrcLevels = 4 and MaxLevels = 7. + /// A map from loop names to level indices would look like + /// a - 1 + /// b - 2 = CommonLevels + /// c - 3 + /// d - 4 = SrcLevels + /// e - 5 + /// f - 6 + /// g - 7 = MaxLevels + void establishNestingLevels(const Instruction *Src, + const Instruction *Dst); + + unsigned CommonLevels, SrcLevels, MaxLevels; + + /// mapSrcLoop - Given one of the loops containing the source, return + /// its level index in our numbering scheme. + unsigned mapSrcLoop(const Loop *SrcLoop) const; + + /// mapDstLoop - Given one of the loops containing the destination, + /// return its level index in our numbering scheme. + unsigned mapDstLoop(const Loop *DstLoop) const; + + /// isLoopInvariant - Returns true if Expression is loop invariant + /// in LoopNest. + bool isLoopInvariant(const SCEV *Expression, const Loop *LoopNest) const; + + /// Makes sure all subscript pairs share the same integer type by + /// sign-extending as necessary. + /// Sign-extending a subscript is safe because getelementptr assumes the + /// array subscripts are signed. + void unifySubscriptType(ArrayRef<Subscript *> Pairs); + + /// removeMatchingExtensions - Examines a subscript pair. + /// If the source and destination are identically sign (or zero) + /// extended, it strips off the extension in an effort to + /// simplify the actual analysis. + void removeMatchingExtensions(Subscript *Pair); + + /// collectCommonLoops - Finds the set of loops from the LoopNest that + /// have a level <= CommonLevels and are referred to by the SCEV Expression. + void collectCommonLoops(const SCEV *Expression, + const Loop *LoopNest, + SmallBitVector &Loops) const; + + /// checkSrcSubscript - Examines the SCEV Src, returning true iff it's + /// linear. Collect the set of loops mentioned by Src. + bool checkSrcSubscript(const SCEV *Src, + const Loop *LoopNest, + SmallBitVector &Loops); + + /// checkDstSubscript - Examines the SCEV Dst, returning true iff it's + /// linear. Collect the set of loops mentioned by Dst. + bool checkDstSubscript(const SCEV *Dst, + const Loop *LoopNest, + SmallBitVector &Loops); + + /// isKnownPredicate - Compare X and Y using the predicate Pred. + /// Basically a wrapper for SCEV::isKnownPredicate, + /// but tries harder, especially in the presence of sign and zero + /// extensions and symbolics. + bool isKnownPredicate(ICmpInst::Predicate Pred, + const SCEV *X, + const SCEV *Y) const; + + /// isKnownLessThan - Compare to see if S is less than Size + /// Another wrapper for isKnownNegative(S - max(Size, 1)) with some extra + /// checking if S is an AddRec and we can prove lessthan using the loop + /// bounds. + bool isKnownLessThan(const SCEV *S, const SCEV *Size) const; + + /// isKnownNonNegative - Compare to see if S is known not to be negative + /// Uses the fact that S comes from Ptr, which may be an inbound GEP, + /// Proving there is no wrapping going on. + bool isKnownNonNegative(const SCEV *S, const Value *Ptr) const; + + /// collectUpperBound - All subscripts are the same type (on my machine, + /// an i64). The loop bound may be a smaller type. collectUpperBound + /// find the bound, if available, and zero extends it to the Type T. + /// (I zero extend since the bound should always be >= 0.) + /// If no upper bound is available, return NULL. + const SCEV *collectUpperBound(const Loop *l, Type *T) const; + + /// collectConstantUpperBound - Calls collectUpperBound(), then + /// attempts to cast it to SCEVConstant. If the cast fails, + /// returns NULL. + const SCEVConstant *collectConstantUpperBound(const Loop *l, Type *T) const; + + /// classifyPair - Examines the subscript pair (the Src and Dst SCEVs) + /// and classifies it as either ZIV, SIV, RDIV, MIV, or Nonlinear. + /// Collects the associated loops in a set. + Subscript::ClassificationKind classifyPair(const SCEV *Src, + const Loop *SrcLoopNest, + const SCEV *Dst, + const Loop *DstLoopNest, + SmallBitVector &Loops); + + /// testZIV - Tests the ZIV subscript pair (Src and Dst) for dependence. + /// Returns true if any possible dependence is disproved. + /// If there might be a dependence, returns false. + /// If the dependence isn't proven to exist, + /// marks the Result as inconsistent. + bool testZIV(const SCEV *Src, + const SCEV *Dst, + FullDependence &Result) const; + + /// testSIV - Tests the SIV subscript pair (Src and Dst) for dependence. + /// Things of the form [c1 + a1*i] and [c2 + a2*j], where + /// i and j are induction variables, c1 and c2 are loop invariant, + /// and a1 and a2 are constant. + /// Returns true if any possible dependence is disproved. + /// If there might be a dependence, returns false. + /// Sets appropriate direction vector entry and, when possible, + /// the distance vector entry. + /// If the dependence isn't proven to exist, + /// marks the Result as inconsistent. + bool testSIV(const SCEV *Src, + const SCEV *Dst, + unsigned &Level, + FullDependence &Result, + Constraint &NewConstraint, + const SCEV *&SplitIter) const; + + /// testRDIV - Tests the RDIV subscript pair (Src and Dst) for dependence. + /// Things of the form [c1 + a1*i] and [c2 + a2*j] + /// where i and j are induction variables, c1 and c2 are loop invariant, + /// and a1 and a2 are constant. + /// With minor algebra, this test can also be used for things like + /// [c1 + a1*i + a2*j][c2]. + /// Returns true if any possible dependence is disproved. + /// If there might be a dependence, returns false. + /// Marks the Result as inconsistent. + bool testRDIV(const SCEV *Src, + const SCEV *Dst, + FullDependence &Result) const; + + /// testMIV - Tests the MIV subscript pair (Src and Dst) for dependence. + /// Returns true if dependence disproved. + /// Can sometimes refine direction vectors. + bool testMIV(const SCEV *Src, + const SCEV *Dst, + const SmallBitVector &Loops, + FullDependence &Result) const; + + /// strongSIVtest - Tests the strong SIV subscript pair (Src and Dst) + /// for dependence. + /// Things of the form [c1 + a*i] and [c2 + a*i], + /// where i is an induction variable, c1 and c2 are loop invariant, + /// and a is a constant + /// Returns true if any possible dependence is disproved. + /// If there might be a dependence, returns false. + /// Sets appropriate direction and distance. + bool strongSIVtest(const SCEV *Coeff, + const SCEV *SrcConst, + const SCEV *DstConst, + const Loop *CurrentLoop, + unsigned Level, + FullDependence &Result, + Constraint &NewConstraint) const; + + /// weakCrossingSIVtest - Tests the weak-crossing SIV subscript pair + /// (Src and Dst) for dependence. + /// Things of the form [c1 + a*i] and [c2 - a*i], + /// where i is an induction variable, c1 and c2 are loop invariant, + /// and a is a constant. + /// Returns true if any possible dependence is disproved. + /// If there might be a dependence, returns false. + /// Sets appropriate direction entry. + /// Set consistent to false. + /// Marks the dependence as splitable. + bool weakCrossingSIVtest(const SCEV *SrcCoeff, + const SCEV *SrcConst, + const SCEV *DstConst, + const Loop *CurrentLoop, + unsigned Level, + FullDependence &Result, + Constraint &NewConstraint, + const SCEV *&SplitIter) const; + + /// ExactSIVtest - Tests the SIV subscript pair + /// (Src and Dst) for dependence. + /// Things of the form [c1 + a1*i] and [c2 + a2*i], + /// where i is an induction variable, c1 and c2 are loop invariant, + /// and a1 and a2 are constant. + /// Returns true if any possible dependence is disproved. + /// If there might be a dependence, returns false. + /// Sets appropriate direction entry. + /// Set consistent to false. + bool exactSIVtest(const SCEV *SrcCoeff, + const SCEV *DstCoeff, + const SCEV *SrcConst, + const SCEV *DstConst, + const Loop *CurrentLoop, + unsigned Level, + FullDependence &Result, + Constraint &NewConstraint) const; + + /// weakZeroSrcSIVtest - Tests the weak-zero SIV subscript pair + /// (Src and Dst) for dependence. + /// Things of the form [c1] and [c2 + a*i], + /// where i is an induction variable, c1 and c2 are loop invariant, + /// and a is a constant. See also weakZeroDstSIVtest. + /// Returns true if any possible dependence is disproved. + /// If there might be a dependence, returns false. + /// Sets appropriate direction entry. + /// Set consistent to false. + /// If loop peeling will break the dependence, mark appropriately. + bool weakZeroSrcSIVtest(const SCEV *DstCoeff, + const SCEV *SrcConst, + const SCEV *DstConst, + const Loop *CurrentLoop, + unsigned Level, + FullDependence &Result, + Constraint &NewConstraint) const; + + /// weakZeroDstSIVtest - Tests the weak-zero SIV subscript pair + /// (Src and Dst) for dependence. + /// Things of the form [c1 + a*i] and [c2], + /// where i is an induction variable, c1 and c2 are loop invariant, + /// and a is a constant. See also weakZeroSrcSIVtest. + /// Returns true if any possible dependence is disproved. + /// If there might be a dependence, returns false. + /// Sets appropriate direction entry. + /// Set consistent to false. + /// If loop peeling will break the dependence, mark appropriately. + bool weakZeroDstSIVtest(const SCEV *SrcCoeff, + const SCEV *SrcConst, + const SCEV *DstConst, + const Loop *CurrentLoop, + unsigned Level, + FullDependence &Result, + Constraint &NewConstraint) const; + + /// exactRDIVtest - Tests the RDIV subscript pair for dependence. + /// Things of the form [c1 + a*i] and [c2 + b*j], + /// where i and j are induction variable, c1 and c2 are loop invariant, + /// and a and b are constants. + /// Returns true if any possible dependence is disproved. + /// Marks the result as inconsistent. + /// Works in some cases that symbolicRDIVtest doesn't, + /// and vice versa. + bool exactRDIVtest(const SCEV *SrcCoeff, + const SCEV *DstCoeff, + const SCEV *SrcConst, + const SCEV *DstConst, + const Loop *SrcLoop, + const Loop *DstLoop, + FullDependence &Result) const; + + /// symbolicRDIVtest - Tests the RDIV subscript pair for dependence. + /// Things of the form [c1 + a*i] and [c2 + b*j], + /// where i and j are induction variable, c1 and c2 are loop invariant, + /// and a and b are constants. + /// Returns true if any possible dependence is disproved. + /// Marks the result as inconsistent. + /// Works in some cases that exactRDIVtest doesn't, + /// and vice versa. Can also be used as a backup for + /// ordinary SIV tests. + bool symbolicRDIVtest(const SCEV *SrcCoeff, + const SCEV *DstCoeff, + const SCEV *SrcConst, + const SCEV *DstConst, + const Loop *SrcLoop, + const Loop *DstLoop) const; + + /// gcdMIVtest - Tests an MIV subscript pair for dependence. + /// Returns true if any possible dependence is disproved. + /// Marks the result as inconsistent. + /// Can sometimes disprove the equal direction for 1 or more loops. + // Can handle some symbolics that even the SIV tests don't get, + /// so we use it as a backup for everything. + bool gcdMIVtest(const SCEV *Src, + const SCEV *Dst, + FullDependence &Result) const; + + /// banerjeeMIVtest - Tests an MIV subscript pair for dependence. + /// Returns true if any possible dependence is disproved. + /// Marks the result as inconsistent. + /// Computes directions. + bool banerjeeMIVtest(const SCEV *Src, + const SCEV *Dst, + const SmallBitVector &Loops, + FullDependence &Result) const; + + /// collectCoefficientInfo - Walks through the subscript, + /// collecting each coefficient, the associated loop bounds, + /// and recording its positive and negative parts for later use. + CoefficientInfo *collectCoeffInfo(const SCEV *Subscript, + bool SrcFlag, + const SCEV *&Constant) const; + + /// getPositivePart - X^+ = max(X, 0). + /// + const SCEV *getPositivePart(const SCEV *X) const; + + /// getNegativePart - X^- = min(X, 0). + /// + const SCEV *getNegativePart(const SCEV *X) const; + + /// getLowerBound - Looks through all the bounds info and + /// computes the lower bound given the current direction settings + /// at each level. + const SCEV *getLowerBound(BoundInfo *Bound) const; + + /// getUpperBound - Looks through all the bounds info and + /// computes the upper bound given the current direction settings + /// at each level. + const SCEV *getUpperBound(BoundInfo *Bound) const; + + /// exploreDirections - Hierarchically expands the direction vector + /// search space, combining the directions of discovered dependences + /// in the DirSet field of Bound. Returns the number of distinct + /// dependences discovered. If the dependence is disproved, + /// it will return 0. + unsigned exploreDirections(unsigned Level, + CoefficientInfo *A, + CoefficientInfo *B, + BoundInfo *Bound, + const SmallBitVector &Loops, + unsigned &DepthExpanded, + const SCEV *Delta) const; + + /// testBounds - Returns true iff the current bounds are plausible. + bool testBounds(unsigned char DirKind, + unsigned Level, + BoundInfo *Bound, + const SCEV *Delta) const; + + /// findBoundsALL - Computes the upper and lower bounds for level K + /// using the * direction. Records them in Bound. + void findBoundsALL(CoefficientInfo *A, + CoefficientInfo *B, + BoundInfo *Bound, + unsigned K) const; + + /// findBoundsLT - Computes the upper and lower bounds for level K + /// using the < direction. Records them in Bound. + void findBoundsLT(CoefficientInfo *A, + CoefficientInfo *B, + BoundInfo *Bound, + unsigned K) const; + + /// findBoundsGT - Computes the upper and lower bounds for level K + /// using the > direction. Records them in Bound. + void findBoundsGT(CoefficientInfo *A, + CoefficientInfo *B, + BoundInfo *Bound, + unsigned K) const; + + /// findBoundsEQ - Computes the upper and lower bounds for level K + /// using the = direction. Records them in Bound. + void findBoundsEQ(CoefficientInfo *A, + CoefficientInfo *B, + BoundInfo *Bound, + unsigned K) const; + + /// intersectConstraints - Updates X with the intersection + /// of the Constraints X and Y. Returns true if X has changed. + bool intersectConstraints(Constraint *X, + const Constraint *Y); + + /// propagate - Review the constraints, looking for opportunities + /// to simplify a subscript pair (Src and Dst). + /// Return true if some simplification occurs. + /// If the simplification isn't exact (that is, if it is conservative + /// in terms of dependence), set consistent to false. + bool propagate(const SCEV *&Src, + const SCEV *&Dst, + SmallBitVector &Loops, + SmallVectorImpl<Constraint> &Constraints, + bool &Consistent); + + /// propagateDistance - Attempt to propagate a distance + /// constraint into a subscript pair (Src and Dst). + /// Return true if some simplification occurs. + /// If the simplification isn't exact (that is, if it is conservative + /// in terms of dependence), set consistent to false. + bool propagateDistance(const SCEV *&Src, + const SCEV *&Dst, + Constraint &CurConstraint, + bool &Consistent); + + /// propagatePoint - Attempt to propagate a point + /// constraint into a subscript pair (Src and Dst). + /// Return true if some simplification occurs. + bool propagatePoint(const SCEV *&Src, + const SCEV *&Dst, + Constraint &CurConstraint); + + /// propagateLine - Attempt to propagate a line + /// constraint into a subscript pair (Src and Dst). + /// Return true if some simplification occurs. + /// If the simplification isn't exact (that is, if it is conservative + /// in terms of dependence), set consistent to false. + bool propagateLine(const SCEV *&Src, + const SCEV *&Dst, + Constraint &CurConstraint, + bool &Consistent); + + /// findCoefficient - Given a linear SCEV, + /// return the coefficient corresponding to specified loop. + /// If there isn't one, return the SCEV constant 0. + /// For example, given a*i + b*j + c*k, returning the coefficient + /// corresponding to the j loop would yield b. + const SCEV *findCoefficient(const SCEV *Expr, + const Loop *TargetLoop) const; + + /// zeroCoefficient - Given a linear SCEV, + /// return the SCEV given by zeroing out the coefficient + /// corresponding to the specified loop. + /// For example, given a*i + b*j + c*k, zeroing the coefficient + /// corresponding to the j loop would yield a*i + c*k. + const SCEV *zeroCoefficient(const SCEV *Expr, + const Loop *TargetLoop) const; + + /// addToCoefficient - Given a linear SCEV Expr, + /// return the SCEV given by adding some Value to the + /// coefficient corresponding to the specified TargetLoop. + /// For example, given a*i + b*j + c*k, adding 1 to the coefficient + /// corresponding to the j loop would yield a*i + (b+1)*j + c*k. + const SCEV *addToCoefficient(const SCEV *Expr, + const Loop *TargetLoop, + const SCEV *Value) const; + + /// updateDirection - Update direction vector entry + /// based on the current constraint. + void updateDirection(Dependence::DVEntry &Level, + const Constraint &CurConstraint) const; + + bool tryDelinearize(Instruction *Src, Instruction *Dst, + SmallVectorImpl<Subscript> &Pair); + + private: + /// checkSubscript - Helper function for checkSrcSubscript and + /// checkDstSubscript to avoid duplicate code + bool checkSubscript(const SCEV *Expr, const Loop *LoopNest, + SmallBitVector &Loops, bool IsSrc); + }; // class DependenceInfo + + /// 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 AnalysisKey Key; + friend struct AnalysisInfoMixin<DependenceAnalysis>; + }; // class DependenceAnalysis + + /// Printer pass to dump DA results. + struct DependenceAnalysisPrinterPass + : public PassInfoMixin<DependenceAnalysisPrinterPass> { + DependenceAnalysisPrinterPass(raw_ostream &OS) : OS(OS) {} + + PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM); + + private: + raw_ostream &OS; + }; // class DependenceAnalysisPrinterPass + + /// Legacy pass manager pass to access dependence information + class DependenceAnalysisWrapperPass : public FunctionPass { + public: + static char ID; // Class identification, replacement for typeinfo + DependenceAnalysisWrapperPass(); + + bool runOnFunction(Function &F) override; + void releaseMemory() override; + void getAnalysisUsage(AnalysisUsage &) const override; + void print(raw_ostream &, const Module * = nullptr) const override; + DependenceInfo &getDI() const; + + private: + std::unique_ptr<DependenceInfo> info; + }; // class DependenceAnalysisWrapperPass + + /// createDependenceAnalysisPass - This creates an instance of the + /// DependenceAnalysis wrapper pass. + FunctionPass *createDependenceAnalysisWrapperPass(); + +} // namespace llvm + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/DependenceGraphBuilder.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/DependenceGraphBuilder.h new file mode 100644 index 0000000..08a13d9 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/DependenceGraphBuilder.h
@@ -0,0 +1,178 @@ +//===- llvm/Analysis/DependenceGraphBuilder.h -------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines a builder interface that can be used to populate dependence +// graphs such as DDG and PDG. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_DEPENDENCE_GRAPH_BUILDER_H +#define LLVM_ANALYSIS_DEPENDENCE_GRAPH_BUILDER_H + +#include "llvm/ADT/EquivalenceClasses.h" +#include "llvm/Analysis/DependenceAnalysis.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Instructions.h" + +namespace llvm { + +/// This abstract builder class defines a set of high-level steps for creating +/// DDG-like graphs. The client code is expected to inherit from this class and +/// define concrete implementation for each of the pure virtual functions used +/// in the high-level algorithm. +template <class GraphType> class AbstractDependenceGraphBuilder { +protected: + using BasicBlockListType = SmallVectorImpl<BasicBlock *>; + +private: + using NodeType = typename GraphType::NodeType; + using EdgeType = typename GraphType::EdgeType; + +public: + using ClassesType = EquivalenceClasses<BasicBlock *>; + using NodeListType = SmallVector<NodeType *, 4>; + + AbstractDependenceGraphBuilder(GraphType &G, DependenceInfo &D, + const BasicBlockListType &BBs) + : Graph(G), DI(D), BBList(BBs) {} + virtual ~AbstractDependenceGraphBuilder() {} + + /// The main entry to the graph construction algorithm. It starts by + /// creating nodes in increasing order of granularity and then + /// adds def-use and memory edges. As one of the final stages, it + /// also creates pi-block nodes to facilitate codegen in transformations + /// that use dependence graphs. + /// + /// The algorithmic complexity of this implementation is O(V^2 * I^2), where V + /// is the number of vertecies (nodes) and I is the number of instructions in + /// each node. The total number of instructions, N, is equal to V * I, + /// therefore the worst-case time complexity is O(N^2). The average time + /// complexity is O((N^2)/2). + void populate() { + computeInstructionOrdinals(); + createFineGrainedNodes(); + createDefUseEdges(); + createMemoryDependencyEdges(); + createAndConnectRootNode(); + createPiBlocks(); + sortNodesTopologically(); + } + + /// Compute ordinal numbers for each instruction and store them in a map for + /// future look up. These ordinals are used to compute node ordinals which are + /// in turn used to order nodes that are part of a cycle. + /// Instruction ordinals are assigned based on lexical program order. + void computeInstructionOrdinals(); + + /// Create fine grained nodes. These are typically atomic nodes that + /// consist of a single instruction. + void createFineGrainedNodes(); + + /// Analyze the def-use chains and create edges from the nodes containing + /// definitions to the nodes containing the uses. + void createDefUseEdges(); + + /// Analyze data dependencies that exist between memory loads or stores, + /// in the graph nodes and create edges between them. + void createMemoryDependencyEdges(); + + /// Create a root node and add edges such that each node in the graph is + /// reachable from the root. + void createAndConnectRootNode(); + + /// Apply graph abstraction to groups of nodes that belong to a strongly + /// connected component of the graph to create larger compound nodes + /// called pi-blocks. The purpose of this abstraction is to isolate sets of + /// program elements that need to stay together during codegen and turn + /// the dependence graph into an acyclic graph. + void createPiBlocks(); + + /// Topologically sort the graph nodes. + void sortNodesTopologically(); + +protected: + /// Create the root node of the graph. + virtual NodeType &createRootNode() = 0; + + /// Create an atomic node in the graph given a single instruction. + virtual NodeType &createFineGrainedNode(Instruction &I) = 0; + + /// Create a pi-block node in the graph representing a group of nodes in an + /// SCC of the graph. + virtual NodeType &createPiBlock(const NodeListType &L) = 0; + + /// Create a def-use edge going from \p Src to \p Tgt. + virtual EdgeType &createDefUseEdge(NodeType &Src, NodeType &Tgt) = 0; + + /// Create a memory dependence edge going from \p Src to \p Tgt. + virtual EdgeType &createMemoryEdge(NodeType &Src, NodeType &Tgt) = 0; + + /// Create a rooted edge going from \p Src to \p Tgt . + virtual EdgeType &createRootedEdge(NodeType &Src, NodeType &Tgt) = 0; + + /// Given a pi-block node, return a vector of all the nodes contained within + /// it. + virtual const NodeListType &getNodesInPiBlock(const NodeType &N) = 0; + + /// Deallocate memory of edge \p E. + virtual void destroyEdge(EdgeType &E) { delete &E; } + + /// Deallocate memory of node \p N. + virtual void destroyNode(NodeType &N) { delete &N; } + + /// Return true if creation of pi-blocks are supported and desired, + /// and false otherwise. + virtual bool shouldCreatePiBlocks() const { return true; } + + /// Given an instruction \p I return its associated ordinal number. + size_t getOrdinal(Instruction &I) { + assert(InstOrdinalMap.find(&I) != InstOrdinalMap.end() && + "No ordinal computed for this instruction."); + return InstOrdinalMap[&I]; + } + + /// Given a node \p N return its associated ordinal number. + size_t getOrdinal(NodeType &N) { + assert(NodeOrdinalMap.find(&N) != NodeOrdinalMap.end() && + "No ordinal computed for this node."); + return NodeOrdinalMap[&N]; + } + + /// Map types to map instructions to nodes used when populating the graph. + using InstToNodeMap = DenseMap<Instruction *, NodeType *>; + + /// Map Types to map instruction/nodes to an ordinal number. + using InstToOrdinalMap = DenseMap<Instruction *, size_t>; + using NodeToOrdinalMap = DenseMap<NodeType *, size_t>; + + /// Reference to the graph that gets built by a concrete implementation of + /// this builder. + GraphType &Graph; + + /// Dependence information used to create memory dependence edges in the + /// graph. + DependenceInfo &DI; + + /// The list of basic blocks to consider when building the graph. + const BasicBlockListType &BBList; + + /// A mapping from instructions to the corresponding nodes in the graph. + InstToNodeMap IMap; + + /// A mapping from each instruction to an ordinal number. This map is used to + /// populate the \p NodeOrdinalMap. + InstToOrdinalMap InstOrdinalMap; + + /// A mapping from nodes to an ordinal number. This map is used to sort nodes + /// in a pi-block based on program order. + NodeToOrdinalMap NodeOrdinalMap; +}; + +} // namespace llvm + +#endif // LLVM_ANALYSIS_DEPENDENCE_GRAPH_BUILDER_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/DivergenceAnalysis.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/DivergenceAnalysis.h new file mode 100644 index 0000000..2fac9c8 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/DivergenceAnalysis.h
@@ -0,0 +1,214 @@ +//===- llvm/Analysis/DivergenceAnalysis.h - Divergence Analysis -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// \file +// The divergence analysis determines which instructions and branches are +// divergent given a set of divergent source instructions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_DIVERGENCE_ANALYSIS_H +#define LLVM_ANALYSIS_DIVERGENCE_ANALYSIS_H + +#include "llvm/ADT/DenseSet.h" +#include "llvm/Analysis/SyncDependenceAnalysis.h" +#include "llvm/IR/Function.h" +#include "llvm/Pass.h" +#include <vector> + +namespace llvm { +class Module; +class Value; +class Instruction; +class Loop; +class raw_ostream; +class TargetTransformInfo; + +/// \brief Generic divergence analysis for reducible CFGs. +/// +/// This analysis propagates divergence in a data-parallel context from sources +/// of divergence to all users. It requires reducible CFGs. All assignments +/// should be in SSA form. +class DivergenceAnalysis { +public: + /// \brief This instance will analyze the whole function \p F or the loop \p + /// RegionLoop. + /// + /// \param RegionLoop if non-null the analysis is restricted to \p RegionLoop. + /// Otherwise the whole function is analyzed. + /// \param IsLCSSAForm whether the analysis may assume that the IR in the + /// region in in LCSSA form. + DivergenceAnalysis(const Function &F, const Loop *RegionLoop, + const DominatorTree &DT, const LoopInfo &LI, + SyncDependenceAnalysis &SDA, bool IsLCSSAForm); + + /// \brief The loop that defines the analyzed region (if any). + const Loop *getRegionLoop() const { return RegionLoop; } + const Function &getFunction() const { return F; } + + /// \brief Whether \p BB is part of the region. + bool inRegion(const BasicBlock &BB) const; + /// \brief Whether \p I is part of the region. + bool inRegion(const Instruction &I) const; + + /// \brief Mark \p UniVal as a value that is always uniform. + void addUniformOverride(const Value &UniVal); + + /// \brief Mark \p DivVal as a value that is always divergent. + void markDivergent(const Value &DivVal); + + /// \brief Propagate divergence to all instructions in the region. + /// Divergence is seeded by calls to \p markDivergent. + void compute(); + + /// \brief Whether any value was marked or analyzed to be divergent. + bool hasDetectedDivergence() const { return !DivergentValues.empty(); } + + /// \brief Whether \p Val will always return a uniform value regardless of its + /// operands + bool isAlwaysUniform(const Value &Val) const; + + /// \brief Whether \p Val is divergent at its definition. + bool isDivergent(const Value &Val) const; + + /// \brief Whether \p U is divergent. Uses of a uniform value can be divergent. + bool isDivergentUse(const Use &U) const; + + void print(raw_ostream &OS, const Module *) const; + +private: + bool updateTerminator(const Instruction &Term) const; + bool updatePHINode(const PHINode &Phi) const; + + /// \brief Computes whether \p Inst is divergent based on the + /// divergence of its operands. + /// + /// \returns Whether \p Inst is divergent. + /// + /// This should only be called for non-phi, non-terminator instructions. + bool updateNormalInstruction(const Instruction &Inst) const; + + /// \brief Mark users of live-out users as divergent. + /// + /// \param LoopHeader the header of the divergent loop. + /// + /// Marks all users of live-out values of the loop headed by \p LoopHeader + /// as divergent and puts them on the worklist. + void taintLoopLiveOuts(const BasicBlock &LoopHeader); + + /// \brief Push all users of \p Val (in the region) to the worklist + void pushUsers(const Value &I); + + /// \brief Push all phi nodes in @block to the worklist + void pushPHINodes(const BasicBlock &Block); + + /// \brief Mark \p Block as join divergent + /// + /// A block is join divergent if two threads may reach it from different + /// incoming blocks at the same time. + void markBlockJoinDivergent(const BasicBlock &Block) { + DivergentJoinBlocks.insert(&Block); + } + + /// \brief Whether \p Val is divergent when read in \p ObservingBlock. + bool isTemporalDivergent(const BasicBlock &ObservingBlock, + const Value &Val) const; + + /// \brief Whether \p Block is join divergent + /// + /// (see markBlockJoinDivergent). + bool isJoinDivergent(const BasicBlock &Block) const { + return DivergentJoinBlocks.find(&Block) != DivergentJoinBlocks.end(); + } + + /// \brief Propagate control-induced divergence to users (phi nodes and + /// instructions). + // + // \param JoinBlock is a divergent loop exit or join point of two disjoint + // paths. + // \returns Whether \p JoinBlock is a divergent loop exit of \p TermLoop. + bool propagateJoinDivergence(const BasicBlock &JoinBlock, + const Loop *TermLoop); + + /// \brief Propagate induced value divergence due to control divergence in \p + /// Term. + void propagateBranchDivergence(const Instruction &Term); + + /// \brief Propagate divergent caused by a divergent loop exit. + /// + /// \param ExitingLoop is a divergent loop. + void propagateLoopDivergence(const Loop &ExitingLoop); + +private: + const Function &F; + // If regionLoop != nullptr, analysis is only performed within \p RegionLoop. + // Otw, analyze the whole function + const Loop *RegionLoop; + + const DominatorTree &DT; + const LoopInfo &LI; + + // Recognized divergent loops + DenseSet<const Loop *> DivergentLoops; + + // The SDA links divergent branches to divergent control-flow joins. + SyncDependenceAnalysis &SDA; + + // Use simplified code path for LCSSA form. + bool IsLCSSAForm; + + // Set of known-uniform values. + DenseSet<const Value *> UniformOverrides; + + // Blocks with joining divergent control from different predecessors. + DenseSet<const BasicBlock *> DivergentJoinBlocks; + + // Detected/marked divergent values. + DenseSet<const Value *> DivergentValues; + + // Internal worklist for divergence propagation. + std::vector<const Instruction *> Worklist; +}; + +/// \brief Divergence analysis frontend for GPU kernels. +class GPUDivergenceAnalysis { + SyncDependenceAnalysis SDA; + DivergenceAnalysis DA; + +public: + /// Runs the divergence analysis on @F, a GPU kernel + GPUDivergenceAnalysis(Function &F, const DominatorTree &DT, + const PostDominatorTree &PDT, const LoopInfo &LI, + const TargetTransformInfo &TTI); + + /// Whether any divergence was detected. + bool hasDivergence() const { return DA.hasDetectedDivergence(); } + + /// The GPU kernel this analysis result is for + const Function &getFunction() const { return DA.getFunction(); } + + /// Whether \p V is divergent at its definition. + bool isDivergent(const Value &V) const; + + /// Whether \p U is divergent. Uses of a uniform value can be divergent. + bool isDivergentUse(const Use &U) const; + + /// Whether \p V is uniform/non-divergent. + bool isUniform(const Value &V) const { return !isDivergent(V); } + + /// Whether \p U is uniform/non-divergent. Uses of a uniform value can be + /// divergent. + bool isUniformUse(const Use &U) const { return !isDivergentUse(U); } + + /// Print all divergent values in the kernel. + void print(raw_ostream &OS, const Module *) const; +}; + +} // namespace llvm + +#endif // LLVM_ANALYSIS_DIVERGENCE_ANALYSIS_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/DomPrinter.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/DomPrinter.h new file mode 100644 index 0000000..a177f87 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/DomPrinter.h
@@ -0,0 +1,29 @@ +//===-- DomPrinter.h - Dom printer external interface ------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines external functions that can be called to explicitly +// instantiate the dominance tree printer. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_DOMPRINTER_H +#define LLVM_ANALYSIS_DOMPRINTER_H + +namespace llvm { + class FunctionPass; + FunctionPass *createDomPrinterPass(); + FunctionPass *createDomOnlyPrinterPass(); + FunctionPass *createDomViewerPass(); + FunctionPass *createDomOnlyViewerPass(); + FunctionPass *createPostDomPrinterPass(); + FunctionPass *createPostDomOnlyPrinterPass(); + FunctionPass *createPostDomViewerPass(); + FunctionPass *createPostDomOnlyViewerPass(); +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/DomTreeUpdater.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/DomTreeUpdater.h new file mode 100644 index 0000000..5ccce2e --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/DomTreeUpdater.h
@@ -0,0 +1,309 @@ +//===- DomTreeUpdater.h - DomTree/Post DomTree Updater ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the DomTreeUpdater class, which provides a uniform way to +// update dominator tree related data structures. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_DOMTREEUPDATER_H +#define LLVM_ANALYSIS_DOMTREEUPDATER_H + +#include "llvm/Analysis/PostDominators.h" +#include "llvm/IR/Dominators.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/Support/GenericDomTree.h" +#include <functional> +#include <vector> + +namespace llvm { +class DomTreeUpdater { +public: + enum class UpdateStrategy : unsigned char { Eager = 0, Lazy = 1 }; + + explicit DomTreeUpdater(UpdateStrategy Strategy_) : Strategy(Strategy_) {} + DomTreeUpdater(DominatorTree &DT_, UpdateStrategy Strategy_) + : DT(&DT_), Strategy(Strategy_) {} + DomTreeUpdater(DominatorTree *DT_, UpdateStrategy Strategy_) + : DT(DT_), Strategy(Strategy_) {} + DomTreeUpdater(PostDominatorTree &PDT_, UpdateStrategy Strategy_) + : PDT(&PDT_), Strategy(Strategy_) {} + DomTreeUpdater(PostDominatorTree *PDT_, UpdateStrategy Strategy_) + : PDT(PDT_), Strategy(Strategy_) {} + DomTreeUpdater(DominatorTree &DT_, PostDominatorTree &PDT_, + UpdateStrategy Strategy_) + : DT(&DT_), PDT(&PDT_), Strategy(Strategy_) {} + DomTreeUpdater(DominatorTree *DT_, PostDominatorTree *PDT_, + UpdateStrategy Strategy_) + : DT(DT_), PDT(PDT_), Strategy(Strategy_) {} + + ~DomTreeUpdater() { flush(); } + + /// Returns true if the current strategy is Lazy. + bool isLazy() const { return Strategy == UpdateStrategy::Lazy; }; + + /// Returns true if the current strategy is Eager. + bool isEager() const { return Strategy == UpdateStrategy::Eager; }; + + /// Returns true if it holds a DominatorTree. + bool hasDomTree() const { return DT != nullptr; } + + /// Returns true if it holds a PostDominatorTree. + bool hasPostDomTree() const { return PDT != nullptr; } + + /// Returns true if there is BasicBlock awaiting deletion. + /// The deletion will only happen until a flush event and + /// all available trees are up-to-date. + /// Returns false under Eager UpdateStrategy. + bool hasPendingDeletedBB() const { return !DeletedBBs.empty(); } + + /// Returns true if DelBB is awaiting deletion. + /// Returns false under Eager UpdateStrategy. + bool isBBPendingDeletion(BasicBlock *DelBB) const; + + /// Returns true if either of DT or PDT is valid and the tree has at + /// least one update pending. If DT or PDT is nullptr it is treated + /// as having no pending updates. This function does not check + /// whether there is BasicBlock awaiting deletion. + /// Returns false under Eager UpdateStrategy. + bool hasPendingUpdates() const; + + /// Returns true if there are DominatorTree updates queued. + /// Returns false under Eager UpdateStrategy or DT is nullptr. + bool hasPendingDomTreeUpdates() const; + + /// Returns true if there are PostDominatorTree updates queued. + /// Returns false under Eager UpdateStrategy or PDT is nullptr. + bool hasPendingPostDomTreeUpdates() const; + + ///@{ + /// \name Mutation APIs + /// + /// These methods provide APIs for submitting updates to the DominatorTree and + /// the PostDominatorTree. + /// + /// Note: There are two strategies to update the DominatorTree and the + /// PostDominatorTree: + /// 1. Eager UpdateStrategy: Updates are submitted and then flushed + /// immediately. + /// 2. Lazy UpdateStrategy: Updates are submitted but only flushed when you + /// explicitly call Flush APIs. It is recommended to use this update strategy + /// when you submit a bunch of updates multiple times which can then + /// add up to a large number of updates between two queries on the + /// DominatorTree. The incremental updater can reschedule the updates or + /// decide to recalculate the dominator tree in order to speedup the updating + /// process depending on the number of updates. + /// + /// Although GenericDomTree provides several update primitives, + /// it is not encouraged to use these APIs directly. + + /// Submit updates to all available trees. + /// The Eager Strategy flushes updates immediately while the Lazy Strategy + /// queues the updates. + /// + /// Note: The "existence" of an edge in a CFG refers to the CFG which DTU is + /// in sync with + all updates before that single update. + /// + /// CAUTION! + /// 1. It is required for the state of the LLVM IR to be updated + /// *before* submitting the updates because the internal update routine will + /// analyze the current state of the CFG to determine whether an update + /// is valid. + /// 2. It is illegal to submit any update that has already been submitted, + /// i.e., you are supposed not to insert an existent edge or delete a + /// nonexistent edge. + void applyUpdates(ArrayRef<DominatorTree::UpdateType> Updates); + + /// Submit updates to all available trees. It will also + /// 1. discard duplicated updates, + /// 2. remove invalid updates. (Invalid updates means deletion of an edge that + /// still exists or insertion of an edge that does not exist.) + /// The Eager Strategy flushes updates immediately while the Lazy Strategy + /// queues the updates. + /// + /// Note: The "existence" of an edge in a CFG refers to the CFG which DTU is + /// in sync with + all updates before that single update. + /// + /// CAUTION! + /// 1. It is required for the state of the LLVM IR to be updated + /// *before* submitting the updates because the internal update routine will + /// analyze the current state of the CFG to determine whether an update + /// is valid. + /// 2. It is illegal to submit any update that has already been submitted, + /// i.e., you are supposed not to insert an existent edge or delete a + /// nonexistent edge. + /// 3. It is only legal to submit updates to an edge in the order CFG changes + /// are made. The order you submit updates on different edges is not + /// restricted. + void applyUpdatesPermissive(ArrayRef<DominatorTree::UpdateType> Updates); + + /// Notify DTU that the entry block was replaced. + /// Recalculate all available trees and flush all BasicBlocks + /// awaiting deletion immediately. + void recalculate(Function &F); + + /// \deprecated { Submit an edge insertion to all available trees. The Eager + /// Strategy flushes this update immediately while the Lazy Strategy queues + /// the update. An internal function checks if the edge exists in the CFG in + /// DEBUG mode. CAUTION! This function has to be called *after* making the + /// update on the actual CFG. It is illegal to submit any update that has + /// already been applied. } + LLVM_ATTRIBUTE_DEPRECATED(void insertEdge(BasicBlock *From, BasicBlock *To), + "Use applyUpdates() instead."); + + /// \deprecated {Submit an edge insertion to all available trees. + /// Under either Strategy, an invalid update will be discard silently. + /// Invalid update means inserting an edge that does not exist in the CFG. + /// The Eager Strategy flushes this update immediately while the Lazy Strategy + /// queues the update. It is only recommended to use this method when you + /// want to discard an invalid update. + /// CAUTION! It is illegal to submit any update that has already been + /// submitted. } + LLVM_ATTRIBUTE_DEPRECATED(void insertEdgeRelaxed(BasicBlock *From, + BasicBlock *To), + "Use applyUpdatesPermissive() instead."); + + /// \deprecated { Submit an edge deletion to all available trees. The Eager + /// Strategy flushes this update immediately while the Lazy Strategy queues + /// the update. An internal function checks if the edge doesn't exist in the + /// CFG in DEBUG mode. + /// CAUTION! This function has to be called *after* making the update on the + /// actual CFG. It is illegal to submit any update that has already been + /// submitted. } + LLVM_ATTRIBUTE_DEPRECATED(void deleteEdge(BasicBlock *From, BasicBlock *To), + "Use applyUpdates() instead."); + + /// \deprecated { Submit an edge deletion to all available trees. + /// Under either Strategy, an invalid update will be discard silently. + /// Invalid update means deleting an edge that exists in the CFG. + /// The Eager Strategy flushes this update immediately while the Lazy Strategy + /// queues the update. It is only recommended to use this method when you + /// want to discard an invalid update. + /// CAUTION! It is illegal to submit any update that has already been + /// submitted. } + LLVM_ATTRIBUTE_DEPRECATED(void deleteEdgeRelaxed(BasicBlock *From, + BasicBlock *To), + "Use applyUpdatesPermissive() instead."); + + /// Delete DelBB. DelBB will be removed from its Parent and + /// erased from available trees if it exists and finally get deleted. + /// Under Eager UpdateStrategy, DelBB will be processed immediately. + /// Under Lazy UpdateStrategy, DelBB will be queued until a flush event and + /// all available trees are up-to-date. Assert if any instruction of DelBB is + /// modified while awaiting deletion. When both DT and PDT are nullptrs, DelBB + /// will be queued until flush() is called. + void deleteBB(BasicBlock *DelBB); + + /// Delete DelBB. DelBB will be removed from its Parent and + /// erased from available trees if it exists. Then the callback will + /// be called. Finally, DelBB will be deleted. + /// Under Eager UpdateStrategy, DelBB will be processed immediately. + /// Under Lazy UpdateStrategy, DelBB will be queued until a flush event and + /// all available trees are up-to-date. Assert if any instruction of DelBB is + /// modified while awaiting deletion. Multiple callbacks can be queued for one + /// DelBB under Lazy UpdateStrategy. + void callbackDeleteBB(BasicBlock *DelBB, + std::function<void(BasicBlock *)> Callback); + + ///@} + + ///@{ + /// \name Flush APIs + /// + /// CAUTION! By the moment these flush APIs are called, the current CFG needs + /// to be the same as the CFG which DTU is in sync with + all updates + /// submitted. + + /// Flush DomTree updates and return DomTree. + /// It flushes Deleted BBs if both trees are up-to-date. + /// It must only be called when it has a DomTree. + DominatorTree &getDomTree(); + + /// Flush PostDomTree updates and return PostDomTree. + /// It flushes Deleted BBs if both trees are up-to-date. + /// It must only be called when it has a PostDomTree. + PostDominatorTree &getPostDomTree(); + + /// Apply all pending updates to available trees and flush all BasicBlocks + /// awaiting deletion. + + void flush(); + + ///@} + + /// Debug method to help view the internal state of this class. + LLVM_DUMP_METHOD void dump() const; + +private: + class CallBackOnDeletion final : public CallbackVH { + public: + CallBackOnDeletion(BasicBlock *V, + std::function<void(BasicBlock *)> Callback) + : CallbackVH(V), DelBB(V), Callback_(Callback) {} + + private: + BasicBlock *DelBB = nullptr; + std::function<void(BasicBlock *)> Callback_; + + void deleted() override { + Callback_(DelBB); + CallbackVH::deleted(); + } + }; + + SmallVector<DominatorTree::UpdateType, 16> PendUpdates; + size_t PendDTUpdateIndex = 0; + size_t PendPDTUpdateIndex = 0; + DominatorTree *DT = nullptr; + PostDominatorTree *PDT = nullptr; + const UpdateStrategy Strategy; + SmallPtrSet<BasicBlock *, 8> DeletedBBs; + std::vector<CallBackOnDeletion> Callbacks; + bool IsRecalculatingDomTree = false; + bool IsRecalculatingPostDomTree = false; + + /// First remove all the instructions of DelBB and then make sure DelBB has a + /// valid terminator instruction which is necessary to have when DelBB still + /// has to be inside of its parent Function while awaiting deletion under Lazy + /// UpdateStrategy to prevent other routines from asserting the state of the + /// IR is inconsistent. Assert if DelBB is nullptr or has predecessors. + void validateDeleteBB(BasicBlock *DelBB); + + /// Returns true if at least one BasicBlock is deleted. + bool forceFlushDeletedBB(); + + /// Helper function to apply all pending DomTree updates. + void applyDomTreeUpdates(); + + /// Helper function to apply all pending PostDomTree updates. + void applyPostDomTreeUpdates(); + + /// Helper function to flush deleted BasicBlocks if all available + /// trees are up-to-date. + void tryFlushDeletedBB(); + + /// Drop all updates applied by all available trees and delete BasicBlocks if + /// all available trees are up-to-date. + void dropOutOfDateUpdates(); + + /// Erase Basic Block node that has been unlinked from Function + /// in the DomTree and PostDomTree. + void eraseDelBBNode(BasicBlock *DelBB); + + /// Returns true if the update appears in the LLVM IR. + /// It is used to check whether an update is valid in + /// insertEdge/deleteEdge or is unnecessary in the batch update. + bool isUpdateValid(DominatorTree::UpdateType Update) const; + + /// Returns true if the update is self dominance. + bool isSelfDominance(DominatorTree::UpdateType Update) const; +}; +} // namespace llvm + +#endif // LLVM_ANALYSIS_DOMTREEUPDATER_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/DominanceFrontier.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/DominanceFrontier.h new file mode 100644 index 0000000..c0bf30e --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/DominanceFrontier.h
@@ -0,0 +1,210 @@ +//===- llvm/Analysis/DominanceFrontier.h - Dominator Frontiers --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the DominanceFrontier class, which calculate and holds the +// dominance frontier for a function. +// +// This should be considered deprecated, don't add any more uses of this data +// structure. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_DOMINANCEFRONTIER_H +#define LLVM_ANALYSIS_DOMINANCEFRONTIER_H + +#include "llvm/ADT/GraphTraits.h" +#include "llvm/Config/llvm-config.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Pass.h" +#include "llvm/Support/GenericDomTree.h" +#include <cassert> +#include <map> +#include <set> +#include <utility> +#include <vector> + +namespace llvm { + +class Function; +class raw_ostream; + +//===----------------------------------------------------------------------===// +/// DominanceFrontierBase - Common base class for computing forward and inverse +/// dominance frontiers for a function. +/// +template <class BlockT, bool IsPostDom> +class DominanceFrontierBase { +public: + using DomSetType = std::set<BlockT *>; // Dom set for a bb + using DomSetMapType = std::map<BlockT *, DomSetType>; // Dom set map + +protected: + using BlockTraits = GraphTraits<BlockT *>; + + DomSetMapType Frontiers; + // Postdominators can have multiple roots. + SmallVector<BlockT *, IsPostDom ? 4 : 1> Roots; + static constexpr bool IsPostDominators = IsPostDom; + +public: + DominanceFrontierBase() = default; + + /// getRoots - Return the root blocks of the current CFG. This may include + /// multiple blocks if we are computing post dominators. For forward + /// dominators, this will always be a single block (the entry node). + const SmallVectorImpl<BlockT *> &getRoots() const { return Roots; } + + BlockT *getRoot() const { + assert(Roots.size() == 1 && "Should always have entry node!"); + return Roots[0]; + } + + /// isPostDominator - Returns true if analysis based of postdoms + bool isPostDominator() const { + return IsPostDominators; + } + + void releaseMemory() { + Frontiers.clear(); + } + + // Accessor interface: + using iterator = typename DomSetMapType::iterator; + using const_iterator = typename DomSetMapType::const_iterator; + + iterator begin() { return Frontiers.begin(); } + const_iterator begin() const { return Frontiers.begin(); } + iterator end() { return Frontiers.end(); } + const_iterator end() const { return Frontiers.end(); } + iterator find(BlockT *B) { return Frontiers.find(B); } + const_iterator find(BlockT *B) const { return Frontiers.find(B); } + + iterator addBasicBlock(BlockT *BB, const DomSetType &frontier) { + assert(find(BB) == end() && "Block already in DominanceFrontier!"); + return Frontiers.insert(std::make_pair(BB, frontier)).first; + } + + /// removeBlock - Remove basic block BB's frontier. + void removeBlock(BlockT *BB); + + void addToFrontier(iterator I, BlockT *Node); + + void removeFromFrontier(iterator I, BlockT *Node); + + /// compareDomSet - Return false if two domsets match. Otherwise + /// return true; + bool compareDomSet(DomSetType &DS1, const DomSetType &DS2) const; + + /// compare - Return true if the other dominance frontier base matches + /// this dominance frontier base. Otherwise return false. + bool compare(DominanceFrontierBase &Other) const; + + /// print - Convert to human readable form + /// + void print(raw_ostream &OS) const; + + /// dump - Dump the dominance frontier to dbgs(). +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) + void dump() const; +#endif +}; + +//===------------------------------------- +/// DominanceFrontier Class - Concrete subclass of DominanceFrontierBase that is +/// used to compute a forward dominator frontiers. +/// +template <class BlockT> +class ForwardDominanceFrontierBase + : public DominanceFrontierBase<BlockT, false> { +private: + using BlockTraits = GraphTraits<BlockT *>; + +public: + using DomTreeT = DomTreeBase<BlockT>; + using DomTreeNodeT = DomTreeNodeBase<BlockT>; + using DomSetType = typename DominanceFrontierBase<BlockT, false>::DomSetType; + + void analyze(DomTreeT &DT) { + assert(DT.getRoots().size() == 1 && + "Only one entry block for forward domfronts!"); + this->Roots = {DT.getRoot()}; + calculate(DT, DT[this->Roots[0]]); + } + + const DomSetType &calculate(const DomTreeT &DT, const DomTreeNodeT *Node); +}; + +class DominanceFrontier : public ForwardDominanceFrontierBase<BasicBlock> { +public: + using DomTreeT = DomTreeBase<BasicBlock>; + using DomTreeNodeT = DomTreeNodeBase<BasicBlock>; + using DomSetType = DominanceFrontierBase<BasicBlock, false>::DomSetType; + using iterator = DominanceFrontierBase<BasicBlock, false>::iterator; + using const_iterator = + DominanceFrontierBase<BasicBlock, false>::const_iterator; + + /// Handle invalidation explicitly. + bool invalidate(Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &); +}; + +class DominanceFrontierWrapperPass : public FunctionPass { + DominanceFrontier DF; + +public: + static char ID; // Pass ID, replacement for typeid + + DominanceFrontierWrapperPass(); + + DominanceFrontier &getDominanceFrontier() { return DF; } + const DominanceFrontier &getDominanceFrontier() const { return DF; } + + void releaseMemory() override; + + bool runOnFunction(Function &) override; + + void getAnalysisUsage(AnalysisUsage &AU) const override; + + void print(raw_ostream &OS, const Module * = nullptr) const override; + + void dump() const; +}; + +extern template class DominanceFrontierBase<BasicBlock, false>; +extern template class DominanceFrontierBase<BasicBlock, true>; +extern template class ForwardDominanceFrontierBase<BasicBlock>; + +/// Analysis pass which computes a \c DominanceFrontier. +class DominanceFrontierAnalysis + : public AnalysisInfoMixin<DominanceFrontierAnalysis> { + friend AnalysisInfoMixin<DominanceFrontierAnalysis>; + + static AnalysisKey Key; + +public: + /// Provide the result type for this analysis pass. + using Result = DominanceFrontier; + + /// Run the analysis pass over a function and produce a dominator tree. + DominanceFrontier run(Function &F, FunctionAnalysisManager &AM); +}; + +/// Printer pass for the \c DominanceFrontier. +class DominanceFrontierPrinterPass + : public PassInfoMixin<DominanceFrontierPrinterPass> { + raw_ostream &OS; + +public: + explicit DominanceFrontierPrinterPass(raw_ostream &OS); + + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_DOMINANCEFRONTIER_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/DominanceFrontierImpl.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/DominanceFrontierImpl.h new file mode 100644 index 0000000..aa764be --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/DominanceFrontierImpl.h
@@ -0,0 +1,231 @@ +//===- llvm/Analysis/DominanceFrontier.h - Dominator Frontiers --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This is the generic implementation of the DominanceFrontier class, which +// calculate and holds the dominance frontier for a function for. +// +// This should be considered deprecated, don't add any more uses of this data +// structure. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_DOMINANCEFRONTIERIMPL_H +#define LLVM_ANALYSIS_DOMINANCEFRONTIERIMPL_H + +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Analysis/DominanceFrontier.h" +#include "llvm/Config/llvm-config.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/GenericDomTree.h" +#include "llvm/Support/raw_ostream.h" +#include <cassert> +#include <set> +#include <utility> +#include <vector> + +namespace llvm { + +template <class BlockT> +class DFCalculateWorkObject { +public: + using DomTreeNodeT = DomTreeNodeBase<BlockT>; + + DFCalculateWorkObject(BlockT *B, BlockT *P, const DomTreeNodeT *N, + const DomTreeNodeT *PN) + : currentBB(B), parentBB(P), Node(N), parentNode(PN) {} + + BlockT *currentBB; + BlockT *parentBB; + const DomTreeNodeT *Node; + const DomTreeNodeT *parentNode; +}; + +template <class BlockT, bool IsPostDom> +void DominanceFrontierBase<BlockT, IsPostDom>::removeBlock(BlockT *BB) { + assert(find(BB) != end() && "Block is not in DominanceFrontier!"); + for (iterator I = begin(), E = end(); I != E; ++I) + I->second.erase(BB); + Frontiers.erase(BB); +} + +template <class BlockT, bool IsPostDom> +void DominanceFrontierBase<BlockT, IsPostDom>::addToFrontier(iterator I, + BlockT *Node) { + assert(I != end() && "BB is not in DominanceFrontier!"); + assert(I->second.count(Node) && "Node is not in DominanceFrontier of BB"); + I->second.erase(Node); +} + +template <class BlockT, bool IsPostDom> +void DominanceFrontierBase<BlockT, IsPostDom>::removeFromFrontier( + iterator I, BlockT *Node) { + assert(I != end() && "BB is not in DominanceFrontier!"); + assert(I->second.count(Node) && "Node is not in DominanceFrontier of BB"); + I->second.erase(Node); +} + +template <class BlockT, bool IsPostDom> +bool DominanceFrontierBase<BlockT, IsPostDom>::compareDomSet( + DomSetType &DS1, const DomSetType &DS2) const { + std::set<BlockT *> tmpSet; + for (BlockT *BB : DS2) + tmpSet.insert(BB); + + for (typename DomSetType::const_iterator I = DS1.begin(), E = DS1.end(); + I != E;) { + BlockT *Node = *I++; + + if (tmpSet.erase(Node) == 0) + // Node is in DS1 but tnot in DS2. + return true; + } + + if (!tmpSet.empty()) { + // There are nodes that are in DS2 but not in DS1. + return true; + } + + // DS1 and DS2 matches. + return false; +} + +template <class BlockT, bool IsPostDom> +bool DominanceFrontierBase<BlockT, IsPostDom>::compare( + DominanceFrontierBase<BlockT, IsPostDom> &Other) const { + DomSetMapType tmpFrontiers; + for (typename DomSetMapType::const_iterator I = Other.begin(), + E = Other.end(); + I != E; ++I) + tmpFrontiers.insert(std::make_pair(I->first, I->second)); + + for (typename DomSetMapType::iterator I = tmpFrontiers.begin(), + E = tmpFrontiers.end(); + I != E;) { + BlockT *Node = I->first; + const_iterator DFI = find(Node); + if (DFI == end()) + return true; + + if (compareDomSet(I->second, DFI->second)) + return true; + + ++I; + tmpFrontiers.erase(Node); + } + + if (!tmpFrontiers.empty()) + return true; + + return false; +} + +template <class BlockT, bool IsPostDom> +void DominanceFrontierBase<BlockT, IsPostDom>::print(raw_ostream &OS) const { + for (const_iterator I = begin(), E = end(); I != E; ++I) { + OS << " DomFrontier for BB "; + if (I->first) + I->first->printAsOperand(OS, false); + else + OS << " <<exit node>>"; + OS << " is:\t"; + + const std::set<BlockT *> &BBs = I->second; + + for (const BlockT *BB : BBs) { + OS << ' '; + if (BB) + BB->printAsOperand(OS, false); + else + OS << "<<exit node>>"; + } + OS << '\n'; + } +} + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +template <class BlockT, bool IsPostDom> +void DominanceFrontierBase<BlockT, IsPostDom>::dump() const { + print(dbgs()); +} +#endif + +template <class BlockT> +const typename ForwardDominanceFrontierBase<BlockT>::DomSetType & +ForwardDominanceFrontierBase<BlockT>::calculate(const DomTreeT &DT, + const DomTreeNodeT *Node) { + BlockT *BB = Node->getBlock(); + DomSetType *Result = nullptr; + + std::vector<DFCalculateWorkObject<BlockT>> workList; + SmallPtrSet<BlockT *, 32> visited; + + workList.push_back(DFCalculateWorkObject<BlockT>(BB, nullptr, Node, nullptr)); + do { + DFCalculateWorkObject<BlockT> *currentW = &workList.back(); + assert(currentW && "Missing work object."); + + BlockT *currentBB = currentW->currentBB; + BlockT *parentBB = currentW->parentBB; + const DomTreeNodeT *currentNode = currentW->Node; + const DomTreeNodeT *parentNode = currentW->parentNode; + assert(currentBB && "Invalid work object. Missing current Basic Block"); + assert(currentNode && "Invalid work object. Missing current Node"); + DomSetType &S = this->Frontiers[currentBB]; + + // Visit each block only once. + if (visited.insert(currentBB).second) { + // Loop over CFG successors to calculate DFlocal[currentNode] + for (const auto Succ : children<BlockT *>(currentBB)) { + // Does Node immediately dominate this successor? + if (DT[Succ]->getIDom() != currentNode) + S.insert(Succ); + } + } + + // At this point, S is DFlocal. Now we union in DFup's of our children... + // Loop through and visit the nodes that Node immediately dominates (Node's + // children in the IDomTree) + bool visitChild = false; + for (typename DomTreeNodeT::const_iterator NI = currentNode->begin(), + NE = currentNode->end(); + NI != NE; ++NI) { + DomTreeNodeT *IDominee = *NI; + BlockT *childBB = IDominee->getBlock(); + if (visited.count(childBB) == 0) { + workList.push_back(DFCalculateWorkObject<BlockT>( + childBB, currentBB, IDominee, currentNode)); + visitChild = true; + } + } + + // If all children are visited or there is any child then pop this block + // from the workList. + if (!visitChild) { + if (!parentBB) { + Result = &S; + break; + } + + typename DomSetType::const_iterator CDFI = S.begin(), CDFE = S.end(); + DomSetType &parentSet = this->Frontiers[parentBB]; + for (; CDFI != CDFE; ++CDFI) { + if (!DT.properlyDominates(parentNode, DT[*CDFI])) + parentSet.insert(*CDFI); + } + workList.pop_back(); + } + + } while (!workList.empty()); + + return *Result; +} + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_DOMINANCEFRONTIERIMPL_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/EHPersonalities.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/EHPersonalities.h new file mode 100644 index 0000000..d89aa11 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/EHPersonalities.h
@@ -0,0 +1,118 @@ +//===- EHPersonalities.h - Compute EH-related information -----------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_EHPERSONALITIES_H +#define LLVM_ANALYSIS_EHPERSONALITIES_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/TinyPtrVector.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/ErrorHandling.h" + +namespace llvm { +class BasicBlock; +class Function; +class Value; + +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, + Rust, + Wasm_CXX +}; + +/// See if the given exception handling personality function is one +/// that we understand. If so, return a description of it; otherwise return +/// Unknown. +EHPersonality classifyEHPersonality(const Value *Pers); + +StringRef getEHPersonalityName(EHPersonality Pers); + +EHPersonality getDefaultEHPersonality(const Triple &T); + +/// Returns true if this personality function catches asynchronous +/// exceptions. +inline bool isAsynchronousEHPersonality(EHPersonality Pers) { + // The two SEH personality functions can catch asynch exceptions. We assume + // unknown personalities don't catch asynch exceptions. + switch (Pers) { + case EHPersonality::MSVC_X86SEH: + case EHPersonality::MSVC_Win64SEH: + return true; + default: + return false; + } + llvm_unreachable("invalid enum"); +} + +/// Returns true if this is a personality function that invokes +/// handler funclets (which must return to it). +inline bool isFuncletEHPersonality(EHPersonality Pers) { + switch (Pers) { + case EHPersonality::MSVC_CXX: + case EHPersonality::MSVC_X86SEH: + case EHPersonality::MSVC_Win64SEH: + case EHPersonality::CoreCLR: + return true; + default: + return false; + } + llvm_unreachable("invalid enum"); +} + +/// Returns true if this personality uses scope-style EH IR instructions: +/// catchswitch, catchpad/ret, and cleanuppad/ret. +inline bool isScopedEHPersonality(EHPersonality Pers) { + switch (Pers) { + case EHPersonality::MSVC_CXX: + case EHPersonality::MSVC_X86SEH: + case EHPersonality::MSVC_Win64SEH: + case EHPersonality::CoreCLR: + case EHPersonality::Wasm_CXX: + return true; + default: + return false; + } + llvm_unreachable("invalid enum"); +} + +/// Return true if this personality may be safely removed if there +/// are no invoke instructions remaining in the current function. +inline bool isNoOpWithoutInvoke(EHPersonality Pers) { + switch (Pers) { + case EHPersonality::Unknown: + return false; + // All known personalities currently have this behavior + default: + return true; + } + llvm_unreachable("invalid enum"); +} + +bool canSimplifyInvokeNoUnwind(const Function *F); + +typedef TinyPtrVector<BasicBlock *> ColorVector; + +/// If an EH funclet personality is in use (see isFuncletEHPersonality), +/// this will recompute which blocks are in which funclet. It is possible that +/// some blocks are in multiple funclets. Consider this analysis to be +/// expensive. +DenseMap<BasicBlock *, ColorVector> colorEHFunclets(Function &F); + +} // end namespace llvm + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/GlobalsModRef.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/GlobalsModRef.h new file mode 100644 index 0000000..fa5b16c --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/GlobalsModRef.h
@@ -0,0 +1,164 @@ +//===- GlobalsModRef.h - Simple Mod/Ref AA for Globals ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// \file +/// This is the interface for a simple mod/ref and alias analysis over globals. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_GLOBALSMODREF_H +#define LLVM_ANALYSIS_GLOBALSMODREF_H + +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/CallGraph.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/Pass.h" +#include <list> + +namespace llvm { + +/// An alias analysis result set for globals. +/// +/// This focuses on handling aliasing properties of globals and interprocedural +/// function call mod/ref information. +class GlobalsAAResult : public AAResultBase<GlobalsAAResult> { + friend AAResultBase<GlobalsAAResult>; + + class FunctionInfo; + + const DataLayout &DL; + std::function<const TargetLibraryInfo &(Function &F)> GetTLI; + + /// The globals that do not have their addresses taken. + SmallPtrSet<const GlobalValue *, 8> NonAddressTakenGlobals; + + /// Are there functions with local linkage that may modify globals. + bool UnknownFunctionsWithLocalLinkage = false; + + /// IndirectGlobals - The memory pointed to by this global is known to be + /// 'owned' by the global. + SmallPtrSet<const GlobalValue *, 8> IndirectGlobals; + + /// AllocsForIndirectGlobals - If an instruction allocates memory for an + /// indirect global, this map indicates which one. + DenseMap<const Value *, const GlobalValue *> AllocsForIndirectGlobals; + + /// For each function, keep track of what globals are modified or read. + DenseMap<const Function *, FunctionInfo> FunctionInfos; + + /// A map of functions to SCC. The SCCs are described by a simple integer + /// ID that is only useful for comparing for equality (are two functions + /// in the same SCC or not?) + DenseMap<const Function *, unsigned> FunctionToSCCMap; + + /// Handle to clear this analysis on deletion of values. + struct DeletionCallbackHandle final : CallbackVH { + GlobalsAAResult *GAR; + std::list<DeletionCallbackHandle>::iterator I; + + DeletionCallbackHandle(GlobalsAAResult &GAR, Value *V) + : CallbackVH(V), GAR(&GAR) {} + + void deleted() override; + }; + + /// List of callbacks for globals being tracked by this analysis. Note that + /// these objects are quite large, but we only anticipate having one per + /// global tracked by this analysis. There are numerous optimizations we + /// could perform to the memory utilization here if this becomes a problem. + std::list<DeletionCallbackHandle> Handles; + + explicit GlobalsAAResult( + const DataLayout &DL, + std::function<const TargetLibraryInfo &(Function &F)> GetTLI); + +public: + GlobalsAAResult(GlobalsAAResult &&Arg); + ~GlobalsAAResult(); + + static GlobalsAAResult + analyzeModule(Module &M, + std::function<const TargetLibraryInfo &(Function &F)> GetTLI, + CallGraph &CG); + + //------------------------------------------------ + // Implement the AliasAnalysis API + // + AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB, + AAQueryInfo &AAQI); + + using AAResultBase::getModRefInfo; + ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc, + AAQueryInfo &AAQI); + + /// getModRefBehavior - Return the behavior of the specified function if + /// called from the specified call site. The call site may be null in which + /// case the most generic behavior of this function should be returned. + FunctionModRefBehavior getModRefBehavior(const Function *F); + + /// getModRefBehavior - Return the behavior of the specified function if + /// called from the specified call site. The call site may be null in which + /// case the most generic behavior of this function should be returned. + FunctionModRefBehavior getModRefBehavior(const CallBase *Call); + +private: + FunctionInfo *getFunctionInfo(const Function *F); + + void AnalyzeGlobals(Module &M); + void AnalyzeCallGraph(CallGraph &CG, Module &M); + bool AnalyzeUsesOfPointer(Value *V, + SmallPtrSetImpl<Function *> *Readers = nullptr, + SmallPtrSetImpl<Function *> *Writers = nullptr, + GlobalValue *OkayStoreDest = nullptr); + bool AnalyzeIndirectGlobalMemory(GlobalVariable *GV); + void CollectSCCMembership(CallGraph &CG); + + bool isNonEscapingGlobalNoAlias(const GlobalValue *GV, const Value *V); + ModRefInfo getModRefInfoForArgument(const CallBase *Call, + const GlobalValue *GV, AAQueryInfo &AAQI); +}; + +/// Analysis pass providing a never-invalidated alias analysis result. +class GlobalsAA : public AnalysisInfoMixin<GlobalsAA> { + friend AnalysisInfoMixin<GlobalsAA>; + static AnalysisKey Key; + +public: + typedef GlobalsAAResult Result; + + GlobalsAAResult run(Module &M, ModuleAnalysisManager &AM); +}; + +/// Legacy wrapper pass to provide the GlobalsAAResult object. +class GlobalsAAWrapperPass : public ModulePass { + std::unique_ptr<GlobalsAAResult> Result; + +public: + static char ID; + + GlobalsAAWrapperPass(); + + GlobalsAAResult &getResult() { return *Result; } + const GlobalsAAResult &getResult() const { return *Result; } + + bool runOnModule(Module &M) override; + bool doFinalization(Module &M) override; + void getAnalysisUsage(AnalysisUsage &AU) const override; +}; + +//===--------------------------------------------------------------------===// +// +// createGlobalsAAWrapperPass - This pass provides alias and mod/ref info for +// global values that do not have their addresses taken. +// +ModulePass *createGlobalsAAWrapperPass(); +} + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/GuardUtils.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/GuardUtils.h new file mode 100644 index 0000000..b832115 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/GuardUtils.h
@@ -0,0 +1,54 @@ +//===-- GuardUtils.h - Utils for work with guards ---------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Utils that are used to perform analyzes related to guards and their +// conditions. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_GUARDUTILS_H +#define LLVM_ANALYSIS_GUARDUTILS_H + +namespace llvm { + +class BasicBlock; +class Use; +class User; +class Value; + +/// Returns true iff \p U has semantics of a guard expressed in a form of call +/// of llvm.experimental.guard intrinsic. +bool isGuard(const User *U); + +/// Returns true iff \p U is a widenable branch (that is, parseWidenableBranch +/// returns true). +bool isWidenableBranch(const User *U); + +/// Returns true iff \p U has semantics of a guard expressed in a form of a +/// widenable conditional branch to deopt block. +bool isGuardAsWidenableBranch(const User *U); + +/// If U is widenable branch looking like: +/// %cond = ... +/// %wc = call i1 @llvm.experimental.widenable.condition() +/// %branch_cond = and i1 %cond, %wc +/// br i1 %branch_cond, label %if_true_bb, label %if_false_bb ; <--- U +/// The function returns true, and the values %cond and %wc and blocks +/// %if_true_bb, if_false_bb are returned in +/// the parameters (Condition, WidenableCondition, IfTrueBB and IfFalseFF) +/// respectively. If \p U does not match this pattern, return false. +bool parseWidenableBranch(const User *U, Value *&Condition, + Value *&WidenableCondition, BasicBlock *&IfTrueBB, + BasicBlock *&IfFalseBB); + +/// Analgous to the above, but return the Uses so that that they can be +/// modified. Unlike previous version, Condition is optional and may be null. +bool parseWidenableBranch(User *U, Use *&Cond, Use *&WC, BasicBlock *&IfTrueBB, + BasicBlock *&IfFalseBB); + +} // llvm + +#endif // LLVM_ANALYSIS_GUARDUTILS_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/IVDescriptors.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/IVDescriptors.h new file mode 100644 index 0000000..7be1fd3 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/IVDescriptors.h
@@ -0,0 +1,367 @@ +//===- llvm/Analysis/IVDescriptors.h - IndVar Descriptors -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file "describes" induction and recurrence variables. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_IVDESCRIPTORS_H +#define LLVM_ANALYSIS_IVDESCRIPTORS_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/DemandedBits.h" +#include "llvm/Analysis/EHPersonalities.h" +#include "llvm/Analysis/MustExecute.h" +#include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/IR/Dominators.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Operator.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/Support/Casting.h" + +namespace llvm { + +class AliasSet; +class AliasSetTracker; +class BasicBlock; +class DataLayout; +class Loop; +class LoopInfo; +class OptimizationRemarkEmitter; +class PredicatedScalarEvolution; +class PredIteratorCache; +class ScalarEvolution; +class SCEV; +class TargetLibraryInfo; +class TargetTransformInfo; + +/// The RecurrenceDescriptor is used to identify recurrences variables in a +/// loop. Reduction is a special case of recurrence that has uses of the +/// recurrence variable outside the loop. The method isReductionPHI identifies +/// reductions that are basic recurrences. +/// +/// Basic recurrences are defined as the summation, product, OR, AND, XOR, min, +/// or max of a set of terms. For example: for(i=0; i<n; i++) { total += +/// array[i]; } is a summation of array elements. Basic recurrences are a +/// special case of chains of recurrences (CR). See ScalarEvolution for CR +/// references. + +/// This struct holds information about recurrence variables. +class RecurrenceDescriptor { +public: + /// This enum represents the kinds of recurrences that we support. + enum RecurrenceKind { + RK_NoRecurrence, ///< Not a recurrence. + RK_IntegerAdd, ///< Sum of integers. + RK_IntegerMult, ///< Product of integers. + RK_IntegerOr, ///< Bitwise or logical OR of numbers. + RK_IntegerAnd, ///< Bitwise or logical AND of numbers. + RK_IntegerXor, ///< Bitwise or logical XOR of numbers. + RK_IntegerMinMax, ///< Min/max implemented in terms of select(cmp()). + RK_FloatAdd, ///< Sum of floats. + RK_FloatMult, ///< Product of floats. + RK_FloatMinMax ///< Min/max implemented in terms of select(cmp()). + }; + + // This enum represents the kind of minmax recurrence. + enum MinMaxRecurrenceKind { + MRK_Invalid, + MRK_UIntMin, + MRK_UIntMax, + MRK_SIntMin, + MRK_SIntMax, + MRK_FloatMin, + MRK_FloatMax + }; + + RecurrenceDescriptor() = default; + + RecurrenceDescriptor(Value *Start, Instruction *Exit, RecurrenceKind K, + FastMathFlags FMF, MinMaxRecurrenceKind MK, + Instruction *UAI, Type *RT, bool Signed, + SmallPtrSetImpl<Instruction *> &CI) + : StartValue(Start), LoopExitInstr(Exit), Kind(K), FMF(FMF), + MinMaxKind(MK), UnsafeAlgebraInst(UAI), RecurrenceType(RT), + IsSigned(Signed) { + CastInsts.insert(CI.begin(), CI.end()); + } + + /// This POD struct holds information about a potential recurrence operation. + class InstDesc { + public: + InstDesc(bool IsRecur, Instruction *I, Instruction *UAI = nullptr) + : IsRecurrence(IsRecur), PatternLastInst(I), MinMaxKind(MRK_Invalid), + UnsafeAlgebraInst(UAI) {} + + InstDesc(Instruction *I, MinMaxRecurrenceKind K, Instruction *UAI = nullptr) + : IsRecurrence(true), PatternLastInst(I), MinMaxKind(K), + UnsafeAlgebraInst(UAI) {} + + bool isRecurrence() { return IsRecurrence; } + + bool hasUnsafeAlgebra() { return UnsafeAlgebraInst != nullptr; } + + Instruction *getUnsafeAlgebraInst() { return UnsafeAlgebraInst; } + + MinMaxRecurrenceKind getMinMaxKind() { return MinMaxKind; } + + Instruction *getPatternInst() { return PatternLastInst; } + + private: + // Is this instruction a recurrence candidate. + bool IsRecurrence; + // The last instruction in a min/max pattern (select of the select(icmp()) + // pattern), or the current recurrence instruction otherwise. + Instruction *PatternLastInst; + // If this is a min/max pattern the comparison predicate. + MinMaxRecurrenceKind MinMaxKind; + // Recurrence has unsafe algebra. + Instruction *UnsafeAlgebraInst; + }; + + /// Returns a struct describing if the instruction 'I' can be a recurrence + /// variable of type 'Kind'. If the recurrence is a min/max pattern of + /// select(icmp()) this function advances the instruction pointer 'I' from the + /// compare instruction to the select instruction and stores this pointer in + /// 'PatternLastInst' member of the returned struct. + static InstDesc isRecurrenceInstr(Instruction *I, RecurrenceKind Kind, + InstDesc &Prev, bool HasFunNoNaNAttr); + + /// Returns true if instruction I has multiple uses in Insts + static bool hasMultipleUsesOf(Instruction *I, + SmallPtrSetImpl<Instruction *> &Insts, + unsigned MaxNumUses); + + /// Returns true if all uses of the instruction I is within the Set. + static bool areAllUsesIn(Instruction *I, SmallPtrSetImpl<Instruction *> &Set); + + /// Returns a struct describing if the instruction if the instruction is a + /// Select(ICmp(X, Y), X, Y) instruction pattern corresponding to a min(X, Y) + /// or max(X, Y). + static InstDesc isMinMaxSelectCmpPattern(Instruction *I, InstDesc &Prev); + + /// Returns a struct describing if the instruction is a + /// Select(FCmp(X, Y), (Z = X op PHINode), PHINode) instruction pattern. + static InstDesc isConditionalRdxPattern(RecurrenceKind Kind, Instruction *I); + + /// Returns identity corresponding to the RecurrenceKind. + static Constant *getRecurrenceIdentity(RecurrenceKind K, Type *Tp); + + /// Returns the opcode of binary operation corresponding to the + /// RecurrenceKind. + static unsigned getRecurrenceBinOp(RecurrenceKind Kind); + + /// Returns true if Phi is a reduction of type Kind and adds it to the + /// RecurrenceDescriptor. If either \p DB is non-null or \p AC and \p DT are + /// non-null, the minimal bit width needed to compute the reduction will be + /// computed. + static bool AddReductionVar(PHINode *Phi, RecurrenceKind Kind, Loop *TheLoop, + bool HasFunNoNaNAttr, + RecurrenceDescriptor &RedDes, + DemandedBits *DB = nullptr, + AssumptionCache *AC = nullptr, + DominatorTree *DT = nullptr); + + /// Returns true if Phi is a reduction in TheLoop. The RecurrenceDescriptor + /// is returned in RedDes. If either \p DB is non-null or \p AC and \p DT are + /// non-null, the minimal bit width needed to compute the reduction will be + /// computed. + static bool isReductionPHI(PHINode *Phi, Loop *TheLoop, + RecurrenceDescriptor &RedDes, + DemandedBits *DB = nullptr, + AssumptionCache *AC = nullptr, + DominatorTree *DT = nullptr); + + /// Returns true if Phi is a first-order recurrence. A first-order recurrence + /// is a non-reduction recurrence relation in which the value of the + /// recurrence in the current loop iteration equals a value defined in the + /// previous iteration. \p SinkAfter includes pairs of instructions where the + /// first will be rescheduled to appear after the second if/when the loop is + /// vectorized. It may be augmented with additional pairs if needed in order + /// to handle Phi as a first-order recurrence. + static bool + isFirstOrderRecurrence(PHINode *Phi, Loop *TheLoop, + DenseMap<Instruction *, Instruction *> &SinkAfter, + DominatorTree *DT); + + RecurrenceKind getRecurrenceKind() { return Kind; } + + MinMaxRecurrenceKind getMinMaxRecurrenceKind() { return MinMaxKind; } + + FastMathFlags getFastMathFlags() { return FMF; } + + TrackingVH<Value> getRecurrenceStartValue() { return StartValue; } + + Instruction *getLoopExitInstr() { return LoopExitInstr; } + + /// Returns true if the recurrence has unsafe algebra which requires a relaxed + /// floating-point model. + bool hasUnsafeAlgebra() { return UnsafeAlgebraInst != nullptr; } + + /// Returns first unsafe algebra instruction in the PHI node's use-chain. + Instruction *getUnsafeAlgebraInst() { return UnsafeAlgebraInst; } + + /// Returns true if the recurrence kind is an integer kind. + static bool isIntegerRecurrenceKind(RecurrenceKind Kind); + + /// Returns true if the recurrence kind is a floating point kind. + static bool isFloatingPointRecurrenceKind(RecurrenceKind Kind); + + /// Returns true if the recurrence kind is an arithmetic kind. + static bool isArithmeticRecurrenceKind(RecurrenceKind Kind); + + /// Returns the type of the recurrence. This type can be narrower than the + /// actual type of the Phi if the recurrence has been type-promoted. + Type *getRecurrenceType() { return RecurrenceType; } + + /// Returns a reference to the instructions used for type-promoting the + /// recurrence. + SmallPtrSet<Instruction *, 8> &getCastInsts() { return CastInsts; } + + /// Returns true if all source operands of the recurrence are SExtInsts. + bool isSigned() { return IsSigned; } + +private: + // The starting value of the recurrence. + // It does not have to be zero! + TrackingVH<Value> StartValue; + // The instruction who's value is used outside the loop. + Instruction *LoopExitInstr = nullptr; + // The kind of the recurrence. + RecurrenceKind Kind = RK_NoRecurrence; + // The fast-math flags on the recurrent instructions. We propagate these + // fast-math flags into the vectorized FP instructions we generate. + FastMathFlags FMF; + // If this a min/max recurrence the kind of recurrence. + MinMaxRecurrenceKind MinMaxKind = MRK_Invalid; + // First occurrence of unasfe algebra in the PHI's use-chain. + Instruction *UnsafeAlgebraInst = nullptr; + // The type of the recurrence. + Type *RecurrenceType = nullptr; + // True if all source operands of the recurrence are SExtInsts. + bool IsSigned = false; + // Instructions used for type-promoting the recurrence. + SmallPtrSet<Instruction *, 8> CastInsts; +}; + +/// A struct for saving information about induction variables. +class InductionDescriptor { +public: + /// This enum represents the kinds of inductions that we support. + enum InductionKind { + IK_NoInduction, ///< Not an induction variable. + IK_IntInduction, ///< Integer induction variable. Step = C. + IK_PtrInduction, ///< Pointer induction var. Step = C / sizeof(elem). + IK_FpInduction ///< Floating point induction variable. + }; + +public: + /// Default constructor - creates an invalid induction. + InductionDescriptor() = default; + + /// Get the consecutive direction. Returns: + /// 0 - unknown or non-consecutive. + /// 1 - consecutive and increasing. + /// -1 - consecutive and decreasing. + int getConsecutiveDirection() const; + + Value *getStartValue() const { return StartValue; } + InductionKind getKind() const { return IK; } + const SCEV *getStep() const { return Step; } + BinaryOperator *getInductionBinOp() const { return InductionBinOp; } + ConstantInt *getConstIntStepValue() const; + + /// Returns true if \p Phi is an induction in the loop \p L. If \p Phi is an + /// induction, the induction descriptor \p D will contain the data describing + /// this induction. If by some other means the caller has a better SCEV + /// expression for \p Phi than the one returned by the ScalarEvolution + /// analysis, it can be passed through \p Expr. If the def-use chain + /// associated with the phi includes casts (that we know we can ignore + /// under proper runtime checks), they are passed through \p CastsToIgnore. + static bool + isInductionPHI(PHINode *Phi, const Loop *L, ScalarEvolution *SE, + InductionDescriptor &D, const SCEV *Expr = nullptr, + SmallVectorImpl<Instruction *> *CastsToIgnore = nullptr); + + /// Returns true if \p Phi is a floating point induction in the loop \p L. + /// If \p Phi is an induction, the induction descriptor \p D will contain + /// the data describing this induction. + static bool isFPInductionPHI(PHINode *Phi, const Loop *L, ScalarEvolution *SE, + InductionDescriptor &D); + + /// Returns true if \p Phi is a loop \p L induction, in the context associated + /// with the run-time predicate of PSE. If \p Assume is true, this can add + /// further SCEV predicates to \p PSE in order to prove that \p Phi is an + /// induction. + /// If \p Phi is an induction, \p D will contain the data describing this + /// induction. + static bool isInductionPHI(PHINode *Phi, const Loop *L, + PredicatedScalarEvolution &PSE, + InductionDescriptor &D, bool Assume = false); + + /// Returns true if the induction type is FP and the binary operator does + /// not have the "fast-math" property. Such operation requires a relaxed FP + /// mode. + bool hasUnsafeAlgebra() { + return (IK == IK_FpInduction) && InductionBinOp && + !cast<FPMathOperator>(InductionBinOp)->isFast(); + } + + /// Returns induction operator that does not have "fast-math" property + /// and requires FP unsafe mode. + Instruction *getUnsafeAlgebraInst() { + if (IK != IK_FpInduction) + return nullptr; + + if (!InductionBinOp || cast<FPMathOperator>(InductionBinOp)->isFast()) + return nullptr; + return InductionBinOp; + } + + /// Returns binary opcode of the induction operator. + Instruction::BinaryOps getInductionOpcode() const { + return InductionBinOp ? InductionBinOp->getOpcode() + : Instruction::BinaryOpsEnd; + } + + /// Returns a reference to the type cast instructions in the induction + /// update chain, that are redundant when guarded with a runtime + /// SCEV overflow check. + const SmallVectorImpl<Instruction *> &getCastInsts() const { + return RedundantCasts; + } + +private: + /// Private constructor - used by \c isInductionPHI. + InductionDescriptor(Value *Start, InductionKind K, const SCEV *Step, + BinaryOperator *InductionBinOp = nullptr, + SmallVectorImpl<Instruction *> *Casts = nullptr); + + /// Start value. + TrackingVH<Value> StartValue; + /// Induction kind. + InductionKind IK = IK_NoInduction; + /// Step value. + const SCEV *Step = nullptr; + // Instruction that advances induction variable. + BinaryOperator *InductionBinOp = nullptr; + // Instructions used for type-casts of the induction variable, + // that are redundant when guarded with a runtime SCEV overflow check. + SmallVector<Instruction *, 2> RedundantCasts; +}; + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_IVDESCRIPTORS_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/IVUsers.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/IVUsers.h new file mode 100644 index 0000000..f8ea3bc --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/IVUsers.h
@@ -0,0 +1,201 @@ +//===- llvm/Analysis/IVUsers.h - Induction Variable Users -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements bookkeeping for "interesting" users of expressions +// computed from induction variables. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_IVUSERS_H +#define LLVM_ANALYSIS_IVUSERS_H + +#include "llvm/Analysis/LoopAnalysisManager.h" +#include "llvm/Analysis/LoopPass.h" +#include "llvm/Analysis/ScalarEvolutionNormalization.h" +#include "llvm/IR/ValueHandle.h" + +namespace llvm { + +class AssumptionCache; +class DominatorTree; +class Instruction; +class Value; +class ScalarEvolution; +class SCEV; +class IVUsers; +class DataLayout; + +/// IVStrideUse - Keep track of one use of a strided induction variable. +/// The Expr member keeps track of the expression, User is the actual user +/// instruction of the operand, and 'OperandValToReplace' is the operand of +/// the User that is the use. +class IVStrideUse final : public CallbackVH, public ilist_node<IVStrideUse> { + friend class IVUsers; +public: + IVStrideUse(IVUsers *P, Instruction* U, Value *O) + : CallbackVH(U), Parent(P), OperandValToReplace(O) { + } + + /// getUser - Return the user instruction for this use. + Instruction *getUser() const { + return cast<Instruction>(getValPtr()); + } + + /// setUser - Assign a new user instruction for this use. + void setUser(Instruction *NewUser) { + setValPtr(NewUser); + } + + /// getOperandValToReplace - Return the Value of the operand in the user + /// instruction that this IVStrideUse is representing. + Value *getOperandValToReplace() const { + return OperandValToReplace; + } + + /// setOperandValToReplace - Assign a new Value as the operand value + /// to replace. + void setOperandValToReplace(Value *Op) { + OperandValToReplace = Op; + } + + /// getPostIncLoops - Return the set of loops for which the expression has + /// been adjusted to use post-inc mode. + const PostIncLoopSet &getPostIncLoops() const { + return PostIncLoops; + } + + /// transformToPostInc - Transform the expression to post-inc form for the + /// given loop. + void transformToPostInc(const Loop *L); + +private: + /// Parent - a pointer to the IVUsers that owns this IVStrideUse. + IVUsers *Parent; + + /// OperandValToReplace - The Value of the operand in the user instruction + /// that this IVStrideUse is representing. + WeakTrackingVH OperandValToReplace; + + /// PostIncLoops - The set of loops for which Expr has been adjusted to + /// use post-inc mode. This corresponds with SCEVExpander's post-inc concept. + PostIncLoopSet PostIncLoops; + + /// Deleted - Implementation of CallbackVH virtual function to + /// receive notification when the User is deleted. + void deleted() override; +}; + +class IVUsers { + friend class IVStrideUse; + Loop *L; + AssumptionCache *AC; + LoopInfo *LI; + DominatorTree *DT; + ScalarEvolution *SE; + SmallPtrSet<Instruction*, 16> Processed; + + /// IVUses - A list of all tracked IV uses of induction variable expressions + /// we are interested in. + ilist<IVStrideUse> IVUses; + + // Ephemeral values used by @llvm.assume in this function. + SmallPtrSet<const Value *, 32> EphValues; + +public: + IVUsers(Loop *L, AssumptionCache *AC, LoopInfo *LI, DominatorTree *DT, + ScalarEvolution *SE); + + IVUsers(IVUsers &&X) + : L(std::move(X.L)), AC(std::move(X.AC)), DT(std::move(X.DT)), + SE(std::move(X.SE)), Processed(std::move(X.Processed)), + IVUses(std::move(X.IVUses)), EphValues(std::move(X.EphValues)) { + for (IVStrideUse &U : IVUses) + U.Parent = this; + } + IVUsers(const IVUsers &) = delete; + IVUsers &operator=(IVUsers &&) = delete; + IVUsers &operator=(const IVUsers &) = delete; + + Loop *getLoop() const { return L; } + + /// AddUsersIfInteresting - Inspect the specified Instruction. If it is a + /// reducible SCEV, recursively add its users to the IVUsesByStride set and + /// return true. Otherwise, return false. + bool AddUsersIfInteresting(Instruction *I); + + IVStrideUse &AddUser(Instruction *User, Value *Operand); + + /// getReplacementExpr - Return a SCEV expression which computes the + /// value of the OperandValToReplace of the given IVStrideUse. + const SCEV *getReplacementExpr(const IVStrideUse &IU) const; + + /// getExpr - Return the expression for the use. + const SCEV *getExpr(const IVStrideUse &IU) const; + + const SCEV *getStride(const IVStrideUse &IU, const Loop *L) const; + + typedef ilist<IVStrideUse>::iterator iterator; + typedef ilist<IVStrideUse>::const_iterator const_iterator; + iterator begin() { return IVUses.begin(); } + iterator end() { return IVUses.end(); } + const_iterator begin() const { return IVUses.begin(); } + const_iterator end() const { return IVUses.end(); } + bool empty() const { return IVUses.empty(); } + + bool isIVUserOrOperand(Instruction *Inst) const { + return Processed.count(Inst); + } + + 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 AnalysisKey Key; + +public: + typedef IVUsers Result; + + IVUsers run(Loop &L, LoopAnalysisManager &AM, + LoopStandardAnalysisResults &AR); +}; + +} + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/IndirectCallPromotionAnalysis.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/IndirectCallPromotionAnalysis.h new file mode 100644 index 0000000..8a05e91 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/IndirectCallPromotionAnalysis.h
@@ -0,0 +1,68 @@ +//===- IndirectCallPromotionAnalysis.h - Indirect call analysis -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// \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. + // TotalCount is the total call count for the indirect-call callsite. + // RemainingCount is the TotalCount minus promoted-direct-call count. + // Return true we should promote this indirect-call target. + bool isPromotionProfitable(uint64_t Count, uint64_t TotalCount, + uint64_t RemainingCount); + + // 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(); + + /// 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
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/IndirectCallVisitor.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/IndirectCallVisitor.h new file mode 100644 index 0000000..1d1f3f4 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/IndirectCallVisitor.h
@@ -0,0 +1,38 @@ +//===-- IndirectCallVisitor.h - indirect call visitor ---------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements defines a visitor class and a helper function that find +// all indirect call-sites in a function. + +#ifndef LLVM_ANALYSIS_INDIRECTCALLVISITOR_H +#define LLVM_ANALYSIS_INDIRECTCALLVISITOR_H + +#include "llvm/IR/InstVisitor.h" +#include <vector> + +namespace llvm { +// Visitor class that finds all indirect call. +struct PGOIndirectCallVisitor : public InstVisitor<PGOIndirectCallVisitor> { + std::vector<Instruction *> IndirectCalls; + PGOIndirectCallVisitor() {} + + void visitCallBase(CallBase &Call) { + if (Call.isIndirectCall()) + IndirectCalls.push_back(&Call); + } +}; + +// Helper function that finds all indirect call sites. +inline std::vector<Instruction *> findIndirectCalls(Function &F) { + PGOIndirectCallVisitor ICV; + ICV.visit(F); + return ICV.IndirectCalls; +} +} // namespace llvm + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/InlineCost.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/InlineCost.h new file mode 100644 index 0000000..611c9de --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/InlineCost.h
@@ -0,0 +1,237 @@ +//===- InlineCost.h - Cost analysis for inliner -----------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements heuristics for inlining decisions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_INLINECOST_H +#define LLVM_ANALYSIS_INLINECOST_H + +#include "llvm/Analysis/AssumptionCache.h" +#include "llvm/Analysis/CallGraphSCCPass.h" +#include "llvm/Analysis/OptimizationRemarkEmitter.h" +#include <cassert> +#include <climits> + +namespace llvm { +class AssumptionCacheTracker; +class BlockFrequencyInfo; +class CallBase; +class DataLayout; +class Function; +class ProfileSummaryInfo; +class TargetTransformInfo; + +namespace InlineConstants { +// Various thresholds used by inline cost analysis. +/// Use when optsize (-Os) is specified. +const int OptSizeThreshold = 50; + +/// Use when minsize (-Oz) is specified. +const int OptMinSizeThreshold = 5; + +/// Use when -O3 is specified. +const int OptAggressiveThreshold = 250; + +// Various magic constants used to adjust heuristics. +const int InstrCost = 5; +const int IndirectCallThreshold = 100; +const int CallPenalty = 25; +const int LastCallToStaticBonus = 15000; +const int ColdccPenalty = 2000; +/// Do not inline functions which allocate this many bytes on the stack +/// when the caller is recursive. +const unsigned TotalAllocaSizeRecursiveCaller = 1024; +} + +/// Represents the cost of inlining a function. +/// +/// This supports special values for functions which should "always" or +/// "never" be inlined. Otherwise, the cost represents a unitless amount; +/// smaller values increase the likelihood of the function being inlined. +/// +/// Objects of this type also provide the adjusted threshold for inlining +/// based on the information available for a particular callsite. They can be +/// directly tested to determine if inlining should occur given the cost and +/// threshold for this cost metric. +class InlineCost { + enum SentinelValues { + AlwaysInlineCost = INT_MIN, + NeverInlineCost = INT_MAX + }; + + /// The estimated cost of inlining this callsite. + int Cost; + + /// The adjusted threshold against which this cost was computed. + int Threshold; + + /// Must be set for Always and Never instances. + const char *Reason = nullptr; + + // Trivial constructor, interesting logic in the factory functions below. + InlineCost(int Cost, int Threshold, const char *Reason = nullptr) + : Cost(Cost), Threshold(Threshold), Reason(Reason) { + assert((isVariable() || Reason) && + "Reason must be provided for Never or Always"); + } + +public: + static InlineCost get(int Cost, int Threshold) { + assert(Cost > AlwaysInlineCost && "Cost crosses sentinel value"); + assert(Cost < NeverInlineCost && "Cost crosses sentinel value"); + return InlineCost(Cost, Threshold); + } + static InlineCost getAlways(const char *Reason) { + return InlineCost(AlwaysInlineCost, 0, Reason); + } + static InlineCost getNever(const char *Reason) { + return InlineCost(NeverInlineCost, 0, Reason); + } + + /// Test whether the inline cost is low enough for inlining. + explicit operator bool() const { + return Cost < Threshold; + } + + bool isAlways() const { return Cost == AlwaysInlineCost; } + bool isNever() const { return Cost == NeverInlineCost; } + bool isVariable() const { return !isAlways() && !isNever(); } + + /// Get the inline cost estimate. + /// It is an error to call this on an "always" or "never" InlineCost. + int getCost() const { + assert(isVariable() && "Invalid access of InlineCost"); + return Cost; + } + + /// Get the threshold against which the cost was computed + int getThreshold() const { + assert(isVariable() && "Invalid access of InlineCost"); + return Threshold; + } + + /// Get the reason of Always or Never. + const char *getReason() const { + assert((Reason || isVariable()) && + "InlineCost reason must be set for Always or Never"); + return Reason; + } + + /// Get the cost delta from the threshold for inlining. + /// Only valid if the cost is of the variable kind. Returns a negative + /// value if the cost is too high to inline. + int getCostDelta() const { return Threshold - getCost(); } +}; + +/// InlineResult is basically true or false. For false results the message +/// describes a reason why it is decided not to inline. +struct InlineResult { + const char *message = nullptr; + InlineResult(bool result, const char *message = nullptr) + : message(result ? nullptr : (message ? message : "cost > threshold")) {} + InlineResult(const char *message = nullptr) : message(message) {} + operator bool() const { return !message; } + operator const char *() const { return message; } +}; + +/// Thresholds to tune inline cost analysis. The inline cost analysis decides +/// the condition to apply a threshold and applies it. Otherwise, +/// DefaultThreshold is used. If a threshold is Optional, it is applied only +/// when it has a valid value. Typically, users of inline cost analysis +/// obtain an InlineParams object through one of the \c getInlineParams methods +/// and pass it to \c getInlineCost. Some specialized versions of inliner +/// (such as the pre-inliner) might have custom logic to compute \c InlineParams +/// object. + +struct InlineParams { + /// The default threshold to start with for a callee. + int DefaultThreshold; + + /// Threshold to use for callees with inline hint. + Optional<int> HintThreshold; + + /// Threshold to use for cold callees. + Optional<int> ColdThreshold; + + /// Threshold to use when the caller is optimized for size. + Optional<int> OptSizeThreshold; + + /// Threshold to use when the caller is optimized for minsize. + Optional<int> OptMinSizeThreshold; + + /// Threshold to use when the callsite is considered hot. + Optional<int> HotCallSiteThreshold; + + /// Threshold to use when the callsite is considered hot relative to function + /// entry. + Optional<int> LocallyHotCallSiteThreshold; + + /// Threshold to use when the callsite is considered cold. + Optional<int> ColdCallSiteThreshold; + + /// Compute inline cost even when the cost has exceeded the threshold. + Optional<bool> ComputeFullInlineCost; +}; + +/// Generate the parameters to tune the inline cost analysis based only on the +/// commandline options. +InlineParams getInlineParams(); + +/// Generate the parameters to tune the inline cost analysis based on command +/// line options. If -inline-threshold option is not explicitly passed, +/// \p Threshold is used as the default threshold. +InlineParams getInlineParams(int Threshold); + +/// Generate the parameters to tune the inline cost analysis based on command +/// line options. If -inline-threshold option is not explicitly passed, +/// the default threshold is computed from \p OptLevel and \p SizeOptLevel. +/// An \p OptLevel value above 3 is considered an aggressive optimization mode. +/// \p SizeOptLevel of 1 corresponds to the -Os flag and 2 corresponds to +/// the -Oz flag. +InlineParams getInlineParams(unsigned OptLevel, unsigned SizeOptLevel); + +/// Return the cost associated with a callsite, including parameter passing +/// and the call/return instruction. +int getCallsiteCost(CallBase &Call, const DataLayout &DL); + +/// Get an InlineCost object representing the cost of inlining this +/// callsite. +/// +/// 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( + CallBase &Call, const InlineParams &Params, TargetTransformInfo &CalleeTTI, + std::function<AssumptionCache &(Function &)> &GetAssumptionCache, + Optional<function_ref<BlockFrequencyInfo &(Function &)>> GetBFI, + ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE = nullptr); + +/// 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(CallBase &Call, Function *Callee, const InlineParams &Params, + TargetTransformInfo &CalleeTTI, + std::function<AssumptionCache &(Function &)> &GetAssumptionCache, + Optional<function_ref<BlockFrequencyInfo &(Function &)>> GetBFI, + ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE); + +/// Minimal filter to detect invalid constructs for inlining. +InlineResult isInlineViable(Function &Callee); +} + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/InstructionPrecedenceTracking.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/InstructionPrecedenceTracking.h new file mode 100644 index 0000000..3c39810 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/InstructionPrecedenceTracking.h
@@ -0,0 +1,149 @@ +//===-- InstructionPrecedenceTracking.h -------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Implements a class that is able to define some instructions as "special" +// (e.g. as having implicit control flow, or writing memory, or having another +// interesting property) and then efficiently answers queries of the types: +// 1. Are there any special instructions in the block of interest? +// 2. Return first of the special instructions in the given block; +// 3. Check if the given instruction is preceeded by the first special +// instruction in the same block. +// The class provides caching that allows to answer these queries quickly. The +// user must make sure that the cached data is invalidated properly whenever +// a content of some tracked block is changed. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_INSTRUCTIONPRECEDENCETRACKING_H +#define LLVM_ANALYSIS_INSTRUCTIONPRECEDENCETRACKING_H + +#include "llvm/IR/Dominators.h" +#include "llvm/Analysis/OrderedInstructions.h" + +namespace llvm { + +class InstructionPrecedenceTracking { + // Maps a block to the topmost special instruction in it. If the value is + // nullptr, it means that it is known that this block does not contain any + // special instructions. + DenseMap<const BasicBlock *, const Instruction *> FirstSpecialInsts; + // Allows to answer queries about precedence of instructions within one block. + OrderedInstructions OI; + + // Fills information about the given block's special instructions. + void fill(const BasicBlock *BB); + +#ifndef NDEBUG + /// Asserts that the cached info for \p BB is up-to-date. This helps to catch + /// the usage error of accessing a block without properly invalidating after a + /// previous transform. + void validate(const BasicBlock *BB) const; + + /// Asserts whether or not the contents of this tracking is up-to-date. This + /// helps to catch the usage error of accessing a block without properly + /// invalidating after a previous transform. + void validateAll() const; +#endif + +protected: + InstructionPrecedenceTracking(DominatorTree *DT) + : OI(OrderedInstructions(DT)) {} + + /// Returns the topmost special instruction from the block \p BB. Returns + /// nullptr if there is no special instructions in the block. + const Instruction *getFirstSpecialInstruction(const BasicBlock *BB); + + /// Returns true iff at least one instruction from the basic block \p BB is + /// special. + bool hasSpecialInstructions(const BasicBlock *BB); + + /// Returns true iff the first special instruction of \p Insn's block exists + /// and dominates \p Insn. + bool isPreceededBySpecialInstruction(const Instruction *Insn); + + /// A predicate that defines whether or not the instruction \p Insn is + /// considered special and needs to be tracked. Implementing this method in + /// children classes allows to implement tracking of implicit control flow, + /// memory writing instructions or any other kinds of instructions we might + /// be interested in. + virtual bool isSpecialInstruction(const Instruction *Insn) const = 0; + + virtual ~InstructionPrecedenceTracking() = default; + +public: + /// Notifies this tracking that we are going to insert a new instruction \p + /// Inst to the basic block \p BB. It makes all necessary updates to internal + /// caches to keep them consistent. + void insertInstructionTo(const Instruction *Inst, const BasicBlock *BB); + + /// Notifies this tracking that we are going to remove the instruction \p Inst + /// It makes all necessary updates to internal caches to keep them consistent. + void removeInstruction(const Instruction *Inst); + + /// Invalidates all information from this tracking. + void clear(); +}; + +/// This class allows to keep track on instructions with implicit control flow. +/// These are instructions that may not pass execution to their successors. For +/// example, throwing calls and guards do not always do this. If we need to know +/// for sure that some instruction is guaranteed to execute if the given block +/// is reached, then we need to make sure that there is no implicit control flow +/// instruction (ICFI) preceding it. For example, this check is required if we +/// perform PRE moving non-speculable instruction to other place. +class ImplicitControlFlowTracking : public InstructionPrecedenceTracking { +public: + ImplicitControlFlowTracking(DominatorTree *DT) + : InstructionPrecedenceTracking(DT) {} + + /// Returns the topmost instruction with implicit control flow from the given + /// basic block. Returns nullptr if there is no such instructions in the block. + const Instruction *getFirstICFI(const BasicBlock *BB) { + return getFirstSpecialInstruction(BB); + } + + /// Returns true if at least one instruction from the given basic block has + /// implicit control flow. + bool hasICF(const BasicBlock *BB) { + return hasSpecialInstructions(BB); + } + + /// Returns true if the first ICFI of Insn's block exists and dominates Insn. + bool isDominatedByICFIFromSameBlock(const Instruction *Insn) { + return isPreceededBySpecialInstruction(Insn); + } + + virtual bool isSpecialInstruction(const Instruction *Insn) const; +}; + +class MemoryWriteTracking : public InstructionPrecedenceTracking { +public: + MemoryWriteTracking(DominatorTree *DT) : InstructionPrecedenceTracking(DT) {} + + /// Returns the topmost instruction that may write memory from the given + /// basic block. Returns nullptr if there is no such instructions in the block. + const Instruction *getFirstMemoryWrite(const BasicBlock *BB) { + return getFirstSpecialInstruction(BB); + } + + /// Returns true if at least one instruction from the given basic block may + /// write memory. + bool mayWriteToMemory(const BasicBlock *BB) { + return hasSpecialInstructions(BB); + } + + /// Returns true if the first memory writing instruction of Insn's block + /// exists and dominates Insn. + bool isDominatedByMemoryWriteFromSameBlock(const Instruction *Insn) { + return isPreceededBySpecialInstruction(Insn); + } + + virtual bool isSpecialInstruction(const Instruction *Insn) const; +}; + +} // llvm + +#endif // LLVM_ANALYSIS_INSTRUCTIONPRECEDENCETRACKING_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/InstructionSimplify.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/InstructionSimplify.h new file mode 100644 index 0000000..b661cae --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/InstructionSimplify.h
@@ -0,0 +1,308 @@ +//===-- InstructionSimplify.h - Fold instrs into simpler forms --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file declares routines for folding instructions into simpler forms +// that do not require creating new instructions. This does constant folding +// ("add i32 1, 1" -> "2") but can also handle non-constant operands, either +// returning a constant ("and i32 %x, 0" -> "0") or an already existing value +// ("and i32 %x, %x" -> "%x"). If the simplification is also an instruction +// then it dominates the original instruction. +// +// These routines implicitly resolve undef uses. The easiest way to be safe when +// using these routines to obtain simplified values for existing instructions is +// to always replace all uses of the instructions with the resulting simplified +// values. This will prevent other code from seeing the same undef uses and +// resolving them to different values. +// +// These routines are designed to tolerate moderately incomplete IR, such as +// instructions that are not connected to basic blocks yet. However, they do +// require that all the IR that they encounter be valid. In particular, they +// require that all non-constant values be defined in the same function, and the +// same call context of that function (and not split between caller and callee +// contexts of a directly recursive call, for example). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_INSTRUCTIONSIMPLIFY_H +#define LLVM_ANALYSIS_INSTRUCTIONSIMPLIFY_H + +#include "llvm/ADT/SetVector.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Operator.h" +#include "llvm/IR/User.h" + +namespace llvm { +class Function; +template <typename T, typename... TArgs> class AnalysisManager; +template <class T> class ArrayRef; +class AssumptionCache; +class CallBase; +class DominatorTree; +class DataLayout; +class FastMathFlags; +struct LoopStandardAnalysisResults; +class OptimizationRemarkEmitter; +class Pass; +class TargetLibraryInfo; +class Type; +class Value; +class MDNode; +class BinaryOperator; + +/// InstrInfoQuery provides an interface to query additional information for +/// instructions like metadata or keywords like nsw, which provides conservative +/// results if the users specified it is safe to use. +struct InstrInfoQuery { + InstrInfoQuery(bool UMD) : UseInstrInfo(UMD) {} + InstrInfoQuery() : UseInstrInfo(true) {} + bool UseInstrInfo = true; + + MDNode *getMetadata(const Instruction *I, unsigned KindID) const { + if (UseInstrInfo) + return I->getMetadata(KindID); + return nullptr; + } + + template <class InstT> bool hasNoUnsignedWrap(const InstT *Op) const { + if (UseInstrInfo) + return Op->hasNoUnsignedWrap(); + return false; + } + + template <class InstT> bool hasNoSignedWrap(const InstT *Op) const { + if (UseInstrInfo) + return Op->hasNoSignedWrap(); + return false; + } + + bool isExact(const BinaryOperator *Op) const { + if (UseInstrInfo && isa<PossiblyExactOperator>(Op)) + return cast<PossiblyExactOperator>(Op)->isExact(); + return false; + } +}; + +struct SimplifyQuery { + const DataLayout &DL; + const TargetLibraryInfo *TLI = nullptr; + const DominatorTree *DT = nullptr; + AssumptionCache *AC = nullptr; + const Instruction *CxtI = nullptr; + + // Wrapper to query additional information for instructions like metadata or + // keywords like nsw, which provides conservative results if those cannot + // be safely used. + const InstrInfoQuery IIQ; + + SimplifyQuery(const DataLayout &DL, const Instruction *CXTI = nullptr) + : DL(DL), CxtI(CXTI) {} + + SimplifyQuery(const DataLayout &DL, const TargetLibraryInfo *TLI, + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CXTI = nullptr, bool UseInstrInfo = true) + : DL(DL), TLI(TLI), DT(DT), AC(AC), CxtI(CXTI), IIQ(UseInstrInfo) {} + SimplifyQuery getWithInstruction(Instruction *I) const { + SimplifyQuery Copy(*this); + Copy.CxtI = I; + return Copy; + } +}; + +// NOTE: the explicit multiple argument versions of these functions are +// deprecated. +// Please use the SimplifyQuery versions in new code. + +/// Given operand for an FNeg, fold the result or return null. +Value *SimplifyFNegInst(Value *Op, FastMathFlags FMF, + const SimplifyQuery &Q); + +/// Given operands for an Add, fold the result or return null. +Value *SimplifyAddInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW, + const SimplifyQuery &Q); + +/// Given operands for a Sub, fold the result or return null. +Value *SimplifySubInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW, + const SimplifyQuery &Q); + +/// Given operands for an FAdd, fold the result or return null. +Value *SimplifyFAddInst(Value *LHS, Value *RHS, FastMathFlags FMF, + const SimplifyQuery &Q); + +/// Given operands for an FSub, fold the result or return null. +Value *SimplifyFSubInst(Value *LHS, Value *RHS, FastMathFlags FMF, + const SimplifyQuery &Q); + +/// Given operands for an FMul, fold the result or return null. +Value *SimplifyFMulInst(Value *LHS, Value *RHS, FastMathFlags FMF, + const SimplifyQuery &Q); + +/// Given operands for the multiplication of a FMA, fold the result or return +/// null. In contrast to SimplifyFMulInst, this function will not perform +/// simplifications whose unrounded results differ when rounded to the argument +/// type. +Value *SimplifyFMAFMul(Value *LHS, Value *RHS, FastMathFlags FMF, + const SimplifyQuery &Q); + +/// Given operands for a Mul, fold the result or return null. +Value *SimplifyMulInst(Value *LHS, Value *RHS, const SimplifyQuery &Q); + +/// Given operands for an SDiv, fold the result or return null. +Value *SimplifySDivInst(Value *LHS, Value *RHS, const SimplifyQuery &Q); + +/// Given operands for a UDiv, fold the result or return null. +Value *SimplifyUDivInst(Value *LHS, Value *RHS, const SimplifyQuery &Q); + +/// Given operands for an FDiv, fold the result or return null. +Value *SimplifyFDivInst(Value *LHS, Value *RHS, FastMathFlags FMF, + const SimplifyQuery &Q); + +/// Given operands for an SRem, fold the result or return null. +Value *SimplifySRemInst(Value *LHS, Value *RHS, const SimplifyQuery &Q); + +/// Given operands for a URem, fold the result or return null. +Value *SimplifyURemInst(Value *LHS, Value *RHS, const SimplifyQuery &Q); + +/// Given operands for an FRem, fold the result or return null. +Value *SimplifyFRemInst(Value *LHS, Value *RHS, FastMathFlags FMF, + const SimplifyQuery &Q); + +/// Given operands for a Shl, fold the result or return null. +Value *SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW, + const SimplifyQuery &Q); + +/// Given operands for a LShr, fold the result or return null. +Value *SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact, + const SimplifyQuery &Q); + +/// Given operands for a AShr, fold the result or return nulll. +Value *SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact, + const SimplifyQuery &Q); + +/// Given operands for an And, fold the result or return null. +Value *SimplifyAndInst(Value *LHS, Value *RHS, const SimplifyQuery &Q); + +/// Given operands for an Or, fold the result or return null. +Value *SimplifyOrInst(Value *LHS, Value *RHS, const SimplifyQuery &Q); + +/// Given operands for an Xor, fold the result or return null. +Value *SimplifyXorInst(Value *LHS, Value *RHS, const SimplifyQuery &Q); + +/// Given operands for an ICmpInst, fold the result or return null. +Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, + const SimplifyQuery &Q); + +/// Given operands for an FCmpInst, fold the result or return null. +Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS, + FastMathFlags FMF, const SimplifyQuery &Q); + +/// Given operands for a SelectInst, fold the result or return null. +Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal, + const SimplifyQuery &Q); + +/// Given operands for a GetElementPtrInst, fold the result or return null. +Value *SimplifyGEPInst(Type *SrcTy, ArrayRef<Value *> Ops, + const SimplifyQuery &Q); + +/// Given operands for an InsertValueInst, fold the result or return null. +Value *SimplifyInsertValueInst(Value *Agg, Value *Val, ArrayRef<unsigned> Idxs, + const SimplifyQuery &Q); + +/// Given operands for an InsertElement, fold the result or return null. +Value *SimplifyInsertElementInst(Value *Vec, Value *Elt, Value *Idx, + const SimplifyQuery &Q); + +/// Given operands for an ExtractValueInst, fold the result or return null. +Value *SimplifyExtractValueInst(Value *Agg, ArrayRef<unsigned> Idxs, + const SimplifyQuery &Q); + +/// Given operands for an ExtractElementInst, fold the result or return null. +Value *SimplifyExtractElementInst(Value *Vec, Value *Idx, + const SimplifyQuery &Q); + +/// Given operands for a CastInst, fold the result or return null. +Value *SimplifyCastInst(unsigned CastOpc, Value *Op, Type *Ty, + const SimplifyQuery &Q); + +/// Given operands for a ShuffleVectorInst, fold the result or return null. +Value *SimplifyShuffleVectorInst(Value *Op0, Value *Op1, Constant *Mask, + Type *RetTy, const SimplifyQuery &Q); + +//=== Helper functions for higher up the class hierarchy. + +/// Given operands for a CmpInst, fold the result or return null. +Value *SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS, + const SimplifyQuery &Q); + +/// Given operand for a UnaryOperator, fold the result or return null. +Value *SimplifyUnOp(unsigned Opcode, Value *Op, const SimplifyQuery &Q); + +/// Given operand for a UnaryOperator, fold the result or return null. +/// Try to use FastMathFlags when folding the result. +Value *SimplifyUnOp(unsigned Opcode, Value *Op, FastMathFlags FMF, + const SimplifyQuery &Q); + +/// Given operands for a BinaryOperator, fold the result or return null. +Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS, + const SimplifyQuery &Q); + +/// Given operands for a BinaryOperator, fold the result or return null. +/// Try to use FastMathFlags when folding the result. +Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS, + FastMathFlags FMF, const SimplifyQuery &Q); + +/// Given a callsite, fold the result or return null. +Value *SimplifyCall(CallBase *Call, const SimplifyQuery &Q); + +/// Given an operand for a Freeze, see if we can fold the result. +/// If not, this returns null. +Value *SimplifyFreezeInst(Value *Op, const SimplifyQuery &Q); + +/// See if we can compute a simplified version of this instruction. If not, +/// return null. +Value *SimplifyInstruction(Instruction *I, const SimplifyQuery &Q, + OptimizationRemarkEmitter *ORE = nullptr); + +/// 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' +/// instruction must not be equal to the simplified value 'SimpleV'. +/// If UnsimplifiedUsers is provided, instructions that could not be simplified +/// are added to it. +/// +/// The function returns true if any simplifications were performed. +bool replaceAndRecursivelySimplify( + Instruction *I, Value *SimpleV, const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, + SmallSetVector<Instruction *, 8> *UnsimplifiedUsers = nullptr); + +/// 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 +/// of the users impacted. It returns true if any simplifications were +/// performed. +bool recursivelySimplifyInstruction(Instruction *I, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr); + +// These helper functions return a SimplifyQuery structure that contains as +// many of the optional analysis we use as are currently valid. This is the +// strongly preferred way of constructing SimplifyQuery in passes. +const SimplifyQuery getBestSimplifyQuery(Pass &, Function &); +template <class T, class... TArgs> +const SimplifyQuery getBestSimplifyQuery(AnalysisManager<T, TArgs...> &, + Function &); +const SimplifyQuery getBestSimplifyQuery(LoopStandardAnalysisResults &, + const DataLayout &); +} // end namespace llvm + +#endif +
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/Interval.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/Interval.h new file mode 100644 index 0000000..5c9a453 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/Interval.h
@@ -0,0 +1,141 @@ +//===- llvm/Analysis/Interval.h - Interval Class Declaration ----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the Interval class, which +// represents a set of CFG nodes and is a portion of an interval partition. +// +// Intervals have some interesting and useful properties, including the +// following: +// 1. The header node of an interval dominates all of the elements of the +// interval +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_INTERVAL_H +#define LLVM_ANALYSIS_INTERVAL_H + +#include "llvm/ADT/GraphTraits.h" +#include <vector> + +namespace llvm { + +class BasicBlock; +class raw_ostream; + +//===----------------------------------------------------------------------===// +// +/// Interval Class - An Interval is a set of nodes defined such that every node +/// in the interval has all of its predecessors in the interval (except for the +/// header) +/// +class Interval { + /// HeaderNode - The header BasicBlock, which dominates all BasicBlocks in this + /// interval. Also, any loops in this interval must go through the HeaderNode. + /// + BasicBlock *HeaderNode; + +public: + using succ_iterator = std::vector<BasicBlock*>::iterator; + using pred_iterator = std::vector<BasicBlock*>::iterator; + using node_iterator = std::vector<BasicBlock*>::iterator; + + inline Interval(BasicBlock *Header) : HeaderNode(Header) { + Nodes.push_back(Header); + } + + inline BasicBlock *getHeaderNode() const { return HeaderNode; } + + /// Nodes - The basic blocks in this interval. + std::vector<BasicBlock*> Nodes; + + /// Successors - List of BasicBlocks that are reachable directly from nodes in + /// this interval, but are not in the interval themselves. + /// These nodes necessarily must be header nodes for other intervals. + std::vector<BasicBlock*> Successors; + + /// Predecessors - List of BasicBlocks that have this Interval's header block + /// as one of their successors. + std::vector<BasicBlock*> Predecessors; + + /// contains - Find out if a basic block is in this interval + inline bool contains(BasicBlock *BB) const { + 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(); + } + + /// isSuccessor - find out if a basic block is a successor of this Interval + inline bool isSuccessor(BasicBlock *BB) const { + 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(); + } + + /// Equality operator. It is only valid to compare two intervals from the + /// same partition, because of this, all we have to check is the header node + /// for equality. + inline bool operator==(const Interval &I) const { + return HeaderNode == I.HeaderNode; + } + + /// isLoop - Find out if there is a back edge in this interval... + bool isLoop() const; + + /// print - Show contents in human readable format... + void print(raw_ostream &O) const; +}; + +/// succ_begin/succ_end - define methods so that Intervals may be used +/// just like BasicBlocks can with the succ_* functions, and *::succ_iterator. +/// +inline Interval::succ_iterator succ_begin(Interval *I) { + return I->Successors.begin(); +} +inline Interval::succ_iterator succ_end(Interval *I) { + return I->Successors.end(); +} + +/// pred_begin/pred_end - define methods so that Intervals may be used +/// just like BasicBlocks can with the pred_* functions, and *::pred_iterator. +/// +inline Interval::pred_iterator pred_begin(Interval *I) { + return I->Predecessors.begin(); +} +inline Interval::pred_iterator pred_end(Interval *I) { + return I->Predecessors.end(); +} + +template <> struct GraphTraits<Interval*> { + using NodeRef = Interval *; + using ChildIteratorType = Interval::succ_iterator; + + static NodeRef getEntryNode(Interval *I) { return I; } + + /// nodes_iterator/begin/end - Allow iteration over all nodes in the graph + static ChildIteratorType child_begin(NodeRef N) { return succ_begin(N); } + static ChildIteratorType child_end(NodeRef N) { return succ_end(N); } +}; + +template <> struct GraphTraits<Inverse<Interval*>> { + using NodeRef = Interval *; + using ChildIteratorType = Interval::pred_iterator; + + static NodeRef getEntryNode(Inverse<Interval *> G) { return G.Graph; } + static ChildIteratorType child_begin(NodeRef N) { return pred_begin(N); } + static ChildIteratorType child_end(NodeRef N) { return pred_end(N); } +}; + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_INTERVAL_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/IntervalIterator.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/IntervalIterator.h new file mode 100644 index 0000000..efaaf97 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/IntervalIterator.h
@@ -0,0 +1,267 @@ +//===- IntervalIterator.h - Interval Iterator Declaration -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines an iterator that enumerates the intervals in a control flow +// graph of some sort. This iterator is parametric, allowing iterator over the +// following types of graphs: +// +// 1. A Function* object, composed of BasicBlock nodes. +// 2. An IntervalPartition& object, composed of Interval nodes. +// +// This iterator is defined to walk the control flow graph, returning intervals +// in depth first order. These intervals are completely filled in except for +// the predecessor fields (the successor information is filled in however). +// +// By default, the intervals created by this iterator are deleted after they +// are no longer any use to the iterator. This behavior can be changed by +// passing a false value into the intervals_begin() function. This causes the +// IOwnMem member to be set, and the intervals to not be deleted. +// +// It is only safe to use this if all of the intervals are deleted by the caller +// and all of the intervals are processed. However, the user of the iterator is +// not allowed to modify or delete the intervals until after the iterator has +// been used completely. The IntervalPartition class uses this functionality. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_INTERVALITERATOR_H +#define LLVM_ANALYSIS_INTERVALITERATOR_H + +#include "llvm/ADT/GraphTraits.h" +#include "llvm/Analysis/Interval.h" +#include "llvm/Analysis/IntervalPartition.h" +#include "llvm/IR/CFG.h" +#include "llvm/IR/Function.h" +#include "llvm/Support/ErrorHandling.h" +#include <algorithm> +#include <cassert> +#include <iterator> +#include <set> +#include <utility> +#include <vector> + +namespace llvm { + +class BasicBlock; + +// getNodeHeader - Given a source graph node and the source graph, return the +// BasicBlock that is the header node. This is the opposite of +// getSourceGraphNode. +inline BasicBlock *getNodeHeader(BasicBlock *BB) { return BB; } +inline BasicBlock *getNodeHeader(Interval *I) { return I->getHeaderNode(); } + +// getSourceGraphNode - Given a BasicBlock and the source graph, return the +// source graph node that corresponds to the BasicBlock. This is the opposite +// of getNodeHeader. +inline BasicBlock *getSourceGraphNode(Function *, BasicBlock *BB) { + return BB; +} +inline Interval *getSourceGraphNode(IntervalPartition *IP, BasicBlock *BB) { + return IP->getBlockInterval(BB); +} + +// addNodeToInterval - This method exists to assist the generic ProcessNode +// with the task of adding a node to the new interval, depending on the +// type of the source node. In the case of a CFG source graph (BasicBlock +// case), the BasicBlock itself is added to the interval. +inline void addNodeToInterval(Interval *Int, BasicBlock *BB) { + Int->Nodes.push_back(BB); +} + +// addNodeToInterval - This method exists to assist the generic ProcessNode +// with the task of adding a node to the new interval, depending on the +// type of the source node. In the case of a CFG source graph (BasicBlock +// case), the BasicBlock itself is added to the interval. In the case of +// an IntervalPartition source graph (Interval case), all of the member +// BasicBlocks are added to the interval. +inline void addNodeToInterval(Interval *Int, Interval *I) { + // Add all of the nodes in I as new nodes in Int. + Int->Nodes.insert(Int->Nodes.end(), I->Nodes.begin(), I->Nodes.end()); +} + +template<class NodeTy, class OrigContainer_t, class GT = GraphTraits<NodeTy *>, + class IGT = GraphTraits<Inverse<NodeTy *>>> +class IntervalIterator { + std::vector<std::pair<Interval *, typename Interval::succ_iterator>> IntStack; + std::set<BasicBlock *> Visited; + OrigContainer_t *OrigContainer; + bool IOwnMem; // If True, delete intervals when done with them + // See file header for conditions of use + +public: + using iterator_category = std::forward_iterator_tag; + + IntervalIterator() = default; // End iterator, empty stack + + IntervalIterator(Function *M, bool OwnMemory) : IOwnMem(OwnMemory) { + OrigContainer = M; + if (!ProcessInterval(&M->front())) { + llvm_unreachable("ProcessInterval should never fail for first interval!"); + } + } + + IntervalIterator(IntervalIterator &&x) + : IntStack(std::move(x.IntStack)), Visited(std::move(x.Visited)), + OrigContainer(x.OrigContainer), IOwnMem(x.IOwnMem) { + x.IOwnMem = false; + } + + IntervalIterator(IntervalPartition &IP, bool OwnMemory) : IOwnMem(OwnMemory) { + OrigContainer = &IP; + if (!ProcessInterval(IP.getRootInterval())) { + llvm_unreachable("ProcessInterval should never fail for first interval!"); + } + } + + ~IntervalIterator() { + if (IOwnMem) + while (!IntStack.empty()) { + delete operator*(); + IntStack.pop_back(); + } + } + + bool operator==(const IntervalIterator &x) const { + return IntStack == x.IntStack; + } + bool operator!=(const IntervalIterator &x) const { return !(*this == x); } + + const Interval *operator*() const { return IntStack.back().first; } + Interval *operator*() { return IntStack.back().first; } + const Interval *operator->() const { return operator*(); } + Interval *operator->() { return operator*(); } + + IntervalIterator &operator++() { // Preincrement + assert(!IntStack.empty() && "Attempting to use interval iterator at end!"); + do { + // All of the intervals on the stack have been visited. Try visiting + // their successors now. + Interval::succ_iterator &SuccIt = IntStack.back().second, + EndIt = succ_end(IntStack.back().first); + while (SuccIt != EndIt) { // Loop over all interval succs + bool Done = ProcessInterval(getSourceGraphNode(OrigContainer, *SuccIt)); + ++SuccIt; // Increment iterator + if (Done) return *this; // Found a new interval! Use it! + } + + // Free interval memory... if necessary + if (IOwnMem) delete IntStack.back().first; + + // We ran out of successors for this interval... pop off the stack + IntStack.pop_back(); + } while (!IntStack.empty()); + + return *this; + } + + IntervalIterator operator++(int) { // Postincrement + IntervalIterator tmp = *this; + ++*this; + return tmp; + } + +private: + // ProcessInterval - This method is used during the construction of the + // interval graph. It walks through the source graph, recursively creating + // an interval per invocation until the entire graph is covered. This uses + // the ProcessNode method to add all of the nodes to the interval. + // + // This method is templated because it may operate on two different source + // graphs: a basic block graph, or a preexisting interval graph. + bool ProcessInterval(NodeTy *Node) { + BasicBlock *Header = getNodeHeader(Node); + if (!Visited.insert(Header).second) + return false; + + Interval *Int = new Interval(Header); + + // Check all of our successors to see if they are in the interval... + for (typename GT::ChildIteratorType I = GT::child_begin(Node), + E = GT::child_end(Node); I != E; ++I) + ProcessNode(Int, getSourceGraphNode(OrigContainer, *I)); + + IntStack.push_back(std::make_pair(Int, succ_begin(Int))); + return true; + } + + // ProcessNode - This method is called by ProcessInterval to add nodes to the + // interval being constructed, and it is also called recursively as it walks + // the source graph. A node is added to the current interval only if all of + // its predecessors are already in the graph. This also takes care of keeping + // the successor set of an interval up to date. + // + // This method is templated because it may operate on two different source + // graphs: a basic block graph, or a preexisting interval graph. + void ProcessNode(Interval *Int, NodeTy *Node) { + assert(Int && "Null interval == bad!"); + assert(Node && "Null Node == bad!"); + + BasicBlock *NodeHeader = getNodeHeader(Node); + + if (Visited.count(NodeHeader)) { // Node already been visited? + if (Int->contains(NodeHeader)) { // Already in this interval... + return; + } else { // In other interval, add as successor + if (!Int->isSuccessor(NodeHeader)) // Add only if not already in set + Int->Successors.push_back(NodeHeader); + } + } else { // Otherwise, not in interval yet + for (typename IGT::ChildIteratorType I = IGT::child_begin(Node), + E = IGT::child_end(Node); I != E; ++I) { + if (!Int->contains(*I)) { // If pred not in interval, we can't be + if (!Int->isSuccessor(NodeHeader)) // Add only if not already in set + Int->Successors.push_back(NodeHeader); + return; // See you later + } + } + + // If we get here, then all of the predecessors of BB are in the interval + // already. In this case, we must add BB to the interval! + addNodeToInterval(Int, Node); + Visited.insert(NodeHeader); // The node has now been visited! + + if (Int->isSuccessor(NodeHeader)) { + // If we were in the successor list from before... remove from succ list + Int->Successors.erase(std::remove(Int->Successors.begin(), + Int->Successors.end(), NodeHeader), + Int->Successors.end()); + } + + // Now that we have discovered that Node is in the interval, perhaps some + // of its successors are as well? + for (typename GT::ChildIteratorType It = GT::child_begin(Node), + End = GT::child_end(Node); It != End; ++It) + ProcessNode(Int, getSourceGraphNode(OrigContainer, *It)); + } + } +}; + +using function_interval_iterator = IntervalIterator<BasicBlock, Function>; +using interval_part_interval_iterator = + IntervalIterator<Interval, IntervalPartition>; + +inline function_interval_iterator intervals_begin(Function *F, + bool DeleteInts = true) { + return function_interval_iterator(F, DeleteInts); +} +inline function_interval_iterator intervals_end(Function *) { + return function_interval_iterator(); +} + +inline interval_part_interval_iterator + intervals_begin(IntervalPartition &IP, bool DeleteIntervals = true) { + return interval_part_interval_iterator(IP, DeleteIntervals); +} + +inline interval_part_interval_iterator intervals_end(IntervalPartition &IP) { + return interval_part_interval_iterator(); +} + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_INTERVALITERATOR_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/IntervalPartition.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/IntervalPartition.h new file mode 100644 index 0000000..66a99fb --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/IntervalPartition.h
@@ -0,0 +1,108 @@ +//===- IntervalPartition.h - Interval partition Calculation -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the IntervalPartition class, which +// calculates and represents the interval partition of a function, or a +// preexisting interval partition. +// +// In this way, the interval partition may be used to reduce a flow graph down +// to its degenerate single node interval partition (unless it is irreducible). +// +// TODO: The IntervalPartition class should take a bool parameter that tells +// whether it should add the "tails" of an interval to an interval itself or if +// they should be represented as distinct intervals. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_INTERVALPARTITION_H +#define LLVM_ANALYSIS_INTERVALPARTITION_H + +#include "llvm/Pass.h" +#include <map> +#include <vector> + +namespace llvm { + +class BasicBlock; +class Interval; + +//===----------------------------------------------------------------------===// +// +// IntervalPartition - This class builds and holds an "interval partition" for +// a function. This partition divides the control flow graph into a set of +// maximal intervals, as defined with the properties above. Intuitively, an +// interval is a (possibly nonexistent) loop with a "tail" of non-looping +// nodes following it. +// +class IntervalPartition : public FunctionPass { + using IntervalMapTy = std::map<BasicBlock *, Interval *>; + IntervalMapTy IntervalMap; + + using IntervalListTy = std::vector<Interval *>; + Interval *RootInterval = nullptr; + std::vector<Interval *> Intervals; + +public: + static char ID; // Pass identification, replacement for typeid + + IntervalPartition(); + + // run - Calculate the interval partition for this function + bool runOnFunction(Function &F) override; + + // IntervalPartition ctor - Build a reduced interval partition from an + // existing interval graph. This takes an additional boolean parameter to + // distinguish it from a copy constructor. Always pass in false for now. + IntervalPartition(IntervalPartition &I, bool); + + // print - Show contents in human readable format... + void print(raw_ostream &O, const Module* = nullptr) const override; + + // getRootInterval() - Return the root interval that contains the starting + // block of the function. + inline Interval *getRootInterval() { return RootInterval; } + + // isDegeneratePartition() - Returns true if the interval partition contains + // a single interval, and thus cannot be simplified anymore. + bool isDegeneratePartition() { return Intervals.size() == 1; } + + // TODO: isIrreducible - look for triangle graph. + + // getBlockInterval - Return the interval that a basic block exists in. + inline Interval *getBlockInterval(BasicBlock *BB) { + IntervalMapTy::iterator I = IntervalMap.find(BB); + return I != IntervalMap.end() ? I->second : nullptr; + } + + // getAnalysisUsage - Implement the Pass API + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + } + + // Interface to Intervals vector... + const std::vector<Interval*> &getIntervals() const { return Intervals; } + + // releaseMemory - Reset state back to before function was analyzed + void releaseMemory() override; + +private: + // addIntervalToPartition - Add an interval to the internal list of intervals, + // and then add mappings from all of the basic blocks in the interval to the + // interval itself (in the IntervalMap). + void addIntervalToPartition(Interval *I); + + // updatePredecessors - Interval generation only sets the successor fields of + // the interval data structures. After interval generation is complete, + // run through all of the intervals and propagate successor info as + // predecessor info. + void updatePredecessors(Interval *Int); +}; + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_INTERVALPARTITION_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/IteratedDominanceFrontier.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/IteratedDominanceFrontier.h new file mode 100644 index 0000000..7c82678 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/IteratedDominanceFrontier.h
@@ -0,0 +1,89 @@ +//===- IteratedDominanceFrontier.h - Calculate IDF --------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_IDF_H +#define LLVM_ANALYSIS_IDF_H + +#include "llvm/IR/CFGDiff.h" +#include "llvm/Support/GenericIteratedDominanceFrontier.h" + +namespace llvm { + +class BasicBlock; + +namespace IDFCalculatorDetail { + +/// Specialization for BasicBlock for the optional use of GraphDiff. +template <bool IsPostDom> struct ChildrenGetterTy<BasicBlock, IsPostDom> { + using NodeRef = BasicBlock *; + using ChildrenTy = SmallVector<BasicBlock *, 8>; + + ChildrenGetterTy() = default; + ChildrenGetterTy(const GraphDiff<BasicBlock *, IsPostDom> *GD) : GD(GD) { + assert(GD); + } + + ChildrenTy get(const NodeRef &N); + + const GraphDiff<BasicBlock *, IsPostDom> *GD = nullptr; +}; + +} // end of namespace IDFCalculatorDetail + +template <bool IsPostDom> +class IDFCalculator final : public IDFCalculatorBase<BasicBlock, IsPostDom> { +public: + using IDFCalculatorBase = + typename llvm::IDFCalculatorBase<BasicBlock, IsPostDom>; + using ChildrenGetterTy = typename IDFCalculatorBase::ChildrenGetterTy; + + IDFCalculator(DominatorTreeBase<BasicBlock, IsPostDom> &DT) + : IDFCalculatorBase(DT) {} + + IDFCalculator(DominatorTreeBase<BasicBlock, IsPostDom> &DT, + const GraphDiff<BasicBlock *, IsPostDom> *GD) + : IDFCalculatorBase(DT, ChildrenGetterTy(GD)) { + assert(GD); + } +}; + +using ForwardIDFCalculator = IDFCalculator<false>; +using ReverseIDFCalculator = IDFCalculator<true>; + +//===----------------------------------------------------------------------===// +// Implementation. +//===----------------------------------------------------------------------===// + +namespace IDFCalculatorDetail { + +template <bool IsPostDom> +typename ChildrenGetterTy<BasicBlock, IsPostDom>::ChildrenTy +ChildrenGetterTy<BasicBlock, IsPostDom>::get(const NodeRef &N) { + + using OrderedNodeTy = + typename IDFCalculatorBase<BasicBlock, IsPostDom>::OrderedNodeTy; + + if (!GD) { + auto Children = children<OrderedNodeTy>(N); + return {Children.begin(), Children.end()}; + } + + using SnapShotBBPairTy = + std::pair<const GraphDiff<BasicBlock *, IsPostDom> *, OrderedNodeTy>; + + ChildrenTy Ret; + for (const auto &SnapShotBBPair : children<SnapShotBBPairTy>({GD, N})) + Ret.emplace_back(SnapShotBBPair.second); + return Ret; +} + +} // end of namespace IDFCalculatorDetail + +} // end of namespace llvm + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/LazyBlockFrequencyInfo.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/LazyBlockFrequencyInfo.h new file mode 100644 index 0000000..0e7dc94 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/LazyBlockFrequencyInfo.h
@@ -0,0 +1,131 @@ +//===- LazyBlockFrequencyInfo.h - Lazy Block Frequency Analysis -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// 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 result is explicitly +// requested by the analysis client. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LAZYBLOCKFREQUENCYINFO_H +#define LLVM_ANALYSIS_LAZYBLOCKFREQUENCYINFO_H + +#include "llvm/Analysis/BlockFrequencyInfo.h" +#include "llvm/Analysis/LazyBranchProbabilityInfo.h" +#include "llvm/Pass.h" + +namespace llvm { +class AnalysisUsage; +class BranchProbabilityInfo; +class Function; +class LoopInfo; + +/// 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. +template <typename FunctionT, typename BranchProbabilityInfoPassT, + typename LoopInfoT, typename BlockFrequencyInfoT> +class LazyBlockFrequencyInfo { +public: + LazyBlockFrequencyInfo() + : Calculated(false), F(nullptr), BPIPass(nullptr), LI(nullptr) {} + + /// Set up the per-function input. + void setAnalysis(const FunctionT *F, BranchProbabilityInfoPassT *BPIPass, + const LoopInfoT *LI) { + this->F = F; + this->BPIPass = BPIPass; + this->LI = LI; + } + + /// Retrieve the BFI with the block frequencies computed. + BlockFrequencyInfoT &getCalculated() { + if (!Calculated) { + assert(F && BPIPass && LI && "call setAnalysis"); + BFI.calculate( + *F, BPIPassTrait<BranchProbabilityInfoPassT>::getBPI(BPIPass), *LI); + Calculated = true; + } + return BFI; + } + + const BlockFrequencyInfoT &getCalculated() const { + return const_cast<LazyBlockFrequencyInfo *>(this)->getCalculated(); + } + + void releaseMemory() { + BFI.releaseMemory(); + Calculated = false; + setAnalysis(nullptr, nullptr, nullptr); + } + +private: + BlockFrequencyInfoT BFI; + bool Calculated; + const FunctionT *F; + BranchProbabilityInfoPassT *BPIPass; + const LoopInfoT *LI; +}; + +/// 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 result 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 { +private: + LazyBlockFrequencyInfo<Function, LazyBranchProbabilityInfoPass, LoopInfo, + BlockFrequencyInfo> + LBFI; + +public: + static char ID; + + LazyBlockFrequencyInfoPass(); + + /// Compute and return the block frequencies. + BlockFrequencyInfo &getBFI() { return LBFI.getCalculated(); } + + /// 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; +}; + +/// Helper for client passes to initialize dependent passes for LBFI. +void initializeLazyBFIPassPass(PassRegistry &Registry); +} +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/LazyBranchProbabilityInfo.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/LazyBranchProbabilityInfo.h new file mode 100644 index 0000000..cae0778 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/LazyBranchProbabilityInfo.h
@@ -0,0 +1,123 @@ +//===- LazyBranchProbabilityInfo.h - Lazy Branch Probability ----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This is an alternative analysis pass to BranchProbabilityInfoWrapperPass. +// The difference is that with this pass the branch probabilities are not +// computed when the analysis pass is executed but rather when the BPI results +// is explicitly requested by the analysis client. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LAZYBRANCHPROBABILITYINFO_H +#define LLVM_ANALYSIS_LAZYBRANCHPROBABILITYINFO_H + +#include "llvm/Analysis/BranchProbabilityInfo.h" +#include "llvm/Pass.h" + +namespace llvm { +class AnalysisUsage; +class Function; +class LoopInfo; +class TargetLibraryInfo; + +/// This is an alternative analysis pass to +/// BranchProbabilityInfoWrapperPass. The difference is that with this pass the +/// branch probabilities are not computed when the analysis pass is executed but +/// rather when the BPI 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(LazyBPIPass) +/// +/// 2. Similarly, getAnalysisUsage should call: +/// +/// LazyBranchProbabilityInfoPass::getLazyBPIAnalysisUsage(AU) +/// +/// 3. The computed BPI should be requested with +/// getAnalysis<LazyBranchProbabilityInfoPass>().getBPI() before LoopInfo +/// 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 LazyBranchProbabilityInfoPass : public FunctionPass { + + /// Wraps a BPI to allow lazy computation of the branch probabilities. + /// + /// A pass that only conditionally uses BPI can uncondtionally require the + /// analysis without paying for the overhead if BPI doesn't end up being used. + class LazyBranchProbabilityInfo { + public: + LazyBranchProbabilityInfo(const Function *F, const LoopInfo *LI, + const TargetLibraryInfo *TLI) + : Calculated(false), F(F), LI(LI), TLI(TLI) {} + + /// Retrieve the BPI with the branch probabilities computed. + BranchProbabilityInfo &getCalculated() { + if (!Calculated) { + assert(F && LI && "call setAnalysis"); + BPI.calculate(*F, *LI, TLI); + Calculated = true; + } + return BPI; + } + + const BranchProbabilityInfo &getCalculated() const { + return const_cast<LazyBranchProbabilityInfo *>(this)->getCalculated(); + } + + private: + BranchProbabilityInfo BPI; + bool Calculated; + const Function *F; + const LoopInfo *LI; + const TargetLibraryInfo *TLI; + }; + + std::unique_ptr<LazyBranchProbabilityInfo> LBPI; + +public: + static char ID; + + LazyBranchProbabilityInfoPass(); + + /// Compute and return the branch probabilities. + BranchProbabilityInfo &getBPI() { return LBPI->getCalculated(); } + + /// Compute and return the branch probabilities. + const BranchProbabilityInfo &getBPI() const { return LBPI->getCalculated(); } + + void getAnalysisUsage(AnalysisUsage &AU) const override; + + /// Helper for client passes to set up the analysis usage on behalf of this + /// pass. + static void getLazyBPIAnalysisUsage(AnalysisUsage &AU); + + bool runOnFunction(Function &F) override; + void releaseMemory() override; + void print(raw_ostream &OS, const Module *M) const override; +}; + +/// Helper for client passes to initialize dependent passes for LBPI. +void initializeLazyBPIPassPass(PassRegistry &Registry); + +/// Simple trait class that provides a mapping between BPI passes and the +/// corresponding BPInfo. +template <typename PassT> struct BPIPassTrait { + static PassT &getBPI(PassT *P) { return *P; } +}; + +template <> struct BPIPassTrait<LazyBranchProbabilityInfoPass> { + static BranchProbabilityInfo &getBPI(LazyBranchProbabilityInfoPass *P) { + return P->getBPI(); + } +}; +} +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/LazyCallGraph.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/LazyCallGraph.h new file mode 100644 index 0000000..20a35be --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/LazyCallGraph.h
@@ -0,0 +1,1308 @@ +//===- LazyCallGraph.h - Analysis of a Module's call graph ------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// Implements a lazy call graph analysis and related passes for the new pass +/// manager. +/// +/// NB: This is *not* a traditional call graph! It is a graph which models both +/// the current calls and potential calls. As a consequence there are many +/// edges in this call graph that do not correspond to a 'call' or 'invoke' +/// instruction. +/// +/// The primary use cases of this graph analysis is to facilitate iterating +/// across the functions of a module in ways that ensure all callees are +/// visited prior to a caller (given any SCC constraints), or vice versa. As +/// such is it particularly well suited to organizing CGSCC optimizations such +/// as inlining, outlining, argument promotion, etc. That is its primary use +/// case and motivates the design. It may not be appropriate for other +/// purposes. The use graph of functions or some other conservative analysis of +/// call instructions may be interesting for optimizations and subsequent +/// analyses which don't work in the context of an overly specified +/// potential-call-edge graph. +/// +/// To understand the specific rules and nature of this call graph analysis, +/// see the documentation of the \c LazyCallGraph below. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LAZYCALLGRAPH_H +#define LLVM_ANALYSIS_LAZYCALLGRAPH_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Analysis/TargetLibraryInfo.h" +#include "llvm/IR/Constant.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/raw_ostream.h" +#include <cassert> +#include <iterator> +#include <string> +#include <utility> + +namespace llvm { + +class Module; +class Value; + +/// A lazily constructed view of the call graph of a module. +/// +/// With the edges of this graph, the motivating constraint that we are +/// attempting to maintain is that function-local optimization, CGSCC-local +/// optimizations, and optimizations transforming a pair of functions connected +/// by an edge in the graph, do not invalidate a bottom-up traversal of the SCC +/// DAG. That is, no optimizations will delete, remove, or add an edge such +/// that functions already visited in a bottom-up order of the SCC DAG are no +/// longer valid to have visited, or such that functions not yet visited in +/// a bottom-up order of the SCC DAG are not required to have already been +/// visited. +/// +/// Within this constraint, the desire is to minimize the merge points of the +/// SCC DAG. The greater the fanout of the SCC DAG and the fewer merge points +/// in the SCC DAG, the more independence there is in optimizing within it. +/// There is a strong desire to enable parallelization of optimizations over +/// the call graph, and both limited fanout and merge points will (artificially +/// in some cases) limit the scaling of such an effort. +/// +/// To this end, graph represents both direct and any potential resolution to +/// an indirect call edge. Another way to think about it is that it represents +/// both the direct call edges and any direct call edges that might be formed +/// through static optimizations. Specifically, it considers taking the address +/// of a function to be an edge in the call graph because this might be +/// forwarded to become a direct call by some subsequent function-local +/// optimization. The result is that the graph closely follows the use-def +/// edges for functions. Walking "up" the graph can be done by looking at all +/// of the uses of a function. +/// +/// The roots of the call graph are the external functions and functions +/// escaped into global variables. Those functions can be called from outside +/// of the module or via unknowable means in the IR -- we may not be able to +/// form even a potential call edge from a function body which may dynamically +/// load the function and call it. +/// +/// This analysis still requires updates to remain valid after optimizations +/// which could potentially change the set of potential callees. The +/// constraints it operates under only make the traversal order remain valid. +/// +/// The entire analysis must be re-computed if full interprocedural +/// optimizations run at any point. For example, globalopt completely +/// invalidates the information in this analysis. +/// +/// FIXME: This class is named LazyCallGraph in a lame attempt to distinguish +/// it from the existing CallGraph. At some point, it is expected that this +/// will be the only call graph and it will be renamed accordingly. +class LazyCallGraph { +public: + class Node; + class EdgeSequence; + class SCC; + class RefSCC; + class edge_iterator; + class call_edge_iterator; + + /// A class used to represent edges in the call graph. + /// + /// The lazy call graph models both *call* edges and *reference* edges. Call + /// edges are much what you would expect, and exist when there is a 'call' or + /// 'invoke' instruction of some function. Reference edges are also tracked + /// along side these, and exist whenever any instruction (transitively + /// through its operands) references a function. All call edges are + /// inherently reference edges, and so the reference graph forms a superset + /// of the formal call graph. + /// + /// All of these forms of edges are fundamentally represented as outgoing + /// edges. The edges are stored in the source node and point at the target + /// node. This allows the edge structure itself to be a very compact data + /// structure: essentially a tagged pointer. + class Edge { + public: + /// The kind of edge in the graph. + enum Kind : bool { Ref = false, Call = true }; + + Edge(); + explicit Edge(Node &N, Kind K); + + /// Test whether the edge is null. + /// + /// This happens when an edge has been deleted. We leave the edge objects + /// around but clear them. + explicit operator bool() const; + + /// Returnss the \c Kind of the edge. + Kind getKind() const; + + /// Test whether the edge represents a direct call to a function. + /// + /// This requires that the edge is not null. + bool isCall() const; + + /// Get the call graph node referenced by this edge. + /// + /// This requires that the edge is not null. + Node &getNode() const; + + /// Get the function referenced by this edge. + /// + /// This requires that the edge is not null. + Function &getFunction() const; + + private: + friend class LazyCallGraph::EdgeSequence; + friend class LazyCallGraph::RefSCC; + + PointerIntPair<Node *, 1, Kind> Value; + + void setKind(Kind K) { Value.setInt(K); } + }; + + /// The edge sequence object. + /// + /// This typically exists entirely within the node but is exposed as + /// a separate type because a node doesn't initially have edges. An explicit + /// population step is required to produce this sequence at first and it is + /// then cached in the node. It is also used to represent edges entering the + /// graph from outside the module to model the graph's roots. + /// + /// The sequence itself both iterable and indexable. The indexes remain + /// stable even as the sequence mutates (including removal). + class EdgeSequence { + friend class LazyCallGraph; + friend class LazyCallGraph::Node; + friend class LazyCallGraph::RefSCC; + + using VectorT = SmallVector<Edge, 4>; + using VectorImplT = SmallVectorImpl<Edge>; + + public: + /// An iterator used for the edges to both entry nodes and child nodes. + class iterator + : public iterator_adaptor_base<iterator, VectorImplT::iterator, + std::forward_iterator_tag> { + friend class LazyCallGraph; + friend class LazyCallGraph::Node; + + VectorImplT::iterator E; + + // Build the iterator for a specific position in the edge list. + iterator(VectorImplT::iterator BaseI, VectorImplT::iterator E) + : iterator_adaptor_base(BaseI), E(E) { + while (I != E && !*I) + ++I; + } + + public: + iterator() = default; + + using iterator_adaptor_base::operator++; + iterator &operator++() { + do { + ++I; + } while (I != E && !*I); + return *this; + } + }; + + /// An iterator over specifically call edges. + /// + /// This has the same iteration properties as the \c iterator, but + /// restricts itself to edges which represent actual calls. + class call_iterator + : public iterator_adaptor_base<call_iterator, VectorImplT::iterator, + std::forward_iterator_tag> { + friend class LazyCallGraph; + friend class LazyCallGraph::Node; + + VectorImplT::iterator E; + + /// Advance the iterator to the next valid, call edge. + void advanceToNextEdge() { + while (I != E && (!*I || !I->isCall())) + ++I; + } + + // Build the iterator for a specific position in the edge list. + call_iterator(VectorImplT::iterator BaseI, VectorImplT::iterator E) + : iterator_adaptor_base(BaseI), E(E) { + advanceToNextEdge(); + } + + public: + call_iterator() = default; + + using iterator_adaptor_base::operator++; + call_iterator &operator++() { + ++I; + advanceToNextEdge(); + return *this; + } + }; + + iterator begin() { return iterator(Edges.begin(), Edges.end()); } + iterator end() { return iterator(Edges.end(), Edges.end()); } + + Edge &operator[](int i) { return Edges[i]; } + Edge &operator[](Node &N) { + assert(EdgeIndexMap.find(&N) != EdgeIndexMap.end() && "No such edge!"); + auto &E = Edges[EdgeIndexMap.find(&N)->second]; + assert(E && "Dead or null edge!"); + return E; + } + + Edge *lookup(Node &N) { + auto EI = EdgeIndexMap.find(&N); + if (EI == EdgeIndexMap.end()) + return nullptr; + auto &E = Edges[EI->second]; + return E ? &E : nullptr; + } + + call_iterator call_begin() { + return call_iterator(Edges.begin(), Edges.end()); + } + call_iterator call_end() { return call_iterator(Edges.end(), Edges.end()); } + + iterator_range<call_iterator> calls() { + return make_range(call_begin(), call_end()); + } + + bool empty() { + for (auto &E : Edges) + if (E) + return false; + + return true; + } + + private: + VectorT Edges; + DenseMap<Node *, int> EdgeIndexMap; + + EdgeSequence() = default; + + /// Internal helper to insert an edge to a node. + void insertEdgeInternal(Node &ChildN, Edge::Kind EK); + + /// Internal helper to change an edge kind. + void setEdgeKind(Node &ChildN, Edge::Kind EK); + + /// Internal helper to remove the edge to the given function. + bool removeEdgeInternal(Node &ChildN); + + /// Internal helper to replace an edge key with a new one. + /// + /// This should be used when the function for a particular node in the + /// graph gets replaced and we are updating all of the edges to that node + /// to use the new function as the key. + void replaceEdgeKey(Function &OldTarget, Function &NewTarget); + }; + + /// A node in the call graph. + /// + /// This represents a single node. It's primary roles are to cache the list of + /// callees, de-duplicate and provide fast testing of whether a function is + /// a callee, and facilitate iteration of child nodes in the graph. + /// + /// The node works much like an optional in order to lazily populate the + /// edges of each node. Until populated, there are no edges. Once populated, + /// you can access the edges by dereferencing the node or using the `->` + /// operator as if the node was an `Optional<EdgeSequence>`. + class Node { + friend class LazyCallGraph; + friend class LazyCallGraph::RefSCC; + + public: + LazyCallGraph &getGraph() const { return *G; } + + Function &getFunction() const { return *F; } + + StringRef getName() const { return F->getName(); } + + /// Equality is defined as address equality. + bool operator==(const Node &N) const { return this == &N; } + bool operator!=(const Node &N) const { return !operator==(N); } + + /// Tests whether the node has been populated with edges. + bool isPopulated() const { return Edges.hasValue(); } + + /// Tests whether this is actually a dead node and no longer valid. + /// + /// Users rarely interact with nodes in this state and other methods are + /// invalid. This is used to model a node in an edge list where the + /// function has been completely removed. + bool isDead() const { + assert(!G == !F && + "Both graph and function pointers should be null or non-null."); + return !G; + } + + // We allow accessing the edges by dereferencing or using the arrow + // operator, essentially wrapping the internal optional. + EdgeSequence &operator*() const { + // Rip const off because the node itself isn't changing here. + return const_cast<EdgeSequence &>(*Edges); + } + EdgeSequence *operator->() const { return &**this; } + + /// Populate the edges of this node if necessary. + /// + /// The first time this is called it will populate the edges for this node + /// in the graph. It does this by scanning the underlying function, so once + /// this is done, any changes to that function must be explicitly reflected + /// in updates to the graph. + /// + /// \returns the populated \c EdgeSequence to simplify walking it. + /// + /// This will not update or re-scan anything if called repeatedly. Instead, + /// the edge sequence is cached and returned immediately on subsequent + /// calls. + EdgeSequence &populate() { + if (Edges) + return *Edges; + + return populateSlow(); + } + + private: + LazyCallGraph *G; + Function *F; + + // We provide for the DFS numbering and Tarjan walk lowlink numbers to be + // stored directly within the node. These are both '-1' when nodes are part + // of an SCC (or RefSCC), or '0' when not yet reached in a DFS walk. + int DFSNumber = 0; + int LowLink = 0; + + Optional<EdgeSequence> Edges; + + /// Basic constructor implements the scanning of F into Edges and + /// EdgeIndexMap. + Node(LazyCallGraph &G, Function &F) : G(&G), F(&F) {} + + /// Implementation of the scan when populating. + EdgeSequence &populateSlow(); + + /// Internal helper to directly replace the function with a new one. + /// + /// This is used to facilitate tranfsormations which need to replace the + /// formal Function object but directly move the body and users from one to + /// the other. + void replaceFunction(Function &NewF); + + void clear() { Edges.reset(); } + + /// Print the name of this node's function. + friend raw_ostream &operator<<(raw_ostream &OS, const Node &N) { + return OS << N.F->getName(); + } + + /// Dump the name of this node's function to stderr. + void dump() const; + }; + + /// An SCC of the call graph. + /// + /// This represents a Strongly Connected Component of the direct call graph + /// -- ignoring indirect calls and function references. It stores this as + /// a collection of call graph nodes. While the order of nodes in the SCC is + /// stable, it is not any particular order. + /// + /// The SCCs are nested within a \c RefSCC, see below for details about that + /// outer structure. SCCs do not support mutation of the call graph, that + /// must be done through the containing \c RefSCC in order to fully reason + /// about the ordering and connections of the graph. + class SCC { + friend class LazyCallGraph; + friend class LazyCallGraph::Node; + + RefSCC *OuterRefSCC; + SmallVector<Node *, 1> Nodes; + + template <typename NodeRangeT> + SCC(RefSCC &OuterRefSCC, NodeRangeT &&Nodes) + : OuterRefSCC(&OuterRefSCC), Nodes(std::forward<NodeRangeT>(Nodes)) {} + + void clear() { + OuterRefSCC = nullptr; + Nodes.clear(); + } + + /// Print a short descrtiption useful for debugging or logging. + /// + /// We print the function names in the SCC wrapped in '()'s and skipping + /// the middle functions if there are a large number. + // + // Note: this is defined inline to dodge issues with GCC's interpretation + // of enclosing namespaces for friend function declarations. + friend raw_ostream &operator<<(raw_ostream &OS, const SCC &C) { + OS << '('; + int i = 0; + for (LazyCallGraph::Node &N : C) { + if (i > 0) + OS << ", "; + // Elide the inner elements if there are too many. + if (i > 8) { + OS << "..., " << *C.Nodes.back(); + break; + } + OS << N; + ++i; + } + OS << ')'; + return OS; + } + + /// Dump a short description of this SCC to stderr. + void dump() const; + +#ifndef NDEBUG + /// Verify invariants about the SCC. + /// + /// This will attempt to validate all of the basic invariants within an + /// SCC, but not that it is a strongly connected componet per-se. Primarily + /// useful while building and updating the graph to check that basic + /// properties are in place rather than having inexplicable crashes later. + void verify(); +#endif + + public: + using iterator = pointee_iterator<SmallVectorImpl<Node *>::const_iterator>; + + iterator begin() const { return Nodes.begin(); } + iterator end() const { return Nodes.end(); } + + int size() const { return Nodes.size(); } + + RefSCC &getOuterRefSCC() const { return *OuterRefSCC; } + + /// Test if this SCC is a parent of \a C. + /// + /// Note that this is linear in the number of edges departing the current + /// SCC. + bool isParentOf(const SCC &C) const; + + /// Test if this SCC is an ancestor of \a C. + /// + /// Note that in the worst case this is linear in the number of edges + /// departing the current SCC and every SCC in the entire graph reachable + /// from this SCC. Thus this very well may walk every edge in the entire + /// call graph! Do not call this in a tight loop! + bool isAncestorOf(const SCC &C) const; + + /// Test if this SCC is a child of \a C. + /// + /// See the comments for \c isParentOf for detailed notes about the + /// complexity of this routine. + bool isChildOf(const SCC &C) const { return C.isParentOf(*this); } + + /// Test if this SCC is a descendant of \a C. + /// + /// See the comments for \c isParentOf for detailed notes about the + /// complexity of this routine. + bool isDescendantOf(const SCC &C) const { return C.isAncestorOf(*this); } + + /// Provide a short name by printing this SCC to a std::string. + /// + /// This copes with the fact that we don't have a name per-se for an SCC + /// while still making the use of this in debugging and logging useful. + std::string getName() const { + std::string Name; + raw_string_ostream OS(Name); + OS << *this; + OS.flush(); + return Name; + } + }; + + /// A RefSCC of the call graph. + /// + /// This models a Strongly Connected Component of function reference edges in + /// the call graph. As opposed to actual SCCs, these can be used to scope + /// subgraphs of the module which are independent from other subgraphs of the + /// module because they do not reference it in any way. This is also the unit + /// where we do mutation of the graph in order to restrict mutations to those + /// which don't violate this independence. + /// + /// A RefSCC contains a DAG of actual SCCs. All the nodes within the RefSCC + /// are necessarily within some actual SCC that nests within it. Since + /// a direct call *is* a reference, there will always be at least one RefSCC + /// around any SCC. + class RefSCC { + friend class LazyCallGraph; + friend class LazyCallGraph::Node; + + LazyCallGraph *G; + + /// A postorder list of the inner SCCs. + SmallVector<SCC *, 4> SCCs; + + /// A map from SCC to index in the postorder list. + SmallDenseMap<SCC *, int, 4> SCCIndices; + + /// Fast-path constructor. RefSCCs should instead be constructed by calling + /// formRefSCCFast on the graph itself. + RefSCC(LazyCallGraph &G); + + void clear() { + SCCs.clear(); + SCCIndices.clear(); + } + + /// Print a short description useful for debugging or logging. + /// + /// We print the SCCs wrapped in '[]'s and skipping the middle SCCs if + /// there are a large number. + // + // Note: this is defined inline to dodge issues with GCC's interpretation + // of enclosing namespaces for friend function declarations. + friend raw_ostream &operator<<(raw_ostream &OS, const RefSCC &RC) { + OS << '['; + int i = 0; + for (LazyCallGraph::SCC &C : RC) { + if (i > 0) + OS << ", "; + // Elide the inner elements if there are too many. + if (i > 4) { + OS << "..., " << *RC.SCCs.back(); + break; + } + OS << C; + ++i; + } + OS << ']'; + return OS; + } + + /// Dump a short description of this RefSCC to stderr. + void dump() const; + +#ifndef NDEBUG + /// Verify invariants about the RefSCC and all its SCCs. + /// + /// This will attempt to validate all of the invariants *within* the + /// RefSCC, but not that it is a strongly connected component of the larger + /// graph. This makes it useful even when partially through an update. + /// + /// Invariants checked: + /// - SCCs and their indices match. + /// - The SCCs list is in fact in post-order. + void verify(); +#endif + + /// Handle any necessary parent set updates after inserting a trivial ref + /// or call edge. + void handleTrivialEdgeInsertion(Node &SourceN, Node &TargetN); + + public: + using iterator = pointee_iterator<SmallVectorImpl<SCC *>::const_iterator>; + using range = iterator_range<iterator>; + using parent_iterator = + pointee_iterator<SmallPtrSetImpl<RefSCC *>::const_iterator>; + + iterator begin() const { return SCCs.begin(); } + iterator end() const { return SCCs.end(); } + + ssize_t size() const { return SCCs.size(); } + + SCC &operator[](int Idx) { return *SCCs[Idx]; } + + iterator find(SCC &C) const { + return SCCs.begin() + SCCIndices.find(&C)->second; + } + + /// Test if this RefSCC is a parent of \a RC. + /// + /// CAUTION: This method walks every edge in the \c RefSCC, it can be very + /// expensive. + bool isParentOf(const RefSCC &RC) const; + + /// Test if this RefSCC is an ancestor of \a RC. + /// + /// CAUTION: This method walks the directed graph of edges as far as + /// necessary to find a possible path to the argument. In the worst case + /// this may walk the entire graph and can be extremely expensive. + bool isAncestorOf(const RefSCC &RC) const; + + /// Test if this RefSCC is a child of \a RC. + /// + /// CAUTION: This method walks every edge in the argument \c RefSCC, it can + /// be very expensive. + bool isChildOf(const RefSCC &RC) const { return RC.isParentOf(*this); } + + /// Test if this RefSCC is a descendant of \a RC. + /// + /// CAUTION: This method walks the directed graph of edges as far as + /// necessary to find a possible path from the argument. In the worst case + /// this may walk the entire graph and can be extremely expensive. + bool isDescendantOf(const RefSCC &RC) const { + return RC.isAncestorOf(*this); + } + + /// Provide a short name by printing this RefSCC to a std::string. + /// + /// This copes with the fact that we don't have a name per-se for an RefSCC + /// while still making the use of this in debugging and logging useful. + std::string getName() const { + std::string Name; + raw_string_ostream OS(Name); + OS << *this; + OS.flush(); + return Name; + } + + ///@{ + /// \name Mutation API + /// + /// These methods provide the core API for updating the call graph in the + /// presence of (potentially still in-flight) DFS-found RefSCCs and SCCs. + /// + /// Note that these methods sometimes have complex runtimes, so be careful + /// how you call them. + + /// Make an existing internal ref edge into a call edge. + /// + /// This may form a larger cycle and thus collapse SCCs into TargetN's SCC. + /// If that happens, the optional callback \p MergedCB will be invoked (if + /// provided) on the SCCs being merged away prior to actually performing + /// the merge. Note that this will never include the target SCC as that + /// will be the SCC functions are merged into to resolve the cycle. Once + /// this function returns, these merged SCCs are not in a valid state but + /// the pointers will remain valid until destruction of the parent graph + /// instance for the purpose of clearing cached information. This function + /// also returns 'true' if a cycle was formed and some SCCs merged away as + /// a convenience. + /// + /// After this operation, both SourceN's SCC and TargetN's SCC may move + /// position within this RefSCC's postorder list. Any SCCs merged are + /// merged into the TargetN's SCC in order to preserve reachability analyses + /// which took place on that SCC. + bool switchInternalEdgeToCall( + Node &SourceN, Node &TargetN, + function_ref<void(ArrayRef<SCC *> MergedSCCs)> MergeCB = {}); + + /// Make an existing internal call edge between separate SCCs into a ref + /// edge. + /// + /// If SourceN and TargetN in separate SCCs within this RefSCC, changing + /// the call edge between them to a ref edge is a trivial operation that + /// does not require any structural changes to the call graph. + void switchTrivialInternalEdgeToRef(Node &SourceN, Node &TargetN); + + /// Make an existing internal call edge within a single SCC into a ref + /// edge. + /// + /// Since SourceN and TargetN are part of a single SCC, this SCC may be + /// split up due to breaking a cycle in the call edges that formed it. If + /// that happens, then this routine will insert new SCCs into the postorder + /// list *before* the SCC of TargetN (previously the SCC of both). This + /// preserves postorder as the TargetN can reach all of the other nodes by + /// definition of previously being in a single SCC formed by the cycle from + /// SourceN to TargetN. + /// + /// The newly added SCCs are added *immediately* and contiguously + /// prior to the TargetN SCC and return the range covering the new SCCs in + /// the RefSCC's postorder sequence. You can directly iterate the returned + /// range to observe all of the new SCCs in postorder. + /// + /// Note that if SourceN and TargetN are in separate SCCs, the simpler + /// routine `switchTrivialInternalEdgeToRef` should be used instead. + iterator_range<iterator> switchInternalEdgeToRef(Node &SourceN, + Node &TargetN); + + /// Make an existing outgoing ref edge into a call edge. + /// + /// Note that this is trivial as there are no cyclic impacts and there + /// remains a reference edge. + void switchOutgoingEdgeToCall(Node &SourceN, Node &TargetN); + + /// Make an existing outgoing call edge into a ref edge. + /// + /// This is trivial as there are no cyclic impacts and there remains + /// a reference edge. + void switchOutgoingEdgeToRef(Node &SourceN, Node &TargetN); + + /// Insert a ref edge from one node in this RefSCC to another in this + /// RefSCC. + /// + /// This is always a trivial operation as it doesn't change any part of the + /// graph structure besides connecting the two nodes. + /// + /// Note that we don't support directly inserting internal *call* edges + /// because that could change the graph structure and requires returning + /// information about what became invalid. As a consequence, the pattern + /// should be to first insert the necessary ref edge, and then to switch it + /// to a call edge if needed and handle any invalidation that results. See + /// the \c switchInternalEdgeToCall routine for details. + void insertInternalRefEdge(Node &SourceN, Node &TargetN); + + /// Insert an edge whose parent is in this RefSCC and child is in some + /// child RefSCC. + /// + /// There must be an existing path from the \p SourceN to the \p TargetN. + /// This operation is inexpensive and does not change the set of SCCs and + /// RefSCCs in the graph. + void insertOutgoingEdge(Node &SourceN, Node &TargetN, Edge::Kind EK); + + /// Insert an edge whose source is in a descendant RefSCC and target is in + /// this RefSCC. + /// + /// There must be an existing path from the target to the source in this + /// case. + /// + /// NB! This is has the potential to be a very expensive function. It + /// inherently forms a cycle in the prior RefSCC DAG and we have to merge + /// RefSCCs to resolve that cycle. But finding all of the RefSCCs which + /// participate in the cycle can in the worst case require traversing every + /// RefSCC in the graph. Every attempt is made to avoid that, but passes + /// must still exercise caution calling this routine repeatedly. + /// + /// Also note that this can only insert ref edges. In order to insert + /// a call edge, first insert a ref edge and then switch it to a call edge. + /// These are intentionally kept as separate interfaces because each step + /// of the operation invalidates a different set of data structures. + /// + /// This returns all the RefSCCs which were merged into the this RefSCC + /// (the target's). This allows callers to invalidate any cached + /// information. + /// + /// FIXME: We could possibly optimize this quite a bit for cases where the + /// caller and callee are very nearby in the graph. See comments in the + /// implementation for details, but that use case might impact users. + SmallVector<RefSCC *, 1> insertIncomingRefEdge(Node &SourceN, + Node &TargetN); + + /// Remove an edge whose source is in this RefSCC and target is *not*. + /// + /// This removes an inter-RefSCC edge. All inter-RefSCC edges originating + /// from this SCC have been fully explored by any in-flight DFS graph + /// formation, so this is always safe to call once you have the source + /// RefSCC. + /// + /// This operation does not change the cyclic structure of the graph and so + /// is very inexpensive. It may change the connectivity graph of the SCCs + /// though, so be careful calling this while iterating over them. + void removeOutgoingEdge(Node &SourceN, Node &TargetN); + + /// Remove a list of ref edges which are entirely within this RefSCC. + /// + /// Both the \a SourceN and all of the \a TargetNs must be within this + /// RefSCC. Removing these edges may break cycles that form this RefSCC and + /// thus this operation may change the RefSCC graph significantly. In + /// particular, this operation will re-form new RefSCCs based on the + /// remaining connectivity of the graph. The following invariants are + /// guaranteed to hold after calling this method: + /// + /// 1) If a ref-cycle remains after removal, it leaves this RefSCC intact + /// and in the graph. No new RefSCCs are built. + /// 2) Otherwise, this RefSCC will be dead after this call and no longer in + /// the graph or the postorder traversal of the call graph. Any iterator + /// pointing at this RefSCC will become invalid. + /// 3) All newly formed RefSCCs will be returned and the order of the + /// RefSCCs returned will be a valid postorder traversal of the new + /// RefSCCs. + /// 4) No RefSCC other than this RefSCC has its member set changed (this is + /// inherent in the definition of removing such an edge). + /// + /// These invariants are very important to ensure that we can build + /// optimization pipelines on top of the CGSCC pass manager which + /// intelligently update the RefSCC graph without invalidating other parts + /// of the RefSCC graph. + /// + /// Note that we provide no routine to remove a *call* edge. Instead, you + /// must first switch it to a ref edge using \c switchInternalEdgeToRef. + /// This split API is intentional as each of these two steps can invalidate + /// a different aspect of the graph structure and needs to have the + /// invalidation handled independently. + /// + /// The runtime complexity of this method is, in the worst case, O(V+E) + /// where V is the number of nodes in this RefSCC and E is the number of + /// edges leaving the nodes in this RefSCC. Note that E includes both edges + /// within this RefSCC and edges from this RefSCC to child RefSCCs. Some + /// effort has been made to minimize the overhead of common cases such as + /// self-edges and edge removals which result in a spanning tree with no + /// more cycles. + SmallVector<RefSCC *, 1> removeInternalRefEdge(Node &SourceN, + ArrayRef<Node *> TargetNs); + + /// A convenience wrapper around the above to handle trivial cases of + /// inserting a new call edge. + /// + /// This is trivial whenever the target is in the same SCC as the source or + /// the edge is an outgoing edge to some descendant SCC. In these cases + /// there is no change to the cyclic structure of SCCs or RefSCCs. + /// + /// To further make calling this convenient, it also handles inserting + /// already existing edges. + void insertTrivialCallEdge(Node &SourceN, Node &TargetN); + + /// A convenience wrapper around the above to handle trivial cases of + /// inserting a new ref edge. + /// + /// This is trivial whenever the target is in the same RefSCC as the source + /// or the edge is an outgoing edge to some descendant RefSCC. In these + /// cases there is no change to the cyclic structure of the RefSCCs. + /// + /// To further make calling this convenient, it also handles inserting + /// already existing edges. + void insertTrivialRefEdge(Node &SourceN, Node &TargetN); + + /// Directly replace a node's function with a new function. + /// + /// This should be used when moving the body and users of a function to + /// a new formal function object but not otherwise changing the call graph + /// structure in any way. + /// + /// It requires that the old function in the provided node have zero uses + /// and the new function must have calls and references to it establishing + /// an equivalent graph. + void replaceNodeFunction(Node &N, Function &NewF); + + ///@} + }; + + /// A post-order depth-first RefSCC iterator over the call graph. + /// + /// This iterator walks the cached post-order sequence of RefSCCs. However, + /// it trades stability for flexibility. It is restricted to a forward + /// iterator but will survive mutations which insert new RefSCCs and continue + /// to point to the same RefSCC even if it moves in the post-order sequence. + class postorder_ref_scc_iterator + : public iterator_facade_base<postorder_ref_scc_iterator, + std::forward_iterator_tag, RefSCC> { + friend class LazyCallGraph; + friend class LazyCallGraph::Node; + + /// Nonce type to select the constructor for the end iterator. + struct IsAtEndT {}; + + LazyCallGraph *G; + RefSCC *RC = nullptr; + + /// Build the begin iterator for a node. + postorder_ref_scc_iterator(LazyCallGraph &G) : G(&G), RC(getRC(G, 0)) {} + + /// Build the end iterator for a node. This is selected purely by overload. + postorder_ref_scc_iterator(LazyCallGraph &G, IsAtEndT /*Nonce*/) : G(&G) {} + + /// Get the post-order RefSCC at the given index of the postorder walk, + /// populating it if necessary. + static RefSCC *getRC(LazyCallGraph &G, int Index) { + if (Index == (int)G.PostOrderRefSCCs.size()) + // We're at the end. + return nullptr; + + return G.PostOrderRefSCCs[Index]; + } + + public: + bool operator==(const postorder_ref_scc_iterator &Arg) const { + return G == Arg.G && RC == Arg.RC; + } + + reference operator*() const { return *RC; } + + using iterator_facade_base::operator++; + postorder_ref_scc_iterator &operator++() { + assert(RC && "Cannot increment the end iterator!"); + RC = getRC(*G, G->RefSCCIndices.find(RC)->second + 1); + return *this; + } + }; + + /// Construct a graph for the given module. + /// + /// This sets up the graph and computes all of the entry points of the graph. + /// No function definitions are scanned until their nodes in the graph are + /// requested during traversal. + LazyCallGraph(Module &M, + function_ref<TargetLibraryInfo &(Function &)> GetTLI); + + LazyCallGraph(LazyCallGraph &&G); + LazyCallGraph &operator=(LazyCallGraph &&RHS); + + EdgeSequence::iterator begin() { return EntryEdges.begin(); } + EdgeSequence::iterator end() { return EntryEdges.end(); } + + void buildRefSCCs(); + + postorder_ref_scc_iterator postorder_ref_scc_begin() { + if (!EntryEdges.empty()) + assert(!PostOrderRefSCCs.empty() && + "Must form RefSCCs before iterating them!"); + return postorder_ref_scc_iterator(*this); + } + postorder_ref_scc_iterator postorder_ref_scc_end() { + if (!EntryEdges.empty()) + assert(!PostOrderRefSCCs.empty() && + "Must form RefSCCs before iterating them!"); + return postorder_ref_scc_iterator(*this, + postorder_ref_scc_iterator::IsAtEndT()); + } + + iterator_range<postorder_ref_scc_iterator> postorder_ref_sccs() { + return make_range(postorder_ref_scc_begin(), postorder_ref_scc_end()); + } + + /// Lookup a function in the graph which has already been scanned and added. + Node *lookup(const Function &F) const { return NodeMap.lookup(&F); } + + /// Lookup a function's SCC in the graph. + /// + /// \returns null if the function hasn't been assigned an SCC via the RefSCC + /// iterator walk. + SCC *lookupSCC(Node &N) const { return SCCMap.lookup(&N); } + + /// Lookup a function's RefSCC in the graph. + /// + /// \returns null if the function hasn't been assigned a RefSCC via the + /// RefSCC iterator walk. + RefSCC *lookupRefSCC(Node &N) const { + if (SCC *C = lookupSCC(N)) + return &C->getOuterRefSCC(); + + return nullptr; + } + + /// Get a graph node for a given function, scanning it to populate the graph + /// data as necessary. + Node &get(Function &F) { + Node *&N = NodeMap[&F]; + if (N) + return *N; + + return insertInto(F, N); + } + + /// Get the sequence of known and defined library functions. + /// + /// These functions, because they are known to LLVM, can have calls + /// introduced out of thin air from arbitrary IR. + ArrayRef<Function *> getLibFunctions() const { + return LibFunctions.getArrayRef(); + } + + /// Test whether a function is a known and defined library function tracked by + /// the call graph. + /// + /// Because these functions are known to LLVM they are specially modeled in + /// the call graph and even when all IR-level references have been removed + /// remain active and reachable. + bool isLibFunction(Function &F) const { return LibFunctions.count(&F); } + + ///@{ + /// \name Pre-SCC Mutation API + /// + /// These methods are only valid to call prior to forming any SCCs for this + /// call graph. They can be used to update the core node-graph during + /// a node-based inorder traversal that precedes any SCC-based traversal. + /// + /// Once you begin manipulating a call graph's SCCs, most mutation of the + /// graph must be performed via a RefSCC method. There are some exceptions + /// below. + + /// Update the call graph after inserting a new edge. + void insertEdge(Node &SourceN, Node &TargetN, Edge::Kind EK); + + /// Update the call graph after inserting a new edge. + void insertEdge(Function &Source, Function &Target, Edge::Kind EK) { + return insertEdge(get(Source), get(Target), EK); + } + + /// Update the call graph after deleting an edge. + void removeEdge(Node &SourceN, Node &TargetN); + + /// Update the call graph after deleting an edge. + void removeEdge(Function &Source, Function &Target) { + return removeEdge(get(Source), get(Target)); + } + + ///@} + + ///@{ + /// \name General Mutation API + /// + /// There are a very limited set of mutations allowed on the graph as a whole + /// once SCCs have started to be formed. These routines have strict contracts + /// but may be called at any point. + + /// Remove a dead function from the call graph (typically to delete it). + /// + /// Note that the function must have an empty use list, and the call graph + /// must be up-to-date prior to calling this. That means it is by itself in + /// a maximal SCC which is by itself in a maximal RefSCC, etc. No structural + /// changes result from calling this routine other than potentially removing + /// entry points into the call graph. + /// + /// If SCC formation has begun, this function must not be part of the current + /// DFS in order to call this safely. Typically, the function will have been + /// fully visited by the DFS prior to calling this routine. + void removeDeadFunction(Function &F); + + ///@} + + ///@{ + /// \name Static helpers for code doing updates to the call graph. + /// + /// These helpers are used to implement parts of the call graph but are also + /// useful to code doing updates or otherwise wanting to walk the IR in the + /// same patterns as when we build the call graph. + + /// Recursively visits the defined functions whose address is reachable from + /// every constant in the \p Worklist. + /// + /// Doesn't recurse through any constants already in the \p Visited set, and + /// updates that set with every constant visited. + /// + /// For each defined function, calls \p Callback with that function. + template <typename CallbackT> + static void visitReferences(SmallVectorImpl<Constant *> &Worklist, + SmallPtrSetImpl<Constant *> &Visited, + CallbackT Callback) { + while (!Worklist.empty()) { + Constant *C = Worklist.pop_back_val(); + + if (Function *F = dyn_cast<Function>(C)) { + if (!F->isDeclaration()) + Callback(*F); + continue; + } + + // The blockaddress constant expression is a weird special case, we can't + // generically walk its operands the way we do for all other constants. + if (BlockAddress *BA = dyn_cast<BlockAddress>(C)) { + // If we've already visited the function referred to by the block + // address, we don't need to revisit it. + if (Visited.count(BA->getFunction())) + continue; + + // If all of the blockaddress' users are instructions within the + // referred to function, we don't need to insert a cycle. + if (llvm::all_of(BA->users(), [&](User *U) { + if (Instruction *I = dyn_cast<Instruction>(U)) + return I->getFunction() == BA->getFunction(); + return false; + })) + continue; + + // Otherwise we should go visit the referred to function. + Visited.insert(BA->getFunction()); + Worklist.push_back(BA->getFunction()); + continue; + } + + for (Value *Op : C->operand_values()) + if (Visited.insert(cast<Constant>(Op)).second) + Worklist.push_back(cast<Constant>(Op)); + } + } + + ///@} + +private: + using node_stack_iterator = SmallVectorImpl<Node *>::reverse_iterator; + using node_stack_range = iterator_range<node_stack_iterator>; + + /// Allocator that holds all the call graph nodes. + SpecificBumpPtrAllocator<Node> BPA; + + /// Maps function->node for fast lookup. + DenseMap<const Function *, Node *> NodeMap; + + /// The entry edges into the graph. + /// + /// These edges are from "external" sources. Put another way, they + /// escape at the module scope. + EdgeSequence EntryEdges; + + /// Allocator that holds all the call graph SCCs. + SpecificBumpPtrAllocator<SCC> SCCBPA; + + /// Maps Function -> SCC for fast lookup. + DenseMap<Node *, SCC *> SCCMap; + + /// Allocator that holds all the call graph RefSCCs. + SpecificBumpPtrAllocator<RefSCC> RefSCCBPA; + + /// The post-order sequence of RefSCCs. + /// + /// This list is lazily formed the first time we walk the graph. + SmallVector<RefSCC *, 16> PostOrderRefSCCs; + + /// A map from RefSCC to the index for it in the postorder sequence of + /// RefSCCs. + DenseMap<RefSCC *, int> RefSCCIndices; + + /// Defined functions that are also known library functions which the + /// optimizer can reason about and therefore might introduce calls to out of + /// thin air. + SmallSetVector<Function *, 4> LibFunctions; + + /// Helper to insert a new function, with an already looked-up entry in + /// the NodeMap. + Node &insertInto(Function &F, Node *&MappedN); + + /// Helper to update pointers back to the graph object during moves. + void updateGraphPtrs(); + + /// Allocates an SCC and constructs it using the graph allocator. + /// + /// The arguments are forwarded to the constructor. + template <typename... Ts> SCC *createSCC(Ts &&... Args) { + return new (SCCBPA.Allocate()) SCC(std::forward<Ts>(Args)...); + } + + /// Allocates a RefSCC and constructs it using the graph allocator. + /// + /// The arguments are forwarded to the constructor. + template <typename... Ts> RefSCC *createRefSCC(Ts &&... Args) { + return new (RefSCCBPA.Allocate()) RefSCC(std::forward<Ts>(Args)...); + } + + /// Common logic for building SCCs from a sequence of roots. + /// + /// This is a very generic implementation of the depth-first walk and SCC + /// formation algorithm. It uses a generic sequence of roots and generic + /// callbacks for each step. This is designed to be used to implement both + /// the RefSCC formation and SCC formation with shared logic. + /// + /// Currently this is a relatively naive implementation of Tarjan's DFS + /// algorithm to form the SCCs. + /// + /// FIXME: We should consider newer variants such as Nuutila. + template <typename RootsT, typename GetBeginT, typename GetEndT, + typename GetNodeT, typename FormSCCCallbackT> + static void buildGenericSCCs(RootsT &&Roots, GetBeginT &&GetBegin, + GetEndT &&GetEnd, GetNodeT &&GetNode, + FormSCCCallbackT &&FormSCC); + + /// Build the SCCs for a RefSCC out of a list of nodes. + void buildSCCs(RefSCC &RC, node_stack_range Nodes); + + /// Get the index of a RefSCC within the postorder traversal. + /// + /// Requires that this RefSCC is a valid one in the (perhaps partial) + /// postorder traversed part of the graph. + int getRefSCCIndex(RefSCC &RC) { + auto IndexIt = RefSCCIndices.find(&RC); + assert(IndexIt != RefSCCIndices.end() && "RefSCC doesn't have an index!"); + assert(PostOrderRefSCCs[IndexIt->second] == &RC && + "Index does not point back at RC!"); + return IndexIt->second; + } +}; + +inline LazyCallGraph::Edge::Edge() : Value() {} +inline LazyCallGraph::Edge::Edge(Node &N, Kind K) : Value(&N, K) {} + +inline LazyCallGraph::Edge::operator bool() const { + return Value.getPointer() && !Value.getPointer()->isDead(); +} + +inline LazyCallGraph::Edge::Kind LazyCallGraph::Edge::getKind() const { + assert(*this && "Queried a null edge!"); + return Value.getInt(); +} + +inline bool LazyCallGraph::Edge::isCall() const { + assert(*this && "Queried a null edge!"); + return getKind() == Call; +} + +inline LazyCallGraph::Node &LazyCallGraph::Edge::getNode() const { + assert(*this && "Queried a null edge!"); + return *Value.getPointer(); +} + +inline Function &LazyCallGraph::Edge::getFunction() const { + assert(*this && "Queried a null edge!"); + return getNode().getFunction(); +} + +// Provide GraphTraits specializations for call graphs. +template <> struct GraphTraits<LazyCallGraph::Node *> { + using NodeRef = LazyCallGraph::Node *; + using ChildIteratorType = LazyCallGraph::EdgeSequence::iterator; + + static NodeRef getEntryNode(NodeRef N) { return N; } + static ChildIteratorType child_begin(NodeRef N) { return (*N)->begin(); } + static ChildIteratorType child_end(NodeRef N) { return (*N)->end(); } +}; +template <> struct GraphTraits<LazyCallGraph *> { + using NodeRef = LazyCallGraph::Node *; + using ChildIteratorType = LazyCallGraph::EdgeSequence::iterator; + + static NodeRef getEntryNode(NodeRef N) { return N; } + static ChildIteratorType child_begin(NodeRef N) { return (*N)->begin(); } + static ChildIteratorType child_end(NodeRef N) { return (*N)->end(); } +}; + +/// An analysis pass which computes the call graph for a module. +class LazyCallGraphAnalysis : public AnalysisInfoMixin<LazyCallGraphAnalysis> { + friend AnalysisInfoMixin<LazyCallGraphAnalysis>; + + static AnalysisKey Key; + +public: + /// Inform generic clients of the result type. + using Result = LazyCallGraph; + + /// Compute the \c LazyCallGraph for the module \c M. + /// + /// This just builds the set of entry points to the call graph. The rest is + /// built lazily as it is walked. + LazyCallGraph run(Module &M, ModuleAnalysisManager &AM) { + FunctionAnalysisManager &FAM = + AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); + auto GetTLI = [&FAM](Function &F) -> TargetLibraryInfo & { + return FAM.getResult<TargetLibraryAnalysis>(F); + }; + return LazyCallGraph(M, GetTLI); + } +}; + +/// A pass which prints the call graph to a \c raw_ostream. +/// +/// This is primarily useful for testing the analysis. +class LazyCallGraphPrinterPass + : public PassInfoMixin<LazyCallGraphPrinterPass> { + raw_ostream &OS; + +public: + explicit LazyCallGraphPrinterPass(raw_ostream &OS); + + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); +}; + +/// A pass which prints the call graph as a DOT file to a \c raw_ostream. +/// +/// This is primarily useful for visualization purposes. +class LazyCallGraphDOTPrinterPass + : public PassInfoMixin<LazyCallGraphDOTPrinterPass> { + raw_ostream &OS; + +public: + explicit LazyCallGraphDOTPrinterPass(raw_ostream &OS); + + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); +}; + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_LAZYCALLGRAPH_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/LazyValueInfo.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/LazyValueInfo.h new file mode 100644 index 0000000..74e8f50 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/LazyValueInfo.h
@@ -0,0 +1,164 @@ +//===- LazyValueInfo.h - Value constraint analysis --------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the interface for lazy computation of value constraint +// information. +// +//===----------------------------------------------------------------------===// + +#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; + class TargetLibraryInfo; + class Value; + +/// This pass computes, caches, and vends lazy value constraint information. +class LazyValueInfo { + friend class LazyValueInfoWrapperPass; + AssumptionCache *AC = nullptr; + const DataLayout *DL = nullptr; + class TargetLibraryInfo *TLI = nullptr; + DominatorTree *DT = nullptr; + void *PImpl = nullptr; + LazyValueInfo(const LazyValueInfo&) = delete; + void operator=(const LazyValueInfo&) = delete; +public: + ~LazyValueInfo(); + LazyValueInfo() {} + LazyValueInfo(AssumptionCache *AC_, const DataLayout *DL_, TargetLibraryInfo *TLI_, + DominatorTree *DT_) + : AC(AC_), DL(DL_), TLI(TLI_), DT(DT_) {} + LazyValueInfo(LazyValueInfo &&Arg) + : AC(Arg.AC), DL(Arg.DL), TLI(Arg.TLI), DT(Arg.DT), PImpl(Arg.PImpl) { + Arg.PImpl = nullptr; + } + LazyValueInfo &operator=(LazyValueInfo &&Arg) { + releaseMemory(); + AC = Arg.AC; + DL = Arg.DL; + TLI = Arg.TLI; + DT = Arg.DT; + PImpl = Arg.PImpl; + Arg.PImpl = nullptr; + return *this; + } + + /// This is used to return true/false/dunno results. + enum Tristate { + Unknown = -1, False = 0, True = 1 + }; + + // Public query interface. + + /// Determine whether the specified value comparison with a constant is known + /// to be true or false on the specified CFG edge. + /// Pred is a CmpInst predicate. + Tristate getPredicateOnEdge(unsigned Pred, Value *V, Constant *C, + BasicBlock *FromBB, BasicBlock *ToBB, + Instruction *CxtI = nullptr); + + /// Determine whether the specified value comparison with a constant is known + /// to be true or false at the specified instruction + /// (from an assume intrinsic). Pred is a CmpInst predicate. + Tristate getPredicateAt(unsigned Pred, Value *V, Constant *C, + Instruction *CxtI); + + /// Determine whether the specified value is known to be a + /// 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, + Instruction *CxtI = nullptr); + + /// Return the ConstantRage constraint that is known to hold for the + /// specified value on the specified edge. This may be only be called + /// on integer-typed Values. + ConstantRange getConstantRangeOnEdge(Value *V, BasicBlock *FromBB, + BasicBlock *ToBB, + Instruction *CxtI = nullptr); + + /// Inform the analysis cache that we have threaded an edge from + /// PredBB to OldSucc to be from PredBB to NewSucc instead. + void threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc, BasicBlock *NewSucc); + + /// Inform the analysis cache that we have erased a block. + void eraseBlock(BasicBlock *BB); + + /// Print the \LazyValueInfo Analysis. + /// We pass in the DTree that is required for identifying which basic blocks + /// we can solve/print for, in the LVIPrinter. The DT is optional + /// in LVI, so we need to pass it here as an argument. + void printLVI(Function &F, DominatorTree &DTree, raw_ostream &OS); + + /// Disables use of the DominatorTree within LVI. + void disableDT(); + + /// Enables use of the DominatorTree within LVI. Does nothing if the class + /// instance was initialized without a DT pointer. + void enableDT(); + + // For old PM pass. Delete once LazyValueInfoWrapperPass is gone. + void releaseMemory(); + + /// Handle invalidation events in the new pass manager. + bool invalidate(Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &Inv); +}; + +/// Analysis to compute lazy value information. +class LazyValueAnalysis : public AnalysisInfoMixin<LazyValueAnalysis> { +public: + typedef LazyValueInfo Result; + Result run(Function &F, FunctionAnalysisManager &FAM); + +private: + static AnalysisKey Key; + 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(); + ~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 + +#endif +
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/LegacyDivergenceAnalysis.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/LegacyDivergenceAnalysis.h new file mode 100644 index 0000000..0770093 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/LegacyDivergenceAnalysis.h
@@ -0,0 +1,70 @@ +//===- llvm/Analysis/LegacyDivergenceAnalysis.h - KernelDivergence Analysis -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// The kernel divergence analysis is an LLVM pass which can be used to find out +// if a branch instruction in a GPU program (kernel) is divergent or not. It can help +// branch optimizations such as jump threading and loop unswitching to make +// better decisions. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_ANALYSIS_LEGACY_DIVERGENCE_ANALYSIS_H +#define LLVM_ANALYSIS_LEGACY_DIVERGENCE_ANALYSIS_H + +#include "llvm/ADT/DenseSet.h" +#include "llvm/Analysis/DivergenceAnalysis.h" +#include "llvm/Pass.h" + +namespace llvm { +class Value; +class Function; +class GPUDivergenceAnalysis; +class LegacyDivergenceAnalysis : public FunctionPass { +public: + static char ID; + + LegacyDivergenceAnalysis(); + + void getAnalysisUsage(AnalysisUsage &AU) const override; + + bool runOnFunction(Function &F) override; + + // Print all divergent branches in the function. + void print(raw_ostream &OS, const Module *) const override; + + // Returns true if V is divergent at its definition. + bool isDivergent(const Value *V) const; + + // Returns true if U is divergent. Uses of a uniform value can be divergent. + bool isDivergentUse(const Use *U) const; + + // Returns true if V is uniform/non-divergent. + bool isUniform(const Value *V) const { return !isDivergent(V); } + + // Returns true if U is uniform/non-divergent. Uses of a uniform value can be + // divergent. + bool isUniformUse(const Use *U) const { return !isDivergentUse(U); } + + // Keep the analysis results uptodate by removing an erased value. + void removeValue(const Value *V) { DivergentValues.erase(V); } + +private: + // Whether analysis should be performed by GPUDivergenceAnalysis. + bool shouldUseGPUDivergenceAnalysis(const Function &F) const; + + // (optional) handle to new DivergenceAnalysis + std::unique_ptr<GPUDivergenceAnalysis> gpuDA; + + // Stores all divergent values. + DenseSet<const Value *> DivergentValues; + + // Stores divergent uses of possibly uniform values. + DenseSet<const Use *> DivergentUses; +}; +} // End llvm namespace + +#endif //LLVM_ANALYSIS_LEGACY_DIVERGENCE_ANALYSIS_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/Lint.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/Lint.h new file mode 100644 index 0000000..0fea81e --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/Lint.h
@@ -0,0 +1,48 @@ +//===-- llvm/Analysis/Lint.h - LLVM IR Lint ---------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines lint interfaces that can be used for some sanity checking +// of input to the system, and for checking that transformations +// haven't done something bad. In contrast to the Verifier, the Lint checker +// checks for undefined behavior or constructions with likely unintended +// behavior. +// +// To see what specifically is checked, look at Lint.cpp +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LINT_H +#define LLVM_ANALYSIS_LINT_H + +namespace llvm { + +class FunctionPass; +class Module; +class Function; + +/// Create a lint pass. +/// +/// Check a module or function. +FunctionPass *createLintPass(); + +/// Check a module. +/// +/// This should only be used for debugging, because it plays games with +/// PassManagers and stuff. +void lintModule( + const Module &M ///< The module to be checked +); + +// lintFunction - Check a function. +void lintFunction( + const Function &F ///< The function to be checked +); + +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/Loads.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/Loads.h new file mode 100644 index 0000000..9604b25 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/Loads.h
@@ -0,0 +1,157 @@ +//===- Loads.h - Local load analysis --------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file declares simple local analyses for load instructions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LOADS_H +#define LLVM_ANALYSIS_LOADS_H + +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/Support/CommandLine.h" + +namespace llvm { + +class DataLayout; +class Loop; +class MDNode; +class ScalarEvolution; + +/// 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, Type *Ty, + 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, Type *Ty, + MaybeAlign Alignment, + const DataLayout &DL, + const Instruction *CtxI = nullptr, + const DominatorTree *DT = nullptr); + +/// Returns true if V is always dereferenceable for Size byte 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, Align Alignment, + const APInt &Size, const DataLayout &DL, + const Instruction *CtxI = nullptr, + const DominatorTree *DT = nullptr); + +/// Return true if we know that executing a load 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, MaybeAlign Alignment, APInt &Size, + const DataLayout &DL, + Instruction *ScanFrom = nullptr, + const DominatorTree *DT = nullptr); + +/// Return true if we can prove that the given load (which is assumed to be +/// within the specified loop) would access only dereferenceable memory, and +/// be properly aligned on every iteration of the specified loop regardless of +/// its placement within the loop. (i.e. does not require predication beyond +/// that required by the the header itself and could be hoisted into the header +/// if desired.) This is more powerful than the variants above when the +/// address loaded from is analyzeable by SCEV. +bool isDereferenceableAndAlignedInLoop(LoadInst *LI, Loop *L, + ScalarEvolution &SE, + DominatorTree &DT); + +/// Return true if we know that executing a load 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, Type *Ty, MaybeAlign Alignment, + const DataLayout &DL, + Instruction *ScanFrom = nullptr, + const DominatorTree *DT = nullptr); + +/// The default number of maximum instructions to scan in the block, used by +/// FindAvailableLoadedValue(). +extern cl::opt<unsigned> DefMaxInstsToScan; + +/// Scan backwards to see if we have the value of the given load available +/// locally within a small number of instructions. +/// +/// 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. +/// +/// 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.) +/// +/// \param Load The load we want to replace. +/// \param ScanBB The basic block to scan. +/// \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] 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, + bool *IsLoadCSE = nullptr, + unsigned *NumScanedInst = nullptr); + +/// Scan backwards to see if we have the value of the given pointer available +/// locally within a small number of instructions. +/// +/// 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. +/// +/// \param Ptr The pointer we want the load and store to originate from. +/// \param AccessTy The access type of the pointer. +/// \param AtLeastAtomic Are we looking for at-least an atomic load/store ? In +/// case it is false, we can return an atomic or non-atomic load or store. In +/// case it is true, we need to return an atomic load or store. +/// \param ScanBB The basic block to scan. +/// \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] IsLoad 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 *FindAvailablePtrLoadStore(Value *Ptr, Type *AccessTy, bool AtLeastAtomic, + BasicBlock *ScanBB, + BasicBlock::iterator &ScanFrom, + unsigned MaxInstsToScan, AliasAnalysis *AA, + bool *IsLoad, unsigned *NumScanedInst); +} + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/LoopAccessAnalysis.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/LoopAccessAnalysis.h new file mode 100644 index 0000000..7f8639a --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/LoopAccessAnalysis.h
@@ -0,0 +1,788 @@ +//===- llvm/Analysis/LoopAccessAnalysis.h -----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the interface for the loop memory dependence framework that +// was originally developed for the Loop Vectorizer. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LOOPACCESSANALYSIS_H +#define LLVM_ANALYSIS_LOOPACCESSANALYSIS_H + +#include "llvm/ADT/EquivalenceClasses.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/AliasSetTracker.h" +#include "llvm/Analysis/LoopAnalysisManager.h" +#include "llvm/Analysis/ScalarEvolutionExpressions.h" +#include "llvm/IR/DiagnosticInfo.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/Pass.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +class Value; +class DataLayout; +class ScalarEvolution; +class Loop; +class SCEV; +class SCEVUnionPredicate; +class LoopAccessInfo; +class OptimizationRemarkEmitter; + +/// Collection of parameters shared beetween the Loop Vectorizer and the +/// Loop Access Analysis. +struct VectorizerParams { + /// Maximum SIMD width. + static const unsigned MaxVectorWidth; + + /// VF as overridden by the user. + static unsigned VectorizationFactor; + /// Interleave factor as overridden by the user. + static unsigned VectorizationInterleave; + /// True if force-vector-interleave was specified by the user. + static bool isInterleaveForced(); + + /// \When performing memory disambiguation checks at runtime do not + /// make more than this number of comparisons. + static unsigned RuntimeMemoryCheckThreshold; +}; + +/// Checks memory dependences among accesses to the same underlying +/// object to determine whether there vectorization is legal or not (and at +/// which vectorization factor). +/// +/// Note: This class will compute a conservative dependence for access to +/// different underlying pointers. Clients, such as the loop vectorizer, will +/// sometimes deal these potential dependencies by emitting runtime checks. +/// +/// We use the ScalarEvolution framework to symbolically evalutate access +/// functions pairs. Since we currently don't restructure the loop we can rely +/// on the program order of memory accesses to determine their safety. +/// At the moment we will only deem accesses as safe for: +/// * A negative constant distance assuming program order. +/// +/// Safe: tmp = a[i + 1]; OR a[i + 1] = x; +/// a[i] = tmp; y = a[i]; +/// +/// The latter case is safe because later checks guarantuee that there can't +/// be a cycle through a phi node (that is, we check that "x" and "y" is not +/// the same variable: a header phi can only be an induction or a reduction, a +/// reduction can't have a memory sink, an induction can't have a memory +/// source). This is important and must not be violated (or we have to +/// resort to checking for cycles through memory). +/// +/// * A positive constant distance assuming program order that is bigger +/// than the biggest memory access. +/// +/// tmp = a[i] OR b[i] = x +/// a[i+2] = tmp y = b[i+2]; +/// +/// Safe distance: 2 x sizeof(a[0]), and 2 x sizeof(b[0]), respectively. +/// +/// * Zero distances and all accesses have the same size. +/// +class MemoryDepChecker { +public: + typedef PointerIntPair<Value *, 1, bool> MemAccessInfo; + typedef SmallVector<MemAccessInfo, 8> MemAccessInfoList; + /// Set of potential dependent memory accesses. + typedef EquivalenceClasses<MemAccessInfo> DepCandidates; + + /// Type to keep track of the status of the dependence check. The order of + /// the elements is important and has to be from most permissive to least + /// permissive. + enum class VectorizationSafetyStatus { + // Can vectorize safely without RT checks. All dependences are known to be + // safe. + Safe, + // Can possibly vectorize with RT checks to overcome unknown dependencies. + PossiblySafeWithRtChecks, + // Cannot vectorize due to known unsafe dependencies. + Unsafe, + }; + + /// Dependece between memory access instructions. + struct Dependence { + /// The type of the dependence. + enum DepType { + // No dependence. + NoDep, + // We couldn't determine the direction or the distance. + Unknown, + // Lexically forward. + // + // FIXME: If we only have loop-independent forward dependences (e.g. a + // read and write of A[i]), LAA will locally deem the dependence "safe" + // without querying the MemoryDepChecker. Therefore we can miss + // enumerating loop-independent forward dependences in + // getDependences. Note that as soon as there are different + // indices used to access the same array, the MemoryDepChecker *is* + // queried and the dependence list is complete. + Forward, + // Forward, but if vectorized, is likely to prevent store-to-load + // forwarding. + ForwardButPreventsForwarding, + // Lexically backward. + Backward, + // Backward, but the distance allows a vectorization factor of + // MaxSafeDepDistBytes. + BackwardVectorizable, + // Same, but may prevent store-to-load forwarding. + BackwardVectorizableButPreventsForwarding + }; + + /// String version of the types. + static const char *DepName[]; + + /// Index of the source of the dependence in the InstMap vector. + unsigned Source; + /// Index of the destination of the dependence in the InstMap vector. + unsigned Destination; + /// The type of the dependence. + DepType Type; + + Dependence(unsigned Source, unsigned Destination, DepType Type) + : Source(Source), Destination(Destination), Type(Type) {} + + /// Return the source instruction of the dependence. + Instruction *getSource(const LoopAccessInfo &LAI) const; + /// Return the destination instruction of the dependence. + Instruction *getDestination(const LoopAccessInfo &LAI) const; + + /// Dependence types that don't prevent vectorization. + static VectorizationSafetyStatus isSafeForVectorization(DepType Type); + + /// Lexically forward dependence. + bool isForward() const; + /// Lexically backward dependence. + bool isBackward() const; + + /// May be a lexically backward dependence type (includes Unknown). + bool isPossiblyBackward() const; + + /// Print the dependence. \p Instr is used to map the instruction + /// indices to instructions. + void print(raw_ostream &OS, unsigned Depth, + const SmallVectorImpl<Instruction *> &Instrs) const; + }; + + MemoryDepChecker(PredicatedScalarEvolution &PSE, const Loop *L) + : PSE(PSE), InnermostLoop(L), AccessIdx(0), MaxSafeDepDistBytes(0), + MaxSafeRegisterWidth(-1U), FoundNonConstantDistanceDependence(false), + Status(VectorizationSafetyStatus::Safe), RecordDependences(true) {} + + /// Register the location (instructions are given increasing numbers) + /// of a write access. + void addAccess(StoreInst *SI) { + Value *Ptr = SI->getPointerOperand(); + Accesses[MemAccessInfo(Ptr, true)].push_back(AccessIdx); + InstMap.push_back(SI); + ++AccessIdx; + } + + /// Register the location (instructions are given increasing numbers) + /// of a write access. + void addAccess(LoadInst *LI) { + Value *Ptr = LI->getPointerOperand(); + Accesses[MemAccessInfo(Ptr, false)].push_back(AccessIdx); + InstMap.push_back(LI); + ++AccessIdx; + } + + /// Check whether the dependencies between the accesses are safe. + /// + /// Only checks sets with elements in \p CheckDeps. + bool areDepsSafe(DepCandidates &AccessSets, MemAccessInfoList &CheckDeps, + const ValueToValueMap &Strides); + + /// No memory dependence was encountered that would inhibit + /// vectorization. + bool isSafeForVectorization() const { + return Status == VectorizationSafetyStatus::Safe; + } + + /// The maximum number of bytes of a vector register we can vectorize + /// the accesses safely with. + uint64_t getMaxSafeDepDistBytes() { return MaxSafeDepDistBytes; } + + /// Return the number of elements that are safe to operate on + /// simultaneously, multiplied by the size of the element in bits. + uint64_t getMaxSafeRegisterWidth() const { return MaxSafeRegisterWidth; } + + /// In same cases when the dependency check fails we can still + /// vectorize the loop with a dynamic array access check. + bool shouldRetryWithRuntimeCheck() const { + return FoundNonConstantDistanceDependence && + Status == VectorizationSafetyStatus::PossiblySafeWithRtChecks; + } + + /// Returns the memory dependences. If null is returned we exceeded + /// the MaxDependences threshold and this information is not + /// available. + const SmallVectorImpl<Dependence> *getDependences() const { + return RecordDependences ? &Dependences : nullptr; + } + + void clearDependences() { Dependences.clear(); } + + /// The vector of memory access instructions. The indices are used as + /// instruction identifiers in the Dependence class. + const SmallVectorImpl<Instruction *> &getMemoryInstructions() const { + return InstMap; + } + + /// Generate a mapping between the memory instructions and their + /// indices according to program order. + DenseMap<Instruction *, unsigned> generateInstructionOrderMap() const { + DenseMap<Instruction *, unsigned> OrderMap; + + for (unsigned I = 0; I < InstMap.size(); ++I) + OrderMap[InstMap[I]] = I; + + return OrderMap; + } + + /// Find the set of instructions that read or write via \p Ptr. + SmallVector<Instruction *, 4> getInstructionsForAccess(Value *Ptr, + bool isWrite) const; + +private: + /// A wrapper around ScalarEvolution, used to add runtime SCEV checks, and + /// applies dynamic knowledge to simplify SCEV expressions and convert them + /// to a more usable form. We need this in case assumptions about SCEV + /// expressions need to be made in order to avoid unknown dependences. For + /// example we might assume a unit stride for a pointer in order to prove + /// that a memory access is strided and doesn't wrap. + PredicatedScalarEvolution &PSE; + const Loop *InnermostLoop; + + /// Maps access locations (ptr, read/write) to program order. + DenseMap<MemAccessInfo, std::vector<unsigned> > Accesses; + + /// Memory access instructions in program order. + SmallVector<Instruction *, 16> InstMap; + + /// The program order index to be used for the next instruction. + unsigned AccessIdx; + + // We can access this many bytes in parallel safely. + uint64_t MaxSafeDepDistBytes; + + /// Number of elements (from consecutive iterations) that are safe to + /// operate on simultaneously, multiplied by the size of the element in bits. + /// The size of the element is taken from the memory access that is most + /// restrictive. + uint64_t MaxSafeRegisterWidth; + + /// If we see a non-constant dependence distance we can still try to + /// vectorize this loop with runtime checks. + bool FoundNonConstantDistanceDependence; + + /// Result of the dependence checks, indicating whether the checked + /// dependences are safe for vectorization, require RT checks or are known to + /// be unsafe. + VectorizationSafetyStatus Status; + + //// True if Dependences reflects the dependences in the + //// loop. If false we exceeded MaxDependences and + //// Dependences is invalid. + bool RecordDependences; + + /// Memory dependences collected during the analysis. Only valid if + /// RecordDependences is true. + SmallVector<Dependence, 8> Dependences; + + /// Check whether there is a plausible dependence between the two + /// accesses. + /// + /// Access \p A must happen before \p B in program order. The two indices + /// identify the index into the program order map. + /// + /// This function checks whether there is a plausible dependence (or the + /// absence of such can't be proved) between the two accesses. If there is a + /// plausible dependence but the dependence distance is bigger than one + /// element access it records this distance in \p MaxSafeDepDistBytes (if this + /// distance is smaller than any other distance encountered so far). + /// Otherwise, this function returns true signaling a possible dependence. + Dependence::DepType isDependent(const MemAccessInfo &A, unsigned AIdx, + const MemAccessInfo &B, unsigned BIdx, + const ValueToValueMap &Strides); + + /// Check whether the data dependence could prevent store-load + /// forwarding. + /// + /// \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); + + /// Updates the current safety status with \p S. We can go from Safe to + /// either PossiblySafeWithRtChecks or Unsafe and from + /// PossiblySafeWithRtChecks to Unsafe. + void mergeInStatus(VectorizationSafetyStatus S); +}; + +/// Holds information about the memory runtime legality checks to verify +/// that a group of pointers do not overlap. +class RuntimePointerChecking { +public: + struct PointerInfo { + /// Holds the pointer value that we need to check. + TrackingVH<Value> PointerValue; + /// Holds the smallest byte address accessed by the pointer throughout all + /// iterations of the loop. + const SCEV *Start; + /// Holds the largest byte address accessed by the pointer throughout all + /// iterations of the loop, plus 1. + const SCEV *End; + /// Holds the information if this pointer is used for writing to memory. + bool IsWritePtr; + /// Holds the id of the set of pointers that could be dependent because of a + /// shared underlying object. + unsigned DependencySetId; + /// Holds the id of the disjoint alias set to which this pointer belongs. + unsigned AliasSetId; + /// SCEV for the access. + const SCEV *Expr; + + PointerInfo(Value *PointerValue, const SCEV *Start, const SCEV *End, + bool IsWritePtr, unsigned DependencySetId, unsigned AliasSetId, + const SCEV *Expr) + : PointerValue(PointerValue), Start(Start), End(End), + IsWritePtr(IsWritePtr), DependencySetId(DependencySetId), + AliasSetId(AliasSetId), Expr(Expr) {} + }; + + RuntimePointerChecking(ScalarEvolution *SE) : Need(false), SE(SE) {} + + /// Reset the state of the pointer runtime information. + void reset() { + Need = false; + Pointers.clear(); + Checks.clear(); + } + + /// Insert a pointer and calculate the start and end SCEVs. + /// 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 add new predicates to \p PSE. + void insert(Loop *Lp, Value *Ptr, bool WritePtr, unsigned DepSetId, + unsigned ASId, const ValueToValueMap &Strides, + PredicatedScalarEvolution &PSE); + + /// No run-time memory checking is necessary. + bool empty() const { return Pointers.empty(); } + + /// A grouping of pointers. A single memcheck is required between + /// two groups. + struct CheckingPtrGroup { + /// Create a new pointer checking group containing a single + /// pointer, with index \p Index in RtCheck. + CheckingPtrGroup(unsigned Index, RuntimePointerChecking &RtCheck) + : RtCheck(RtCheck), High(RtCheck.Pointers[Index].End), + Low(RtCheck.Pointers[Index].Start) { + Members.push_back(Index); + } + + /// Tries to add the pointer recorded in RtCheck at index + /// \p Index to this pointer checking group. We can only add a pointer + /// to a checking group if we will still be able to get + /// the upper and lower bounds of the check. Returns true in case + /// of success, false otherwise. + bool addPointer(unsigned Index); + + /// Constitutes the context of this pointer checking group. For each + /// pointer that is a member of this group we will retain the index + /// at which it appears in RtCheck. + RuntimePointerChecking &RtCheck; + /// The SCEV expression which represents the upper bound of all the + /// pointers in this group. + const SCEV *High; + /// The SCEV expression which represents the lower bound of all the + /// pointers in this group. + const SCEV *Low; + /// Indices of all the pointers that constitute this grouping. + SmallVector<unsigned, 2> Members; + }; + + /// A memcheck which made up of a pair of grouped pointers. + /// + /// These *have* to be const for now, since checks are generated from + /// CheckingPtrGroups in LAI::addRuntimeChecks which is a const member + /// function. FIXME: once check-generation is moved inside this class (after + /// the PtrPartition hack is removed), we could drop const. + typedef std::pair<const CheckingPtrGroup *, const CheckingPtrGroup *> + PointerCheck; + + /// Generate the checks and store it. This also performs the grouping + /// of pointers to reduce the number of memchecks necessary. + void generateChecks(MemoryDepChecker::DepCandidates &DepCands, + bool UseDependencies); + + /// Returns the checks that generateChecks created. + const SmallVector<PointerCheck, 4> &getChecks() const { return Checks; } + + /// Decide if we need to add a check between two groups of pointers, + /// according to needsChecking. + bool needsChecking(const CheckingPtrGroup &M, + const CheckingPtrGroup &N) const; + + /// Returns the number of run-time checks required according to + /// needsChecking. + unsigned getNumberOfChecks() const { return Checks.size(); } + + /// Print the list run-time memory checks necessary. + void print(raw_ostream &OS, unsigned Depth = 0) const; + + /// Print \p Checks. + void printChecks(raw_ostream &OS, const SmallVectorImpl<PointerCheck> &Checks, + unsigned Depth = 0) const; + + /// This flag indicates if we need to add the runtime check. + bool Need; + + /// Information about the pointers that may require checking. + SmallVector<PointerInfo, 2> Pointers; + + /// Holds a partitioning of pointers into "check groups". + SmallVector<CheckingPtrGroup, 2> CheckingGroups; + + /// Check if pointers are in the same partition + /// + /// \p PtrToPartition contains the partition number for pointers (-1 if the + /// pointer belongs to multiple partitions). + static bool + arePointersInSamePartition(const SmallVectorImpl<int> &PtrToPartition, + unsigned PtrIdx1, unsigned PtrIdx2); + + /// Decide whether we need to issue a run-time check for pointer at + /// index \p I and \p J to prove their independence. + bool needsChecking(unsigned I, unsigned J) const; + + /// Return PointerInfo for pointer at index \p PtrIdx. + const PointerInfo &getPointerInfo(unsigned PtrIdx) const { + return Pointers[PtrIdx]; + } + +private: + /// Groups pointers such that a single memcheck is required + /// between two different groups. This will clear the CheckingGroups vector + /// and re-compute it. We will only group dependecies if \p UseDependencies + /// is true, otherwise we will create a separate group for each pointer. + void groupChecks(MemoryDepChecker::DepCandidates &DepCands, + bool UseDependencies); + + /// Generate the checks and return them. + SmallVector<PointerCheck, 4> + generateChecks() const; + + /// Holds a pointer to the ScalarEvolution analysis. + ScalarEvolution *SE; + + /// Set of run-time checks required to establish independence of + /// otherwise may-aliasing pointers in the loop. + SmallVector<PointerCheck, 4> Checks; +}; + +/// Drive the analysis of memory accesses in the loop +/// +/// This class is responsible for analyzing the memory accesses of a loop. It +/// collects the accesses and then its main helper the AccessAnalysis class +/// finds and categorizes the dependences in buildDependenceSets. +/// +/// For memory dependences that can be analyzed at compile time, it determines +/// whether the dependence is part of cycle inhibiting vectorization. This work +/// is delegated to the MemoryDepChecker class. +/// +/// For memory dependences that cannot be determined at compile time, it +/// generates run-time checks to prove independence. This is done by +/// AccessAnalysis::canCheckPtrAtRT and the checks are maintained by the +/// RuntimePointerCheck class. +/// +/// If pointers can wrap or can't be expressed as affine AddRec expressions by +/// ScalarEvolution, we will generate run-time checks by emitting a +/// SCEVUnionPredicate. +/// +/// Checks for both memory dependences and the SCEV predicates contained in the +/// PSE must be emitted in order for the results of this analysis to be valid. +class LoopAccessInfo { +public: + LoopAccessInfo(Loop *L, ScalarEvolution *SE, const TargetLibraryInfo *TLI, + AliasAnalysis *AA, DominatorTree *DT, LoopInfo *LI); + + /// Return true we can analyze the memory accesses in the loop and there are + /// no memory dependence cycles. + bool canVectorizeMemory() const { return CanVecMem; } + + /// Return true if there is a convergent operation in the loop. There may + /// still be reported runtime pointer checks that would be required, but it is + /// not legal to insert them. + bool hasConvergentOp() const { return HasConvergentOp; } + + const RuntimePointerChecking *getRuntimePointerChecking() const { + return PtrRtChecking.get(); + } + + /// Number of memchecks required to prove independence of otherwise + /// may-alias pointers. + unsigned getNumRuntimePointerChecks() const { + return PtrRtChecking->getNumberOfChecks(); + } + + /// Return true if the block BB needs to be predicated in order for the loop + /// to be vectorized. + static bool blockNeedsPredication(BasicBlock *BB, Loop *TheLoop, + DominatorTree *DT); + + /// Returns true if the value V is uniform within the loop. + bool isUniform(Value *V) const; + + uint64_t getMaxSafeDepDistBytes() const { return MaxSafeDepDistBytes; } + unsigned getNumStores() const { return NumStores; } + unsigned getNumLoads() const { return NumLoads;} + + /// Add code that checks at runtime if the accessed arrays overlap. + /// + /// Returns a pair of instructions where the first element is the first + /// instruction generated in possibly a sequence of instructions and the + /// second value is the final comparator value or NULL if no check is needed. + std::pair<Instruction *, Instruction *> + addRuntimeChecks(Instruction *Loc) const; + + /// Generete the instructions for the checks in \p PointerChecks. + /// + /// Returns a pair of instructions where the first element is the first + /// instruction generated in possibly a sequence of instructions and the + /// second value is the final comparator value or NULL if no check is needed. + std::pair<Instruction *, Instruction *> + addRuntimeChecks(Instruction *Loc, + const SmallVectorImpl<RuntimePointerChecking::PointerCheck> + &PointerChecks) const; + + /// The diagnostics report generated for the analysis. E.g. why we + /// couldn't analyze the loop. + const OptimizationRemarkAnalysis *getReport() const { return Report.get(); } + + /// the Memory Dependence Checker which can determine the + /// loop-independent and loop-carried dependences between memory accesses. + const MemoryDepChecker &getDepChecker() const { return *DepChecker; } + + /// 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); + } + + /// If an access has a symbolic strides, this maps the pointer value to + /// the stride symbol. + const ValueToValueMap &getSymbolicStrides() const { return SymbolicStrides; } + + /// Pointer has a symbolic stride. + bool hasStride(Value *V) const { return StrideSet.count(V); } + + /// Print the information about the memory accesses in the loop. + void print(raw_ostream &OS, unsigned Depth = 0) const; + + /// If the loop has memory dependence involving an invariant address, i.e. two + /// stores or a store and a load, then return true, else return false. + bool hasDependenceInvolvingLoopInvariantAddress() const { + return HasDependenceInvolvingLoopInvariantAddress; + } + + /// Used to add runtime SCEV checks. Simplifies SCEV expressions and converts + /// them to a more usable form. All SCEV expressions during the analysis + /// 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. + const PredicatedScalarEvolution &getPSE() const { return *PSE; } + +private: + /// Analyze the loop. + void analyzeLoop(AliasAnalysis *AA, LoopInfo *LI, + const TargetLibraryInfo *TLI, DominatorTree *DT); + + /// Check if the structure of the loop allows it to be analyzed by this + /// pass. + bool canAnalyzeLoop(); + + /// Save the analysis remark. + /// + /// LAA does not directly emits the remarks. Instead it stores it which the + /// client can retrieve and presents as its own analysis + /// (e.g. -Rpass-analysis=loop-vectorize). + OptimizationRemarkAnalysis &recordAnalysis(StringRef RemarkName, + Instruction *Instr = nullptr); + + /// 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. Using std::unique_ptr to make using move ctor simpler. + std::unique_ptr<RuntimePointerChecking> PtrRtChecking; + + /// the Memory Dependence Checker which can determine the + /// loop-independent and loop-carried dependences between memory accesses. + std::unique_ptr<MemoryDepChecker> DepChecker; + + Loop *TheLoop; + + unsigned NumLoads; + unsigned NumStores; + + uint64_t MaxSafeDepDistBytes; + + /// Cache the result of analyzeLoop. + bool CanVecMem; + bool HasConvergentOp; + + /// Indicator that there are non vectorizable stores to a uniform address. + bool HasDependenceInvolvingLoopInvariantAddress; + + /// The diagnostics report generated for the analysis. E.g. why we + /// couldn't analyze the loop. + std::unique_ptr<OptimizationRemarkAnalysis> Report; + + /// If an access has a symbolic strides, this maps the pointer value to + /// the stride symbol. + ValueToValueMap SymbolicStrides; + + /// Set of symbolic strides values. + SmallPtrSet<Value *, 8> StrideSet; +}; + +Value *stripIntegerCast(Value *V); + +/// 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 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 +/// stride as collected by LoopVectorizationLegality::collectStridedAccess. +const SCEV *replaceSymbolicStrideSCEV(PredicatedScalarEvolution &PSE, + const ValueToValueMap &PtrToStride, + Value *Ptr, Value *OrigPtr = nullptr); + +/// 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 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, bool ShouldCheckWrap = true); + +/// Attempt to sort the pointers in \p VL and return the sorted indices +/// in \p SortedIndices, if reordering is required. +/// +/// Returns 'true' if sorting is legal, otherwise returns 'false'. +/// +/// For example, for a given \p VL of memory accesses in program order, a[i+4], +/// a[i+0], a[i+1] and a[i+7], this function will sort the \p VL and save the +/// sorted indices in \p SortedIndices as a[i+0], a[i+1], a[i+4], a[i+7] and +/// saves the mask for actual memory accesses in program order in +/// \p SortedIndices as <1,2,0,3> +bool sortPtrAccesses(ArrayRef<Value *> VL, const DataLayout &DL, + ScalarEvolution &SE, + SmallVectorImpl<unsigned> &SortedIndices); + +/// 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); + +/// 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 LAA::getInfo. getInfo return a +/// LoopAccessInfo object. See this class for the specifics of what information +/// is provided. +class LoopAccessLegacyAnalysis : public FunctionPass { +public: + static char ID; + + LoopAccessLegacyAnalysis(); + + bool runOnFunction(Function &F) override; + + void getAnalysisUsage(AnalysisUsage &AU) const override; + + /// Query the result of the loop access information for the loop \p L. + /// + /// 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. + LoopAccessInfoMap.clear(); + } + + /// Print the result of the analysis when invoked with -analyze. + void print(raw_ostream &OS, const Module *M = nullptr) const override; + +private: + /// The cache. + DenseMap<Loop *, std::unique_ptr<LoopAccessInfo>> LoopAccessInfoMap; + + // The used analysis passes. + ScalarEvolution *SE = nullptr; + const TargetLibraryInfo *TLI = nullptr; + AliasAnalysis *AA = nullptr; + DominatorTree *DT = nullptr; + LoopInfo *LI = nullptr; +}; + +/// 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 AnalysisKey Key; + +public: + typedef LoopAccessInfo Result; + + Result run(Loop &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR); +}; + +inline Instruction *MemoryDepChecker::Dependence::getSource( + const LoopAccessInfo &LAI) const { + return LAI.getDepChecker().getMemoryInstructions()[Source]; +} + +inline Instruction *MemoryDepChecker::Dependence::getDestination( + const LoopAccessInfo &LAI) const { + return LAI.getDepChecker().getMemoryInstructions()[Destination]; +} + +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/LoopAnalysisManager.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/LoopAnalysisManager.h new file mode 100644 index 0000000..a2e65a7 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/LoopAnalysisManager.h
@@ -0,0 +1,162 @@ +//===- LoopAnalysisManager.h - Loop analysis management ---------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This header provides classes for managing per-loop analyses. These are +/// typically used as part of a loop pass pipeline over the loop nests of +/// a function. +/// +/// Loop analyses are allowed to make some simplifying assumptions: +/// 1) Loops are, where possible, in simplified form. +/// 2) Loops are *always* in LCSSA form. +/// 3) A collection of analysis results are available: +/// - LoopInfo +/// - DominatorTree +/// - ScalarEvolution +/// - AAManager +/// +/// The primary mechanism to provide these invariants is the loop pass manager, +/// but they can also be manually provided in order to reason about a loop from +/// outside of a dedicated pass manager. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LOOPANALYSISMANAGER_H +#define LLVM_ANALYSIS_LOOPANALYSISMANAGER_H + +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/ADT/PriorityWorklist.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/BasicAliasAnalysis.h" +#include "llvm/Analysis/GlobalsModRef.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/MemorySSA.h" +#include "llvm/Analysis/ScalarEvolution.h" +#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h" +#include "llvm/Analysis/TargetLibraryInfo.h" +#include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/IR/Dominators.h" +#include "llvm/IR/PassManager.h" + +namespace llvm { + +/// The adaptor from a function pass to a loop pass computes these analyses and +/// makes them available to the loop passes "for free". Each loop pass is +/// expected expected to update these analyses if necessary to ensure they're +/// valid after it runs. +struct LoopStandardAnalysisResults { + AAResults &AA; + AssumptionCache &AC; + DominatorTree &DT; + LoopInfo &LI; + ScalarEvolution &SE; + TargetLibraryInfo &TLI; + TargetTransformInfo &TTI; + MemorySSA *MSSA; +}; + +/// Extern template declaration for the analysis set for this IR unit. +extern template class AllAnalysesOn<Loop>; + +extern template class AnalysisManager<Loop, LoopStandardAnalysisResults &>; +/// 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, LoopStandardAnalysisResults &> + LoopAnalysisManager; + +/// A proxy from a \c LoopAnalysisManager to a \c Function. +typedef InnerAnalysisManagerProxy<LoopAnalysisManager, Function> + LoopAnalysisManagerFunctionProxy; + +/// A specialized result for the \c LoopAnalysisManagerFunctionProxy which +/// retains a \c LoopInfo reference. +/// +/// This allows it to collect loop objects for which analysis results may be +/// cached in the \c LoopAnalysisManager. +template <> class LoopAnalysisManagerFunctionProxy::Result { +public: + explicit Result(LoopAnalysisManager &InnerAM, LoopInfo &LI) + : InnerAM(&InnerAM), LI(&LI), MSSAUsed(false) {} + Result(Result &&Arg) + : InnerAM(std::move(Arg.InnerAM)), LI(Arg.LI), MSSAUsed(Arg.MSSAUsed) { + // We have to null out the analysis manager in the moved-from state + // because we are taking ownership of the responsibilty to clear the + // analysis state. + Arg.InnerAM = nullptr; + } + Result &operator=(Result &&RHS) { + InnerAM = RHS.InnerAM; + LI = RHS.LI; + MSSAUsed = RHS.MSSAUsed; + // We have to null out the analysis manager in the moved-from state + // because we are taking ownership of the responsibilty to clear the + // analysis state. + RHS.InnerAM = nullptr; + return *this; + } + ~Result() { + // InnerAM is cleared in a moved from state where there is nothing to do. + if (!InnerAM) + return; + + // Clear out the analysis manager if we're being destroyed -- it means we + // didn't even see an invalidate call when we got invalidated. + InnerAM->clear(); + } + + /// Mark MemorySSA as used so we can invalidate self if MSSA is invalidated. + void markMSSAUsed() { MSSAUsed = true; } + + /// Accessor for the analysis manager. + LoopAnalysisManager &getManager() { return *InnerAM; } + + /// Handler for invalidation of the proxy for a particular function. + /// + /// If the proxy, \c LoopInfo, and associated analyses are preserved, this + /// will merely forward the invalidation event to any cached loop analysis + /// results for loops within this function. + /// + /// If the necessary loop infrastructure is not preserved, this will forcibly + /// clear all of the cached analysis results that are keyed on the \c + /// LoopInfo for this function. + bool invalidate(Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &Inv); + +private: + LoopAnalysisManager *InnerAM; + LoopInfo *LI; + bool MSSAUsed; +}; + +/// Provide a specialized run method for the \c LoopAnalysisManagerFunctionProxy +/// so it can pass the \c LoopInfo to the result. +template <> +LoopAnalysisManagerFunctionProxy::Result +LoopAnalysisManagerFunctionProxy::run(Function &F, FunctionAnalysisManager &AM); + +// Ensure the \c LoopAnalysisManagerFunctionProxy is provided as an extern +// template. +extern template class InnerAnalysisManagerProxy<LoopAnalysisManager, Function>; + +extern template class OuterAnalysisManagerProxy<FunctionAnalysisManager, Loop, + LoopStandardAnalysisResults &>; +/// A proxy from a \c FunctionAnalysisManager to a \c Loop. +typedef OuterAnalysisManagerProxy<FunctionAnalysisManager, Loop, + LoopStandardAnalysisResults &> + FunctionAnalysisManagerLoopProxy; + +/// Returns the minimum set of Analyses that all loop passes must preserve. +PreservedAnalyses getLoopPassPreservedAnalyses(); +} + +#endif // LLVM_ANALYSIS_LOOPANALYSISMANAGER_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/LoopCacheAnalysis.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/LoopCacheAnalysis.h new file mode 100644 index 0000000..ffec78b --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/LoopCacheAnalysis.h
@@ -0,0 +1,281 @@ +//===- llvm/Analysis/LoopCacheAnalysis.h ------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file defines the interface for the loop cache analysis. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LOOPCACHEANALYSIS_H +#define LLVM_ANALYSIS_LOOPCACHEANALYSIS_H + +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/DependenceAnalysis.h" +#include "llvm/Analysis/LoopAnalysisManager.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/ScalarEvolution.h" +#include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/IR/Instructions.h" +#include "llvm/Pass.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +class LPMUpdater; +using CacheCostTy = int64_t; +using LoopVectorTy = SmallVector<Loop *, 8>; + +/// Represents a memory reference as a base pointer and a set of indexing +/// operations. For example given the array reference A[i][2j+1][3k+2] in a +/// 3-dim loop nest: +/// for(i=0;i<n;++i) +/// for(j=0;j<m;++j) +/// for(k=0;k<o;++k) +/// ... A[i][2j+1][3k+2] ... +/// We expect: +/// BasePointer -> A +/// Subscripts -> [{0,+,1}<%for.i>][{1,+,2}<%for.j>][{2,+,3}<%for.k>] +/// Sizes -> [m][o][4] +class IndexedReference { + friend raw_ostream &operator<<(raw_ostream &OS, const IndexedReference &R); + +public: + /// Construct an indexed reference given a \p StoreOrLoadInst instruction. + IndexedReference(Instruction &StoreOrLoadInst, const LoopInfo &LI, + ScalarEvolution &SE); + + bool isValid() const { return IsValid; } + const SCEV *getBasePointer() const { return BasePointer; } + size_t getNumSubscripts() const { return Subscripts.size(); } + const SCEV *getSubscript(unsigned SubNum) const { + assert(SubNum < getNumSubscripts() && "Invalid subscript number"); + return Subscripts[SubNum]; + } + const SCEV *getFirstSubscript() const { + assert(!Subscripts.empty() && "Expecting non-empty container"); + return Subscripts.front(); + } + const SCEV *getLastSubscript() const { + assert(!Subscripts.empty() && "Expecting non-empty container"); + return Subscripts.back(); + } + + /// Return true/false if the current object and the indexed reference \p Other + /// are/aren't in the same cache line of size \p CLS. Two references are in + /// the same chace line iff the distance between them in the innermost + /// dimension is less than the cache line size. Return None if unsure. + Optional<bool> hasSpacialReuse(const IndexedReference &Other, unsigned CLS, + AliasAnalysis &AA) const; + + /// Return true if the current object and the indexed reference \p Other + /// have distance smaller than \p MaxDistance in the dimension associated with + /// the given loop \p L. Return false if the distance is not smaller than \p + /// MaxDistance and None if unsure. + Optional<bool> hasTemporalReuse(const IndexedReference &Other, + unsigned MaxDistance, const Loop &L, + DependenceInfo &DI, AliasAnalysis &AA) const; + + /// Compute the cost of the reference w.r.t. the given loop \p L when it is + /// considered in the innermost position in the loop nest. + /// The cost is defined as: + /// - equal to one if the reference is loop invariant, or + /// - equal to '(TripCount * stride) / cache_line_size' if: + /// + the reference stride is less than the cache line size, and + /// + the coefficient of this loop's index variable used in all other + /// subscripts is zero + /// - or otherwise equal to 'TripCount'. + CacheCostTy computeRefCost(const Loop &L, unsigned CLS) const; + +private: + /// Attempt to delinearize the indexed reference. + bool delinearize(const LoopInfo &LI); + + /// Return true if the index reference is invariant with respect to loop \p L. + bool isLoopInvariant(const Loop &L) const; + + /// Return true if the indexed reference is 'consecutive' in loop \p L. + /// An indexed reference is 'consecutive' if the only coefficient that uses + /// the loop induction variable is the rightmost one, and the access stride is + /// smaller than the cache line size \p CLS. + bool isConsecutive(const Loop &L, unsigned CLS) const; + + /// Return the coefficient used in the rightmost dimension. + const SCEV *getLastCoefficient() const; + + /// Return true if the coefficient corresponding to induction variable of + /// loop \p L in the given \p Subscript is zero or is loop invariant in \p L. + bool isCoeffForLoopZeroOrInvariant(const SCEV &Subscript, + const Loop &L) const; + + /// Verify that the given \p Subscript is 'well formed' (must be a simple add + /// recurrence). + bool isSimpleAddRecurrence(const SCEV &Subscript, const Loop &L) const; + + /// Return true if the given reference \p Other is definetely aliased with + /// the indexed reference represented by this class. + bool isAliased(const IndexedReference &Other, AliasAnalysis &AA) const; + +private: + /// True if the reference can be delinearized, false otherwise. + bool IsValid = false; + + /// Represent the memory reference instruction. + Instruction &StoreOrLoadInst; + + /// The base pointer of the memory reference. + const SCEV *BasePointer = nullptr; + + /// The subscript (indexes) of the memory reference. + SmallVector<const SCEV *, 3> Subscripts; + + /// The dimensions of the memory reference. + SmallVector<const SCEV *, 3> Sizes; + + ScalarEvolution &SE; +}; + +/// A reference group represents a set of memory references that exhibit +/// temporal or spacial reuse. Two references belong to the same +/// reference group with respect to a inner loop L iff: +/// 1. they have a loop independent dependency, or +/// 2. they have a loop carried dependence with a small dependence distance +/// (e.g. less than 2) carried by the inner loop, or +/// 3. they refer to the same array, and the subscript in their innermost +/// dimension is less than or equal to 'd' (where 'd' is less than the cache +/// line size) +/// +/// Intuitively a reference group represents memory references that access +/// the same cache line. Conditions 1,2 above account for temporal reuse, while +/// contition 3 accounts for spacial reuse. +using ReferenceGroupTy = SmallVector<std::unique_ptr<IndexedReference>, 8>; +using ReferenceGroupsTy = SmallVector<ReferenceGroupTy, 8>; + +/// \c CacheCost represents the estimated cost of a inner loop as the number of +/// cache lines used by the memory references it contains. +/// The 'cache cost' of a loop 'L' in a loop nest 'LN' is computed as the sum of +/// the cache costs of all of its reference groups when the loop is considered +/// to be in the innermost position in the nest. +/// A reference group represents memory references that fall into the same cache +/// line. Each reference group is analysed with respect to the innermost loop in +/// a loop nest. The cost of a reference is defined as follow: +/// - one if it is loop invariant w.r.t the innermost loop, +/// - equal to the loop trip count divided by the cache line times the +/// reference stride if the reference stride is less than the cache line +/// size (CLS), and the coefficient of this loop's index variable used in all +/// other subscripts is zero (e.g. RefCost = TripCount/(CLS/RefStride)) +/// - equal to the innermost loop trip count if the reference stride is greater +/// or equal to the cache line size CLS. +class CacheCost { + friend raw_ostream &operator<<(raw_ostream &OS, const CacheCost &CC); + using LoopTripCountTy = std::pair<const Loop *, unsigned>; + using LoopCacheCostTy = std::pair<const Loop *, CacheCostTy>; + +public: + static CacheCostTy constexpr InvalidCost = -1; + + /// Construct a CacheCost object for the loop nest described by \p Loops. + /// The optional parameter \p TRT can be used to specify the max. distance + /// between array elements accessed in a loop so that the elements are + /// classified to have temporal reuse. + CacheCost(const LoopVectorTy &Loops, const LoopInfo &LI, ScalarEvolution &SE, + TargetTransformInfo &TTI, AliasAnalysis &AA, DependenceInfo &DI, + Optional<unsigned> TRT = None); + + /// Create a CacheCost for the loop nest rooted by \p Root. + /// The optional parameter \p TRT can be used to specify the max. distance + /// between array elements accessed in a loop so that the elements are + /// classified to have temporal reuse. + static std::unique_ptr<CacheCost> + getCacheCost(Loop &Root, LoopStandardAnalysisResults &AR, DependenceInfo &DI, + Optional<unsigned> TRT = None); + + /// Return the estimated cost of loop \p L if the given loop is part of the + /// loop nest associated with this object. Return -1 otherwise. + CacheCostTy getLoopCost(const Loop &L) const { + auto IT = std::find_if( + LoopCosts.begin(), LoopCosts.end(), + [&L](const LoopCacheCostTy &LCC) { return LCC.first == &L; }); + return (IT != LoopCosts.end()) ? (*IT).second : -1; + } + + /// Return the estimated ordered loop costs. + const ArrayRef<LoopCacheCostTy> getLoopCosts() const { return LoopCosts; } + +private: + /// Calculate the cache footprint of each loop in the nest (when it is + /// considered to be in the innermost position). + void calculateCacheFootprint(); + + /// Partition store/load instructions in the loop nest into reference groups. + /// Two or more memory accesses belong in the same reference group if they + /// share the same cache line. + bool populateReferenceGroups(ReferenceGroupsTy &RefGroups) const; + + /// Calculate the cost of the given loop \p L assuming it is the innermost + /// loop in nest. + CacheCostTy computeLoopCacheCost(const Loop &L, + const ReferenceGroupsTy &RefGroups) const; + + /// Compute the cost of a representative reference in reference group \p RG + /// when the given loop \p L is considered as the innermost loop in the nest. + /// The computed cost is an estimate for the number of cache lines used by the + /// reference group. The representative reference cost is defined as: + /// - equal to one if the reference is loop invariant, or + /// - equal to '(TripCount * stride) / cache_line_size' if (a) loop \p L's + /// induction variable is used only in the reference subscript associated + /// with loop \p L, and (b) the reference stride is less than the cache + /// line size, or + /// - TripCount otherwise + CacheCostTy computeRefGroupCacheCost(const ReferenceGroupTy &RG, + const Loop &L) const; + + /// Sort the LoopCosts vector by decreasing cache cost. + void sortLoopCosts() { + sort(LoopCosts, [](const LoopCacheCostTy &A, const LoopCacheCostTy &B) { + return A.second > B.second; + }); + } + +private: + /// Loops in the loop nest associated with this object. + LoopVectorTy Loops; + + /// Trip counts for the loops in the loop nest associated with this object. + SmallVector<LoopTripCountTy, 3> TripCounts; + + /// Cache costs for the loops in the loop nest associated with this object. + SmallVector<LoopCacheCostTy, 3> LoopCosts; + + /// The max. distance between array elements accessed in a loop so that the + /// elements are classified to have temporal reuse. + Optional<unsigned> TRT; + + const LoopInfo &LI; + ScalarEvolution &SE; + TargetTransformInfo &TTI; + AliasAnalysis &AA; + DependenceInfo &DI; +}; + +raw_ostream &operator<<(raw_ostream &OS, const IndexedReference &R); +raw_ostream &operator<<(raw_ostream &OS, const CacheCost &CC); + +/// Printer pass for the \c CacheCost results. +class LoopCachePrinterPass : public PassInfoMixin<LoopCachePrinterPass> { + raw_ostream &OS; + +public: + explicit LoopCachePrinterPass(raw_ostream &OS) : OS(OS) {} + + PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, + LoopStandardAnalysisResults &AR, LPMUpdater &U); +}; + +} // namespace llvm + +#endif // LLVM_ANALYSIS_LOOPCACHEANALYSIS_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/LoopInfo.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/LoopInfo.h new file mode 100644 index 0000000..a010451 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/LoopInfo.h
@@ -0,0 +1,1287 @@ +//===- llvm/Analysis/LoopInfo.h - Natural Loop Calculator -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the LoopInfo class that is used to identify natural loops +// and determine the loop depth of various nodes of the CFG. A natural loop +// has exactly one entry-point, which is called the header. Note that natural +// loops may actually be several loops that share the same header node. +// +// This analysis calculates the nesting structure of loops in a function. For +// each natural loop identified, this analysis identifies natural loops +// contained entirely within the loop and the basic blocks the make up the loop. +// +// It can calculate on the fly various bits of information, for example: +// +// * whether there is a preheader for the loop +// * the number of back edges to the header +// * whether or not a particular block branches out of the loop +// * the successor blocks of the loop +// * the loop depth +// * etc... +// +// Note that this analysis specifically identifies *Loops* not cycles or SCCs +// in the CFG. There can be strongly connected components 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. +// +// For an overview of terminology used in this API (and thus all of our loop +// analyses or transforms), see docs/LoopTerminology.rst. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LOOPINFO_H +#define LLVM_ANALYSIS_LOOPINFO_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/IR/CFG.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Pass.h" +#include "llvm/Support/Allocator.h" +#include <algorithm> +#include <utility> + +namespace llvm { + +class DominatorTree; +class LoopInfo; +class Loop; +class InductionDescriptor; +class MDNode; +class MemorySSAUpdater; +class PHINode; +class ScalarEvolution; +class raw_ostream; +template <class N, bool IsPostDom> class DominatorTreeBase; +template <class N, class M> class LoopInfoBase; +template <class N, class M> class LoopBase; + +//===----------------------------------------------------------------------===// +/// Instances of this class are used to represent loops that are detected in the +/// flow graph. +/// +template <class BlockT, class LoopT> class LoopBase { + LoopT *ParentLoop; + // Loops contained entirely within this one. + std::vector<LoopT *> SubLoops; + + // The list of blocks in this loop. First entry is the header node. + std::vector<BlockT *> Blocks; + + SmallPtrSet<const BlockT *, 8> DenseBlockSet; + +#if LLVM_ENABLE_ABI_BREAKING_CHECKS + /// Indicator that this loop is no longer a valid loop. + bool IsInvalid = false; +#endif + + LoopBase(const LoopBase<BlockT, LoopT> &) = delete; + const LoopBase<BlockT, LoopT> & + operator=(const LoopBase<BlockT, LoopT> &) = delete; + +public: + /// Return the nesting level of this loop. An outer-most loop has depth 1, + /// for consistency with loop depth values used for basic blocks, where depth + /// 0 is used for blocks not inside any loops. + unsigned getLoopDepth() const { + assert(!isInvalid() && "Loop not in a valid state!"); + unsigned D = 1; + for (const LoopT *CurLoop = ParentLoop; CurLoop; + CurLoop = CurLoop->ParentLoop) + ++D; + return D; + } + BlockT *getHeader() const { return getBlocks().front(); } + LoopT *getParentLoop() const { return ParentLoop; } + + /// This is a raw interface for bypassing addChildLoop. + void setParentLoop(LoopT *L) { + assert(!isInvalid() && "Loop not in a valid state!"); + ParentLoop = L; + } + + /// Return true if the specified loop is contained within in this loop. + bool contains(const LoopT *L) const { + assert(!isInvalid() && "Loop not in a valid state!"); + if (L == this) + return true; + if (!L) + return false; + return contains(L->getParentLoop()); + } + + /// Return true if the specified basic block is in this loop. + bool contains(const BlockT *BB) const { + assert(!isInvalid() && "Loop not in a valid state!"); + return DenseBlockSet.count(BB); + } + + /// Return true if the specified instruction is in this loop. + template <class InstT> bool contains(const InstT *Inst) const { + return contains(Inst->getParent()); + } + + /// Return the loops contained entirely within this loop. + const std::vector<LoopT *> &getSubLoops() const { + assert(!isInvalid() && "Loop not in a valid state!"); + return SubLoops; + } + std::vector<LoopT *> &getSubLoopsVector() { + assert(!isInvalid() && "Loop not in a valid state!"); + return SubLoops; + } + typedef typename std::vector<LoopT *>::const_iterator iterator; + typedef + typename std::vector<LoopT *>::const_reverse_iterator reverse_iterator; + iterator begin() const { return getSubLoops().begin(); } + iterator end() const { return getSubLoops().end(); } + reverse_iterator rbegin() const { return getSubLoops().rbegin(); } + reverse_iterator rend() const { return getSubLoops().rend(); } + bool empty() const { return getSubLoops().empty(); } + + /// Get a list of the basic blocks which make up this loop. + ArrayRef<BlockT *> getBlocks() const { + assert(!isInvalid() && "Loop not in a valid state!"); + return Blocks; + } + typedef typename ArrayRef<BlockT *>::const_iterator block_iterator; + block_iterator block_begin() const { return getBlocks().begin(); } + block_iterator block_end() const { return getBlocks().end(); } + inline iterator_range<block_iterator> blocks() const { + assert(!isInvalid() && "Loop not in a valid state!"); + return make_range(block_begin(), block_end()); + } + + /// Get the number of blocks in this loop in constant time. + /// Invalidate the loop, indicating that it is no longer a loop. + unsigned getNumBlocks() const { + assert(!isInvalid() && "Loop not in a valid state!"); + return Blocks.size(); + } + + /// Return a direct, mutable handle to the blocks vector so that we can + /// mutate it efficiently with techniques like `std::remove`. + std::vector<BlockT *> &getBlocksVector() { + assert(!isInvalid() && "Loop not in a valid state!"); + return Blocks; + } + /// Return a direct, mutable handle to the blocks set so that we can + /// mutate it efficiently. + SmallPtrSetImpl<const BlockT *> &getBlocksSet() { + assert(!isInvalid() && "Loop not in a valid state!"); + return DenseBlockSet; + } + + /// Return a direct, immutable handle to the blocks set. + const SmallPtrSetImpl<const BlockT *> &getBlocksSet() const { + assert(!isInvalid() && "Loop not in a valid state!"); + return DenseBlockSet; + } + + /// Return true if this loop is no longer valid. The only valid use of this + /// helper is "assert(L.isInvalid())" or equivalent, since IsInvalid is set to + /// true by the destructor. In other words, if this accessor returns true, + /// the caller has already triggered UB by calling this accessor; and so it + /// can only be called in a context where a return value of true indicates a + /// programmer error. + bool isInvalid() const { +#if LLVM_ENABLE_ABI_BREAKING_CHECKS + return IsInvalid; +#else + return false; +#endif + } + + /// True if terminator in the block can branch to another block that is + /// outside of the current loop. \p BB must be inside the loop. + bool isLoopExiting(const BlockT *BB) const { + assert(!isInvalid() && "Loop not in a valid state!"); + assert(contains(BB) && "Exiting block must be part of the loop"); + for (const auto *Succ : children<const BlockT *>(BB)) { + if (!contains(Succ)) + return true; + } + return false; + } + + /// Returns true if \p BB is a loop-latch. + /// A latch block is a block that contains a branch back to the header. + /// This function is useful when there are multiple latches in a loop + /// because \fn getLoopLatch will return nullptr in that case. + bool isLoopLatch(const BlockT *BB) const { + assert(!isInvalid() && "Loop not in a valid state!"); + assert(contains(BB) && "block does not belong to the loop"); + + BlockT *Header = getHeader(); + auto PredBegin = GraphTraits<Inverse<BlockT *>>::child_begin(Header); + auto PredEnd = GraphTraits<Inverse<BlockT *>>::child_end(Header); + return std::find(PredBegin, PredEnd, BB) != PredEnd; + } + + /// Calculate the number of back edges to the loop header. + unsigned getNumBackEdges() const { + assert(!isInvalid() && "Loop not in a valid state!"); + unsigned NumBackEdges = 0; + BlockT *H = getHeader(); + + for (const auto Pred : children<Inverse<BlockT *>>(H)) + if (contains(Pred)) + ++NumBackEdges; + + return NumBackEdges; + } + + //===--------------------------------------------------------------------===// + // APIs for simple analysis of the loop. + // + // Note that all of these methods can fail on general loops (ie, there may not + // be a preheader, etc). For best success, the loop simplification and + // induction variable canonicalization pass should be used to normalize loops + // for easy analysis. These methods assume canonical loops. + + /// Return all blocks inside the loop that have successors outside of the + /// loop. These are the blocks _inside of the current loop_ which branch out. + /// The returned list is always unique. + void getExitingBlocks(SmallVectorImpl<BlockT *> &ExitingBlocks) const; + + /// If getExitingBlocks would return exactly one block, return that block. + /// Otherwise return null. + BlockT *getExitingBlock() const; + + /// Return all of the successor blocks of this loop. These are the blocks + /// _outside of the current loop_ which are branched to. + void getExitBlocks(SmallVectorImpl<BlockT *> &ExitBlocks) const; + + /// If getExitBlocks would return exactly one block, return that block. + /// Otherwise return null. + BlockT *getExitBlock() const; + + /// Return true if no exit block for the loop has a predecessor that is + /// outside the loop. + bool hasDedicatedExits() const; + + /// Return all unique successor blocks of this loop. + /// These are the blocks _outside of the current loop_ which are branched to. + void getUniqueExitBlocks(SmallVectorImpl<BlockT *> &ExitBlocks) const; + + /// Return all unique successor blocks of this loop except successors from + /// Latch block are not considered. If the exit comes from Latch has also + /// non Latch predecessor in a loop it will be added to ExitBlocks. + /// These are the blocks _outside of the current loop_ which are branched to. + void getUniqueNonLatchExitBlocks(SmallVectorImpl<BlockT *> &ExitBlocks) const; + + /// If getUniqueExitBlocks would return exactly one block, return that block. + /// Otherwise return null. + BlockT *getUniqueExitBlock() const; + + /// Edge type. + typedef std::pair<BlockT *, BlockT *> Edge; + + /// Return all pairs of (_inside_block_,_outside_block_). + void getExitEdges(SmallVectorImpl<Edge> &ExitEdges) const; + + /// If there is a preheader for this loop, return it. A loop has a preheader + /// if there is only one edge to the header of the loop from outside of the + /// loop. If this is the case, the block branching to the header of the loop + /// is the preheader node. + /// + /// This method returns null if there is no preheader for the loop. + BlockT *getLoopPreheader() const; + + /// If the given loop's header has exactly one unique predecessor outside the + /// loop, return it. Otherwise return null. + /// This is less strict that the loop "preheader" concept, which requires + /// the predecessor to have exactly one successor. + BlockT *getLoopPredecessor() const; + + /// If there is a single latch block for this loop, return it. + /// A latch block is a block that contains a branch back to the header. + BlockT *getLoopLatch() const; + + /// Return all loop latch blocks of this loop. A latch block is a block that + /// contains a branch back to the header. + void getLoopLatches(SmallVectorImpl<BlockT *> &LoopLatches) const { + assert(!isInvalid() && "Loop not in a valid state!"); + BlockT *H = getHeader(); + for (const auto Pred : children<Inverse<BlockT *>>(H)) + if (contains(Pred)) + LoopLatches.push_back(Pred); + } + + /// Return all inner loops in the loop nest rooted by the loop in preorder, + /// with siblings in forward program order. + template <class Type> + static void getInnerLoopsInPreorder(const LoopT &L, + SmallVectorImpl<Type> &PreOrderLoops) { + SmallVector<LoopT *, 4> PreOrderWorklist; + PreOrderWorklist.append(L.rbegin(), L.rend()); + + while (!PreOrderWorklist.empty()) { + LoopT *L = PreOrderWorklist.pop_back_val(); + // Sub-loops are stored in forward program order, but will process the + // worklist backwards so append them in reverse order. + PreOrderWorklist.append(L->rbegin(), L->rend()); + PreOrderLoops.push_back(L); + } + } + + /// Return all loops in the loop nest rooted by the loop in preorder, with + /// siblings in forward program order. + SmallVector<const LoopT *, 4> getLoopsInPreorder() const { + SmallVector<const LoopT *, 4> PreOrderLoops; + const LoopT *CurLoop = static_cast<const LoopT *>(this); + PreOrderLoops.push_back(CurLoop); + getInnerLoopsInPreorder(*CurLoop, PreOrderLoops); + return PreOrderLoops; + } + SmallVector<LoopT *, 4> getLoopsInPreorder() { + SmallVector<LoopT *, 4> PreOrderLoops; + LoopT *CurLoop = static_cast<LoopT *>(this); + PreOrderLoops.push_back(CurLoop); + getInnerLoopsInPreorder(*CurLoop, PreOrderLoops); + return PreOrderLoops; + } + + //===--------------------------------------------------------------------===// + // APIs for updating loop information after changing the CFG + // + + /// This method is used by other analyses to update loop information. + /// NewBB is set to be a new member of the current loop. + /// Because of this, it is added as a member of all parent loops, and is added + /// to the specified LoopInfo object as being in the current basic block. It + /// is not valid to replace the loop header with this method. + void addBasicBlockToLoop(BlockT *NewBB, LoopInfoBase<BlockT, LoopT> &LI); + + /// This is used when splitting loops up. It replaces the OldChild entry in + /// our children list with NewChild, and updates the parent pointer of + /// OldChild to be null and the NewChild to be this loop. + /// This updates the loop depth of the new child. + void replaceChildLoopWith(LoopT *OldChild, LoopT *NewChild); + + /// Add the specified loop to be a child of this loop. + /// This updates the loop depth of the new child. + void addChildLoop(LoopT *NewChild) { + assert(!isInvalid() && "Loop not in a valid state!"); + assert(!NewChild->ParentLoop && "NewChild already has a parent!"); + NewChild->ParentLoop = static_cast<LoopT *>(this); + SubLoops.push_back(NewChild); + } + + /// This removes the specified child from being a subloop of this loop. The + /// loop is not deleted, as it will presumably be inserted into another loop. + LoopT *removeChildLoop(iterator I) { + assert(!isInvalid() && "Loop not in a valid state!"); + assert(I != SubLoops.end() && "Cannot remove end iterator!"); + LoopT *Child = *I; + assert(Child->ParentLoop == this && "Child is not a child of this loop!"); + SubLoops.erase(SubLoops.begin() + (I - begin())); + Child->ParentLoop = nullptr; + return Child; + } + + /// This removes the specified child from being a subloop of this loop. The + /// loop is not deleted, as it will presumably be inserted into another loop. + LoopT *removeChildLoop(LoopT *Child) { + return removeChildLoop(llvm::find(*this, Child)); + } + + /// This adds a basic block directly to the basic block list. + /// This should only be used by transformations that create new loops. Other + /// transformations should use addBasicBlockToLoop. + void addBlockEntry(BlockT *BB) { + assert(!isInvalid() && "Loop not in a valid state!"); + Blocks.push_back(BB); + DenseBlockSet.insert(BB); + } + + /// interface to reverse Blocks[from, end of loop] in this loop + void reverseBlock(unsigned from) { + assert(!isInvalid() && "Loop not in a valid state!"); + std::reverse(Blocks.begin() + from, Blocks.end()); + } + + /// interface to do reserve() for Blocks + void reserveBlocks(unsigned size) { + assert(!isInvalid() && "Loop not in a valid state!"); + Blocks.reserve(size); + } + + /// This method is used to move BB (which must be part of this loop) to be the + /// loop header of the loop (the block that dominates all others). + void moveToHeader(BlockT *BB) { + assert(!isInvalid() && "Loop not in a valid state!"); + if (Blocks[0] == BB) + return; + for (unsigned i = 0;; ++i) { + assert(i != Blocks.size() && "Loop does not contain BB!"); + if (Blocks[i] == BB) { + Blocks[i] = Blocks[0]; + Blocks[0] = BB; + return; + } + } + } + + /// This removes the specified basic block from the current loop, updating the + /// Blocks as appropriate. This does not update the mapping in the LoopInfo + /// class. + void removeBlockFromLoop(BlockT *BB) { + assert(!isInvalid() && "Loop not in a valid state!"); + auto I = find(Blocks, BB); + assert(I != Blocks.end() && "N is not in this list!"); + Blocks.erase(I); + + DenseBlockSet.erase(BB); + } + + /// Verify loop structure + void verifyLoop() const; + + /// Verify loop structure of this loop and all nested loops. + void verifyLoopNest(DenseSet<const LoopT *> *Loops) const; + + /// Returns true if the loop is annotated parallel. + /// + /// Derived classes can override this method using static template + /// polymorphism. + bool isAnnotatedParallel() const { return false; } + + /// Print loop with all the BBs inside it. + void print(raw_ostream &OS, unsigned Depth = 0, bool Verbose = false) const; + +protected: + friend class LoopInfoBase<BlockT, LoopT>; + + /// This creates an empty loop. + LoopBase() : ParentLoop(nullptr) {} + + explicit LoopBase(BlockT *BB) : ParentLoop(nullptr) { + Blocks.push_back(BB); + DenseBlockSet.insert(BB); + } + + // Since loop passes like SCEV are allowed to key analysis results off of + // `Loop` pointers, we cannot re-use pointers within a loop pass manager. + // This means loop passes should not be `delete` ing `Loop` objects directly + // (and risk a later `Loop` allocation re-using the address of a previous one) + // but should be using LoopInfo::markAsRemoved, which keeps around the `Loop` + // pointer till the end of the lifetime of the `LoopInfo` object. + // + // To make it easier to follow this rule, we mark the destructor as + // non-public. + ~LoopBase() { + for (auto *SubLoop : SubLoops) + SubLoop->~LoopT(); + +#if LLVM_ENABLE_ABI_BREAKING_CHECKS + IsInvalid = true; +#endif + SubLoops.clear(); + Blocks.clear(); + DenseBlockSet.clear(); + ParentLoop = nullptr; + } +}; + +template <class BlockT, class LoopT> +raw_ostream &operator<<(raw_ostream &OS, const LoopBase<BlockT, LoopT> &Loop) { + Loop.print(OS); + return OS; +} + +// 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 necessarily loops. +class Loop : public LoopBase<BasicBlock, Loop> { +public: + /// A range representing the start and end location of a loop. + class LocRange { + DebugLoc Start; + DebugLoc End; + + public: + LocRange() {} + LocRange(DebugLoc Start) : Start(Start), End(Start) {} + LocRange(DebugLoc Start, DebugLoc End) + : Start(std::move(Start)), End(std::move(End)) {} + + const DebugLoc &getStart() const { return Start; } + const DebugLoc &getEnd() const { return End; } + + /// Check for null. + /// + explicit operator bool() const { return Start && End; } + }; + + /// Return true if the specified value is loop invariant. + bool isLoopInvariant(const Value *V) const; + + /// Return true if all the operands of the specified instruction are loop + /// invariant. + bool hasLoopInvariantOperands(const Instruction *I) const; + + /// If the given value is an instruction inside of the loop and it can be + /// hoisted, do so to make it trivially loop-invariant. + /// Return true if the value after any hoisting is loop invariant. This + /// function can be used as a slightly more aggressive replacement for + /// isLoopInvariant. + /// + /// If InsertPt is specified, it is the point to hoist instructions to. + /// If null, the terminator of the loop preheader is used. + bool makeLoopInvariant(Value *V, bool &Changed, + Instruction *InsertPt = nullptr, + MemorySSAUpdater *MSSAU = nullptr) const; + + /// If the given instruction is inside of the loop and it can be hoisted, do + /// so to make it trivially loop-invariant. + /// Return true if the instruction after any hoisting is loop invariant. This + /// function can be used as a slightly more aggressive replacement for + /// isLoopInvariant. + /// + /// If InsertPt is specified, it is the point to hoist instructions to. + /// If null, the terminator of the loop preheader is used. + /// + bool makeLoopInvariant(Instruction *I, bool &Changed, + Instruction *InsertPt = nullptr, + MemorySSAUpdater *MSSAU = nullptr) const; + + /// Check to see if the loop has a canonical induction variable: an integer + /// recurrence that starts at 0 and increments by one each time through the + /// loop. If so, return the phi node that corresponds to it. + /// + /// The IndVarSimplify pass transforms loops to have a canonical induction + /// variable. + /// + PHINode *getCanonicalInductionVariable() const; + + /// Obtain the unique incoming and back edge. Return false if they are + /// non-unique or the loop is dead; otherwise, return true. + bool getIncomingAndBackEdge(BasicBlock *&Incoming, + BasicBlock *&Backedge) const; + + /// Below are some utilities to get the loop guard, loop bounds and induction + /// variable, and to check if a given phinode is an auxiliary induction + /// variable, if the loop is guarded, and if the loop is canonical. + /// + /// Here is an example: + /// \code + /// for (int i = lb; i < ub; i+=step) + /// <loop body> + /// --- pseudo LLVMIR --- + /// beforeloop: + /// guardcmp = (lb < ub) + /// if (guardcmp) goto preheader; else goto afterloop + /// preheader: + /// loop: + /// i_1 = phi[{lb, preheader}, {i_2, latch}] + /// <loop body> + /// i_2 = i_1 + step + /// latch: + /// cmp = (i_2 < ub) + /// if (cmp) goto loop + /// exit: + /// afterloop: + /// \endcode + /// + /// - getBounds + /// - getInitialIVValue --> lb + /// - getStepInst --> i_2 = i_1 + step + /// - getStepValue --> step + /// - getFinalIVValue --> ub + /// - getCanonicalPredicate --> '<' + /// - getDirection --> Increasing + /// + /// - getInductionVariable --> i_1 + /// - isAuxiliaryInductionVariable(x) --> true if x == i_1 + /// - getLoopGuardBranch() + /// --> `if (guardcmp) goto preheader; else goto afterloop` + /// - isGuarded() --> true + /// - isCanonical --> false + struct LoopBounds { + /// Return the LoopBounds object if + /// - the given \p IndVar is an induction variable + /// - the initial value of the induction variable can be found + /// - the step instruction of the induction variable can be found + /// - the final value of the induction variable can be found + /// + /// Else None. + static Optional<Loop::LoopBounds> getBounds(const Loop &L, PHINode &IndVar, + ScalarEvolution &SE); + + /// Get the initial value of the loop induction variable. + Value &getInitialIVValue() const { return InitialIVValue; } + + /// Get the instruction that updates the loop induction variable. + Instruction &getStepInst() const { return StepInst; } + + /// Get the step that the loop induction variable gets updated by in each + /// loop iteration. Return nullptr if not found. + Value *getStepValue() const { return StepValue; } + + /// Get the final value of the loop induction variable. + Value &getFinalIVValue() const { return FinalIVValue; } + + /// Return the canonical predicate for the latch compare instruction, if + /// able to be calcuated. Else BAD_ICMP_PREDICATE. + /// + /// A predicate is considered as canonical if requirements below are all + /// satisfied: + /// 1. The first successor of the latch branch is the loop header + /// If not, inverse the predicate. + /// 2. One of the operands of the latch comparison is StepInst + /// If not, and + /// - if the current calcuated predicate is not ne or eq, flip the + /// predicate. + /// - else if the loop is increasing, return slt + /// (notice that it is safe to change from ne or eq to sign compare) + /// - else if the loop is decreasing, return sgt + /// (notice that it is safe to change from ne or eq to sign compare) + /// + /// Here is an example when both (1) and (2) are not satisfied: + /// \code + /// loop.header: + /// %iv = phi [%initialiv, %loop.preheader], [%inc, %loop.header] + /// %inc = add %iv, %step + /// %cmp = slt %iv, %finaliv + /// br %cmp, %loop.exit, %loop.header + /// loop.exit: + /// \endcode + /// - The second successor of the latch branch is the loop header instead + /// of the first successor (slt -> sge) + /// - The first operand of the latch comparison (%cmp) is the IndVar (%iv) + /// instead of the StepInst (%inc) (sge -> sgt) + /// + /// The predicate would be sgt if both (1) and (2) are satisfied. + /// getCanonicalPredicate() returns sgt for this example. + /// Note: The IR is not changed. + ICmpInst::Predicate getCanonicalPredicate() const; + + /// An enum for the direction of the loop + /// - for (int i = 0; i < ub; ++i) --> Increasing + /// - for (int i = ub; i > 0; --i) --> Descresing + /// - for (int i = x; i != y; i+=z) --> Unknown + enum class Direction { Increasing, Decreasing, Unknown }; + + /// Get the direction of the loop. + Direction getDirection() const; + + private: + LoopBounds(const Loop &Loop, Value &I, Instruction &SI, Value *SV, Value &F, + ScalarEvolution &SE) + : L(Loop), InitialIVValue(I), StepInst(SI), StepValue(SV), + FinalIVValue(F), SE(SE) {} + + const Loop &L; + + // The initial value of the loop induction variable + Value &InitialIVValue; + + // The instruction that updates the loop induction variable + Instruction &StepInst; + + // The value that the loop induction variable gets updated by in each loop + // iteration + Value *StepValue; + + // The final value of the loop induction variable + Value &FinalIVValue; + + ScalarEvolution &SE; + }; + + /// Return the struct LoopBounds collected if all struct members are found, + /// else None. + Optional<LoopBounds> getBounds(ScalarEvolution &SE) const; + + /// Return the loop induction variable if found, else return nullptr. + /// An instruction is considered as the loop induction variable if + /// - it is an induction variable of the loop; and + /// - it is used to determine the condition of the branch in the loop latch + /// + /// Note: the induction variable doesn't need to be canonical, i.e. starts at + /// zero and increments by one each time through the loop (but it can be). + PHINode *getInductionVariable(ScalarEvolution &SE) const; + + /// Get the loop induction descriptor for the loop induction variable. Return + /// true if the loop induction variable is found. + bool getInductionDescriptor(ScalarEvolution &SE, + InductionDescriptor &IndDesc) const; + + /// Return true if the given PHINode \p AuxIndVar is + /// - in the loop header + /// - not used outside of the loop + /// - incremented by a loop invariant step for each loop iteration + /// - step instruction opcode should be add or sub + /// Note: auxiliary induction variable is not required to be used in the + /// conditional branch in the loop latch. (but it can be) + bool isAuxiliaryInductionVariable(PHINode &AuxIndVar, + ScalarEvolution &SE) const; + + /// Return the loop guard branch, if it exists. + /// + /// This currently only works on simplified loop, as it requires a preheader + /// and a latch to identify the guard. It will work on loops of the form: + /// \code + /// GuardBB: + /// br cond1, Preheader, ExitSucc <== GuardBranch + /// Preheader: + /// br Header + /// Header: + /// ... + /// br Latch + /// Latch: + /// br cond2, Header, ExitBlock + /// ExitBlock: + /// br ExitSucc + /// ExitSucc: + /// \endcode + BranchInst *getLoopGuardBranch() const; + + /// Return true iff the loop is + /// - in simplify rotated form, and + /// - guarded by a loop guard branch. + bool isGuarded() const { return (getLoopGuardBranch() != nullptr); } + + /// Return true if the loop is in rotated form. + /// + /// This does not check if the loop was rotated by loop rotation, instead it + /// only checks if the loop is in rotated form (has a valid latch that exists + /// the loop). + bool isRotatedForm() const { + assert(!isInvalid() && "Loop not in a valid state!"); + BasicBlock *Latch = getLoopLatch(); + return Latch && isLoopExiting(Latch); + } + + /// Return true if the loop induction variable starts at zero and increments + /// by one each time through the loop. + bool isCanonical(ScalarEvolution &SE) const; + + /// Return true if the Loop is in LCSSA form. + bool isLCSSAForm(DominatorTree &DT) const; + + /// Return true if this Loop and all inner subloops are in LCSSA form. + bool isRecursivelyLCSSAForm(DominatorTree &DT, const LoopInfo &LI) const; + + /// Return true if the Loop is in the form that the LoopSimplify form + /// transforms loops to, which is sometimes called normal form. + bool isLoopSimplifyForm() const; + + /// Return true if the loop body is safe to clone in practice. + bool isSafeToClone() const; + + /// Returns true if the loop is annotated parallel. + /// + /// A parallel loop can be assumed to not contain any dependencies between + /// iterations by the compiler. That is, any loop-carried dependency checking + /// can be skipped completely when parallelizing the loop on the target + /// machine. Thus, if the parallel loop information originates from the + /// programmer, e.g. via the OpenMP parallel for pragma, it is the + /// programmer's responsibility to ensure there are no loop-carried + /// dependencies. The final execution order of the instructions across + /// iterations is not guaranteed, thus, the end result might or might not + /// implement actual concurrent execution of instructions across multiple + /// iterations. + bool isAnnotatedParallel() const; + + /// Return the llvm.loop loop id metadata node for this loop if it is present. + /// + /// If this loop contains the same llvm.loop metadata on each branch to the + /// header then the node is returned. If any latch instruction does not + /// contain llvm.loop or if multiple latches contain different nodes then + /// 0 is returned. + MDNode *getLoopID() const; + /// Set the llvm.loop loop id metadata for this loop. + /// + /// The LoopID metadata node will be added to each terminator instruction in + /// the loop that branches to the loop header. + /// + /// The LoopID metadata node should have one or more operands and the first + /// operand should be the node itself. + void setLoopID(MDNode *LoopID) const; + + /// Add llvm.loop.unroll.disable to this loop's loop id metadata. + /// + /// Remove existing unroll metadata and add unroll disable metadata to + /// indicate the loop has already been unrolled. This prevents a loop + /// from being unrolled more than is directed by a pragma if the loop + /// unrolling pass is run more than once (which it generally is). + void setLoopAlreadyUnrolled(); + + void dump() const; + void dumpVerbose() const; + + /// Return the debug location of the start of this loop. + /// This looks for a BB terminating instruction with a known debug + /// location by looking at the preheader and header blocks. If it + /// cannot find a terminating instruction with location information, + /// it returns an unknown location. + DebugLoc getStartLoc() const; + + /// Return the source code span of the loop. + LocRange getLocRange() const; + + StringRef getName() const { + if (BasicBlock *Header = getHeader()) + if (Header->hasName()) + return Header->getName(); + return "<unnamed loop>"; + } + +private: + Loop() = default; + + friend class LoopInfoBase<BasicBlock, Loop>; + friend class LoopBase<BasicBlock, Loop>; + explicit Loop(BasicBlock *BB) : LoopBase<BasicBlock, Loop>(BB) {} + ~Loop() = default; +}; + +//===----------------------------------------------------------------------===// +/// This class builds and contains all of the top-level loop +/// structures in the specified function. +/// + +template <class BlockT, class LoopT> class LoopInfoBase { + // BBMap - Mapping of basic blocks to the inner most loop they occur in + DenseMap<const BlockT *, LoopT *> BBMap; + std::vector<LoopT *> TopLevelLoops; + BumpPtrAllocator LoopAllocator; + + friend class LoopBase<BlockT, LoopT>; + friend class LoopInfo; + + void operator=(const LoopInfoBase &) = delete; + LoopInfoBase(const LoopInfoBase &) = delete; + +public: + LoopInfoBase() {} + ~LoopInfoBase() { releaseMemory(); } + + LoopInfoBase(LoopInfoBase &&Arg) + : BBMap(std::move(Arg.BBMap)), + TopLevelLoops(std::move(Arg.TopLevelLoops)), + LoopAllocator(std::move(Arg.LoopAllocator)) { + // We have to clear the arguments top level loops as we've taken ownership. + Arg.TopLevelLoops.clear(); + } + LoopInfoBase &operator=(LoopInfoBase &&RHS) { + BBMap = std::move(RHS.BBMap); + + for (auto *L : TopLevelLoops) + L->~LoopT(); + + TopLevelLoops = std::move(RHS.TopLevelLoops); + LoopAllocator = std::move(RHS.LoopAllocator); + RHS.TopLevelLoops.clear(); + return *this; + } + + void releaseMemory() { + BBMap.clear(); + + for (auto *L : TopLevelLoops) + L->~LoopT(); + TopLevelLoops.clear(); + LoopAllocator.Reset(); + } + + template <typename... ArgsTy> LoopT *AllocateLoop(ArgsTy &&... Args) { + LoopT *Storage = LoopAllocator.Allocate<LoopT>(); + return new (Storage) LoopT(std::forward<ArgsTy>(Args)...); + } + + /// iterator/begin/end - The interface to the top-level loops in the current + /// function. + /// + typedef typename std::vector<LoopT *>::const_iterator iterator; + typedef + typename std::vector<LoopT *>::const_reverse_iterator reverse_iterator; + iterator begin() const { return TopLevelLoops.begin(); } + iterator end() const { return TopLevelLoops.end(); } + reverse_iterator rbegin() const { return TopLevelLoops.rbegin(); } + reverse_iterator rend() const { return TopLevelLoops.rend(); } + bool empty() const { return TopLevelLoops.empty(); } + + /// Return all of the loops in the function in preorder across the loop + /// nests, with siblings in forward program order. + /// + /// Note that because loops form a forest of trees, preorder is equivalent to + /// reverse postorder. + SmallVector<LoopT *, 4> getLoopsInPreorder(); + + /// Return all of the loops in the function in preorder across the loop + /// nests, with siblings in *reverse* program order. + /// + /// Note that because loops form a forest of trees, preorder is equivalent to + /// reverse postorder. + /// + /// Also note that this is *not* a reverse preorder. Only the siblings are in + /// reverse program order. + SmallVector<LoopT *, 4> getLoopsInReverseSiblingPreorder(); + + /// Return the inner most loop that BB lives in. If a basic block is in no + /// loop (for example the entry node), null is returned. + LoopT *getLoopFor(const BlockT *BB) const { return BBMap.lookup(BB); } + + /// Same as getLoopFor. + const LoopT *operator[](const BlockT *BB) const { return getLoopFor(BB); } + + /// Return the loop nesting level of the specified block. A depth of 0 means + /// the block is not inside any loop. + unsigned getLoopDepth(const BlockT *BB) const { + const LoopT *L = getLoopFor(BB); + return L ? L->getLoopDepth() : 0; + } + + // True if the block is a loop header node + bool isLoopHeader(const BlockT *BB) const { + const LoopT *L = getLoopFor(BB); + return L && L->getHeader() == BB; + } + + /// This removes the specified top-level loop from this loop info object. + /// The loop is not deleted, as it will presumably be inserted into + /// another loop. + LoopT *removeLoop(iterator I) { + assert(I != end() && "Cannot remove end iterator!"); + LoopT *L = *I; + assert(!L->getParentLoop() && "Not a top-level loop!"); + TopLevelLoops.erase(TopLevelLoops.begin() + (I - begin())); + return L; + } + + /// Change the top-level loop that contains BB to the specified loop. + /// This should be used by transformations that restructure the loop hierarchy + /// tree. + void changeLoopFor(BlockT *BB, LoopT *L) { + if (!L) { + BBMap.erase(BB); + return; + } + BBMap[BB] = L; + } + + /// Replace the specified loop in the top-level loops list with the indicated + /// loop. + void changeTopLevelLoop(LoopT *OldLoop, LoopT *NewLoop) { + auto I = find(TopLevelLoops, OldLoop); + assert(I != TopLevelLoops.end() && "Old loop not at top level!"); + *I = NewLoop; + assert(!NewLoop->ParentLoop && !OldLoop->ParentLoop && + "Loops already embedded into a subloop!"); + } + + /// This adds the specified loop to the collection of top-level loops. + void addTopLevelLoop(LoopT *New) { + assert(!New->getParentLoop() && "Loop already in subloop!"); + TopLevelLoops.push_back(New); + } + + /// This method completely removes BB from all data structures, + /// including all of the Loop objects it is nested in and our mapping from + /// BasicBlocks to loops. + void removeBlock(BlockT *BB) { + auto I = BBMap.find(BB); + if (I != BBMap.end()) { + for (LoopT *L = I->second; L; L = L->getParentLoop()) + L->removeBlockFromLoop(BB); + + BBMap.erase(I); + } + } + + // Internals + + static bool isNotAlreadyContainedIn(const LoopT *SubLoop, + const LoopT *ParentLoop) { + if (!SubLoop) + return true; + if (SubLoop == ParentLoop) + return false; + return isNotAlreadyContainedIn(SubLoop->getParentLoop(), ParentLoop); + } + + /// Create the loop forest using a stable algorithm. + void analyze(const DominatorTreeBase<BlockT, false> &DomTree); + + // Debugging + void print(raw_ostream &OS) const; + + void verify(const DominatorTreeBase<BlockT, false> &DomTree) const; + + /// Destroy a loop that has been removed from the `LoopInfo` nest. + /// + /// This runs the destructor of the loop object making it invalid to + /// reference afterward. The memory is retained so that the *pointer* to the + /// loop remains valid. + /// + /// The caller is responsible for removing this loop from the loop nest and + /// otherwise disconnecting it from the broader `LoopInfo` data structures. + /// Callers that don't naturally handle this themselves should probably call + /// `erase' instead. + void destroy(LoopT *L) { + L->~LoopT(); + + // Since LoopAllocator is a BumpPtrAllocator, this Deallocate only poisons + // \c L, but the pointer remains valid for non-dereferencing uses. + LoopAllocator.Deallocate(L); + } +}; + +// Implementation in LoopInfoImpl.h +extern template class LoopInfoBase<BasicBlock, Loop>; + +class LoopInfo : public LoopInfoBase<BasicBlock, Loop> { + typedef LoopInfoBase<BasicBlock, Loop> BaseT; + + friend class LoopBase<BasicBlock, Loop>; + + void operator=(const LoopInfo &) = delete; + LoopInfo(const LoopInfo &) = delete; + +public: + LoopInfo() {} + explicit LoopInfo(const DominatorTreeBase<BasicBlock, false> &DomTree); + + LoopInfo(LoopInfo &&Arg) : BaseT(std::move(static_cast<BaseT &>(Arg))) {} + LoopInfo &operator=(LoopInfo &&RHS) { + BaseT::operator=(std::move(static_cast<BaseT &>(RHS))); + return *this; + } + + /// Handle invalidation explicitly. + bool invalidate(Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &); + + // Most of the public interface is provided via LoopInfoBase. + + /// Update LoopInfo after removing the last backedge from a loop. This updates + /// the loop forest and parent loops for each block so that \c L is no longer + /// referenced, but does not actually delete \c L immediately. The pointer + /// will remain valid until this LoopInfo's memory is released. + void erase(Loop *L); + + /// Returns true if replacing From with To everywhere is guaranteed to + /// preserve LCSSA form. + bool replacementPreservesLCSSAForm(Instruction *From, Value *To) { + // Preserving LCSSA form is only problematic if the replacing value is an + // instruction. + Instruction *I = dyn_cast<Instruction>(To); + if (!I) + return true; + // If both instructions are defined in the same basic block then replacement + // cannot break LCSSA form. + if (I->getParent() == From->getParent()) + return true; + // If the instruction is not defined in a loop then it can safely replace + // anything. + Loop *ToLoop = getLoopFor(I->getParent()); + if (!ToLoop) + return true; + // If the replacing instruction is defined in the same loop as the original + // instruction, or in a loop that contains it as an inner loop, then using + // it as a replacement will not break LCSSA form. + return ToLoop->contains(getLoopFor(From->getParent())); + } + + /// Checks if moving a specific instruction can break LCSSA in any loop. + /// + /// Return true if moving \p Inst to before \p NewLoc will break LCSSA, + /// assuming that the function containing \p Inst and \p NewLoc is currently + /// in LCSSA form. + bool movementPreservesLCSSAForm(Instruction *Inst, Instruction *NewLoc) { + assert(Inst->getFunction() == NewLoc->getFunction() && + "Can't reason about IPO!"); + + auto *OldBB = Inst->getParent(); + auto *NewBB = NewLoc->getParent(); + + // Movement within the same loop does not break LCSSA (the equality check is + // to avoid doing a hashtable lookup in case of intra-block movement). + if (OldBB == NewBB) + return true; + + auto *OldLoop = getLoopFor(OldBB); + auto *NewLoop = getLoopFor(NewBB); + + if (OldLoop == NewLoop) + return true; + + // Check if Outer contains Inner; with the null loop counting as the + // "outermost" loop. + auto Contains = [](const Loop *Outer, const Loop *Inner) { + return !Outer || Outer->contains(Inner); + }; + + // To check that the movement of Inst to before NewLoc does not break LCSSA, + // we need to check two sets of uses for possible LCSSA violations at + // NewLoc: the users of NewInst, and the operands of NewInst. + + // If we know we're hoisting Inst out of an inner loop to an outer loop, + // then the uses *of* Inst don't need to be checked. + + if (!Contains(NewLoop, OldLoop)) { + for (Use &U : Inst->uses()) { + auto *UI = cast<Instruction>(U.getUser()); + auto *UBB = isa<PHINode>(UI) ? cast<PHINode>(UI)->getIncomingBlock(U) + : UI->getParent(); + if (UBB != NewBB && getLoopFor(UBB) != NewLoop) + return false; + } + } + + // If we know we're sinking Inst from an outer loop into an inner loop, then + // the *operands* of Inst don't need to be checked. + + if (!Contains(OldLoop, NewLoop)) { + // See below on why we can't handle phi nodes here. + if (isa<PHINode>(Inst)) + return false; + + for (Use &U : Inst->operands()) { + auto *DefI = dyn_cast<Instruction>(U.get()); + if (!DefI) + return false; + + // This would need adjustment if we allow Inst to be a phi node -- the + // new use block won't simply be NewBB. + + auto *DefBlock = DefI->getParent(); + if (DefBlock != NewBB && getLoopFor(DefBlock) != NewLoop) + return false; + } + } + + return true; + } +}; + +// Allow clients to walk the list of nested loops... +template <> struct GraphTraits<const Loop *> { + typedef const Loop *NodeRef; + typedef LoopInfo::iterator ChildIteratorType; + + static NodeRef getEntryNode(const Loop *L) { return L; } + static ChildIteratorType child_begin(NodeRef N) { return N->begin(); } + static ChildIteratorType child_end(NodeRef N) { return N->end(); } +}; + +template <> struct GraphTraits<Loop *> { + typedef Loop *NodeRef; + typedef LoopInfo::iterator ChildIteratorType; + + static NodeRef getEntryNode(Loop *L) { return L; } + static ChildIteratorType child_begin(NodeRef N) { return N->begin(); } + static ChildIteratorType child_end(NodeRef N) { return N->end(); } +}; + +/// Analysis pass that exposes the \c LoopInfo for a function. +class LoopAnalysis : public AnalysisInfoMixin<LoopAnalysis> { + friend AnalysisInfoMixin<LoopAnalysis>; + static AnalysisKey Key; + +public: + typedef LoopInfo Result; + + LoopInfo run(Function &F, FunctionAnalysisManager &AM); +}; + +/// Printer pass for the \c LoopAnalysis results. +class LoopPrinterPass : public PassInfoMixin<LoopPrinterPass> { + raw_ostream &OS; + +public: + explicit LoopPrinterPass(raw_ostream &OS) : OS(OS) {} + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + +/// Verifier pass for the \c LoopAnalysis results. +struct LoopVerifierPass : public PassInfoMixin<LoopVerifierPass> { + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + +/// The legacy pass manager's analysis pass to compute loop information. +class LoopInfoWrapperPass : public FunctionPass { + LoopInfo LI; + +public: + static char ID; // Pass identification, replacement for typeid + + LoopInfoWrapperPass(); + + LoopInfo &getLoopInfo() { return LI; } + const LoopInfo &getLoopInfo() const { return LI; } + + /// Calculate the natural loop information for a given function. + bool runOnFunction(Function &F) override; + + void verifyAnalysis() const override; + + void releaseMemory() override { LI.releaseMemory(); } + + void print(raw_ostream &O, const Module *M = nullptr) const override; + + void getAnalysisUsage(AnalysisUsage &AU) const override; +}; + +/// Function to print a loop's contents as LLVM's text IR assembly. +void printLoop(Loop &L, raw_ostream &OS, const std::string &Banner = ""); + +/// Find and return the loop attribute node for the attribute @p Name in +/// @p LoopID. Return nullptr if there is no such attribute. +MDNode *findOptionMDForLoopID(MDNode *LoopID, StringRef Name); + +/// Find string metadata for a loop. +/// +/// Returns the MDNode where the first operand is the metadata's name. The +/// following operands are the metadata's values. If no metadata with @p Name is +/// found, return nullptr. +MDNode *findOptionMDForLoop(const Loop *TheLoop, StringRef Name); + +/// Return whether an MDNode might represent an access group. +/// +/// Access group metadata nodes have to be distinct and empty. Being +/// always-empty ensures that it never needs to be changed (which -- because +/// MDNodes are designed immutable -- would require creating a new MDNode). Note +/// that this is not a sufficient condition: not every distinct and empty NDNode +/// is representing an access group. +bool isValidAsAccessGroup(MDNode *AccGroup); + +/// Create a new LoopID after the loop has been transformed. +/// +/// This can be used when no follow-up loop attributes are defined +/// (llvm::makeFollowupLoopID returning None) to stop transformations to be +/// applied again. +/// +/// @param Context The LLVMContext in which to create the new LoopID. +/// @param OrigLoopID The original LoopID; can be nullptr if the original +/// loop has no LoopID. +/// @param RemovePrefixes Remove all loop attributes that have these prefixes. +/// Use to remove metadata of the transformation that has +/// been applied. +/// @param AddAttrs Add these loop attributes to the new LoopID. +/// +/// @return A new LoopID that can be applied using Loop::setLoopID(). +llvm::MDNode * +makePostTransformationMetadata(llvm::LLVMContext &Context, MDNode *OrigLoopID, + llvm::ArrayRef<llvm::StringRef> RemovePrefixes, + llvm::ArrayRef<llvm::MDNode *> AddAttrs); + +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/LoopInfoImpl.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/LoopInfoImpl.h new file mode 100644 index 0000000..99f192a --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/LoopInfoImpl.h
@@ -0,0 +1,737 @@ +//===- llvm/Analysis/LoopInfoImpl.h - Natural Loop Calculator ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This is the generic implementation of LoopInfo used for both Loops and +// MachineLoops. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LOOPINFOIMPL_H +#define LLVM_ANALYSIS_LOOPINFOIMPL_H + +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/IR/Dominators.h" + +namespace llvm { + +//===----------------------------------------------------------------------===// +// APIs for simple analysis of the loop. See header notes. + +/// getExitingBlocks - Return all blocks inside the loop that have successors +/// outside of the loop. These are the blocks _inside of the current loop_ +/// which branch out. The returned list is always unique. +/// +template <class BlockT, class LoopT> +void LoopBase<BlockT, LoopT>::getExitingBlocks( + SmallVectorImpl<BlockT *> &ExitingBlocks) const { + assert(!isInvalid() && "Loop not in a valid state!"); + for (const auto BB : blocks()) + for (auto *Succ : children<BlockT *>(BB)) + if (!contains(Succ)) { + // Not in current loop? It must be an exit block. + ExitingBlocks.push_back(BB); + break; + } +} + +/// getExitingBlock - If getExitingBlocks would return exactly one block, +/// return that block. Otherwise return null. +template <class BlockT, class LoopT> +BlockT *LoopBase<BlockT, LoopT>::getExitingBlock() const { + assert(!isInvalid() && "Loop not in a valid state!"); + SmallVector<BlockT *, 8> ExitingBlocks; + getExitingBlocks(ExitingBlocks); + if (ExitingBlocks.size() == 1) + return ExitingBlocks[0]; + return nullptr; +} + +/// getExitBlocks - Return all of the successor blocks of this loop. These +/// are the blocks _outside of the current loop_ which are branched to. +/// +template <class BlockT, class LoopT> +void LoopBase<BlockT, LoopT>::getExitBlocks( + SmallVectorImpl<BlockT *> &ExitBlocks) const { + assert(!isInvalid() && "Loop not in a valid state!"); + for (const auto BB : blocks()) + for (auto *Succ : children<BlockT *>(BB)) + if (!contains(Succ)) + // Not in current loop? It must be an exit block. + ExitBlocks.push_back(Succ); +} + +/// getExitBlock - If getExitBlocks would return exactly one block, +/// return that block. Otherwise return null. +template <class BlockT, class LoopT> +BlockT *LoopBase<BlockT, LoopT>::getExitBlock() const { + assert(!isInvalid() && "Loop not in a valid state!"); + SmallVector<BlockT *, 8> ExitBlocks; + getExitBlocks(ExitBlocks); + if (ExitBlocks.size() == 1) + return ExitBlocks[0]; + return nullptr; +} + +template <class BlockT, class LoopT> +bool LoopBase<BlockT, LoopT>::hasDedicatedExits() const { + // Each predecessor of each exit block of a normal loop is contained + // within the loop. + SmallVector<BlockT *, 4> UniqueExitBlocks; + getUniqueExitBlocks(UniqueExitBlocks); + for (BlockT *EB : UniqueExitBlocks) + for (BlockT *Predecessor : children<Inverse<BlockT *>>(EB)) + if (!contains(Predecessor)) + return false; + // All the requirements are met. + return true; +} + +// Helper function to get unique loop exits. Pred is a predicate pointing to +// BasicBlocks in a loop which should be considered to find loop exits. +template <class BlockT, class LoopT, typename PredicateT> +void getUniqueExitBlocksHelper(const LoopT *L, + SmallVectorImpl<BlockT *> &ExitBlocks, + PredicateT Pred) { + assert(!L->isInvalid() && "Loop not in a valid state!"); + SmallPtrSet<BlockT *, 32> Visited; + auto Filtered = make_filter_range(L->blocks(), Pred); + for (BlockT *BB : Filtered) + for (BlockT *Successor : children<BlockT *>(BB)) + if (!L->contains(Successor)) + if (Visited.insert(Successor).second) + ExitBlocks.push_back(Successor); +} + +template <class BlockT, class LoopT> +void LoopBase<BlockT, LoopT>::getUniqueExitBlocks( + SmallVectorImpl<BlockT *> &ExitBlocks) const { + getUniqueExitBlocksHelper(this, ExitBlocks, + [](const BlockT *BB) { return true; }); +} + +template <class BlockT, class LoopT> +void LoopBase<BlockT, LoopT>::getUniqueNonLatchExitBlocks( + SmallVectorImpl<BlockT *> &ExitBlocks) const { + const BlockT *Latch = getLoopLatch(); + assert(Latch && "Latch block must exists"); + getUniqueExitBlocksHelper(this, ExitBlocks, + [Latch](const BlockT *BB) { return BB != Latch; }); +} + +template <class BlockT, class LoopT> +BlockT *LoopBase<BlockT, LoopT>::getUniqueExitBlock() const { + SmallVector<BlockT *, 8> UniqueExitBlocks; + getUniqueExitBlocks(UniqueExitBlocks); + if (UniqueExitBlocks.size() == 1) + return UniqueExitBlocks[0]; + return nullptr; +} + +/// getExitEdges - Return all pairs of (_inside_block_,_outside_block_). +template <class BlockT, class LoopT> +void LoopBase<BlockT, LoopT>::getExitEdges( + SmallVectorImpl<Edge> &ExitEdges) const { + assert(!isInvalid() && "Loop not in a valid state!"); + for (const auto BB : blocks()) + for (auto *Succ : children<BlockT *>(BB)) + if (!contains(Succ)) + // Not in current loop? It must be an exit block. + ExitEdges.emplace_back(BB, Succ); +} + +/// getLoopPreheader - If there is a preheader for this loop, return it. A +/// loop has a preheader if there is only one edge to the header of the loop +/// from outside of the loop and it is legal to hoist instructions into the +/// predecessor. If this is the case, the block branching to the header of the +/// loop is the preheader node. +/// +/// This method returns null if there is no preheader for the loop. +/// +template <class BlockT, class LoopT> +BlockT *LoopBase<BlockT, LoopT>::getLoopPreheader() const { + assert(!isInvalid() && "Loop not in a valid state!"); + // Keep track of nodes outside the loop branching to the header... + BlockT *Out = getLoopPredecessor(); + if (!Out) + return nullptr; + + // Make sure we are allowed to hoist instructions into the predecessor. + if (!Out->isLegalToHoistInto()) + return nullptr; + + // Make sure there is only one exit out of the preheader. + typedef GraphTraits<BlockT *> BlockTraits; + typename BlockTraits::ChildIteratorType SI = BlockTraits::child_begin(Out); + ++SI; + if (SI != BlockTraits::child_end(Out)) + return nullptr; // Multiple exits from the block, must not be a preheader. + + // The predecessor has exactly one successor, so it is a preheader. + return Out; +} + +/// getLoopPredecessor - If the given loop's header has exactly one unique +/// predecessor outside the loop, return it. Otherwise return null. +/// This is less strict that the loop "preheader" concept, which requires +/// the predecessor to have exactly one successor. +/// +template <class BlockT, class LoopT> +BlockT *LoopBase<BlockT, LoopT>::getLoopPredecessor() const { + assert(!isInvalid() && "Loop not in a valid state!"); + // Keep track of nodes outside the loop branching to the header... + BlockT *Out = nullptr; + + // Loop over the predecessors of the header node... + BlockT *Header = getHeader(); + for (const auto Pred : children<Inverse<BlockT *>>(Header)) { + if (!contains(Pred)) { // If the block is not in the loop... + if (Out && Out != Pred) + return nullptr; // Multiple predecessors outside the loop + Out = Pred; + } + } + + return Out; +} + +/// getLoopLatch - If there is a single latch block for this loop, return it. +/// A latch block is a block that contains a branch back to the header. +template <class BlockT, class LoopT> +BlockT *LoopBase<BlockT, LoopT>::getLoopLatch() const { + assert(!isInvalid() && "Loop not in a valid state!"); + BlockT *Header = getHeader(); + BlockT *Latch = nullptr; + for (const auto Pred : children<Inverse<BlockT *>>(Header)) { + if (contains(Pred)) { + if (Latch) + return nullptr; + Latch = Pred; + } + } + + return Latch; +} + +//===----------------------------------------------------------------------===// +// APIs for updating loop information after changing the CFG +// + +/// addBasicBlockToLoop - This method is used by other analyses to update loop +/// information. NewBB is set to be a new member of the current loop. +/// Because of this, it is added as a member of all parent loops, and is added +/// to the specified LoopInfo object as being in the current basic block. It +/// is not valid to replace the loop header with this method. +/// +template <class BlockT, class LoopT> +void LoopBase<BlockT, LoopT>::addBasicBlockToLoop( + BlockT *NewBB, LoopInfoBase<BlockT, LoopT> &LIB) { + assert(!isInvalid() && "Loop not in a valid state!"); +#ifndef NDEBUG + if (!Blocks.empty()) { + auto SameHeader = LIB[getHeader()]; + assert(contains(SameHeader) && getHeader() == SameHeader->getHeader() && + "Incorrect LI specified for this loop!"); + } +#endif + assert(NewBB && "Cannot add a null basic block to the loop!"); + assert(!LIB[NewBB] && "BasicBlock already in the loop!"); + + LoopT *L = static_cast<LoopT *>(this); + + // Add the loop mapping to the LoopInfo object... + LIB.BBMap[NewBB] = L; + + // Add the basic block to this loop and all parent loops... + while (L) { + L->addBlockEntry(NewBB); + L = L->getParentLoop(); + } +} + +/// replaceChildLoopWith - This is used when splitting loops up. It replaces +/// the OldChild entry in our children list with NewChild, and updates the +/// parent pointer of OldChild to be null and the NewChild to be this loop. +/// This updates the loop depth of the new child. +template <class BlockT, class LoopT> +void LoopBase<BlockT, LoopT>::replaceChildLoopWith(LoopT *OldChild, + LoopT *NewChild) { + assert(!isInvalid() && "Loop not in a valid state!"); + assert(OldChild->ParentLoop == this && "This loop is already broken!"); + assert(!NewChild->ParentLoop && "NewChild already has a parent!"); + typename std::vector<LoopT *>::iterator I = find(SubLoops, OldChild); + assert(I != SubLoops.end() && "OldChild not in loop!"); + *I = NewChild; + OldChild->ParentLoop = nullptr; + NewChild->ParentLoop = static_cast<LoopT *>(this); +} + +/// verifyLoop - Verify loop structure +template <class BlockT, class LoopT> +void LoopBase<BlockT, LoopT>::verifyLoop() const { + assert(!isInvalid() && "Loop not in a valid state!"); +#ifndef NDEBUG + assert(!Blocks.empty() && "Loop header is missing"); + + // Setup for using a depth-first iterator to visit every block in the loop. + SmallVector<BlockT *, 8> ExitBBs; + getExitBlocks(ExitBBs); + df_iterator_default_set<BlockT *> VisitSet; + VisitSet.insert(ExitBBs.begin(), ExitBBs.end()); + df_ext_iterator<BlockT *, df_iterator_default_set<BlockT *>> + BI = df_ext_begin(getHeader(), VisitSet), + BE = df_ext_end(getHeader(), VisitSet); + + // Keep track of the BBs visited. + SmallPtrSet<BlockT *, 8> VisitedBBs; + + // Check the individual blocks. + for (; BI != BE; ++BI) { + BlockT *BB = *BI; + + assert(std::any_of(GraphTraits<BlockT *>::child_begin(BB), + GraphTraits<BlockT *>::child_end(BB), + [&](BlockT *B) { return contains(B); }) && + "Loop block has no in-loop successors!"); + + assert(std::any_of(GraphTraits<Inverse<BlockT *>>::child_begin(BB), + GraphTraits<Inverse<BlockT *>>::child_end(BB), + [&](BlockT *B) { return contains(B); }) && + "Loop block has no in-loop predecessors!"); + + SmallVector<BlockT *, 2> OutsideLoopPreds; + std::for_each(GraphTraits<Inverse<BlockT *>>::child_begin(BB), + GraphTraits<Inverse<BlockT *>>::child_end(BB), + [&](BlockT *B) { + if (!contains(B)) + OutsideLoopPreds.push_back(B); + }); + + if (BB == getHeader()) { + assert(!OutsideLoopPreds.empty() && "Loop is unreachable!"); + } else if (!OutsideLoopPreds.empty()) { + // A non-header loop shouldn't be reachable from outside the loop, + // though it is permitted if the predecessor is not itself actually + // reachable. + BlockT *EntryBB = &BB->getParent()->front(); + for (BlockT *CB : depth_first(EntryBB)) + for (unsigned i = 0, e = OutsideLoopPreds.size(); i != e; ++i) + assert(CB != OutsideLoopPreds[i] && + "Loop has multiple entry points!"); + } + assert(BB != &getHeader()->getParent()->front() && + "Loop contains function entry block!"); + + VisitedBBs.insert(BB); + } + + if (VisitedBBs.size() != getNumBlocks()) { + dbgs() << "The following blocks are unreachable in the loop: "; + for (auto BB : Blocks) { + if (!VisitedBBs.count(BB)) { + dbgs() << *BB << "\n"; + } + } + assert(false && "Unreachable block in loop"); + } + + // Check the subloops. + for (iterator I = begin(), E = end(); I != E; ++I) + // Each block in each subloop should be contained within this loop. + for (block_iterator BI = (*I)->block_begin(), BE = (*I)->block_end(); + BI != BE; ++BI) { + assert(contains(*BI) && + "Loop does not contain all the blocks of a subloop!"); + } + + // Check the parent loop pointer. + if (ParentLoop) { + assert(is_contained(*ParentLoop, this) && + "Loop is not a subloop of its parent!"); + } +#endif +} + +/// verifyLoop - Verify loop structure of this loop and all nested loops. +template <class BlockT, class LoopT> +void LoopBase<BlockT, LoopT>::verifyLoopNest( + DenseSet<const LoopT *> *Loops) const { + assert(!isInvalid() && "Loop not in a valid state!"); + Loops->insert(static_cast<const LoopT *>(this)); + // Verify this loop. + verifyLoop(); + // Verify the subloops. + for (iterator I = begin(), E = end(); I != E; ++I) + (*I)->verifyLoopNest(Loops); +} + +template <class BlockT, class LoopT> +void LoopBase<BlockT, LoopT>::print(raw_ostream &OS, unsigned Depth, + bool Verbose) const { + OS.indent(Depth * 2); + if (static_cast<const LoopT *>(this)->isAnnotatedParallel()) + OS << "Parallel "; + OS << "Loop at depth " << getLoopDepth() << " containing: "; + + BlockT *H = getHeader(); + for (unsigned i = 0; i < getBlocks().size(); ++i) { + BlockT *BB = getBlocks()[i]; + if (!Verbose) { + if (i) + OS << ","; + BB->printAsOperand(OS, false); + } else + OS << "\n"; + + if (BB == H) + OS << "<header>"; + if (isLoopLatch(BB)) + OS << "<latch>"; + if (isLoopExiting(BB)) + OS << "<exiting>"; + if (Verbose) + BB->print(OS); + } + OS << "\n"; + + for (iterator I = begin(), E = end(); I != E; ++I) + (*I)->print(OS, Depth + 2); +} + +//===----------------------------------------------------------------------===// +/// Stable LoopInfo Analysis - Build a loop tree using stable iterators so the +/// result does / not depend on use list (block predecessor) order. +/// + +/// Discover a subloop with the specified backedges such that: All blocks within +/// this loop are mapped to this loop or a subloop. And all subloops within this +/// loop have their parent loop set to this loop or a subloop. +template <class BlockT, class LoopT> +static void discoverAndMapSubloop(LoopT *L, ArrayRef<BlockT *> Backedges, + LoopInfoBase<BlockT, LoopT> *LI, + const DomTreeBase<BlockT> &DomTree) { + typedef GraphTraits<Inverse<BlockT *>> InvBlockTraits; + + unsigned NumBlocks = 0; + unsigned NumSubloops = 0; + + // Perform a backward CFG traversal using a worklist. + std::vector<BlockT *> ReverseCFGWorklist(Backedges.begin(), Backedges.end()); + while (!ReverseCFGWorklist.empty()) { + BlockT *PredBB = ReverseCFGWorklist.back(); + ReverseCFGWorklist.pop_back(); + + LoopT *Subloop = LI->getLoopFor(PredBB); + if (!Subloop) { + if (!DomTree.isReachableFromEntry(PredBB)) + continue; + + // This is an undiscovered block. Map it to the current loop. + LI->changeLoopFor(PredBB, L); + ++NumBlocks; + if (PredBB == L->getHeader()) + continue; + // Push all block predecessors on the worklist. + ReverseCFGWorklist.insert(ReverseCFGWorklist.end(), + InvBlockTraits::child_begin(PredBB), + InvBlockTraits::child_end(PredBB)); + } else { + // This is a discovered block. Find its outermost discovered loop. + while (LoopT *Parent = Subloop->getParentLoop()) + Subloop = Parent; + + // If it is already discovered to be a subloop of this loop, continue. + if (Subloop == L) + continue; + + // Discover a subloop of this loop. + Subloop->setParentLoop(L); + ++NumSubloops; + NumBlocks += Subloop->getBlocksVector().capacity(); + PredBB = Subloop->getHeader(); + // Continue traversal along predecessors that are not loop-back edges from + // within this subloop tree itself. Note that a predecessor may directly + // reach another subloop that is not yet discovered to be a subloop of + // this loop, which we must traverse. + for (const auto Pred : children<Inverse<BlockT *>>(PredBB)) { + if (LI->getLoopFor(Pred) != Subloop) + ReverseCFGWorklist.push_back(Pred); + } + } + } + L->getSubLoopsVector().reserve(NumSubloops); + L->reserveBlocks(NumBlocks); +} + +/// Populate all loop data in a stable order during a single forward DFS. +template <class BlockT, class LoopT> class PopulateLoopsDFS { + typedef GraphTraits<BlockT *> BlockTraits; + typedef typename BlockTraits::ChildIteratorType SuccIterTy; + + LoopInfoBase<BlockT, LoopT> *LI; + +public: + PopulateLoopsDFS(LoopInfoBase<BlockT, LoopT> *li) : LI(li) {} + + void traverse(BlockT *EntryBlock); + +protected: + void insertIntoLoop(BlockT *Block); +}; + +/// Top-level driver for the forward DFS within the loop. +template <class BlockT, class LoopT> +void PopulateLoopsDFS<BlockT, LoopT>::traverse(BlockT *EntryBlock) { + for (BlockT *BB : post_order(EntryBlock)) + insertIntoLoop(BB); +} + +/// Add a single Block to its ancestor loops in PostOrder. If the block is a +/// subloop header, add the subloop to its parent in PostOrder, then reverse the +/// Block and Subloop vectors of the now complete subloop to achieve RPO. +template <class BlockT, class LoopT> +void PopulateLoopsDFS<BlockT, LoopT>::insertIntoLoop(BlockT *Block) { + LoopT *Subloop = LI->getLoopFor(Block); + if (Subloop && Block == Subloop->getHeader()) { + // We reach this point once per subloop after processing all the blocks in + // the subloop. + if (Subloop->getParentLoop()) + Subloop->getParentLoop()->getSubLoopsVector().push_back(Subloop); + else + LI->addTopLevelLoop(Subloop); + + // For convenience, Blocks and Subloops are inserted in postorder. Reverse + // the lists, except for the loop header, which is always at the beginning. + Subloop->reverseBlock(1); + std::reverse(Subloop->getSubLoopsVector().begin(), + Subloop->getSubLoopsVector().end()); + + Subloop = Subloop->getParentLoop(); + } + for (; Subloop; Subloop = Subloop->getParentLoop()) + Subloop->addBlockEntry(Block); +} + +/// Analyze LoopInfo discovers loops during a postorder DominatorTree traversal +/// interleaved with backward CFG traversals within each subloop +/// (discoverAndMapSubloop). The backward traversal skips inner subloops, so +/// this part of the algorithm is linear in the number of CFG edges. Subloop and +/// Block vectors are then populated during a single forward CFG traversal +/// (PopulateLoopDFS). +/// +/// During the two CFG traversals each block is seen three times: +/// 1) Discovered and mapped by a reverse CFG traversal. +/// 2) Visited during a forward DFS CFG traversal. +/// 3) Reverse-inserted in the loop in postorder following forward DFS. +/// +/// The Block vectors are inclusive, so step 3 requires loop-depth number of +/// insertions per block. +template <class BlockT, class LoopT> +void LoopInfoBase<BlockT, LoopT>::analyze(const DomTreeBase<BlockT> &DomTree) { + // Postorder traversal of the dominator tree. + const DomTreeNodeBase<BlockT> *DomRoot = DomTree.getRootNode(); + for (auto DomNode : post_order(DomRoot)) { + + BlockT *Header = DomNode->getBlock(); + SmallVector<BlockT *, 4> Backedges; + + // Check each predecessor of the potential loop header. + for (const auto Backedge : children<Inverse<BlockT *>>(Header)) { + // If Header dominates predBB, this is a new loop. Collect the backedges. + if (DomTree.dominates(Header, Backedge) && + DomTree.isReachableFromEntry(Backedge)) { + Backedges.push_back(Backedge); + } + } + // Perform a backward CFG traversal to discover and map blocks in this loop. + if (!Backedges.empty()) { + LoopT *L = AllocateLoop(Header); + discoverAndMapSubloop(L, ArrayRef<BlockT *>(Backedges), this, DomTree); + } + } + // Perform a single forward CFG traversal to populate block and subloop + // vectors for all loops. + PopulateLoopsDFS<BlockT, LoopT> DFS(this); + DFS.traverse(DomRoot->getBlock()); +} + +template <class BlockT, class LoopT> +SmallVector<LoopT *, 4> LoopInfoBase<BlockT, LoopT>::getLoopsInPreorder() { + SmallVector<LoopT *, 4> PreOrderLoops, PreOrderWorklist; + // The outer-most loop actually goes into the result in the same relative + // order as we walk it. But LoopInfo stores the top level loops in reverse + // program order so for here we reverse it to get forward program order. + // FIXME: If we change the order of LoopInfo we will want to remove the + // reverse here. + for (LoopT *RootL : reverse(*this)) { + auto PreOrderLoopsInRootL = RootL->getLoopsInPreorder(); + PreOrderLoops.append(PreOrderLoopsInRootL.begin(), + PreOrderLoopsInRootL.end()); + } + + return PreOrderLoops; +} + +template <class BlockT, class LoopT> +SmallVector<LoopT *, 4> +LoopInfoBase<BlockT, LoopT>::getLoopsInReverseSiblingPreorder() { + SmallVector<LoopT *, 4> PreOrderLoops, PreOrderWorklist; + // The outer-most loop actually goes into the result in the same relative + // order as we walk it. LoopInfo stores the top level loops in reverse + // program order so we walk in order here. + // FIXME: If we change the order of LoopInfo we will want to add a reverse + // here. + for (LoopT *RootL : *this) { + assert(PreOrderWorklist.empty() && + "Must start with an empty preorder walk worklist."); + PreOrderWorklist.push_back(RootL); + do { + LoopT *L = PreOrderWorklist.pop_back_val(); + // Sub-loops are stored in forward program order, but will process the + // worklist backwards so we can just append them in order. + PreOrderWorklist.append(L->begin(), L->end()); + PreOrderLoops.push_back(L); + } while (!PreOrderWorklist.empty()); + } + + return PreOrderLoops; +} + +// Debugging +template <class BlockT, class LoopT> +void LoopInfoBase<BlockT, LoopT>::print(raw_ostream &OS) const { + for (unsigned i = 0; i < TopLevelLoops.size(); ++i) + TopLevelLoops[i]->print(OS); +#if 0 + for (DenseMap<BasicBlock*, LoopT*>::const_iterator I = BBMap.begin(), + E = BBMap.end(); I != E; ++I) + OS << "BB '" << I->first->getName() << "' level = " + << I->second->getLoopDepth() << "\n"; +#endif +} + +template <typename T> +bool compareVectors(std::vector<T> &BB1, std::vector<T> &BB2) { + llvm::sort(BB1); + llvm::sort(BB2); + return BB1 == BB2; +} + +template <class BlockT, class LoopT> +void addInnerLoopsToHeadersMap(DenseMap<BlockT *, const LoopT *> &LoopHeaders, + const LoopInfoBase<BlockT, LoopT> &LI, + const LoopT &L) { + LoopHeaders[L.getHeader()] = &L; + for (LoopT *SL : L) + addInnerLoopsToHeadersMap(LoopHeaders, LI, *SL); +} + +#ifndef NDEBUG +template <class BlockT, class LoopT> +static void compareLoops(const LoopT *L, const LoopT *OtherL, + DenseMap<BlockT *, const LoopT *> &OtherLoopHeaders) { + BlockT *H = L->getHeader(); + BlockT *OtherH = OtherL->getHeader(); + assert(H == OtherH && + "Mismatched headers even though found in the same map entry!"); + + assert(L->getLoopDepth() == OtherL->getLoopDepth() && + "Mismatched loop depth!"); + const LoopT *ParentL = L, *OtherParentL = OtherL; + do { + assert(ParentL->getHeader() == OtherParentL->getHeader() && + "Mismatched parent loop headers!"); + ParentL = ParentL->getParentLoop(); + OtherParentL = OtherParentL->getParentLoop(); + } while (ParentL); + + for (const LoopT *SubL : *L) { + BlockT *SubH = SubL->getHeader(); + const LoopT *OtherSubL = OtherLoopHeaders.lookup(SubH); + assert(OtherSubL && "Inner loop is missing in computed loop info!"); + OtherLoopHeaders.erase(SubH); + compareLoops(SubL, OtherSubL, OtherLoopHeaders); + } + + std::vector<BlockT *> BBs = L->getBlocks(); + std::vector<BlockT *> OtherBBs = OtherL->getBlocks(); + assert(compareVectors(BBs, OtherBBs) && + "Mismatched basic blocks in the loops!"); + + const SmallPtrSetImpl<const BlockT *> &BlocksSet = L->getBlocksSet(); + const SmallPtrSetImpl<const BlockT *> &OtherBlocksSet = L->getBlocksSet(); + assert(BlocksSet.size() == OtherBlocksSet.size() && + std::all_of(BlocksSet.begin(), BlocksSet.end(), + [&OtherBlocksSet](const BlockT *BB) { + return OtherBlocksSet.count(BB); + }) && + "Mismatched basic blocks in BlocksSets!"); +} +#endif + +template <class BlockT, class LoopT> +void LoopInfoBase<BlockT, LoopT>::verify( + const DomTreeBase<BlockT> &DomTree) const { + DenseSet<const LoopT *> Loops; + for (iterator I = begin(), E = end(); I != E; ++I) { + assert(!(*I)->getParentLoop() && "Top-level loop has a parent!"); + (*I)->verifyLoopNest(&Loops); + } + +// Verify that blocks are mapped to valid loops. +#ifndef NDEBUG + for (auto &Entry : BBMap) { + const BlockT *BB = Entry.first; + LoopT *L = Entry.second; + assert(Loops.count(L) && "orphaned loop"); + assert(L->contains(BB) && "orphaned block"); + for (LoopT *ChildLoop : *L) + assert(!ChildLoop->contains(BB) && + "BBMap should point to the innermost loop containing BB"); + } + + // Recompute LoopInfo to verify loops structure. + LoopInfoBase<BlockT, LoopT> OtherLI; + OtherLI.analyze(DomTree); + + // Build a map we can use to move from our LI to the computed one. This + // allows us to ignore the particular order in any layer of the loop forest + // while still comparing the structure. + DenseMap<BlockT *, const LoopT *> OtherLoopHeaders; + for (LoopT *L : OtherLI) + addInnerLoopsToHeadersMap(OtherLoopHeaders, OtherLI, *L); + + // Walk the top level loops and ensure there is a corresponding top-level + // loop in the computed version and then recursively compare those loop + // nests. + for (LoopT *L : *this) { + BlockT *Header = L->getHeader(); + const LoopT *OtherL = OtherLoopHeaders.lookup(Header); + assert(OtherL && "Top level loop is missing in computed loop info!"); + // Now that we've matched this loop, erase its header from the map. + OtherLoopHeaders.erase(Header); + // And recursively compare these loops. + compareLoops(L, OtherL, OtherLoopHeaders); + } + + // Any remaining entries in the map are loops which were found when computing + // a fresh LoopInfo but not present in the current one. + if (!OtherLoopHeaders.empty()) { + for (const auto &HeaderAndLoop : OtherLoopHeaders) + dbgs() << "Found new loop: " << *HeaderAndLoop.second << "\n"; + llvm_unreachable("Found new loops when recomputing LoopInfo!"); + } +#endif +} + +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/LoopIterator.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/LoopIterator.h new file mode 100644 index 0000000..fa4da42 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/LoopIterator.h
@@ -0,0 +1,259 @@ +//===--------- LoopIterator.h - Iterate over loop blocks --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// This file defines iterators to visit the basic blocks within a loop. +// +// These iterators currently visit blocks within subloops as well. +// Unfortunately we have no efficient way of summarizing loop exits which would +// allow skipping subloops during traversal. +// +// If you want to visit all blocks in a loop and don't need an ordered traveral, +// use Loop::block_begin() instead. +// +// This is intentionally designed to work with ill-formed loops in which the +// backedge has been deleted. The only prerequisite is that all blocks +// contained within the loop according to the most recent LoopInfo analysis are +// reachable from the loop header. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LOOPITERATOR_H +#define LLVM_ANALYSIS_LOOPITERATOR_H + +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/Analysis/LoopInfo.h" + +namespace llvm { + +class LoopBlocksTraversal; + +// A traits type that is intended to be used in graph algorithms. The graph +// traits starts at the loop header, and traverses the BasicBlocks that are in +// the loop body, but not the loop header. Since the loop header is skipped, +// the back edges are excluded. +// +// TODO: Explore the possibility to implement LoopBlocksTraversal in terms of +// LoopBodyTraits, so that insertEdge doesn't have to be specialized. +struct LoopBodyTraits { + using NodeRef = std::pair<const Loop *, BasicBlock *>; + + // This wraps a const Loop * into the iterator, so we know which edges to + // filter out. + class WrappedSuccIterator + : public iterator_adaptor_base< + WrappedSuccIterator, succ_iterator, + typename std::iterator_traits<succ_iterator>::iterator_category, + NodeRef, std::ptrdiff_t, NodeRef *, NodeRef> { + using BaseT = iterator_adaptor_base< + WrappedSuccIterator, succ_iterator, + typename std::iterator_traits<succ_iterator>::iterator_category, + NodeRef, std::ptrdiff_t, NodeRef *, NodeRef>; + + const Loop *L; + + public: + WrappedSuccIterator(succ_iterator Begin, const Loop *L) + : BaseT(Begin), L(L) {} + + NodeRef operator*() const { return {L, *I}; } + }; + + struct LoopBodyFilter { + bool operator()(NodeRef N) const { + const Loop *L = N.first; + return N.second != L->getHeader() && L->contains(N.second); + } + }; + + using ChildIteratorType = + filter_iterator<WrappedSuccIterator, LoopBodyFilter>; + + static NodeRef getEntryNode(const Loop &G) { return {&G, G.getHeader()}; } + + static ChildIteratorType child_begin(NodeRef Node) { + return make_filter_range(make_range<WrappedSuccIterator>( + {succ_begin(Node.second), Node.first}, + {succ_end(Node.second), Node.first}), + LoopBodyFilter{}) + .begin(); + } + + static ChildIteratorType child_end(NodeRef Node) { + return make_filter_range(make_range<WrappedSuccIterator>( + {succ_begin(Node.second), Node.first}, + {succ_end(Node.second), Node.first}), + LoopBodyFilter{}) + .end(); + } +}; + +/// Store the result of a depth first search within basic blocks contained by a +/// single loop. +/// +/// TODO: This could be generalized for any CFG region, or the entire CFG. +class LoopBlocksDFS { +public: + /// Postorder list iterators. + typedef std::vector<BasicBlock*>::const_iterator POIterator; + typedef std::vector<BasicBlock*>::const_reverse_iterator RPOIterator; + + friend class LoopBlocksTraversal; + +private: + Loop *L; + + /// Map each block to its postorder number. A block is only mapped after it is + /// preorder visited by DFS. It's postorder number is initially zero and set + /// to nonzero after it is finished by postorder traversal. + DenseMap<BasicBlock*, unsigned> PostNumbers; + std::vector<BasicBlock*> PostBlocks; + +public: + LoopBlocksDFS(Loop *Container) : + L(Container), PostNumbers(NextPowerOf2(Container->getNumBlocks())) { + PostBlocks.reserve(Container->getNumBlocks()); + } + + Loop *getLoop() const { return L; } + + /// Traverse the loop blocks and store the DFS result. + void perform(LoopInfo *LI); + + /// Return true if postorder numbers are assigned to all loop blocks. + bool isComplete() const { return PostBlocks.size() == L->getNumBlocks(); } + + /// Iterate over the cached postorder blocks. + POIterator beginPostorder() const { + assert(isComplete() && "bad loop DFS"); + return PostBlocks.begin(); + } + POIterator endPostorder() const { return PostBlocks.end(); } + + /// Reverse iterate over the cached postorder blocks. + RPOIterator beginRPO() const { + assert(isComplete() && "bad loop DFS"); + return PostBlocks.rbegin(); + } + RPOIterator endRPO() const { return PostBlocks.rend(); } + + /// Return true if this block has been preorder visited. + bool hasPreorder(BasicBlock *BB) const { return PostNumbers.count(BB); } + + /// Return true if this block has a postorder number. + bool hasPostorder(BasicBlock *BB) const { + DenseMap<BasicBlock*, unsigned>::const_iterator I = PostNumbers.find(BB); + return I != PostNumbers.end() && I->second; + } + + /// Get a block's postorder number. + unsigned getPostorder(BasicBlock *BB) const { + DenseMap<BasicBlock*, unsigned>::const_iterator I = PostNumbers.find(BB); + assert(I != PostNumbers.end() && "block not visited by DFS"); + assert(I->second && "block not finished by DFS"); + return I->second; + } + + /// Get a block's reverse postorder number. + unsigned getRPO(BasicBlock *BB) const { + return 1 + PostBlocks.size() - getPostorder(BB); + } + + void clear() { + PostNumbers.clear(); + PostBlocks.clear(); + } +}; + +/// Wrapper class to LoopBlocksDFS that provides a standard begin()/end() +/// interface for the DFS reverse post-order traversal of blocks in a loop body. +class LoopBlocksRPO { +private: + LoopBlocksDFS DFS; + +public: + LoopBlocksRPO(Loop *Container) : DFS(Container) {} + + /// Traverse the loop blocks and store the DFS result. + void perform(LoopInfo *LI) { + DFS.perform(LI); + } + + /// Reverse iterate over the cached postorder blocks. + LoopBlocksDFS::RPOIterator begin() const { return DFS.beginRPO(); } + LoopBlocksDFS::RPOIterator end() const { return DFS.endRPO(); } +}; + +/// Specialize po_iterator_storage to record postorder numbers. +template<> class po_iterator_storage<LoopBlocksTraversal, true> { + LoopBlocksTraversal &LBT; +public: + po_iterator_storage(LoopBlocksTraversal &lbs) : LBT(lbs) {} + // These functions are defined below. + bool insertEdge(Optional<BasicBlock *> From, BasicBlock *To); + void finishPostorder(BasicBlock *BB); +}; + +/// Traverse the blocks in a loop using a depth-first search. +class LoopBlocksTraversal { +public: + /// Graph traversal iterator. + typedef po_iterator<BasicBlock*, LoopBlocksTraversal, true> POTIterator; + +private: + LoopBlocksDFS &DFS; + LoopInfo *LI; + +public: + LoopBlocksTraversal(LoopBlocksDFS &Storage, LoopInfo *LInfo) : + DFS(Storage), LI(LInfo) {} + + /// Postorder traversal over the graph. This only needs to be done once. + /// po_iterator "automatically" calls back to visitPreorder and + /// finishPostorder to record the DFS result. + POTIterator begin() { + assert(DFS.PostBlocks.empty() && "Need clear DFS result before traversing"); + assert(DFS.L->getNumBlocks() && "po_iterator cannot handle an empty graph"); + return po_ext_begin(DFS.L->getHeader(), *this); + } + POTIterator end() { + // po_ext_end interface requires a basic block, but ignores its value. + return po_ext_end(DFS.L->getHeader(), *this); + } + + /// Called by po_iterator upon reaching a block via a CFG edge. If this block + /// is contained in the loop and has not been visited, then mark it preorder + /// visited and return true. + /// + /// TODO: If anyone is interested, we could record preorder numbers here. + bool visitPreorder(BasicBlock *BB) { + if (!DFS.L->contains(LI->getLoopFor(BB))) + return false; + + return DFS.PostNumbers.insert(std::make_pair(BB, 0)).second; + } + + /// Called by po_iterator each time it advances, indicating a block's + /// postorder. + void finishPostorder(BasicBlock *BB) { + assert(DFS.PostNumbers.count(BB) && "Loop DFS skipped preorder"); + DFS.PostBlocks.push_back(BB); + DFS.PostNumbers[BB] = DFS.PostBlocks.size(); + } +}; + +inline bool po_iterator_storage<LoopBlocksTraversal, true>::insertEdge( + Optional<BasicBlock *> From, BasicBlock *To) { + return LBT.visitPreorder(To); +} + +inline void po_iterator_storage<LoopBlocksTraversal, true>:: +finishPostorder(BasicBlock *BB) { + LBT.finishPostorder(BB); +} + +} // End namespace llvm + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/LoopPass.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/LoopPass.h new file mode 100644 index 0000000..04fed15 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/LoopPass.h
@@ -0,0 +1,176 @@ +//===- LoopPass.h - LoopPass class ----------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines LoopPass class. All loop optimization +// and transformation passes are derived from LoopPass. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LOOPPASS_H +#define LLVM_ANALYSIS_LOOPPASS_H + +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/IR/LegacyPassManagers.h" +#include "llvm/Pass.h" +#include <deque> + +namespace llvm { + +class LPPassManager; +class Function; +class PMStack; + +class LoopPass : public Pass { +public: + explicit LoopPass(char &pid) : Pass(PT_Loop, pid) {} + + /// getPrinterPass - Get a pass to print the function corresponding + /// to a Loop. + Pass *createPrinterPass(raw_ostream &O, + const std::string &Banner) const override; + + // runOnLoop - This method should be implemented by the subclass to perform + // whatever action is necessary for the specified Loop. + virtual bool runOnLoop(Loop *L, LPPassManager &LPM) = 0; + + using llvm::Pass::doInitialization; + using llvm::Pass::doFinalization; + + // Initialization and finalization hooks. + virtual bool doInitialization(Loop *L, LPPassManager &LPM) { + return false; + } + + // Finalization hook does not supply Loop because at this time + // loop nest is completely different. + virtual bool doFinalization() { return false; } + + // Check if this pass is suitable for the current LPPassManager, if + // available. This pass P is not suitable for a LPPassManager if P + // is not preserving higher level analysis info used by other + // LPPassManager passes. In such case, pop LPPassManager from the + // stack. This will force assignPassManager() to create new + // LPPassManger as expected. + void preparePassManager(PMStack &PMS) override; + + /// Assign pass manager to manage this pass + void assignPassManager(PMStack &PMS, PassManagerType PMT) override; + + /// Return what kind of Pass Manager can manage this pass. + PassManagerType getPotentialPassManagerType() const override { + return PMT_LoopPassManager; + } + + //===--------------------------------------------------------------------===// + /// SimpleAnalysis - Provides simple interface to update analysis info + /// maintained by various passes. Note, if required this interface can + /// be extracted into a separate abstract class but it would require + /// additional use of multiple inheritance in Pass class hierarchy, something + /// we are trying to avoid. + + /// Each loop pass can override these simple analysis hooks to update + /// desired analysis information. + /// cloneBasicBlockAnalysis - Clone analysis info associated with basic block. + virtual void cloneBasicBlockAnalysis(BasicBlock *F, BasicBlock *T, Loop *L) {} + + /// deleteAnalysisValue - Delete analysis info associated with value V. + virtual void deleteAnalysisValue(Value *V, Loop *L) {} + + /// Delete analysis info associated with Loop L. + /// Called to notify a Pass that a loop has been deleted and any + /// associated analysis values can be deleted. + virtual void deleteAnalysisLoop(Loop *L) {} + +protected: + /// 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 { +public: + static char ID; + explicit LPPassManager(); + + /// run - Execute all of the passes scheduled for execution. Keep track of + /// whether any of the passes modifies the module, and if so, return true. + bool runOnFunction(Function &F) override; + + /// Pass Manager itself does not invalidate any analysis info. + // LPPassManager needs LoopInfo. + void getAnalysisUsage(AnalysisUsage &Info) const override; + + StringRef getPassName() const override { return "Loop Pass Manager"; } + + PMDataManager *getAsPMDataManager() override { return this; } + Pass *getAsPass() override { return this; } + + /// Print passes managed by this manager + void dumpPassStructure(unsigned Offset) override; + + LoopPass *getContainedPass(unsigned N) { + assert(N < PassVector.size() && "Pass number out of range!"); + LoopPass *LP = static_cast<LoopPass *>(PassVector[N]); + return LP; + } + + PassManagerType getPassManagerType() const override { + return PMT_LoopPassManager; + } + +public: + // Add a new loop into the loop queue. + void addLoop(Loop &L); + + // Mark \p L as deleted. + void markLoopAsDeleted(Loop &L); + + //===--------------------------------------------------------------------===// + /// SimpleAnalysis - Provides simple interface to update analysis info + /// maintained by various passes. Note, if required this interface can + /// be extracted into a separate abstract class but it would require + /// additional use of multiple inheritance in Pass class hierarchy, something + /// we are trying to avoid. + + /// cloneBasicBlockSimpleAnalysis - Invoke cloneBasicBlockAnalysis hook for + /// all passes that implement simple analysis interface. + void cloneBasicBlockSimpleAnalysis(BasicBlock *From, BasicBlock *To, Loop *L); + + /// deleteSimpleAnalysisValue - Invoke deleteAnalysisValue hook for all passes + /// that implement simple analysis interface. + void deleteSimpleAnalysisValue(Value *V, Loop *L); + + /// Invoke deleteAnalysisLoop hook for all passes that implement simple + /// analysis interface. + void deleteSimpleAnalysisLoop(Loop *L); + +private: + std::deque<Loop *> LQ; + LoopInfo *LI; + Loop *CurrentLoop; + bool CurrentLoopDeleted; +}; + +// This pass is required by the LCSSA transformation. It is used inside +// LPPassManager to check if current pass preserves LCSSA form, and if it does +// pass manager calls lcssa verification for the current loop. +struct LCSSAVerificationPass : public FunctionPass { + static char ID; + LCSSAVerificationPass(); + + bool runOnFunction(Function &F) override { return false; } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + } +}; + +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/LoopUnrollAnalyzer.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/LoopUnrollAnalyzer.h new file mode 100644 index 0000000..5f332e3 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/LoopUnrollAnalyzer.h
@@ -0,0 +1,94 @@ +//===- llvm/Analysis/LoopUnrollAnalyzer.h - Loop Unroll Analyzer-*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// 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: + /// 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; + + /// SCEV expression corresponding to number of currently simulated + /// iteration. + const SCEV *IterationNumber; + + /// 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
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/MemoryBuiltins.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/MemoryBuiltins.h new file mode 100644 index 0000000..a89d76b --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/MemoryBuiltins.h
@@ -0,0 +1,345 @@ +//==- llvm/Analysis/MemoryBuiltins.h - Calls to memory builtins --*- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This family of functions identifies calls to builtin functions that allocate +// or free memory. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_MEMORYBUILTINS_H +#define LLVM_ANALYSIS_MEMORYBUILTINS_H + +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Analysis/TargetFolder.h" +#include "llvm/Analysis/TargetLibraryInfo.h" +#include "llvm/IR/CallSite.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/InstVisitor.h" +#include "llvm/IR/ValueHandle.h" +#include <cstdint> +#include <utility> + +namespace llvm { + +class AllocaInst; +class Argument; +class CallInst; +class ConstantInt; +class ConstantPointerNull; +class DataLayout; +class ExtractElementInst; +class ExtractValueInst; +class GEPOperator; +class GlobalAlias; +class GlobalVariable; +class Instruction; +class IntegerType; +class IntrinsicInst; +class IntToPtrInst; +class LLVMContext; +class LoadInst; +class PHINode; +class PointerType; +class SelectInst; +class TargetLibraryInfo; +class Type; +class UndefValue; +class Value; + +/// Tests if a value is a call or invoke to a library function that +/// allocates or reallocates memory (either malloc, calloc, realloc, or strdup +/// like). +bool isAllocationFn(const Value *V, const TargetLibraryInfo *TLI, + bool LookThroughBitCast = false); +bool isAllocationFn(const Value *V, + function_ref<const TargetLibraryInfo &(Function &)> GetTLI, + bool LookThroughBitCast = false); + +/// Tests if a value is a call or invoke to a function that returns a +/// NoAlias pointer (including malloc/calloc/realloc/strdup-like functions). +bool isNoAliasFn(const Value *V, const TargetLibraryInfo *TLI, + bool LookThroughBitCast = false); + +/// Tests if a value is a call or invoke to a library function that +/// allocates uninitialized memory (such as malloc). +bool isMallocLikeFn(const Value *V, const TargetLibraryInfo *TLI, + bool LookThroughBitCast = false); +bool isMallocLikeFn(const Value *V, + function_ref<const TargetLibraryInfo &(Function &)> GetTLI, + bool LookThroughBitCast = false); + +/// Tests if a value is a call or invoke to a library function that +/// allocates zero-filled memory (such as calloc). +bool isCallocLikeFn(const Value *V, const TargetLibraryInfo *TLI, + bool LookThroughBitCast = false); + +/// Tests if a value is a call or invoke to a library function that +/// allocates memory similar to malloc or calloc. +bool isMallocOrCallocLikeFn(const Value *V, const TargetLibraryInfo *TLI, + bool LookThroughBitCast = false); + +/// Tests if a value is a call or invoke to a library function that +/// allocates memory (either malloc, calloc, or strdup like). +bool isAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI, + bool LookThroughBitCast = false); + +/// Tests if a value is a call or invoke to a library function that +/// reallocates memory (e.g., realloc). +bool isReallocLikeFn(const Value *V, const TargetLibraryInfo *TLI, + bool LookThroughBitCast = false); + +/// Tests if a function is a call or invoke to a library function that +/// reallocates memory (e.g., realloc). +bool isReallocLikeFn(const Function *F, const TargetLibraryInfo *TLI); + +/// Tests if a value is a call or invoke to a library function that +/// allocates memory and throws if an allocation failed (e.g., new). +bool isOpNewLikeFn(const Value *V, const TargetLibraryInfo *TLI, + bool LookThroughBitCast = false); + +/// Tests if a value is a call or invoke to a library function that +/// allocates memory (strdup, strndup). +bool isStrdupLikeFn(const Value *V, const TargetLibraryInfo *TLI, + bool LookThroughBitCast = false); + +//===----------------------------------------------------------------------===// +// malloc Call Utility Functions. +// + +/// extractMallocCall - Returns the corresponding CallInst if the instruction +/// is a malloc call. Since CallInst::CreateMalloc() only creates calls, we +/// ignore InvokeInst here. +const CallInst * +extractMallocCall(const Value *I, + function_ref<const TargetLibraryInfo &(Function &)> GetTLI); +inline CallInst * +extractMallocCall(Value *I, + function_ref<const TargetLibraryInfo &(Function &)> GetTLI) { + return const_cast<CallInst *>(extractMallocCall((const Value *)I, GetTLI)); +} + +/// getMallocType - Returns the PointerType resulting from the malloc call. +/// The PointerType depends on the number of bitcast uses of the malloc call: +/// 0: PointerType is the malloc calls' return type. +/// 1: PointerType is the bitcast's result type. +/// >1: Unique PointerType cannot be determined, return NULL. +PointerType *getMallocType(const CallInst *CI, const TargetLibraryInfo *TLI); + +/// getMallocAllocatedType - Returns the Type allocated by malloc call. +/// The Type depends on the number of bitcast uses of the malloc call: +/// 0: PointerType is the malloc calls' return type. +/// 1: PointerType is the bitcast's result type. +/// >1: Unique PointerType cannot be determined, return NULL. +Type *getMallocAllocatedType(const CallInst *CI, const TargetLibraryInfo *TLI); + +/// getMallocArraySize - Returns the array size of a malloc call. If the +/// argument passed to malloc is a multiple of the size of the malloced type, +/// then return that multiple. For non-array mallocs, the multiple is +/// constant 1. Otherwise, return NULL for mallocs whose array size cannot be +/// determined. +Value *getMallocArraySize(CallInst *CI, const DataLayout &DL, + const TargetLibraryInfo *TLI, + bool LookThroughSExt = false); + +//===----------------------------------------------------------------------===// +// calloc Call Utility Functions. +// + +/// extractCallocCall - Returns the corresponding CallInst if the instruction +/// is a calloc call. +const CallInst *extractCallocCall(const Value *I, const TargetLibraryInfo *TLI); +inline CallInst *extractCallocCall(Value *I, const TargetLibraryInfo *TLI) { + return const_cast<CallInst*>(extractCallocCall((const Value*)I, TLI)); +} + + +//===----------------------------------------------------------------------===// +// free Call Utility Functions. +// + +/// isLibFreeFunction - Returns true if the function is a builtin free() +bool isLibFreeFunction(const Function *F, const LibFunc TLIFn); + +/// isFreeCall - Returns non-null if the value is a call to the builtin free() +const CallInst *isFreeCall(const Value *I, const TargetLibraryInfo *TLI); + +inline CallInst *isFreeCall(Value *I, const TargetLibraryInfo *TLI) { + return const_cast<CallInst*>(isFreeCall((const Value*)I, TLI)); +} + +//===----------------------------------------------------------------------===// +// Utility functions to compute size of objects. +// + +/// Various options to control the behavior of getObjectSize. +struct ObjectSizeOpts { + /// Controls how we handle conditional statements with unknown conditions. + enum class Mode : uint8_t { + /// Fail to evaluate an unknown condition. + Exact, + /// Evaluate all branches of an unknown condition. If all evaluations + /// succeed, pick the minimum size. + Min, + /// Same as Min, except we pick the maximum size of all of the branches. + Max + }; + + /// How we want to evaluate this object's size. + Mode EvalMode = Mode::Exact; + /// Whether to round the result up to the alignment of allocas, byval + /// arguments, and global variables. + bool RoundToAlign = false; + /// If this is true, null pointers in address space 0 will be treated as + /// though they can't be evaluated. Otherwise, null is always considered to + /// point to a 0 byte region of memory. + bool NullIsUnknownSize = false; +}; + +/// Compute the size of the object pointed by Ptr. Returns true and the +/// object size in Size if successful, and false otherwise. In this context, by +/// object we mean the region of memory starting at Ptr to the end of the +/// underlying object pointed to by Ptr. +bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL, + const TargetLibraryInfo *TLI, ObjectSizeOpts Opts = {}); + +/// Try to turn a call to \@llvm.objectsize into an integer value of the given +/// Type. Returns null on failure. If MustSucceed is true, this function will +/// not return null, and may return conservative values governed by the second +/// argument of the call to objectsize. +Value *lowerObjectSizeCall(IntrinsicInst *ObjectSize, const DataLayout &DL, + const TargetLibraryInfo *TLI, bool MustSucceed); + + + +using SizeOffsetType = std::pair<APInt, APInt>; + +/// Evaluate the size and offset of an object pointed to by a Value* +/// statically. Fails if size or offset are not known at compile time. +class ObjectSizeOffsetVisitor + : public InstVisitor<ObjectSizeOffsetVisitor, SizeOffsetType> { + const DataLayout &DL; + const TargetLibraryInfo *TLI; + ObjectSizeOpts Options; + unsigned IntTyBits; + APInt Zero; + SmallPtrSet<Instruction *, 8> SeenInsts; + + APInt align(APInt Size, uint64_t Align); + + SizeOffsetType unknown() { + return std::make_pair(APInt(), APInt()); + } + +public: + ObjectSizeOffsetVisitor(const DataLayout &DL, const TargetLibraryInfo *TLI, + LLVMContext &Context, ObjectSizeOpts Options = {}); + + SizeOffsetType compute(Value *V); + + static bool knownSize(const SizeOffsetType &SizeOffset) { + return SizeOffset.first.getBitWidth() > 1; + } + + static bool knownOffset(const SizeOffsetType &SizeOffset) { + return SizeOffset.second.getBitWidth() > 1; + } + + static bool bothKnown(const SizeOffsetType &SizeOffset) { + return knownSize(SizeOffset) && knownOffset(SizeOffset); + } + + // These are "private", except they can't actually be made private. Only + // compute() should be used by external users. + SizeOffsetType visitAllocaInst(AllocaInst &I); + SizeOffsetType visitArgument(Argument &A); + SizeOffsetType visitCallSite(CallSite CS); + SizeOffsetType visitConstantPointerNull(ConstantPointerNull&); + SizeOffsetType visitExtractElementInst(ExtractElementInst &I); + SizeOffsetType visitExtractValueInst(ExtractValueInst &I); + SizeOffsetType visitGEPOperator(GEPOperator &GEP); + SizeOffsetType visitGlobalAlias(GlobalAlias &GA); + SizeOffsetType visitGlobalVariable(GlobalVariable &GV); + SizeOffsetType visitIntToPtrInst(IntToPtrInst&); + SizeOffsetType visitLoadInst(LoadInst &I); + SizeOffsetType visitPHINode(PHINode&); + SizeOffsetType visitSelectInst(SelectInst &I); + SizeOffsetType visitUndefValue(UndefValue&); + SizeOffsetType visitInstruction(Instruction &I); + +private: + bool CheckedZextOrTrunc(APInt &I); +}; + +using SizeOffsetEvalType = std::pair<Value *, Value *>; + +/// Evaluate the size and offset of an object pointed to by a Value*. +/// May create code to compute the result at run-time. +class ObjectSizeOffsetEvaluator + : public InstVisitor<ObjectSizeOffsetEvaluator, SizeOffsetEvalType> { + using BuilderTy = IRBuilder<TargetFolder, IRBuilderCallbackInserter>; + using WeakEvalType = std::pair<WeakTrackingVH, WeakTrackingVH>; + using CacheMapTy = DenseMap<const Value *, WeakEvalType>; + using PtrSetTy = SmallPtrSet<const Value *, 8>; + + const DataLayout &DL; + const TargetLibraryInfo *TLI; + LLVMContext &Context; + BuilderTy Builder; + IntegerType *IntTy; + Value *Zero; + CacheMapTy CacheMap; + PtrSetTy SeenVals; + ObjectSizeOpts EvalOpts; + SmallPtrSet<Instruction *, 8> InsertedInstructions; + + SizeOffsetEvalType compute_(Value *V); + +public: + static SizeOffsetEvalType unknown() { + return std::make_pair(nullptr, nullptr); + } + + ObjectSizeOffsetEvaluator(const DataLayout &DL, const TargetLibraryInfo *TLI, + LLVMContext &Context, ObjectSizeOpts EvalOpts = {}); + + SizeOffsetEvalType compute(Value *V); + + bool knownSize(SizeOffsetEvalType SizeOffset) { + return SizeOffset.first; + } + + bool knownOffset(SizeOffsetEvalType SizeOffset) { + return SizeOffset.second; + } + + bool anyKnown(SizeOffsetEvalType SizeOffset) { + return knownSize(SizeOffset) || knownOffset(SizeOffset); + } + + bool bothKnown(SizeOffsetEvalType SizeOffset) { + return knownSize(SizeOffset) && knownOffset(SizeOffset); + } + + // The individual instruction visitors should be treated as private. + SizeOffsetEvalType visitAllocaInst(AllocaInst &I); + SizeOffsetEvalType visitCallSite(CallSite CS); + SizeOffsetEvalType visitExtractElementInst(ExtractElementInst &I); + SizeOffsetEvalType visitExtractValueInst(ExtractValueInst &I); + SizeOffsetEvalType visitGEPOperator(GEPOperator &GEP); + SizeOffsetEvalType visitIntToPtrInst(IntToPtrInst&); + SizeOffsetEvalType visitLoadInst(LoadInst &I); + SizeOffsetEvalType visitPHINode(PHINode &PHI); + SizeOffsetEvalType visitSelectInst(SelectInst &I); + SizeOffsetEvalType visitInstruction(Instruction &I); +}; + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_MEMORYBUILTINS_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h new file mode 100644 index 0000000..e89e569 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h
@@ -0,0 +1,553 @@ +//===- llvm/Analysis/MemoryDependenceAnalysis.h - Memory Deps ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the MemoryDependenceAnalysis analysis pass. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_MEMORYDEPENDENCEANALYSIS_H +#define LLVM_ANALYSIS_MEMORYDEPENDENCEANALYSIS_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/PointerEmbeddedInt.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/PointerSumType.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/MemoryLocation.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Metadata.h" +#include "llvm/IR/PassManager.h" +#include "llvm/IR/PredIteratorCache.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/Pass.h" +#include "llvm/Support/ErrorHandling.h" +#include <cassert> +#include <cstdint> +#include <utility> +#include <vector> + +namespace llvm { + +class AssumptionCache; +class DominatorTree; +class Function; +class Instruction; +class LoadInst; +class PHITransAddr; +class TargetLibraryInfo; +class PhiValues; +class Value; + +/// A memory dependence query can return one of three different answers. +class MemDepResult { + enum DepType { + /// Clients of MemDep never see this. + /// + /// 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, + + /// 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, + + /// 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 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 + }; + + using ValueTy = PointerSumType< + DepType, PointerSumTypeMember<Invalid, Instruction *>, + PointerSumTypeMember<Clobber, Instruction *>, + PointerSumTypeMember<Def, Instruction *>, + PointerSumTypeMember<Other, PointerEmbeddedInt<OtherType, 3>>>; + ValueTy Value; + + explicit MemDepResult(ValueTy V) : Value(V) {} + +public: + MemDepResult() = default; + + /// 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) {} + + // BB is the sort key, it can't be changed. + BasicBlock *getBB() const { return BB; } + + void setResult(const MemDepResult &R) { Result = R; } + + const MemDepResult &getResult() const { return Result; } + + bool operator<(const NonLocalDepEntry &RHS) const { return BB < RHS.BB; } +}; + +/// This is a result from a NonLocal dependence query. +/// +/// For each BasicBlock (the BB entry) it keeps a MemDepResult and the +/// (potentially phi translated) address that was live in the block. +class NonLocalDepResult { + NonLocalDepEntry Entry; + Value *Address; + +public: + NonLocalDepResult(BasicBlock *bb, MemDepResult result, Value *address) + : Entry(bb, result), Address(address) {} + + // BB is the sort key, it can't be changed. + BasicBlock *getBB() const { return Entry.getBB(); } + + void setResult(const MemDepResult &R, Value *Addr) { + Entry.setResult(R); + Address = Addr; + } + + const MemDepResult &getResult() const { return Entry.getResult(); } + + /// 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. + using LocalDepMapType = DenseMap<Instruction *, MemDepResult>; + LocalDepMapType LocalDeps; + +public: + using NonLocalDepInfo = std::vector<NonLocalDepEntry>; + +private: + /// A pair<Value*, bool> where the bool is true if the dependence is a read + /// only dependence, false if read/write. + using ValueIsLoadPair = PointerIntPair<const Value *, 1, bool>; + + /// 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. + using BBSkipFirstBlockPair = PointerIntPair<BasicBlock *, 1, bool>; + + /// 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. + /// + /// May be UnknownSize if the sizes are unknown. + LocationSize Size = LocationSize::unknown(); + /// 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() = default; + }; + + /// Cache storing single nonlocal def for the instruction. + /// It is set when nonlocal def would be found in function returning only + /// local dependencies. + DenseMap<AssertingVH<const Value>, NonLocalDepResult> NonLocalDefsCache; + using ReverseNonLocalDefsCacheTy = + DenseMap<Instruction *, SmallPtrSet<const Value*, 4>>; + ReverseNonLocalDefsCacheTy ReverseNonLocalDefsCache; + + /// 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. + using CachedNonLocalPointerInfo = + DenseMap<ValueIsLoadPair, NonLocalPointerInfo>; + CachedNonLocalPointerInfo NonLocalPointerDeps; + + // A map from instructions to their non-local pointer dependencies. + using ReverseNonLocalPtrDepTy = + DenseMap<Instruction *, SmallPtrSet<ValueIsLoadPair, 4>>; + ReverseNonLocalPtrDepTy ReverseNonLocalPtrDeps; + + /// 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. + using PerInstNLInfo = std::pair<NonLocalDepInfo, bool>; + + // A map from instructions to their non-local dependencies. + using NonLocalDepMapType = DenseMap<Instruction *, PerInstNLInfo>; + + NonLocalDepMapType NonLocalDeps; + + // A reverse mapping from dependencies to the dependees. This is + // used when removing instructions to keep the cache coherent. + using ReverseDepMapType = + DenseMap<Instruction *, SmallPtrSet<Instruction *, 4>>; + ReverseDepMapType ReverseLocalDeps; + + // A reverse mapping from dependencies to the non-local dependees. + ReverseDepMapType ReverseNonLocalDeps; + + /// Current AA implementation, just a cache. + AliasAnalysis &AA; + AssumptionCache &AC; + const TargetLibraryInfo &TLI; + DominatorTree &DT; + PhiValues &PV; + PredIteratorCache PredCache; + + unsigned DefaultBlockScanLimit; + +public: + MemoryDependenceResults(AliasAnalysis &AA, AssumptionCache &AC, + const TargetLibraryInfo &TLI, DominatorTree &DT, + PhiValues &PV, unsigned DefaultBlockScanLimit) + : AA(AA), AC(AC), TLI(TLI), DT(DT), PV(PV), + DefaultBlockScanLimit(DefaultBlockScanLimit) {} + + /// Handle invalidation in the new PM. + bool invalidate(Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &Inv); + + /// Some methods limit the number of instructions they will examine. + /// The return value of this method is the default limit that will be + /// used if no limit is explicitly passed in. + unsigned getDefaultBlockScanLimit() const; + + /// 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, + OrderedBasicBlock *OBB = nullptr); + + /// 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(CallBase *QueryCall); + + /// 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); + + /// Removes an instruction from the dependence analysis, updating the + /// dependence of instructions that previously depended on it. + void removeInstruction(Instruction *InstToRemove); + + /// 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); + + /// Clears the PredIteratorCache info. + /// + /// This needs to be done when the CFG changes, e.g., due to splitting + /// critical edges. + void invalidateCachedPredecessors(); + + /// 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. \p Limit + /// can be used to set the maximum number of instructions that will be + /// examined to find the pointer dependency. On return, it will be set to + /// the number of instructions left to examine. If a null pointer is passed + /// in, the limit will default to the value of -memdep-block-scan-limit. + /// + /// 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, + unsigned *Limit = nullptr, + OrderedBasicBlock *OBB = nullptr); + + MemDepResult + getSimplePointerDependencyFrom(const MemoryLocation &MemLoc, bool isLoad, + BasicBlock::iterator ScanIt, BasicBlock *BB, + Instruction *QueryInst, unsigned *Limit, + OrderedBasicBlock *OBB); + + /// 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 and NonLocal which indicate that non-local Def was + /// found, which can be retrieved by calling getNonLocalPointerDependency + /// with the same queried instruction. + MemDepResult getInvariantGroupPointerDependency(LoadInst *LI, BasicBlock *BB); + + /// 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); + + /// Release memory in caches. + void releaseMemory(); + +private: + MemDepResult getCallDependencyFrom(CallBase *Call, 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); + + 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 AnalysisKey Key; + + unsigned DefaultBlockScanLimit; + +public: + using Result = MemoryDependenceResults; + + MemoryDependenceAnalysis(); + MemoryDependenceAnalysis(unsigned DefaultBlockScanLimit) : DefaultBlockScanLimit(DefaultBlockScanLimit) { } + + MemoryDependenceResults run(Function &F, FunctionAnalysisManager &AM); +}; + +/// A wrapper analysis pass for the legacy pass manager that exposes a \c +/// MemoryDepnedenceResults instance. +class MemoryDependenceWrapperPass : public FunctionPass { + Optional<MemoryDependenceResults> MemDep; + +public: + static char ID; + + MemoryDependenceWrapperPass(); + ~MemoryDependenceWrapperPass() override; + + /// 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 namespace llvm + +#endif // LLVM_ANALYSIS_MEMORYDEPENDENCEANALYSIS_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/MemoryLocation.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/MemoryLocation.h new file mode 100644 index 0000000..7c26353 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/MemoryLocation.h
@@ -0,0 +1,307 @@ +//===- MemoryLocation.h - Memory location descriptions ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// \file +/// This file provides utility analysis objects describing memory locations. +/// These are used both by the Alias Analysis infrastructure and more +/// specialized memory analysis layers. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_MEMORYLOCATION_H +#define LLVM_ANALYSIS_MEMORYLOCATION_H + +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/ADT/Optional.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Metadata.h" + +namespace llvm { + +class LoadInst; +class StoreInst; +class MemTransferInst; +class MemIntrinsic; +class AtomicMemTransferInst; +class AtomicMemIntrinsic; +class AnyMemTransferInst; +class AnyMemIntrinsic; +class TargetLibraryInfo; + +// Represents the size of a MemoryLocation. Logically, it's an +// Optional<uint63_t> that also carries a bit to represent whether the integer +// it contains, N, is 'precise'. Precise, in this context, means that we know +// that the area of storage referenced by the given MemoryLocation must be +// precisely N bytes. An imprecise value is formed as the union of two or more +// precise values, and can conservatively represent all of the values unioned +// into it. Importantly, imprecise values are an *upper-bound* on the size of a +// MemoryLocation. +// +// Concretely, a precise MemoryLocation is (%p, 4) in +// store i32 0, i32* %p +// +// Since we know that %p must be at least 4 bytes large at this point. +// Otherwise, we have UB. An example of an imprecise MemoryLocation is (%p, 4) +// at the memcpy in +// +// %n = select i1 %foo, i64 1, i64 4 +// call void @llvm.memcpy.p0i8.p0i8.i64(i8* %p, i8* %baz, i64 %n, i32 1, +// i1 false) +// +// ...Since we'll copy *up to* 4 bytes into %p, but we can't guarantee that +// we'll ever actually do so. +// +// If asked to represent a pathologically large value, this will degrade to +// None. +class LocationSize { + enum : uint64_t { + Unknown = ~uint64_t(0), + ImpreciseBit = uint64_t(1) << 63, + MapEmpty = Unknown - 1, + MapTombstone = Unknown - 2, + + // The maximum value we can represent without falling back to 'unknown'. + MaxValue = (MapTombstone - 1) & ~ImpreciseBit, + }; + + uint64_t Value; + + // Hack to support implicit construction. This should disappear when the + // public LocationSize ctor goes away. + enum DirectConstruction { Direct }; + + constexpr LocationSize(uint64_t Raw, DirectConstruction): Value(Raw) {} + + static_assert(Unknown & ImpreciseBit, "Unknown is imprecise by definition."); +public: + // FIXME: Migrate all users to construct via either `precise` or `upperBound`, + // to make it more obvious at the callsite the kind of size that they're + // providing. + // + // Since the overwhelming majority of users of this provide precise values, + // this assumes the provided value is precise. + constexpr LocationSize(uint64_t Raw) + : Value(Raw > MaxValue ? Unknown : Raw) {} + + static LocationSize precise(uint64_t Value) { return LocationSize(Value); } + + static LocationSize upperBound(uint64_t Value) { + // You can't go lower than 0, so give a precise result. + if (LLVM_UNLIKELY(Value == 0)) + return precise(0); + if (LLVM_UNLIKELY(Value > MaxValue)) + return unknown(); + return LocationSize(Value | ImpreciseBit, Direct); + } + + constexpr static LocationSize unknown() { + return LocationSize(Unknown, Direct); + } + + // Sentinel values, generally used for maps. + constexpr static LocationSize mapTombstone() { + return LocationSize(MapTombstone, Direct); + } + constexpr static LocationSize mapEmpty() { + return LocationSize(MapEmpty, Direct); + } + + // Returns a LocationSize that can correctly represent either `*this` or + // `Other`. + LocationSize unionWith(LocationSize Other) const { + if (Other == *this) + return *this; + + if (!hasValue() || !Other.hasValue()) + return unknown(); + + return upperBound(std::max(getValue(), Other.getValue())); + } + + bool hasValue() const { return Value != Unknown; } + uint64_t getValue() const { + assert(hasValue() && "Getting value from an unknown LocationSize!"); + return Value & ~ImpreciseBit; + } + + // Returns whether or not this value is precise. Note that if a value is + // precise, it's guaranteed to not be `unknown()`. + bool isPrecise() const { + return (Value & ImpreciseBit) == 0; + } + + // Convenience method to check if this LocationSize's value is 0. + bool isZero() const { return hasValue() && getValue() == 0; } + + bool operator==(const LocationSize &Other) const { + return Value == Other.Value; + } + + bool operator!=(const LocationSize &Other) const { + return !(*this == Other); + } + + // Ordering operators are not provided, since it's unclear if there's only one + // reasonable way to compare: + // - values that don't exist against values that do, and + // - precise values to imprecise values + + void print(raw_ostream &OS) const; + + // Returns an opaque value that represents this LocationSize. Cannot be + // reliably converted back into a LocationSize. + uint64_t toRaw() const { return Value; } +}; + +inline raw_ostream &operator<<(raw_ostream &OS, LocationSize Size) { + Size.print(OS); + return OS; +} + +/// Representation for a specific memory location. +/// +/// This abstraction can be used to represent a specific location in memory. +/// The goal of the location is to represent enough information to describe +/// abstract aliasing, modification, and reference behaviors of whatever +/// value(s) are stored in memory at the particular location. +/// +/// The primary user of this interface is LLVM's Alias Analysis, but other +/// memory analyses such as MemoryDependence can use it as well. +class MemoryLocation { +public: + /// UnknownSize - This is a special value which can be used with the + /// size arguments in alias queries to indicate that the caller does not + /// know the sizes of the potential memory references. + enum : uint64_t { UnknownSize = ~UINT64_C(0) }; + + /// The address of the start of the location. + const Value *Ptr; + + /// The maximum size of the location, in address-units, or + /// UnknownSize if the size is not known. + /// + /// Note that an unknown size does not mean the pointer aliases the entire + /// virtual address space, because there are restrictions on stepping out of + /// one object and into another. See + /// http://llvm.org/docs/LangRef.html#pointeraliasing + LocationSize Size; + + /// The metadata nodes which describes the aliasing of the location (each + /// member is null if that kind of information is unavailable). + AAMDNodes AATags; + + /// Return a location with information about the memory reference by the given + /// instruction. + static MemoryLocation get(const LoadInst *LI); + static MemoryLocation get(const StoreInst *SI); + static MemoryLocation get(const VAArgInst *VI); + static MemoryLocation get(const AtomicCmpXchgInst *CXI); + static MemoryLocation get(const AtomicRMWInst *RMWI); + static MemoryLocation get(const Instruction *Inst) { + return *MemoryLocation::getOrNone(Inst); + } + static Optional<MemoryLocation> getOrNone(const Instruction *Inst) { + switch (Inst->getOpcode()) { + case Instruction::Load: + return get(cast<LoadInst>(Inst)); + case Instruction::Store: + return get(cast<StoreInst>(Inst)); + case Instruction::VAArg: + return get(cast<VAArgInst>(Inst)); + case Instruction::AtomicCmpXchg: + return get(cast<AtomicCmpXchgInst>(Inst)); + case Instruction::AtomicRMW: + return get(cast<AtomicRMWInst>(Inst)); + default: + return None; + } + } + + /// Return a location representing the source of a memory transfer. + static MemoryLocation getForSource(const MemTransferInst *MTI); + static MemoryLocation getForSource(const AtomicMemTransferInst *MTI); + static MemoryLocation getForSource(const AnyMemTransferInst *MTI); + + /// Return a location representing the destination of a memory set or + /// transfer. + static MemoryLocation getForDest(const MemIntrinsic *MI); + static MemoryLocation getForDest(const AtomicMemIntrinsic *MI); + static MemoryLocation getForDest(const AnyMemIntrinsic *MI); + + /// Return a location representing a particular argument of a call. + static MemoryLocation getForArgument(const CallBase *Call, unsigned ArgIdx, + const TargetLibraryInfo *TLI); + static MemoryLocation getForArgument(const CallBase *Call, unsigned ArgIdx, + const TargetLibraryInfo &TLI) { + return getForArgument(Call, ArgIdx, &TLI); + } + + explicit MemoryLocation(const Value *Ptr = nullptr, + LocationSize Size = LocationSize::unknown(), + const AAMDNodes &AATags = AAMDNodes()) + : Ptr(Ptr), Size(Size), AATags(AATags) {} + + MemoryLocation getWithNewPtr(const Value *NewPtr) const { + MemoryLocation Copy(*this); + Copy.Ptr = NewPtr; + return Copy; + } + + MemoryLocation getWithNewSize(LocationSize NewSize) const { + MemoryLocation Copy(*this); + Copy.Size = NewSize; + return Copy; + } + + MemoryLocation getWithoutAATags() const { + MemoryLocation Copy(*this); + Copy.AATags = AAMDNodes(); + return Copy; + } + + bool operator==(const MemoryLocation &Other) const { + return Ptr == Other.Ptr && Size == Other.Size && AATags == Other.AATags; + } +}; + +// Specialize DenseMapInfo. +template <> struct DenseMapInfo<LocationSize> { + static inline LocationSize getEmptyKey() { + return LocationSize::mapEmpty(); + } + static inline LocationSize getTombstoneKey() { + return LocationSize::mapTombstone(); + } + static unsigned getHashValue(const LocationSize &Val) { + return DenseMapInfo<uint64_t>::getHashValue(Val.toRaw()); + } + static bool isEqual(const LocationSize &LHS, const LocationSize &RHS) { + return LHS == RHS; + } +}; + +template <> struct DenseMapInfo<MemoryLocation> { + static inline MemoryLocation getEmptyKey() { + return MemoryLocation(DenseMapInfo<const Value *>::getEmptyKey(), + DenseMapInfo<LocationSize>::getEmptyKey()); + } + static inline MemoryLocation getTombstoneKey() { + return MemoryLocation(DenseMapInfo<const Value *>::getTombstoneKey(), + DenseMapInfo<LocationSize>::getTombstoneKey()); + } + static unsigned getHashValue(const MemoryLocation &Val) { + return DenseMapInfo<const Value *>::getHashValue(Val.Ptr) ^ + DenseMapInfo<LocationSize>::getHashValue(Val.Size) ^ + DenseMapInfo<AAMDNodes>::getHashValue(Val.AATags); + } + static bool isEqual(const MemoryLocation &LHS, const MemoryLocation &RHS) { + return LHS == RHS; + } +}; +} + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/MemorySSA.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/MemorySSA.h new file mode 100644 index 0000000..9b393c9 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/MemorySSA.h
@@ -0,0 +1,1314 @@ +//===- MemorySSA.h - Build Memory SSA ---------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +/// \file +/// This file exposes an interface to building/using memory SSA to +/// walk memory instructions using a use/def graph. +/// +/// Memory SSA class builds an SSA form that links together memory access +/// instructions such as loads, stores, atomics, and calls. Additionally, it +/// does a trivial form of "heap versioning" Every time the memory state changes +/// in the program, we generate a new heap version. It generates +/// MemoryDef/Uses/Phis that are overlayed on top of the existing instructions. +/// +/// As a trivial example, +/// define i32 @main() #0 { +/// entry: +/// %call = call noalias i8* @_Znwm(i64 4) #2 +/// %0 = bitcast i8* %call to i32* +/// %call1 = call noalias i8* @_Znwm(i64 4) #2 +/// %1 = bitcast i8* %call1 to i32* +/// store i32 5, i32* %0, align 4 +/// store i32 7, i32* %1, align 4 +/// %2 = load i32* %0, align 4 +/// %3 = load i32* %1, align 4 +/// %add = add nsw i32 %2, %3 +/// ret i32 %add +/// } +/// +/// Will become +/// define i32 @main() #0 { +/// entry: +/// ; 1 = MemoryDef(0) +/// %call = call noalias i8* @_Znwm(i64 4) #3 +/// %2 = bitcast i8* %call to i32* +/// ; 2 = MemoryDef(1) +/// %call1 = call noalias i8* @_Znwm(i64 4) #3 +/// %4 = bitcast i8* %call1 to i32* +/// ; 3 = MemoryDef(2) +/// store i32 5, i32* %2, align 4 +/// ; 4 = MemoryDef(3) +/// store i32 7, i32* %4, align 4 +/// ; MemoryUse(3) +/// %7 = load i32* %2, align 4 +/// ; MemoryUse(4) +/// %8 = load i32* %4, align 4 +/// %add = add nsw i32 %7, %8 +/// ret i32 %add +/// } +/// +/// Given this form, all the stores that could ever effect the load at %8 can be +/// gotten by using the MemoryUse associated with it, and walking from use to +/// def until you hit the top of the function. +/// +/// Each def also has a list of users associated with it, so you can walk from +/// both def to users, and users to defs. Note that we disambiguate MemoryUses, +/// but not the RHS of MemoryDefs. You can see this above at %7, which would +/// otherwise be a MemoryUse(4). Being disambiguated means that for a given +/// store, all the MemoryUses on its use lists are may-aliases of that store +/// (but the MemoryDefs on its use list may not be). +/// +/// MemoryDefs are not disambiguated because it would require multiple reaching +/// definitions, which would require multiple phis, and multiple memoryaccesses +/// per instruction. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_MEMORYSSA_H +#define LLVM_ANALYSIS_MEMORYSSA_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/ilist.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/ADT/iterator.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/ADT/simple_ilist.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/MemoryLocation.h" +#include "llvm/Analysis/PHITransAddr.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/DerivedUser.h" +#include "llvm/IR/Dominators.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/Use.h" +#include "llvm/IR/User.h" +#include "llvm/IR/Value.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/Pass.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/CommandLine.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <iterator> +#include <memory> +#include <utility> + +namespace llvm { + +/// Enables memory ssa as a dependency for loop passes. +extern cl::opt<bool> EnableMSSALoopDependency; + +class Function; +class Instruction; +class MemoryAccess; +class MemorySSAWalker; +class LLVMContext; +class raw_ostream; + +namespace MSSAHelpers { + +struct AllAccessTag {}; +struct DefsOnlyTag {}; + +} // end namespace MSSAHelpers + +enum : unsigned { + // Used to signify what the default invalid ID is for MemoryAccess's + // getID() + INVALID_MEMORYACCESS_ID = -1U +}; + +template <class T> class memoryaccess_def_iterator_base; +using memoryaccess_def_iterator = memoryaccess_def_iterator_base<MemoryAccess>; +using const_memoryaccess_def_iterator = + memoryaccess_def_iterator_base<const MemoryAccess>; + +// The base for all memory accesses. All memory accesses in a block are +// linked together using an intrusive list. +class MemoryAccess + : public DerivedUser, + public ilist_node<MemoryAccess, ilist_tag<MSSAHelpers::AllAccessTag>>, + public ilist_node<MemoryAccess, ilist_tag<MSSAHelpers::DefsOnlyTag>> { +public: + using AllAccessType = + ilist_node<MemoryAccess, ilist_tag<MSSAHelpers::AllAccessTag>>; + using DefsOnlyType = + ilist_node<MemoryAccess, ilist_tag<MSSAHelpers::DefsOnlyTag>>; + + MemoryAccess(const MemoryAccess &) = delete; + MemoryAccess &operator=(const MemoryAccess &) = delete; + + void *operator new(size_t) = delete; + + // Methods for support type inquiry through isa, cast, and + // dyn_cast + static bool classof(const Value *V) { + unsigned ID = V->getValueID(); + return ID == MemoryUseVal || ID == MemoryPhiVal || ID == MemoryDefVal; + } + + BasicBlock *getBlock() const { return Block; } + + void print(raw_ostream &OS) const; + void dump() const; + + /// The user iterators for a memory access + using iterator = user_iterator; + using const_iterator = const_user_iterator; + + /// This iterator walks over all of the defs in a given + /// MemoryAccess. For MemoryPhi nodes, this walks arguments. For + /// MemoryUse/MemoryDef, this walks the defining access. + memoryaccess_def_iterator defs_begin(); + const_memoryaccess_def_iterator defs_begin() const; + memoryaccess_def_iterator defs_end(); + const_memoryaccess_def_iterator defs_end() const; + + /// Get the iterators for the all access list and the defs only list + /// We default to the all access list. + AllAccessType::self_iterator getIterator() { + return this->AllAccessType::getIterator(); + } + AllAccessType::const_self_iterator getIterator() const { + return this->AllAccessType::getIterator(); + } + AllAccessType::reverse_self_iterator getReverseIterator() { + return this->AllAccessType::getReverseIterator(); + } + AllAccessType::const_reverse_self_iterator getReverseIterator() const { + return this->AllAccessType::getReverseIterator(); + } + DefsOnlyType::self_iterator getDefsIterator() { + return this->DefsOnlyType::getIterator(); + } + DefsOnlyType::const_self_iterator getDefsIterator() const { + return this->DefsOnlyType::getIterator(); + } + DefsOnlyType::reverse_self_iterator getReverseDefsIterator() { + return this->DefsOnlyType::getReverseIterator(); + } + DefsOnlyType::const_reverse_self_iterator getReverseDefsIterator() const { + return this->DefsOnlyType::getReverseIterator(); + } + +protected: + friend class MemoryDef; + friend class MemoryPhi; + friend class MemorySSA; + friend class MemoryUse; + friend class MemoryUseOrDef; + + /// Used by MemorySSA to change the block of a MemoryAccess when it is + /// moved. + void setBlock(BasicBlock *BB) { Block = BB; } + + /// Used for debugging and tracking things about MemoryAccesses. + /// Guaranteed unique among MemoryAccesses, no guarantees otherwise. + inline unsigned getID() const; + + MemoryAccess(LLVMContext &C, unsigned Vty, DeleteValueTy DeleteValue, + BasicBlock *BB, unsigned NumOperands) + : DerivedUser(Type::getVoidTy(C), Vty, nullptr, NumOperands, DeleteValue), + Block(BB) {} + + // Use deleteValue() to delete a generic MemoryAccess. + ~MemoryAccess() = default; + +private: + BasicBlock *Block; +}; + +template <> +struct ilist_alloc_traits<MemoryAccess> { + static void deleteNode(MemoryAccess *MA) { MA->deleteValue(); } +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const MemoryAccess &MA) { + MA.print(OS); + return OS; +} + +/// Class that has the common methods + fields of memory uses/defs. It's +/// a little awkward to have, but there are many cases where we want either a +/// use or def, and there are many cases where uses are needed (defs aren't +/// acceptable), and vice-versa. +/// +/// This class should never be instantiated directly; make a MemoryUse or +/// MemoryDef instead. +class MemoryUseOrDef : public MemoryAccess { +public: + void *operator new(size_t) = delete; + + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess); + + /// Get the instruction that this MemoryUse represents. + Instruction *getMemoryInst() const { return MemoryInstruction; } + + /// Get the access that produces the memory state used by this Use. + MemoryAccess *getDefiningAccess() const { return getOperand(0); } + + static bool classof(const Value *MA) { + return MA->getValueID() == MemoryUseVal || MA->getValueID() == MemoryDefVal; + } + + // Sadly, these have to be public because they are needed in some of the + // iterators. + inline bool isOptimized() const; + inline MemoryAccess *getOptimized() const; + inline void setOptimized(MemoryAccess *); + + // Retrieve AliasResult type of the optimized access. Ideally this would be + // returned by the caching walker and may go away in the future. + Optional<AliasResult> getOptimizedAccessType() const { + return OptimizedAccessAlias; + } + + /// Reset the ID of what this MemoryUse was optimized to, causing it to + /// be rewalked by the walker if necessary. + /// This really should only be called by tests. + inline void resetOptimized(); + +protected: + friend class MemorySSA; + friend class MemorySSAUpdater; + + MemoryUseOrDef(LLVMContext &C, MemoryAccess *DMA, unsigned Vty, + DeleteValueTy DeleteValue, Instruction *MI, BasicBlock *BB, + unsigned NumOperands) + : MemoryAccess(C, Vty, DeleteValue, BB, NumOperands), + MemoryInstruction(MI), OptimizedAccessAlias(MayAlias) { + setDefiningAccess(DMA); + } + + // Use deleteValue() to delete a generic MemoryUseOrDef. + ~MemoryUseOrDef() = default; + + void setOptimizedAccessType(Optional<AliasResult> AR) { + OptimizedAccessAlias = AR; + } + + void setDefiningAccess(MemoryAccess *DMA, bool Optimized = false, + Optional<AliasResult> AR = MayAlias) { + if (!Optimized) { + setOperand(0, DMA); + return; + } + setOptimized(DMA); + setOptimizedAccessType(AR); + } + +private: + Instruction *MemoryInstruction; + Optional<AliasResult> OptimizedAccessAlias; +}; + +/// Represents read-only accesses to memory +/// +/// In particular, the set of Instructions that will be represented by +/// MemoryUse's is exactly the set of Instructions for which +/// AliasAnalysis::getModRefInfo returns "Ref". +class MemoryUse final : public MemoryUseOrDef { +public: + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess); + + MemoryUse(LLVMContext &C, MemoryAccess *DMA, Instruction *MI, BasicBlock *BB) + : MemoryUseOrDef(C, DMA, MemoryUseVal, deleteMe, MI, BB, + /*NumOperands=*/1) {} + + // allocate space for exactly one operand + void *operator new(size_t s) { return User::operator new(s, 1); } + + static bool classof(const Value *MA) { + return MA->getValueID() == MemoryUseVal; + } + + void print(raw_ostream &OS) const; + + void setOptimized(MemoryAccess *DMA) { + OptimizedID = DMA->getID(); + setOperand(0, DMA); + } + + bool isOptimized() const { + return getDefiningAccess() && OptimizedID == getDefiningAccess()->getID(); + } + + MemoryAccess *getOptimized() const { + return getDefiningAccess(); + } + + void resetOptimized() { + OptimizedID = INVALID_MEMORYACCESS_ID; + } + +protected: + friend class MemorySSA; + +private: + static void deleteMe(DerivedUser *Self); + + unsigned OptimizedID = INVALID_MEMORYACCESS_ID; +}; + +template <> +struct OperandTraits<MemoryUse> : public FixedNumOperandTraits<MemoryUse, 1> {}; +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryUse, MemoryAccess) + +/// Represents a read-write access to memory, whether it is a must-alias, +/// or a may-alias. +/// +/// In particular, the set of Instructions that will be represented by +/// MemoryDef's is exactly the set of Instructions for which +/// AliasAnalysis::getModRefInfo returns "Mod" or "ModRef". +/// Note that, in order to provide def-def chains, all defs also have a use +/// associated with them. This use points to the nearest reaching +/// MemoryDef/MemoryPhi. +class MemoryDef final : public MemoryUseOrDef { +public: + friend class MemorySSA; + + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess); + + MemoryDef(LLVMContext &C, MemoryAccess *DMA, Instruction *MI, BasicBlock *BB, + unsigned Ver) + : MemoryUseOrDef(C, DMA, MemoryDefVal, deleteMe, MI, BB, + /*NumOperands=*/2), + ID(Ver) {} + + // allocate space for exactly two operands + void *operator new(size_t s) { return User::operator new(s, 2); } + + static bool classof(const Value *MA) { + return MA->getValueID() == MemoryDefVal; + } + + void setOptimized(MemoryAccess *MA) { + setOperand(1, MA); + OptimizedID = MA->getID(); + } + + MemoryAccess *getOptimized() const { + return cast_or_null<MemoryAccess>(getOperand(1)); + } + + bool isOptimized() const { + return getOptimized() && OptimizedID == getOptimized()->getID(); + } + + void resetOptimized() { + OptimizedID = INVALID_MEMORYACCESS_ID; + setOperand(1, nullptr); + } + + void print(raw_ostream &OS) const; + + unsigned getID() const { return ID; } + +private: + static void deleteMe(DerivedUser *Self); + + const unsigned ID; + unsigned OptimizedID = INVALID_MEMORYACCESS_ID; +}; + +template <> +struct OperandTraits<MemoryDef> : public FixedNumOperandTraits<MemoryDef, 2> {}; +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryDef, MemoryAccess) + +template <> +struct OperandTraits<MemoryUseOrDef> { + static Use *op_begin(MemoryUseOrDef *MUD) { + if (auto *MU = dyn_cast<MemoryUse>(MUD)) + return OperandTraits<MemoryUse>::op_begin(MU); + return OperandTraits<MemoryDef>::op_begin(cast<MemoryDef>(MUD)); + } + + static Use *op_end(MemoryUseOrDef *MUD) { + if (auto *MU = dyn_cast<MemoryUse>(MUD)) + return OperandTraits<MemoryUse>::op_end(MU); + return OperandTraits<MemoryDef>::op_end(cast<MemoryDef>(MUD)); + } + + static unsigned operands(const MemoryUseOrDef *MUD) { + if (const auto *MU = dyn_cast<MemoryUse>(MUD)) + return OperandTraits<MemoryUse>::operands(MU); + return OperandTraits<MemoryDef>::operands(cast<MemoryDef>(MUD)); + } +}; +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryUseOrDef, MemoryAccess) + +/// Represents phi nodes for memory accesses. +/// +/// These have the same semantic as regular phi nodes, with the exception that +/// only one phi will ever exist in a given basic block. +/// Guaranteeing one phi per block means guaranteeing there is only ever one +/// valid reaching MemoryDef/MemoryPHI along each path to the phi node. +/// This is ensured by not allowing disambiguation of the RHS of a MemoryDef or +/// a MemoryPhi's operands. +/// That is, given +/// if (a) { +/// store %a +/// store %b +/// } +/// it *must* be transformed into +/// if (a) { +/// 1 = MemoryDef(liveOnEntry) +/// store %a +/// 2 = MemoryDef(1) +/// store %b +/// } +/// and *not* +/// if (a) { +/// 1 = MemoryDef(liveOnEntry) +/// store %a +/// 2 = MemoryDef(liveOnEntry) +/// store %b +/// } +/// even if the two stores do not conflict. Otherwise, both 1 and 2 reach the +/// end of the branch, and if there are not two phi nodes, one will be +/// disconnected completely from the SSA graph below that point. +/// Because MemoryUse's do not generate new definitions, they do not have this +/// issue. +class MemoryPhi final : public MemoryAccess { + // allocate space for exactly zero operands + void *operator new(size_t s) { return User::operator new(s); } + +public: + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess); + + MemoryPhi(LLVMContext &C, BasicBlock *BB, unsigned Ver, unsigned NumPreds = 0) + : MemoryAccess(C, MemoryPhiVal, deleteMe, BB, 0), ID(Ver), + ReservedSpace(NumPreds) { + allocHungoffUses(ReservedSpace); + } + + // Block iterator interface. This provides access to the list of incoming + // basic blocks, which parallels the list of incoming values. + using block_iterator = BasicBlock **; + using const_block_iterator = BasicBlock *const *; + + block_iterator block_begin() { + auto *Ref = reinterpret_cast<Use::UserRef *>(op_begin() + ReservedSpace); + return reinterpret_cast<block_iterator>(Ref + 1); + } + + const_block_iterator block_begin() const { + const auto *Ref = + reinterpret_cast<const Use::UserRef *>(op_begin() + ReservedSpace); + return reinterpret_cast<const_block_iterator>(Ref + 1); + } + + block_iterator block_end() { return block_begin() + getNumOperands(); } + + const_block_iterator block_end() const { + return block_begin() + getNumOperands(); + } + + iterator_range<block_iterator> blocks() { + return make_range(block_begin(), block_end()); + } + + iterator_range<const_block_iterator> blocks() const { + return make_range(block_begin(), block_end()); + } + + op_range incoming_values() { return operands(); } + + const_op_range incoming_values() const { return operands(); } + + /// Return the number of incoming edges + unsigned getNumIncomingValues() const { return getNumOperands(); } + + /// Return incoming value number x + MemoryAccess *getIncomingValue(unsigned I) const { return getOperand(I); } + void setIncomingValue(unsigned I, MemoryAccess *V) { + assert(V && "PHI node got a null value!"); + setOperand(I, V); + } + + static unsigned getOperandNumForIncomingValue(unsigned I) { return I; } + static unsigned getIncomingValueNumForOperand(unsigned I) { return I; } + + /// Return incoming basic block number @p i. + BasicBlock *getIncomingBlock(unsigned I) const { return block_begin()[I]; } + + /// Return incoming basic block corresponding + /// to an operand of the PHI. + BasicBlock *getIncomingBlock(const Use &U) const { + assert(this == U.getUser() && "Iterator doesn't point to PHI's Uses?"); + return getIncomingBlock(unsigned(&U - op_begin())); + } + + /// Return incoming basic block corresponding + /// to value use iterator. + BasicBlock *getIncomingBlock(MemoryAccess::const_user_iterator I) const { + return getIncomingBlock(I.getUse()); + } + + void setIncomingBlock(unsigned I, BasicBlock *BB) { + assert(BB && "PHI node got a null basic block!"); + block_begin()[I] = BB; + } + + /// Add an incoming value to the end of the PHI list + void addIncoming(MemoryAccess *V, BasicBlock *BB) { + if (getNumOperands() == ReservedSpace) + growOperands(); // Get more space! + // Initialize some new operands. + setNumHungOffUseOperands(getNumOperands() + 1); + setIncomingValue(getNumOperands() - 1, V); + setIncomingBlock(getNumOperands() - 1, BB); + } + + /// Return the first index of the specified basic + /// block in the value list for this PHI. Returns -1 if no instance. + int getBasicBlockIndex(const BasicBlock *BB) const { + for (unsigned I = 0, E = getNumOperands(); I != E; ++I) + if (block_begin()[I] == BB) + return I; + return -1; + } + + MemoryAccess *getIncomingValueForBlock(const BasicBlock *BB) const { + int Idx = getBasicBlockIndex(BB); + assert(Idx >= 0 && "Invalid basic block argument!"); + return getIncomingValue(Idx); + } + + // After deleting incoming position I, the order of incoming may be changed. + void unorderedDeleteIncoming(unsigned I) { + unsigned E = getNumOperands(); + assert(I < E && "Cannot remove out of bounds Phi entry."); + // MemoryPhi must have at least two incoming values, otherwise the MemoryPhi + // itself should be deleted. + assert(E >= 2 && "Cannot only remove incoming values in MemoryPhis with " + "at least 2 values."); + setIncomingValue(I, getIncomingValue(E - 1)); + setIncomingBlock(I, block_begin()[E - 1]); + setOperand(E - 1, nullptr); + block_begin()[E - 1] = nullptr; + setNumHungOffUseOperands(getNumOperands() - 1); + } + + // After deleting entries that satisfy Pred, remaining entries may have + // changed order. + template <typename Fn> void unorderedDeleteIncomingIf(Fn &&Pred) { + for (unsigned I = 0, E = getNumOperands(); I != E; ++I) + if (Pred(getIncomingValue(I), getIncomingBlock(I))) { + unorderedDeleteIncoming(I); + E = getNumOperands(); + --I; + } + assert(getNumOperands() >= 1 && + "Cannot remove all incoming blocks in a MemoryPhi."); + } + + // After deleting incoming block BB, the incoming blocks order may be changed. + void unorderedDeleteIncomingBlock(const BasicBlock *BB) { + unorderedDeleteIncomingIf( + [&](const MemoryAccess *, const BasicBlock *B) { return BB == B; }); + } + + // After deleting incoming memory access MA, the incoming accesses order may + // be changed. + void unorderedDeleteIncomingValue(const MemoryAccess *MA) { + unorderedDeleteIncomingIf( + [&](const MemoryAccess *M, const BasicBlock *) { return MA == M; }); + } + + static bool classof(const Value *V) { + return V->getValueID() == MemoryPhiVal; + } + + void print(raw_ostream &OS) const; + + unsigned getID() const { return ID; } + +protected: + friend class MemorySSA; + + /// this is more complicated than the generic + /// User::allocHungoffUses, because we have to allocate Uses for the incoming + /// values and pointers to the incoming blocks, all in one allocation. + void allocHungoffUses(unsigned N) { + User::allocHungoffUses(N, /* IsPhi */ true); + } + +private: + // For debugging only + const unsigned ID; + unsigned ReservedSpace; + + /// This grows the operand list in response to a push_back style of + /// operation. This grows the number of ops by 1.5 times. + void growOperands() { + unsigned E = getNumOperands(); + // 2 op PHI nodes are VERY common, so reserve at least enough for that. + ReservedSpace = std::max(E + E / 2, 2u); + growHungoffUses(ReservedSpace, /* IsPhi */ true); + } + + static void deleteMe(DerivedUser *Self); +}; + +inline unsigned MemoryAccess::getID() const { + assert((isa<MemoryDef>(this) || isa<MemoryPhi>(this)) && + "only memory defs and phis have ids"); + if (const auto *MD = dyn_cast<MemoryDef>(this)) + return MD->getID(); + return cast<MemoryPhi>(this)->getID(); +} + +inline bool MemoryUseOrDef::isOptimized() const { + if (const auto *MD = dyn_cast<MemoryDef>(this)) + return MD->isOptimized(); + return cast<MemoryUse>(this)->isOptimized(); +} + +inline MemoryAccess *MemoryUseOrDef::getOptimized() const { + if (const auto *MD = dyn_cast<MemoryDef>(this)) + return MD->getOptimized(); + return cast<MemoryUse>(this)->getOptimized(); +} + +inline void MemoryUseOrDef::setOptimized(MemoryAccess *MA) { + if (auto *MD = dyn_cast<MemoryDef>(this)) + MD->setOptimized(MA); + else + cast<MemoryUse>(this)->setOptimized(MA); +} + +inline void MemoryUseOrDef::resetOptimized() { + if (auto *MD = dyn_cast<MemoryDef>(this)) + MD->resetOptimized(); + else + cast<MemoryUse>(this)->resetOptimized(); +} + +template <> struct OperandTraits<MemoryPhi> : public HungoffOperandTraits<2> {}; +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryPhi, MemoryAccess) + +/// Encapsulates MemorySSA, including all data associated with memory +/// accesses. +class MemorySSA { +public: + MemorySSA(Function &, AliasAnalysis *, DominatorTree *); + + // MemorySSA must remain where it's constructed; Walkers it creates store + // pointers to it. + MemorySSA(MemorySSA &&) = delete; + + ~MemorySSA(); + + MemorySSAWalker *getWalker(); + MemorySSAWalker *getSkipSelfWalker(); + + /// Given a memory Mod/Ref'ing instruction, get the MemorySSA + /// access associated with it. If passed a basic block gets the memory phi + /// node that exists for that block, if there is one. Otherwise, this will get + /// a MemoryUseOrDef. + MemoryUseOrDef *getMemoryAccess(const Instruction *I) const { + return cast_or_null<MemoryUseOrDef>(ValueToMemoryAccess.lookup(I)); + } + + MemoryPhi *getMemoryAccess(const BasicBlock *BB) const { + return cast_or_null<MemoryPhi>(ValueToMemoryAccess.lookup(cast<Value>(BB))); + } + + void dump() const; + void print(raw_ostream &) const; + + /// Return true if \p MA represents the live on entry value + /// + /// Loads and stores from pointer arguments and other global values may be + /// defined by memory operations that do not occur in the current function, so + /// they may be live on entry to the function. MemorySSA represents such + /// memory state by the live on entry definition, which is guaranteed to occur + /// before any other memory access in the function. + inline bool isLiveOnEntryDef(const MemoryAccess *MA) const { + return MA == LiveOnEntryDef.get(); + } + + inline MemoryAccess *getLiveOnEntryDef() const { + return LiveOnEntryDef.get(); + } + + // Sadly, iplists, by default, owns and deletes pointers added to the + // list. It's not currently possible to have two iplists for the same type, + // where one owns the pointers, and one does not. This is because the traits + // are per-type, not per-tag. If this ever changes, we should make the + // DefList an iplist. + using AccessList = iplist<MemoryAccess, ilist_tag<MSSAHelpers::AllAccessTag>>; + using DefsList = + simple_ilist<MemoryAccess, ilist_tag<MSSAHelpers::DefsOnlyTag>>; + + /// Return the list of MemoryAccess's for a given basic block. + /// + /// This list is not modifiable by the user. + const AccessList *getBlockAccesses(const BasicBlock *BB) const { + return getWritableBlockAccesses(BB); + } + + /// Return the list of MemoryDef's and MemoryPhi's for a given basic + /// block. + /// + /// This list is not modifiable by the user. + const DefsList *getBlockDefs(const BasicBlock *BB) const { + return getWritableBlockDefs(BB); + } + + /// Given two memory accesses in the same basic block, determine + /// whether MemoryAccess \p A dominates MemoryAccess \p B. + bool locallyDominates(const MemoryAccess *A, const MemoryAccess *B) const; + + /// Given two memory accesses in potentially different blocks, + /// determine whether MemoryAccess \p A dominates MemoryAccess \p B. + bool dominates(const MemoryAccess *A, const MemoryAccess *B) const; + + /// Given a MemoryAccess and a Use, determine whether MemoryAccess \p A + /// dominates Use \p B. + bool dominates(const MemoryAccess *A, const Use &B) const; + + /// Verify that MemorySSA is self consistent (IE definitions dominate + /// all uses, uses appear in the right places). This is used by unit tests. + void verifyMemorySSA() const; + + /// Used in various insertion functions to specify whether we are talking + /// about the beginning or end of a block. + enum InsertionPlace { Beginning, End, BeforeTerminator }; + +protected: + // Used by Memory SSA annotater, dumpers, and wrapper pass + friend class MemorySSAAnnotatedWriter; + friend class MemorySSAPrinterLegacyPass; + friend class MemorySSAUpdater; + + void verifyOrderingDominationAndDefUses(Function &F) const; + void verifyDominationNumbers(const Function &F) const; + void verifyPrevDefInPhis(Function &F) const; + + // This is used by the use optimizer and updater. + AccessList *getWritableBlockAccesses(const BasicBlock *BB) const { + auto It = PerBlockAccesses.find(BB); + return It == PerBlockAccesses.end() ? nullptr : It->second.get(); + } + + // This is used by the use optimizer and updater. + DefsList *getWritableBlockDefs(const BasicBlock *BB) const { + auto It = PerBlockDefs.find(BB); + return It == PerBlockDefs.end() ? nullptr : It->second.get(); + } + + // These is used by the updater to perform various internal MemorySSA + // machinsations. They do not always leave the IR in a correct state, and + // relies on the updater to fixup what it breaks, so it is not public. + + void moveTo(MemoryUseOrDef *What, BasicBlock *BB, AccessList::iterator Where); + void moveTo(MemoryAccess *What, BasicBlock *BB, InsertionPlace Point); + + // Rename the dominator tree branch rooted at BB. + void renamePass(BasicBlock *BB, MemoryAccess *IncomingVal, + SmallPtrSetImpl<BasicBlock *> &Visited) { + renamePass(DT->getNode(BB), IncomingVal, Visited, true, true); + } + + void removeFromLookups(MemoryAccess *); + void removeFromLists(MemoryAccess *, bool ShouldDelete = true); + void insertIntoListsForBlock(MemoryAccess *, const BasicBlock *, + InsertionPlace); + void insertIntoListsBefore(MemoryAccess *, const BasicBlock *, + AccessList::iterator); + MemoryUseOrDef *createDefinedAccess(Instruction *, MemoryAccess *, + const MemoryUseOrDef *Template = nullptr, + bool CreationMustSucceed = true); + +private: + template <class AliasAnalysisType> class ClobberWalkerBase; + template <class AliasAnalysisType> class CachingWalker; + template <class AliasAnalysisType> class SkipSelfWalker; + class OptimizeUses; + + CachingWalker<AliasAnalysis> *getWalkerImpl(); + void buildMemorySSA(BatchAAResults &BAA); + void optimizeUses(); + + void prepareForMoveTo(MemoryAccess *, BasicBlock *); + void verifyUseInDefs(MemoryAccess *, MemoryAccess *) const; + + using AccessMap = DenseMap<const BasicBlock *, std::unique_ptr<AccessList>>; + using DefsMap = DenseMap<const BasicBlock *, std::unique_ptr<DefsList>>; + + void + determineInsertionPoint(const SmallPtrSetImpl<BasicBlock *> &DefiningBlocks); + void markUnreachableAsLiveOnEntry(BasicBlock *BB); + bool dominatesUse(const MemoryAccess *, const MemoryAccess *) const; + MemoryPhi *createMemoryPhi(BasicBlock *BB); + template <typename AliasAnalysisType> + MemoryUseOrDef *createNewAccess(Instruction *, AliasAnalysisType *, + const MemoryUseOrDef *Template = nullptr); + MemoryAccess *findDominatingDef(BasicBlock *, enum InsertionPlace); + void placePHINodes(const SmallPtrSetImpl<BasicBlock *> &); + MemoryAccess *renameBlock(BasicBlock *, MemoryAccess *, bool); + void renameSuccessorPhis(BasicBlock *, MemoryAccess *, bool); + void renamePass(DomTreeNode *, MemoryAccess *IncomingVal, + SmallPtrSetImpl<BasicBlock *> &Visited, + bool SkipVisited = false, bool RenameAllUses = false); + AccessList *getOrCreateAccessList(const BasicBlock *); + DefsList *getOrCreateDefsList(const BasicBlock *); + void renumberBlock(const BasicBlock *) const; + AliasAnalysis *AA; + DominatorTree *DT; + Function &F; + + // Memory SSA mappings + DenseMap<const Value *, MemoryAccess *> ValueToMemoryAccess; + + // These two mappings contain the main block to access/def mappings for + // MemorySSA. The list contained in PerBlockAccesses really owns all the + // MemoryAccesses. + // Both maps maintain the invariant that if a block is found in them, the + // corresponding list is not empty, and if a block is not found in them, the + // corresponding list is empty. + AccessMap PerBlockAccesses; + DefsMap PerBlockDefs; + std::unique_ptr<MemoryAccess, ValueDeleter> LiveOnEntryDef; + + // Domination mappings + // Note that the numbering is local to a block, even though the map is + // global. + mutable SmallPtrSet<const BasicBlock *, 16> BlockNumberingValid; + mutable DenseMap<const MemoryAccess *, unsigned long> BlockNumbering; + + // Memory SSA building info + std::unique_ptr<ClobberWalkerBase<AliasAnalysis>> WalkerBase; + std::unique_ptr<CachingWalker<AliasAnalysis>> Walker; + std::unique_ptr<SkipSelfWalker<AliasAnalysis>> SkipWalker; + unsigned NextID; +}; + +// Internal MemorySSA utils, for use by MemorySSA classes and walkers +class MemorySSAUtil { +protected: + friend class GVNHoist; + friend class MemorySSAWalker; + + // This function should not be used by new passes. + static bool defClobbersUseOrDef(MemoryDef *MD, const MemoryUseOrDef *MU, + AliasAnalysis &AA); +}; + +// This pass does eager building and then printing of MemorySSA. It is used by +// the tests to be able to build, dump, and verify Memory SSA. +class MemorySSAPrinterLegacyPass : public FunctionPass { +public: + MemorySSAPrinterLegacyPass(); + + bool runOnFunction(Function &) override; + void getAnalysisUsage(AnalysisUsage &AU) const override; + + static char ID; +}; + +/// An analysis that produces \c MemorySSA for a function. +/// +class MemorySSAAnalysis : public AnalysisInfoMixin<MemorySSAAnalysis> { + friend AnalysisInfoMixin<MemorySSAAnalysis>; + + static AnalysisKey Key; + +public: + // Wrap MemorySSA result to ensure address stability of internal MemorySSA + // pointers after construction. Use a wrapper class instead of plain + // unique_ptr<MemorySSA> to avoid build breakage on MSVC. + struct Result { + Result(std::unique_ptr<MemorySSA> &&MSSA) : MSSA(std::move(MSSA)) {} + + MemorySSA &getMSSA() { return *MSSA.get(); } + + std::unique_ptr<MemorySSA> MSSA; + + bool invalidate(Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &Inv); + }; + + Result run(Function &F, FunctionAnalysisManager &AM); +}; + +/// Printer pass for \c MemorySSA. +class MemorySSAPrinterPass : public PassInfoMixin<MemorySSAPrinterPass> { + raw_ostream &OS; + +public: + explicit MemorySSAPrinterPass(raw_ostream &OS) : OS(OS) {} + + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + +/// Verifier pass for \c MemorySSA. +struct MemorySSAVerifierPass : PassInfoMixin<MemorySSAVerifierPass> { + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + +/// Legacy analysis pass which computes \c MemorySSA. +class MemorySSAWrapperPass : public FunctionPass { +public: + MemorySSAWrapperPass(); + + static char ID; + + bool runOnFunction(Function &) override; + void releaseMemory() override; + MemorySSA &getMSSA() { return *MSSA; } + const MemorySSA &getMSSA() const { return *MSSA; } + + void getAnalysisUsage(AnalysisUsage &AU) const override; + + void verifyAnalysis() const override; + void print(raw_ostream &OS, const Module *M = nullptr) const override; + +private: + std::unique_ptr<MemorySSA> MSSA; +}; + +/// This is the generic walker interface for walkers of MemorySSA. +/// Walkers are used to be able to further disambiguate the def-use chains +/// MemorySSA gives you, or otherwise produce better info than MemorySSA gives +/// you. +/// In particular, while the def-use chains provide basic information, and are +/// guaranteed to give, for example, the nearest may-aliasing MemoryDef for a +/// MemoryUse as AliasAnalysis considers it, a user mant want better or other +/// information. In particular, they may want to use SCEV info to further +/// disambiguate memory accesses, or they may want the nearest dominating +/// may-aliasing MemoryDef for a call or a store. This API enables a +/// standardized interface to getting and using that info. +class MemorySSAWalker { +public: + MemorySSAWalker(MemorySSA *); + virtual ~MemorySSAWalker() = default; + + using MemoryAccessSet = SmallVector<MemoryAccess *, 8>; + + /// Given a memory Mod/Ref/ModRef'ing instruction, calling this + /// will give you the nearest dominating MemoryAccess that Mod's the location + /// the instruction accesses (by skipping any def which AA can prove does not + /// alias the location(s) accessed by the instruction given). + /// + /// Note that this will return a single access, and it must dominate the + /// Instruction, so if an operand of a MemoryPhi node Mod's the instruction, + /// this will return the MemoryPhi, not the operand. This means that + /// given: + /// if (a) { + /// 1 = MemoryDef(liveOnEntry) + /// store %a + /// } else { + /// 2 = MemoryDef(liveOnEntry) + /// store %b + /// } + /// 3 = MemoryPhi(2, 1) + /// MemoryUse(3) + /// load %a + /// + /// calling this API on load(%a) will return the MemoryPhi, not the MemoryDef + /// in the if (a) branch. + MemoryAccess *getClobberingMemoryAccess(const Instruction *I) { + MemoryAccess *MA = MSSA->getMemoryAccess(I); + assert(MA && "Handed an instruction that MemorySSA doesn't recognize?"); + return getClobberingMemoryAccess(MA); + } + + /// Does the same thing as getClobberingMemoryAccess(const Instruction *I), + /// but takes a MemoryAccess instead of an Instruction. + virtual MemoryAccess *getClobberingMemoryAccess(MemoryAccess *) = 0; + + /// Given a potentially clobbering memory access and a new location, + /// calling this will give you the nearest dominating clobbering MemoryAccess + /// (by skipping non-aliasing def links). + /// + /// This version of the function is mainly used to disambiguate phi translated + /// pointers, where the value of a pointer may have changed from the initial + /// memory access. Note that this expects to be handed either a MemoryUse, + /// or an already potentially clobbering access. Unlike the above API, if + /// given a MemoryDef that clobbers the pointer as the starting access, it + /// will return that MemoryDef, whereas the above would return the clobber + /// starting from the use side of the memory def. + virtual MemoryAccess *getClobberingMemoryAccess(MemoryAccess *, + const MemoryLocation &) = 0; + + /// Given a memory access, invalidate anything this walker knows about + /// that access. + /// This API is used by walkers that store information to perform basic cache + /// invalidation. This will be called by MemorySSA at appropriate times for + /// the walker it uses or returns. + virtual void invalidateInfo(MemoryAccess *) {} + +protected: + friend class MemorySSA; // For updating MSSA pointer in MemorySSA move + // constructor. + MemorySSA *MSSA; +}; + +/// A MemorySSAWalker that does no alias queries, or anything else. It +/// simply returns the links as they were constructed by the builder. +class DoNothingMemorySSAWalker final : public MemorySSAWalker { +public: + // Keep the overrides below from hiding the Instruction overload of + // getClobberingMemoryAccess. + using MemorySSAWalker::getClobberingMemoryAccess; + + MemoryAccess *getClobberingMemoryAccess(MemoryAccess *) override; + MemoryAccess *getClobberingMemoryAccess(MemoryAccess *, + const MemoryLocation &) override; +}; + +using MemoryAccessPair = std::pair<MemoryAccess *, MemoryLocation>; +using ConstMemoryAccessPair = std::pair<const MemoryAccess *, MemoryLocation>; + +/// Iterator base class used to implement const and non-const iterators +/// over the defining accesses of a MemoryAccess. +template <class T> +class memoryaccess_def_iterator_base + : public iterator_facade_base<memoryaccess_def_iterator_base<T>, + std::forward_iterator_tag, T, ptrdiff_t, T *, + T *> { + using BaseT = typename memoryaccess_def_iterator_base::iterator_facade_base; + +public: + memoryaccess_def_iterator_base(T *Start) : Access(Start) {} + memoryaccess_def_iterator_base() = default; + + bool operator==(const memoryaccess_def_iterator_base &Other) const { + return Access == Other.Access && (!Access || ArgNo == Other.ArgNo); + } + + // This is a bit ugly, but for MemoryPHI's, unlike PHINodes, you can't get the + // block from the operand in constant time (In a PHINode, the uselist has + // both, so it's just subtraction). We provide it as part of the + // iterator to avoid callers having to linear walk to get the block. + // If the operation becomes constant time on MemoryPHI's, this bit of + // abstraction breaking should be removed. + BasicBlock *getPhiArgBlock() const { + MemoryPhi *MP = dyn_cast<MemoryPhi>(Access); + assert(MP && "Tried to get phi arg block when not iterating over a PHI"); + return MP->getIncomingBlock(ArgNo); + } + + typename BaseT::iterator::pointer operator*() const { + assert(Access && "Tried to access past the end of our iterator"); + // Go to the first argument for phis, and the defining access for everything + // else. + if (const MemoryPhi *MP = dyn_cast<MemoryPhi>(Access)) + return MP->getIncomingValue(ArgNo); + return cast<MemoryUseOrDef>(Access)->getDefiningAccess(); + } + + using BaseT::operator++; + memoryaccess_def_iterator_base &operator++() { + assert(Access && "Hit end of iterator"); + if (const MemoryPhi *MP = dyn_cast<MemoryPhi>(Access)) { + if (++ArgNo >= MP->getNumIncomingValues()) { + ArgNo = 0; + Access = nullptr; + } + } else { + Access = nullptr; + } + return *this; + } + +private: + T *Access = nullptr; + unsigned ArgNo = 0; +}; + +inline memoryaccess_def_iterator MemoryAccess::defs_begin() { + return memoryaccess_def_iterator(this); +} + +inline const_memoryaccess_def_iterator MemoryAccess::defs_begin() const { + return const_memoryaccess_def_iterator(this); +} + +inline memoryaccess_def_iterator MemoryAccess::defs_end() { + return memoryaccess_def_iterator(); +} + +inline const_memoryaccess_def_iterator MemoryAccess::defs_end() const { + return const_memoryaccess_def_iterator(); +} + +/// GraphTraits for a MemoryAccess, which walks defs in the normal case, +/// and uses in the inverse case. +template <> struct GraphTraits<MemoryAccess *> { + using NodeRef = MemoryAccess *; + using ChildIteratorType = memoryaccess_def_iterator; + + static NodeRef getEntryNode(NodeRef N) { return N; } + static ChildIteratorType child_begin(NodeRef N) { return N->defs_begin(); } + static ChildIteratorType child_end(NodeRef N) { return N->defs_end(); } +}; + +template <> struct GraphTraits<Inverse<MemoryAccess *>> { + using NodeRef = MemoryAccess *; + using ChildIteratorType = MemoryAccess::iterator; + + static NodeRef getEntryNode(NodeRef N) { return N; } + static ChildIteratorType child_begin(NodeRef N) { return N->user_begin(); } + static ChildIteratorType child_end(NodeRef N) { return N->user_end(); } +}; + +/// Provide an iterator that walks defs, giving both the memory access, +/// and the current pointer location, updating the pointer location as it +/// changes due to phi node translation. +/// +/// This iterator, while somewhat specialized, is what most clients actually +/// want when walking upwards through MemorySSA def chains. It takes a pair of +/// <MemoryAccess,MemoryLocation>, and walks defs, properly translating the +/// memory location through phi nodes for the user. +class upward_defs_iterator + : public iterator_facade_base<upward_defs_iterator, + std::forward_iterator_tag, + const MemoryAccessPair> { + using BaseT = upward_defs_iterator::iterator_facade_base; + +public: + upward_defs_iterator(const MemoryAccessPair &Info) + : DefIterator(Info.first), Location(Info.second), + OriginalAccess(Info.first) { + CurrentPair.first = nullptr; + + WalkingPhi = Info.first && isa<MemoryPhi>(Info.first); + fillInCurrentPair(); + } + + upward_defs_iterator() { CurrentPair.first = nullptr; } + + bool operator==(const upward_defs_iterator &Other) const { + return DefIterator == Other.DefIterator; + } + + BaseT::iterator::reference operator*() const { + assert(DefIterator != OriginalAccess->defs_end() && + "Tried to access past the end of our iterator"); + return CurrentPair; + } + + using BaseT::operator++; + upward_defs_iterator &operator++() { + assert(DefIterator != OriginalAccess->defs_end() && + "Tried to access past the end of the iterator"); + ++DefIterator; + if (DefIterator != OriginalAccess->defs_end()) + fillInCurrentPair(); + return *this; + } + + BasicBlock *getPhiArgBlock() const { return DefIterator.getPhiArgBlock(); } + +private: + void fillInCurrentPair() { + CurrentPair.first = *DefIterator; + if (WalkingPhi && Location.Ptr) { + PHITransAddr Translator( + const_cast<Value *>(Location.Ptr), + OriginalAccess->getBlock()->getModule()->getDataLayout(), nullptr); + if (!Translator.PHITranslateValue(OriginalAccess->getBlock(), + DefIterator.getPhiArgBlock(), nullptr, + false)) + if (Translator.getAddr() != Location.Ptr) { + CurrentPair.second = Location.getWithNewPtr(Translator.getAddr()); + return; + } + } + CurrentPair.second = Location; + } + + MemoryAccessPair CurrentPair; + memoryaccess_def_iterator DefIterator; + MemoryLocation Location; + MemoryAccess *OriginalAccess = nullptr; + bool WalkingPhi = false; +}; + +inline upward_defs_iterator upward_defs_begin(const MemoryAccessPair &Pair) { + return upward_defs_iterator(Pair); +} + +inline upward_defs_iterator upward_defs_end() { return upward_defs_iterator(); } + +inline iterator_range<upward_defs_iterator> +upward_defs(const MemoryAccessPair &Pair) { + return make_range(upward_defs_begin(Pair), upward_defs_end()); +} + +/// Walks the defining accesses of MemoryDefs. Stops after we hit something that +/// has no defining use (e.g. a MemoryPhi or liveOnEntry). Note that, when +/// comparing against a null def_chain_iterator, this will compare equal only +/// after walking said Phi/liveOnEntry. +/// +/// The UseOptimizedChain flag specifies whether to walk the clobbering +/// access chain, or all the accesses. +/// +/// Normally, MemoryDef are all just def/use linked together, so a def_chain on +/// a MemoryDef will walk all MemoryDefs above it in the program until it hits +/// a phi node. The optimized chain walks the clobbering access of a store. +/// So if you are just trying to find, given a store, what the next +/// thing that would clobber the same memory is, you want the optimized chain. +template <class T, bool UseOptimizedChain = false> +struct def_chain_iterator + : public iterator_facade_base<def_chain_iterator<T, UseOptimizedChain>, + std::forward_iterator_tag, MemoryAccess *> { + def_chain_iterator() : MA(nullptr) {} + def_chain_iterator(T MA) : MA(MA) {} + + T operator*() const { return MA; } + + def_chain_iterator &operator++() { + // N.B. liveOnEntry has a null defining access. + if (auto *MUD = dyn_cast<MemoryUseOrDef>(MA)) { + if (UseOptimizedChain && MUD->isOptimized()) + MA = MUD->getOptimized(); + else + MA = MUD->getDefiningAccess(); + } else { + MA = nullptr; + } + + return *this; + } + + bool operator==(const def_chain_iterator &O) const { return MA == O.MA; } + +private: + T MA; +}; + +template <class T> +inline iterator_range<def_chain_iterator<T>> +def_chain(T MA, MemoryAccess *UpTo = nullptr) { +#ifdef EXPENSIVE_CHECKS + assert((!UpTo || find(def_chain(MA), UpTo) != def_chain_iterator<T>()) && + "UpTo isn't in the def chain!"); +#endif + return make_range(def_chain_iterator<T>(MA), def_chain_iterator<T>(UpTo)); +} + +template <class T> +inline iterator_range<def_chain_iterator<T, true>> optimized_def_chain(T MA) { + return make_range(def_chain_iterator<T, true>(MA), + def_chain_iterator<T, true>(nullptr)); +} + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_MEMORYSSA_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/MemorySSAUpdater.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/MemorySSAUpdater.h new file mode 100644 index 0000000..1d34663 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/MemorySSAUpdater.h
@@ -0,0 +1,309 @@ +//===- MemorySSAUpdater.h - Memory SSA Updater-------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// \file +// An automatic updater for MemorySSA that handles arbitrary insertion, +// deletion, and moves. It performs phi insertion where necessary, and +// automatically updates the MemorySSA IR to be correct. +// While updating loads or removing instructions is often easy enough to not +// need this, updating stores should generally not be attemped outside this +// API. +// +// Basic API usage: +// Create the memory access you want for the instruction (this is mainly so +// we know where it is, without having to duplicate the entire set of create +// functions MemorySSA supports). +// Call insertDef or insertUse depending on whether it's a MemoryUse or a +// MemoryDef. +// That's it. +// +// For moving, first, move the instruction itself using the normal SSA +// instruction moving API, then just call moveBefore, moveAfter,or moveTo with +// the right arguments. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_MEMORYSSAUPDATER_H +#define LLVM_ANALYSIS_MEMORYSSAUPDATER_H + +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/LoopIterator.h" +#include "llvm/Analysis/MemorySSA.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/CFGDiff.h" +#include "llvm/IR/Dominators.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/OperandTraits.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/Use.h" +#include "llvm/IR/User.h" +#include "llvm/IR/Value.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/IR/ValueMap.h" +#include "llvm/Pass.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" + +namespace llvm { + +class Function; +class Instruction; +class MemoryAccess; +class LLVMContext; +class raw_ostream; + +using ValueToValueMapTy = ValueMap<const Value *, WeakTrackingVH>; +using PhiToDefMap = SmallDenseMap<MemoryPhi *, MemoryAccess *>; +using CFGUpdate = cfg::Update<BasicBlock *>; +using GraphDiffInvBBPair = + std::pair<const GraphDiff<BasicBlock *> *, Inverse<BasicBlock *>>; + +class MemorySSAUpdater { +private: + MemorySSA *MSSA; + + /// We use WeakVH rather than a costly deletion to deal with dangling pointers. + /// MemoryPhis are created eagerly and sometimes get zapped shortly afterwards. + SmallVector<WeakVH, 16> InsertedPHIs; + + SmallPtrSet<BasicBlock *, 8> VisitedBlocks; + SmallSet<AssertingVH<MemoryPhi>, 8> NonOptPhis; + +public: + MemorySSAUpdater(MemorySSA *MSSA) : MSSA(MSSA) {} + + /// Insert a definition into the MemorySSA IR. RenameUses will rename any use + /// below the new def block (and any inserted phis). RenameUses should be set + /// to true if the definition may cause new aliases for loads below it. This + /// is not the case for hoisting or sinking or other forms of code *movement*. + /// It *is* the case for straight code insertion. + /// For example: + /// store a + /// if (foo) { } + /// load a + /// + /// Moving the store into the if block, and calling insertDef, does not + /// require RenameUses. + /// However, changing it to: + /// store a + /// if (foo) { store b } + /// load a + /// Where a mayalias b, *does* require RenameUses be set to true. + void insertDef(MemoryDef *Def, bool RenameUses = false); + void insertUse(MemoryUse *Use, bool RenameUses = false); + /// Update the MemoryPhi in `To` following an edge deletion between `From` and + /// `To`. If `To` becomes unreachable, a call to removeBlocks should be made. + void removeEdge(BasicBlock *From, BasicBlock *To); + /// Update the MemoryPhi in `To` to have a single incoming edge from `From`, + /// following a CFG change that replaced multiple edges (switch) with a direct + /// branch. + void removeDuplicatePhiEdgesBetween(const BasicBlock *From, + const BasicBlock *To); + /// Update MemorySSA when inserting a unique backedge block for a loop. + void updatePhisWhenInsertingUniqueBackedgeBlock(BasicBlock *LoopHeader, + BasicBlock *LoopPreheader, + BasicBlock *BackedgeBlock); + /// Update MemorySSA after a loop was cloned, given the blocks in RPO order, + /// the exit blocks and a 1:1 mapping of all blocks and instructions + /// cloned. This involves duplicating all defs and uses in the cloned blocks + /// Updating phi nodes in exit block successors is done separately. + void updateForClonedLoop(const LoopBlocksRPO &LoopBlocks, + ArrayRef<BasicBlock *> ExitBlocks, + const ValueToValueMapTy &VM, + bool IgnoreIncomingWithNoClones = false); + // Block BB was fully or partially cloned into its predecessor P1. Map + // contains the 1:1 mapping of instructions cloned and VM[BB]=P1. + void updateForClonedBlockIntoPred(BasicBlock *BB, BasicBlock *P1, + const ValueToValueMapTy &VM); + /// Update phi nodes in exit block successors following cloning. Exit blocks + /// that were not cloned don't have additional predecessors added. + void updateExitBlocksForClonedLoop(ArrayRef<BasicBlock *> ExitBlocks, + const ValueToValueMapTy &VMap, + DominatorTree &DT); + void updateExitBlocksForClonedLoop( + ArrayRef<BasicBlock *> ExitBlocks, + ArrayRef<std::unique_ptr<ValueToValueMapTy>> VMaps, DominatorTree &DT); + + /// Apply CFG updates, analogous with the DT edge updates. + void applyUpdates(ArrayRef<CFGUpdate> Updates, DominatorTree &DT); + /// Apply CFG insert updates, analogous with the DT edge updates. + void applyInsertUpdates(ArrayRef<CFGUpdate> Updates, DominatorTree &DT); + + void moveBefore(MemoryUseOrDef *What, MemoryUseOrDef *Where); + void moveAfter(MemoryUseOrDef *What, MemoryUseOrDef *Where); + void moveToPlace(MemoryUseOrDef *What, BasicBlock *BB, + MemorySSA::InsertionPlace Where); + /// `From` block was spliced into `From` and `To`. There is a CFG edge from + /// `From` to `To`. Move all accesses from `From` to `To` starting at + /// instruction `Start`. `To` is newly created BB, so empty of + /// MemorySSA::MemoryAccesses. Edges are already updated, so successors of + /// `To` with MPhi nodes need to update incoming block. + /// |------| |------| + /// | From | | From | + /// | | |------| + /// | | || + /// | | => \/ + /// | | |------| <- Start + /// | | | To | + /// |------| |------| + void moveAllAfterSpliceBlocks(BasicBlock *From, BasicBlock *To, + Instruction *Start); + /// `From` block was merged into `To`. There is a CFG edge from `To` to + /// `From`.`To` still branches to `From`, but all instructions were moved and + /// `From` is now an empty block; `From` is about to be deleted. Move all + /// accesses from `From` to `To` starting at instruction `Start`. `To` may + /// have multiple successors, `From` has a single predecessor. `From` may have + /// successors with MPhi nodes, replace their incoming block with `To`. + /// |------| |------| + /// | To | | To | + /// |------| | | + /// || => | | + /// \/ | | + /// |------| | | <- Start + /// | From | | | + /// |------| |------| + void moveAllAfterMergeBlocks(BasicBlock *From, BasicBlock *To, + Instruction *Start); + /// A new empty BasicBlock (New) now branches directly to Old. Some of + /// Old's predecessors (Preds) are now branching to New instead of Old. + /// If New is the only predecessor, move Old's Phi, if present, to New. + /// Otherwise, add a new Phi in New with appropriate incoming values, and + /// update the incoming values in Old's Phi node too, if present. + void wireOldPredecessorsToNewImmediatePredecessor( + BasicBlock *Old, BasicBlock *New, ArrayRef<BasicBlock *> Preds, + bool IdenticalEdgesWereMerged = true); + // The below are utility functions. Other than creation of accesses to pass + // to insertDef, and removeAccess to remove accesses, you should generally + // not attempt to update memoryssa yourself. It is very non-trivial to get + // the edge cases right, and the above calls already operate in near-optimal + // time bounds. + + /// Create a MemoryAccess in MemorySSA at a specified point in a block, + /// with a specified clobbering definition. + /// + /// Returns the new MemoryAccess. + /// This should be called when a memory instruction is created that is being + /// used to replace an existing memory instruction. It will *not* create PHI + /// nodes, or verify the clobbering definition. The insertion place is used + /// solely to determine where in the memoryssa access lists the instruction + /// will be placed. The caller is expected to keep ordering the same as + /// instructions. + /// It will return the new MemoryAccess. + /// Note: If a MemoryAccess already exists for I, this function will make it + /// inaccessible and it *must* have removeMemoryAccess called on it. + MemoryAccess *createMemoryAccessInBB(Instruction *I, MemoryAccess *Definition, + const BasicBlock *BB, + MemorySSA::InsertionPlace Point); + + /// Create a MemoryAccess in MemorySSA before or after an existing + /// MemoryAccess. + /// + /// Returns the new MemoryAccess. + /// This should be called when a memory instruction is created that is being + /// used to replace an existing memory instruction. It will *not* create PHI + /// nodes, or verify the clobbering definition. + /// + /// Note: If a MemoryAccess already exists for I, this function will make it + /// inaccessible and it *must* have removeMemoryAccess called on it. + MemoryUseOrDef *createMemoryAccessBefore(Instruction *I, + MemoryAccess *Definition, + MemoryUseOrDef *InsertPt); + MemoryUseOrDef *createMemoryAccessAfter(Instruction *I, + MemoryAccess *Definition, + MemoryAccess *InsertPt); + + /// Remove a MemoryAccess from MemorySSA, including updating all + /// definitions and uses. + /// This should be called when a memory instruction that has a MemoryAccess + /// associated with it is erased from the program. For example, if a store or + /// load is simply erased (not replaced), removeMemoryAccess should be called + /// on the MemoryAccess for that store/load. + void removeMemoryAccess(MemoryAccess *, bool OptimizePhis = false); + + /// Remove MemoryAccess for a given instruction, if a MemoryAccess exists. + /// This should be called when an instruction (load/store) is deleted from + /// the program. + void removeMemoryAccess(const Instruction *I, bool OptimizePhis = false) { + if (MemoryAccess *MA = MSSA->getMemoryAccess(I)) + removeMemoryAccess(MA, OptimizePhis); + } + + /// Remove all MemoryAcceses in a set of BasicBlocks about to be deleted. + /// Assumption we make here: all uses of deleted defs and phi must either + /// occur in blocks about to be deleted (thus will be deleted as well), or + /// they occur in phis that will simply lose an incoming value. + /// Deleted blocks still have successor info, but their predecessor edges and + /// Phi nodes may already be updated. Instructions in DeadBlocks should be + /// deleted after this call. + void removeBlocks(const SmallSetVector<BasicBlock *, 8> &DeadBlocks); + + /// Instruction I will be changed to an unreachable. Remove all accesses in + /// I's block that follow I (inclusive), and update the Phis in the blocks' + /// successors. + void changeToUnreachable(const Instruction *I); + + /// Conditional branch BI is changed or replaced with an unconditional branch + /// to `To`. Update Phis in BI's successors to remove BI's BB. + void changeCondBranchToUnconditionalTo(const BranchInst *BI, + const BasicBlock *To); + + /// Get handle on MemorySSA. + MemorySSA* getMemorySSA() const { return MSSA; } + +private: + // Move What before Where in the MemorySSA IR. + template <class WhereType> + void moveTo(MemoryUseOrDef *What, BasicBlock *BB, WhereType Where); + // Move all memory accesses from `From` to `To` starting at `Start`. + // Restrictions apply, see public wrappers of this method. + void moveAllAccesses(BasicBlock *From, BasicBlock *To, Instruction *Start); + MemoryAccess *getPreviousDef(MemoryAccess *); + MemoryAccess *getPreviousDefInBlock(MemoryAccess *); + MemoryAccess * + getPreviousDefFromEnd(BasicBlock *, + DenseMap<BasicBlock *, TrackingVH<MemoryAccess>> &); + MemoryAccess * + getPreviousDefRecursive(BasicBlock *, + DenseMap<BasicBlock *, TrackingVH<MemoryAccess>> &); + MemoryAccess *recursePhi(MemoryAccess *Phi); + MemoryAccess *tryRemoveTrivialPhi(MemoryPhi *Phi); + template <class RangeType> + MemoryAccess *tryRemoveTrivialPhi(MemoryPhi *Phi, RangeType &Operands); + void tryRemoveTrivialPhis(ArrayRef<WeakVH> UpdatedPHIs); + void fixupDefs(const SmallVectorImpl<WeakVH> &); + // Clone all uses and defs from BB to NewBB given a 1:1 map of all + // instructions and blocks cloned, and a map of MemoryPhi : Definition + // (MemoryAccess Phi or Def). VMap maps old instructions to cloned + // instructions and old blocks to cloned blocks. MPhiMap, is created in the + // caller of this private method, and maps existing MemoryPhis to new + // definitions that new MemoryAccesses must point to. These definitions may + // not necessarily be MemoryPhis themselves, they may be MemoryDefs. As such, + // the map is between MemoryPhis and MemoryAccesses, where the MemoryAccesses + // may be MemoryPhis or MemoryDefs and not MemoryUses. + // If CloneWasSimplified = true, the clone was exact. Otherwise, assume that + // the clone involved simplifications that may have: (1) turned a MemoryUse + // into an instruction that MemorySSA has no representation for, or (2) turned + // a MemoryDef into a MemoryUse or an instruction that MemorySSA has no + // representation for. No other cases are supported. + void cloneUsesAndDefs(BasicBlock *BB, BasicBlock *NewBB, + const ValueToValueMapTy &VMap, PhiToDefMap &MPhiMap, + bool CloneWasSimplified = false); + template <typename Iter> + void privateUpdateExitBlocksForClonedLoop(ArrayRef<BasicBlock *> ExitBlocks, + Iter ValuesBegin, Iter ValuesEnd, + DominatorTree &DT); + void applyInsertUpdates(ArrayRef<CFGUpdate>, DominatorTree &DT, + const GraphDiff<BasicBlock *> *GD); +}; +} // end namespace llvm + +#endif // LLVM_ANALYSIS_MEMORYSSAUPDATER_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/ModuleSummaryAnalysis.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/ModuleSummaryAnalysis.h new file mode 100644 index 0000000..1572a49 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/ModuleSummaryAnalysis.h
@@ -0,0 +1,80 @@ +//===- ModuleSummaryAnalysis.h - Module summary index builder ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// \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/Optional.h" +#include "llvm/IR/ModuleSummaryIndex.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Pass.h" +#include <functional> + +namespace llvm { + +class BlockFrequencyInfo; +class Function; +class Module; +class ProfileSummaryInfo; + +/// Direct function to compute a \c ModuleSummaryIndex from a given module. +/// +/// If operating within a pass manager which has defined ways to compute the \c +/// BlockFrequencyInfo for a given function, that can be provided via +/// a std::function callback. Otherwise, this routine will manually construct +/// that information. +ModuleSummaryIndex buildModuleSummaryIndex( + const Module &M, + std::function<BlockFrequencyInfo *(const Function &F)> GetBFICallback, + ProfileSummaryInfo *PSI); + +/// Analysis pass to provide the ModuleSummaryIndex object. +class ModuleSummaryIndexAnalysis + : public AnalysisInfoMixin<ModuleSummaryIndexAnalysis> { + friend AnalysisInfoMixin<ModuleSummaryIndexAnalysis>; + + static AnalysisKey Key; + +public: + using Result = ModuleSummaryIndex; + + Result run(Module &M, ModuleAnalysisManager &AM); +}; + +/// Legacy wrapper pass to provide the ModuleSummaryIndex object. +class ModuleSummaryIndexWrapperPass : public ModulePass { + Optional<ModuleSummaryIndex> Index; + +public: + static char ID; + + ModuleSummaryIndexWrapperPass(); + + /// Get the index built by pass + ModuleSummaryIndex &getIndex() { return *Index; } + const ModuleSummaryIndex &getIndex() const { return *Index; } + + 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(); + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_MODULESUMMARYANALYSIS_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/MustExecute.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/MustExecute.h new file mode 100644 index 0000000..d88cdf4 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/MustExecute.h
@@ -0,0 +1,501 @@ +//===- MustExecute.h - Is an instruction known to execute--------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// \file +/// Contains a collection of routines for determining if a given instruction is +/// guaranteed to execute if a given point in control flow is reached. The most +/// common example is an instruction within a loop being provably executed if we +/// branch to the header of it's containing loop. +/// +/// There are two interfaces available to determine if an instruction is +/// executed once a given point in the control flow is reached: +/// 1) A loop-centric one derived from LoopSafetyInfo. +/// 2) A "must be executed context"-based one implemented in the +/// MustBeExecutedContextExplorer. +/// Please refer to the class comments for more information. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_MUSTEXECUTE_H +#define LLVM_ANALYSIS_MUSTEXECUTE_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/Analysis/EHPersonalities.h" +#include "llvm/Analysis/InstructionPrecedenceTracking.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Dominators.h" +#include "llvm/IR/Instruction.h" + +namespace llvm { + +namespace { +template <typename T> using GetterTy = std::function<T *(const Function &F)>; +} + +class Instruction; +class DominatorTree; +class PostDominatorTree; +class Loop; + +/// Captures loop safety information. +/// It keep information for loop blocks may throw exception or otherwise +/// exit abnormaly on any iteration of the loop which might actually execute +/// at runtime. The primary way to consume this infromation is via +/// isGuaranteedToExecute below, but some callers bailout or fallback to +/// alternate reasoning if a loop contains any implicit control flow. +/// NOTE: LoopSafetyInfo contains cached information regarding loops and their +/// particular blocks. This information is only dropped on invocation of +/// computeLoopSafetyInfo. If the loop or any of its block is deleted, or if +/// any thrower instructions have been added or removed from them, or if the +/// control flow has changed, or in case of other meaningful modifications, the +/// LoopSafetyInfo needs to be recomputed. If a meaningful modifications to the +/// loop were made and the info wasn't recomputed properly, the behavior of all +/// methods except for computeLoopSafetyInfo is undefined. +class LoopSafetyInfo { + // Used to update funclet bundle operands. + DenseMap<BasicBlock *, ColorVector> BlockColors; + +protected: + /// Computes block colors. + void computeBlockColors(const Loop *CurLoop); + +public: + /// Returns block colors map that is used to update funclet operand bundles. + const DenseMap<BasicBlock *, ColorVector> &getBlockColors() const; + + /// Copy colors of block \p Old into the block \p New. + void copyColors(BasicBlock *New, BasicBlock *Old); + + /// Returns true iff the block \p BB potentially may throw exception. It can + /// be false-positive in cases when we want to avoid complex analysis. + virtual bool blockMayThrow(const BasicBlock *BB) const = 0; + + /// Returns true iff any block of the loop for which this info is contains an + /// instruction that may throw or otherwise exit abnormally. + virtual bool anyBlockMayThrow() const = 0; + + /// Return true if we must reach the block \p BB under assumption that the + /// loop \p CurLoop is entered. + bool allLoopPathsLeadToBlock(const Loop *CurLoop, const BasicBlock *BB, + const DominatorTree *DT) const; + + /// Computes safety information for a loop checks loop body & header for + /// the possibility of may throw exception, it takes LoopSafetyInfo and loop + /// as argument. Updates safety information in LoopSafetyInfo argument. + /// Note: This is defined to clear and reinitialize an already initialized + /// LoopSafetyInfo. Some callers rely on this fact. + virtual void computeLoopSafetyInfo(const Loop *CurLoop) = 0; + + /// Returns true if the instruction in a loop is guaranteed to execute at + /// least once (under the assumption that the loop is entered). + virtual bool isGuaranteedToExecute(const Instruction &Inst, + const DominatorTree *DT, + const Loop *CurLoop) const = 0; + + LoopSafetyInfo() = default; + + virtual ~LoopSafetyInfo() = default; +}; + + +/// Simple and conservative implementation of LoopSafetyInfo that can give +/// false-positive answers to its queries in order to avoid complicated +/// analysis. +class SimpleLoopSafetyInfo: public LoopSafetyInfo { + bool MayThrow = false; // The current loop contains an instruction which + // may throw. + bool HeaderMayThrow = false; // Same as previous, but specific to loop header + +public: + virtual bool blockMayThrow(const BasicBlock *BB) const; + + virtual bool anyBlockMayThrow() const; + + virtual void computeLoopSafetyInfo(const Loop *CurLoop); + + virtual bool isGuaranteedToExecute(const Instruction &Inst, + const DominatorTree *DT, + const Loop *CurLoop) const; + + SimpleLoopSafetyInfo() : LoopSafetyInfo() {}; + + virtual ~SimpleLoopSafetyInfo() {}; +}; + +/// This implementation of LoopSafetyInfo use ImplicitControlFlowTracking to +/// give precise answers on "may throw" queries. This implementation uses cache +/// that should be invalidated by calling the methods insertInstructionTo and +/// removeInstruction whenever we modify a basic block's contents by adding or +/// removing instructions. +class ICFLoopSafetyInfo: public LoopSafetyInfo { + bool MayThrow = false; // The current loop contains an instruction which + // may throw. + // Contains information about implicit control flow in this loop's blocks. + mutable ImplicitControlFlowTracking ICF; + // Contains information about instruction that may possibly write memory. + mutable MemoryWriteTracking MW; + +public: + virtual bool blockMayThrow(const BasicBlock *BB) const; + + virtual bool anyBlockMayThrow() const; + + virtual void computeLoopSafetyInfo(const Loop *CurLoop); + + virtual bool isGuaranteedToExecute(const Instruction &Inst, + const DominatorTree *DT, + const Loop *CurLoop) const; + + /// Returns true if we could not execute a memory-modifying instruction before + /// we enter \p BB under assumption that \p CurLoop is entered. + bool doesNotWriteMemoryBefore(const BasicBlock *BB, const Loop *CurLoop) + const; + + /// Returns true if we could not execute a memory-modifying instruction before + /// we execute \p I under assumption that \p CurLoop is entered. + bool doesNotWriteMemoryBefore(const Instruction &I, const Loop *CurLoop) + const; + + /// Inform the safety info that we are planning to insert a new instruction + /// \p Inst into the basic block \p BB. It will make all cache updates to keep + /// it correct after this insertion. + void insertInstructionTo(const Instruction *Inst, const BasicBlock *BB); + + /// Inform safety info that we are planning to remove the instruction \p Inst + /// from its block. It will make all cache updates to keep it correct after + /// this removal. + void removeInstruction(const Instruction *Inst); + + ICFLoopSafetyInfo(DominatorTree *DT) : LoopSafetyInfo(), ICF(DT), MW(DT) {}; + + virtual ~ICFLoopSafetyInfo() {}; +}; + +struct MustBeExecutedContextExplorer; + +/// Must be executed iterators visit stretches of instructions that are +/// guaranteed to be executed together, potentially with other instruction +/// executed in-between. +/// +/// Given the following code, and assuming all statements are single +/// instructions which transfer execution to the successor (see +/// isGuaranteedToTransferExecutionToSuccessor), there are two possible +/// outcomes. If we start the iterator at A, B, or E, we will visit only A, B, +/// and E. If we start at C or D, we will visit all instructions A-E. +/// +/// \code +/// A; +/// B; +/// if (...) { +/// C; +/// D; +/// } +/// E; +/// \endcode +/// +/// +/// Below is the example extneded with instructions F and G. Now we assume F +/// might not transfer execution to it's successor G. As a result we get the +/// following visit sets: +/// +/// Start Instruction | Visit Set +/// A | A, B, E, F +/// B | A, B, E, F +/// C | A, B, C, D, E, F +/// D | A, B, C, D, E, F +/// E | A, B, E, F +/// F | A, B, E, F +/// G | A, B, E, F, G +/// +/// +/// \code +/// A; +/// B; +/// if (...) { +/// C; +/// D; +/// } +/// E; +/// F; // Might not transfer execution to its successor G. +/// G; +/// \endcode +/// +/// +/// A more complex example involving conditionals, loops, break, and continue +/// is shown below. We again assume all instructions will transmit control to +/// the successor and we assume we can prove the inner loop to be finite. We +/// omit non-trivial branch conditions as the exploration is oblivious to them. +/// Constant branches are assumed to be unconditional in the CFG. The resulting +/// visist sets are shown in the table below. +/// +/// \code +/// A; +/// while (true) { +/// B; +/// if (...) +/// C; +/// if (...) +/// continue; +/// D; +/// if (...) +/// break; +/// do { +/// if (...) +/// continue; +/// E; +/// } while (...); +/// F; +/// } +/// G; +/// \endcode +/// +/// Start Instruction | Visit Set +/// A | A, B +/// B | A, B +/// C | A, B, C +/// D | A, B, D +/// E | A, B, D, E, F +/// F | A, B, D, F +/// G | A, B, D, G +/// +/// +/// Note that the examples show optimal visist sets but not necessarily the ones +/// derived by the explorer depending on the available CFG analyses (see +/// MustBeExecutedContextExplorer). Also note that we, depending on the options, +/// the visit set can contain instructions from other functions. +struct MustBeExecutedIterator { + /// Type declarations that make his class an input iterator. + ///{ + typedef const Instruction *value_type; + typedef std::ptrdiff_t difference_type; + typedef const Instruction **pointer; + typedef const Instruction *&reference; + typedef std::input_iterator_tag iterator_category; + ///} + + using ExplorerTy = MustBeExecutedContextExplorer; + + MustBeExecutedIterator(const MustBeExecutedIterator &Other) + : Visited(Other.Visited), Explorer(Other.Explorer), + CurInst(Other.CurInst) {} + + MustBeExecutedIterator(MustBeExecutedIterator &&Other) + : Visited(std::move(Other.Visited)), Explorer(Other.Explorer), + CurInst(Other.CurInst) {} + + MustBeExecutedIterator &operator=(MustBeExecutedIterator &&Other) { + if (this != &Other) { + std::swap(Visited, Other.Visited); + std::swap(CurInst, Other.CurInst); + } + return *this; + } + + ~MustBeExecutedIterator() {} + + /// Pre- and post-increment operators. + ///{ + MustBeExecutedIterator &operator++() { + CurInst = advance(); + return *this; + } + + MustBeExecutedIterator operator++(int) { + MustBeExecutedIterator tmp(*this); + operator++(); + return tmp; + } + ///} + + /// Equality and inequality operators. Note that we ignore the history here. + ///{ + bool operator==(const MustBeExecutedIterator &Other) const { + return CurInst == Other.CurInst; + } + + bool operator!=(const MustBeExecutedIterator &Other) const { + return !(*this == Other); + } + ///} + + /// Return the underlying instruction. + const Instruction *&operator*() { return CurInst; } + const Instruction *getCurrentInst() const { return CurInst; } + + /// Return true if \p I was encountered by this iterator already. + bool count(const Instruction *I) const { return Visited.count(I); } + +private: + using VisitedSetTy = DenseSet<const Instruction *>; + + /// Private constructors. + MustBeExecutedIterator(ExplorerTy &Explorer, const Instruction *I); + + /// Reset the iterator to its initial state pointing at \p I. + void reset(const Instruction *I); + + /// Try to advance one of the underlying positions (Head or Tail). + /// + /// \return The next instruction in the must be executed context, or nullptr + /// if none was found. + const Instruction *advance(); + + /// A set to track the visited instructions in order to deal with endless + /// loops and recursion. + VisitedSetTy Visited; + + /// A reference to the explorer that created this iterator. + ExplorerTy &Explorer; + + /// The instruction we are currently exposing to the user. There is always an + /// instruction that we know is executed with the given program point, + /// initially the program point itself. + const Instruction *CurInst; + + friend struct MustBeExecutedContextExplorer; +}; + +/// A "must be executed context" for a given program point PP is the set of +/// instructions, potentially before and after PP, that are executed always when +/// PP is reached. The MustBeExecutedContextExplorer an interface to explore +/// "must be executed contexts" in a module through the use of +/// MustBeExecutedIterator. +/// +/// The explorer exposes "must be executed iterators" that traverse the must be +/// executed context. There is little information sharing between iterators as +/// the expected use case involves few iterators for "far apart" instructions. +/// If that changes, we should consider caching more intermediate results. +struct MustBeExecutedContextExplorer { + + /// In the description of the parameters we use PP to denote a program point + /// for which the must be executed context is explored, or put differently, + /// for which the MustBeExecutedIterator is created. + /// + /// \param ExploreInterBlock Flag to indicate if instructions in blocks + /// other than the parent of PP should be + /// explored. + MustBeExecutedContextExplorer( + bool ExploreInterBlock, + GetterTy<const LoopInfo> LIGetter = + [](const Function &) { return nullptr; }, + GetterTy<const PostDominatorTree> PDTGetter = + [](const Function &) { return nullptr; }) + : ExploreInterBlock(ExploreInterBlock), LIGetter(LIGetter), + PDTGetter(PDTGetter), EndIterator(*this, nullptr) {} + + /// Clean up the dynamically allocated iterators. + ~MustBeExecutedContextExplorer() { + DeleteContainerSeconds(InstructionIteratorMap); + } + + /// Iterator-based interface. \see MustBeExecutedIterator. + ///{ + using iterator = MustBeExecutedIterator; + using const_iterator = const MustBeExecutedIterator; + + /// Return an iterator to explore the context around \p PP. + iterator &begin(const Instruction *PP) { + auto *&It = InstructionIteratorMap[PP]; + if (!It) + It = new iterator(*this, PP); + return *It; + } + + /// Return an iterator to explore the cached context around \p PP. + const_iterator &begin(const Instruction *PP) const { + return *InstructionIteratorMap.lookup(PP); + } + + /// Return an universal end iterator. + ///{ + iterator &end() { return EndIterator; } + iterator &end(const Instruction *) { return EndIterator; } + + const_iterator &end() const { return EndIterator; } + const_iterator &end(const Instruction *) const { return EndIterator; } + ///} + + /// Return an iterator range to explore the context around \p PP. + llvm::iterator_range<iterator> range(const Instruction *PP) { + return llvm::make_range(begin(PP), end(PP)); + } + + /// Return an iterator range to explore the cached context around \p PP. + llvm::iterator_range<const_iterator> range(const Instruction *PP) const { + return llvm::make_range(begin(PP), end(PP)); + } + ///} + + /// Helper to look for \p I in the context of \p PP. + /// + /// The context is expanded until \p I was found or no more expansion is + /// possible. + /// + /// \returns True, iff \p I was found. + bool findInContextOf(const Instruction *I, const Instruction *PP) { + auto EIt = begin(PP), EEnd = end(PP); + return findInContextOf(I, EIt, EEnd); + } + + /// Helper to look for \p I in the context defined by \p EIt and \p EEnd. + /// + /// The context is expanded until \p I was found or no more expansion is + /// possible. + /// + /// \returns True, iff \p I was found. + bool findInContextOf(const Instruction *I, iterator &EIt, iterator &EEnd) { + bool Found = EIt.count(I); + while (!Found && EIt != EEnd) + Found = (++EIt).getCurrentInst() == I; + return Found; + } + + /// Return the next instruction that is guaranteed to be executed after \p PP. + /// + /// \param It The iterator that is used to traverse the must be + /// executed context. + /// \param PP The program point for which the next instruction + /// that is guaranteed to execute is determined. + const Instruction * + getMustBeExecutedNextInstruction(MustBeExecutedIterator &It, + const Instruction *PP); + + /// Find the next join point from \p InitBB in forward direction. + const BasicBlock *findForwardJoinPoint(const BasicBlock *InitBB); + + /// Parameter that limit the performed exploration. See the constructor for + /// their meaning. + ///{ + const bool ExploreInterBlock; + ///} + +private: + /// Getters for common CFG analyses: LoopInfo, DominatorTree, and + /// PostDominatorTree. + ///{ + GetterTy<const LoopInfo> LIGetter; + GetterTy<const PostDominatorTree> PDTGetter; + ///} + + /// Map to cache isGuaranteedToTransferExecutionToSuccessor results. + DenseMap<const BasicBlock *, Optional<bool>> BlockTransferMap; + + /// Map to cache containsIrreducibleCFG results. + DenseMap<const Function*, Optional<bool>> IrreducibleControlMap; + + /// Map from instructions to associated must be executed iterators. + DenseMap<const Instruction *, MustBeExecutedIterator *> + InstructionIteratorMap; + + /// A unique end iterator. + MustBeExecutedIterator EndIterator; +}; + +} // namespace llvm + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/ObjCARCAliasAnalysis.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/ObjCARCAliasAnalysis.h new file mode 100644 index 0000000..b4f4e5f --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/ObjCARCAliasAnalysis.h
@@ -0,0 +1,99 @@ +//===- ObjCARCAliasAnalysis.h - ObjC ARC Alias Analysis ---------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// \file +/// This file declares a simple ARC-aware AliasAnalysis using special knowledge +/// of Objective C to enhance other optimization passes which rely on the Alias +/// Analysis infrastructure. +/// +/// WARNING: This file knows about certain library functions. It recognizes them +/// by name, and hardwires knowledge of their semantics. +/// +/// WARNING: This file knows about how certain Objective-C library functions are +/// used. Naive LLVM IR transformations which would otherwise be +/// behavior-preserving may break these assumptions. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_OBJCARCALIASANALYSIS_H +#define LLVM_ANALYSIS_OBJCARCALIASANALYSIS_H + +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Pass.h" + +namespace llvm { +namespace objcarc { + +/// This is a simple alias analysis implementation that uses knowledge +/// of ARC constructs to answer queries. +/// +/// TODO: This class could be generalized to know about other ObjC-specific +/// tricks. Such as knowing that ivars in the non-fragile ABI are non-aliasing +/// even though their offsets are dynamic. +class ObjCARCAAResult : public AAResultBase<ObjCARCAAResult> { + friend AAResultBase<ObjCARCAAResult>; + + const DataLayout &DL; + +public: + explicit ObjCARCAAResult(const DataLayout &DL) : AAResultBase(), DL(DL) {} + ObjCARCAAResult(ObjCARCAAResult &&Arg) + : AAResultBase(std::move(Arg)), DL(Arg.DL) {} + + /// Handle invalidation events from the new pass manager. + /// + /// By definition, this result is stateless and so remains valid. + bool invalidate(Function &, const PreservedAnalyses &, + FunctionAnalysisManager::Invalidator &) { + return false; + } + + AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB, + AAQueryInfo &AAQI); + bool pointsToConstantMemory(const MemoryLocation &Loc, AAQueryInfo &AAQI, + bool OrLocal); + + using AAResultBase::getModRefBehavior; + FunctionModRefBehavior getModRefBehavior(const Function *F); + + using AAResultBase::getModRefInfo; + ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc, + AAQueryInfo &AAQI); +}; + +/// Analysis pass providing a never-invalidated alias analysis result. +class ObjCARCAA : public AnalysisInfoMixin<ObjCARCAA> { + friend AnalysisInfoMixin<ObjCARCAA>; + static AnalysisKey Key; + +public: + typedef ObjCARCAAResult Result; + + ObjCARCAAResult run(Function &F, FunctionAnalysisManager &AM); +}; + +/// Legacy wrapper pass to provide the ObjCARCAAResult object. +class ObjCARCAAWrapperPass : public ImmutablePass { + std::unique_ptr<ObjCARCAAResult> Result; + +public: + static char ID; + + ObjCARCAAWrapperPass(); + + ObjCARCAAResult &getResult() { return *Result; } + const ObjCARCAAResult &getResult() const { return *Result; } + + bool doInitialization(Module &M) override; + bool doFinalization(Module &M) override; + void getAnalysisUsage(AnalysisUsage &AU) const override; +}; + +} // namespace objcarc +} // namespace llvm + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h new file mode 100644 index 0000000..522abd7 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h
@@ -0,0 +1,300 @@ +//===- ObjCARCAnalysisUtils.h - ObjC ARC Analysis Utilities -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// \file +/// This file defines common analysis utilities used by the ObjC ARC Optimizer. +/// ARC stands for Automatic Reference Counting and is a system for managing +/// reference counts for objects in Objective C. +/// +/// WARNING: This file knows about certain library functions. It recognizes them +/// by name, and hardwires knowledge of their semantics. +/// +/// WARNING: This file knows about how certain Objective-C library functions are +/// used. Naive LLVM IR transformations which would otherwise be +/// behavior-preserving may break these assumptions. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_ANALYSIS_OBJCARCANALYSISUTILS_H +#define LLVM_LIB_ANALYSIS_OBJCARCANALYSISUTILS_H + +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/ObjCARCInstKind.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/IR/CallSite.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/InstIterator.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/Pass.h" + +namespace llvm { +class raw_ostream; +} + +namespace llvm { +namespace objcarc { + +/// A handy option to enable/disable all ARC Optimizations. +extern bool EnableARCOpts; + +/// Test if the given module looks interesting to run ARC optimization +/// on. +inline bool ModuleHasARC(const Module &M) { + return + M.getNamedValue("llvm.objc.retain") || + M.getNamedValue("llvm.objc.release") || + M.getNamedValue("llvm.objc.autorelease") || + M.getNamedValue("llvm.objc.retainAutoreleasedReturnValue") || + M.getNamedValue("llvm.objc.unsafeClaimAutoreleasedReturnValue") || + M.getNamedValue("llvm.objc.retainBlock") || + M.getNamedValue("llvm.objc.autoreleaseReturnValue") || + M.getNamedValue("llvm.objc.autoreleasePoolPush") || + M.getNamedValue("llvm.objc.loadWeakRetained") || + M.getNamedValue("llvm.objc.loadWeak") || + M.getNamedValue("llvm.objc.destroyWeak") || + M.getNamedValue("llvm.objc.storeWeak") || + M.getNamedValue("llvm.objc.initWeak") || + M.getNamedValue("llvm.objc.moveWeak") || + M.getNamedValue("llvm.objc.copyWeak") || + M.getNamedValue("llvm.objc.retainedObject") || + M.getNamedValue("llvm.objc.unretainedObject") || + M.getNamedValue("llvm.objc.unretainedPointer") || + M.getNamedValue("llvm.objc.clang.arc.use"); +} + +/// This is a wrapper around getUnderlyingObject which also knows how to +/// look through objc_retain and objc_autorelease calls, which we know to return +/// their argument verbatim. +inline const Value *GetUnderlyingObjCPtr(const Value *V, + const DataLayout &DL) { + for (;;) { + V = GetUnderlyingObject(V, DL); + if (!IsForwarding(GetBasicARCInstKind(V))) + break; + V = cast<CallInst>(V)->getArgOperand(0); + } + + return V; +} + +/// A wrapper for GetUnderlyingObjCPtr used for results memoization. +inline const Value * +GetUnderlyingObjCPtrCached(const Value *V, const DataLayout &DL, + DenseMap<const Value *, WeakTrackingVH> &Cache) { + if (auto InCache = Cache.lookup(V)) + return InCache; + + const Value *Computed = GetUnderlyingObjCPtr(V, DL); + Cache[V] = const_cast<Value *>(Computed); + return Computed; +} + +/// The RCIdentity root of a value \p V is a dominating value U for which +/// retaining or releasing U is equivalent to retaining or releasing V. In other +/// words, ARC operations on \p V are equivalent to ARC operations on \p U. +/// +/// We use this in the ARC optimizer to make it easier to match up ARC +/// operations by always mapping ARC operations to RCIdentityRoots instead of +/// pointers themselves. +/// +/// The two ways that we see RCIdentical values in ObjC are via: +/// +/// 1. PointerCasts +/// 2. Forwarding Calls that return their argument verbatim. +/// +/// Thus this function strips off pointer casts and forwarding calls. *NOTE* +/// This implies that two RCIdentical values must alias. +inline const Value *GetRCIdentityRoot(const Value *V) { + for (;;) { + V = V->stripPointerCasts(); + if (!IsForwarding(GetBasicARCInstKind(V))) + break; + V = cast<CallInst>(V)->getArgOperand(0); + } + return V; +} + +/// Helper which calls const Value *GetRCIdentityRoot(const Value *V) and just +/// casts away the const of the result. For documentation about what an +/// RCIdentityRoot (and by extension GetRCIdentityRoot is) look at that +/// function. +inline Value *GetRCIdentityRoot(Value *V) { + return const_cast<Value *>(GetRCIdentityRoot((const Value *)V)); +} + +/// Assuming the given instruction is one of the special calls such as +/// objc_retain or objc_release, return the RCIdentity root of the argument of +/// the call. +inline Value *GetArgRCIdentityRoot(Value *Inst) { + return GetRCIdentityRoot(cast<CallInst>(Inst)->getArgOperand(0)); +} + +inline bool IsNullOrUndef(const Value *V) { + return isa<ConstantPointerNull>(V) || isa<UndefValue>(V); +} + +inline bool IsNoopInstruction(const Instruction *I) { + return isa<BitCastInst>(I) || + (isa<GetElementPtrInst>(I) && + cast<GetElementPtrInst>(I)->hasAllZeroIndices()); +} + +/// Test whether the given value is possible a retainable object pointer. +inline bool IsPotentialRetainableObjPtr(const Value *Op) { + // Pointers to static or stack storage are not valid retainable object + // pointers. + if (isa<Constant>(Op) || isa<AllocaInst>(Op)) + return false; + // Special arguments can not be a valid retainable object pointer. + if (const Argument *Arg = dyn_cast<Argument>(Op)) + if (Arg->hasByValAttr() || + Arg->hasInAllocaAttr() || + Arg->hasNestAttr() || + Arg->hasStructRetAttr()) + return false; + // Only consider values with pointer types. + // + // It seemes intuitive to exclude function pointer types as well, since + // functions are never retainable object pointers, however clang occasionally + // bitcasts retainable object pointers to function-pointer type temporarily. + PointerType *Ty = dyn_cast<PointerType>(Op->getType()); + if (!Ty) + return false; + // Conservatively assume anything else is a potential retainable object + // pointer. + return true; +} + +inline bool IsPotentialRetainableObjPtr(const Value *Op, + AliasAnalysis &AA) { + // First make the rudimentary check. + if (!IsPotentialRetainableObjPtr(Op)) + return false; + + // Objects in constant memory are not reference-counted. + if (AA.pointsToConstantMemory(Op)) + return false; + + // Pointers in constant memory are not pointing to reference-counted objects. + if (const LoadInst *LI = dyn_cast<LoadInst>(Op)) + if (AA.pointsToConstantMemory(LI->getPointerOperand())) + return false; + + // Otherwise assume the worst. + return true; +} + +/// Helper for GetARCInstKind. Determines what kind of construct CS +/// is. +inline ARCInstKind GetCallSiteClass(ImmutableCallSite CS) { + for (ImmutableCallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end(); + I != E; ++I) + if (IsPotentialRetainableObjPtr(*I)) + return CS.onlyReadsMemory() ? ARCInstKind::User : ARCInstKind::CallOrUser; + + return CS.onlyReadsMemory() ? ARCInstKind::None : ARCInstKind::Call; +} + +/// Return true if this value refers to a distinct and identifiable +/// object. +/// +/// This is similar to AliasAnalysis's isIdentifiedObject, except that it uses +/// special knowledge of ObjC conventions. +inline bool IsObjCIdentifiedObject(const Value *V) { + // Assume that call results and arguments have their own "provenance". + // Constants (including GlobalVariables) and Allocas are never + // reference-counted. + if (isa<CallInst>(V) || isa<InvokeInst>(V) || + isa<Argument>(V) || isa<Constant>(V) || + isa<AllocaInst>(V)) + return true; + + if (const LoadInst *LI = dyn_cast<LoadInst>(V)) { + const Value *Pointer = + GetRCIdentityRoot(LI->getPointerOperand()); + if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Pointer)) { + // A constant pointer can't be pointing to an object on the heap. It may + // be reference-counted, but it won't be deleted. + if (GV->isConstant()) + return true; + StringRef Name = GV->getName(); + // These special variables are known to hold values which are not + // reference-counted pointers. + if (Name.startswith("\01l_objc_msgSend_fixup_")) + return true; + + StringRef Section = GV->getSection(); + if (Section.find("__message_refs") != StringRef::npos || + Section.find("__objc_classrefs") != StringRef::npos || + Section.find("__objc_superrefs") != StringRef::npos || + Section.find("__objc_methname") != StringRef::npos || + Section.find("__cstring") != StringRef::npos) + return true; + } + } + + return false; +} + +enum class ARCMDKindID { + ImpreciseRelease, + CopyOnEscape, + NoObjCARCExceptions, +}; + +/// A cache of MDKinds used by various ARC optimizations. +class ARCMDKindCache { + Module *M; + + /// The Metadata Kind for clang.imprecise_release metadata. + llvm::Optional<unsigned> ImpreciseReleaseMDKind; + + /// The Metadata Kind for clang.arc.copy_on_escape metadata. + llvm::Optional<unsigned> CopyOnEscapeMDKind; + + /// The Metadata Kind for clang.arc.no_objc_arc_exceptions metadata. + llvm::Optional<unsigned> NoObjCARCExceptionsMDKind; + +public: + void init(Module *Mod) { + M = Mod; + ImpreciseReleaseMDKind = NoneType::None; + CopyOnEscapeMDKind = NoneType::None; + NoObjCARCExceptionsMDKind = NoneType::None; + } + + unsigned get(ARCMDKindID ID) { + switch (ID) { + case ARCMDKindID::ImpreciseRelease: + if (!ImpreciseReleaseMDKind) + ImpreciseReleaseMDKind = + M->getContext().getMDKindID("clang.imprecise_release"); + return *ImpreciseReleaseMDKind; + case ARCMDKindID::CopyOnEscape: + if (!CopyOnEscapeMDKind) + CopyOnEscapeMDKind = + M->getContext().getMDKindID("clang.arc.copy_on_escape"); + return *CopyOnEscapeMDKind; + case ARCMDKindID::NoObjCARCExceptions: + if (!NoObjCARCExceptionsMDKind) + NoObjCARCExceptionsMDKind = + M->getContext().getMDKindID("clang.arc.no_objc_arc_exceptions"); + return *NoObjCARCExceptionsMDKind; + } + llvm_unreachable("Covered switch isn't covered?!"); + } +}; + +} // end namespace objcarc +} // end namespace llvm + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/ObjCARCInstKind.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/ObjCARCInstKind.h new file mode 100644 index 0000000..dc6093a --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/ObjCARCInstKind.h
@@ -0,0 +1,128 @@ +//===- ObjCARCInstKind.h - ARC instruction equivalence classes --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_OBJCARCINSTKIND_H +#define LLVM_ANALYSIS_OBJCARCINSTKIND_H + +#include "llvm/IR/Function.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/IR/Instructions.h" + +namespace llvm { +namespace objcarc { + +/// \enum ARCInstKind +/// +/// Equivalence classes of instructions in the ARC Model. +/// +/// Since we do not have "instructions" to represent ARC concepts in LLVM IR, +/// we instead operate on equivalence classes of instructions. +/// +/// TODO: This should be split into two enums: a runtime entry point enum +/// (possibly united with the ARCRuntimeEntrypoint class) and an enum that deals +/// with effects of instructions in the ARC model (which would handle the notion +/// of a User or CallOrUser). +enum class ARCInstKind { + Retain, ///< objc_retain + RetainRV, ///< objc_retainAutoreleasedReturnValue + ClaimRV, ///< objc_unsafeClaimAutoreleasedReturnValue + RetainBlock, ///< objc_retainBlock + Release, ///< objc_release + Autorelease, ///< objc_autorelease + AutoreleaseRV, ///< objc_autoreleaseReturnValue + AutoreleasepoolPush, ///< objc_autoreleasePoolPush + AutoreleasepoolPop, ///< objc_autoreleasePoolPop + NoopCast, ///< objc_retainedObject, etc. + FusedRetainAutorelease, ///< objc_retainAutorelease + FusedRetainAutoreleaseRV, ///< objc_retainAutoreleaseReturnValue + LoadWeakRetained, ///< objc_loadWeakRetained (primitive) + StoreWeak, ///< objc_storeWeak (primitive) + InitWeak, ///< objc_initWeak (derived) + LoadWeak, ///< objc_loadWeak (derived) + MoveWeak, ///< objc_moveWeak (derived) + CopyWeak, ///< objc_copyWeak (derived) + DestroyWeak, ///< objc_destroyWeak (derived) + StoreStrong, ///< objc_storeStrong (derived) + IntrinsicUser, ///< llvm.objc.clang.arc.use + CallOrUser, ///< could call objc_release and/or "use" pointers + Call, ///< could call objc_release + User, ///< could "use" a pointer + None ///< anything that is inert from an ARC perspective. +}; + +raw_ostream &operator<<(raw_ostream &OS, const ARCInstKind Class); + +/// Test if the given class is a kind of user. +bool IsUser(ARCInstKind Class); + +/// Test if the given class is objc_retain or equivalent. +bool IsRetain(ARCInstKind Class); + +/// Test if the given class is objc_autorelease or equivalent. +bool IsAutorelease(ARCInstKind Class); + +/// Test if the given class represents instructions which return their +/// argument verbatim. +bool IsForwarding(ARCInstKind Class); + +/// Test if the given class represents instructions which do nothing if +/// passed a null pointer. +bool IsNoopOnNull(ARCInstKind Class); + +/// Test if the given class represents instructions which do nothing if +/// passed a global variable. +bool IsNoopOnGlobal(ARCInstKind Class); + +/// Test if the given class represents instructions which are always safe +/// to mark with the "tail" keyword. +bool IsAlwaysTail(ARCInstKind Class); + +/// Test if the given class represents instructions which are never safe +/// to mark with the "tail" keyword. +bool IsNeverTail(ARCInstKind Class); + +/// Test if the given class represents instructions which are always safe +/// to mark with the nounwind attribute. +bool IsNoThrow(ARCInstKind Class); + +/// Test whether the given instruction can autorelease any pointer or cause an +/// autoreleasepool pop. +bool CanInterruptRV(ARCInstKind Class); + +/// Determine if F is one of the special known Functions. If it isn't, +/// return ARCInstKind::CallOrUser. +ARCInstKind GetFunctionClass(const Function *F); + +/// Determine which objc runtime call instruction class V belongs to. +/// +/// This is similar to GetARCInstKind except that it only detects objc +/// runtime calls. This allows it to be faster. +/// +inline ARCInstKind GetBasicARCInstKind(const Value *V) { + if (const CallInst *CI = dyn_cast<CallInst>(V)) { + if (const Function *F = CI->getCalledFunction()) + return GetFunctionClass(F); + // Otherwise, be conservative. + return ARCInstKind::CallOrUser; + } + + // Otherwise, be conservative. + return isa<InvokeInst>(V) ? ARCInstKind::CallOrUser : ARCInstKind::User; +} + +/// Map V to its ARCInstKind equivalence class. +ARCInstKind GetARCInstKind(const Value *V); + +/// Returns false if conservatively we can prove that any instruction mapped to +/// this kind can not decrement ref counts. Returns true otherwise. +bool CanDecrementRefCount(ARCInstKind Kind); + +} // end namespace objcarc +} // end namespace llvm + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/OptimizationRemarkEmitter.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/OptimizationRemarkEmitter.h new file mode 100644 index 0000000..7b84044 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/OptimizationRemarkEmitter.h
@@ -0,0 +1,167 @@ +//===- OptimizationRemarkEmitter.h - Optimization Diagnostic ----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// 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/Analysis/BlockFrequencyInfo.h" +#include "llvm/IR/DiagnosticInfo.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Pass.h" + +namespace llvm { +class DebugLoc; +class Loop; +class Pass; +class Twine; +class Value; + +/// The optimization diagnostic interface. +/// +/// It allows reporting when optimizations are performed and when they are not +/// along with the reasons for it. Hotness information of the corresponding +/// code region can be included in the remark if DiagnosticsHotnessRequested is +/// enabled in the LLVM context. +class OptimizationRemarkEmitter { +public: + OptimizationRemarkEmitter(const Function *F, BlockFrequencyInfo *BFI) + : F(F), BFI(BFI) {} + + /// This variant can be used to generate ORE on demand (without the + /// analysis pass). + /// + /// Note that this ctor has a very different cost depending on whether + /// F->getContext().getDiagnosticsHotnessRequested() is on or not. If it's off + /// the operation is free. + /// + /// Whereas if DiagnosticsHotnessRequested is on, it is fairly expensive + /// operation since BFI and all its required analyses are computed. This is + /// for example useful for CGSCC passes that can't use function analyses + /// passes in the old PM. + OptimizationRemarkEmitter(const Function *F); + + OptimizationRemarkEmitter(OptimizationRemarkEmitter &&Arg) + : F(Arg.F), BFI(Arg.BFI) {} + + OptimizationRemarkEmitter &operator=(OptimizationRemarkEmitter &&RHS) { + F = RHS.F; + BFI = RHS.BFI; + return *this; + } + + /// Handle invalidation events in the new pass manager. + bool invalidate(Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &Inv); + + /// Output the remark via the diagnostic handler and to the + /// optimization record file. + void emit(DiagnosticInfoOptimizationBase &OptDiag); + + /// Take a lambda that returns a remark which will be emitted. Second + /// argument is only used to restrict this to functions. + template <typename T> + void emit(T RemarkBuilder, decltype(RemarkBuilder()) * = nullptr) { + // Avoid building the remark unless we know there are at least *some* + // remarks enabled. We can't currently check whether remarks are requested + // for the calling pass since that requires actually building the remark. + + if (F->getContext().getRemarkStreamer() || + F->getContext().getDiagHandlerPtr()->isAnyRemarkEnabled()) { + auto R = RemarkBuilder(); + emit((DiagnosticInfoOptimizationBase &)R); + } + } + + /// Whether we allow for extra compile-time budget to perform more + /// analysis to produce fewer false positives. + /// + /// This is useful when reporting missed optimizations. In this case we can + /// use the extra analysis (1) to filter trivial false positives or (2) to + /// provide more context so that non-trivial false positives can be quickly + /// detected by the user. + bool allowExtraAnalysis(StringRef PassName) const { + return (F->getContext().getRemarkStreamer() || + F->getContext().getDiagHandlerPtr()->isAnyRemarkEnabled(PassName)); + } + +private: + const Function *F; + + BlockFrequencyInfo *BFI; + + /// If we generate BFI on demand, we need to free it when ORE is freed. + std::unique_ptr<BlockFrequencyInfo> OwnedBFI; + + /// Compute hotness from IR value (currently assumed to be a block) if PGO is + /// available. + Optional<uint64_t> computeHotness(const Value *V); + + /// Similar but use value from \p OptDiag and update hotness there. + void computeHotness(DiagnosticInfoIROptimization &OptDiag); + + /// Only allow verbose messages if we know we're filtering by hotness + /// (BFI is only set in this case). + bool shouldEmitVerbose() { return BFI != nullptr; } + + OptimizationRemarkEmitter(const OptimizationRemarkEmitter &) = delete; + void operator=(const OptimizationRemarkEmitter &) = delete; +}; + +/// Add a small namespace to avoid name clashes with the classes used in +/// the streaming interface. We want these to be short for better +/// write/readability. +namespace ore { +using NV = DiagnosticInfoOptimizationBase::Argument; +using setIsVerbose = DiagnosticInfoOptimizationBase::setIsVerbose; +using setExtraArgs = DiagnosticInfoOptimizationBase::setExtraArgs; +} + +/// OptimizationRemarkEmitter legacy analysis pass +/// +/// Note that this pass shouldn't generally be marked as preserved by other +/// passes. It's holding onto BFI, so if the pass does not preserve BFI, BFI +/// could be freed. +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 AnalysisKey Key; + +public: + /// Provide the result typedef for this analysis pass. + typedef OptimizationRemarkEmitter Result; + + /// Run the analysis pass over a function and produce BFI. + Result run(Function &F, FunctionAnalysisManager &AM); +}; +} +#endif // LLVM_IR_OPTIMIZATIONDIAGNOSTICINFO_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/OrderedBasicBlock.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/OrderedBasicBlock.h new file mode 100644 index 0000000..ae64c01 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/OrderedBasicBlock.h
@@ -0,0 +1,74 @@ +//===- llvm/Analysis/OrderedBasicBlock.h --------------------- -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the OrderedBasicBlock class. OrderedBasicBlock maintains +// an interface where clients can query if one instruction comes before another +// in a BasicBlock. Since BasicBlock currently lacks a reliable way to query +// relative position between instructions one can use OrderedBasicBlock to do +// such queries. OrderedBasicBlock is lazily built on a source BasicBlock and +// maintains an internal Instruction -> Position map. A OrderedBasicBlock +// instance should be discarded whenever the source BasicBlock changes. +// +// It's currently used by the CaptureTracker in order to find relative +// positions of a pair of instructions inside a BasicBlock. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_ORDEREDBASICBLOCK_H +#define LLVM_ANALYSIS_ORDEREDBASICBLOCK_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/IR/BasicBlock.h" + +namespace llvm { + +class Instruction; +class BasicBlock; + +class OrderedBasicBlock { +private: + /// Map a instruction to its position in a BasicBlock. + SmallDenseMap<const Instruction *, unsigned, 32> NumberedInsts; + + /// Keep track of last instruction inserted into \p NumberedInsts. + /// It speeds up queries for uncached instructions by providing a start point + /// for new queries in OrderedBasicBlock::comesBefore. + BasicBlock::const_iterator LastInstFound; + + /// The position/number to tag the next instruction to be found. + unsigned NextInstPos; + + /// The source BasicBlock to map. + const BasicBlock *BB; + + /// Given no cached results, find if \p A comes before \p B in \p BB. + /// Cache and number out instruction while walking \p BB. + bool comesBefore(const Instruction *A, const Instruction *B); + +public: + OrderedBasicBlock(const BasicBlock *BasicB); + + /// Find out whether \p A dominates \p B, meaning whether \p A + /// comes before \p B in \p BB. This is a simplification that considers + /// cached instruction positions and ignores other basic blocks, being + /// only relevant to compare relative instructions positions inside \p BB. + /// Returns false for A == B. + bool dominates(const Instruction *A, const Instruction *B); + + /// Remove \p from the ordering, if it is present. + void eraseInstruction(const Instruction *I); + + /// Replace \p Old with \p New in the ordering. \p New is assigned the + /// numbering of \p Old, so it must be inserted at the same position in the + /// IR. + void replaceInstruction(const Instruction *Old, const Instruction *New); +}; + +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/OrderedInstructions.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/OrderedInstructions.h new file mode 100644 index 0000000..967b146 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/OrderedInstructions.h
@@ -0,0 +1,64 @@ +//===- llvm/Transforms/Utils/OrderedInstructions.h -------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines an efficient way to check for dominance relation between 2 +// instructions. +// +// This interface dispatches to appropriate dominance check given 2 +// instructions, i.e. in case the instructions are in the same basic block, +// OrderedBasicBlock (with instruction numbering and caching) are used. +// Otherwise, dominator tree is used. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_ORDEREDINSTRUCTIONS_H +#define LLVM_ANALYSIS_ORDEREDINSTRUCTIONS_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/Analysis/OrderedBasicBlock.h" +#include "llvm/IR/Dominators.h" +#include "llvm/IR/Operator.h" + +namespace llvm { + +class OrderedInstructions { + /// Used to check dominance for instructions in same basic block. + mutable DenseMap<const BasicBlock *, std::unique_ptr<OrderedBasicBlock>> + OBBMap; + + /// The dominator tree of the parent function. + DominatorTree *DT; + + /// Return true if the first instruction comes before the second in the + /// same basic block. It will create an ordered basic block, if it does + /// not yet exist in OBBMap. + bool localDominates(const Instruction *, const Instruction *) const; + +public: + /// Constructor. + OrderedInstructions(DominatorTree *DT) : DT(DT) {} + + /// Return true if first instruction dominates the second. + bool dominates(const Instruction *, const Instruction *) const; + + /// Return true if the first instruction comes before the second in the + /// dominator tree DFS traversal if they are in different basic blocks, + /// or if the first instruction comes before the second in the same basic + /// block. + bool dfsBefore(const Instruction *, const Instruction *) const; + + /// Invalidate the OrderedBasicBlock cache when its basic block changes. + /// i.e. If an instruction is deleted or added to the basic block, the user + /// should call this function to invalidate the OrderedBasicBlock cache for + /// this basic block. + void invalidateBlock(const BasicBlock *BB) { OBBMap.erase(BB); } +}; + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_ORDEREDINSTRUCTIONS_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/PHITransAddr.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/PHITransAddr.h new file mode 100644 index 0000000..54a07f0 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/PHITransAddr.h
@@ -0,0 +1,126 @@ +//===- PHITransAddr.h - PHI Translation for Addresses -----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file declares the PHITransAddr class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_PHITRANSADDR_H +#define LLVM_ANALYSIS_PHITRANSADDR_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/IR/Instruction.h" + +namespace llvm { + class AssumptionCache; + class DominatorTree; + class DataLayout; + class TargetLibraryInfo; + +/// PHITransAddr - An address value which tracks and handles phi translation. +/// As we walk "up" the CFG through predecessors, we need to ensure that the +/// address we're tracking is kept up to date. For example, if we're analyzing +/// an address of "&A[i]" and walk through the definition of 'i' which is a PHI +/// node, we *must* phi translate i to get "&A[j]" or else we will analyze an +/// incorrect pointer in the predecessor block. +/// +/// This is designed to be a relatively small object that lives on the stack and +/// is copyable. +/// +class PHITransAddr { + /// Addr - The actual address we're analyzing. + Value *Addr; + + /// The DataLayout we are playing with. + const DataLayout &DL; + + /// TLI - The target library info if known, otherwise null. + const TargetLibraryInfo *TLI; + + /// A cache of \@llvm.assume calls used by SimplifyInstruction. + AssumptionCache *AC; + + /// InstInputs - The inputs for our symbolic address. + SmallVector<Instruction*, 4> InstInputs; + +public: + PHITransAddr(Value *addr, const DataLayout &DL, AssumptionCache *AC) + : Addr(addr), DL(DL), TLI(nullptr), AC(AC) { + // If the address is an instruction, the whole thing is considered an input. + if (Instruction *I = dyn_cast<Instruction>(Addr)) + InstInputs.push_back(I); + } + + Value *getAddr() const { return Addr; } + + /// NeedsPHITranslationFromBlock - Return true if moving from the specified + /// BasicBlock to its predecessors requires PHI translation. + bool NeedsPHITranslationFromBlock(BasicBlock *BB) const { + // We do need translation if one of our input instructions is defined in + // this block. + for (unsigned i = 0, e = InstInputs.size(); i != e; ++i) + if (InstInputs[i]->getParent() == BB) + return true; + return false; + } + + /// IsPotentiallyPHITranslatable - If this needs PHI translation, return true + /// if we have some hope of doing it. This should be used as a filter to + /// avoid calling PHITranslateValue in hopeless situations. + bool IsPotentiallyPHITranslatable() const; + + /// PHITranslateValue - PHI translate the current address up the CFG from + /// CurBB to Pred, updating our state to reflect any needed changes. If + /// 'MustDominate' is true, the translated value must dominate + /// PredBB. This returns true on failure and sets Addr to null. + bool PHITranslateValue(BasicBlock *CurBB, BasicBlock *PredBB, + const DominatorTree *DT, bool MustDominate); + + /// PHITranslateWithInsertion - PHI translate this value into the specified + /// predecessor block, inserting a computation of the value if it is + /// unavailable. + /// + /// All newly created instructions are added to the NewInsts list. This + /// returns null on failure. + /// + Value *PHITranslateWithInsertion(BasicBlock *CurBB, BasicBlock *PredBB, + const DominatorTree &DT, + SmallVectorImpl<Instruction *> &NewInsts); + + void dump() const; + + /// Verify - Check internal consistency of this data structure. If the + /// structure is valid, it returns true. If invalid, it prints errors and + /// returns false. + bool Verify() const; + +private: + Value *PHITranslateSubExpr(Value *V, BasicBlock *CurBB, BasicBlock *PredBB, + const DominatorTree *DT); + + /// InsertPHITranslatedSubExpr - Insert a computation of the PHI translated + /// version of 'V' for the edge PredBB->CurBB into the end of the PredBB + /// block. All newly created instructions are added to the NewInsts list. + /// This returns null on failure. + /// + Value *InsertPHITranslatedSubExpr(Value *InVal, BasicBlock *CurBB, + BasicBlock *PredBB, const DominatorTree &DT, + SmallVectorImpl<Instruction *> &NewInsts); + + /// AddAsInput - If the specified value is an instruction, add it as an input. + Value *AddAsInput(Value *V) { + // If V is an instruction, it is now an input. + if (Instruction *VI = dyn_cast<Instruction>(V)) + InstInputs.push_back(VI); + return V; + } +}; + +} // end namespace llvm + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/Passes.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/Passes.h new file mode 100644 index 0000000..8562519 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/Passes.h
@@ -0,0 +1,115 @@ +//===-- llvm/Analysis/Passes.h - Constructors for analyses ------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This header file defines prototypes for accessor functions that expose passes +// in the analysis libraries. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_PASSES_H +#define LLVM_ANALYSIS_PASSES_H + +namespace llvm { + class FunctionPass; + class ImmutablePass; + class LoopPass; + class ModulePass; + class Pass; + class PassInfo; + + //===--------------------------------------------------------------------===// + // + // createObjCARCAAWrapperPass - This pass implements ObjC-ARC-based + // alias analysis. + // + ImmutablePass *createObjCARCAAWrapperPass(); + + FunctionPass *createPAEvalPass(); + + //===--------------------------------------------------------------------===// + // + /// createLazyValueInfoPass - This creates an instance of the LazyValueInfo + /// pass. + FunctionPass *createLazyValueInfoPass(); + + //===--------------------------------------------------------------------===// + // + // createDependenceAnalysisWrapperPass - This creates an instance of the + // DependenceAnalysisWrapper pass. + // + FunctionPass *createDependenceAnalysisWrapperPass(); + + //===--------------------------------------------------------------------===// + // + // createCostModelAnalysisPass - This creates an instance of the + // CostModelAnalysis pass. + // + FunctionPass *createCostModelAnalysisPass(); + + //===--------------------------------------------------------------------===// + // + // createDelinearizationPass - This pass implements attempts to restore + // multidimensional array indices from linearized expressions. + // + FunctionPass *createDelinearizationPass(); + + //===--------------------------------------------------------------------===// + // + // createLegacyDivergenceAnalysisPass - This pass determines which branches in a GPU + // program are divergent. + // + FunctionPass *createLegacyDivergenceAnalysisPass(); + + //===--------------------------------------------------------------------===// + // + // Minor pass prototypes, allowing us to expose them through bugpoint and + // analyze. + FunctionPass *createInstCountPass(); + + //===--------------------------------------------------------------------===// + // + // createRegionInfoPass - This pass finds all single entry single exit regions + // in a function and builds the region hierarchy. + // + FunctionPass *createRegionInfoPass(); + + // Print module-level debug info metadata in human-readable form. + ModulePass *createModuleDebugInfoPrinterPass(); + + //===--------------------------------------------------------------------===// + // + // createMemDepPrinter - This pass exhaustively collects all memdep + // information and prints it with -analyze. + // + FunctionPass *createMemDepPrinter(); + + //===--------------------------------------------------------------------===// + // + // createMemDerefPrinter - This pass collects memory dereferenceability + // information and prints it with -analyze. + // + FunctionPass *createMemDerefPrinter(); + + //===--------------------------------------------------------------------===// + // + // createMustExecutePrinter - This pass collects information about which + // instructions within a loop are guaranteed to execute if the loop header is + // entered and prints it with -analyze. + // + FunctionPass *createMustExecutePrinter(); + + //===--------------------------------------------------------------------===// + // + // createMustBeExecutedContextPrinter - This pass prints information about which + // instructions are guaranteed to execute together (run with -analyze). + // + ModulePass *createMustBeExecutedContextPrinter(); + +} + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/PhiValues.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/PhiValues.h new file mode 100644 index 0000000..ee6eec8 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/PhiValues.h
@@ -0,0 +1,158 @@ +//===- PhiValues.h - Phi Value Analysis -------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the PhiValues class, and associated passes, which can be +// used to find the underlying values of the phis in a function, i.e. the +// non-phi values that can be found by traversing the phi graph. +// +// This information is computed lazily and cached. If new phis are added to the +// function they are handled correctly, but if an existing phi has its operands +// modified PhiValues has to be notified by calling invalidateValue. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_PHIVALUES_H +#define LLVM_ANALYSIS_PHIVALUES_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/IR/PassManager.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/Pass.h" + +namespace llvm { + +class Use; +class Value; +class PHINode; +class Function; + +/// Class for calculating and caching the underlying values of phis in a +/// function. +/// +/// Initially the PhiValues is empty, and gets incrementally populated whenever +/// it is queried. +class PhiValues { +public: + using ValueSet = SmallPtrSet<Value *, 4>; + + /// Construct an empty PhiValues. + PhiValues(const Function &F) : F(F) {} + + /// Get the underlying values of a phi. + /// + /// This returns the cached value if PN has previously been processed, + /// otherwise it processes it first. + const ValueSet &getValuesForPhi(const PHINode *PN); + + /// Notify PhiValues that the cached information using V is no longer valid + /// + /// Whenever a phi has its operands modified the cached values for that phi + /// (and the phis that use that phi) become invalid. A user of PhiValues has + /// to notify it of this by calling invalidateValue on either the operand or + /// the phi, which will then clear the relevant cached information. + void invalidateValue(const Value *V); + + /// Free the memory used by this class. + void releaseMemory(); + + /// Print out the values currently in the cache. + void print(raw_ostream &OS) const; + + /// Handle invalidation events in the new pass manager. + bool invalidate(Function &, const PreservedAnalyses &, + FunctionAnalysisManager::Invalidator &); + +private: + using PhiSet = SmallPtrSet<const PHINode *, 4>; + using ConstValueSet = SmallPtrSet<const Value *, 4>; + + /// The next depth number to be used by processPhi. + unsigned int NextDepthNumber = 1; + + /// Depth numbers of phis. Phis with the same depth number are part of the + /// same strongly connected component. + DenseMap<const PHINode *, unsigned int> DepthMap; + + /// Non-phi values reachable from each component. + DenseMap<unsigned int, ValueSet> NonPhiReachableMap; + + /// All values reachable from each component. + DenseMap<unsigned int, ConstValueSet> ReachableMap; + + /// A CallbackVH to notify PhiValues when a value is deleted or replaced, so + /// that the cached information for that value can be cleared to avoid + /// dangling pointers to invalid values. + class PhiValuesCallbackVH final : public CallbackVH { + PhiValues *PV; + void deleted() override; + void allUsesReplacedWith(Value *New) override; + + public: + PhiValuesCallbackVH(Value *V, PhiValues *PV = nullptr) + : CallbackVH(V), PV(PV) {} + }; + + /// A set of callbacks to the values that processPhi has seen. + DenseSet<PhiValuesCallbackVH, DenseMapInfo<Value *>> TrackedValues; + + /// The function that the PhiValues is for. + const Function &F; + + /// Process a phi so that its entries in the depth and reachable maps are + /// fully populated. + void processPhi(const PHINode *PN, SmallVectorImpl<const PHINode *> &Stack); +}; + +/// The analysis pass which yields a PhiValues +/// +/// The analysis does nothing by itself, and just returns an empty PhiValues +/// which will get filled in as it's used. +class PhiValuesAnalysis : public AnalysisInfoMixin<PhiValuesAnalysis> { + friend AnalysisInfoMixin<PhiValuesAnalysis>; + static AnalysisKey Key; + +public: + using Result = PhiValues; + PhiValues run(Function &F, FunctionAnalysisManager &); +}; + +/// A pass for printing the PhiValues for a function. +/// +/// This pass doesn't print whatever information the PhiValues happens to hold, +/// but instead first uses the PhiValues to analyze all the phis in the function +/// so the complete information is printed. +class PhiValuesPrinterPass : public PassInfoMixin<PhiValuesPrinterPass> { + raw_ostream &OS; + +public: + explicit PhiValuesPrinterPass(raw_ostream &OS) : OS(OS) {} + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + +/// Wrapper pass for the legacy pass manager +class PhiValuesWrapperPass : public FunctionPass { + std::unique_ptr<PhiValues> Result; + +public: + static char ID; + PhiValuesWrapperPass(); + + PhiValues &getResult() { return *Result; } + const PhiValues &getResult() const { return *Result; } + + bool runOnFunction(Function &F) override; + void releaseMemory() override; + void getAnalysisUsage(AnalysisUsage &AU) const override; +}; + +} // namespace llvm + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/PostDominators.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/PostDominators.h new file mode 100644 index 0000000..801eb3d --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/PostDominators.h
@@ -0,0 +1,120 @@ +//=- llvm/Analysis/PostDominators.h - Post Dominator Calculation --*- C++ -*-=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file exposes interfaces to post dominance information. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_POSTDOMINATORS_H +#define LLVM_ANALYSIS_POSTDOMINATORS_H + +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/IR/Dominators.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Pass.h" + +namespace llvm { + +class Function; +class raw_ostream; + +/// PostDominatorTree Class - Concrete subclass of DominatorTree that is used to +/// compute the post-dominator tree. +class PostDominatorTree : public PostDomTreeBase<BasicBlock> { +public: + using Base = PostDomTreeBase<BasicBlock>; + + PostDominatorTree() = default; + explicit PostDominatorTree(Function &F) { recalculate(F); } + /// Handle invalidation explicitly. + bool invalidate(Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &); + + // Ensure base-class overloads are visible. + using Base::dominates; + + /// Return true if \p I1 dominates \p I2. This checks if \p I2 comes before + /// \p I1 if they belongs to the same basic block. + bool dominates(const Instruction *I1, const Instruction *I2) const; +}; + +/// Analysis pass which computes a \c PostDominatorTree. +class PostDominatorTreeAnalysis + : public AnalysisInfoMixin<PostDominatorTreeAnalysis> { + friend AnalysisInfoMixin<PostDominatorTreeAnalysis>; + + static AnalysisKey Key; + +public: + /// Provide the result type for this analysis pass. + using Result = PostDominatorTree; + + /// Run the analysis pass over a function and produce a post dominator + /// tree. + PostDominatorTree run(Function &F, FunctionAnalysisManager &); +}; + +/// Printer pass for the \c PostDominatorTree. +class PostDominatorTreePrinterPass + : public PassInfoMixin<PostDominatorTreePrinterPass> { + raw_ostream &OS; + +public: + explicit PostDominatorTreePrinterPass(raw_ostream &OS); + + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + +struct PostDominatorTreeWrapperPass : public FunctionPass { + static char ID; // Pass identification, replacement for typeid + + PostDominatorTree DT; + + PostDominatorTreeWrapperPass(); + + PostDominatorTree &getPostDomTree() { return DT; } + const PostDominatorTree &getPostDomTree() const { return DT; } + + bool runOnFunction(Function &F) override; + + void verifyAnalysis() const override; + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + } + + void releaseMemory() override { + DT.releaseMemory(); + } + + void print(raw_ostream &OS, const Module*) const override; +}; + +FunctionPass* createPostDomTree(); + +template <> struct GraphTraits<PostDominatorTree*> + : public GraphTraits<DomTreeNode*> { + static NodeRef getEntryNode(PostDominatorTree *DT) { + return DT->getRootNode(); + } + + static nodes_iterator nodes_begin(PostDominatorTree *N) { + if (getEntryNode(N)) + return df_begin(getEntryNode(N)); + else + return df_end(getEntryNode(N)); + } + + static nodes_iterator nodes_end(PostDominatorTree *N) { + return df_end(getEntryNode(N)); + } +}; + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_POSTDOMINATORS_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/ProfileSummaryInfo.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/ProfileSummaryInfo.h new file mode 100644 index 0000000..6693e40 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/ProfileSummaryInfo.h
@@ -0,0 +1,201 @@ +//===- llvm/Analysis/ProfileSummaryInfo.h - profile summary ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// 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 BasicBlock; +class BlockFrequencyInfo; +class CallSite; +class ProfileSummary; +/// 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; + bool computeSummary(); + void computeThresholds(); + // Count thresholds to answer isHotCount and isColdCount queries. + Optional<uint64_t> HotCountThreshold, ColdCountThreshold; + // True if the working set size of the code is considered huge, + // because the number of profile counts required to reach the hot + // percentile is above a huge threshold. + Optional<bool> HasHugeWorkingSetSize; + // True if the working set size of the code is considered large, + // because the number of profile counts required to reach the hot + // percentile is above a large threshold. + Optional<bool> HasLargeWorkingSetSize; + // Compute the threshold for a given cutoff. + Optional<uint64_t> computeThreshold(int PercentileCutoff); + // The map that caches the threshold values. The keys are the percentile + // cutoff values and the values are the corresponding threshold values. + DenseMap<int, uint64_t> ThresholdCache; + +public: + ProfileSummaryInfo(Module &M) : M(M) {} + ProfileSummaryInfo(ProfileSummaryInfo &&Arg) + : M(Arg.M), Summary(std::move(Arg.Summary)) {} + + /// Returns true if profile summary is available. + bool hasProfileSummary() { return computeSummary(); } + + /// Returns true if module \c M has sample profile. + bool hasSampleProfile() { + return hasProfileSummary() && + Summary->getKind() == ProfileSummary::PSK_Sample; + } + + /// Returns true if module \c M has instrumentation profile. + bool hasInstrumentationProfile() { + return hasProfileSummary() && + Summary->getKind() == ProfileSummary::PSK_Instr; + } + + /// Returns true if module \c M has context sensitive instrumentation profile. + bool hasCSInstrumentationProfile() { + return hasProfileSummary() && + Summary->getKind() == ProfileSummary::PSK_CSInstr; + } + + /// Handle the invalidation of this information. + /// + /// When used as a result of \c ProfileSummaryAnalysis this method will be + /// called when the module this was computed for changes. Since profile + /// summary is immutable after it is annotated on the module, we return false + /// here. + bool invalidate(Module &, const PreservedAnalyses &, + ModuleAnalysisManager::Invalidator &) { + return false; + } + + /// Returns the profile count for \p CallInst. + Optional<uint64_t> getProfileCount(const Instruction *CallInst, + BlockFrequencyInfo *BFI, + bool AllowSynthetic = false); + /// Returns true if the working set size of the code is considered huge. + bool hasHugeWorkingSetSize(); + /// Returns true if the working set size of the code is considered large. + bool hasLargeWorkingSetSize(); + /// Returns true if \p F has hot function entry. + bool isFunctionEntryHot(const Function *F); + /// Returns true if \p F contains hot code. + bool isFunctionHotInCallGraph(const Function *F, BlockFrequencyInfo &BFI); + /// Returns true if \p F has cold function entry. + bool isFunctionEntryCold(const Function *F); + /// Returns true if \p F contains only cold code. + bool isFunctionColdInCallGraph(const Function *F, BlockFrequencyInfo &BFI); + /// Returns true if \p F contains hot code with regard to a given hot + /// percentile cutoff value. + bool isFunctionHotInCallGraphNthPercentile(int PercentileCutoff, + const Function *F, + BlockFrequencyInfo &BFI); + /// Returns true if count \p C is considered hot. + bool isHotCount(uint64_t C); + /// Returns true if count \p C is considered cold. + bool isColdCount(uint64_t C); + /// Returns true if count \p C is considered hot with regard to a given + /// hot percentile cutoff value. + bool isHotCountNthPercentile(int PercentileCutoff, uint64_t C); + /// Returns true if BasicBlock \p BB is considered hot. + bool isHotBlock(const BasicBlock *BB, BlockFrequencyInfo *BFI); + /// Returns true if BasicBlock \p BB is considered cold. + bool isColdBlock(const BasicBlock *BB, BlockFrequencyInfo *BFI); + /// Returns true if BasicBlock \p BB is considered hot with regard to a given + /// hot percentile cutoff value. + bool isHotBlockNthPercentile(int PercentileCutoff, + const BasicBlock *BB, BlockFrequencyInfo *BFI); + /// Returns true if CallSite \p CS is considered hot. + bool isHotCallSite(const CallSite &CS, BlockFrequencyInfo *BFI); + /// Returns true if Callsite \p CS is considered cold. + bool isColdCallSite(const CallSite &CS, BlockFrequencyInfo *BFI); + /// Returns HotCountThreshold if set. Recompute HotCountThreshold + /// if not set. + uint64_t getOrCompHotCountThreshold(); + /// Returns ColdCountThreshold if set. Recompute HotCountThreshold + /// if not set. + uint64_t getOrCompColdCountThreshold(); + /// Returns HotCountThreshold if set. + uint64_t getHotCountThreshold() { + return HotCountThreshold ? HotCountThreshold.getValue() : 0; + } + /// Returns ColdCountThreshold if set. + uint64_t getColdCountThreshold() { + return ColdCountThreshold ? ColdCountThreshold.getValue() : 0; + } +}; + +/// 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() { return *PSI; } + const ProfileSummaryInfo &getPSI() const { return *PSI; } + + bool doInitialization(Module &M) override; + bool doFinalization(Module &M) override; + 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; + + Result run(Module &M, ModuleAnalysisManager &); + +private: + friend AnalysisInfoMixin<ProfileSummaryAnalysis>; + static AnalysisKey Key; +}; + +/// 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, ModuleAnalysisManager &AM); +}; + +} // end namespace llvm + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/PtrUseVisitor.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/PtrUseVisitor.h new file mode 100644 index 0000000..05bca22 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/PtrUseVisitor.h
@@ -0,0 +1,306 @@ +//===- PtrUseVisitor.h - InstVisitors over a pointers uses ------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +/// \file +/// This file provides a collection of visitors which walk the (instruction) +/// uses of a pointer. These visitors all provide the same essential behavior +/// as an InstVisitor with similar template-based flexibility and +/// implementation strategies. +/// +/// These can be used, for example, to quickly analyze the uses of an alloca, +/// global variable, or function argument. +/// +/// FIXME: Provide a variant which doesn't track offsets and is cheaper. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_PTRUSEVISITOR_H +#define LLVM_ANALYSIS_PTRUSEVISITOR_H + +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/IR/CallSite.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/InstVisitor.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/Use.h" +#include "llvm/IR/User.h" +#include "llvm/Support/Casting.h" +#include <algorithm> +#include <cassert> +#include <type_traits> + +namespace llvm { + +namespace detail { + +/// Implementation of non-dependent functionality for \c PtrUseVisitor. +/// +/// See \c PtrUseVisitor for the public interface and detailed comments about +/// usage. This class is just a helper base class which is not templated and +/// contains all common code to be shared between different instantiations of +/// PtrUseVisitor. +class PtrUseVisitorBase { +public: + /// This class provides information about the result of a visit. + /// + /// After walking all the users (recursively) of a pointer, the basic + /// infrastructure records some commonly useful information such as escape + /// analysis and whether the visit completed or aborted early. + class PtrInfo { + public: + PtrInfo() : AbortedInfo(nullptr, false), EscapedInfo(nullptr, false) {} + + /// Reset the pointer info, clearing all state. + void reset() { + AbortedInfo.setPointer(nullptr); + AbortedInfo.setInt(false); + EscapedInfo.setPointer(nullptr); + EscapedInfo.setInt(false); + } + + /// Did we abort the visit early? + bool isAborted() const { return AbortedInfo.getInt(); } + + /// Is the pointer escaped at some point? + bool isEscaped() const { return EscapedInfo.getInt(); } + + /// Get the instruction causing the visit to abort. + /// \returns a pointer to the instruction causing the abort if one is + /// available; otherwise returns null. + Instruction *getAbortingInst() const { return AbortedInfo.getPointer(); } + + /// Get the instruction causing the pointer to escape. + /// \returns a pointer to the instruction which escapes the pointer if one + /// is available; otherwise returns null. + Instruction *getEscapingInst() const { return EscapedInfo.getPointer(); } + + /// Mark the visit as aborted. Intended for use in a void return. + /// \param I The instruction which caused the visit to abort, if available. + void setAborted(Instruction *I = nullptr) { + AbortedInfo.setInt(true); + AbortedInfo.setPointer(I); + } + + /// Mark the pointer as escaped. Intended for use in a void return. + /// \param I The instruction which escapes the pointer, if available. + void setEscaped(Instruction *I = nullptr) { + EscapedInfo.setInt(true); + EscapedInfo.setPointer(I); + } + + /// Mark the pointer as escaped, and the visit as aborted. Intended + /// for use in a void return. + /// \param I The instruction which both escapes the pointer and aborts the + /// visit, if available. + void setEscapedAndAborted(Instruction *I = nullptr) { + setEscaped(I); + setAborted(I); + } + + private: + PointerIntPair<Instruction *, 1, bool> AbortedInfo, EscapedInfo; + }; + +protected: + const DataLayout &DL; + + /// \name Visitation infrastructure + /// @{ + + /// The info collected about the pointer being visited thus far. + PtrInfo PI; + + /// A struct of the data needed to visit a particular use. + /// + /// This is used to maintain a worklist fo to-visit uses. This is used to + /// make the visit be iterative rather than recursive. + struct UseToVisit { + using UseAndIsOffsetKnownPair = PointerIntPair<Use *, 1, bool>; + + UseAndIsOffsetKnownPair UseAndIsOffsetKnown; + APInt Offset; + }; + + /// The worklist of to-visit uses. + SmallVector<UseToVisit, 8> Worklist; + + /// A set of visited uses to break cycles in unreachable code. + SmallPtrSet<Use *, 8> VisitedUses; + + /// @} + + /// \name Per-visit state + /// This state is reset for each instruction visited. + /// @{ + + /// The use currently being visited. + Use *U; + + /// True if we have a known constant offset for the use currently + /// being visited. + bool IsOffsetKnown; + + /// The constant offset of the use if that is known. + APInt Offset; + + /// @} + + /// Note that the constructor is protected because this class must be a base + /// class, we can't create instances directly of this class. + PtrUseVisitorBase(const DataLayout &DL) : DL(DL) {} + + /// Enqueue the users of this instruction in the visit worklist. + /// + /// This will visit the users with the same offset of the current visit + /// (including an unknown offset if that is the current state). + void enqueueUsers(Instruction &I); + + /// Walk the operands of a GEP and adjust the offset as appropriate. + /// + /// This routine does the heavy lifting of the pointer walk by computing + /// offsets and looking through GEPs. + bool adjustOffsetForGEP(GetElementPtrInst &GEPI); +}; + +} // end namespace detail + +/// A base class for visitors over the uses of a pointer value. +/// +/// Once constructed, a user can call \c visit on a pointer value, and this +/// will walk its uses and visit each instruction using an InstVisitor. It also +/// provides visit methods which will recurse through any pointer-to-pointer +/// transformations such as GEPs and bitcasts. +/// +/// During the visit, the current Use* being visited is available to the +/// subclass, as well as the current offset from the original base pointer if +/// known. +/// +/// The recursive visit of uses is accomplished with a worklist, so the only +/// ordering guarantee is that an instruction is visited before any uses of it +/// are visited. Note that this does *not* mean before any of its users are +/// visited! This is because users can be visited multiple times due to +/// multiple, different uses of pointers derived from the same base. +/// +/// A particular Use will only be visited once, but a User may be visited +/// multiple times, once per Use. This visits may notably have different +/// offsets. +/// +/// All visit methods on the underlying InstVisitor return a boolean. This +/// return short-circuits the visit, stopping it immediately. +/// +/// FIXME: Generalize this for all values rather than just instructions. +template <typename DerivedT> +class PtrUseVisitor : protected InstVisitor<DerivedT>, + public detail::PtrUseVisitorBase { + friend class InstVisitor<DerivedT>; + + using Base = InstVisitor<DerivedT>; + +public: + PtrUseVisitor(const DataLayout &DL) : PtrUseVisitorBase(DL) { + static_assert(std::is_base_of<PtrUseVisitor, DerivedT>::value, + "Must pass the derived type to this template!"); + } + + /// Recursively visit the uses of the given pointer. + /// \returns An info struct about the pointer. See \c PtrInfo for details. + PtrInfo visitPtr(Instruction &I) { + // This must be a pointer type. Get an integer type suitable to hold + // offsets on this pointer. + // FIXME: Support a vector of pointers. + assert(I.getType()->isPointerTy()); + IntegerType *IntIdxTy = cast<IntegerType>(DL.getIndexType(I.getType())); + IsOffsetKnown = true; + Offset = APInt(IntIdxTy->getBitWidth(), 0); + PI.reset(); + + // Enqueue the uses of this pointer. + enqueueUsers(I); + + // Visit all the uses off the worklist until it is empty. + while (!Worklist.empty()) { + UseToVisit ToVisit = Worklist.pop_back_val(); + U = ToVisit.UseAndIsOffsetKnown.getPointer(); + IsOffsetKnown = ToVisit.UseAndIsOffsetKnown.getInt(); + if (IsOffsetKnown) + Offset = std::move(ToVisit.Offset); + + Instruction *I = cast<Instruction>(U->getUser()); + static_cast<DerivedT*>(this)->visit(I); + if (PI.isAborted()) + break; + } + return PI; + } + +protected: + void visitStoreInst(StoreInst &SI) { + if (SI.getValueOperand() == U->get()) + PI.setEscaped(&SI); + } + + void visitBitCastInst(BitCastInst &BC) { + enqueueUsers(BC); + } + + void visitAddrSpaceCastInst(AddrSpaceCastInst &ASC) { + enqueueUsers(ASC); + } + + void visitPtrToIntInst(PtrToIntInst &I) { + PI.setEscaped(&I); + } + + void visitGetElementPtrInst(GetElementPtrInst &GEPI) { + if (GEPI.use_empty()) + return; + + // If we can't walk the GEP, clear the offset. + if (!adjustOffsetForGEP(GEPI)) { + IsOffsetKnown = false; + Offset = APInt(); + } + + // Enqueue the users now that the offset has been adjusted. + enqueueUsers(GEPI); + } + + // No-op intrinsics which we know don't escape the pointer to logic in + // some other function. + void visitDbgInfoIntrinsic(DbgInfoIntrinsic &I) {} + void visitMemIntrinsic(MemIntrinsic &I) {} + void visitIntrinsicInst(IntrinsicInst &II) { + switch (II.getIntrinsicID()) { + default: + return Base::visitIntrinsicInst(II); + + case Intrinsic::lifetime_start: + case Intrinsic::lifetime_end: + return; // No-op intrinsics. + } + } + + // Generically, arguments to calls and invokes escape the pointer to some + // other function. Mark that. + void visitCallSite(CallSite CS) { + PI.setEscaped(CS.getInstruction()); + Base::visitCallSite(CS); + } +}; + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_PTRUSEVISITOR_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/RegionInfo.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/RegionInfo.h new file mode 100644 index 0000000..8bcc3e8 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/RegionInfo.h
@@ -0,0 +1,1032 @@ +//===- RegionInfo.h - SESE region analysis ----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Calculate a program structure tree built out of single entry single exit +// regions. +// The basic ideas are taken from "The Program Structure Tree - Richard Johnson, +// David Pearson, Keshav Pingali - 1994", however enriched with ideas from "The +// Refined Process Structure Tree - Jussi Vanhatalo, Hagen Voelyer, Jana +// Koehler - 2009". +// The algorithm to calculate these data structures however is completely +// different, as it takes advantage of existing information already available +// in (Post)dominace tree and dominance frontier passes. This leads to a simpler +// and in practice hopefully better performing algorithm. The runtime of the +// algorithms described in the papers above are both linear in graph size, +// O(V+E), whereas this algorithm is not, as the dominance frontier information +// itself is not, but in practice runtime seems to be in the order of magnitude +// of dominance tree calculation. +// +// WARNING: LLVM is generally very concerned about compile time such that +// the use of additional analysis passes in the default +// optimization sequence is avoided as much as possible. +// Specifically, if you do not need the RegionInfo, but dominance +// information could be sufficient please base your work only on +// the dominator tree. Most passes maintain it, such that using +// it has often near zero cost. In contrast RegionInfo is by +// default not available, is not maintained by existing +// transformations and there is no intention to do so. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_REGIONINFO_H +#define LLVM_ANALYSIS_REGIONINFO_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Config/llvm-config.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Dominators.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Pass.h" +#include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cassert> +#include <map> +#include <memory> +#include <set> +#include <string> +#include <type_traits> +#include <vector> + +namespace llvm { + +class DominanceFrontier; +class DominatorTree; +class Loop; +class LoopInfo; +class PostDominatorTree; +class Region; +template <class RegionTr> class RegionBase; +class RegionInfo; +template <class RegionTr> class RegionInfoBase; +class RegionNode; + +// Class to be specialized for different users of RegionInfo +// (i.e. BasicBlocks or MachineBasicBlocks). This is only to avoid needing to +// pass around an unreasonable number of template parameters. +template <class FuncT_> +struct RegionTraits { + // FuncT + // BlockT + // RegionT + // RegionNodeT + // RegionInfoT + using BrokenT = typename FuncT_::UnknownRegionTypeError; +}; + +template <> +struct RegionTraits<Function> { + using FuncT = Function; + using BlockT = BasicBlock; + using RegionT = Region; + using RegionNodeT = RegionNode; + using RegionInfoT = RegionInfo; + using DomTreeT = DominatorTree; + using DomTreeNodeT = DomTreeNode; + using DomFrontierT = DominanceFrontier; + using PostDomTreeT = PostDominatorTree; + using InstT = Instruction; + using LoopT = Loop; + using LoopInfoT = LoopInfo; + + static unsigned getNumSuccessors(BasicBlock *BB) { + return BB->getTerminator()->getNumSuccessors(); + } +}; + +/// Marker class to iterate over the elements of a Region in flat mode. +/// +/// The class is used to either iterate in Flat mode or by not using it to not +/// iterate in Flat mode. During a Flat mode iteration all Regions are entered +/// and the iteration returns every BasicBlock. If the Flat mode is not +/// selected for SubRegions just one RegionNode containing the subregion is +/// returned. +template <class GraphType> +class FlatIt {}; + +/// A RegionNode represents a subregion or a BasicBlock that is part of a +/// Region. +template <class Tr> +class RegionNodeBase { + friend class RegionBase<Tr>; + +public: + using BlockT = typename Tr::BlockT; + using RegionT = typename Tr::RegionT; + +private: + /// This is the entry basic block that starts this region node. If this is a + /// BasicBlock RegionNode, then entry is just the basic block, that this + /// RegionNode represents. Otherwise it is the entry of this (Sub)RegionNode. + /// + /// In the BBtoRegionNode map of the parent of this node, BB will always map + /// to this node no matter which kind of node this one is. + /// + /// The node can hold either a Region or a BasicBlock. + /// Use one bit to save, if this RegionNode is a subregion or BasicBlock + /// RegionNode. + PointerIntPair<BlockT *, 1, bool> entry; + + /// The parent Region of this RegionNode. + /// @see getParent() + RegionT *parent; + +protected: + /// Create a RegionNode. + /// + /// @param Parent The parent of this RegionNode. + /// @param Entry The entry BasicBlock of the RegionNode. If this + /// RegionNode represents a BasicBlock, this is the + /// BasicBlock itself. If it represents a subregion, this + /// is the entry BasicBlock of the subregion. + /// @param isSubRegion If this RegionNode represents a SubRegion. + inline RegionNodeBase(RegionT *Parent, BlockT *Entry, + bool isSubRegion = false) + : entry(Entry, isSubRegion), parent(Parent) {} + +public: + RegionNodeBase(const RegionNodeBase &) = delete; + RegionNodeBase &operator=(const RegionNodeBase &) = delete; + + /// Get the parent Region of this RegionNode. + /// + /// The parent Region is the Region this RegionNode belongs to. If for + /// example a BasicBlock is element of two Regions, there exist two + /// RegionNodes for this BasicBlock. Each with the getParent() function + /// pointing to the Region this RegionNode belongs to. + /// + /// @return Get the parent Region of this RegionNode. + inline RegionT *getParent() const { return parent; } + + /// Get the entry BasicBlock of this RegionNode. + /// + /// If this RegionNode represents a BasicBlock this is just the BasicBlock + /// itself, otherwise we return the entry BasicBlock of the Subregion + /// + /// @return The entry BasicBlock of this RegionNode. + inline BlockT *getEntry() const { return entry.getPointer(); } + + /// Get the content of this RegionNode. + /// + /// This can be either a BasicBlock or a subregion. Before calling getNodeAs() + /// check the type of the content with the isSubRegion() function call. + /// + /// @return The content of this RegionNode. + template <class T> inline T *getNodeAs() const; + + /// Is this RegionNode a subregion? + /// + /// @return True if it contains a subregion. False if it contains a + /// BasicBlock. + inline bool isSubRegion() const { return entry.getInt(); } +}; + +//===----------------------------------------------------------------------===// +/// A single entry single exit Region. +/// +/// A Region is a connected subgraph of a control flow graph that has exactly +/// two connections to the remaining graph. It can be used to analyze or +/// optimize parts of the control flow graph. +/// +/// A <em> simple Region </em> is connected to the remaining graph by just two +/// edges. One edge entering the Region and another one leaving the Region. +/// +/// An <em> extended Region </em> (or just Region) is a subgraph that can be +/// transform into a simple Region. The transformation is done by adding +/// BasicBlocks that merge several entry or exit edges so that after the merge +/// just one entry and one exit edge exists. +/// +/// The \e Entry of a Region is the first BasicBlock that is passed after +/// entering the Region. It is an element of the Region. The entry BasicBlock +/// dominates all BasicBlocks in the Region. +/// +/// The \e Exit of a Region is the first BasicBlock that is passed after +/// leaving the Region. It is not an element of the Region. The exit BasicBlock, +/// postdominates all BasicBlocks in the Region. +/// +/// A <em> canonical Region </em> cannot be constructed by combining smaller +/// Regions. +/// +/// Region A is the \e parent of Region B, if B is completely contained in A. +/// +/// Two canonical Regions either do not intersect at all or one is +/// the parent of the other. +/// +/// The <em> Program Structure Tree</em> is a graph (V, E) where V is the set of +/// Regions in the control flow graph and E is the \e parent relation of these +/// Regions. +/// +/// Example: +/// +/// \verbatim +/// A simple control flow graph, that contains two regions. +/// +/// 1 +/// / | +/// 2 | +/// / \ 3 +/// 4 5 | +/// | | | +/// 6 7 8 +/// \ | / +/// \ |/ Region A: 1 -> 9 {1,2,3,4,5,6,7,8} +/// 9 Region B: 2 -> 9 {2,4,5,6,7} +/// \endverbatim +/// +/// You can obtain more examples by either calling +/// +/// <tt> "opt -regions -analyze anyprogram.ll" </tt> +/// or +/// <tt> "opt -view-regions-only anyprogram.ll" </tt> +/// +/// on any LLVM file you are interested in. +/// +/// The first call returns a textual representation of the program structure +/// tree, the second one creates a graphical representation using graphviz. +template <class Tr> +class RegionBase : public RegionNodeBase<Tr> { + friend class RegionInfoBase<Tr>; + + using FuncT = typename Tr::FuncT; + using BlockT = typename Tr::BlockT; + using RegionInfoT = typename Tr::RegionInfoT; + using RegionT = typename Tr::RegionT; + using RegionNodeT = typename Tr::RegionNodeT; + using DomTreeT = typename Tr::DomTreeT; + using LoopT = typename Tr::LoopT; + using LoopInfoT = typename Tr::LoopInfoT; + using InstT = typename Tr::InstT; + + using BlockTraits = GraphTraits<BlockT *>; + using InvBlockTraits = GraphTraits<Inverse<BlockT *>>; + using SuccIterTy = typename BlockTraits::ChildIteratorType; + using PredIterTy = typename InvBlockTraits::ChildIteratorType; + + // Information necessary to manage this Region. + RegionInfoT *RI; + DomTreeT *DT; + + // The exit BasicBlock of this region. + // (The entry BasicBlock is part of RegionNode) + BlockT *exit; + + using RegionSet = std::vector<std::unique_ptr<RegionT>>; + + // The subregions of this region. + RegionSet children; + + using BBNodeMapT = std::map<BlockT *, std::unique_ptr<RegionNodeT>>; + + // Save the BasicBlock RegionNodes that are element of this Region. + mutable BBNodeMapT BBNodeMap; + + /// Check if a BB is in this Region. This check also works + /// if the region is incorrectly built. (EXPENSIVE!) + void verifyBBInRegion(BlockT *BB) const; + + /// Walk over all the BBs of the region starting from BB and + /// verify that all reachable basic blocks are elements of the region. + /// (EXPENSIVE!) + void verifyWalk(BlockT *BB, std::set<BlockT *> *visitedBB) const; + + /// Verify if the region and its children are valid regions (EXPENSIVE!) + void verifyRegionNest() const; + +public: + /// Create a new region. + /// + /// @param Entry The entry basic block of the region. + /// @param Exit The exit basic block of the region. + /// @param RI The region info object that is managing this region. + /// @param DT The dominator tree of the current function. + /// @param Parent The surrounding region or NULL if this is a top level + /// region. + RegionBase(BlockT *Entry, BlockT *Exit, RegionInfoT *RI, DomTreeT *DT, + RegionT *Parent = nullptr); + + RegionBase(const RegionBase &) = delete; + RegionBase &operator=(const RegionBase &) = delete; + + /// Delete the Region and all its subregions. + ~RegionBase(); + + /// Get the entry BasicBlock of the Region. + /// @return The entry BasicBlock of the region. + BlockT *getEntry() const { + return RegionNodeBase<Tr>::getEntry(); + } + + /// Replace the entry basic block of the region with the new basic + /// block. + /// + /// @param BB The new entry basic block of the region. + void replaceEntry(BlockT *BB); + + /// Replace the exit basic block of the region with the new basic + /// block. + /// + /// @param BB The new exit basic block of the region. + void replaceExit(BlockT *BB); + + /// Recursively replace the entry basic block of the region. + /// + /// This function replaces the entry basic block with a new basic block. It + /// also updates all child regions that have the same entry basic block as + /// this region. + /// + /// @param NewEntry The new entry basic block. + void replaceEntryRecursive(BlockT *NewEntry); + + /// Recursively replace the exit basic block of the region. + /// + /// This function replaces the exit basic block with a new basic block. It + /// also updates all child regions that have the same exit basic block as + /// this region. + /// + /// @param NewExit The new exit basic block. + void replaceExitRecursive(BlockT *NewExit); + + /// Get the exit BasicBlock of the Region. + /// @return The exit BasicBlock of the Region, NULL if this is the TopLevel + /// Region. + BlockT *getExit() const { return exit; } + + /// Get the parent of the Region. + /// @return The parent of the Region or NULL if this is a top level + /// Region. + RegionT *getParent() const { + return RegionNodeBase<Tr>::getParent(); + } + + /// Get the RegionNode representing the current Region. + /// @return The RegionNode representing the current Region. + RegionNodeT *getNode() const { + return const_cast<RegionNodeT *>( + reinterpret_cast<const RegionNodeT *>(this)); + } + + /// Get the nesting level of this Region. + /// + /// An toplevel Region has depth 0. + /// + /// @return The depth of the region. + unsigned getDepth() const; + + /// Check if a Region is the TopLevel region. + /// + /// The toplevel region represents the whole function. + bool isTopLevelRegion() const { return exit == nullptr; } + + /// Return a new (non-canonical) region, that is obtained by joining + /// this region with its predecessors. + /// + /// @return A region also starting at getEntry(), but reaching to the next + /// basic block that forms with getEntry() a (non-canonical) region. + /// NULL if such a basic block does not exist. + RegionT *getExpandedRegion() const; + + /// Return the first block of this region's single entry edge, + /// if existing. + /// + /// @return The BasicBlock starting this region's single entry edge, + /// else NULL. + BlockT *getEnteringBlock() const; + + /// Return the first block of this region's single exit edge, + /// if existing. + /// + /// @return The BasicBlock starting this region's single exit edge, + /// else NULL. + BlockT *getExitingBlock() const; + + /// Collect all blocks of this region's single exit edge, if existing. + /// + /// @return True if this region contains all the predecessors of the exit. + bool getExitingBlocks(SmallVectorImpl<BlockT *> &Exitings) const; + + /// Is this a simple region? + /// + /// A region is simple if it has exactly one exit and one entry edge. + /// + /// @return True if the Region is simple. + bool isSimple() const; + + /// Returns the name of the Region. + /// @return The Name of the Region. + std::string getNameStr() const; + + /// Return the RegionInfo object, that belongs to this Region. + RegionInfoT *getRegionInfo() const { return RI; } + + /// PrintStyle - Print region in difference ways. + enum PrintStyle { PrintNone, PrintBB, PrintRN }; + + /// Print the region. + /// + /// @param OS The output stream the Region is printed to. + /// @param printTree Print also the tree of subregions. + /// @param level The indentation level used for printing. + void print(raw_ostream &OS, bool printTree = true, unsigned level = 0, + PrintStyle Style = PrintNone) const; + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) + /// Print the region to stderr. + void dump() const; +#endif + + /// Check if the region contains a BasicBlock. + /// + /// @param BB The BasicBlock that might be contained in this Region. + /// @return True if the block is contained in the region otherwise false. + bool contains(const BlockT *BB) const; + + /// Check if the region contains another region. + /// + /// @param SubRegion The region that might be contained in this Region. + /// @return True if SubRegion is contained in the region otherwise false. + bool contains(const RegionT *SubRegion) const { + // Toplevel Region. + if (!getExit()) + return true; + + return contains(SubRegion->getEntry()) && + (contains(SubRegion->getExit()) || + SubRegion->getExit() == getExit()); + } + + /// Check if the region contains an Instruction. + /// + /// @param Inst The Instruction that might be contained in this region. + /// @return True if the Instruction is contained in the region otherwise + /// false. + bool contains(const InstT *Inst) const { return contains(Inst->getParent()); } + + /// Check if the region contains a loop. + /// + /// @param L The loop that might be contained in this region. + /// @return True if the loop is contained in the region otherwise false. + /// In case a NULL pointer is passed to this function the result + /// is false, except for the region that describes the whole function. + /// In that case true is returned. + bool contains(const LoopT *L) const; + + /// Get the outermost loop in the region that contains a loop. + /// + /// Find for a Loop L the outermost loop OuterL that is a parent loop of L + /// and is itself contained in the region. + /// + /// @param L The loop the lookup is started. + /// @return The outermost loop in the region, NULL if such a loop does not + /// exist or if the region describes the whole function. + LoopT *outermostLoopInRegion(LoopT *L) const; + + /// Get the outermost loop in the region that contains a basic block. + /// + /// Find for a basic block BB the outermost loop L that contains BB and is + /// itself contained in the region. + /// + /// @param LI A pointer to a LoopInfo analysis. + /// @param BB The basic block surrounded by the loop. + /// @return The outermost loop in the region, NULL if such a loop does not + /// exist or if the region describes the whole function. + LoopT *outermostLoopInRegion(LoopInfoT *LI, BlockT *BB) const; + + /// Get the subregion that starts at a BasicBlock + /// + /// @param BB The BasicBlock the subregion should start. + /// @return The Subregion if available, otherwise NULL. + RegionT *getSubRegionNode(BlockT *BB) const; + + /// Get the RegionNode for a BasicBlock + /// + /// @param BB The BasicBlock at which the RegionNode should start. + /// @return If available, the RegionNode that represents the subregion + /// starting at BB. If no subregion starts at BB, the RegionNode + /// representing BB. + RegionNodeT *getNode(BlockT *BB) const; + + /// Get the BasicBlock RegionNode for a BasicBlock + /// + /// @param BB The BasicBlock for which the RegionNode is requested. + /// @return The RegionNode representing the BB. + RegionNodeT *getBBNode(BlockT *BB) const; + + /// Add a new subregion to this Region. + /// + /// @param SubRegion The new subregion that will be added. + /// @param moveChildren Move the children of this region, that are also + /// contained in SubRegion into SubRegion. + void addSubRegion(RegionT *SubRegion, bool moveChildren = false); + + /// Remove a subregion from this Region. + /// + /// The subregion is not deleted, as it will probably be inserted into another + /// region. + /// @param SubRegion The SubRegion that will be removed. + RegionT *removeSubRegion(RegionT *SubRegion); + + /// Move all direct child nodes of this Region to another Region. + /// + /// @param To The Region the child nodes will be transferred to. + void transferChildrenTo(RegionT *To); + + /// Verify if the region is a correct region. + /// + /// Check if this is a correctly build Region. This is an expensive check, as + /// the complete CFG of the Region will be walked. + void verifyRegion() const; + + /// Clear the cache for BB RegionNodes. + /// + /// After calling this function the BasicBlock RegionNodes will be stored at + /// different memory locations. RegionNodes obtained before this function is + /// called are therefore not comparable to RegionNodes abtained afterwords. + void clearNodeCache(); + + /// @name Subregion Iterators + /// + /// These iterators iterator over all subregions of this Region. + //@{ + using iterator = typename RegionSet::iterator; + using const_iterator = typename RegionSet::const_iterator; + + iterator begin() { return children.begin(); } + iterator end() { return children.end(); } + + const_iterator begin() const { return children.begin(); } + const_iterator end() const { return children.end(); } + //@} + + /// @name BasicBlock Iterators + /// + /// These iterators iterate over all BasicBlocks that are contained in this + /// Region. The iterator also iterates over BasicBlocks that are elements of + /// a subregion of this Region. It is therefore called a flat iterator. + //@{ + template <bool IsConst> + class block_iterator_wrapper + : public df_iterator< + typename std::conditional<IsConst, const BlockT, BlockT>::type *> { + using super = + df_iterator< + typename std::conditional<IsConst, const BlockT, BlockT>::type *>; + + public: + using Self = block_iterator_wrapper<IsConst>; + using value_type = typename super::value_type; + + // Construct the begin iterator. + block_iterator_wrapper(value_type Entry, value_type Exit) + : super(df_begin(Entry)) { + // Mark the exit of the region as visited, so that the children of the + // exit and the exit itself, i.e. the block outside the region will never + // be visited. + super::Visited.insert(Exit); + } + + // Construct the end iterator. + block_iterator_wrapper() : super(df_end<value_type>((BlockT *)nullptr)) {} + + /*implicit*/ block_iterator_wrapper(super I) : super(I) {} + + // FIXME: Even a const_iterator returns a non-const BasicBlock pointer. + // This was introduced for backwards compatibility, but should + // be removed as soon as all users are fixed. + BlockT *operator*() const { + return const_cast<BlockT *>(super::operator*()); + } + }; + + using block_iterator = block_iterator_wrapper<false>; + using const_block_iterator = block_iterator_wrapper<true>; + + block_iterator block_begin() { return block_iterator(getEntry(), getExit()); } + + block_iterator block_end() { return block_iterator(); } + + const_block_iterator block_begin() const { + return const_block_iterator(getEntry(), getExit()); + } + const_block_iterator block_end() const { return const_block_iterator(); } + + using block_range = iterator_range<block_iterator>; + using const_block_range = iterator_range<const_block_iterator>; + + /// Returns a range view of the basic blocks in the region. + inline block_range blocks() { + return block_range(block_begin(), block_end()); + } + + /// Returns a range view of the basic blocks in the region. + /// + /// This is the 'const' version of the range view. + inline const_block_range blocks() const { + return const_block_range(block_begin(), block_end()); + } + //@} + + /// @name Element Iterators + /// + /// These iterators iterate over all BasicBlock and subregion RegionNodes that + /// are direct children of this Region. It does not iterate over any + /// RegionNodes that are also element of a subregion of this Region. + //@{ + using element_iterator = + df_iterator<RegionNodeT *, df_iterator_default_set<RegionNodeT *>, false, + GraphTraits<RegionNodeT *>>; + + using const_element_iterator = + df_iterator<const RegionNodeT *, + df_iterator_default_set<const RegionNodeT *>, false, + GraphTraits<const RegionNodeT *>>; + + element_iterator element_begin(); + element_iterator element_end(); + iterator_range<element_iterator> elements() { + return make_range(element_begin(), element_end()); + } + + const_element_iterator element_begin() const; + const_element_iterator element_end() const; + iterator_range<const_element_iterator> elements() const { + return make_range(element_begin(), element_end()); + } + //@} +}; + +/// Print a RegionNode. +template <class Tr> +inline raw_ostream &operator<<(raw_ostream &OS, const RegionNodeBase<Tr> &Node); + +//===----------------------------------------------------------------------===// +/// Analysis that detects all canonical Regions. +/// +/// The RegionInfo pass detects all canonical regions in a function. The Regions +/// are connected using the parent relation. This builds a Program Structure +/// Tree. +template <class Tr> +class RegionInfoBase { + friend class RegionInfo; + friend class MachineRegionInfo; + + using BlockT = typename Tr::BlockT; + using FuncT = typename Tr::FuncT; + using RegionT = typename Tr::RegionT; + using RegionInfoT = typename Tr::RegionInfoT; + using DomTreeT = typename Tr::DomTreeT; + using DomTreeNodeT = typename Tr::DomTreeNodeT; + using PostDomTreeT = typename Tr::PostDomTreeT; + using DomFrontierT = typename Tr::DomFrontierT; + using BlockTraits = GraphTraits<BlockT *>; + using InvBlockTraits = GraphTraits<Inverse<BlockT *>>; + using SuccIterTy = typename BlockTraits::ChildIteratorType; + using PredIterTy = typename InvBlockTraits::ChildIteratorType; + + using BBtoBBMap = DenseMap<BlockT *, BlockT *>; + using BBtoRegionMap = DenseMap<BlockT *, RegionT *>; + + RegionInfoBase(); + + 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; + } + + virtual ~RegionInfoBase(); + + DomTreeT *DT; + PostDomTreeT *PDT; + DomFrontierT *DF; + + /// The top level region. + RegionT *TopLevelRegion = nullptr; + + /// Map every BB to the smallest region, that contains BB. + BBtoRegionMap BBtoRegion; + +protected: + /// Update refences to a RegionInfoT held by the RegionT managed here + /// + /// This is a post-move helper. Regions hold references to the owning + /// RegionInfo object. After a move these need to be fixed. + template<typename TheRegionT> + void updateRegionTree(RegionInfoT &RI, TheRegionT *R) { + if (!R) + return; + R->RI = &RI; + for (auto &SubR : *R) + updateRegionTree(RI, SubR.get()); + } + +private: + /// 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. + void verifyBBMap(const RegionT *SR) const; + + // Returns true if BB is in the dominance frontier of + // entry, because it was inherited from exit. In the other case there is an + // edge going from entry to BB without passing exit. + bool isCommonDomFrontier(BlockT *BB, BlockT *entry, BlockT *exit) const; + + // Check if entry and exit surround a valid region, based on + // dominance tree and dominance frontier. + bool isRegion(BlockT *entry, BlockT *exit) const; + + // Saves a shortcut pointing from entry to exit. + // This function may extend this shortcut if possible. + void insertShortCut(BlockT *entry, BlockT *exit, BBtoBBMap *ShortCut) const; + + // Returns the next BB that postdominates N, while skipping + // all post dominators that cannot finish a canonical region. + DomTreeNodeT *getNextPostDom(DomTreeNodeT *N, BBtoBBMap *ShortCut) const; + + // A region is trivial, if it contains only one BB. + bool isTrivialRegion(BlockT *entry, BlockT *exit) const; + + // Creates a single entry single exit region. + RegionT *createRegion(BlockT *entry, BlockT *exit); + + // Detect all regions starting with bb 'entry'. + void findRegionsWithEntry(BlockT *entry, BBtoBBMap *ShortCut); + + // Detects regions in F. + void scanForRegions(FuncT &F, BBtoBBMap *ShortCut); + + // Get the top most parent with the same entry block. + RegionT *getTopMostParent(RegionT *region); + + // Build the region hierarchy after all region detected. + void buildRegionsTree(DomTreeNodeT *N, RegionT *region); + + // Update statistic about created regions. + virtual void updateStatistics(RegionT *R) = 0; + + // Detect all regions in function and build the region tree. + void calculate(FuncT &F); + +public: + RegionInfoBase(const RegionInfoBase &) = delete; + RegionInfoBase &operator=(const RegionInfoBase &) = delete; + + static bool VerifyRegionInfo; + static typename RegionT::PrintStyle printStyle; + + void print(raw_ostream &OS) const; +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) + void dump() const; +#endif + + void releaseMemory(); + + /// Get the smallest region that contains a BasicBlock. + /// + /// @param BB The basic block. + /// @return The smallest region, that contains BB or NULL, if there is no + /// region containing BB. + RegionT *getRegionFor(BlockT *BB) const; + + /// Set the smallest region that surrounds a basic block. + /// + /// @param BB The basic block surrounded by a region. + /// @param R The smallest region that surrounds BB. + void setRegionFor(BlockT *BB, RegionT *R); + + /// A shortcut for getRegionFor(). + /// + /// @param BB The basic block. + /// @return The smallest region, that contains BB or NULL, if there is no + /// region containing BB. + RegionT *operator[](BlockT *BB) const; + + /// Return the exit of the maximal refined region, that starts at a + /// BasicBlock. + /// + /// @param BB The BasicBlock the refined region starts. + BlockT *getMaxRegionExit(BlockT *BB) const; + + /// Find the smallest region that contains two regions. + /// + /// @param A The first region. + /// @param B The second region. + /// @return The smallest region containing A and B. + RegionT *getCommonRegion(RegionT *A, RegionT *B) const; + + /// Find the smallest region that contains two basic blocks. + /// + /// @param A The first basic block. + /// @param B The second basic block. + /// @return The smallest region that contains A and B. + RegionT *getCommonRegion(BlockT *A, BlockT *B) const { + return getCommonRegion(getRegionFor(A), getRegionFor(B)); + } + + /// Find the smallest region that contains a set of regions. + /// + /// @param Regions A vector of regions. + /// @return The smallest region that contains all regions in Regions. + RegionT *getCommonRegion(SmallVectorImpl<RegionT *> &Regions) const; + + /// Find the smallest region that contains a set of basic blocks. + /// + /// @param BBs A vector of basic blocks. + /// @return The smallest region that contains all basic blocks in BBS. + RegionT *getCommonRegion(SmallVectorImpl<BlockT *> &BBs) const; + + RegionT *getTopLevelRegion() const { return TopLevelRegion; } + + /// Clear the Node Cache for all Regions. + /// + /// @see Region::clearNodeCache() + void clearNodeCache() { + if (TopLevelRegion) + TopLevelRegion->clearNodeCache(); + } + + void verifyAnalysis() const; +}; + +class Region; + +class RegionNode : public RegionNodeBase<RegionTraits<Function>> { +public: + inline RegionNode(Region *Parent, BasicBlock *Entry, bool isSubRegion = false) + : RegionNodeBase<RegionTraits<Function>>(Parent, Entry, isSubRegion) {} + + bool operator==(const Region &RN) const { + return this == reinterpret_cast<const RegionNode *>(&RN); + } +}; + +class Region : public RegionBase<RegionTraits<Function>> { +public: + Region(BasicBlock *Entry, BasicBlock *Exit, RegionInfo *RI, DominatorTree *DT, + Region *Parent = nullptr); + ~Region(); + + bool operator==(const RegionNode &RN) const { + return &RN == reinterpret_cast<const RegionNode *>(this); + } +}; + +class RegionInfo : public RegionInfoBase<RegionTraits<Function>> { +public: + using Base = RegionInfoBase<RegionTraits<Function>>; + + explicit RegionInfo(); + + RegionInfo(RegionInfo &&Arg) : Base(std::move(static_cast<Base &>(Arg))) { + updateRegionTree(*this, TopLevelRegion); + } + + RegionInfo &operator=(RegionInfo &&RHS) { + Base::operator=(std::move(static_cast<Base &>(RHS))); + updateRegionTree(*this, TopLevelRegion); + return *this; + } + + ~RegionInfo() override; + + /// Handle invalidation explicitly. + bool invalidate(Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &); + + // updateStatistics - Update statistic about created regions. + void updateStatistics(Region *R) final; + + void recalculate(Function &F, DominatorTree *DT, PostDominatorTree *PDT, + DominanceFrontier *DF); + +#ifndef NDEBUG + /// Opens a viewer to show the GraphViz visualization of the regions. + /// + /// Useful during debugging as an alternative to dump(). + void view(); + + /// Opens a viewer to show the GraphViz visualization of this region + /// without instructions in the BasicBlocks. + /// + /// Useful during debugging as an alternative to dump(). + void viewOnly(); +#endif +}; + +class RegionInfoPass : public FunctionPass { + RegionInfo RI; + +public: + static char ID; + + explicit RegionInfoPass(); + ~RegionInfoPass() override; + + RegionInfo &getRegionInfo() { return RI; } + + const RegionInfo &getRegionInfo() const { return RI; } + + /// @name FunctionPass interface + //@{ + bool runOnFunction(Function &F) override; + void releaseMemory() override; + void verifyAnalysis() const override; + void getAnalysisUsage(AnalysisUsage &AU) const override; + void print(raw_ostream &OS, const Module *) const override; + void dump() const; + //@} +}; + +/// Analysis pass that exposes the \c RegionInfo for a function. +class RegionInfoAnalysis : public AnalysisInfoMixin<RegionInfoAnalysis> { + friend AnalysisInfoMixin<RegionInfoAnalysis>; + + static AnalysisKey Key; + +public: + using Result = RegionInfo; + + RegionInfo run(Function &F, FunctionAnalysisManager &AM); +}; + +/// Printer pass for the \c RegionInfo. +class RegionInfoPrinterPass : public PassInfoMixin<RegionInfoPrinterPass> { + raw_ostream &OS; + +public: + explicit RegionInfoPrinterPass(raw_ostream &OS); + + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + +/// Verifier pass for the \c RegionInfo. +struct RegionInfoVerifierPass : PassInfoMixin<RegionInfoVerifierPass> { + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + +template <> +template <> +inline BasicBlock * +RegionNodeBase<RegionTraits<Function>>::getNodeAs<BasicBlock>() const { + assert(!isSubRegion() && "This is not a BasicBlock RegionNode!"); + return getEntry(); +} + +template <> +template <> +inline Region * +RegionNodeBase<RegionTraits<Function>>::getNodeAs<Region>() const { + assert(isSubRegion() && "This is not a subregion RegionNode!"); + auto Unconst = const_cast<RegionNodeBase<RegionTraits<Function>> *>(this); + return reinterpret_cast<Region *>(Unconst); +} + +template <class Tr> +inline raw_ostream &operator<<(raw_ostream &OS, + const RegionNodeBase<Tr> &Node) { + using BlockT = typename Tr::BlockT; + using RegionT = typename Tr::RegionT; + + if (Node.isSubRegion()) + return OS << Node.template getNodeAs<RegionT>()->getNameStr(); + else + return OS << Node.template getNodeAs<BlockT>()->getName(); +} + +extern template class RegionBase<RegionTraits<Function>>; +extern template class RegionNodeBase<RegionTraits<Function>>; +extern template class RegionInfoBase<RegionTraits<Function>>; + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_REGIONINFO_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/RegionInfoImpl.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/RegionInfoImpl.h new file mode 100644 index 0000000..6b59366 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/RegionInfoImpl.h
@@ -0,0 +1,931 @@ +//===- RegionInfoImpl.h - SESE region detection analysis --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Detects single entry single exit regions in the control flow graph. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_REGIONINFOIMPL_H +#define LLVM_ANALYSIS_REGIONINFOIMPL_H + +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Analysis/DominanceFrontier.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/PostDominators.h" +#include "llvm/Analysis/RegionInfo.h" +#include "llvm/Analysis/RegionIterator.h" +#include "llvm/Config/llvm-config.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cassert> +#include <iterator> +#include <memory> +#include <set> +#include <string> +#include <type_traits> +#include <vector> + +#define DEBUG_TYPE "region" + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// RegionBase Implementation +template <class Tr> +RegionBase<Tr>::RegionBase(BlockT *Entry, BlockT *Exit, + typename Tr::RegionInfoT *RInfo, DomTreeT *dt, + RegionT *Parent) + : RegionNodeBase<Tr>(Parent, Entry, 1), RI(RInfo), DT(dt), exit(Exit) {} + +template <class Tr> +RegionBase<Tr>::~RegionBase() { + // Only clean the cache for this Region. Caches of child Regions will be + // cleaned when the child Regions are deleted. + BBNodeMap.clear(); +} + +template <class Tr> +void RegionBase<Tr>::replaceEntry(BlockT *BB) { + this->entry.setPointer(BB); +} + +template <class Tr> +void RegionBase<Tr>::replaceExit(BlockT *BB) { + assert(exit && "No exit to replace!"); + exit = BB; +} + +template <class Tr> +void RegionBase<Tr>::replaceEntryRecursive(BlockT *NewEntry) { + std::vector<RegionT *> RegionQueue; + BlockT *OldEntry = getEntry(); + + RegionQueue.push_back(static_cast<RegionT *>(this)); + while (!RegionQueue.empty()) { + RegionT *R = RegionQueue.back(); + RegionQueue.pop_back(); + + R->replaceEntry(NewEntry); + for (std::unique_ptr<RegionT> &Child : *R) { + if (Child->getEntry() == OldEntry) + RegionQueue.push_back(Child.get()); + } + } +} + +template <class Tr> +void RegionBase<Tr>::replaceExitRecursive(BlockT *NewExit) { + std::vector<RegionT *> RegionQueue; + BlockT *OldExit = getExit(); + + RegionQueue.push_back(static_cast<RegionT *>(this)); + while (!RegionQueue.empty()) { + RegionT *R = RegionQueue.back(); + RegionQueue.pop_back(); + + R->replaceExit(NewExit); + for (std::unique_ptr<RegionT> &Child : *R) { + if (Child->getExit() == OldExit) + RegionQueue.push_back(Child.get()); + } + } +} + +template <class Tr> +bool RegionBase<Tr>::contains(const BlockT *B) const { + BlockT *BB = const_cast<BlockT *>(B); + + if (!DT->getNode(BB)) + return false; + + BlockT *entry = getEntry(), *exit = getExit(); + + // Toplevel region. + if (!exit) + return true; + + return (DT->dominates(entry, BB) && + !(DT->dominates(exit, BB) && DT->dominates(entry, exit))); +} + +template <class Tr> +bool RegionBase<Tr>::contains(const LoopT *L) const { + // BBs that are not part of any loop are element of the Loop + // described by the NULL pointer. This loop is not part of any region, + // except if the region describes the whole function. + if (!L) + return getExit() == nullptr; + + if (!contains(L->getHeader())) + return false; + + SmallVector<BlockT *, 8> ExitingBlocks; + L->getExitingBlocks(ExitingBlocks); + + for (BlockT *BB : ExitingBlocks) { + if (!contains(BB)) + return false; + } + + return true; +} + +template <class Tr> +typename Tr::LoopT *RegionBase<Tr>::outermostLoopInRegion(LoopT *L) const { + if (!contains(L)) + return nullptr; + + while (L && contains(L->getParentLoop())) { + L = L->getParentLoop(); + } + + return L; +} + +template <class Tr> +typename Tr::LoopT *RegionBase<Tr>::outermostLoopInRegion(LoopInfoT *LI, + BlockT *BB) const { + assert(LI && BB && "LI and BB cannot be null!"); + LoopT *L = LI->getLoopFor(BB); + return outermostLoopInRegion(L); +} + +template <class Tr> +typename RegionBase<Tr>::BlockT *RegionBase<Tr>::getEnteringBlock() const { + BlockT *entry = getEntry(); + BlockT *enteringBlock = nullptr; + + for (BlockT *Pred : make_range(InvBlockTraits::child_begin(entry), + InvBlockTraits::child_end(entry))) { + if (DT->getNode(Pred) && !contains(Pred)) { + if (enteringBlock) + return nullptr; + + enteringBlock = Pred; + } + } + + return enteringBlock; +} + +template <class Tr> +bool RegionBase<Tr>::getExitingBlocks( + SmallVectorImpl<BlockT *> &Exitings) const { + bool CoverAll = true; + + if (!exit) + return CoverAll; + + for (PredIterTy PI = InvBlockTraits::child_begin(exit), + PE = InvBlockTraits::child_end(exit); + PI != PE; ++PI) { + BlockT *Pred = *PI; + if (contains(Pred)) { + Exitings.push_back(Pred); + continue; + } + + CoverAll = false; + } + + return CoverAll; +} + +template <class Tr> +typename RegionBase<Tr>::BlockT *RegionBase<Tr>::getExitingBlock() const { + BlockT *exit = getExit(); + BlockT *exitingBlock = nullptr; + + if (!exit) + return nullptr; + + for (BlockT *Pred : make_range(InvBlockTraits::child_begin(exit), + InvBlockTraits::child_end(exit))) { + if (contains(Pred)) { + if (exitingBlock) + return nullptr; + + exitingBlock = Pred; + } + } + + return exitingBlock; +} + +template <class Tr> +bool RegionBase<Tr>::isSimple() const { + return !isTopLevelRegion() && getEnteringBlock() && getExitingBlock(); +} + +template <class Tr> +std::string RegionBase<Tr>::getNameStr() const { + std::string exitName; + std::string entryName; + + if (getEntry()->getName().empty()) { + raw_string_ostream OS(entryName); + + getEntry()->printAsOperand(OS, false); + } else + entryName = getEntry()->getName(); + + if (getExit()) { + if (getExit()->getName().empty()) { + raw_string_ostream OS(exitName); + + getExit()->printAsOperand(OS, false); + } else + exitName = getExit()->getName(); + } else + exitName = "<Function Return>"; + + return entryName + " => " + exitName; +} + +template <class Tr> +void RegionBase<Tr>::verifyBBInRegion(BlockT *BB) const { + if (!contains(BB)) + report_fatal_error("Broken region found: enumerated BB not in region!"); + + BlockT *entry = getEntry(), *exit = getExit(); + + for (BlockT *Succ : + make_range(BlockTraits::child_begin(BB), BlockTraits::child_end(BB))) { + if (!contains(Succ) && exit != Succ) + report_fatal_error("Broken region found: edges leaving the region must go " + "to the exit node!"); + } + + if (entry != BB) { + for (BlockT *Pred : make_range(InvBlockTraits::child_begin(BB), + InvBlockTraits::child_end(BB))) { + if (!contains(Pred)) + report_fatal_error("Broken region found: edges entering the region must " + "go to the entry node!"); + } + } +} + +template <class Tr> +void RegionBase<Tr>::verifyWalk(BlockT *BB, std::set<BlockT *> *visited) const { + BlockT *exit = getExit(); + + visited->insert(BB); + + verifyBBInRegion(BB); + + for (BlockT *Succ : + make_range(BlockTraits::child_begin(BB), BlockTraits::child_end(BB))) { + if (Succ != exit && visited->find(Succ) == visited->end()) + verifyWalk(Succ, visited); + } +} + +template <class Tr> +void RegionBase<Tr>::verifyRegion() const { + // Only do verification when user wants to, otherwise this expensive check + // will be invoked by PMDataManager::verifyPreservedAnalysis when + // a regionpass (marked PreservedAll) finish. + if (!RegionInfoBase<Tr>::VerifyRegionInfo) + return; + + std::set<BlockT *> visited; + verifyWalk(getEntry(), &visited); +} + +template <class Tr> +void RegionBase<Tr>::verifyRegionNest() const { + for (const std::unique_ptr<RegionT> &R : *this) + R->verifyRegionNest(); + + verifyRegion(); +} + +template <class Tr> +typename RegionBase<Tr>::element_iterator RegionBase<Tr>::element_begin() { + return GraphTraits<RegionT *>::nodes_begin(static_cast<RegionT *>(this)); +} + +template <class Tr> +typename RegionBase<Tr>::element_iterator RegionBase<Tr>::element_end() { + return GraphTraits<RegionT *>::nodes_end(static_cast<RegionT *>(this)); +} + +template <class Tr> +typename RegionBase<Tr>::const_element_iterator +RegionBase<Tr>::element_begin() const { + return GraphTraits<const RegionT *>::nodes_begin( + static_cast<const RegionT *>(this)); +} + +template <class Tr> +typename RegionBase<Tr>::const_element_iterator +RegionBase<Tr>::element_end() const { + return GraphTraits<const RegionT *>::nodes_end( + static_cast<const RegionT *>(this)); +} + +template <class Tr> +typename Tr::RegionT *RegionBase<Tr>::getSubRegionNode(BlockT *BB) const { + using RegionT = typename Tr::RegionT; + + RegionT *R = RI->getRegionFor(BB); + + if (!R || R == this) + return nullptr; + + // If we pass the BB out of this region, that means our code is broken. + assert(contains(R) && "BB not in current region!"); + + while (contains(R->getParent()) && R->getParent() != this) + R = R->getParent(); + + if (R->getEntry() != BB) + return nullptr; + + return R; +} + +template <class Tr> +typename Tr::RegionNodeT *RegionBase<Tr>::getBBNode(BlockT *BB) const { + assert(contains(BB) && "Can get BB node out of this region!"); + + typename BBNodeMapT::const_iterator at = BBNodeMap.find(BB); + + if (at == BBNodeMap.end()) { + auto Deconst = const_cast<RegionBase<Tr> *>(this); + typename BBNodeMapT::value_type V = { + BB, + std::make_unique<RegionNodeT>(static_cast<RegionT *>(Deconst), BB)}; + at = BBNodeMap.insert(std::move(V)).first; + } + return at->second.get(); +} + +template <class Tr> +typename Tr::RegionNodeT *RegionBase<Tr>::getNode(BlockT *BB) const { + assert(contains(BB) && "Can get BB node out of this region!"); + if (RegionT *Child = getSubRegionNode(BB)) + return Child->getNode(); + + return getBBNode(BB); +} + +template <class Tr> +void RegionBase<Tr>::transferChildrenTo(RegionT *To) { + for (std::unique_ptr<RegionT> &R : *this) { + R->parent = To; + To->children.push_back(std::move(R)); + } + children.clear(); +} + +template <class Tr> +void RegionBase<Tr>::addSubRegion(RegionT *SubRegion, bool moveChildren) { + assert(!SubRegion->parent && "SubRegion already has a parent!"); + assert(llvm::find_if(*this, + [&](const std::unique_ptr<RegionT> &R) { + return R.get() == SubRegion; + }) == children.end() && + "Subregion already exists!"); + + SubRegion->parent = static_cast<RegionT *>(this); + children.push_back(std::unique_ptr<RegionT>(SubRegion)); + + if (!moveChildren) + return; + + assert(SubRegion->children.empty() && + "SubRegions that contain children are not supported"); + + for (RegionNodeT *Element : elements()) { + if (!Element->isSubRegion()) { + BlockT *BB = Element->template getNodeAs<BlockT>(); + + if (SubRegion->contains(BB)) + RI->setRegionFor(BB, SubRegion); + } + } + + std::vector<std::unique_ptr<RegionT>> Keep; + for (std::unique_ptr<RegionT> &R : *this) { + if (SubRegion->contains(R.get()) && R.get() != SubRegion) { + R->parent = SubRegion; + SubRegion->children.push_back(std::move(R)); + } else + Keep.push_back(std::move(R)); + } + + children.clear(); + children.insert( + children.begin(), + std::move_iterator<typename RegionSet::iterator>(Keep.begin()), + std::move_iterator<typename RegionSet::iterator>(Keep.end())); +} + +template <class Tr> +typename Tr::RegionT *RegionBase<Tr>::removeSubRegion(RegionT *Child) { + assert(Child->parent == this && "Child is not a child of this region!"); + Child->parent = nullptr; + typename RegionSet::iterator I = + llvm::find_if(children, [&](const std::unique_ptr<RegionT> &R) { + return R.get() == Child; + }); + assert(I != children.end() && "Region does not exit. Unable to remove."); + children.erase(children.begin() + (I - begin())); + return Child; +} + +template <class Tr> +unsigned RegionBase<Tr>::getDepth() const { + unsigned Depth = 0; + + for (RegionT *R = getParent(); R != nullptr; R = R->getParent()) + ++Depth; + + return Depth; +} + +template <class Tr> +typename Tr::RegionT *RegionBase<Tr>::getExpandedRegion() const { + unsigned NumSuccessors = Tr::getNumSuccessors(exit); + + if (NumSuccessors == 0) + return nullptr; + + RegionT *R = RI->getRegionFor(exit); + + if (R->getEntry() != exit) { + for (BlockT *Pred : make_range(InvBlockTraits::child_begin(getExit()), + InvBlockTraits::child_end(getExit()))) + if (!contains(Pred)) + return nullptr; + if (Tr::getNumSuccessors(exit) == 1) + return new RegionT(getEntry(), *BlockTraits::child_begin(exit), RI, DT); + return nullptr; + } + + while (R->getParent() && R->getParent()->getEntry() == exit) + R = R->getParent(); + + for (BlockT *Pred : make_range(InvBlockTraits::child_begin(getExit()), + InvBlockTraits::child_end(getExit()))) { + if (!(contains(Pred) || R->contains(Pred))) + return nullptr; + } + + return new RegionT(getEntry(), R->getExit(), RI, DT); +} + +template <class Tr> +void RegionBase<Tr>::print(raw_ostream &OS, bool print_tree, unsigned level, + PrintStyle Style) const { + if (print_tree) + OS.indent(level * 2) << '[' << level << "] " << getNameStr(); + else + OS.indent(level * 2) << getNameStr(); + + OS << '\n'; + + if (Style != PrintNone) { + OS.indent(level * 2) << "{\n"; + OS.indent(level * 2 + 2); + + if (Style == PrintBB) { + for (const auto *BB : blocks()) + OS << BB->getName() << ", "; // TODO: remove the last "," + } else if (Style == PrintRN) { + for (const RegionNodeT *Element : elements()) { + OS << *Element << ", "; // TODO: remove the last ", + } + } + + OS << '\n'; + } + + if (print_tree) { + for (const std::unique_ptr<RegionT> &R : *this) + R->print(OS, print_tree, level + 1, Style); + } + + if (Style != PrintNone) + OS.indent(level * 2) << "} \n"; +} + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +template <class Tr> +void RegionBase<Tr>::dump() const { + print(dbgs(), true, getDepth(), RegionInfoBase<Tr>::printStyle); +} +#endif + +template <class Tr> +void RegionBase<Tr>::clearNodeCache() { + BBNodeMap.clear(); + for (std::unique_ptr<RegionT> &R : *this) + R->clearNodeCache(); +} + +//===----------------------------------------------------------------------===// +// RegionInfoBase implementation +// + +template <class Tr> +RegionInfoBase<Tr>::RegionInfoBase() = default; + +template <class Tr> +RegionInfoBase<Tr>::~RegionInfoBase() { + releaseMemory(); +} + +template <class Tr> +void RegionInfoBase<Tr>::verifyBBMap(const RegionT *R) const { + assert(R && "Re must be non-null"); + for (const typename Tr::RegionNodeT *Element : R->elements()) { + if (Element->isSubRegion()) { + const RegionT *SR = Element->template getNodeAs<RegionT>(); + verifyBBMap(SR); + } else { + BlockT *BB = Element->template getNodeAs<BlockT>(); + if (getRegionFor(BB) != R) + report_fatal_error("BB map does not match region nesting"); + } + } +} + +template <class Tr> +bool RegionInfoBase<Tr>::isCommonDomFrontier(BlockT *BB, BlockT *entry, + BlockT *exit) const { + for (BlockT *P : make_range(InvBlockTraits::child_begin(BB), + InvBlockTraits::child_end(BB))) { + if (DT->dominates(entry, P) && !DT->dominates(exit, P)) + return false; + } + + return true; +} + +template <class Tr> +bool RegionInfoBase<Tr>::isRegion(BlockT *entry, BlockT *exit) const { + assert(entry && exit && "entry and exit must not be null!"); + + using DST = typename DomFrontierT::DomSetType; + + DST *entrySuccs = &DF->find(entry)->second; + + // Exit is the header of a loop that contains the entry. In this case, + // the dominance frontier must only contain the exit. + if (!DT->dominates(entry, exit)) { + for (typename DST::iterator SI = entrySuccs->begin(), + SE = entrySuccs->end(); + SI != SE; ++SI) { + if (*SI != exit && *SI != entry) + return false; + } + + return true; + } + + DST *exitSuccs = &DF->find(exit)->second; + + // Do not allow edges leaving the region. + for (BlockT *Succ : *entrySuccs) { + if (Succ == exit || Succ == entry) + continue; + if (exitSuccs->find(Succ) == exitSuccs->end()) + return false; + if (!isCommonDomFrontier(Succ, entry, exit)) + return false; + } + + // Do not allow edges pointing into the region. + for (BlockT *Succ : *exitSuccs) { + if (DT->properlyDominates(entry, Succ) && Succ != exit) + return false; + } + + return true; +} + +template <class Tr> +void RegionInfoBase<Tr>::insertShortCut(BlockT *entry, BlockT *exit, + BBtoBBMap *ShortCut) const { + assert(entry && exit && "entry and exit must not be null!"); + + typename BBtoBBMap::iterator e = ShortCut->find(exit); + + if (e == ShortCut->end()) + // No further region at exit available. + (*ShortCut)[entry] = exit; + else { + // We found a region e that starts at exit. Therefore (entry, e->second) + // is also a region, that is larger than (entry, exit). Insert the + // larger one. + BlockT *BB = e->second; + (*ShortCut)[entry] = BB; + } +} + +template <class Tr> +typename Tr::DomTreeNodeT * +RegionInfoBase<Tr>::getNextPostDom(DomTreeNodeT *N, BBtoBBMap *ShortCut) const { + typename BBtoBBMap::iterator e = ShortCut->find(N->getBlock()); + + if (e == ShortCut->end()) + return N->getIDom(); + + return PDT->getNode(e->second)->getIDom(); +} + +template <class Tr> +bool RegionInfoBase<Tr>::isTrivialRegion(BlockT *entry, BlockT *exit) const { + assert(entry && exit && "entry and exit must not be null!"); + + unsigned num_successors = + BlockTraits::child_end(entry) - BlockTraits::child_begin(entry); + + if (num_successors <= 1 && exit == *(BlockTraits::child_begin(entry))) + return true; + + return false; +} + +template <class Tr> +typename Tr::RegionT *RegionInfoBase<Tr>::createRegion(BlockT *entry, + BlockT *exit) { + assert(entry && exit && "entry and exit must not be null!"); + + if (isTrivialRegion(entry, exit)) + return nullptr; + + RegionT *region = + new RegionT(entry, exit, static_cast<RegionInfoT *>(this), DT); + BBtoRegion.insert({entry, region}); + +#ifdef EXPENSIVE_CHECKS + region->verifyRegion(); +#else + LLVM_DEBUG(region->verifyRegion()); +#endif + + updateStatistics(region); + return region; +} + +template <class Tr> +void RegionInfoBase<Tr>::findRegionsWithEntry(BlockT *entry, + BBtoBBMap *ShortCut) { + assert(entry); + + DomTreeNodeT *N = PDT->getNode(entry); + if (!N) + return; + + RegionT *lastRegion = nullptr; + BlockT *lastExit = entry; + + // As only a BasicBlock that postdominates entry can finish a region, walk the + // post dominance tree upwards. + while ((N = getNextPostDom(N, ShortCut))) { + BlockT *exit = N->getBlock(); + + if (!exit) + break; + + if (isRegion(entry, exit)) { + RegionT *newRegion = createRegion(entry, exit); + + if (lastRegion) + newRegion->addSubRegion(lastRegion); + + lastRegion = newRegion; + lastExit = exit; + } + + // This can never be a region, so stop the search. + if (!DT->dominates(entry, exit)) + break; + } + + // Tried to create regions from entry to lastExit. Next time take a + // shortcut from entry to lastExit. + if (lastExit != entry) + insertShortCut(entry, lastExit, ShortCut); +} + +template <class Tr> +void RegionInfoBase<Tr>::scanForRegions(FuncT &F, BBtoBBMap *ShortCut) { + using FuncPtrT = typename std::add_pointer<FuncT>::type; + + BlockT *entry = GraphTraits<FuncPtrT>::getEntryNode(&F); + DomTreeNodeT *N = DT->getNode(entry); + + // Iterate over the dominance tree in post order to start with the small + // regions from the bottom of the dominance tree. If the small regions are + // detected first, detection of bigger regions is faster, as we can jump + // over the small regions. + for (auto DomNode : post_order(N)) + findRegionsWithEntry(DomNode->getBlock(), ShortCut); +} + +template <class Tr> +typename Tr::RegionT *RegionInfoBase<Tr>::getTopMostParent(RegionT *region) { + while (region->getParent()) + region = region->getParent(); + + return region; +} + +template <class Tr> +void RegionInfoBase<Tr>::buildRegionsTree(DomTreeNodeT *N, RegionT *region) { + BlockT *BB = N->getBlock(); + + // Passed region exit + while (BB == region->getExit()) + region = region->getParent(); + + typename BBtoRegionMap::iterator it = BBtoRegion.find(BB); + + // This basic block is a start block of a region. It is already in the + // BBtoRegion relation. Only the child basic blocks have to be updated. + if (it != BBtoRegion.end()) { + RegionT *newRegion = it->second; + region->addSubRegion(getTopMostParent(newRegion)); + region = newRegion; + } else { + BBtoRegion[BB] = region; + } + + for (DomTreeNodeBase<BlockT> *C : *N) { + buildRegionsTree(C, region); + } +} + +#ifdef EXPENSIVE_CHECKS +template <class Tr> +bool RegionInfoBase<Tr>::VerifyRegionInfo = true; +#else +template <class Tr> +bool RegionInfoBase<Tr>::VerifyRegionInfo = false; +#endif + +template <class Tr> +typename Tr::RegionT::PrintStyle RegionInfoBase<Tr>::printStyle = + RegionBase<Tr>::PrintNone; + +template <class Tr> +void RegionInfoBase<Tr>::print(raw_ostream &OS) const { + OS << "Region tree:\n"; + TopLevelRegion->print(OS, true, 0, printStyle); + OS << "End region tree\n"; +} + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +template <class Tr> +void RegionInfoBase<Tr>::dump() const { print(dbgs()); } +#endif + +template <class Tr> +void RegionInfoBase<Tr>::releaseMemory() { + BBtoRegion.clear(); + if (TopLevelRegion) + delete TopLevelRegion; + TopLevelRegion = nullptr; +} + +template <class Tr> +void RegionInfoBase<Tr>::verifyAnalysis() const { + // Do only verify regions if explicitely activated using EXPENSIVE_CHECKS or + // -verify-region-info + if (!RegionInfoBase<Tr>::VerifyRegionInfo) + return; + + TopLevelRegion->verifyRegionNest(); + + verifyBBMap(TopLevelRegion); +} + +// Region pass manager support. +template <class Tr> +typename Tr::RegionT *RegionInfoBase<Tr>::getRegionFor(BlockT *BB) const { + typename BBtoRegionMap::const_iterator I = BBtoRegion.find(BB); + return I != BBtoRegion.end() ? I->second : nullptr; +} + +template <class Tr> +void RegionInfoBase<Tr>::setRegionFor(BlockT *BB, RegionT *R) { + BBtoRegion[BB] = R; +} + +template <class Tr> +typename Tr::RegionT *RegionInfoBase<Tr>::operator[](BlockT *BB) const { + return getRegionFor(BB); +} + +template <class Tr> +typename RegionInfoBase<Tr>::BlockT * +RegionInfoBase<Tr>::getMaxRegionExit(BlockT *BB) const { + BlockT *Exit = nullptr; + + while (true) { + // Get largest region that starts at BB. + RegionT *R = getRegionFor(BB); + while (R && R->getParent() && R->getParent()->getEntry() == BB) + R = R->getParent(); + + // Get the single exit of BB. + if (R && R->getEntry() == BB) + Exit = R->getExit(); + else if (++BlockTraits::child_begin(BB) == BlockTraits::child_end(BB)) + Exit = *BlockTraits::child_begin(BB); + else // No single exit exists. + return Exit; + + // Get largest region that starts at Exit. + RegionT *ExitR = getRegionFor(Exit); + while (ExitR && ExitR->getParent() && + ExitR->getParent()->getEntry() == Exit) + ExitR = ExitR->getParent(); + + for (BlockT *Pred : make_range(InvBlockTraits::child_begin(Exit), + InvBlockTraits::child_end(Exit))) { + if (!R->contains(Pred) && !ExitR->contains(Pred)) + break; + } + + // This stops infinite cycles. + if (DT->dominates(Exit, BB)) + break; + + BB = Exit; + } + + return Exit; +} + +template <class Tr> +typename Tr::RegionT *RegionInfoBase<Tr>::getCommonRegion(RegionT *A, + RegionT *B) const { + assert(A && B && "One of the Regions is NULL"); + + if (A->contains(B)) + return A; + + while (!B->contains(A)) + B = B->getParent(); + + return B; +} + +template <class Tr> +typename Tr::RegionT * +RegionInfoBase<Tr>::getCommonRegion(SmallVectorImpl<RegionT *> &Regions) const { + RegionT *ret = Regions.back(); + Regions.pop_back(); + + for (RegionT *R : Regions) + ret = getCommonRegion(ret, R); + + return ret; +} + +template <class Tr> +typename Tr::RegionT * +RegionInfoBase<Tr>::getCommonRegion(SmallVectorImpl<BlockT *> &BBs) const { + RegionT *ret = getRegionFor(BBs.back()); + BBs.pop_back(); + + for (BlockT *BB : BBs) + ret = getCommonRegion(ret, getRegionFor(BB)); + + return ret; +} + +template <class Tr> +void RegionInfoBase<Tr>::calculate(FuncT &F) { + using FuncPtrT = typename std::add_pointer<FuncT>::type; + + // ShortCut a function where for every BB the exit of the largest region + // starting with BB is stored. These regions can be threated as single BBS. + // This improves performance on linear CFGs. + BBtoBBMap ShortCut; + + scanForRegions(F, &ShortCut); + BlockT *BB = GraphTraits<FuncPtrT>::getEntryNode(&F); + buildRegionsTree(DT->getNode(BB), TopLevelRegion); +} + +} // end namespace llvm + +#undef DEBUG_TYPE + +#endif // LLVM_ANALYSIS_REGIONINFOIMPL_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/RegionIterator.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/RegionIterator.h new file mode 100644 index 0000000..72bc5bb --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/RegionIterator.h
@@ -0,0 +1,359 @@ +//===- RegionIterator.h - Iterators to iteratate over Regions ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// This file defines the iterators to iterate over the elements of a Region. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_REGIONITERATOR_H +#define LLVM_ANALYSIS_REGIONITERATOR_H + +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/Analysis/RegionInfo.h" +#include "llvm/IR/CFG.h" +#include <cassert> +#include <iterator> +#include <type_traits> + +namespace llvm { + +class BasicBlock; + +//===----------------------------------------------------------------------===// +/// Hierarchical RegionNode successor iterator. +/// +/// This iterator iterates over all successors of a RegionNode. +/// +/// For a BasicBlock RegionNode it skips all BasicBlocks that are not part of +/// the parent Region. Furthermore for BasicBlocks that start a subregion, a +/// RegionNode representing the subregion is returned. +/// +/// For a subregion RegionNode there is just one successor. The RegionNode +/// representing the exit of the subregion. +template <class NodeRef, class BlockT, class RegionT> +class RNSuccIterator + : public std::iterator<std::forward_iterator_tag, NodeRef> { + using super = std::iterator<std::forward_iterator_tag, NodeRef>; + using BlockTraits = GraphTraits<BlockT *>; + using SuccIterTy = typename BlockTraits::ChildIteratorType; + + // The iterator works in two modes, bb mode or region mode. + enum ItMode { + // In BB mode it returns all successors of this BasicBlock as its + // successors. + ItBB, + // In region mode there is only one successor, thats the regionnode mapping + // to the exit block of the regionnode + ItRgBegin, // At the beginning of the regionnode successor. + ItRgEnd // At the end of the regionnode successor. + }; + + static_assert(std::is_pointer<NodeRef>::value, + "FIXME: Currently RNSuccIterator only supports NodeRef as " + "pointers due to the use of pointer-specific data structures " + "(e.g. PointerIntPair and SmallPtrSet) internally. Generalize " + "it to support non-pointer types"); + + // Use two bit to represent the mode iterator. + PointerIntPair<NodeRef, 2, ItMode> Node; + + // The block successor iterator. + SuccIterTy BItor; + + // advanceRegionSucc - A region node has only one successor. It reaches end + // once we advance it. + void advanceRegionSucc() { + assert(Node.getInt() == ItRgBegin && "Cannot advance region successor!"); + Node.setInt(ItRgEnd); + } + + NodeRef getNode() const { return Node.getPointer(); } + + // isRegionMode - Is the current iterator in region mode? + bool isRegionMode() const { return Node.getInt() != ItBB; } + + // Get the immediate successor. This function may return a Basic Block + // RegionNode or a subregion RegionNode. + NodeRef getISucc(BlockT *BB) const { + NodeRef succ; + succ = getNode()->getParent()->getNode(BB); + assert(succ && "BB not in Region or entered subregion!"); + return succ; + } + + // getRegionSucc - Return the successor basic block of a SubRegion RegionNode. + inline BlockT* getRegionSucc() const { + assert(Node.getInt() == ItRgBegin && "Cannot get the region successor!"); + return getNode()->template getNodeAs<RegionT>()->getExit(); + } + + // isExit - Is this the exit BB of the Region? + inline bool isExit(BlockT* BB) const { + return getNode()->getParent()->getExit() == BB; + } + +public: + using Self = RNSuccIterator<NodeRef, BlockT, RegionT>; + using value_type = typename super::value_type; + + /// Create begin iterator of a RegionNode. + inline RNSuccIterator(NodeRef node) + : Node(node, node->isSubRegion() ? ItRgBegin : ItBB), + BItor(BlockTraits::child_begin(node->getEntry())) { + // Skip the exit block + if (!isRegionMode()) + while (BlockTraits::child_end(node->getEntry()) != BItor && isExit(*BItor)) + ++BItor; + + if (isRegionMode() && isExit(getRegionSucc())) + advanceRegionSucc(); + } + + /// Create an end iterator. + inline RNSuccIterator(NodeRef node, bool) + : Node(node, node->isSubRegion() ? ItRgEnd : ItBB), + BItor(BlockTraits::child_end(node->getEntry())) {} + + inline bool operator==(const Self& x) const { + assert(isRegionMode() == x.isRegionMode() && "Broken iterator!"); + if (isRegionMode()) + return Node.getInt() == x.Node.getInt(); + else + return BItor == x.BItor; + } + + inline bool operator!=(const Self& x) const { return !operator==(x); } + + inline value_type operator*() const { + BlockT *BB = isRegionMode() ? getRegionSucc() : *BItor; + assert(!isExit(BB) && "Iterator out of range!"); + return getISucc(BB); + } + + inline Self& operator++() { + if(isRegionMode()) { + // The Region only has 1 successor. + advanceRegionSucc(); + } else { + // Skip the exit. + do + ++BItor; + while (BItor != BlockTraits::child_end(getNode()->getEntry()) + && isExit(*BItor)); + } + return *this; + } + + inline Self operator++(int) { + Self tmp = *this; + ++*this; + return tmp; + } +}; + +//===----------------------------------------------------------------------===// +/// Flat RegionNode iterator. +/// +/// The Flat Region iterator will iterate over all BasicBlock RegionNodes that +/// are contained in the Region and its subregions. This is close to a virtual +/// control flow graph of the Region. +template <class NodeRef, class BlockT, class RegionT> +class RNSuccIterator<FlatIt<NodeRef>, BlockT, RegionT> + : public std::iterator<std::forward_iterator_tag, NodeRef> { + using super = std::iterator<std::forward_iterator_tag, NodeRef>; + using BlockTraits = GraphTraits<BlockT *>; + using SuccIterTy = typename BlockTraits::ChildIteratorType; + + NodeRef Node; + SuccIterTy Itor; + +public: + using Self = RNSuccIterator<FlatIt<NodeRef>, BlockT, RegionT>; + using value_type = typename super::value_type; + + /// Create the iterator from a RegionNode. + /// + /// Note that the incoming node must be a bb node, otherwise it will trigger + /// an assertion when we try to get a BasicBlock. + inline RNSuccIterator(NodeRef node) + : Node(node), Itor(BlockTraits::child_begin(node->getEntry())) { + assert(!Node->isSubRegion() && + "Subregion node not allowed in flat iterating mode!"); + assert(Node->getParent() && "A BB node must have a parent!"); + + // Skip the exit block of the iterating region. + while (BlockTraits::child_end(Node->getEntry()) != Itor && + Node->getParent()->getExit() == *Itor) + ++Itor; + } + + /// Create an end iterator + inline RNSuccIterator(NodeRef node, bool) + : Node(node), Itor(BlockTraits::child_end(node->getEntry())) { + assert(!Node->isSubRegion() && + "Subregion node not allowed in flat iterating mode!"); + } + + inline bool operator==(const Self& x) const { + assert(Node->getParent() == x.Node->getParent() + && "Cannot compare iterators of different regions!"); + + return Itor == x.Itor && Node == x.Node; + } + + inline bool operator!=(const Self& x) const { return !operator==(x); } + + inline value_type operator*() const { + BlockT *BB = *Itor; + + // Get the iterating region. + RegionT *Parent = Node->getParent(); + + // The only case that the successor reaches out of the region is it reaches + // the exit of the region. + assert(Parent->getExit() != BB && "iterator out of range!"); + + return Parent->getBBNode(BB); + } + + inline Self& operator++() { + // Skip the exit block of the iterating region. + do + ++Itor; + while (Itor != succ_end(Node->getEntry()) + && Node->getParent()->getExit() == *Itor); + + return *this; + } + + inline Self operator++(int) { + Self tmp = *this; + ++*this; + return tmp; + } +}; + +template <class NodeRef, class BlockT, class RegionT> +inline RNSuccIterator<NodeRef, BlockT, RegionT> succ_begin(NodeRef Node) { + return RNSuccIterator<NodeRef, BlockT, RegionT>(Node); +} + +template <class NodeRef, class BlockT, class RegionT> +inline RNSuccIterator<NodeRef, BlockT, RegionT> succ_end(NodeRef Node) { + return RNSuccIterator<NodeRef, BlockT, RegionT>(Node, true); +} + +//===--------------------------------------------------------------------===// +// RegionNode GraphTraits specialization so the bbs in the region can be +// iterate by generic graph iterators. +// +// NodeT can either be region node or const region node, otherwise child_begin +// and child_end fail. + +#define RegionNodeGraphTraits(NodeT, BlockT, RegionT) \ + template <> struct GraphTraits<NodeT *> { \ + using NodeRef = NodeT *; \ + using ChildIteratorType = RNSuccIterator<NodeRef, BlockT, RegionT>; \ + static NodeRef getEntryNode(NodeRef N) { return N; } \ + static inline ChildIteratorType child_begin(NodeRef N) { \ + return RNSuccIterator<NodeRef, BlockT, RegionT>(N); \ + } \ + static inline ChildIteratorType child_end(NodeRef N) { \ + return RNSuccIterator<NodeRef, BlockT, RegionT>(N, true); \ + } \ + }; \ + template <> struct GraphTraits<FlatIt<NodeT *>> { \ + using NodeRef = NodeT *; \ + using ChildIteratorType = \ + RNSuccIterator<FlatIt<NodeRef>, BlockT, RegionT>; \ + static NodeRef getEntryNode(NodeRef N) { return N; } \ + static inline ChildIteratorType child_begin(NodeRef N) { \ + return RNSuccIterator<FlatIt<NodeRef>, BlockT, RegionT>(N); \ + } \ + static inline ChildIteratorType child_end(NodeRef N) { \ + return RNSuccIterator<FlatIt<NodeRef>, BlockT, RegionT>(N, true); \ + } \ + } + +#define RegionGraphTraits(RegionT, NodeT) \ + template <> struct GraphTraits<RegionT *> : public GraphTraits<NodeT *> { \ + using nodes_iterator = df_iterator<NodeRef>; \ + static NodeRef getEntryNode(RegionT *R) { \ + return R->getNode(R->getEntry()); \ + } \ + static nodes_iterator nodes_begin(RegionT *R) { \ + return nodes_iterator::begin(getEntryNode(R)); \ + } \ + static nodes_iterator nodes_end(RegionT *R) { \ + return nodes_iterator::end(getEntryNode(R)); \ + } \ + }; \ + template <> \ + struct GraphTraits<FlatIt<RegionT *>> \ + : public GraphTraits<FlatIt<NodeT *>> { \ + using nodes_iterator = \ + df_iterator<NodeRef, df_iterator_default_set<NodeRef>, false, \ + GraphTraits<FlatIt<NodeRef>>>; \ + static NodeRef getEntryNode(RegionT *R) { \ + return R->getBBNode(R->getEntry()); \ + } \ + static nodes_iterator nodes_begin(RegionT *R) { \ + return nodes_iterator::begin(getEntryNode(R)); \ + } \ + static nodes_iterator nodes_end(RegionT *R) { \ + return nodes_iterator::end(getEntryNode(R)); \ + } \ + } + +RegionNodeGraphTraits(RegionNode, BasicBlock, Region); +RegionNodeGraphTraits(const RegionNode, BasicBlock, Region); + +RegionGraphTraits(Region, RegionNode); +RegionGraphTraits(const Region, const RegionNode); + +template <> struct GraphTraits<RegionInfo*> + : public GraphTraits<FlatIt<RegionNode*>> { + using nodes_iterator = + df_iterator<NodeRef, df_iterator_default_set<NodeRef>, false, + GraphTraits<FlatIt<NodeRef>>>; + + static NodeRef getEntryNode(RegionInfo *RI) { + return GraphTraits<FlatIt<Region*>>::getEntryNode(RI->getTopLevelRegion()); + } + + static nodes_iterator nodes_begin(RegionInfo* RI) { + return nodes_iterator::begin(getEntryNode(RI)); + } + + static nodes_iterator nodes_end(RegionInfo *RI) { + return nodes_iterator::end(getEntryNode(RI)); + } +}; + +template <> struct GraphTraits<RegionInfoPass*> + : public GraphTraits<RegionInfo *> { + using nodes_iterator = + df_iterator<NodeRef, df_iterator_default_set<NodeRef>, false, + GraphTraits<FlatIt<NodeRef>>>; + + static NodeRef getEntryNode(RegionInfoPass *RI) { + return GraphTraits<RegionInfo*>::getEntryNode(&RI->getRegionInfo()); + } + + static nodes_iterator nodes_begin(RegionInfoPass* RI) { + return GraphTraits<RegionInfo*>::nodes_begin(&RI->getRegionInfo()); + } + + static nodes_iterator nodes_end(RegionInfoPass *RI) { + return GraphTraits<RegionInfo*>::nodes_end(&RI->getRegionInfo()); + } +}; + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_REGIONITERATOR_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/RegionPass.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/RegionPass.h new file mode 100644 index 0000000..5b1864a --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/RegionPass.h
@@ -0,0 +1,130 @@ +//===- RegionPass.h - RegionPass class --------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the RegionPass class. All region based analysis, +// optimization and transformation passes are derived from RegionPass. +// This class is implemented following the some ideas of the LoopPass.h class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_REGIONPASS_H +#define LLVM_ANALYSIS_REGIONPASS_H + +#include "llvm/Analysis/RegionInfo.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/LegacyPassManagers.h" +#include "llvm/Pass.h" +#include <deque> + +namespace llvm { + +class RGPassManager; +class Function; + +//===----------------------------------------------------------------------===// +/// A pass that runs on each Region in a function. +/// +/// RegionPass is managed by RGPassManager. +class RegionPass : public Pass { +public: + explicit RegionPass(char &pid) : Pass(PT_Region, pid) {} + + //===--------------------------------------------------------------------===// + /// @name To be implemented by every RegionPass + /// + //@{ + /// Run the pass on a specific Region + /// + /// Accessing regions not contained in the current region is not allowed. + /// + /// @param R The region this pass is run on. + /// @param RGM The RegionPassManager that manages this Pass. + /// + /// @return True if the pass modifies this Region. + virtual bool runOnRegion(Region *R, RGPassManager &RGM) = 0; + + /// Get a pass to print the LLVM IR in the region. + /// + /// @param O The output stream to print the Region. + /// @param Banner The banner to separate different printed passes. + /// + /// @return The pass to print the LLVM IR in the region. + Pass *createPrinterPass(raw_ostream &O, + const std::string &Banner) const override; + + using llvm::Pass::doInitialization; + using llvm::Pass::doFinalization; + + virtual bool doInitialization(Region *R, RGPassManager &RGM) { return false; } + virtual bool doFinalization() { return false; } + //@} + + //===--------------------------------------------------------------------===// + /// @name PassManager API + /// + //@{ + void preparePassManager(PMStack &PMS) override; + + void assignPassManager(PMStack &PMS, + PassManagerType PMT = PMT_RegionPassManager) override; + + PassManagerType getPotentialPassManagerType() const override { + return PMT_RegionPassManager; + } + //@} + +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 skipRegion(Region &R) const; +}; + +/// The pass manager to schedule RegionPasses. +class RGPassManager : public FunctionPass, public PMDataManager { + std::deque<Region*> RQ; + bool skipThisRegion; + bool redoThisRegion; + RegionInfo *RI; + Region *CurrentRegion; + +public: + static char ID; + explicit RGPassManager(); + + /// Execute all of the passes scheduled for execution. + /// + /// @return True if any of the passes modifies the function. + bool runOnFunction(Function &F) override; + + /// Pass Manager itself does not invalidate any analysis info. + /// RGPassManager needs RegionInfo. + void getAnalysisUsage(AnalysisUsage &Info) const override; + + StringRef getPassName() const override { return "Region Pass Manager"; } + + PMDataManager *getAsPMDataManager() override { return this; } + Pass *getAsPass() override { return this; } + + /// Print passes managed by this manager. + void dumpPassStructure(unsigned Offset) override; + + /// Get passes contained by this manager. + Pass *getContainedPass(unsigned N) { + assert(N < PassVector.size() && "Pass number out of range!"); + Pass *FP = static_cast<Pass *>(PassVector[N]); + return FP; + } + + PassManagerType getPassManagerType() const override { + return PMT_RegionPassManager; + } +}; + +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/RegionPrinter.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/RegionPrinter.h new file mode 100644 index 0000000..154ac35 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/RegionPrinter.h
@@ -0,0 +1,70 @@ +//===-- RegionPrinter.h - Region printer external interface -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines external functions that can be called to explicitly +// instantiate the region printer. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_REGIONPRINTER_H +#define LLVM_ANALYSIS_REGIONPRINTER_H + +namespace llvm { + class FunctionPass; + class Function; + class RegionInfo; + + FunctionPass *createRegionViewerPass(); + FunctionPass *createRegionOnlyViewerPass(); + FunctionPass *createRegionPrinterPass(); + FunctionPass *createRegionOnlyPrinterPass(); + +#ifndef NDEBUG + /// Open a viewer to display the GraphViz vizualization of the analysis + /// result. + /// + /// Practical to call in the debugger. + /// Includes the instructions in each BasicBlock. + /// + /// @param RI The analysis to display. + void viewRegion(llvm::RegionInfo *RI); + + /// Analyze the regions of a function and open its GraphViz + /// visualization in a viewer. + /// + /// Useful to call in the debugger. + /// Includes the instructions in each BasicBlock. + /// The result of a new analysis may differ from the RegionInfo the pass + /// manager currently holds. + /// + /// @param F Function to analyze. + void viewRegion(const llvm::Function *F); + + /// Open a viewer to display the GraphViz vizualization of the analysis + /// result. + /// + /// Useful to call in the debugger. + /// Shows only the BasicBlock names without their instructions. + /// + /// @param RI The analysis to display. + void viewRegionOnly(llvm::RegionInfo *RI); + + /// Analyze the regions of a function and open its GraphViz + /// visualization in a viewer. + /// + /// Useful to call in the debugger. + /// Shows only the BasicBlock names without their instructions. + /// The result of a new analysis may differ from the RegionInfo the pass + /// manager currently holds. + /// + /// @param F Function to analyze. + void viewRegionOnly(const llvm::Function *F); +#endif +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/ScalarEvolution.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/ScalarEvolution.h new file mode 100644 index 0000000..5286f6a --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -0,0 +1,2061 @@ +//===- llvm/Analysis/ScalarEvolution.h - Scalar Evolution -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// The ScalarEvolution class is an LLVM pass which can be used to analyze and +// categorize scalar expressions in loops. It specializes in recognizing +// general induction variables, representing them with the abstract and opaque +// SCEV class. Given this analysis, trip counts of loops and other important +// properties can be obtained. +// +// This analysis is primarily useful for induction variable substitution and +// strength reduction. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_SCALAREVOLUTION_H +#define LLVM_ANALYSIS_SCALAREVOLUTION_H + +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/Hashing.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/IR/ConstantRange.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/InstrTypes.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/Casting.h" +#include "llvm/Support/Compiler.h" +#include <algorithm> +#include <cassert> +#include <cstdint> +#include <memory> +#include <utility> + +namespace llvm { + +class AssumptionCache; +class BasicBlock; +class Constant; +class ConstantInt; +class DataLayout; +class DominatorTree; +class GEPOperator; +class Instruction; +class LLVMContext; +class raw_ostream; +class ScalarEvolution; +class SCEVAddRecExpr; +class SCEVUnknown; +class StructType; +class TargetLibraryInfo; +class Type; +class Value; + +/// This class represents an analyzed expression in the program. These are +/// opaque objects that the client is not allowed to do much with directly. +/// +class SCEV : public FoldingSetNode { + friend struct FoldingSetTrait<SCEV>; + + /// A reference to an Interned FoldingSetNodeID for this node. The + /// ScalarEvolution's BumpPtrAllocator holds the data. + FoldingSetNodeIDRef FastID; + + // The SCEV baseclass this node corresponds to + const unsigned short SCEVType; + +protected: + // Estimated complexity of this node's expression tree size. + const unsigned short ExpressionSize; + + /// This field is initialized to zero and may be used in subclasses to store + /// miscellaneous information. + unsigned short SubclassData = 0; + +public: + /// NoWrapFlags are bitfield indices into SubclassData. + /// + /// Add and Mul expressions may have no-unsigned-wrap <NUW> or + /// no-signed-wrap <NSW> properties, which are derived from the IR + /// operator. NSW is a misnomer that we use to mean no signed overflow or + /// underflow. + /// + /// AddRec expressions may have a no-self-wraparound <NW> property if, in + /// the integer domain, abs(step) * max-iteration(loop) <= + /// unsigned-max(bitwidth). This means that the recurrence will never reach + /// its start value if the step is non-zero. Computing the same value on + /// each iteration is not considered wrapping, and recurrences with step = 0 + /// are trivially <NW>. <NW> is independent of the sign of step and the + /// value the add recurrence starts with. + /// + /// Note that NUW and NSW are also valid properties of a recurrence, and + /// either implies NW. For convenience, NW will be set for a recurrence + /// whenever either NUW or NSW are set. + enum NoWrapFlags { + FlagAnyWrap = 0, // No guarantee. + FlagNW = (1 << 0), // No self-wrap. + FlagNUW = (1 << 1), // No unsigned wrap. + FlagNSW = (1 << 2), // No signed wrap. + NoWrapMask = (1 << 3) - 1 + }; + + explicit SCEV(const FoldingSetNodeIDRef ID, unsigned SCEVTy, + unsigned short ExpressionSize) + : FastID(ID), SCEVType(SCEVTy), ExpressionSize(ExpressionSize) {} + SCEV(const SCEV &) = delete; + SCEV &operator=(const SCEV &) = delete; + + unsigned getSCEVType() const { return SCEVType; } + + /// Return the LLVM type of this SCEV expression. + Type *getType() const; + + /// Return true if the expression is a constant zero. + bool isZero() const; + + /// Return true if the expression is a constant one. + bool isOne() const; + + /// Return true if the expression is a constant all-ones value. + bool isAllOnesValue() const; + + /// Return true if the specified scev is negated, but not a constant. + bool isNonConstantNegative() const; + + // Returns estimated size of the mathematical expression represented by this + // SCEV. The rules of its calculation are following: + // 1) Size of a SCEV without operands (like constants and SCEVUnknown) is 1; + // 2) Size SCEV with operands Op1, Op2, ..., OpN is calculated by formula: + // (1 + Size(Op1) + ... + Size(OpN)). + // This value gives us an estimation of time we need to traverse through this + // SCEV and all its operands recursively. We may use it to avoid performing + // heavy transformations on SCEVs of excessive size for sake of saving the + // compilation time. + unsigned short getExpressionSize() const { + return ExpressionSize; + } + + /// Print out the internal representation of this scalar to the specified + /// stream. This should really only be used for debugging purposes. + void print(raw_ostream &OS) const; + + /// This method is used for debugging. + void dump() const; +}; + +// Specialize FoldingSetTrait for SCEV to avoid needing to compute +// temporary FoldingSetNodeID values. +template <> struct FoldingSetTrait<SCEV> : DefaultFoldingSetTrait<SCEV> { + static void Profile(const SCEV &X, FoldingSetNodeID &ID) { ID = X.FastID; } + + static bool Equals(const SCEV &X, const FoldingSetNodeID &ID, unsigned IDHash, + FoldingSetNodeID &TempID) { + return ID == X.FastID; + } + + static unsigned ComputeHash(const SCEV &X, FoldingSetNodeID &TempID) { + return X.FastID.ComputeHash(); + } +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const SCEV &S) { + S.print(OS); + return OS; +} + +/// An object of this class is returned by queries that could not be answered. +/// For example, if you ask for the number of iterations of a linked-list +/// traversal loop, you will get one of these. None of the standard SCEV +/// operations are valid on this class, it is just a marker. +struct SCEVCouldNotCompute : public SCEV { + SCEVCouldNotCompute(); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const SCEV *S); +}; + +/// This class represents an assumption made using SCEV expressions which can +/// be checked at run-time. +class SCEVPredicate : public FoldingSetNode { + friend struct FoldingSetTrait<SCEVPredicate>; + + /// A reference to an Interned FoldingSetNodeID for this node. The + /// ScalarEvolution's BumpPtrAllocator holds the data. + FoldingSetNodeIDRef FastID; + +public: + enum SCEVPredicateKind { P_Union, P_Equal, P_Wrap }; + +protected: + SCEVPredicateKind Kind; + ~SCEVPredicate() = default; + SCEVPredicate(const SCEVPredicate &) = default; + SCEVPredicate &operator=(const SCEVPredicate &) = default; + +public: + SCEVPredicate(const FoldingSetNodeIDRef ID, SCEVPredicateKind Kind); + + SCEVPredicateKind getKind() const { return Kind; } + + /// 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; } + + /// 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; + + /// Returns true if this predicate implies \p N. + virtual bool implies(const SCEVPredicate *N) const = 0; + + /// Prints a textual representation of this predicate with an indentation of + /// \p Depth. + virtual void print(raw_ostream &OS, unsigned Depth = 0) const = 0; + + /// Returns the SCEV to which this predicate applies, or nullptr if this is + /// a SCEVUnionPredicate. + virtual const SCEV *getExpr() const = 0; +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const SCEVPredicate &P) { + P.print(OS); + return OS; +} + +// Specialize FoldingSetTrait for SCEVPredicate to avoid needing to compute +// temporary FoldingSetNodeID values. +template <> +struct FoldingSetTrait<SCEVPredicate> : DefaultFoldingSetTrait<SCEVPredicate> { + static void Profile(const SCEVPredicate &X, FoldingSetNodeID &ID) { + ID = X.FastID; + } + + static bool Equals(const SCEVPredicate &X, const FoldingSetNodeID &ID, + unsigned IDHash, FoldingSetNodeID &TempID) { + return ID == X.FastID; + } + + static unsigned ComputeHash(const SCEVPredicate &X, + FoldingSetNodeID &TempID) { + return X.FastID.ComputeHash(); + } +}; + +/// This class represents an assumption that two SCEV expressions are equal, +/// and this can be checked at run-time. +class SCEVEqualPredicate final : public SCEVPredicate { + /// We assume that LHS == RHS. + const SCEV *LHS; + const SCEV *RHS; + +public: + SCEVEqualPredicate(const FoldingSetNodeIDRef ID, const SCEV *LHS, + const SCEV *RHS); + + /// Implementation of the SCEVPredicate interface + bool implies(const SCEVPredicate *N) const override; + void print(raw_ostream &OS, unsigned Depth = 0) const override; + bool isAlwaysTrue() const override; + const SCEV *getExpr() const override; + + /// Returns the left hand side of the equality. + const SCEV *getLHS() const { return LHS; } + + /// Returns the right hand side of the equality. + const SCEV *getRHS() const { return RHS; } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const SCEVPredicate *P) { + return P->getKind() == P_Equal; + } +}; + +/// 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. + LLVM_NODISCARD static SCEVWrapPredicate::IncrementWrapFlags + 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); + } + + LLVM_NODISCARD static SCEVWrapPredicate::IncrementWrapFlags + 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); + } + + LLVM_NODISCARD static SCEVWrapPredicate::IncrementWrapFlags + 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. + LLVM_NODISCARD 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 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. +/// +/// NB! Unlike other SCEVPredicate sub-classes this class does not live in the +/// ScalarEvolution::Preds folding set. This is why the \c add function is sound. +class SCEVUnionPredicate final : public SCEVPredicate { +private: + using PredicateMap = + DenseMap<const SCEV *, SmallVector<const SCEVPredicate *, 4>>; + + /// Vector with references to all predicates in this union. + SmallVector<const SCEVPredicate *, 16> Preds; + + /// Maps SCEVs to predicates for quick look-ups. + PredicateMap SCEVToPreds; + +public: + SCEVUnionPredicate(); + + const SmallVectorImpl<const SCEVPredicate *> &getPredicates() const { + return Preds; + } + + /// Adds a predicate to this union. + void add(const SCEVPredicate *N); + + /// 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 + bool isAlwaysTrue() const override; + bool implies(const SCEVPredicate *N) const override; + void print(raw_ostream &OS, unsigned Depth) const override; + const SCEV *getExpr() const override; + + /// 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: + static bool classof(const SCEVPredicate *P) { + return P->getKind() == P_Union; + } +}; + +/// The main scalar evolution driver. Because client code (intentionally) +/// can't do much with the SCEV objects directly, they must ask this class +/// for services. +class ScalarEvolution { + friend class ScalarEvolutionsTest; + +public: + /// An enum describing the relationship between a SCEV and a loop. + enum LoopDisposition { + LoopVariant, ///< The SCEV is loop-variant (unknown). + LoopInvariant, ///< The SCEV is loop-invariant. + LoopComputable ///< The SCEV varies predictably with the loop. + }; + + /// An enum describing the relationship between a SCEV and a basic block. + enum BlockDisposition { + DoesNotDominateBlock, ///< The SCEV does not dominate the block. + DominatesBlock, ///< The SCEV dominates the block. + ProperlyDominatesBlock ///< The SCEV properly dominates the block. + }; + + /// Convenient NoWrapFlags manipulation that hides enum casts and is + /// visible in the ScalarEvolution name space. + LLVM_NODISCARD static SCEV::NoWrapFlags maskFlags(SCEV::NoWrapFlags Flags, + int Mask) { + return (SCEV::NoWrapFlags)(Flags & Mask); + } + LLVM_NODISCARD static SCEV::NoWrapFlags setFlags(SCEV::NoWrapFlags Flags, + SCEV::NoWrapFlags OnFlags) { + return (SCEV::NoWrapFlags)(Flags | OnFlags); + } + LLVM_NODISCARD static SCEV::NoWrapFlags + clearFlags(SCEV::NoWrapFlags Flags, SCEV::NoWrapFlags OffFlags) { + return (SCEV::NoWrapFlags)(Flags & ~OffFlags); + } + + ScalarEvolution(Function &F, TargetLibraryInfo &TLI, AssumptionCache &AC, + DominatorTree &DT, LoopInfo &LI); + ScalarEvolution(ScalarEvolution &&Arg); + ~ScalarEvolution(); + + LLVMContext &getContext() const { return F.getContext(); } + + /// Test if values of the given type are analyzable within the SCEV + /// framework. This primarily includes integer types, and it can optionally + /// include pointer types if the ScalarEvolution class has access to + /// target-specific information. + bool isSCEVable(Type *Ty) const; + + /// Return the size in bits of the specified type, for which isSCEVable must + /// return true. + uint64_t getTypeSizeInBits(Type *Ty) const; + + /// Return a type with the same bitwidth as the given type and which + /// represents how SCEV will treat the given type, for which isSCEVable must + /// return true. For pointer types, this is the pointer-sized integer type. + Type *getEffectiveSCEVType(Type *Ty) const; + + // Returns a wider type among {Ty1, Ty2}. + Type *getWiderType(Type *Ty1, Type *Ty2) 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); + + /// 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); + + const SCEV *getConstant(ConstantInt *V); + const SCEV *getConstant(const APInt &Val); + const SCEV *getConstant(Type *Ty, uint64_t V, bool isSigned = false); + const SCEV *getTruncateExpr(const SCEV *Op, Type *Ty, unsigned Depth = 0); + const SCEV *getZeroExtendExpr(const SCEV *Op, Type *Ty, unsigned Depth = 0); + const SCEV *getSignExtendExpr(const SCEV *Op, Type *Ty, unsigned Depth = 0); + const SCEV *getAnyExtendExpr(const SCEV *Op, Type *Ty); + const SCEV *getAddExpr(SmallVectorImpl<const SCEV *> &Ops, + SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap, + unsigned Depth = 0); + const SCEV *getAddExpr(const SCEV *LHS, const SCEV *RHS, + SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap, + unsigned Depth = 0) { + SmallVector<const SCEV *, 2> Ops = {LHS, RHS}; + return getAddExpr(Ops, Flags, Depth); + } + const SCEV *getAddExpr(const SCEV *Op0, const SCEV *Op1, const SCEV *Op2, + SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap, + unsigned Depth = 0) { + SmallVector<const SCEV *, 3> Ops = {Op0, Op1, Op2}; + return getAddExpr(Ops, Flags, Depth); + } + const SCEV *getMulExpr(SmallVectorImpl<const SCEV *> &Ops, + SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap, + unsigned Depth = 0); + const SCEV *getMulExpr(const SCEV *LHS, const SCEV *RHS, + SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap, + unsigned Depth = 0) { + SmallVector<const SCEV *, 2> Ops = {LHS, RHS}; + return getMulExpr(Ops, Flags, Depth); + } + const SCEV *getMulExpr(const SCEV *Op0, const SCEV *Op1, const SCEV *Op2, + SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap, + unsigned Depth = 0) { + SmallVector<const SCEV *, 3> Ops = {Op0, Op1, Op2}; + return getMulExpr(Ops, Flags, Depth); + } + const SCEV *getUDivExpr(const SCEV *LHS, const SCEV *RHS); + const SCEV *getUDivExactExpr(const SCEV *LHS, const SCEV *RHS); + const SCEV *getURemExpr(const SCEV *LHS, const SCEV *RHS); + const SCEV *getAddRecExpr(const SCEV *Start, const SCEV *Step, const Loop *L, + SCEV::NoWrapFlags Flags); + const SCEV *getAddRecExpr(SmallVectorImpl<const SCEV *> &Operands, + const Loop *L, SCEV::NoWrapFlags Flags); + const SCEV *getAddRecExpr(const SmallVectorImpl<const SCEV *> &Operands, + const Loop *L, SCEV::NoWrapFlags Flags) { + SmallVector<const SCEV *, 4> NewOp(Operands.begin(), Operands.end()); + return getAddRecExpr(NewOp, L, Flags); + } + + /// Checks if \p SymbolicPHI can be rewritten as an AddRecExpr under some + /// Predicates. If successful return these <AddRecExpr, Predicates>; + /// The function is intended to be called from PSCEV (the caller will decide + /// whether to actually add the predicates and carry out the rewrites). + Optional<std::pair<const SCEV *, SmallVector<const SCEVPredicate *, 3>>> + createAddRecFromPHIWithCasts(const SCEVUnknown *SymbolicPHI); + + /// Returns an expression for a GEP + /// + /// \p GEP The GEP. The indices contained in the GEP itself are ignored, + /// instead we use IndexExprs. + /// \p IndexExprs The expressions for the indices. + const SCEV *getGEPExpr(GEPOperator *GEP, + const SmallVectorImpl<const SCEV *> &IndexExprs); + const SCEV *getMinMaxExpr(unsigned Kind, + SmallVectorImpl<const SCEV *> &Operands); + const SCEV *getSMaxExpr(const SCEV *LHS, const SCEV *RHS); + const SCEV *getSMaxExpr(SmallVectorImpl<const SCEV *> &Operands); + const SCEV *getUMaxExpr(const SCEV *LHS, const SCEV *RHS); + const SCEV *getUMaxExpr(SmallVectorImpl<const SCEV *> &Operands); + const SCEV *getSMinExpr(const SCEV *LHS, const SCEV *RHS); + const SCEV *getSMinExpr(SmallVectorImpl<const SCEV *> &Operands); + const SCEV *getUMinExpr(const SCEV *LHS, const SCEV *RHS); + const SCEV *getUMinExpr(SmallVectorImpl<const SCEV *> &Operands); + const SCEV *getUnknown(Value *V); + const SCEV *getCouldNotCompute(); + + /// Return a SCEV for the constant 0 of a specific type. + const SCEV *getZero(Type *Ty) { return getConstant(Ty, 0); } + + /// 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 + const SCEV *getSizeOfExpr(Type *IntTy, Type *AllocTy); + + /// Return an expression for offsetof on the given field with type IntTy + const SCEV *getOffsetOfExpr(Type *IntTy, StructType *STy, unsigned FieldNo); + + /// Return the SCEV object corresponding to -V. + const SCEV *getNegativeSCEV(const SCEV *V, + SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap); + + /// Return the SCEV object corresponding to ~V. + const SCEV *getNotSCEV(const SCEV *V); + + /// Return LHS-RHS. Minus is represented in SCEV as A+B*-1. + const SCEV *getMinusSCEV(const SCEV *LHS, const SCEV *RHS, + SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap, + unsigned Depth = 0); + + /// Return a SCEV corresponding to a conversion of the input value to the + /// specified type. If the type must be extended, it is zero extended. + const SCEV *getTruncateOrZeroExtend(const SCEV *V, Type *Ty, + unsigned Depth = 0); + + /// Return a SCEV corresponding to a conversion of the input value to the + /// specified type. If the type must be extended, it is sign extended. + const SCEV *getTruncateOrSignExtend(const SCEV *V, Type *Ty, + unsigned Depth = 0); + + /// Return a SCEV corresponding to a conversion of the input value to the + /// specified type. If the type must be extended, it is zero extended. The + /// conversion must not be narrowing. + const SCEV *getNoopOrZeroExtend(const SCEV *V, Type *Ty); + + /// Return a SCEV corresponding to a conversion of the input value to the + /// specified type. If the type must be extended, it is sign extended. The + /// conversion must not be narrowing. + const SCEV *getNoopOrSignExtend(const SCEV *V, Type *Ty); + + /// Return a SCEV corresponding to a conversion of the input value to the + /// specified type. If the type must be extended, it is extended with + /// unspecified bits. The conversion must not be narrowing. + const SCEV *getNoopOrAnyExtend(const SCEV *V, Type *Ty); + + /// Return a SCEV corresponding to a conversion of the input value to the + /// specified type. The conversion must not be widening. + const SCEV *getTruncateOrNoop(const SCEV *V, Type *Ty); + + /// Promote the operands to the wider of the types using zero-extension, and + /// then perform a umax operation with them. + const SCEV *getUMaxFromMismatchedTypes(const SCEV *LHS, const SCEV *RHS); + + /// Promote the operands to the wider of the types using zero-extension, and + /// then perform a umin operation with them. + const SCEV *getUMinFromMismatchedTypes(const SCEV *LHS, const SCEV *RHS); + + /// Promote the operands to the wider of the types using zero-extension, and + /// then perform a umin operation with them. N-ary function. + const SCEV *getUMinFromMismatchedTypes(SmallVectorImpl<const SCEV *> &Ops); + + /// Transitively follow the chain of pointer-type operands until reaching a + /// SCEV that does not have a single pointer operand. This returns a + /// SCEVUnknown pointer for well-formed pointer-type expressions, but corner + /// cases do exist. + const SCEV *getPointerBase(const SCEV *V); + + /// Return a SCEV expression for the specified value at the specified scope + /// in the program. The L value specifies a loop nest to evaluate the + /// expression at, where null is the top-level or a specified loop is + /// immediately inside of the loop. + /// + /// This method can be used to compute the exit value for a variable defined + /// in a loop by querying what the value will hold in the parent loop. + /// + /// In the case that a relevant loop exit value cannot be computed, the + /// original value V is returned. + const SCEV *getSCEVAtScope(const SCEV *S, const Loop *L); + + /// This is a convenience function which does getSCEVAtScope(getSCEV(V), L). + const SCEV *getSCEVAtScope(Value *V, const Loop *L); + + /// Test whether entry to the loop is protected by a conditional between LHS + /// and RHS. This is used to help avoid max expressions in loop trip + /// counts, and to eliminate casts. + bool isLoopEntryGuardedByCond(const Loop *L, ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS); + + /// Test whether the backedge of the loop is protected by a conditional + /// between LHS and RHS. This is used to eliminate casts. + bool isLoopBackedgeGuardedByCond(const Loop *L, ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS); + + /// 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 + /// the single exiting block passed to it. See that routine for details. + unsigned getSmallConstantTripCount(const Loop *L); + + /// Returns the maximum trip count of this loop as a normal unsigned + /// value. Returns 0 if the trip count is unknown or not constant. This + /// "trip count" assumes that control exits via ExitingBlock. More + /// precisely, it is the number of times that control may reach ExitingBlock + /// before taking the branch. For loops with multiple exits, it may not be + /// the number times that the loop header executes if the loop exits + /// prematurely via another branch. + unsigned getSmallConstantTripCount(const Loop *L, BasicBlock *ExitingBlock); + + /// Returns the upper bound of the loop trip count as a normal unsigned + /// value. + /// Returns 0 if the trip count is unknown or not constant. + unsigned getSmallConstantMaxTripCount(const Loop *L); + + /// 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. + /// + /// Implemented in terms of the \c getSmallConstantTripMultiple overload with + /// the single exiting block passed to it. See that routine for details. + unsigned getSmallConstantTripMultiple(const Loop *L); + + /// Returns the largest constant divisor of the trip count of this loop as a + /// normal unsigned value, if possible. This means that the actual trip + /// count is always a multiple of the returned value (don't forget the trip + /// count could very well be zero as well!). As explained in the comments + /// for getSmallConstantTripCount, this assumes that control exits the loop + /// via ExitingBlock. + unsigned getSmallConstantTripMultiple(const Loop *L, + BasicBlock *ExitingBlock); + + + /// The terms "backedge taken count" and "exit count" are used + /// interchangeably to refer to the number of times the backedge of a loop + /// has executed before the loop is exited. + enum ExitCountKind { + /// An expression exactly describing the number of times the backedge has + /// executed when a loop is exited. + Exact, + /// A constant which provides an upper bound on the exact trip count. + ConstantMaximum, + }; + + /// Return the number of times the backedge executes before the given exit + /// would be taken; if not exactly computable, return SCEVCouldNotCompute. + /// For a single exit loop, this value is equivelent to the result of + /// getBackedgeTakenCount. The loop is guaranteed to exit (via *some* exit) + /// before the backedge is executed (ExitCount + 1) times. Note that there + /// is no guarantee about *which* exit is taken on the exiting iteration. + const SCEV *getExitCount(const Loop *L, BasicBlock *ExitingBlock, + ExitCountKind Kind = Exact); + + /// If the specified loop has a predictable backedge-taken count, return it, + /// otherwise return a SCEVCouldNotCompute object. The backedge-taken count is + /// the number of times the loop header will be branched to from within the + /// loop, assuming there are no abnormal exists like exception throws. This is + /// one less than the trip count of the loop, since it doesn't count the first + /// iteration, when the header is branched to from outside the loop. + /// + /// Note that it is not valid to call this method on a loop without a + /// loop-invariant backedge-taken count (see + /// hasLoopInvariantBackedgeTakenCount). + const SCEV *getBackedgeTakenCount(const Loop *L, ExitCountKind Kind = Exact); + + /// 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); + + /// When successful, this returns a SCEVConstant that is greater than or equal + /// to (i.e. a "conservative over-approximation") of the value returend by + /// getBackedgeTakenCount. If such a value cannot be computed, it returns the + /// SCEVCouldNotCompute object. + const SCEV *getConstantMaxBackedgeTakenCount(const Loop *L) { + return getBackedgeTakenCount(L, ConstantMaximum); + } + + /// Return true if the backedge taken count is either the value returned by + /// getConstantMaxBackedgeTakenCount or zero. + bool isBackedgeTakenCountMaxOrZero(const Loop *L); + + /// Return true if the specified loop has an analyzable loop-invariant + /// backedge-taken count. + bool hasLoopInvariantBackedgeTakenCount(const Loop *L); + + // This method should be called by the client when it made any change that + // would invalidate SCEV's answers, and the client wants to remove all loop + // information held internally by ScalarEvolution. This is intended to be used + // when the alternative to forget a loop is too expensive (i.e. large loop + // bodies). + void forgetAllLoops(); + + /// This method should be called by the client when it has changed a loop in + /// a way that may effect ScalarEvolution's ability to compute a trip count, + /// or if the loop is deleted. This call is potentially expensive for large + /// loop bodies. + void forgetLoop(const Loop *L); + + // This method invokes forgetLoop for the outermost loop of the given loop + // \p L, making ScalarEvolution forget about all this subtree. This needs to + // be done whenever we make a transform that may affect the parameters of the + // outer loop, such as exit counts for branches. + void forgetTopmostLoop(const Loop *L); + + /// This method should be called by the client when it has changed a value + /// in a way that may effect its value, or which may disconnect it from a + /// def-use chain linking it to a loop. + void forgetValue(Value *V); + + /// 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 + /// recompute is simpler. + void forgetLoopDispositions(const Loop *L) { LoopDispositions.clear(); } + + /// Determine the minimum number of zero bits that S is guaranteed to end in + /// (at every loop iteration). It is, at the same time, the minimum number + /// of times S is divisible by 2. For example, given {4,+,8} it returns 2. + /// If S is guaranteed to be 0, it returns the bitwidth of S. + uint32_t GetMinTrailingZeros(const SCEV *S); + + /// Determine the unsigned range for a particular SCEV. + /// NOTE: This returns a copy of the reference returned by getRangeRef. + ConstantRange getUnsignedRange(const SCEV *S) { + return getRangeRef(S, HINT_RANGE_UNSIGNED); + } + + /// Determine the min of the unsigned range for a particular SCEV. + APInt getUnsignedRangeMin(const SCEV *S) { + return getRangeRef(S, HINT_RANGE_UNSIGNED).getUnsignedMin(); + } + + /// Determine the max of the unsigned range for a particular SCEV. + APInt getUnsignedRangeMax(const SCEV *S) { + return getRangeRef(S, HINT_RANGE_UNSIGNED).getUnsignedMax(); + } + + /// Determine the signed range for a particular SCEV. + /// NOTE: This returns a copy of the reference returned by getRangeRef. + ConstantRange getSignedRange(const SCEV *S) { + return getRangeRef(S, HINT_RANGE_SIGNED); + } + + /// Determine the min of the signed range for a particular SCEV. + APInt getSignedRangeMin(const SCEV *S) { + return getRangeRef(S, HINT_RANGE_SIGNED).getSignedMin(); + } + + /// Determine the max of the signed range for a particular SCEV. + APInt getSignedRangeMax(const SCEV *S) { + return getRangeRef(S, HINT_RANGE_SIGNED).getSignedMax(); + } + + /// Test if the given expression is known to be negative. + bool isKnownNegative(const SCEV *S); + + /// Test if the given expression is known to be positive. + bool isKnownPositive(const SCEV *S); + + /// Test if the given expression is known to be non-negative. + bool isKnownNonNegative(const SCEV *S); + + /// Test if the given expression is known to be non-positive. + bool isKnownNonPositive(const SCEV *S); + + /// Test if the given expression is known to be non-zero. + bool isKnownNonZero(const SCEV *S); + + /// Splits SCEV expression \p S into two SCEVs. One of them is obtained from + /// \p S by substitution of all AddRec sub-expression related to loop \p L + /// with initial value of that SCEV. The second is obtained from \p S by + /// substitution of all AddRec sub-expressions related to loop \p L with post + /// increment of this AddRec in the loop \p L. In both cases all other AddRec + /// sub-expressions (not related to \p L) remain the same. + /// If the \p S contains non-invariant unknown SCEV the function returns + /// CouldNotCompute SCEV in both values of std::pair. + /// For example, for SCEV S={0, +, 1}<L1> + {0, +, 1}<L2> and loop L=L1 + /// the function returns pair: + /// first = {0, +, 1}<L2> + /// second = {1, +, 1}<L1> + {0, +, 1}<L2> + /// We can see that for the first AddRec sub-expression it was replaced with + /// 0 (initial value) for the first element and to {1, +, 1}<L1> (post + /// increment value) for the second one. In both cases AddRec expression + /// related to L2 remains the same. + std::pair<const SCEV *, const SCEV *> SplitIntoInitAndPostInc(const Loop *L, + const SCEV *S); + + /// We'd like to check the predicate on every iteration of the most dominated + /// loop between loops used in LHS and RHS. + /// To do this we use the following list of steps: + /// 1. Collect set S all loops on which either LHS or RHS depend. + /// 2. If S is non-empty + /// a. Let PD be the element of S which is dominated by all other elements. + /// b. Let E(LHS) be value of LHS on entry of PD. + /// To get E(LHS), we should just take LHS and replace all AddRecs that are + /// attached to PD on with their entry values. + /// Define E(RHS) in the same way. + /// c. Let B(LHS) be value of L on backedge of PD. + /// To get B(LHS), we should just take LHS and replace all AddRecs that are + /// attached to PD on with their backedge values. + /// Define B(RHS) in the same way. + /// d. Note that E(LHS) and E(RHS) are automatically available on entry of PD, + /// so we can assert on that. + /// e. Return true if isLoopEntryGuardedByCond(Pred, E(LHS), E(RHS)) && + /// isLoopBackedgeGuardedByCond(Pred, B(LHS), B(RHS)) + bool isKnownViaInduction(ICmpInst::Predicate Pred, const SCEV *LHS, + const SCEV *RHS); + + /// Test if the given expression is known to satisfy the condition described + /// by Pred, LHS, and RHS. + bool isKnownPredicate(ICmpInst::Predicate Pred, const SCEV *LHS, + const SCEV *RHS); + + /// Test if the condition described by Pred, LHS, RHS is known to be true on + /// every iteration of the loop of the recurrency LHS. + bool isKnownOnEveryIteration(ICmpInst::Predicate Pred, + const SCEVAddRecExpr *LHS, const SCEV *RHS); + + /// Return true if, for all loop invariant X, the predicate "LHS `Pred` X" + /// is monotonically increasing or decreasing. In the former case set + /// `Increasing` to true and in the latter case set `Increasing` to false. + /// + /// A predicate is said to be monotonically increasing if may go from being + /// false to being true as the loop iterates, but never the other way + /// around. A predicate is said to be monotonically decreasing if may go + /// from being true to being false as the loop iterates, but never the other + /// way around. + bool isMonotonicPredicate(const SCEVAddRecExpr *LHS, ICmpInst::Predicate Pred, + bool &Increasing); + + /// Return true if the result of the predicate LHS `Pred` RHS is loop + /// invariant with respect to L. Set InvariantPred, InvariantLHS and + /// InvariantLHS so that InvariantLHS `InvariantPred` InvariantRHS is the + /// loop invariant form of LHS `Pred` RHS. + bool isLoopInvariantPredicate(ICmpInst::Predicate Pred, const SCEV *LHS, + const SCEV *RHS, const Loop *L, + ICmpInst::Predicate &InvariantPred, + const SCEV *&InvariantLHS, + const SCEV *&InvariantRHS); + + /// Simplify LHS and RHS in a comparison with predicate Pred. Return true + /// iff any changes were made. If the operands are provably equal or + /// unequal, LHS and RHS are set to the same value and Pred is set to either + /// ICMP_EQ or ICMP_NE. + bool SimplifyICmpOperands(ICmpInst::Predicate &Pred, const SCEV *&LHS, + const SCEV *&RHS, unsigned Depth = 0); + + /// Return the "disposition" of the given SCEV with respect to the given + /// loop. + LoopDisposition getLoopDisposition(const SCEV *S, const Loop *L); + + /// Return true if the value of the given SCEV is unchanging in the + /// specified loop. + bool isLoopInvariant(const SCEV *S, const Loop *L); + + /// Determine if the SCEV can be evaluated at loop's entry. It is true if it + /// doesn't depend on a SCEVUnknown of an instruction which is dominated by + /// the header of loop L. + bool isAvailableAtLoopEntry(const SCEV *S, const Loop *L); + + /// Return true if the given SCEV changes value in a known way in the + /// specified loop. This property being true implies that the value is + /// variant in the loop AND that we can emit an expression to compute the + /// value of the expression at any particular loop iteration. + bool hasComputableLoopEvolution(const SCEV *S, const Loop *L); + + /// Return the "disposition" of the given SCEV with respect to the given + /// block. + BlockDisposition getBlockDisposition(const SCEV *S, const BasicBlock *BB); + + /// Return true if elements that makes up the given SCEV dominate the + /// specified basic block. + bool dominates(const SCEV *S, const BasicBlock *BB); + + /// Return true if elements that makes up the given SCEV properly dominate + /// the specified basic block. + bool properlyDominates(const SCEV *S, const BasicBlock *BB); + + /// Test whether the given SCEV has Op as a direct or indirect operand. + bool hasOperand(const SCEV *S, const SCEV *Op) const; + + /// Return the size of an element read or written by Inst. + const SCEV *getElementSize(Instruction *Inst); + + /// Compute the array dimensions Sizes from the set of Terms extracted from + /// the memory access function of this SCEVAddRecExpr (second step of + /// delinearization). + void findArrayDimensions(SmallVectorImpl<const SCEV *> &Terms, + SmallVectorImpl<const SCEV *> &Sizes, + const SCEV *ElementSize); + + void print(raw_ostream &OS) const; + void verify() const; + bool invalidate(Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &Inv); + + /// 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 + /// (third step of delinearization). + void computeAccessFunctions(const SCEV *Expr, + SmallVectorImpl<const SCEV *> &Subscripts, + SmallVectorImpl<const SCEV *> &Sizes); + + /// Split this SCEVAddRecExpr into two vectors of SCEVs representing the + /// subscripts and sizes of an array access. + /// + /// The delinearization is a 3 step process: the first two steps compute the + /// sizes of each subscript and the third step computes the access functions + /// for the delinearized array: + /// + /// 1. Find the terms in the step functions + /// 2. Compute the array size + /// 3. Compute the access function: divide the SCEV by the array size + /// starting with the innermost dimensions found in step 2. The Quotient + /// is the SCEV to be divided in the next step of the recursion. The + /// Remainder is the subscript of the innermost dimension. Loop over all + /// array dimensions computed in step 2. + /// + /// To compute a uniform array size for several memory accesses to the same + /// object, one can collect in step 1 all the step terms for all the memory + /// accesses, and compute in step 2 a unique array shape. This guarantees + /// that the array shape will be the same across all memory accesses. + /// + /// FIXME: We could derive the result of steps 1 and 2 from a description of + /// the array shape given in metadata. + /// + /// Example: + /// + /// A[][n][m] + /// + /// for i + /// for j + /// for k + /// A[j+k][2i][5i] = + /// + /// The initial SCEV: + /// + /// A[{{{0,+,2*m+5}_i, +, n*m}_j, +, n*m}_k] + /// + /// 1. Find the different terms in the step functions: + /// -> [2*m, 5, n*m, n*m] + /// + /// 2. Compute the array size: sort and unique them + /// -> [n*m, 2*m, 5] + /// find the GCD of all the terms = 1 + /// divide by the GCD and erase constant terms + /// -> [n*m, 2*m] + /// GCD = m + /// divide by GCD -> [n, 2] + /// remove constant terms + /// -> [n] + /// size of the array is A[unknown][n][m] + /// + /// 3. Compute the access function + /// a. Divide {{{0,+,2*m+5}_i, +, n*m}_j, +, n*m}_k by the innermost size m + /// Quotient: {{{0,+,2}_i, +, n}_j, +, n}_k + /// Remainder: {{{0,+,5}_i, +, 0}_j, +, 0}_k + /// The remainder is the subscript of the innermost array dimension: [5i]. + /// + /// b. Divide Quotient: {{{0,+,2}_i, +, n}_j, +, n}_k by next outer size n + /// Quotient: {{{0,+,0}_i, +, 1}_j, +, 1}_k + /// Remainder: {{{0,+,2}_i, +, 0}_j, +, 0}_k + /// The Remainder is the subscript of the next array dimension: [2i]. + /// + /// The subscript of the outermost dimension is the Quotient: [j+k]. + /// + /// Overall, we have: A[][n][m], and the access function: A[j+k][2i][5i]. + void delinearize(const SCEV *Expr, SmallVectorImpl<const SCEV *> &Subscripts, + SmallVectorImpl<const SCEV *> &Sizes, + const SCEV *ElementSize); + + /// Return the DataLayout associated with the module this SCEV instance is + /// operating on. + const DataLayout &getDataLayout() const { + return F.getParent()->getDataLayout(); + } + + const SCEVPredicate *getEqualPredicate(const SCEV *LHS, const SCEV *RHS); + + 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, + SmallPtrSetImpl<const SCEVPredicate *> &Preds); + +private: + /// A CallbackVH to arrange for ScalarEvolution to be notified whenever a + /// Value is deleted. + class SCEVCallbackVH final : public CallbackVH { + ScalarEvolution *SE; + + void deleted() override; + void allUsesReplacedWith(Value *New) override; + + public: + SCEVCallbackVH(Value *V, ScalarEvolution *SE = nullptr); + }; + + friend class SCEVCallbackVH; + friend class SCEVExpander; + friend class SCEVUnknown; + + /// The function we are analyzing. + 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; + + /// The tracker for \@llvm.assume intrinsics in this function. + AssumptionCache &AC; + + /// The dominator tree. + DominatorTree &DT; + + /// The loop information for the function we are currently analyzing. + LoopInfo &LI; + + /// This SCEV is used to represent unknown trip counts and things. + std::unique_ptr<SCEVCouldNotCompute> CouldNotCompute; + + /// The type for HasRecMap. + using HasRecMapType = DenseMap<const SCEV *, bool>; + + /// This is a cache to record whether a SCEV contains any scAddRecExpr. + HasRecMapType HasRecMap; + + /// The type for ExprValueMap. + using ValueOffsetPair = std::pair<Value *, ConstantInt *>; + using ExprValueMapType = DenseMap<const SCEV *, SetVector<ValueOffsetPair>>; + + /// ExprValueMap -- This map records the original values from which + /// the SCEV expr is generated from. + /// + /// We want to represent the mapping as SCEV -> ValueOffsetPair instead + /// of SCEV -> Value: + /// Suppose we know S1 expands to V1, and + /// S1 = S2 + C_a + /// S3 = S2 + C_b + /// where C_a and C_b are different SCEVConstants. Then we'd like to + /// expand S3 as V1 - C_a + C_b instead of expanding S2 literally. + /// It is helpful when S2 is a complex SCEV expr. + /// + /// In order to do that, we represent ExprValueMap as a mapping from + /// SCEV to ValueOffsetPair. We will save both S1->{V1, 0} and + /// S2->{V1, C_a} into the map when we create SCEV for V1. When S3 + /// is expanded, it will first expand S2 to V1 - C_a because of + /// S2->{V1, C_a} in the map, then expand S3 to V1 - C_a + C_b. + /// + /// Note: S->{V, Offset} in the ExprValueMap means S can be expanded + /// to V - Offset. + ExprValueMapType ExprValueMap; + + /// The type for ValueExprMap. + using ValueExprMapType = + DenseMap<SCEVCallbackVH, const SCEV *, DenseMapInfo<Value *>>; + + /// This is a cache of the values we have analyzed so far. + ValueExprMapType ValueExprMap; + + /// Mark predicate values currently being processed by isImpliedCond. + SmallPtrSet<Value *, 6> PendingLoopPredicates; + + /// Mark SCEVUnknown Phis currently being processed by getRangeRef. + SmallPtrSet<const PHINode *, 6> PendingPhiRanges; + + // Mark SCEVUnknown Phis currently being processed by isImpliedViaMerge. + SmallPtrSet<const PHINode *, 6> PendingMerges; + + /// Set to true by isLoopBackedgeGuardedByCond when we're walking the set of + /// conditions dominating the backedge of a loop. + bool WalkingBEDominatingConds = false; + + /// Set to true by isKnownPredicateViaSplitting when we're trying to prove a + /// predicate by splitting it into a set of independent predicates. + bool ProvingSplitPredicate = false; + + /// Memoized values for the GetMinTrailingZeros + DenseMap<const SCEV *, uint32_t> MinTrailingZerosCache; + + /// Return the Value set from which the SCEV expr is generated. + SetVector<ValueOffsetPair> *getSCEVValues(const SCEV *S); + + /// Private helper method for the GetMinTrailingZeros method + uint32_t GetMinTrailingZerosImpl(const SCEV *S); + + /// Information about the number of loop iterations for which a loop exit's + /// branch condition evaluates to the not-taken path. This is a temporary + /// pair of exact and max expressions that are eventually summarized in + /// ExitNotTakenInfo and BackedgeTakenInfo. + struct ExitLimit { + const SCEV *ExactNotTaken; // The exit is not taken exactly this many times + const SCEV *MaxNotTaken; // The exit is not taken at most this many times + + // Not taken either exactly MaxNotTaken or zero times + bool MaxOrZero = false; + + /// A set of predicate guards for this ExitLimit. The result is only valid + /// if all of the predicates in \c Predicates evaluate to 'true' at + /// run-time. + SmallPtrSet<const SCEVPredicate *, 4> Predicates; + + void addPredicate(const SCEVPredicate *P) { + assert(!isa<SCEVUnionPredicate>(P) && "Only add leaf predicates here!"); + Predicates.insert(P); + } + + /// Construct either an exact exit limit from a constant, or an unknown + /// one from a SCEVCouldNotCompute. No other types of SCEVs are allowed + /// as arguments and asserts enforce that internally. + /*implicit*/ ExitLimit(const SCEV *E); + + ExitLimit( + const SCEV *E, const SCEV *M, bool MaxOrZero, + ArrayRef<const SmallPtrSetImpl<const SCEVPredicate *> *> PredSetList); + + ExitLimit(const SCEV *E, const SCEV *M, bool MaxOrZero, + const SmallPtrSetImpl<const SCEVPredicate *> &PredSet); + + ExitLimit(const SCEV *E, const SCEV *M, bool MaxOrZero); + + /// Test whether this ExitLimit contains any computed information, or + /// whether it's all SCEVCouldNotCompute values. + bool hasAnyInfo() const { + return !isa<SCEVCouldNotCompute>(ExactNotTaken) || + !isa<SCEVCouldNotCompute>(MaxNotTaken); + } + + bool hasOperand(const SCEV *S) const; + + /// Test whether this ExitLimit contains all information. + bool hasFullInfo() const { + return !isa<SCEVCouldNotCompute>(ExactNotTaken); + } + }; + + /// Information about the number of times a particular loop exit may be + /// reached before exiting the loop. + struct ExitNotTakenInfo { + PoisoningVH<BasicBlock> ExitingBlock; + const SCEV *ExactNotTaken; + const SCEV *MaxNotTaken; + std::unique_ptr<SCEVUnionPredicate> Predicate; + + explicit ExitNotTakenInfo(PoisoningVH<BasicBlock> ExitingBlock, + const SCEV *ExactNotTaken, + const SCEV *MaxNotTaken, + std::unique_ptr<SCEVUnionPredicate> Predicate) + : ExitingBlock(ExitingBlock), ExactNotTaken(ExactNotTaken), + MaxNotTaken(ExactNotTaken), Predicate(std::move(Predicate)) {} + + bool hasAlwaysTruePredicate() const { + return !Predicate || Predicate->isAlwaysTrue(); + } + }; + + /// Information about the backedge-taken count of a loop. This currently + /// includes an exact count and a maximum count. + /// + class BackedgeTakenInfo { + /// A list of computable exits and their not-taken counts. Loops almost + /// never have more than one computable exit. + SmallVector<ExitNotTakenInfo, 1> ExitNotTaken; + + /// The pointer part of \c MaxAndComplete is an expression indicating the + /// least maximum backedge-taken count of the loop that is known, or a + /// SCEVCouldNotCompute. This expression is only valid if the predicates + /// associated with all loop exits are true. + /// + /// The integer part of \c MaxAndComplete is a boolean indicating if \c + /// ExitNotTaken has an element for every exiting block in the loop. + PointerIntPair<const SCEV *, 1> MaxAndComplete; + + /// True iff the backedge is taken either exactly Max or zero times. + bool MaxOrZero = false; + + /// \name Helper projection functions on \c MaxAndComplete. + /// @{ + bool isComplete() const { return MaxAndComplete.getInt(); } + const SCEV *getMax() const { return MaxAndComplete.getPointer(); } + /// @} + + public: + BackedgeTakenInfo() : MaxAndComplete(nullptr, 0) {} + BackedgeTakenInfo(BackedgeTakenInfo &&) = default; + BackedgeTakenInfo &operator=(BackedgeTakenInfo &&) = default; + + using EdgeExitInfo = std::pair<BasicBlock *, ExitLimit>; + + /// Initialize BackedgeTakenInfo from a list of exact exit counts. + BackedgeTakenInfo(ArrayRef<EdgeExitInfo> ExitCounts, bool Complete, + const SCEV *MaxCount, bool MaxOrZero); + + /// Test whether this BackedgeTakenInfo contains any computed information, + /// or whether it's all SCEVCouldNotCompute values. + bool hasAnyInfo() const { + return !ExitNotTaken.empty() || !isa<SCEVCouldNotCompute>(getMax()); + } + + /// Test whether this BackedgeTakenInfo contains complete information. + bool hasFullInfo() const { return isComplete(); } + + /// Return an expression indicating the exact *backedge-taken* + /// count of the loop if it is known or SCEVCouldNotCompute + /// otherwise. If execution makes it to the backedge on every + /// iteration (i.e. there are no abnormal exists like exception + /// throws and thread exits) then this is the number of times the + /// loop header will execute minus one. + /// + /// 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(const Loop *L, 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 + /// this block before this number of iterations, but may exit via another + /// block. + const SCEV *getExact(BasicBlock *ExitingBlock, ScalarEvolution *SE) const; + + /// Get the max backedge taken count for the loop. + const SCEV *getMax(ScalarEvolution *SE) const; + + /// Get the max backedge taken count for the particular loop exit. + const SCEV *getMax(BasicBlock *ExitingBlock, ScalarEvolution *SE) const; + + /// Return true if the number of times this backedge is taken is either the + /// value returned by getMax or zero. + bool isMaxOrZero(ScalarEvolution *SE) const; + + /// Return true if any backedge taken count expressions refer to the given + /// subexpression. + bool hasOperand(const SCEV *S, ScalarEvolution *SE) const; + + /// Invalidate this result and free associated memory. + void clear(); + }; + + /// Cache the backedge-taken count of the loops for this function as they + /// are computed. + 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 + /// potentially expensive recomputation of these properties. An instruction + /// maps to null if we are unable to compute its exit value. + DenseMap<PHINode *, Constant *> ConstantEvolutionLoopExitValue; + + /// This map contains entries for all the expressions that we attempt to + /// compute getSCEVAtScope information for, which can be expensive in + /// extreme cases. + DenseMap<const SCEV *, SmallVector<std::pair<const Loop *, const SCEV *>, 2>> + ValuesAtScopes; + + /// Memoized computeLoopDisposition results. + DenseMap<const SCEV *, + SmallVector<PointerIntPair<const Loop *, 2, LoopDisposition>, 2>> + LoopDispositions; + + struct LoopProperties { + /// Set to true if the loop contains no instruction that can have side + /// effects (i.e. via throwing an exception, volatile or atomic access). + bool HasNoAbnormalExits; + + /// Set to true if the loop 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 HasNoSideEffects; + }; + + /// Cache for \c getLoopProperties. + DenseMap<const Loop *, LoopProperties> LoopPropertiesCache; + + /// Return a \c LoopProperties instance for \p L, creating one if necessary. + LoopProperties getLoopProperties(const Loop *L); + + bool loopHasNoSideEffects(const Loop *L) { + return getLoopProperties(L).HasNoSideEffects; + } + + bool loopHasNoAbnormalExits(const Loop *L) { + return getLoopProperties(L).HasNoAbnormalExits; + } + + /// Compute a LoopDisposition value. + LoopDisposition computeLoopDisposition(const SCEV *S, const Loop *L); + + /// Memoized computeBlockDisposition results. + DenseMap< + const SCEV *, + SmallVector<PointerIntPair<const BasicBlock *, 2, BlockDisposition>, 2>> + BlockDispositions; + + /// Compute a BlockDisposition value. + BlockDisposition computeBlockDisposition(const SCEV *S, const BasicBlock *BB); + + /// Memoized results from getRange + DenseMap<const SCEV *, ConstantRange> UnsignedRanges; + + /// Memoized results from getRange + DenseMap<const SCEV *, ConstantRange> SignedRanges; + + /// Used to parameterize getRange + enum RangeSignHint { HINT_RANGE_UNSIGNED, HINT_RANGE_SIGNED }; + + /// Set the memoized range for the given SCEV. + const ConstantRange &setRange(const SCEV *S, RangeSignHint Hint, + ConstantRange CR) { + DenseMap<const SCEV *, ConstantRange> &Cache = + Hint == HINT_RANGE_UNSIGNED ? UnsignedRanges : SignedRanges; + + auto Pair = Cache.try_emplace(S, std::move(CR)); + if (!Pair.second) + Pair.first->second = std::move(CR); + return Pair.first->second; + } + + /// Determine the range for a particular SCEV. + /// NOTE: This returns a reference to an entry in a cache. It must be + /// copied if its needed for longer. + const ConstantRange &getRangeRef(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); + + /// Provide the special handling we need to analyze PHI SCEVs. + const SCEV *createNodeForPHI(PHINode *PN); + + /// Helper function called from createNodeForPHI. + const SCEV *createAddRecFromPHI(PHINode *PN); + + /// A helper function for createAddRecFromPHI to handle simple cases. + const SCEV *createSimpleAffineAddRec(PHINode *PN, Value *BEValueV, + Value *StartValueV); + + /// Helper function called from createNodeForPHI. + const SCEV *createNodeFromSelectLikePHI(PHINode *PN); + + /// Provide special handling for a select-like instruction (currently this + /// is either a select instruction or a phi node). \p I is the instruction + /// being processed, and it is assumed equivalent to "Cond ? TrueVal : + /// FalseVal". + const SCEV *createNodeForSelectOrPHI(Instruction *I, Value *Cond, + Value *TrueVal, Value *FalseVal); + + /// Provide the special handling we need to analyze GEP SCEVs. + const SCEV *createNodeForGEP(GEPOperator *GEP); + + /// Implementation code for getSCEVAtScope; called at most once for each + /// SCEV+Loop pair. + const SCEV *computeSCEVAtScope(const SCEV *S, const Loop *L); + + /// 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); + + /// Return the BackedgeTakenInfo for the given loop, lazily computing new + /// 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. + /// 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. 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. + /// + /// \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, + bool ExitIfTrue, bool ControlsExit, + bool AllowPredicates = false); + + // Helper functions for computeExitLimitFromCond to avoid exponential time + // complexity. + + class ExitLimitCache { + // It may look like we need key on the whole (L, ExitIfTrue, ControlsExit, + // AllowPredicates) tuple, but recursive calls to + // computeExitLimitFromCondCached from computeExitLimitFromCondImpl only + // vary the in \c ExitCond and \c ControlsExit parameters. We remember the + // initial values of the other values to assert our assumption. + SmallDenseMap<PointerIntPair<Value *, 1>, ExitLimit> TripCountMap; + + const Loop *L; + bool ExitIfTrue; + bool AllowPredicates; + + public: + ExitLimitCache(const Loop *L, bool ExitIfTrue, bool AllowPredicates) + : L(L), ExitIfTrue(ExitIfTrue), AllowPredicates(AllowPredicates) {} + + Optional<ExitLimit> find(const Loop *L, Value *ExitCond, bool ExitIfTrue, + bool ControlsExit, bool AllowPredicates); + + void insert(const Loop *L, Value *ExitCond, bool ExitIfTrue, + bool ControlsExit, bool AllowPredicates, const ExitLimit &EL); + }; + + using ExitLimitCacheTy = ExitLimitCache; + + ExitLimit computeExitLimitFromCondCached(ExitLimitCacheTy &Cache, + const Loop *L, Value *ExitCond, + bool ExitIfTrue, + bool ControlsExit, + bool AllowPredicates); + ExitLimit computeExitLimitFromCondImpl(ExitLimitCacheTy &Cache, const Loop *L, + Value *ExitCond, bool ExitIfTrue, + bool ControlsExit, + bool AllowPredicates); + + /// 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 and ExitIfTrue. 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, + bool ExitIfTrue, + 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 + /// to ExitingBB. + ExitLimit computeExitLimitFromSingleExitSwitch(const Loop *L, + SwitchInst *Switch, + BasicBlock *ExitingBB, + bool IsSubExpr); + + /// Given an exit condition of 'icmp op load X, cst', try to see if we can + /// compute the backedge-taken count. + ExitLimit computeLoadConstantCompareExitLimit(LoadInst *LI, Constant *RHS, + const Loop *L, + ICmpInst::Predicate p); + + /// Compute the exit limit of a loop that is controlled by a + /// "(IV >> 1) != 0" type comparison. We cannot compute the exact trip + /// count in these cases (since SCEV has no way of expressing them), but we + /// can still sometimes compute an upper bound. + /// + /// Return an ExitLimit for a loop whose backedge is guarded by `LHS Pred + /// RHS`. + ExitLimit computeShiftCompareExitLimit(Value *LHS, Value *RHS, const Loop *L, + ICmpInst::Predicate Pred); + + /// If the loop is known to execute a constant number of times (the + /// condition evolves only from constants), try to evaluate a few iterations + /// of the loop until we get the exit condition gets a value of ExitWhen + /// (true or false). If we cannot evaluate the exit count of the loop, + /// return CouldNotCompute. + const SCEV *computeExitCountExhaustively(const Loop *L, Value *Cond, + bool ExitWhen); + + /// Return the number of times an exit condition comparing the specified + /// value to zero will execute. If not computable, return CouldNotCompute. + /// 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); + + /// Return the number of times an exit condition containing the specified + /// less-than comparison will execute. If not computable, return + /// 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 + /// no such block is found. + std::pair<BasicBlock *, BasicBlock *> + getPredecessorWithUniqueSuccessorForBB(BasicBlock *BB); + + /// Test whether the condition described by Pred, LHS, and RHS is true + /// whenever the given FoundCondValue value evaluates to true. + bool isImpliedCond(ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS, + Value *FoundCondValue, bool Inverse); + + /// Test whether the condition described by Pred, LHS, and RHS is true + /// whenever the condition described by FoundPred, FoundLHS, FoundRHS is + /// true. + bool isImpliedCond(ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS, + ICmpInst::Predicate FoundPred, const SCEV *FoundLHS, + const SCEV *FoundRHS); + + /// Test whether the condition described by Pred, LHS, and RHS is true + /// whenever the condition described by Pred, FoundLHS, and FoundRHS is + /// true. + bool isImpliedCondOperands(ICmpInst::Predicate Pred, const SCEV *LHS, + const SCEV *RHS, const SCEV *FoundLHS, + const SCEV *FoundRHS); + + /// Test whether the condition described by Pred, LHS, and RHS is true + /// whenever the condition described by Pred, FoundLHS, and FoundRHS is + /// true. Here LHS is an operation that includes FoundLHS as one of its + /// arguments. + bool isImpliedViaOperations(ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS, + const SCEV *FoundLHS, const SCEV *FoundRHS, + unsigned Depth = 0); + + /// Test whether the condition described by Pred, LHS, and RHS is true. + /// Use only simple non-recursive types of checks, such as range analysis etc. + bool isKnownViaNonRecursiveReasoning(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. + bool isImpliedCondOperandsHelper(ICmpInst::Predicate Pred, const SCEV *LHS, + const SCEV *RHS, const SCEV *FoundLHS, + const SCEV *FoundRHS); + + /// 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. 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. + /// + /// This routine tries to rule out certain kinds of integer overflow, and + /// then tries to reason about arithmetic properties of the predicates. + bool isImpliedCondOperandsViaNoOverflow(ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS, + const SCEV *FoundLHS, + const SCEV *FoundRHS); + + /// Test whether the condition described by Pred, LHS, and RHS is true + /// whenever the condition described by Pred, FoundLHS, and FoundRHS is + /// true. + /// + /// This routine tries to figure out predicate for Phis which are SCEVUnknown + /// if it is true for every possible incoming value from their respective + /// basic blocks. + bool isImpliedViaMerge(ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS, + const SCEV *FoundLHS, const SCEV *FoundRHS, + unsigned Depth); + + /// If we know that the specified Phi is in the header of its containing + /// loop, we know the loop executes a constant number of times, and the PHI + /// node is just a recurrence involving constants, fold it. + Constant *getConstantEvolutionLoopExitValue(PHINode *PN, const APInt &BEs, + const Loop *L); + + /// Test if the given expression is known to satisfy the condition described + /// by Pred and the known constant ranges of LHS and 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. + /// + /// For instance, this will return true for "A s< (A + C)<nsw>" if C is + /// positive. + bool isKnownPredicateViaNoOverflow(ICmpInst::Predicate Pred, const SCEV *LHS, + const SCEV *RHS); + + /// Try to split Pred LHS RHS into logical conjunctions (and's) and try to + /// prove them individually. + bool isKnownPredicateViaSplitting(ICmpInst::Predicate Pred, const SCEV *LHS, + const SCEV *RHS); + + /// Try to match the Expr as "(L + R)<Flags>". + bool splitBinaryAdd(const SCEV *Expr, const SCEV *&L, const SCEV *&R, + SCEV::NoWrapFlags &Flags); + + /// Compute \p LHS - \p RHS and returns the result as an APInt if it is a + /// constant, and None if it isn't. + /// + /// This is intended to be a cheaper version of getMinusSCEV. We can be + /// frugal here since we just bail out of actually constructing and + /// canonicalizing an expression in the cases where the result isn't going + /// to be a constant. + Optional<APInt> computeConstantDifference(const SCEV *LHS, const SCEV *RHS); + + /// Drop memoized information computed for S. + void forgetMemoizedResults(const SCEV *S); + + /// Return an existing SCEV for V if there is one, otherwise return nullptr. + const SCEV *getExistingSCEV(Value *V); + + /// Return false iff given SCEV contains a SCEVUnknown with NULL value- + /// pointer. + bool checkValidity(const SCEV *S) const; + + /// Return true if `ExtendOpTy`({`Start`,+,`Step`}) can be proved to be + /// equal to {`ExtendOpTy`(`Start`),+,`ExtendOpTy`(`Step`)}. This is + /// equivalent to proving no signed (resp. unsigned) wrap in + /// {`Start`,+,`Step`} if `ExtendOpTy` is `SCEVSignExtendExpr` + /// (resp. `SCEVZeroExtendExpr`). + template <typename ExtendOpTy> + 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); + + /// 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); + + /// Similar to createAddRecFromPHI, but with the additional flexibility of + /// suggesting runtime overflow checks in case casts are encountered. + /// If successful, the analysis records that for this loop, \p SymbolicPHI, + /// which is the UnknownSCEV currently representing the PHI, can be rewritten + /// into an AddRec, assuming some predicates; The function then returns the + /// AddRec and the predicates as a pair, and caches this pair in + /// PredicatedSCEVRewrites. + /// If the analysis is not successful, a mapping from the \p SymbolicPHI to + /// itself (with no predicates) is recorded, and a nullptr with an empty + /// predicates vector is returned as a pair. + Optional<std::pair<const SCEV *, SmallVector<const SCEVPredicate *, 3>>> + createAddRecFromPHIWithCastsImpl(const SCEVUnknown *SymbolicPHI); + + /// Compute the backedge taken count knowing the interval difference, the + /// stride and presence of the equality in the comparison. + const SCEV *computeBECount(const SCEV *Delta, const SCEV *Stride, + bool Equality); + + /// Compute the maximum backedge count based on the range of values + /// permitted by Start, End, and Stride. This is for loops of the form + /// {Start, +, Stride} LT End. + /// + /// Precondition: the induction variable is known to be positive. We *don't* + /// assert these preconditions so please be careful. + const SCEV *computeMaxBECountForLT(const SCEV *Start, const SCEV *Stride, + const SCEV *End, unsigned BitWidth, + bool IsSigned); + + /// Verify if an linear IV with positive stride can overflow when in a + /// less-than comparison, knowing the invariant term of the comparison, + /// the stride and the knowledge of NSW/NUW flags on the recurrence. + bool doesIVOverflowOnLT(const SCEV *RHS, const SCEV *Stride, bool IsSigned, + bool NoWrap); + + /// Verify if an linear IV with negative stride can overflow when in a + /// greater-than comparison, knowing the invariant term of the comparison, + /// the stride and the knowledge of NSW/NUW flags on the recurrence. + bool doesIVOverflowOnGT(const SCEV *RHS, const SCEV *Stride, bool IsSigned, + bool NoWrap); + + /// Get add expr already created or create a new one. + const SCEV *getOrCreateAddExpr(ArrayRef<const SCEV *> Ops, + SCEV::NoWrapFlags Flags); + + /// Get mul expr already created or create a new one. + const SCEV *getOrCreateMulExpr(ArrayRef<const SCEV *> Ops, + SCEV::NoWrapFlags Flags); + + // Get addrec expr already created or create a new one. + const SCEV *getOrCreateAddRecExpr(ArrayRef<const SCEV *> Ops, + const Loop *L, SCEV::NoWrapFlags Flags); + + /// Return x if \p Val is f(x) where f is a 1-1 function. + const SCEV *stripInjectiveFunctions(const SCEV *Val) const; + + /// Find all of the loops transitively used in \p S, and fill \p LoopsUsed. + /// A loop is considered "used" by an expression if it contains + /// an add rec on said loop. + void getUsedLoops(const SCEV *S, SmallPtrSetImpl<const Loop *> &LoopsUsed); + + /// Find all of the loops transitively used in \p S, and update \c LoopUsers + /// accordingly. + void addToLoopUseLists(const SCEV *S); + + /// Try to match the pattern generated by getURemExpr(A, B). If successful, + /// Assign A and B to LHS and RHS, respectively. + bool matchURem(const SCEV *Expr, const SCEV *&LHS, const SCEV *&RHS); + + /// Look for a SCEV expression with type `SCEVType` and operands `Ops` in + /// `UniqueSCEVs`. + /// + /// The first component of the returned tuple is the SCEV if found and null + /// otherwise. The second component is the `FoldingSetNodeID` that was + /// constructed to look up the SCEV and the third component is the insertion + /// point. + std::tuple<const SCEV *, FoldingSetNodeID, void *> + findExistingSCEVInCache(int SCEVType, ArrayRef<const SCEV *> Ops); + + FoldingSet<SCEV> UniqueSCEVs; + FoldingSet<SCEVPredicate> UniquePreds; + BumpPtrAllocator SCEVAllocator; + + /// This maps loops to a list of SCEV expressions that (transitively) use said + /// loop. + DenseMap<const Loop *, SmallVector<const SCEV *, 4>> LoopUsers; + + /// Cache tentative mappings from UnknownSCEVs in a Loop, to a SCEV expression + /// they can be rewritten into under certain predicates. + DenseMap<std::pair<const SCEVUnknown *, const Loop *>, + std::pair<const SCEV *, SmallVector<const SCEVPredicate *, 3>>> + PredicatedSCEVRewrites; + + /// The head of a linked list of all SCEVUnknown values that have been + /// allocated. This is used by releaseMemory to locate them all and call + /// their destructors. + SCEVUnknown *FirstUnknown = nullptr; +}; + +/// Analysis pass that exposes the \c ScalarEvolution for a function. +class ScalarEvolutionAnalysis + : public AnalysisInfoMixin<ScalarEvolutionAnalysis> { + friend AnalysisInfoMixin<ScalarEvolutionAnalysis>; + + static AnalysisKey Key; + +public: + using Result = ScalarEvolution; + + ScalarEvolution run(Function &F, FunctionAnalysisManager &AM); +}; + +/// Verifier pass for the \c ScalarEvolutionAnalysis results. +class ScalarEvolutionVerifierPass + : public PassInfoMixin<ScalarEvolutionVerifierPass> { +public: + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + +/// 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, FunctionAnalysisManager &AM); +}; + +class ScalarEvolutionWrapperPass : public FunctionPass { + std::unique_ptr<ScalarEvolution> SE; + +public: + static char ID; + + ScalarEvolutionWrapperPass(); + + ScalarEvolution &getSE() { return *SE; } + const ScalarEvolution &getSE() const { return *SE; } + + bool runOnFunction(Function &F) override; + void releaseMemory() override; + void getAnalysisUsage(AnalysisUsage &AU) const override; + void print(raw_ostream &OS, const Module * = nullptr) const override; + void verifyAnalysis() const override; +}; + +/// An interface layer with SCEV used to manage how we see SCEV expressions +/// for values in the context of existing predicates. We can add new +/// predicates, but we cannot remove them. +/// +/// This layer has multiple purposes: +/// - provides a simple interface for SCEV versioning. +/// - guarantees that the order of transformations applied on a SCEV +/// expression for a single Value is consistent across two different +/// getSCEV calls. This means that, for example, once we've obtained +/// an AddRec expression for a certain value through expression +/// rewriting, we will continue to get an AddRec expression for that +/// Value. +/// - lowers the number of expression rewrites. +class PredicatedScalarEvolution { +public: + PredicatedScalarEvolution(ScalarEvolution &SE, Loop &L); + + const SCEVUnionPredicate &getUnionPredicate() const; + + /// 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); + + /// Get the (predicated) backedge count for the analyzed loop. + const SCEV *getBackedgeTakenCount(); + + /// Adds a new predicate. + void addPredicate(const SCEVPredicate &Pred); + + /// 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; + + /// Check if \p AR1 and \p AR2 are equal, while taking into account + /// Equal predicates in Preds. + bool areAddRecsEqualWithPreds(const SCEVAddRecExpr *AR1, + const SCEVAddRecExpr *AR2) const; + +private: + /// 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. + using RewriteEntry = std::pair<unsigned, const SCEV *>; + + /// 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 = 0; + + /// The backedge taken count. + const SCEV *BackedgeCount = nullptr; +}; + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_SCALAREVOLUTION_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/ScalarEvolutionAliasAnalysis.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/ScalarEvolutionAliasAnalysis.h new file mode 100644 index 0000000..98d5323 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/ScalarEvolutionAliasAnalysis.h
@@ -0,0 +1,72 @@ +//===- ScalarEvolutionAliasAnalysis.h - SCEV-based AA -----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// \file +/// This is the interface for a SCEV-based alias analysis. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_SCALAREVOLUTIONALIASANALYSIS_H +#define LLVM_ANALYSIS_SCALAREVOLUTIONALIASANALYSIS_H + +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/ScalarEvolutionExpressions.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" +#include "llvm/Pass.h" + +namespace llvm { + +/// A simple alias analysis implementation that uses ScalarEvolution to answer +/// queries. +class SCEVAAResult : public AAResultBase<SCEVAAResult> { + ScalarEvolution &SE; + +public: + 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, + AAQueryInfo &AAQI); + +private: + Value *GetBaseValue(const SCEV *S); +}; + +/// Analysis pass providing a never-invalidated alias analysis result. +class SCEVAA : public AnalysisInfoMixin<SCEVAA> { + friend AnalysisInfoMixin<SCEVAA>; + static AnalysisKey Key; + +public: + typedef SCEVAAResult Result; + + SCEVAAResult run(Function &F, FunctionAnalysisManager &AM); +}; + +/// Legacy wrapper pass to provide the SCEVAAResult object. +class SCEVAAWrapperPass : public FunctionPass { + std::unique_ptr<SCEVAAResult> Result; + +public: + static char ID; + + SCEVAAWrapperPass(); + + SCEVAAResult &getResult() { return *Result; } + const SCEVAAResult &getResult() const { return *Result; } + + bool runOnFunction(Function &F) override; + void getAnalysisUsage(AnalysisUsage &AU) const override; +}; + +/// Creates an instance of \c SCEVAAWrapperPass. +FunctionPass *createSCEVAAWrapperPass(); + +} + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/ScalarEvolutionExpander.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/ScalarEvolutionExpander.h new file mode 100644 index 0000000..b4d7274 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/ScalarEvolutionExpander.h
@@ -0,0 +1,415 @@ +//===---- llvm/Analysis/ScalarEvolutionExpander.h - SCEV Exprs --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the classes used to generate code from scalar expressions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_SCALAREVOLUTIONEXPANDER_H +#define LLVM_ANALYSIS_SCALAREVOLUTIONEXPANDER_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/Optional.h" +#include "llvm/Analysis/ScalarEvolutionExpressions.h" +#include "llvm/Analysis/ScalarEvolutionNormalization.h" +#include "llvm/Analysis/TargetFolder.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/ValueHandle.h" + +namespace llvm { + class TargetTransformInfo; + + /// Return true if the given expression is safe to expand in the sense that + /// all materialized values are safe to speculate anywhere their operands are + /// defined. + bool isSafeToExpand(const SCEV *S, ScalarEvolution &SE); + + /// Return true if the given expression is safe to expand in the sense that + /// all materialized values are defined and safe to speculate at the specified + /// location and their operands are defined at this location. + bool isSafeToExpandAt(const SCEV *S, const Instruction *InsertionPoint, + ScalarEvolution &SE); + + /// This class uses information about analyze scalars to rewrite expressions + /// in canonical form. + /// + /// Clients should create an instance of this class when rewriting is needed, + /// and destroy it when finished to allow the release of the associated + /// memory. + class SCEVExpander : public SCEVVisitor<SCEVExpander, Value*> { + ScalarEvolution &SE; + const DataLayout &DL; + + // New instructions receive a name to identify them with the current pass. + const char* IVName; + + // InsertedExpressions caches Values for reuse, so must track RAUW. + DenseMap<std::pair<const SCEV *, Instruction *>, TrackingVH<Value>> + InsertedExpressions; + + // InsertedValues only flags inserted instructions so needs no RAUW. + DenseSet<AssertingVH<Value>> InsertedValues; + DenseSet<AssertingVH<Value>> InsertedPostIncValues; + + /// A memoization of the "relevant" loop for a given SCEV. + DenseMap<const SCEV *, const Loop *> RelevantLoops; + + /// Addrecs referring to any of the given loops are expanded in post-inc + /// mode. For example, expanding {1,+,1}<L> in post-inc mode returns the add + /// instruction that adds one to the phi for {0,+,1}<L>, as opposed to a new + /// phi starting at 1. This is only supported in non-canonical mode. + PostIncLoopSet PostIncLoops; + + /// When this is non-null, addrecs expanded in the loop it indicates should + /// be inserted with increments at IVIncInsertPos. + const Loop *IVIncInsertLoop; + + /// When expanding addrecs in the IVIncInsertLoop loop, insert the IV + /// increment at this position. + Instruction *IVIncInsertPos; + + /// Phis that complete an IV chain. Reuse + DenseSet<AssertingVH<PHINode>> ChainedPhis; + + /// When true, SCEVExpander tries to expand expressions in "canonical" form. + /// When false, expressions are expanded in a more literal form. + /// + /// In "canonical" form addrecs are expanded as arithmetic based on a + /// canonical induction variable. Note that CanonicalMode doesn't guarantee + /// that all expressions are expanded in "canonical" form. For some + /// expressions literal mode can be preferred. + bool CanonicalMode; + + /// When invoked from LSR, the expander is in "strength reduction" mode. The + /// only difference is that phi's are only reused if they are already in + /// "expanded" form. + bool LSRMode; + + 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 + + friend struct SCEVVisitor<SCEVExpander, Value*>; + + public: + /// Construct a SCEVExpander in "canonical" mode. + explicit SCEVExpander(ScalarEvolution &se, const DataLayout &DL, + const char *name) + : SE(se), DL(DL), IVName(name), IVIncInsertLoop(nullptr), + IVIncInsertPos(nullptr), CanonicalMode(true), LSRMode(false), + Builder(se.getContext(), TargetFolder(DL)) { +#ifndef NDEBUG + DebugType = ""; +#endif + } + + ~SCEVExpander() { + // Make sure the insert point guard stack is consistent. + assert(InsertPointGuards.empty()); + } + +#ifndef NDEBUG + void setDebugType(const char* s) { DebugType = s; } +#endif + + /// Erase the contents of the InsertedExpressions map so that users trying + /// to expand the same expression into multiple BasicBlocks or different + /// places within the same BasicBlock can do so. + void clear() { + InsertedExpressions.clear(); + InsertedValues.clear(); + InsertedPostIncValues.clear(); + ChainedPhis.clear(); + } + + /// Return true for expressions that may incur non-trivial cost to evaluate + /// at runtime. + /// + /// At is an optional parameter which specifies point in code where user is + /// going to expand this expression. Sometimes this knowledge can lead to a + /// more accurate cost estimation. + bool isHighCostExpansion(const SCEV *Expr, Loop *L, + const Instruction *At = nullptr) { + SmallPtrSet<const SCEV *, 8> Processed; + return isHighCostExpansionHelper(Expr, L, At, Processed); + } + + /// This method returns the canonical induction variable of the specified + /// type for the specified loop (inserting one if there is none). A + /// canonical induction variable starts at zero and steps by one on each + /// iteration. + PHINode *getOrInsertCanonicalInductionVariable(const Loop *L, Type *Ty); + + /// Return the induction variable increment's IV operand. + Instruction *getIVIncOperand(Instruction *IncV, Instruction *InsertPos, + bool allowScale); + + /// Utility for hoisting an IV increment. + bool hoistIVInc(Instruction *IncV, Instruction *InsertPos); + + /// replace congruent phis with their most canonical representative. Return + /// the number of phis eliminated. + unsigned replaceCongruentIVs(Loop *L, const DominatorTree *DT, + SmallVectorImpl<WeakTrackingVH> &DeadInsts, + const TargetTransformInfo *TTI = nullptr); + + /// Insert code to directly compute the specified SCEV expression into the + /// program. The inserted code is inserted into the specified block. + Value *expandCodeFor(const SCEV *SH, Type *Ty, Instruction *I); + + /// Insert code to directly compute the specified SCEV expression into the + /// program. The inserted code is inserted into the SCEVExpander's current + /// insertion point. If a type is specified, the result will be expanded to + /// have that type, with a cast if necessary. + Value *expandCodeFor(const SCEV *SH, Type *Ty = nullptr); + + + /// Generates a code sequence that evaluates this predicate. The inserted + /// instructions will be at position \p Loc. The result will be of type i1 + /// and will have a value of 0 when the predicate is false and 1 otherwise. + Value *expandCodeForPredicate(const SCEVPredicate *Pred, Instruction *Loc); + + /// A specialized variant of expandCodeForPredicate, handling the case when + /// we are expanding code for a SCEVEqualPredicate. + Value *expandEqualPredicate(const SCEVEqualPredicate *Pred, + Instruction *Loc); + + /// Generates code that evaluates if the \p AR expression will overflow. + Value *generateOverflowCheck(const SCEVAddRecExpr *AR, Instruction *Loc, + bool Signed); + + /// A specialized variant of expandCodeForPredicate, handling the case when + /// we are expanding code for a SCEVWrapPredicate. + Value *expandWrapPredicate(const SCEVWrapPredicate *P, Instruction *Loc); + + /// A specialized variant of expandCodeForPredicate, handling the case when + /// we are expanding code for a SCEVUnionPredicate. + Value *expandUnionPredicate(const SCEVUnionPredicate *Pred, + Instruction *Loc); + + /// Set the current IV increment loop and position. + void setIVIncInsertPos(const Loop *L, Instruction *Pos) { + assert(!CanonicalMode && + "IV increment positions are not supported in CanonicalMode"); + IVIncInsertLoop = L; + IVIncInsertPos = Pos; + } + + /// Enable post-inc expansion for addrecs referring to the given + /// loops. Post-inc expansion is only supported in non-canonical mode. + void setPostInc(const PostIncLoopSet &L) { + assert(!CanonicalMode && + "Post-inc expansion is not supported in CanonicalMode"); + PostIncLoops = L; + } + + /// Disable all post-inc expansion. + void clearPostInc() { + PostIncLoops.clear(); + + // When we change the post-inc loop set, cached expansions may no + // longer be valid. + InsertedPostIncValues.clear(); + } + + /// Disable the behavior of expanding expressions in canonical form rather + /// than in a more literal form. Non-canonical mode is useful for late + /// optimization passes. + void disableCanonicalMode() { CanonicalMode = false; } + + void enableLSRMode() { LSRMode = true; } + + /// Set the current insertion point. This is useful if multiple calls to + /// expandCodeFor() are going to be made with the same insert point and the + /// insert point may be moved during one of the expansions (e.g. if the + /// insert point is not a block terminator). + void setInsertPoint(Instruction *IP) { + assert(IP); + Builder.SetInsertPoint(IP); + } + + /// Clear the current insertion point. This is useful if the instruction + /// that had been serving as the insertion point may have been deleted. + void clearInsertPoint() { Builder.ClearInsertionPoint(); } + + /// Set location information used by debugging information. + void SetCurrentDebugLocation(DebugLoc L) { + Builder.SetCurrentDebugLocation(std::move(L)); + } + + /// Get location information used by debugging information. + const DebugLoc &getCurrentDebugLocation() const { + return Builder.getCurrentDebugLocation(); + } + + /// Return true if the specified instruction was inserted by the code + /// rewriter. If so, the client should not modify the instruction. + bool isInsertedInstruction(Instruction *I) const { + return InsertedValues.count(I) || InsertedPostIncValues.count(I); + } + + void setChainedPhi(PHINode *PN) { ChainedPhis.insert(PN); } + + /// Try to find existing LLVM IR value for S available at the point At. + Value *getExactExistingExpansion(const SCEV *S, const Instruction *At, + Loop *L); + + /// Try to find the ValueOffsetPair for S. The function is mainly used to + /// check whether S can be expanded cheaply. If this returns a non-None + /// value, we know we can codegen the `ValueOffsetPair` into a suitable + /// expansion identical with S so that S can be expanded cheaply. + /// + /// L is a hint which tells in which loop to look for the suitable value. + /// On success return value which is equivalent to the expanded S at point + /// At. Return nullptr if value was not found. + /// + /// Note that this function does not perform an exhaustive search. I.e if it + /// didn't find any value it does not mean that there is no such value. + /// + Optional<ScalarEvolution::ValueOffsetPair> + getRelatedExistingExpansion(const SCEV *S, const Instruction *At, Loop *L); + + private: + LLVMContext &getContext() const { return SE.getContext(); } + + /// Recursive helper function for isHighCostExpansion. + bool isHighCostExpansionHelper(const SCEV *S, Loop *L, + const Instruction *At, + SmallPtrSetImpl<const SCEV *> &Processed); + + /// Insert the specified binary operator, doing a small amount of work to + /// avoid inserting an obviously redundant operation, and hoisting to an + /// outer loop when the opportunity is there and it is safe. + Value *InsertBinop(Instruction::BinaryOps Opcode, Value *LHS, Value *RHS, + SCEV::NoWrapFlags Flags, bool IsSafeToHoist); + + /// Arrange for there to be a cast of V to Ty at IP, reusing an existing + /// cast if a suitable one exists, moving an existing cast if a suitable one + /// exists but isn't in the right place, or creating a new one. + Value *ReuseOrCreateCast(Value *V, Type *Ty, + Instruction::CastOps Op, + BasicBlock::iterator IP); + + /// Insert a cast of V to the specified type, which must be possible with a + /// noop cast, doing what we can to share the casts. + Value *InsertNoopCastOfTo(Value *V, Type *Ty); + + /// Expand a SCEVAddExpr with a pointer type into a GEP instead of using + /// ptrtoint+arithmetic+inttoptr. + Value *expandAddToGEP(const SCEV *const *op_begin, + const SCEV *const *op_end, + PointerType *PTy, Type *Ty, Value *V); + Value *expandAddToGEP(const SCEV *Op, PointerType *PTy, Type *Ty, Value *V); + + /// Find a previous Value in ExprValueMap for expand. + ScalarEvolution::ValueOffsetPair + FindValueInExprValueMap(const SCEV *S, const Instruction *InsertPt); + + Value *expand(const SCEV *S); + + /// Determine the most "relevant" loop for the given SCEV. + const Loop *getRelevantLoop(const SCEV *); + + Value *visitConstant(const SCEVConstant *S) { + return S->getValue(); + } + + Value *visitTruncateExpr(const SCEVTruncateExpr *S); + + Value *visitZeroExtendExpr(const SCEVZeroExtendExpr *S); + + Value *visitSignExtendExpr(const SCEVSignExtendExpr *S); + + Value *visitAddExpr(const SCEVAddExpr *S); + + Value *visitMulExpr(const SCEVMulExpr *S); + + Value *visitUDivExpr(const SCEVUDivExpr *S); + + Value *visitAddRecExpr(const SCEVAddRecExpr *S); + + Value *visitSMaxExpr(const SCEVSMaxExpr *S); + + Value *visitUMaxExpr(const SCEVUMaxExpr *S); + + Value *visitSMinExpr(const SCEVSMinExpr *S); + + Value *visitUMinExpr(const SCEVUMinExpr *S); + + Value *visitUnknown(const SCEVUnknown *S) { + return S->getValue(); + } + + void rememberInstruction(Value *I); + + bool isNormalAddRecExprPHI(PHINode *PN, Instruction *IncV, const Loop *L); + + bool isExpandedAddRecExprPHI(PHINode *PN, Instruction *IncV, const Loop *L); + + Value *expandAddRecExprLiterally(const SCEVAddRecExpr *); + PHINode *getAddRecExprPHILiterally(const SCEVAddRecExpr *Normalized, + const Loop *L, + Type *ExpandTy, + Type *IntTy, + Type *&TruncTy, + 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); + }; +} + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h new file mode 100644 index 0000000..d008af7 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h
@@ -0,0 +1,854 @@ +//===- llvm/Analysis/ScalarEvolutionExpressions.h - SCEV Exprs --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the classes used to represent and build scalar expressions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_SCALAREVOLUTIONEXPRESSIONS_H +#define LLVM_ANALYSIS_SCALAREVOLUTIONEXPRESSIONS_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Analysis/ScalarEvolution.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Value.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" +#include <cassert> +#include <cstddef> + +namespace llvm { + +class APInt; +class Constant; +class ConstantRange; +class Loop; +class Type; + + enum SCEVTypes { + // These should be ordered in terms of increasing complexity to make the + // folders simpler. + scConstant, scTruncate, scZeroExtend, scSignExtend, scAddExpr, scMulExpr, + scUDivExpr, scAddRecExpr, scUMaxExpr, scSMaxExpr, scUMinExpr, scSMinExpr, + scUnknown, scCouldNotCompute + }; + + /// This class represents a constant integer value. + class SCEVConstant : public SCEV { + friend class ScalarEvolution; + + ConstantInt *V; + + SCEVConstant(const FoldingSetNodeIDRef ID, ConstantInt *v) : + SCEV(ID, scConstant, 1), V(v) {} + + public: + ConstantInt *getValue() const { return V; } + const APInt &getAPInt() const { return getValue()->getValue(); } + + Type *getType() const { return V->getType(); } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const SCEV *S) { + return S->getSCEVType() == scConstant; + } + }; + + static unsigned short computeExpressionSize(ArrayRef<const SCEV *> Args) { + APInt Size(16, 1); + for (auto *Arg : Args) + Size = Size.uadd_sat(APInt(16, Arg->getExpressionSize())); + return (unsigned short)Size.getZExtValue(); + } + + /// This is the base class for unary cast operator classes. + class SCEVCastExpr : public SCEV { + protected: + const SCEV *Op; + Type *Ty; + + SCEVCastExpr(const FoldingSetNodeIDRef ID, + unsigned SCEVTy, const SCEV *op, Type *ty); + + public: + const SCEV *getOperand() const { return Op; } + Type *getType() const { return Ty; } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const SCEV *S) { + return S->getSCEVType() == scTruncate || + S->getSCEVType() == scZeroExtend || + S->getSCEVType() == scSignExtend; + } + }; + + /// This class represents a truncation of an integer value to a + /// smaller integer value. + class SCEVTruncateExpr : public SCEVCastExpr { + friend class ScalarEvolution; + + SCEVTruncateExpr(const FoldingSetNodeIDRef ID, + const SCEV *op, Type *ty); + + public: + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const SCEV *S) { + return S->getSCEVType() == scTruncate; + } + }; + + /// This class represents a zero extension of a small integer value + /// to a larger integer value. + class SCEVZeroExtendExpr : public SCEVCastExpr { + friend class ScalarEvolution; + + SCEVZeroExtendExpr(const FoldingSetNodeIDRef ID, + const SCEV *op, Type *ty); + + public: + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const SCEV *S) { + return S->getSCEVType() == scZeroExtend; + } + }; + + /// This class represents a sign extension of a small integer value + /// to a larger integer value. + class SCEVSignExtendExpr : public SCEVCastExpr { + friend class ScalarEvolution; + + SCEVSignExtendExpr(const FoldingSetNodeIDRef ID, + const SCEV *op, Type *ty); + + public: + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const SCEV *S) { + return S->getSCEVType() == scSignExtend; + } + }; + + /// 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 + // arrays with its SCEVAllocator, so this class just needs a simple + // pointer rather than a more elaborate vector-like data structure. + // This also avoids the need for a non-trivial destructor. + const SCEV *const *Operands; + size_t NumOperands; + + SCEVNAryExpr(const FoldingSetNodeIDRef ID, enum SCEVTypes T, + const SCEV *const *O, size_t N) + : SCEV(ID, T, computeExpressionSize(makeArrayRef(O, N))), Operands(O), + NumOperands(N) {} + + public: + size_t getNumOperands() const { return NumOperands; } + + const SCEV *getOperand(unsigned i) const { + assert(i < NumOperands && "Operand index out of range!"); + return Operands[i]; + } + + using op_iterator = const SCEV *const *; + using op_range = iterator_range<op_iterator>; + + op_iterator op_begin() const { return Operands; } + op_iterator op_end() const { return Operands + NumOperands; } + op_range operands() const { + return make_range(op_begin(), op_end()); + } + + Type *getType() const { return getOperand(0)->getType(); } + + NoWrapFlags getNoWrapFlags(NoWrapFlags Mask = NoWrapMask) const { + 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 bool classof(const SCEV *S) { + return S->getSCEVType() == scAddExpr || S->getSCEVType() == scMulExpr || + S->getSCEVType() == scSMaxExpr || S->getSCEVType() == scUMaxExpr || + S->getSCEVType() == scSMinExpr || S->getSCEVType() == scUMinExpr || + S->getSCEVType() == scAddRecExpr; + } + }; + + /// This node is the base class for n'ary commutative operators. + class SCEVCommutativeExpr : public SCEVNAryExpr { + protected: + SCEVCommutativeExpr(const FoldingSetNodeIDRef ID, + enum SCEVTypes T, const SCEV *const *O, size_t N) + : SCEVNAryExpr(ID, T, O, N) {} + + public: + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const SCEV *S) { + return S->getSCEVType() == scAddExpr || S->getSCEVType() == scMulExpr || + S->getSCEVType() == scSMaxExpr || S->getSCEVType() == scUMaxExpr || + S->getSCEVType() == scSMinExpr || S->getSCEVType() == scUMinExpr; + } + + /// Set flags for a non-recurrence without clearing previously set flags. + void setNoWrapFlags(NoWrapFlags Flags) { + SubclassData |= Flags; + } + }; + + /// This node represents an addition of some number of SCEVs. + class SCEVAddExpr : public SCEVCommutativeExpr { + friend class ScalarEvolution; + + SCEVAddExpr(const FoldingSetNodeIDRef ID, + const SCEV *const *O, size_t N) + : SCEVCommutativeExpr(ID, scAddExpr, O, N) {} + + public: + Type *getType() const { + // Use the type of the last operand, which is likely to be a pointer + // type, if there is one. This doesn't usually matter, but it can help + // reduce casts when the expressions are expanded. + return getOperand(getNumOperands() - 1)->getType(); + } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const SCEV *S) { + return S->getSCEVType() == scAddExpr; + } + }; + + /// This node represents multiplication of some number of SCEVs. + class SCEVMulExpr : public SCEVCommutativeExpr { + friend class ScalarEvolution; + + SCEVMulExpr(const FoldingSetNodeIDRef ID, + const SCEV *const *O, size_t N) + : SCEVCommutativeExpr(ID, scMulExpr, O, N) {} + + public: + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const SCEV *S) { + return S->getSCEVType() == scMulExpr; + } + }; + + /// This class represents a binary unsigned division operation. + class SCEVUDivExpr : public SCEV { + friend class ScalarEvolution; + + const SCEV *LHS; + const SCEV *RHS; + + SCEVUDivExpr(const FoldingSetNodeIDRef ID, const SCEV *lhs, const SCEV *rhs) + : SCEV(ID, scUDivExpr, computeExpressionSize({lhs, rhs})), LHS(lhs), + RHS(rhs) {} + + public: + const SCEV *getLHS() const { return LHS; } + const SCEV *getRHS() const { return RHS; } + + Type *getType() const { + // In most cases the types of LHS and RHS will be the same, but in some + // crazy cases one or the other may be a pointer. ScalarEvolution doesn't + // depend on the type for correctness, but handling types carefully can + // avoid extra casts in the SCEVExpander. The LHS is more likely to be + // a pointer type than the RHS, so use the RHS' type here. + return getRHS()->getType(); + } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const SCEV *S) { + return S->getSCEVType() == scUDivExpr; + } + }; + + /// 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. + /// + class SCEVAddRecExpr : public SCEVNAryExpr { + friend class ScalarEvolution; + + const Loop *L; + + SCEVAddRecExpr(const FoldingSetNodeIDRef ID, + const SCEV *const *O, size_t N, const Loop *l) + : SCEVNAryExpr(ID, scAddRecExpr, O, N), L(l) {} + + public: + const SCEV *getStart() const { return Operands[0]; } + const Loop *getLoop() const { return L; } + + /// 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, + op_end()), + getLoop(), FlagAnyWrap); + } + + /// 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; + } + + /// 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; + } + + /// Set flags for a recurrence without clearing any previously set flags. + /// For AddRec, either NUW or NSW implies NW. Keep track of this fact here + /// to make it easier to propagate flags. + void setNoWrapFlags(NoWrapFlags Flags) { + if (Flags & (FlagNUW | FlagNSW)) + Flags = ScalarEvolution::setFlags(Flags, FlagNW); + SubclassData |= Flags; + } + + /// Return the value of this chain of recurrences at the specified + /// iteration number. + const SCEV *evaluateAtIteration(const SCEV *It, 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; + + /// Return an expression representing the value of this expression + /// one iteration of the loop ahead. + const SCEVAddRecExpr *getPostIncExpr(ScalarEvolution &SE) const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const SCEV *S) { + return S->getSCEVType() == scAddRecExpr; + } + }; + + /// This node is the base class min/max selections. + class SCEVMinMaxExpr : public SCEVCommutativeExpr { + friend class ScalarEvolution; + + static bool isMinMaxType(enum SCEVTypes T) { + return T == scSMaxExpr || T == scUMaxExpr || T == scSMinExpr || + T == scUMinExpr; + } + + protected: + /// Note: Constructing subclasses via this constructor is allowed + SCEVMinMaxExpr(const FoldingSetNodeIDRef ID, enum SCEVTypes T, + const SCEV *const *O, size_t N) + : SCEVCommutativeExpr(ID, T, O, N) { + assert(isMinMaxType(T)); + // Min and max never overflow + setNoWrapFlags((NoWrapFlags)(FlagNUW | FlagNSW)); + } + + public: + static bool classof(const SCEV *S) { + return isMinMaxType(static_cast<SCEVTypes>(S->getSCEVType())); + } + + static enum SCEVTypes negate(enum SCEVTypes T) { + switch (T) { + case scSMaxExpr: + return scSMinExpr; + case scSMinExpr: + return scSMaxExpr; + case scUMaxExpr: + return scUMinExpr; + case scUMinExpr: + return scUMaxExpr; + default: + llvm_unreachable("Not a min or max SCEV type!"); + } + } + }; + + /// This class represents a signed maximum selection. + class SCEVSMaxExpr : public SCEVMinMaxExpr { + friend class ScalarEvolution; + + SCEVSMaxExpr(const FoldingSetNodeIDRef ID, const SCEV *const *O, size_t N) + : SCEVMinMaxExpr(ID, scSMaxExpr, O, N) {} + + public: + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const SCEV *S) { + return S->getSCEVType() == scSMaxExpr; + } + }; + + /// This class represents an unsigned maximum selection. + class SCEVUMaxExpr : public SCEVMinMaxExpr { + friend class ScalarEvolution; + + SCEVUMaxExpr(const FoldingSetNodeIDRef ID, const SCEV *const *O, size_t N) + : SCEVMinMaxExpr(ID, scUMaxExpr, O, N) {} + + public: + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const SCEV *S) { + return S->getSCEVType() == scUMaxExpr; + } + }; + + /// This class represents a signed minimum selection. + class SCEVSMinExpr : public SCEVMinMaxExpr { + friend class ScalarEvolution; + + SCEVSMinExpr(const FoldingSetNodeIDRef ID, const SCEV *const *O, size_t N) + : SCEVMinMaxExpr(ID, scSMinExpr, O, N) {} + + public: + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const SCEV *S) { + return S->getSCEVType() == scSMinExpr; + } + }; + + /// This class represents an unsigned minimum selection. + class SCEVUMinExpr : public SCEVMinMaxExpr { + friend class ScalarEvolution; + + SCEVUMinExpr(const FoldingSetNodeIDRef ID, const SCEV *const *O, size_t N) + : SCEVMinMaxExpr(ID, scUMinExpr, O, N) {} + + public: + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const SCEV *S) { + return S->getSCEVType() == scUMinExpr; + } + }; + + /// 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; + + /// 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; + + /// The next pointer in the linked list of all SCEVUnknown + /// instances owned by a ScalarEvolution. + SCEVUnknown *Next; + + SCEVUnknown(const FoldingSetNodeIDRef ID, Value *V, + ScalarEvolution *se, SCEVUnknown *next) : + SCEV(ID, scUnknown, 1), CallbackVH(V), SE(se), Next(next) {} + + // Implement CallbackVH. + void deleted() override; + void allUsesReplacedWith(Value *New) override; + + public: + Value *getValue() const { return getValPtr(); } + + /// @{ + /// 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(); } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const SCEV *S) { + return S->getSCEVType() == scUnknown; + } + }; + + /// 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) { + switch (S->getSCEVType()) { + case scConstant: + return ((SC*)this)->visitConstant((const SCEVConstant*)S); + case scTruncate: + return ((SC*)this)->visitTruncateExpr((const SCEVTruncateExpr*)S); + case scZeroExtend: + return ((SC*)this)->visitZeroExtendExpr((const SCEVZeroExtendExpr*)S); + case scSignExtend: + return ((SC*)this)->visitSignExtendExpr((const SCEVSignExtendExpr*)S); + case scAddExpr: + return ((SC*)this)->visitAddExpr((const SCEVAddExpr*)S); + case scMulExpr: + return ((SC*)this)->visitMulExpr((const SCEVMulExpr*)S); + case scUDivExpr: + return ((SC*)this)->visitUDivExpr((const SCEVUDivExpr*)S); + case scAddRecExpr: + return ((SC*)this)->visitAddRecExpr((const SCEVAddRecExpr*)S); + case scSMaxExpr: + return ((SC*)this)->visitSMaxExpr((const SCEVSMaxExpr*)S); + case scUMaxExpr: + return ((SC*)this)->visitUMaxExpr((const SCEVUMaxExpr*)S); + case scSMinExpr: + return ((SC *)this)->visitSMinExpr((const SCEVSMinExpr *)S); + case scUMinExpr: + return ((SC *)this)->visitUMinExpr((const SCEVUMinExpr *)S); + case scUnknown: + return ((SC*)this)->visitUnknown((const SCEVUnknown*)S); + case scCouldNotCompute: + return ((SC*)this)->visitCouldNotCompute((const SCEVCouldNotCompute*)S); + default: + llvm_unreachable("Unknown SCEV type!"); + } + } + + RetVal visitCouldNotCompute(const SCEVCouldNotCompute *S) { + llvm_unreachable("Invalid use of SCEVCouldNotCompute!"); + } + }; + + /// Visit all nodes in the expression tree using worklist traversal. + /// + /// Visitor implements: + /// // return true to follow this node. + /// bool follow(const SCEV *S); + /// // return true to terminate the search. + /// bool isDone(); + template<typename SV> + class SCEVTraversal { + SV &Visitor; + SmallVector<const SCEV *, 8> Worklist; + SmallPtrSet<const SCEV *, 8> Visited; + + void push(const SCEV *S) { + if (Visited.insert(S).second && Visitor.follow(S)) + Worklist.push_back(S); + } + + public: + SCEVTraversal(SV& V): Visitor(V) {} + + void visitAll(const SCEV *Root) { + push(Root); + while (!Worklist.empty() && !Visitor.isDone()) { + const SCEV *S = Worklist.pop_back_val(); + + switch (S->getSCEVType()) { + case scConstant: + case scUnknown: + break; + case scTruncate: + case scZeroExtend: + case scSignExtend: + push(cast<SCEVCastExpr>(S)->getOperand()); + break; + case scAddExpr: + case scMulExpr: + case scSMaxExpr: + case scUMaxExpr: + case scSMinExpr: + case scUMinExpr: + case scAddRecExpr: + for (const auto *Op : cast<SCEVNAryExpr>(S)->operands()) + push(Op); + break; + case scUDivExpr: { + const SCEVUDivExpr *UDiv = cast<SCEVUDivExpr>(S); + push(UDiv->getLHS()); + push(UDiv->getRHS()); + break; + } + case scCouldNotCompute: + llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!"); + default: + llvm_unreachable("Unknown SCEV kind!"); + } + } + } + }; + + /// Use SCEVTraversal to visit all nodes in the given expression tree. + template<typename SV> + void visitAll(const SCEV *Root, SV& Visitor) { + SCEVTraversal<SV> T(Visitor); + T.visitAll(Root); + } + + /// Return true if any node in \p Root satisfies the predicate \p Pred. + template <typename PredTy> + bool SCEVExprContains(const SCEV *Root, PredTy Pred) { + struct FindClosure { + bool Found = false; + PredTy Pred; + + FindClosure(PredTy Pred) : Pred(Pred) {} + + bool follow(const SCEV *S) { + if (!Pred(S)) + return true; + + Found = true; + return false; + } + + bool isDone() const { return Found; } + }; + + FindClosure FC(Pred); + visitAll(Root, FC); + return FC.Found; + } + + /// This visitor recursively visits a SCEV expression and re-writes it. + /// The result from each visit is cached, so it will return the same + /// SCEV for the same input. + template<typename SC> + class SCEVRewriteVisitor : public SCEVVisitor<SC, const SCEV *> { + protected: + ScalarEvolution &SE; + // Memoize the result of each visit so that we only compute once for + // the same input SCEV. This is to avoid redundant computations when + // a SCEV is referenced by multiple SCEVs. Without memoization, this + // visit algorithm would have exponential time complexity in the worst + // case, causing the compiler to hang on certain tests. + DenseMap<const SCEV *, const SCEV *> RewriteResults; + + public: + SCEVRewriteVisitor(ScalarEvolution &SE) : SE(SE) {} + + const SCEV *visit(const SCEV *S) { + auto It = RewriteResults.find(S); + if (It != RewriteResults.end()) + return It->second; + auto* Visited = SCEVVisitor<SC, const SCEV *>::visit(S); + auto Result = RewriteResults.try_emplace(S, Visited); + assert(Result.second && "Should insert a new entry"); + return Result.first->second; + } + + const SCEV *visitConstant(const SCEVConstant *Constant) { + return Constant; + } + + const SCEV *visitTruncateExpr(const SCEVTruncateExpr *Expr) { + const SCEV *Operand = ((SC*)this)->visit(Expr->getOperand()); + return Operand == Expr->getOperand() + ? Expr + : SE.getTruncateExpr(Operand, Expr->getType()); + } + + const SCEV *visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) { + const SCEV *Operand = ((SC*)this)->visit(Expr->getOperand()); + return Operand == Expr->getOperand() + ? Expr + : SE.getZeroExtendExpr(Operand, Expr->getType()); + } + + const SCEV *visitSignExtendExpr(const SCEVSignExtendExpr *Expr) { + const SCEV *Operand = ((SC*)this)->visit(Expr->getOperand()); + return Operand == Expr->getOperand() + ? Expr + : SE.getSignExtendExpr(Operand, Expr->getType()); + } + + const SCEV *visitAddExpr(const SCEVAddExpr *Expr) { + SmallVector<const SCEV *, 2> Operands; + bool Changed = false; + for (auto *Op : Expr->operands()) { + Operands.push_back(((SC*)this)->visit(Op)); + Changed |= Op != Operands.back(); + } + return !Changed ? Expr : SE.getAddExpr(Operands); + } + + const SCEV *visitMulExpr(const SCEVMulExpr *Expr) { + SmallVector<const SCEV *, 2> Operands; + bool Changed = false; + for (auto *Op : Expr->operands()) { + Operands.push_back(((SC*)this)->visit(Op)); + Changed |= Op != Operands.back(); + } + return !Changed ? Expr : SE.getMulExpr(Operands); + } + + const SCEV *visitUDivExpr(const SCEVUDivExpr *Expr) { + auto *LHS = ((SC *)this)->visit(Expr->getLHS()); + auto *RHS = ((SC *)this)->visit(Expr->getRHS()); + bool Changed = LHS != Expr->getLHS() || RHS != Expr->getRHS(); + return !Changed ? Expr : SE.getUDivExpr(LHS, RHS); + } + + const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) { + SmallVector<const SCEV *, 2> Operands; + bool Changed = false; + for (auto *Op : Expr->operands()) { + Operands.push_back(((SC*)this)->visit(Op)); + Changed |= Op != Operands.back(); + } + return !Changed ? Expr + : SE.getAddRecExpr(Operands, Expr->getLoop(), + Expr->getNoWrapFlags()); + } + + const SCEV *visitSMaxExpr(const SCEVSMaxExpr *Expr) { + SmallVector<const SCEV *, 2> Operands; + bool Changed = false; + for (auto *Op : Expr->operands()) { + Operands.push_back(((SC *)this)->visit(Op)); + Changed |= Op != Operands.back(); + } + return !Changed ? Expr : SE.getSMaxExpr(Operands); + } + + const SCEV *visitUMaxExpr(const SCEVUMaxExpr *Expr) { + SmallVector<const SCEV *, 2> Operands; + bool Changed = false; + for (auto *Op : Expr->operands()) { + Operands.push_back(((SC*)this)->visit(Op)); + Changed |= Op != Operands.back(); + } + return !Changed ? Expr : SE.getUMaxExpr(Operands); + } + + const SCEV *visitSMinExpr(const SCEVSMinExpr *Expr) { + SmallVector<const SCEV *, 2> Operands; + bool Changed = false; + for (auto *Op : Expr->operands()) { + Operands.push_back(((SC *)this)->visit(Op)); + Changed |= Op != Operands.back(); + } + return !Changed ? Expr : SE.getSMinExpr(Operands); + } + + const SCEV *visitUMinExpr(const SCEVUMinExpr *Expr) { + SmallVector<const SCEV *, 2> Operands; + bool Changed = false; + for (auto *Op : Expr->operands()) { + Operands.push_back(((SC *)this)->visit(Op)); + Changed |= Op != Operands.back(); + } + return !Changed ? Expr : SE.getUMinExpr(Operands); + } + + const SCEV *visitUnknown(const SCEVUnknown *Expr) { + return Expr; + } + + const SCEV *visitCouldNotCompute(const SCEVCouldNotCompute *Expr) { + return Expr; + } + }; + + using ValueToValueMap = DenseMap<const Value *, Value *>; + + /// The SCEVParameterRewriter takes a scalar evolution expression and updates + /// the SCEVUnknown components following the Map (Value -> Value). + class SCEVParameterRewriter : public SCEVRewriteVisitor<SCEVParameterRewriter> { + public: + static const SCEV *rewrite(const SCEV *Scev, ScalarEvolution &SE, + ValueToValueMap &Map, + bool InterpretConsts = false) { + SCEVParameterRewriter Rewriter(SE, Map, InterpretConsts); + return Rewriter.visit(Scev); + } + + SCEVParameterRewriter(ScalarEvolution &SE, ValueToValueMap &M, bool C) + : SCEVRewriteVisitor(SE), Map(M), InterpretConsts(C) {} + + const SCEV *visitUnknown(const SCEVUnknown *Expr) { + Value *V = Expr->getValue(); + if (Map.count(V)) { + Value *NV = Map[V]; + if (InterpretConsts && isa<ConstantInt>(NV)) + return SE.getConstant(cast<ConstantInt>(NV)); + return SE.getUnknown(NV); + } + return Expr; + } + + private: + ValueToValueMap ⤅ + bool InterpretConsts; + }; + + using LoopToScevMapT = DenseMap<const Loop *, const SCEV *>; + + /// The SCEVLoopAddRecRewriter takes a scalar evolution expression and applies + /// the Map (Loop -> SCEV) to all AddRecExprs. + class SCEVLoopAddRecRewriter + : public SCEVRewriteVisitor<SCEVLoopAddRecRewriter> { + public: + SCEVLoopAddRecRewriter(ScalarEvolution &SE, LoopToScevMapT &M) + : SCEVRewriteVisitor(SE), Map(M) {} + + static const SCEV *rewrite(const SCEV *Scev, LoopToScevMapT &Map, + ScalarEvolution &SE) { + SCEVLoopAddRecRewriter Rewriter(SE, Map); + return Rewriter.visit(Scev); + } + + const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) { + SmallVector<const SCEV *, 2> Operands; + for (const SCEV *Op : Expr->operands()) + Operands.push_back(visit(Op)); + + const Loop *L = Expr->getLoop(); + const SCEV *Res = SE.getAddRecExpr(Operands, L, Expr->getNoWrapFlags()); + + if (0 == Map.count(L)) + return Res; + + const SCEVAddRecExpr *Rec = cast<SCEVAddRecExpr>(Res); + return Rec->evaluateAtIteration(Map[L], SE); + } + + private: + LoopToScevMapT ⤅ + }; + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_SCALAREVOLUTIONEXPRESSIONS_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/ScalarEvolutionNormalization.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/ScalarEvolutionNormalization.h new file mode 100644 index 0000000..1a05594 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/ScalarEvolutionNormalization.h
@@ -0,0 +1,68 @@ +//===- llvm/Analysis/ScalarEvolutionNormalization.h - See below -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines utilities for working with "normalized" ScalarEvolution +// expressions. +// +// The following example illustrates post-increment uses and how normalized +// expressions help. +// +// for (i=0; i!=n; ++i) { +// ... +// } +// use(i); +// +// While the expression for most uses of i inside the loop is {0,+,1}<%L>, the +// expression for the use of i outside the loop is {1,+,1}<%L>, since i is +// incremented at the end of the loop body. This is inconveient, since it +// suggests that we need two different induction variables, one that starts +// at 0 and one that starts at 1. We'd prefer to be able to think of these as +// the same induction variable, with uses inside the loop using the +// "pre-incremented" value, and uses after the loop using the +// "post-incremented" value. +// +// Expressions for post-incremented uses are represented as an expression +// paired with a set of loops for which the expression is in "post-increment" +// mode (there may be multiple loops). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_SCALAREVOLUTIONNORMALIZATION_H +#define LLVM_ANALYSIS_SCALAREVOLUTIONNORMALIZATION_H + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Analysis/ScalarEvolutionExpressions.h" + +namespace llvm { + +class Loop; +class ScalarEvolution; +class SCEV; + +typedef SmallPtrSet<const Loop *, 2> PostIncLoopSet; + +typedef function_ref<bool(const SCEVAddRecExpr *)> NormalizePredTy; + +/// Normalize \p S to be post-increment for all loops present in \p +/// Loops. +const SCEV *normalizeForPostIncUse(const SCEV *S, const PostIncLoopSet &Loops, + ScalarEvolution &SE); + +/// Normalize \p S for all add recurrence sub-expressions for which \p +/// Pred returns true. +const SCEV *normalizeForPostIncUseIf(const SCEV *S, NormalizePredTy Pred, + ScalarEvolution &SE); + +/// Denormalize \p S to be post-increment for all loops present in \p +/// Loops. +const SCEV *denormalizeForPostIncUse(const SCEV *S, const PostIncLoopSet &Loops, + ScalarEvolution &SE); +} // namespace llvm + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/ScopedNoAliasAA.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/ScopedNoAliasAA.h new file mode 100644 index 0000000..dae733b --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/ScopedNoAliasAA.h
@@ -0,0 +1,91 @@ +//===- ScopedNoAliasAA.h - Scoped No-Alias Alias Analysis -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +/// \file +/// This is the interface for a metadata-based scoped no-alias analysis. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_SCOPEDNOALIASAA_H +#define LLVM_ANALYSIS_SCOPEDNOALIASAA_H + +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Pass.h" +#include <memory> + +namespace llvm { + +class Function; +class MDNode; +class MemoryLocation; + +/// A simple AA result which uses scoped-noalias metadata to answer queries. +class ScopedNoAliasAAResult : public AAResultBase<ScopedNoAliasAAResult> { + friend AAResultBase<ScopedNoAliasAAResult>; + +public: + /// Handle invalidation events from the new pass manager. + /// + /// By definition, this result is stateless and so remains valid. + bool invalidate(Function &, const PreservedAnalyses &, + FunctionAnalysisManager::Invalidator &) { + return false; + } + + AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB, + AAQueryInfo &AAQI); + ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc, + AAQueryInfo &AAQI); + ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2, + AAQueryInfo &AAQI); + +private: + bool mayAliasInScopes(const MDNode *Scopes, const MDNode *NoAlias) const; +}; + +/// Analysis pass providing a never-invalidated alias analysis result. +class ScopedNoAliasAA : public AnalysisInfoMixin<ScopedNoAliasAA> { + friend AnalysisInfoMixin<ScopedNoAliasAA>; + + static AnalysisKey Key; + +public: + using Result = ScopedNoAliasAAResult; + + ScopedNoAliasAAResult run(Function &F, FunctionAnalysisManager &AM); +}; + +/// Legacy wrapper pass to provide the ScopedNoAliasAAResult object. +class ScopedNoAliasAAWrapperPass : public ImmutablePass { + std::unique_ptr<ScopedNoAliasAAResult> Result; + +public: + static char ID; + + ScopedNoAliasAAWrapperPass(); + + ScopedNoAliasAAResult &getResult() { return *Result; } + const ScopedNoAliasAAResult &getResult() const { return *Result; } + + bool doInitialization(Module &M) override; + bool doFinalization(Module &M) override; + void getAnalysisUsage(AnalysisUsage &AU) const override; +}; + +//===--------------------------------------------------------------------===// +// +// createScopedNoAliasAAWrapperPass - This pass implements metadata-based +// scoped noalias analysis. +// +ImmutablePass *createScopedNoAliasAAWrapperPass(); + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_SCOPEDNOALIASAA_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/SparsePropagation.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/SparsePropagation.h new file mode 100644 index 0000000..fac92e4 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/SparsePropagation.h
@@ -0,0 +1,526 @@ +//===- SparsePropagation.h - Sparse Conditional Property Propagation ------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements an abstract sparse conditional propagation algorithm, +// modeled after SCCP, but with a customizable lattice function. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_SPARSEPROPAGATION_H +#define LLVM_ANALYSIS_SPARSEPROPAGATION_H + +#include "llvm/IR/Instructions.h" +#include "llvm/Support/Debug.h" +#include <set> + +#define DEBUG_TYPE "sparseprop" + +namespace llvm { + +/// A template for translating between LLVM Values and LatticeKeys. Clients must +/// provide a specialization of LatticeKeyInfo for their LatticeKey type. +template <class LatticeKey> struct LatticeKeyInfo { + // static inline Value *getValueFromLatticeKey(LatticeKey Key); + // static inline LatticeKey getLatticeKeyFromValue(Value *V); +}; + +template <class LatticeKey, class LatticeVal, + class KeyInfo = LatticeKeyInfo<LatticeKey>> +class SparseSolver; + +/// AbstractLatticeFunction - This class is implemented by the dataflow instance +/// to specify what the lattice values are and how they handle merges etc. This +/// gives the client the power to compute lattice values from instructions, +/// constants, etc. The current requirement is that lattice values must be +/// copyable. At the moment, nothing tries to avoid copying. Additionally, +/// lattice keys must be able to be used as keys of a mapping data structure. +/// Internally, the generic solver currently uses a DenseMap to map lattice keys +/// to lattice values. If the lattice key is a non-standard type, a +/// specialization of DenseMapInfo must be provided. +template <class LatticeKey, class LatticeVal> class AbstractLatticeFunction { +private: + LatticeVal UndefVal, OverdefinedVal, UntrackedVal; + +public: + AbstractLatticeFunction(LatticeVal undefVal, LatticeVal overdefinedVal, + LatticeVal untrackedVal) { + UndefVal = undefVal; + OverdefinedVal = overdefinedVal; + UntrackedVal = untrackedVal; + } + + virtual ~AbstractLatticeFunction() = default; + + LatticeVal getUndefVal() const { return UndefVal; } + LatticeVal getOverdefinedVal() const { return OverdefinedVal; } + LatticeVal getUntrackedVal() const { return UntrackedVal; } + + /// IsUntrackedValue - If the specified LatticeKey is obviously uninteresting + /// to the analysis (i.e., it would always return UntrackedVal), this + /// function can return true to avoid pointless work. + virtual bool IsUntrackedValue(LatticeKey Key) { return false; } + + /// ComputeLatticeVal - Compute and return a LatticeVal corresponding to the + /// given LatticeKey. + virtual LatticeVal ComputeLatticeVal(LatticeKey Key) { + return getOverdefinedVal(); + } + + /// IsSpecialCasedPHI - Given a PHI node, determine whether this PHI node is + /// one that the we want to handle through ComputeInstructionState. + virtual bool IsSpecialCasedPHI(PHINode *PN) { return false; } + + /// MergeValues - Compute and return the merge of the two specified lattice + /// values. Merging should only move one direction down the lattice to + /// guarantee convergence (toward overdefined). + virtual LatticeVal MergeValues(LatticeVal X, LatticeVal Y) { + return getOverdefinedVal(); // always safe, never useful. + } + + /// ComputeInstructionState - Compute the LatticeKeys that change as a result + /// of executing instruction \p I. Their associated LatticeVals are store in + /// \p ChangedValues. + virtual void + ComputeInstructionState(Instruction &I, + DenseMap<LatticeKey, LatticeVal> &ChangedValues, + SparseSolver<LatticeKey, LatticeVal> &SS) = 0; + + /// PrintLatticeVal - Render the given LatticeVal to the specified stream. + virtual void PrintLatticeVal(LatticeVal LV, raw_ostream &OS); + + /// PrintLatticeKey - Render the given LatticeKey to the specified stream. + virtual void PrintLatticeKey(LatticeKey Key, raw_ostream &OS); + + /// GetValueFromLatticeVal - If the given LatticeVal is representable as an + /// LLVM value, return it; otherwise, return nullptr. If a type is given, the + /// returned value must have the same type. This function is used by the + /// generic solver in attempting to resolve branch and switch conditions. + virtual Value *GetValueFromLatticeVal(LatticeVal LV, Type *Ty = nullptr) { + return nullptr; + } +}; + +/// SparseSolver - This class is a general purpose solver for Sparse Conditional +/// Propagation with a programmable lattice function. +template <class LatticeKey, class LatticeVal, class KeyInfo> +class SparseSolver { + + /// LatticeFunc - This is the object that knows the lattice and how to + /// compute transfer functions. + AbstractLatticeFunction<LatticeKey, LatticeVal> *LatticeFunc; + + /// ValueState - Holds the LatticeVals associated with LatticeKeys. + DenseMap<LatticeKey, LatticeVal> ValueState; + + /// BBExecutable - Holds the basic blocks that are executable. + SmallPtrSet<BasicBlock *, 16> BBExecutable; + + /// ValueWorkList - Holds values that should be processed. + SmallVector<Value *, 64> ValueWorkList; + + /// BBWorkList - Holds basic blocks that should be processed. + SmallVector<BasicBlock *, 64> BBWorkList; + + using Edge = std::pair<BasicBlock *, BasicBlock *>; + + /// KnownFeasibleEdges - Entries in this set are edges which have already had + /// PHI nodes retriggered. + std::set<Edge> KnownFeasibleEdges; + +public: + explicit SparseSolver( + AbstractLatticeFunction<LatticeKey, LatticeVal> *Lattice) + : LatticeFunc(Lattice) {} + SparseSolver(const SparseSolver &) = delete; + SparseSolver &operator=(const SparseSolver &) = delete; + + /// Solve - Solve for constants and executable blocks. + void Solve(); + + void Print(raw_ostream &OS) const; + + /// getExistingValueState - Return the LatticeVal object corresponding to the + /// given value from the ValueState map. If the value is not in the map, + /// UntrackedVal is returned, unlike the getValueState method. + LatticeVal getExistingValueState(LatticeKey Key) const { + auto I = ValueState.find(Key); + return I != ValueState.end() ? I->second : LatticeFunc->getUntrackedVal(); + } + + /// getValueState - Return the LatticeVal object corresponding to the given + /// value from the ValueState map. If the value is not in the map, its state + /// is initialized. + LatticeVal getValueState(LatticeKey Key); + + /// isEdgeFeasible - Return true if the control flow edge from the 'From' + /// basic block to the 'To' basic block is currently feasible. If + /// AggressiveUndef is true, then this treats values with unknown lattice + /// values as undefined. This is generally only useful when solving the + /// lattice, not when querying it. + bool isEdgeFeasible(BasicBlock *From, BasicBlock *To, + bool AggressiveUndef = false); + + /// isBlockExecutable - Return true if there are any known feasible + /// edges into the basic block. This is generally only useful when + /// querying the lattice. + bool isBlockExecutable(BasicBlock *BB) const { + return BBExecutable.count(BB); + } + + /// MarkBlockExecutable - This method can be used by clients to mark all of + /// the blocks that are known to be intrinsically live in the processed unit. + void MarkBlockExecutable(BasicBlock *BB); + +private: + /// UpdateState - When the state of some LatticeKey is potentially updated to + /// the given LatticeVal, this function notices and adds the LLVM value + /// corresponding the key to the work list, if needed. + void UpdateState(LatticeKey Key, LatticeVal LV); + + /// markEdgeExecutable - Mark a basic block as executable, adding it to the BB + /// work list if it is not already executable. + void markEdgeExecutable(BasicBlock *Source, BasicBlock *Dest); + + /// getFeasibleSuccessors - Return a vector of booleans to indicate which + /// successors are reachable from a given terminator instruction. + void getFeasibleSuccessors(Instruction &TI, SmallVectorImpl<bool> &Succs, + bool AggressiveUndef); + + void visitInst(Instruction &I); + void visitPHINode(PHINode &I); + void visitTerminator(Instruction &TI); +}; + +//===----------------------------------------------------------------------===// +// AbstractLatticeFunction Implementation +//===----------------------------------------------------------------------===// + +template <class LatticeKey, class LatticeVal> +void AbstractLatticeFunction<LatticeKey, LatticeVal>::PrintLatticeVal( + LatticeVal V, raw_ostream &OS) { + if (V == UndefVal) + OS << "undefined"; + else if (V == OverdefinedVal) + OS << "overdefined"; + else if (V == UntrackedVal) + OS << "untracked"; + else + OS << "unknown lattice value"; +} + +template <class LatticeKey, class LatticeVal> +void AbstractLatticeFunction<LatticeKey, LatticeVal>::PrintLatticeKey( + LatticeKey Key, raw_ostream &OS) { + OS << "unknown lattice key"; +} + +//===----------------------------------------------------------------------===// +// SparseSolver Implementation +//===----------------------------------------------------------------------===// + +template <class LatticeKey, class LatticeVal, class KeyInfo> +LatticeVal +SparseSolver<LatticeKey, LatticeVal, KeyInfo>::getValueState(LatticeKey Key) { + auto I = ValueState.find(Key); + if (I != ValueState.end()) + return I->second; // Common case, in the map + + if (LatticeFunc->IsUntrackedValue(Key)) + return LatticeFunc->getUntrackedVal(); + LatticeVal LV = LatticeFunc->ComputeLatticeVal(Key); + + // If this value is untracked, don't add it to the map. + if (LV == LatticeFunc->getUntrackedVal()) + return LV; + return ValueState[Key] = std::move(LV); +} + +template <class LatticeKey, class LatticeVal, class KeyInfo> +void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::UpdateState(LatticeKey Key, + LatticeVal LV) { + auto I = ValueState.find(Key); + if (I != ValueState.end() && I->second == LV) + return; // No change. + + // Update the state of the given LatticeKey and add its corresponding LLVM + // value to the work list. + ValueState[Key] = std::move(LV); + if (Value *V = KeyInfo::getValueFromLatticeKey(Key)) + ValueWorkList.push_back(V); +} + +template <class LatticeKey, class LatticeVal, class KeyInfo> +void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::MarkBlockExecutable( + BasicBlock *BB) { + if (!BBExecutable.insert(BB).second) + return; + LLVM_DEBUG(dbgs() << "Marking Block Executable: " << BB->getName() << "\n"); + BBWorkList.push_back(BB); // Add the block to the work list! +} + +template <class LatticeKey, class LatticeVal, class KeyInfo> +void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::markEdgeExecutable( + BasicBlock *Source, BasicBlock *Dest) { + if (!KnownFeasibleEdges.insert(Edge(Source, Dest)).second) + return; // This edge is already known to be executable! + + LLVM_DEBUG(dbgs() << "Marking Edge Executable: " << Source->getName() + << " -> " << Dest->getName() << "\n"); + + if (BBExecutable.count(Dest)) { + // The destination is already executable, but we just made an edge + // feasible that wasn't before. Revisit the PHI nodes in the block + // because they have potentially new operands. + for (BasicBlock::iterator I = Dest->begin(); isa<PHINode>(I); ++I) + visitPHINode(*cast<PHINode>(I)); + } else { + MarkBlockExecutable(Dest); + } +} + +template <class LatticeKey, class LatticeVal, class KeyInfo> +void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::getFeasibleSuccessors( + Instruction &TI, SmallVectorImpl<bool> &Succs, bool AggressiveUndef) { + Succs.resize(TI.getNumSuccessors()); + if (TI.getNumSuccessors() == 0) + return; + + if (BranchInst *BI = dyn_cast<BranchInst>(&TI)) { + if (BI->isUnconditional()) { + Succs[0] = true; + return; + } + + LatticeVal BCValue; + if (AggressiveUndef) + BCValue = + getValueState(KeyInfo::getLatticeKeyFromValue(BI->getCondition())); + else + BCValue = getExistingValueState( + KeyInfo::getLatticeKeyFromValue(BI->getCondition())); + + if (BCValue == LatticeFunc->getOverdefinedVal() || + BCValue == LatticeFunc->getUntrackedVal()) { + // Overdefined condition variables can branch either way. + Succs[0] = Succs[1] = true; + return; + } + + // If undefined, neither is feasible yet. + if (BCValue == LatticeFunc->getUndefVal()) + return; + + Constant *C = + dyn_cast_or_null<Constant>(LatticeFunc->GetValueFromLatticeVal( + std::move(BCValue), BI->getCondition()->getType())); + if (!C || !isa<ConstantInt>(C)) { + // Non-constant values can go either way. + Succs[0] = Succs[1] = true; + return; + } + + // Constant condition variables mean the branch can only go a single way + Succs[C->isNullValue()] = true; + return; + } + + if (TI.isExceptionalTerminator() || + TI.isIndirectTerminator()) { + Succs.assign(Succs.size(), true); + return; + } + + SwitchInst &SI = cast<SwitchInst>(TI); + LatticeVal SCValue; + if (AggressiveUndef) + SCValue = getValueState(KeyInfo::getLatticeKeyFromValue(SI.getCondition())); + else + SCValue = getExistingValueState( + KeyInfo::getLatticeKeyFromValue(SI.getCondition())); + + if (SCValue == LatticeFunc->getOverdefinedVal() || + SCValue == LatticeFunc->getUntrackedVal()) { + // All destinations are executable! + Succs.assign(TI.getNumSuccessors(), true); + return; + } + + // If undefined, neither is feasible yet. + if (SCValue == LatticeFunc->getUndefVal()) + return; + + Constant *C = dyn_cast_or_null<Constant>(LatticeFunc->GetValueFromLatticeVal( + std::move(SCValue), SI.getCondition()->getType())); + if (!C || !isa<ConstantInt>(C)) { + // All destinations are executable! + Succs.assign(TI.getNumSuccessors(), true); + return; + } + SwitchInst::CaseHandle Case = *SI.findCaseValue(cast<ConstantInt>(C)); + Succs[Case.getSuccessorIndex()] = true; +} + +template <class LatticeKey, class LatticeVal, class KeyInfo> +bool SparseSolver<LatticeKey, LatticeVal, KeyInfo>::isEdgeFeasible( + BasicBlock *From, BasicBlock *To, bool AggressiveUndef) { + SmallVector<bool, 16> SuccFeasible; + Instruction *TI = From->getTerminator(); + getFeasibleSuccessors(*TI, SuccFeasible, AggressiveUndef); + + for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) + if (TI->getSuccessor(i) == To && SuccFeasible[i]) + return true; + + return false; +} + +template <class LatticeKey, class LatticeVal, class KeyInfo> +void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::visitTerminator( + Instruction &TI) { + SmallVector<bool, 16> SuccFeasible; + getFeasibleSuccessors(TI, SuccFeasible, true); + + BasicBlock *BB = TI.getParent(); + + // Mark all feasible successors executable... + for (unsigned i = 0, e = SuccFeasible.size(); i != e; ++i) + if (SuccFeasible[i]) + markEdgeExecutable(BB, TI.getSuccessor(i)); +} + +template <class LatticeKey, class LatticeVal, class KeyInfo> +void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::visitPHINode(PHINode &PN) { + // The lattice function may store more information on a PHINode than could be + // computed from its incoming values. For example, SSI form stores its sigma + // functions as PHINodes with a single incoming value. + if (LatticeFunc->IsSpecialCasedPHI(&PN)) { + DenseMap<LatticeKey, LatticeVal> ChangedValues; + LatticeFunc->ComputeInstructionState(PN, ChangedValues, *this); + for (auto &ChangedValue : ChangedValues) + if (ChangedValue.second != LatticeFunc->getUntrackedVal()) + UpdateState(std::move(ChangedValue.first), + std::move(ChangedValue.second)); + return; + } + + LatticeKey Key = KeyInfo::getLatticeKeyFromValue(&PN); + LatticeVal PNIV = getValueState(Key); + LatticeVal Overdefined = LatticeFunc->getOverdefinedVal(); + + // If this value is already overdefined (common) just return. + if (PNIV == Overdefined || PNIV == LatticeFunc->getUntrackedVal()) + return; // Quick exit + + // Super-extra-high-degree PHI nodes are unlikely to ever be interesting, + // and slow us down a lot. Just mark them overdefined. + if (PN.getNumIncomingValues() > 64) { + UpdateState(Key, Overdefined); + return; + } + + // Look at all of the executable operands of the PHI node. If any of them + // are overdefined, the PHI becomes overdefined as well. Otherwise, ask the + // transfer function to give us the merge of the incoming values. + for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) { + // If the edge is not yet known to be feasible, it doesn't impact the PHI. + if (!isEdgeFeasible(PN.getIncomingBlock(i), PN.getParent(), true)) + continue; + + // Merge in this value. + LatticeVal OpVal = + getValueState(KeyInfo::getLatticeKeyFromValue(PN.getIncomingValue(i))); + if (OpVal != PNIV) + PNIV = LatticeFunc->MergeValues(PNIV, OpVal); + + if (PNIV == Overdefined) + break; // Rest of input values don't matter. + } + + // Update the PHI with the compute value, which is the merge of the inputs. + UpdateState(Key, PNIV); +} + +template <class LatticeKey, class LatticeVal, class KeyInfo> +void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::visitInst(Instruction &I) { + // PHIs are handled by the propagation logic, they are never passed into the + // transfer functions. + if (PHINode *PN = dyn_cast<PHINode>(&I)) + return visitPHINode(*PN); + + // Otherwise, ask the transfer function what the result is. If this is + // something that we care about, remember it. + DenseMap<LatticeKey, LatticeVal> ChangedValues; + LatticeFunc->ComputeInstructionState(I, ChangedValues, *this); + for (auto &ChangedValue : ChangedValues) + if (ChangedValue.second != LatticeFunc->getUntrackedVal()) + UpdateState(ChangedValue.first, ChangedValue.second); + + if (I.isTerminator()) + visitTerminator(I); +} + +template <class LatticeKey, class LatticeVal, class KeyInfo> +void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::Solve() { + // Process the work lists until they are empty! + while (!BBWorkList.empty() || !ValueWorkList.empty()) { + // Process the value work list. + while (!ValueWorkList.empty()) { + Value *V = ValueWorkList.back(); + ValueWorkList.pop_back(); + + LLVM_DEBUG(dbgs() << "\nPopped off V-WL: " << *V << "\n"); + + // "V" got into the work list because it made a transition. See if any + // users are both live and in need of updating. + for (User *U : V->users()) + if (Instruction *Inst = dyn_cast<Instruction>(U)) + if (BBExecutable.count(Inst->getParent())) // Inst is executable? + visitInst(*Inst); + } + + // Process the basic block work list. + while (!BBWorkList.empty()) { + BasicBlock *BB = BBWorkList.back(); + BBWorkList.pop_back(); + + LLVM_DEBUG(dbgs() << "\nPopped off BBWL: " << *BB); + + // Notify all instructions in this basic block that they are newly + // executable. + for (Instruction &I : *BB) + visitInst(I); + } + } +} + +template <class LatticeKey, class LatticeVal, class KeyInfo> +void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::Print( + raw_ostream &OS) const { + if (ValueState.empty()) + return; + + LatticeKey Key; + LatticeVal LV; + + OS << "ValueState:\n"; + for (auto &Entry : ValueState) { + std::tie(Key, LV) = Entry; + if (LV == LatticeFunc->getUntrackedVal()) + continue; + OS << "\t"; + LatticeFunc->PrintLatticeVal(LV, OS); + OS << ": "; + LatticeFunc->PrintLatticeKey(Key, OS); + OS << "\n"; + } +} +} // end namespace llvm + +#undef DEBUG_TYPE + +#endif // LLVM_ANALYSIS_SPARSEPROPAGATION_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/StackSafetyAnalysis.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/StackSafetyAnalysis.h new file mode 100644 index 0000000..f9d8b08 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/StackSafetyAnalysis.h
@@ -0,0 +1,119 @@ +//===- StackSafetyAnalysis.h - Stack memory safety analysis -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Stack Safety Analysis detects allocas and arguments with safe access. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_STACKSAFETYANALYSIS_H +#define LLVM_ANALYSIS_STACKSAFETYANALYSIS_H + +#include "llvm/IR/PassManager.h" +#include "llvm/Pass.h" + +namespace llvm { + +/// Interface to access stack safety analysis results for single function. +class StackSafetyInfo { +public: + struct FunctionInfo; + +private: + std::unique_ptr<FunctionInfo> Info; + +public: + StackSafetyInfo(); + StackSafetyInfo(FunctionInfo &&Info); + StackSafetyInfo(StackSafetyInfo &&); + StackSafetyInfo &operator=(StackSafetyInfo &&); + ~StackSafetyInfo(); + + // TODO: Add useful for client methods. + void print(raw_ostream &O) const; +}; + +/// StackSafetyInfo wrapper for the new pass manager. +class StackSafetyAnalysis : public AnalysisInfoMixin<StackSafetyAnalysis> { + friend AnalysisInfoMixin<StackSafetyAnalysis>; + static AnalysisKey Key; + +public: + using Result = StackSafetyInfo; + StackSafetyInfo run(Function &F, FunctionAnalysisManager &AM); +}; + +/// Printer pass for the \c StackSafetyAnalysis results. +class StackSafetyPrinterPass : public PassInfoMixin<StackSafetyPrinterPass> { + raw_ostream &OS; + +public: + explicit StackSafetyPrinterPass(raw_ostream &OS) : OS(OS) {} + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + +/// StackSafetyInfo wrapper for the legacy pass manager +class StackSafetyInfoWrapperPass : public FunctionPass { + StackSafetyInfo SSI; + +public: + static char ID; + StackSafetyInfoWrapperPass(); + + const StackSafetyInfo &getResult() const { return SSI; } + + void print(raw_ostream &O, const Module *M) const override; + void getAnalysisUsage(AnalysisUsage &AU) const override; + + bool runOnFunction(Function &F) override; +}; + +using StackSafetyGlobalInfo = std::map<const GlobalValue *, StackSafetyInfo>; + +/// This pass performs the global (interprocedural) stack safety analysis (new +/// pass manager). +class StackSafetyGlobalAnalysis + : public AnalysisInfoMixin<StackSafetyGlobalAnalysis> { + friend AnalysisInfoMixin<StackSafetyGlobalAnalysis>; + static AnalysisKey Key; + +public: + using Result = StackSafetyGlobalInfo; + Result run(Module &M, ModuleAnalysisManager &AM); +}; + +/// Printer pass for the \c StackSafetyGlobalAnalysis results. +class StackSafetyGlobalPrinterPass + : public PassInfoMixin<StackSafetyGlobalPrinterPass> { + raw_ostream &OS; + +public: + explicit StackSafetyGlobalPrinterPass(raw_ostream &OS) : OS(OS) {} + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); +}; + +/// This pass performs the global (interprocedural) stack safety analysis +/// (legacy pass manager). +class StackSafetyGlobalInfoWrapperPass : public ModulePass { + StackSafetyGlobalInfo SSI; + +public: + static char ID; + + StackSafetyGlobalInfoWrapperPass(); + + const StackSafetyGlobalInfo &getResult() const { return SSI; } + + void print(raw_ostream &O, const Module *M) const override; + void getAnalysisUsage(AnalysisUsage &AU) const override; + + bool runOnModule(Module &M) override; +}; + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_STACKSAFETYANALYSIS_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/SyncDependenceAnalysis.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/SyncDependenceAnalysis.h new file mode 100644 index 0000000..099403b --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/SyncDependenceAnalysis.h
@@ -0,0 +1,85 @@ +//===- SyncDependenceAnalysis.h - Divergent Branch Dependence -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// \file +// This file defines the SyncDependenceAnalysis class, which computes for +// every divergent branch the set of phi nodes that the branch will make +// divergent. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_SYNC_DEPENDENCE_ANALYSIS_H +#define LLVM_ANALYSIS_SYNC_DEPENDENCE_ANALYSIS_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Analysis/LoopInfo.h" +#include <memory> + +namespace llvm { + +class BasicBlock; +class DominatorTree; +class Loop; +class PostDominatorTree; + +using ConstBlockSet = SmallPtrSet<const BasicBlock *, 4>; + +/// \brief Relates points of divergent control to join points in +/// reducible CFGs. +/// +/// This analysis relates points of divergent control to points of converging +/// divergent control. The analysis requires all loops to be reducible. +class SyncDependenceAnalysis { + void visitSuccessor(const BasicBlock &succBlock, const Loop *termLoop, + const BasicBlock *defBlock); + +public: + bool inRegion(const BasicBlock &BB) const; + + ~SyncDependenceAnalysis(); + SyncDependenceAnalysis(const DominatorTree &DT, const PostDominatorTree &PDT, + const LoopInfo &LI); + + /// \brief Computes divergent join points and loop exits caused by branch + /// divergence in \p Term. + /// + /// The set of blocks which are reachable by disjoint paths from \p Term. + /// The set also contains loop exits if there two disjoint paths: + /// one from \p Term to the loop exit and another from \p Term to the loop + /// header. Those exit blocks are added to the returned set. + /// If L is the parent loop of \p Term and an exit of L is in the returned + /// set then L is a divergent loop. + const ConstBlockSet &join_blocks(const Instruction &Term); + + /// \brief Computes divergent join points and loop exits (in the surrounding + /// loop) caused by the divergent loop exits of\p Loop. + /// + /// The set of blocks which are reachable by disjoint paths from the + /// loop exits of \p Loop. + /// This treats the loop as a single node in \p Loop's parent loop. + /// The returned set has the same properties as for join_blocks(TermInst&). + const ConstBlockSet &join_blocks(const Loop &Loop); + +private: + static ConstBlockSet EmptyBlockSet; + + ReversePostOrderTraversal<const Function *> FuncRPOT; + const DominatorTree &DT; + const PostDominatorTree &PDT; + const LoopInfo &LI; + + std::map<const Loop *, std::unique_ptr<ConstBlockSet>> CachedLoopExitJoins; + std::map<const Instruction *, std::unique_ptr<ConstBlockSet>> + CachedBranchJoins; +}; + +} // namespace llvm + +#endif // LLVM_ANALYSIS_SYNC_DEPENDENCE_ANALYSIS_H
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/SyntheticCountsUtils.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/SyntheticCountsUtils.h new file mode 100644 index 0000000..b9b4c98 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/SyntheticCountsUtils.h
@@ -0,0 +1,52 @@ +//===- SyntheticCountsUtils.h - utilities for count propagation--*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines utilities for synthetic counts propagation. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_SYNTHETIC_COUNTS_UTILS_H +#define LLVM_ANALYSIS_SYNTHETIC_COUNTS_UTILS_H + +#include "llvm/ADT/STLExtras.h" +#include "llvm/Analysis/CallGraph.h" +#include "llvm/Support/ScaledNumber.h" + +namespace llvm { + +class CallGraph; +class Function; + +/// Class with methods to propagate synthetic entry counts. +/// +/// This class is templated on the type of the call graph and designed to work +/// with the traditional per-module callgraph and the summary callgraphs used in +/// ThinLTO. This contains only static methods and alias templates. +template <typename CallGraphType> class SyntheticCountsUtils { +public: + using Scaled64 = ScaledNumber<uint64_t>; + using CGT = GraphTraits<CallGraphType>; + using NodeRef = typename CGT::NodeRef; + using EdgeRef = typename CGT::EdgeRef; + using SccTy = std::vector<NodeRef>; + + // Not all EdgeRef have information about the source of the edge. Hence + // NodeRef corresponding to the source of the EdgeRef is explicitly passed. + using GetProfCountTy = function_ref<Optional<Scaled64>(NodeRef, EdgeRef)>; + using AddCountTy = function_ref<void(NodeRef, Scaled64)>; + + static void propagate(const CallGraphType &CG, GetProfCountTy GetProfCount, + AddCountTy AddCount); + +private: + static void propagateFromSCC(const SccTy &SCC, GetProfCountTy GetProfCount, + AddCountTy AddCount); +}; +} // namespace llvm + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/TargetFolder.h b/third_party/llvm-10.0/llvm/include/llvm/Analysis/TargetFolder.h new file mode 100644 index 0000000..7ab6562 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/TargetFolder.h
@@ -0,0 +1,272 @@ +//====- TargetFolder.h - Constant folding helper ---------------*- C++ -*-====// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the TargetFolder class, a helper for IRBuilder. +// It provides IRBuilder with a set of methods for creating constants with +// target dependent folding, in addition to the same target-independent +// folding that the ConstantFolder class provides. For general constant +// creation and folding, use ConstantExpr and the routines in +// llvm/Analysis/ConstantFolding.h. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_TARGETFOLDER_H +#define LLVM_ANALYSIS_TARGETFOLDER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Analysis/ConstantFolding.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/InstrTypes.h" + +namespace llvm { + +class DataLayout; + +/// TargetFolder - Create constants with target dependent folding. +class TargetFolder { + const DataLayout &DL; + + /// Fold - Fold the constant using target specific information. + Constant *Fold(Constant *C) const { + if (Constant *CF = ConstantFoldConstant(C, DL)) + return CF; + return C; + } + +public: + explicit TargetFolder(const DataLayout &DL) : DL(DL) {} + + //===--------------------------------------------------------------------===// + // Binary Operators + //===--------------------------------------------------------------------===// + + Constant *CreateAdd(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return Fold(ConstantExpr::getAdd(LHS, RHS, HasNUW, HasNSW)); + } + Constant *CreateFAdd(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getFAdd(LHS, RHS)); + } + Constant *CreateSub(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return Fold(ConstantExpr::getSub(LHS, RHS, HasNUW, HasNSW)); + } + Constant *CreateFSub(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getFSub(LHS, RHS)); + } + Constant *CreateMul(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return Fold(ConstantExpr::getMul(LHS, RHS, HasNUW, HasNSW)); + } + Constant *CreateFMul(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getFMul(LHS, RHS)); + } + Constant *CreateUDiv(Constant *LHS, Constant *RHS, bool isExact = false)const{ + return Fold(ConstantExpr::getUDiv(LHS, RHS, isExact)); + } + Constant *CreateSDiv(Constant *LHS, Constant *RHS, bool isExact = false)const{ + return Fold(ConstantExpr::getSDiv(LHS, RHS, isExact)); + } + Constant *CreateFDiv(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getFDiv(LHS, RHS)); + } + Constant *CreateURem(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getURem(LHS, RHS)); + } + Constant *CreateSRem(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getSRem(LHS, RHS)); + } + Constant *CreateFRem(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getFRem(LHS, RHS)); + } + Constant *CreateShl(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return Fold(ConstantExpr::getShl(LHS, RHS, HasNUW, HasNSW)); + } + Constant *CreateLShr(Constant *LHS, Constant *RHS, bool isExact = false)const{ + return Fold(ConstantExpr::getLShr(LHS, RHS, isExact)); + } + Constant *CreateAShr(Constant *LHS, Constant *RHS, bool isExact = false)const{ + return Fold(ConstantExpr::getAShr(LHS, RHS, isExact)); + } + Constant *CreateAnd(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getAnd(LHS, RHS)); + } + Constant *CreateOr(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getOr(LHS, RHS)); + } + Constant *CreateXor(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getXor(LHS, RHS)); + } + + Constant *CreateBinOp(Instruction::BinaryOps Opc, + Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::get(Opc, LHS, RHS)); + } + + //===--------------------------------------------------------------------===// + // Unary Operators + //===--------------------------------------------------------------------===// + + Constant *CreateNeg(Constant *C, + bool HasNUW = false, bool HasNSW = false) const { + return Fold(ConstantExpr::getNeg(C, HasNUW, HasNSW)); + } + Constant *CreateFNeg(Constant *C) const { + return Fold(ConstantExpr::getFNeg(C)); + } + Constant *CreateNot(Constant *C) const { + return Fold(ConstantExpr::getNot(C)); + } + + Constant *CreateUnOp(Instruction::UnaryOps Opc, Constant *C) const { + return Fold(ConstantExpr::get(Opc, C)); + } + + //===--------------------------------------------------------------------===// + // Memory Instructions + //===--------------------------------------------------------------------===// + + Constant *CreateGetElementPtr(Type *Ty, Constant *C, + ArrayRef<Constant *> IdxList) const { + return Fold(ConstantExpr::getGetElementPtr(Ty, C, IdxList)); + } + Constant *CreateGetElementPtr(Type *Ty, Constant *C, Constant *Idx) const { + // This form of the function only exists to avoid ambiguous overload + // warnings about whether to convert Idx to ArrayRef<Constant *> or + // ArrayRef<Value *>. + return Fold(ConstantExpr::getGetElementPtr(Ty, C, Idx)); + } + Constant *CreateGetElementPtr(Type *Ty, Constant *C, + ArrayRef<Value *> IdxList) const { + return Fold(ConstantExpr::getGetElementPtr(Ty, C, IdxList)); + } + + Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, + ArrayRef<Constant *> IdxList) const { + return Fold(ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList)); + } + Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, + Constant *Idx) const { + // This form of the function only exists to avoid ambiguous overload + // warnings about whether to convert Idx to ArrayRef<Constant *> or + // ArrayRef<Value *>. + return Fold(ConstantExpr::getInBoundsGetElementPtr(Ty, C, Idx)); + } + Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, + ArrayRef<Value *> IdxList) const { + return Fold(ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList)); + } + + //===--------------------------------------------------------------------===// + // Cast/Conversion Operators + //===--------------------------------------------------------------------===// + + Constant *CreateCast(Instruction::CastOps Op, Constant *C, + Type *DestTy) const { + if (C->getType() == DestTy) + return C; // avoid calling Fold + return Fold(ConstantExpr::getCast(Op, C, DestTy)); + } + Constant *CreateIntCast(Constant *C, Type *DestTy, + bool isSigned) const { + if (C->getType() == DestTy) + return C; // avoid calling Fold + return Fold(ConstantExpr::getIntegerCast(C, DestTy, isSigned)); + } + Constant *CreatePointerCast(Constant *C, Type *DestTy) const { + if (C->getType() == DestTy) + return C; // avoid calling Fold + return Fold(ConstantExpr::getPointerCast(C, DestTy)); + } + Constant *CreateFPCast(Constant *C, Type *DestTy) const { + if (C->getType() == DestTy) + return C; // avoid calling Fold + return Fold(ConstantExpr::getFPCast(C, DestTy)); + } + Constant *CreateBitCast(Constant *C, Type *DestTy) const { + return CreateCast(Instruction::BitCast, C, DestTy); + } + Constant *CreateIntToPtr(Constant *C, Type *DestTy) const { + return CreateCast(Instruction::IntToPtr, C, DestTy); + } + Constant *CreatePtrToInt(Constant *C, Type *DestTy) const { + return CreateCast(Instruction::PtrToInt, C, DestTy); + } + Constant *CreateZExtOrBitCast(Constant *C, Type *DestTy) const { + if (C->getType() == DestTy) + return C; // avoid calling Fold + return Fold(ConstantExpr::getZExtOrBitCast(C, DestTy)); + } + Constant *CreateSExtOrBitCast(Constant *C, Type *DestTy) const { + if (C->getType() == DestTy) + return C; // avoid calling Fold + return Fold(ConstantExpr::getSExtOrBitCast(C, DestTy)); + } + Constant *CreateTruncOrBitCast(Constant *C, Type *DestTy) const { + if (C->getType() == DestTy) + return C; // avoid calling Fold + return Fold(ConstantExpr::getTruncOrBitCast(C, DestTy)); + } + + Constant *CreatePointerBitCastOrAddrSpaceCast(Constant *C, + Type *DestTy) const { + if (C->getType() == DestTy) + return C; // avoid calling Fold + return Fold(ConstantExpr::getPointerBitCastOrAddrSpaceCast(C, DestTy)); + } + + //===--------------------------------------------------------------------===// + // Compare Instructions + //===--------------------------------------------------------------------===// + + Constant *CreateICmp(CmpInst::Predicate P, Constant *LHS, + Constant *RHS) const { + return Fold(ConstantExpr::getCompare(P, LHS, RHS)); + } + Constant *CreateFCmp(CmpInst::Predicate P, Constant *LHS, + Constant *RHS) const { + return Fold(ConstantExpr::getCompare(P, LHS, RHS)); + } + + //===--------------------------------------------------------------------===// + // Other Instructions + //===--------------------------------------------------------------------===// + + Constant *CreateSelect(Constant *C, Constant *True, Constant *False) const { + return Fold(ConstantExpr::getSelect(C, True, False)); + } + + Constant *CreateExtractElement(Constant *Vec, Constant *Idx) const { + return Fold(ConstantExpr::getExtractElement(Vec, Idx)); + } + + Constant *CreateInsertElement(Constant *Vec, Constant *NewElt, + Constant *Idx) const { + return Fold(ConstantExpr::getInsertElement(Vec, NewElt, Idx)); + } + + Constant *CreateShuffleVector(Constant *V1, Constant *V2, + Constant *Mask) const { + return Fold(ConstantExpr::getShuffleVector(V1, V2, Mask)); + } + + Constant *CreateExtractValue(Constant *Agg, + ArrayRef<unsigned> IdxList) const { + return Fold(ConstantExpr::getExtractValue(Agg, IdxList)); + } + + Constant *CreateInsertValue(Constant *Agg, Constant *Val, + ArrayRef<unsigned> IdxList) const { + return Fold(ConstantExpr::getInsertValue(Agg, Val, IdxList)); + } +}; + +} + +#endif
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Analysis/TargetLibraryInfo.def b/third_party/llvm-10.0/llvm/include/llvm/Analysis/TargetLibraryInfo.def new file mode 100644 index 0000000..afed404 --- /dev/null +++ b/third_party/llvm-10.0/llvm/include/llvm/Analysis/TargetLibraryInfo.def
@@ -0,0 +1,1411 @@ +//===-- TargetLibraryInfo.def - Library information -------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// This .def file will either fill in the enum definition or fill in the +// string representation array definition for TargetLibraryInfo. +// Which is defined depends on whether TLI_DEFINE_ENUM is defined or +// TLI_DEFINE_STRING is defined. Only one should be defined at a time. + +// NOTE: The nofree attribute is added to Libfuncs which are not +// listed as free or realloc functions in MemoryBuiltins.cpp +// +// When adding a function which frees memory include the LibFunc +// in lib/Analysis/MemoryBuiltins.cpp "isLibFreeFunction". +// +// When adding a LibFunc which reallocates memory include the LibFunc +// in lib/Analysis/MemoryBuiltins.cpp "AllocationFnData[]". + +#if !(defined(TLI_DEFINE_ENUM) || defined(TLI_DEFINE_STRING)) +#error "Must define TLI_DEFINE_ENUM or TLI_DEFINE_STRING for TLI .def." +#elif defined(TLI_DEFINE_ENUM) && defined(TLI_DEFINE_STRING) +#error "Can only define one of TLI_DEFINE_ENUM or TLI_DEFINE_STRING at a time." +#else +// One of TLI_DEFINE_ENUM/STRING are defined. + +#if defined(TLI_DEFINE_ENUM) +#define TLI_DEFINE_ENUM_INTERNAL(enum_variant) LibFunc_##enum_variant, +#define TLI_DEFINE_STRING_INTERNAL(string_repr) +#else +#define TLI_DEFINE_ENUM_INTERNAL(enum_variant) +#define TLI_DEFINE_STRING_INTERNAL(string_repr) string_repr, +#endif + +/// void *new(unsigned int); +TLI_DEFINE_ENUM_INTERNAL(msvc_new_int) +TLI_DEFINE_STRING_INTERNAL("??2@YAPAXI@Z") + +/// void *new(unsigned int, nothrow); +TLI_DEFINE_ENUM_INTERNAL(msvc_new_int_nothrow) +TLI_DEFINE_STRING_INTERNAL("??2@YAPAXIABUnothrow_t@std@@@Z") + +/// void *new(unsigned long long); +TLI_DEFINE_ENUM_INTERNAL(msvc_new_longlong) +TLI_DEFINE_STRING_INTERNAL("??2@YAPEAX_K@Z") + +/// void *new(unsigned long long, nothrow); +TLI_DEFINE_ENUM_INTERNAL(msvc_new_longlong_nothrow) +TLI_DEFINE_STRING_INTERNAL("??2@YAPEAX_KAEBUnothrow_t@std@@@Z") + +/// void operator delete(void*); +TLI_DEFINE_ENUM_INTERNAL(msvc_delete_ptr32) +TLI_DEFINE_STRING_INTERNAL("??3@YAXPAX@Z") + +/// void operator delete(void*, nothrow); +TLI_DEFINE_ENUM_INTERNAL(msvc_delete_ptr32_nothrow) +TLI_DEFINE_STRING_INTERNAL("??3@YAXPAXABUnothrow_t@std@@@Z") + +/// void operator delete(void*, unsigned int); +TLI_DEFINE_ENUM_INTERNAL(msvc_delete_ptr32_int) +TLI_DEFINE_STRING_INTERNAL("??3@YAXPAXI@Z") + +/// void operator delete(void*); +TLI_DEFINE_ENUM_INTERNAL(msvc_delete_ptr64) +TLI_DEFINE_STRING_INTERNAL("??3@YAXPEAX@Z") + +/// void operator de